增加考题管理模块
This commit is contained in:
@@ -0,0 +1,340 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
|
||||
"server/models"
|
||||
"server/services"
|
||||
|
||||
beego "github.com/beego/beego/v2/server/web"
|
||||
)
|
||||
|
||||
type ExamQuestionController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
type ExamQuestionBankController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
// Get list
|
||||
// @router /exam-questions [get]
|
||||
func (c *ExamQuestionController) GetList() {
|
||||
tenantId, _ := c.Ctx.Input.GetData("tenantId").(int)
|
||||
keyword := c.GetString("keyword")
|
||||
typeStr := c.GetString("type")
|
||||
var qtype *int8
|
||||
if typeStr != "" {
|
||||
if iv, err := strconv.Atoi(typeStr); err == nil {
|
||||
v := int8(iv)
|
||||
qtype = &v
|
||||
}
|
||||
}
|
||||
page, _ := c.GetInt("page", 1)
|
||||
pageSize, _ := c.GetInt("pageSize", 10)
|
||||
list, total, err := services.GetExamQuestions(services.QuestionListParams{
|
||||
TenantId: tenantId,
|
||||
Keyword: keyword,
|
||||
QuestionType: qtype,
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
})
|
||||
if err != nil {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "获取试题列表失败: " + err.Error(), "data": nil}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
// build minimal DTO to limit fields in response
|
||||
items := make([]map[string]interface{}, 0, len(list))
|
||||
for _, q := range list {
|
||||
if q == nil {
|
||||
continue
|
||||
}
|
||||
items = append(items, map[string]interface{}{
|
||||
"id": q.Id,
|
||||
"tenant_id": q.TenantId,
|
||||
"question_type": q.QuestionType,
|
||||
"question_title": q.QuestionTitle,
|
||||
"score": q.Score,
|
||||
})
|
||||
}
|
||||
c.Data["json"] = map[string]interface{}{
|
||||
"code": 0,
|
||||
"message": "ok",
|
||||
"data": map[string]interface{}{
|
||||
"list": items,
|
||||
"total": total,
|
||||
},
|
||||
}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// Get detail
|
||||
// @router /exam-questions/:id [get]
|
||||
func (c *ExamQuestionController) GetDetail() {
|
||||
tenantId, _ := c.Ctx.Input.GetData("tenantId").(int)
|
||||
id, err := c.GetInt64(":id")
|
||||
if err != nil || id <= 0 {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "ID无效", "data": nil}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
detail, err := services.GetExamQuestionDetail(tenantId, id)
|
||||
if err != nil {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "试题不存在", "data": nil}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = map[string]interface{}{"code": 0, "message": "ok", "data": detail}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// Create
|
||||
// @router /exam-questions [post]
|
||||
func (c *ExamQuestionController) Create() {
|
||||
tenantId, _ := c.Ctx.Input.GetData("tenantId").(int)
|
||||
var payload struct {
|
||||
QuestionTitle string `json:"question_title"`
|
||||
QuestionType int8 `json:"question_type"`
|
||||
Score float64 `json:"score"`
|
||||
QuestionAnalysis string `json:"question_analysis"`
|
||||
Options []map[string]string `json:"options"`
|
||||
Answer interface{} `json:"answer"`
|
||||
}
|
||||
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &payload); err != nil {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "请求参数错误: " + err.Error(), "data": nil}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
q := &models.ExamQuestion{
|
||||
TenantId: tenantId,
|
||||
QuestionType: payload.QuestionType,
|
||||
QuestionTitle: payload.QuestionTitle,
|
||||
QuestionAnalysis: payload.QuestionAnalysis,
|
||||
Score: payload.Score,
|
||||
Status: 1,
|
||||
}
|
||||
var opts []models.ExamQuestionOption
|
||||
for _, o := range payload.Options {
|
||||
opts = append(opts, models.ExamQuestionOption{OptionLabel: o["label"], OptionContent: o["content"]})
|
||||
}
|
||||
answerContent := ""
|
||||
switch v := payload.Answer.(type) {
|
||||
case string:
|
||||
answerContent = v
|
||||
case []interface{}:
|
||||
for i, item := range v {
|
||||
if s, ok := item.(string); ok {
|
||||
if i == 0 {
|
||||
answerContent = s
|
||||
} else {
|
||||
answerContent += "," + s
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
id, err := services.CreateExamQuestion(tenantId, q, opts, answerContent)
|
||||
if err != nil {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "创建失败: " + err.Error(), "data": nil}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = map[string]interface{}{"code": 0, "message": "创建成功", "data": map[string]interface{}{"id": id}}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// Update
|
||||
// @router /exam-questions/:id [put]
|
||||
func (c *ExamQuestionController) Update() {
|
||||
tenantId, _ := c.Ctx.Input.GetData("tenantId").(int)
|
||||
id, err := c.GetInt64(":id")
|
||||
if err != nil || id <= 0 {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "ID无效", "data": nil}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
var payload struct {
|
||||
QuestionTitle string `json:"question_title"`
|
||||
QuestionType int8 `json:"question_type"`
|
||||
Score float64 `json:"score"`
|
||||
QuestionAnalysis string `json:"question_analysis"`
|
||||
Options []map[string]string `json:"options"`
|
||||
Answer interface{} `json:"answer"`
|
||||
}
|
||||
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &payload); err != nil {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "请求参数错误: " + err.Error(), "data": nil}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
q := &models.ExamQuestion{QuestionType: payload.QuestionType, QuestionTitle: payload.QuestionTitle, QuestionAnalysis: payload.QuestionAnalysis, Score: payload.Score}
|
||||
var opts []models.ExamQuestionOption
|
||||
for _, o := range payload.Options {
|
||||
opts = append(opts, models.ExamQuestionOption{OptionLabel: o["label"], OptionContent: o["content"]})
|
||||
}
|
||||
answerContent := ""
|
||||
switch v := payload.Answer.(type) {
|
||||
case string:
|
||||
answerContent = v
|
||||
case []interface{}:
|
||||
for i, item := range v {
|
||||
if s, ok := item.(string); ok {
|
||||
if i == 0 {
|
||||
answerContent = s
|
||||
} else {
|
||||
answerContent += "," + s
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := services.UpdateExamQuestion(tenantId, id, q, opts, answerContent); err != nil {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "更新失败: " + err.Error(), "data": nil}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = map[string]interface{}{"code": 0, "message": "更新成功", "data": nil}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// Delete
|
||||
// @router /exam-questions/:id [delete]
|
||||
func (c *ExamQuestionController) Delete() {
|
||||
tenantId, _ := c.Ctx.Input.GetData("tenantId").(int)
|
||||
id, err := c.GetInt64(":id")
|
||||
if err != nil || id <= 0 {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "ID无效", "data": nil}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
if err := services.DeleteExamQuestion(tenantId, id); err != nil {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "删除失败: " + err.Error(), "data": nil}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = map[string]interface{}{"code": 0, "message": "删除成功", "data": nil}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// GetBankList
|
||||
// @router /exam-question-banks [get]
|
||||
func (c *ExamQuestionBankController) GetBankList() {
|
||||
tenantId, _ := c.Ctx.Input.GetData("tenantId").(int)
|
||||
keyword := c.GetString("keyword")
|
||||
page, _ := c.GetInt("page", 1)
|
||||
pageSize, _ := c.GetInt("pageSize", 10)
|
||||
list, total, err := services.GetExamQuestionBanks(services.BankListParams{
|
||||
TenantId: tenantId,
|
||||
Keyword: keyword,
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
})
|
||||
if err != nil {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "获取试题库列表失败: " + err.Error(), "data": nil}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = map[string]interface{}{"code": 0, "message": "ok", "data": map[string]interface{}{"list": list, "total": total}}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// GetBankDetail
|
||||
// @router /exam-question-banks/:id [get]
|
||||
func (c *ExamQuestionBankController) GetBankDetail() {
|
||||
tenantId, _ := c.Ctx.Input.GetData("tenantId").(int)
|
||||
id, err := c.GetInt64(":id")
|
||||
if err != nil || id <= 0 {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "ID无效", "data": nil}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
bank, err := services.GetExamQuestionBankDetail(tenantId, id)
|
||||
if err != nil {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "试题库不存在", "data": nil}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = map[string]interface{}{"code": 0, "message": "ok", "data": bank}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// CreateBank
|
||||
// @router /exam-question-banks [post]
|
||||
func (c *ExamQuestionBankController) CreateBank() {
|
||||
tenantId, _ := c.Ctx.Input.GetData("tenantId").(int)
|
||||
var payload struct {
|
||||
BankName string `json:"bank_name"`
|
||||
BankDesc string `json:"bank_desc"`
|
||||
}
|
||||
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &payload); err != nil {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "请求参数错误: " + err.Error(), "data": nil}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
bank := &models.ExamQuestionBank{
|
||||
TenantId: tenantId,
|
||||
BankName: payload.BankName,
|
||||
BankDesc: payload.BankDesc,
|
||||
Status: 1,
|
||||
}
|
||||
id, err := services.CreateExamQuestionBank(tenantId, bank)
|
||||
if err != nil {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "创建失败: " + err.Error(), "data": nil}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = map[string]interface{}{"code": 0, "message": "创建成功", "data": map[string]interface{}{"id": id}}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// UpdateBank
|
||||
// @router /exam-question-banks/:id [put]
|
||||
func (c *ExamQuestionBankController) UpdateBank() {
|
||||
tenantId, _ := c.Ctx.Input.GetData("tenantId").(int)
|
||||
id, err := c.GetInt64(":id")
|
||||
if err != nil || id <= 0 {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "ID无效", "data": nil}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
var payload struct {
|
||||
BankName string `json:"bank_name"`
|
||||
BankDesc string `json:"bank_desc"`
|
||||
}
|
||||
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &payload); err != nil {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "请求参数错误: " + err.Error(), "data": nil}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
bank := &models.ExamQuestionBank{
|
||||
Id: id,
|
||||
TenantId: tenantId,
|
||||
BankName: payload.BankName,
|
||||
BankDesc: payload.BankDesc,
|
||||
}
|
||||
if err := services.UpdateExamQuestionBank(tenantId, id, bank); err != nil {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "更新失败: " + err.Error(), "data": nil}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = map[string]interface{}{"code": 0, "message": "更新成功", "data": nil}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// DeleteBank
|
||||
// @router /exam-question-banks/:id [delete]
|
||||
func (c *ExamQuestionBankController) DeleteBank() {
|
||||
tenantId, _ := c.Ctx.Input.GetData("tenantId").(int)
|
||||
id, err := c.GetInt64(":id")
|
||||
if err != nil || id <= 0 {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "ID无效", "data": nil}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
if err := services.DeleteExamQuestionBank(tenantId, id); err != nil {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "删除失败: " + err.Error(), "data": nil}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = map[string]interface{}{"code": 0, "message": "删除成功", "data": nil}
|
||||
c.ServeJSON()
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
-- MySQL dump 10.13 Distrib 8.0.41, for Win64 (x86_64)
|
||||
-- MySQL dump 10.13 Distrib 8.0.41, for Win64 (x86_64)
|
||||
--
|
||||
-- Host: 212.64.112.158 Database: gotest
|
||||
-- ------------------------------------------------------
|
||||
@@ -228,6 +228,30 @@ CREATE TABLE `yz_exam_category` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='考试分类表(含多租户隔离)';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `yz_exam_question_bank`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `yz_exam_question_bank`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `yz_exam_question_bank` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '题库ID',
|
||||
`tenant_id` int(11) NOT NULL COMMENT '租户ID(多租户隔离)',
|
||||
`bank_name` varchar(100) NOT NULL COMMENT '题库名称',
|
||||
`bank_desc` varchar(500) DEFAULT '' COMMENT '题库描述',
|
||||
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态(1-启用,0-禁用)',
|
||||
`sort_order` int(11) NOT NULL DEFAULT '0' COMMENT '排序序号',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`delete_time` datetime DEFAULT NULL COMMENT '删除时间(软删除)',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_tenant_status` (`tenant_id`,`status`),
|
||||
KEY `idx_tenant_name` (`tenant_id`,`bank_name`),
|
||||
KEY `idx_delete_time` (`delete_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='考试题库表(支持租户隔离、软删除)';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `yz_exam_users`
|
||||
--
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/beego/beego/v2/client/orm"
|
||||
)
|
||||
|
||||
// ExamQuestion 对应表 yz_exam_question
|
||||
type ExamQuestion struct {
|
||||
Id int64 `orm:"column(id);auto" json:"id"`
|
||||
TenantId int `orm:"column(tenant_id)" json:"tenant_id"`
|
||||
QuestionType int8 `orm:"column(question_type)" json:"question_type"`
|
||||
QuestionTitle string `orm:"column(question_title);size(1000)" json:"question_title"`
|
||||
QuestionAnalysis string `orm:"column(question_analysis);size(2000);null" json:"question_analysis"`
|
||||
Score float64 `orm:"column(score);digits(5);decimals(2)" json:"score"`
|
||||
SortOrder int8 `orm:"column(sort_order);null" json:"sort_order"`
|
||||
Status int8 `orm:"column(status)" json:"status"`
|
||||
CreateTime time.Time `orm:"column(create_time);type(datetime);auto_now_add" json:"create_time"`
|
||||
UpdateTime time.Time `orm:"column(update_time);type(datetime);auto_now" json:"update_time"`
|
||||
DeleteTime *time.Time `orm:"column(delete_time);type(datetime);null" json:"delete_time,omitempty"`
|
||||
}
|
||||
|
||||
func (q *ExamQuestion) TableName() string {
|
||||
return "yz_exam_question"
|
||||
}
|
||||
|
||||
// ExamQuestionOption 对应表 yz_exam_question_option
|
||||
type ExamQuestionOption struct {
|
||||
Id int64 `orm:"column(id);auto" json:"id"`
|
||||
TenantId int `orm:"column(tenant_id)" json:"tenant_id"`
|
||||
QuestionId int64 `orm:"column(question_id)" json:"question_id"`
|
||||
OptionLabel string `orm:"column(option_label);size(10)" json:"option_label"`
|
||||
OptionContent string `orm:"column(option_content);size(500)" json:"option_content"`
|
||||
SortOrder int8 `orm:"column(sort_order);null" json:"sort_order"`
|
||||
CreateTime time.Time `orm:"column(create_time);type(datetime);auto_now_add" json:"create_time"`
|
||||
UpdateTime time.Time `orm:"column(update_time);type(datetime);auto_now" json:"update_time"`
|
||||
DeleteTime *time.Time `orm:"column(delete_time);type(datetime);null" json:"delete_time,omitempty"`
|
||||
}
|
||||
|
||||
func (o *ExamQuestionOption) TableName() string {
|
||||
return "yz_exam_question_option"
|
||||
}
|
||||
|
||||
// ExamQuestionAnswer 对应表 yz_exam_question_answer
|
||||
type ExamQuestionAnswer struct {
|
||||
Id int64 `orm:"column(id);auto" json:"id"`
|
||||
TenantId int `orm:"column(tenant_id)" json:"tenant_id"`
|
||||
QuestionId int64 `orm:"column(question_id)" json:"question_id"`
|
||||
AnswerContent string `orm:"column(answer_content);size(1000)" json:"answer_content"`
|
||||
CreateTime time.Time `orm:"column(create_time);type(datetime);auto_now_add" json:"create_time"`
|
||||
UpdateTime time.Time `orm:"column(update_time);type(datetime);auto_now" json:"update_time"`
|
||||
DeleteTime *time.Time `orm:"column(delete_time);type(datetime);null" json:"delete_time,omitempty"`
|
||||
}
|
||||
|
||||
func (a *ExamQuestionAnswer) TableName() string {
|
||||
return "yz_exam_question_answer"
|
||||
}
|
||||
|
||||
// ExamQuestionBank 对应表 yz_exam_question_bank
|
||||
type ExamQuestionBank struct {
|
||||
Id int64 `orm:"column(id);auto" json:"id"`
|
||||
TenantId int `orm:"column(tenant_id)" json:"tenant_id"`
|
||||
BankName string `orm:"column(bank_name);size(100)" json:"bank_name"`
|
||||
BankDesc string `orm:"column(bank_desc);size(500);null" json:"bank_desc"`
|
||||
Status int8 `orm:"column(status)" json:"status"`
|
||||
SortOrder int8 `orm:"column(sort_order);null" json:"sort_order"`
|
||||
CreateTime time.Time `orm:"column(create_time);type(datetime);auto_now_add" json:"create_time"`
|
||||
UpdateTime time.Time `orm:"column(update_time);type(datetime);auto_now" json:"update_time"`
|
||||
DeleteTime *time.Time `orm:"column(delete_time);type(datetime);null" json:"delete_time,omitempty"`
|
||||
}
|
||||
|
||||
func (b *ExamQuestionBank) TableName() string {
|
||||
return "yz_exam_question_bank"
|
||||
}
|
||||
|
||||
func init() {
|
||||
orm.RegisterModel(new(ExamQuestion), new(ExamQuestionOption), new(ExamQuestionAnswer), new(ExamQuestionBank))
|
||||
}
|
||||
@@ -283,12 +283,20 @@ func init() {
|
||||
beego.Router("/api/files/search", &controllers.FileController{}, "get:SearchFiles")
|
||||
beego.Router("/api/files/statistics", &controllers.FileController{}, "get:GetFileStatistics")
|
||||
|
||||
// 考试题目路由
|
||||
beego.Router("/api/exam-questions", &controllers.ExamQuestionController{}, "get:GetList;post:Create")
|
||||
beego.Router("/api/exam-questions/:id", &controllers.ExamQuestionController{}, "get:GetDetail;put:Update;delete:Delete")
|
||||
|
||||
// 考试题库路由
|
||||
beego.Router("/api/exam-question-banks", &controllers.ExamQuestionBankController{}, "get:GetBankList;post:CreateBank")
|
||||
beego.Router("/api/exam-question-banks/:id", &controllers.ExamQuestionBankController{}, "get:GetBankDetail;put:UpdateBank;delete:DeleteBank")
|
||||
|
||||
// 知识库路由
|
||||
beego.Router("/api/knowledge/list", &controllers.KnowledgeController{}, "get:List")
|
||||
beego.Router("/api/knowledge/count", &controllers.KnowledgeController{}, "get:GetCount")
|
||||
beego.Router("/api/knowledge/detail", &controllers.KnowledgeController{}, "get:Detail")
|
||||
beego.Router("/api/knowledge/create", &controllers.KnowledgeController{}, "post:Create")
|
||||
beego.Router("/api/knowledge/update", &controllers.KnowledgeController{}, "post:Update")
|
||||
// ...
|
||||
beego.Router("/api/knowledge/delete", &controllers.KnowledgeController{}, "post:Delete")
|
||||
beego.Router("/api/knowledge/categories", &controllers.KnowledgeController{}, "get:GetCategories")
|
||||
beego.Router("/api/knowledge/tags", &controllers.KnowledgeController{}, "get:GetTags")
|
||||
@@ -314,10 +322,10 @@ func init() {
|
||||
// OA基础数据合并接口(一次性获取部门、职位、角色)
|
||||
beego.Router("/api/oa/base-data/:tenantId", &controllers.OAController{}, "get:GetOABaseData")
|
||||
|
||||
// OA任务管理路由
|
||||
beego.Router("/api/oa/tasks", &controllers.TaskController{}, "get:GetTasks;post:CreateTask")
|
||||
beego.Router("/api/oa/tasks/:id", &controllers.TaskController{}, "get:GetTaskById;put:UpdateTask;delete:DeleteTask")
|
||||
beego.Router("/api/oa/tasks/todo", &controllers.TaskController{}, "get:GetTodoTasks")
|
||||
// OA任务管理路由
|
||||
beego.Router("/api/oa/tasks", &controllers.TaskController{}, "get:GetTasks;post:CreateTask")
|
||||
beego.Router("/api/oa/tasks/:id", &controllers.TaskController{}, "get:GetTaskById;put:UpdateTask;delete:DeleteTask")
|
||||
beego.Router("/api/oa/tasks/todo", &controllers.TaskController{}, "get:GetTodoTasks")
|
||||
|
||||
// CRM 客户路由
|
||||
beego.Router("/api/crm/customer/list", &controllers.CustomerController{}, "get:List")
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"server/models"
|
||||
|
||||
"github.com/beego/beego/v2/client/orm"
|
||||
)
|
||||
|
||||
type QuestionListParams struct {
|
||||
TenantId int
|
||||
Keyword string
|
||||
QuestionType *int8
|
||||
Page int
|
||||
PageSize int
|
||||
}
|
||||
|
||||
type QuestionWithMeta struct {
|
||||
Question *models.ExamQuestion
|
||||
Options []*models.ExamQuestionOption
|
||||
Answer *models.ExamQuestionAnswer
|
||||
}
|
||||
|
||||
type BankListParams struct {
|
||||
TenantId int
|
||||
Keyword string
|
||||
Page int
|
||||
PageSize int
|
||||
}
|
||||
|
||||
func GetExamQuestions(params QuestionListParams) ([]*models.ExamQuestion, int64, error) {
|
||||
o := orm.NewOrm()
|
||||
qs := o.QueryTable(new(models.ExamQuestion)).Filter("delete_time__isnull", true).Filter("status", 1)
|
||||
if params.TenantId > 0 {
|
||||
qs = qs.Filter("tenant_id", params.TenantId)
|
||||
}
|
||||
if params.Keyword != "" {
|
||||
qs = qs.Filter("question_title__icontains", params.Keyword)
|
||||
}
|
||||
if params.QuestionType != nil {
|
||||
qs = qs.Filter("question_type", *params.QuestionType)
|
||||
}
|
||||
total, err := qs.Count()
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if params.Page <= 0 {
|
||||
params.Page = 1
|
||||
}
|
||||
if params.PageSize <= 0 {
|
||||
params.PageSize = 10
|
||||
}
|
||||
offset := (params.Page - 1) * params.PageSize
|
||||
var list []*models.ExamQuestion
|
||||
_, err = qs.OrderBy("-id").Limit(params.PageSize, offset).All(&list, "Id", "TenantId", "QuestionType", "QuestionTitle", "Score")
|
||||
return list, total, err
|
||||
}
|
||||
|
||||
func GetExamQuestionDetail(tenantId int, id int64) (*QuestionWithMeta, error) {
|
||||
o := orm.NewOrm()
|
||||
q := new(models.ExamQuestion)
|
||||
if err := o.QueryTable(q).Filter("id", id).Filter("delete_time__isnull", true).One(q); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if tenantId > 0 && q.TenantId != tenantId {
|
||||
return nil, errors.New("not found")
|
||||
}
|
||||
var opts []*models.ExamQuestionOption
|
||||
_, _ = o.QueryTable(new(models.ExamQuestionOption)).Filter("question_id", q.Id).Filter("delete_time__isnull", true).All(&opts)
|
||||
a := new(models.ExamQuestionAnswer)
|
||||
_ = o.QueryTable(a).Filter("question_id", q.Id).Filter("delete_time__isnull", true).One(a)
|
||||
return &QuestionWithMeta{Question: q, Options: opts, Answer: a}, nil
|
||||
}
|
||||
|
||||
func CreateExamQuestion(tenantId int, q *models.ExamQuestion, options []models.ExamQuestionOption, answerContent string) (int64, error) {
|
||||
o := orm.NewOrm()
|
||||
if tenantId > 0 {
|
||||
q.TenantId = tenantId
|
||||
}
|
||||
q.Status = 1
|
||||
if _, err := o.Insert(q); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
for i := range options {
|
||||
options[i].TenantId = q.TenantId
|
||||
options[i].QuestionId = q.Id
|
||||
_, _ = o.Insert(&options[i])
|
||||
}
|
||||
ans := &models.ExamQuestionAnswer{TenantId: q.TenantId, QuestionId: q.Id, AnswerContent: answerContent}
|
||||
_, _ = o.Insert(ans)
|
||||
return q.Id, nil
|
||||
}
|
||||
|
||||
func UpdateExamQuestion(tenantId int, id int64, q *models.ExamQuestion, options []models.ExamQuestionOption, answerContent string) error {
|
||||
o := orm.NewOrm()
|
||||
existing := models.ExamQuestion{Id: id}
|
||||
if err := o.Read(&existing); err != nil {
|
||||
return err
|
||||
}
|
||||
if tenantId > 0 && existing.TenantId != tenantId {
|
||||
return errors.New("not found")
|
||||
}
|
||||
existing.QuestionType = q.QuestionType
|
||||
existing.QuestionTitle = q.QuestionTitle
|
||||
existing.QuestionAnalysis = q.QuestionAnalysis
|
||||
existing.Score = q.Score
|
||||
if _, err := o.Update(&existing, "QuestionType", "QuestionTitle", "QuestionAnalysis", "Score"); err != nil {
|
||||
return err
|
||||
}
|
||||
// soft delete old options and answer
|
||||
now := time.Now()
|
||||
o.QueryTable(new(models.ExamQuestionOption)).Filter("question_id", id).Filter("delete_time__isnull", true).Update(orm.Params{"delete_time": now})
|
||||
o.QueryTable(new(models.ExamQuestionAnswer)).Filter("question_id", id).Filter("delete_time__isnull", true).Update(orm.Params{"delete_time": now})
|
||||
for i := range options {
|
||||
options[i].TenantId = existing.TenantId
|
||||
options[i].QuestionId = id
|
||||
_, _ = o.Insert(&options[i])
|
||||
}
|
||||
ans := &models.ExamQuestionAnswer{TenantId: existing.TenantId, QuestionId: id, AnswerContent: answerContent}
|
||||
_, _ = o.Insert(ans)
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteExamQuestion(tenantId int, id int64) error {
|
||||
o := orm.NewOrm()
|
||||
existing := models.ExamQuestion{Id: id}
|
||||
if err := o.Read(&existing); err != nil {
|
||||
return err
|
||||
}
|
||||
if tenantId > 0 && existing.TenantId != tenantId {
|
||||
return errors.New("not found")
|
||||
}
|
||||
now := time.Now()
|
||||
if _, err := o.QueryTable(new(models.ExamQuestion)).Filter("id", id).Update(orm.Params{"delete_time": now}); err != nil {
|
||||
return err
|
||||
}
|
||||
o.QueryTable(new(models.ExamQuestionOption)).Filter("question_id", id).Filter("delete_time__isnull", true).Update(orm.Params{"delete_time": now})
|
||||
o.QueryTable(new(models.ExamQuestionAnswer)).Filter("question_id", id).Filter("delete_time__isnull", true).Update(orm.Params{"delete_time": now})
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetExamQuestionBanks(params BankListParams) ([]*models.ExamQuestionBank, int64, error) {
|
||||
o := orm.NewOrm()
|
||||
qs := o.QueryTable(new(models.ExamQuestionBank)).Filter("delete_time__isnull", true).Filter("status", 1)
|
||||
if params.TenantId > 0 {
|
||||
qs = qs.Filter("tenant_id", params.TenantId)
|
||||
}
|
||||
if params.Keyword != "" {
|
||||
qs = qs.Filter("bank_name__icontains", params.Keyword)
|
||||
}
|
||||
total, err := qs.Count()
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if params.Page <= 0 {
|
||||
params.Page = 1
|
||||
}
|
||||
if params.PageSize <= 0 {
|
||||
params.PageSize = 10
|
||||
}
|
||||
offset := (params.Page - 1) * params.PageSize
|
||||
var list []*models.ExamQuestionBank
|
||||
_, err = qs.OrderBy("-id").Limit(params.PageSize, offset).All(&list, "Id", "TenantId", "BankName", "BankDesc")
|
||||
return list, total, err
|
||||
}
|
||||
|
||||
func GetExamQuestionBankDetail(tenantId int, id int64) (*models.ExamQuestionBank, error) {
|
||||
o := orm.NewOrm()
|
||||
bank := new(models.ExamQuestionBank)
|
||||
if err := o.QueryTable(bank).Filter("id", id).Filter("delete_time__isnull", true).One(bank); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if tenantId > 0 && bank.TenantId != tenantId {
|
||||
return nil, errors.New("not found")
|
||||
}
|
||||
return bank, nil
|
||||
}
|
||||
|
||||
func CreateExamQuestionBank(tenantId int, bank *models.ExamQuestionBank) (int64, error) {
|
||||
o := orm.NewOrm()
|
||||
if tenantId > 0 {
|
||||
bank.TenantId = tenantId
|
||||
}
|
||||
bank.Status = 1
|
||||
if _, err := o.Insert(bank); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return bank.Id, nil
|
||||
}
|
||||
|
||||
func UpdateExamQuestionBank(tenantId int, id int64, bank *models.ExamQuestionBank) error {
|
||||
o := orm.NewOrm()
|
||||
existing := models.ExamQuestionBank{Id: id}
|
||||
if err := o.Read(&existing); err != nil {
|
||||
return err
|
||||
}
|
||||
if tenantId > 0 && existing.TenantId != tenantId {
|
||||
return errors.New("not found")
|
||||
}
|
||||
existing.BankName = bank.BankName
|
||||
existing.BankDesc = bank.BankDesc
|
||||
if _, err := o.Update(&existing, "BankName", "BankDesc"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteExamQuestionBank(tenantId int, id int64) error {
|
||||
o := orm.NewOrm()
|
||||
existing := models.ExamQuestionBank{Id: id}
|
||||
if err := o.Read(&existing); err != nil {
|
||||
return err
|
||||
}
|
||||
if tenantId > 0 && existing.TenantId != tenantId {
|
||||
return errors.New("not found")
|
||||
}
|
||||
now := time.Now()
|
||||
if _, err := o.QueryTable(new(models.ExamQuestionBank)).Filter("id", id).Update(orm.Params{"delete_time": now}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user