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") bankId, _ := c.GetInt64("bank_id", 0) 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, BankId: bankId, Page: page, PageSize: pageSize, }) if err != nil { c.Data["json"] = map[string]interface{}{"code": 1, "message": "获取试题列表失败: " + err.Error(), "data": nil} c.ServeJSON() return } 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"` BankId int64 `json:"bank_id"` } 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, } if payload.BankId > 0 { q.BankId = payload.BankId } 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() } // BatchCreate // @router /exam-questions/batch [post] func (c *ExamQuestionController) BatchCreate() { tenantId, _ := c.Ctx.Input.GetData("tenantId").(int) var payload struct { BankId int64 `json:"bank_id"` Items []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"` } `json:"items"` } 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 } if len(payload.Items) == 0 { c.Data["json"] = map[string]interface{}{"code": 1, "message": "导入数据为空", "data": nil} c.ServeJSON() return } success := 0 fails := 0 createdIds := make([]int64, 0, len(payload.Items)) updatedIds := make([]int64, 0, len(payload.Items)) for _, item := range payload.Items { q := &models.ExamQuestion{ TenantId: tenantId, QuestionType: item.QuestionType, QuestionTitle: item.QuestionTitle, QuestionAnalysis: item.QuestionAnalysis, Score: item.Score, Status: 1, } if payload.BankId > 0 { q.BankId = payload.BankId } var opts []models.ExamQuestionOption for _, o := range item.Options { opts = append(opts, models.ExamQuestionOption{OptionLabel: o["label"], OptionContent: o["content"]}) } answerContent := "" switch v := item.Answer.(type) { case string: answerContent = v case []interface{}: for i, it := range v { if s, ok := it.(string); ok { if i == 0 { answerContent = s } else { answerContent += "," + s } } } } // 如果存在完全匹配的题目标题,则覆盖更新;否则新增 if existing, err := services.FindExamQuestionByTitle(tenantId, item.QuestionTitle); err == nil && existing != nil { if err := services.UpdateExamQuestion(tenantId, existing.Id, q, opts, answerContent); err != nil { fails++ continue } updatedIds = append(updatedIds, existing.Id) success++ } else { id, err := services.CreateExamQuestion(tenantId, q, opts, answerContent) if err != nil { fails++ continue } createdIds = append(createdIds, id) success++ } } c.Data["json"] = map[string]interface{}{ "code": 0, "message": "批量导入完成", "data": map[string]interface{}{ "success": success, "failed": fails, "created_ids": createdIds, "updated_ids": updatedIds, }, } 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"` BankId int64 `json:"bank_id"` } 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} if payload.BankId > 0 { q.BankId = payload.BankId } 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() }