2 Commits

  1. 38
      Knowledge_Test_Go/api/v1/questionBank.go
  2. 10
      Knowledge_Test_Go/internal/cmd/cmd.go
  3. 24
      Knowledge_Test_Go/internal/logic/knowledge/knowledge.go
  4. 93
      Knowledge_Test_Go/internal/logic/questionBank/questionBank.go

38
Knowledge_Test_Go/api/v1/questionBank.go

@ -24,8 +24,8 @@ type SubmitAnswersReq struct {
// AnswerItem 答案项 // AnswerItem 答案项
type AnswerItem struct { type AnswerItem struct {
QuestionId int `json:"questionId" dc:"题目ID"`
UserAnswer string `json:"userAnswer" dc:"用户答案"`
QuestionId int `json:"question_id" dc:"题目ID"`
UserAnswer string `json:"user_answer" dc:"用户答案"`
} }
// SubmitAnswersRes 提交答案响应 // SubmitAnswersRes 提交答案响应
@ -64,8 +64,8 @@ type GetCourseRes struct {
// GetWrongQuestionsRes 错题详情 // GetWrongQuestionsRes 错题详情
type GetWrongQuestionsRes struct { type GetWrongQuestionsRes struct {
GetQuestionsRes `json:"question"` GetQuestionsRes `json:"question"`
UserAnswer string `json:"userAnswer" dc:"用户答案"`
CorrectAnswer string `json:"correctAnswer" dc:"正确答案"`
UserAnswer string `json:"user_answer" dc:"用户答案"`
CorrectAnswer string `json:"correct_answer" dc:"正确答案"`
} }
//------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------
@ -74,11 +74,11 @@ type GetWrongQuestionsRes struct {
type QuestionOutputReq struct { type QuestionOutputReq struct {
Stem string `json:"stem"` Stem string `json:"stem"`
QuestionTypeId string `json:"question_type_id"` QuestionTypeId string `json:"question_type_id"`
CourseRecommendationId string `json:"course+recommendation_id"`
CourseRecommendationId string `json:"course_recommendation_id"`
Page int `json:"page"` Page int `json:"page"`
PageSize int `json:"page_size"` PageSize int `json:"page_size"`
SortField string `json:"sort_field"` // 排序字段:error_count, error_rate, id
SortOrder string `json:"sort_order"` // 排序方向:asc, desc
SortField string `json:"sort_field"` // 排序字段:error_count, error_rate, id
SortOrder string `json:"sort_order" d:"DESC"` // 排序方向:asc, desc
} }
// QuestionOutputRes 题目输出 // QuestionOutputRes 题目输出
@ -89,12 +89,12 @@ type QuestionOutputRes struct {
B string `json:"B"` B string `json:"B"`
C string `json:"C"` C string `json:"C"`
D string `json:"D"` D string `json:"D"`
CorrectAnswer string `json:"correctAnswer"`
QuestionTypeName string `json:"questionTypeName"`
CrName string `json:"CrName"`
CitationCount int `json:"citationCount"`
ErrorCount int `json:"errorCount"`
ErrorRate int `json:"errorRate"`
CorrectAnswer string `json:"correct_answer"`
QuestionTypeName string `json:"question_type_name"`
CrName string `json:"cr_name"`
CitationCount int `json:"citation_count"`
ErrorCount int `json:"error_count"`
ErrorRate int `json:"error_rate"`
} }
// QuestionUpdateReq 修改题目请求 // QuestionUpdateReq 修改题目请求
@ -122,16 +122,16 @@ type UserScoreOutputRes struct {
UserIdentity string `json:"user_identity"` UserIdentity string `json:"user_identity"`
Jwcode int `json:"jwcode"` Jwcode int `json:"jwcode"`
Score int `json:"score"` Score int `json:"score"`
CreatedAt string `json:"createdAt"`
CreatedAt string `json:"created_at"`
} }
// UserScoreOutputReq 获取用户成绩列表请求 // UserScoreOutputReq 获取用户成绩列表请求
type UserScoreOutputReq struct { type UserScoreOutputReq struct {
UserName string `json:"user_name"` // 用户名(精准查询)
UserIdentity string `json:"user_identity"` // 用户身份(过滤)
Jwcode string `json:"jwcode"` // 精网号(精准查询)
StartTime string `json:"start_time"` // 开始时间(提交时间范围)
EndTime string `json:"end_time"` // 结束时间(提交时间范围)
UserName string `json:"user_name"` // 用户名(精准查询)
UserIdentity string `json:"user_identity"` // 用户身份(过滤)
Jwcode string `json:"jwcode" v:"integer|length:8"` // 精网号(精准查询)
StartTime string `json:"start_time"` // 开始时间(提交时间范围)
EndTime string `json:"end_time"` // 结束时间(提交时间范围)
Page int `json:"page"` Page int `json:"page"`
PageSize int `json:"page_size"` PageSize int `json:"page_size"`
SortField string `json:"sort_field"` // 排序字段:score, created_at SortField string `json:"sort_field"` // 排序字段:score, created_at

10
Knowledge_Test_Go/internal/cmd/cmd.go

@ -23,11 +23,11 @@ var (
ghttp.MiddlewareHandlerResponse, ghttp.MiddlewareHandlerResponse,
ghttp.MiddlewareCORS, ghttp.MiddlewareCORS,
) )
group.POST("/knowledge/questions", controller.NewKnowledgeTest().GetQuestions) // 获取题目列表
group.POST("/knowledge/submit", controller.NewKnowledgeTest().SubmitAnswers) // 提交答案
group.POST("/knowledge/scores", controller.NewKnowledgeTest().GetUserScores) // 获取用户成绩
group.POST("/knowledge/wrong-questions", controller.NewKnowledgeTest().GetWrongQuestions) // 获取错题列表
group.POST("/knowledge/course", controller.NewKnowledgeTest().GetCourse) // 获取课程
group.POST("/knowledge/questions", controller.NewKnowledgeTest().GetQuestions) // 获取题目列表
group.POST("/knowledge/submit", controller.NewKnowledgeTest().SubmitAnswers) // 提交答案
group.POST("/knowledge/scores", controller.NewKnowledgeTest().GetUserScores) // 获取用户成绩
group.POST("/knowledge/wrongQuestions", controller.NewKnowledgeTest().GetWrongQuestions) // 获取错题列表
group.POST("/knowledge/course", controller.NewKnowledgeTest().GetCourse) // 获取课程
}) })
// 后台路由组 // 后台路由组

24
Knowledge_Test_Go/internal/logic/knowledge/knowledge.go

@ -21,7 +21,7 @@ func init() {
// GetQuestions 获取题目列表 // GetQuestions 获取题目列表
func (s *sKnowledgeTest) GetQuestions(ctx context.Context, req *v1.GetQuestionsReq) (res []*v1.GetQuestionsRes, total int, err error) { func (s *sKnowledgeTest) GetQuestions(ctx context.Context, req *v1.GetQuestionsReq) (res []*v1.GetQuestionsRes, total int, err error) {
db := g.Model("question_bank a").Where("isdel=0").Fields("a.id", "a.stem", "a.a", "a.b", "a.c", "a.d")
db := g.Model("question_bank qb").Where("isdel=0").Fields("qb.id", "qb.stem", "qb.a", "qb.b", "qb.c", "qb.d")
err = db.Page(req.Page, req.PageSize).ScanAndCount(&res, &total, false) err = db.Page(req.Page, req.PageSize).ScanAndCount(&res, &total, false)
return return
} }
@ -48,13 +48,13 @@ func (s *sKnowledgeTest) GetCourse(ctx context.Context, req *v1.GetCourseReq) (r
var courses []Course var courses []Course
// 查询数据 // 查询数据
err = g.Model("question_record a").
LeftJoin("question_bank b", "a.question_bank_id = b.id").
LeftJoin("course_recommend c", "b.course_recommendation_id = c.id").
Where("a.jwcode = ?", req.Jwcode).
Where("c.cr_name IS NOT NULL").
Where("c.cr_name != ''").
Fields("DISTINCT c.cr_name"). // DISTINCT去重
err = g.Model("question_record qr").
LeftJoin("question_bank qb", "qr.question_bank_id = qb.id").
LeftJoin("course_recommend cr", "qb.course_recommendation_id = cr.id").
Where("qr.jwcode = ?", req.Jwcode).
Where("cr.cr_name IS NOT NULL").
Where("cr.cr_name != ''").
Fields("DISTINCT cr.cr_name"). // DISTINCT去重
Ctx(ctx). Ctx(ctx).
Scan(&courses) Scan(&courses)
@ -225,9 +225,9 @@ func (s *sKnowledgeTest) updateErrorRatesInTransaction(ctx context.Context, tx g
// GetWrongQuestions 获取错题列表 // GetWrongQuestions 获取错题列表
func (s *sKnowledgeTest) GetWrongQuestions(ctx context.Context, req *v1.GetWrongQuestionsReq) (res []*v1.GetWrongQuestionsRes, total int, err error) { func (s *sKnowledgeTest) GetWrongQuestions(ctx context.Context, req *v1.GetWrongQuestionsReq) (res []*v1.GetWrongQuestionsRes, total int, err error) {
db := g.Model("question_record b").
RightJoin("question_bank a", "a.id=b.question_bank_id").
Where("b.jwcode=?", req.Jwcode).Fields("a.id", "a.stem", "a.a", "a.b", "a.c", "a.d", "a.correct_answer", "b.user_answer")
err = db.Page(req.Page, req.PageSize).ScanAndCount(&res, &total, false)
err = g.Model("question_record qr").
RightJoin("question_bank qb", "qb.id=qr.question_bank_id").
Where("qr.jwcode=?", req.Jwcode).Fields("qb.id", "qb.stem", "qb.a", "qb.b", "qb.c", "qb.d", "qb.correct_answer", "qr.user_answer").
Page(req.Page, req.PageSize).ScanAndCount(&res, &total, false)
return return
} }

93
Knowledge_Test_Go/internal/logic/questionBank/questionBank.go

@ -9,6 +9,8 @@ import (
"regexp" "regexp"
"strconv" "strconv"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
@ -25,27 +27,27 @@ func init() {
// GetQuestions 获取题目列表 // GetQuestions 获取题目列表
func (s *sQuestionBank) GetQuestions(ctx context.Context, req *v1.QuestionOutputReq) (res []*v1.QuestionOutputRes, total int, err error) { func (s *sQuestionBank) GetQuestions(ctx context.Context, req *v1.QuestionOutputReq) (res []*v1.QuestionOutputRes, total int, err error) {
db := g.Model("question_bank a").
LeftJoin("question_type b", "a.question_type_id = b.id").
LeftJoin("course_recommend c", "a.course_recommendation_id = c.id").
Where("a.isdel = 0").
Fields("a.id", "a.stem", "a.a", "a.b", "a.c", "a.d", "a.correct_answer",
"b.question_type_name", "c.cr_name", "a.error_count", "a.citation_count", "a.error_rate") // 添加 error_rate 字段
db := g.Model("question_bank qb"). //! 别名尽量别用a, b, c之类的
LeftJoin("question_type qt", "qb.question_type_id = qt.id").
LeftJoin("course_recommend cr", "qb.course_recommendation_id = cr.id").
Where("qb.isdel = 0").
Fields("qb.id", "qb.stem", "qb.a", "qb.b", "qb.c", "qb.d", "qb.correct_answer",
"qt.question_type_name", "cr.cr_name", "qb.error_count", "qb.citation_count", "qb.error_rate") // 添加 error_rate 字段
// 添加查询条件 // 添加查询条件
if req.Stem != "" { if req.Stem != "" {
// 对题干进行模糊查询 // 对题干进行模糊查询
db = db.Where("a.stem LIKE ?", "%"+req.Stem+"%")
db = db.WhereLike("qb.stem", "%"+req.Stem+"%")
} }
if req.QuestionTypeId != "" { if req.QuestionTypeId != "" {
// 对题目类型ID进行精准查询 // 对题目类型ID进行精准查询
db = db.Where("a.question_type_id = ?", req.QuestionTypeId)
db = db.Where("qb.question_type_id = ?", req.QuestionTypeId)
} }
if req.CourseRecommendationId != "" { if req.CourseRecommendationId != "" {
// 对课程推荐ID进行精准查询 // 对课程推荐ID进行精准查询
db = db.Where("a.course_recommendation_id = ?", req.CourseRecommendationId)
db = db.Where("qb.course_recommendation_id = ?", req.CourseRecommendationId)
} }
// 添加排序逻辑 // 添加排序逻辑
@ -59,26 +61,20 @@ func (s *sQuestionBank) GetQuestions(ctx context.Context, req *v1.QuestionOutput
func (s *sQuestionBank) buildSortCondition(db *gdb.Model, req *v1.QuestionOutputReq) *gdb.Model { func (s *sQuestionBank) buildSortCondition(db *gdb.Model, req *v1.QuestionOutputReq) *gdb.Model {
// 默认排序(按ID倒序) // 默认排序(按ID倒序)
if req.SortField == "" { if req.SortField == "" {
return db.OrderDesc("a.id")
}
// 确定排序方向
order := "DESC"
if req.SortOrder == "asc" {
order = "ASC"
return db.OrderDesc("qb.created_at") //! 尽量不要用id进行排序
} }
// 根据排序字段构建排序条件 // 根据排序字段构建排序条件
switch req.SortField { switch req.SortField {
case "error_count": case "error_count":
return db.Order("a.error_count " + order)
return db.Order("qb.error_count " + req.SortOrder)
case "error_rate": case "error_rate":
return db.Order("a.error_rate " + order)
return db.Order("qb.error_rate " + req.SortOrder)
case "id": case "id":
return db.Order("a.id " + order)
return db.Order("qb.id " + req.SortOrder)
default: default:
// 默认按ID倒序 // 默认按ID倒序
return db.OrderDesc("a.id")
return db.OrderDesc("qb.created_at")
} }
} }
@ -100,14 +96,12 @@ func (s *sQuestionBank) QuestionUpdate(ctx context.Context, req *v1.QuestionUpda
if req.Id == 0 { if req.Id == 0 {
// 新增记录 // 新增记录
result, err := g.Model("question_bank").Data(data).Insert()
result, err := g.Model("question_bank").Data(data).InsertAndGetId()
if err != nil { if err != nil {
return "新增失败", err return "新增失败", err
} }
// 获取新增的ID
id, _ := result.LastInsertId()
return fmt.Sprintf("新增成功,ID: %d", id), nil
return fmt.Sprintf("新增成功,ID: %d", gconv.Int(result)), nil
} else { } else {
// 更新记录 // 更新记录
_, err := g.Model("question_bank").Where("id = ?", req.Id).Data(data).Update() _, err := g.Model("question_bank").Where("id = ?", req.Id).Data(data).Update()
@ -140,17 +134,17 @@ func (s *sQuestionBank) QuestionDel(ctx context.Context, req *v1.QuestionDelReq)
// UserScoreOutput 获取用户成绩列表 // UserScoreOutput 获取用户成绩列表
func (s *sQuestionBank) UserScoreOutput(ctx context.Context, req *v1.UserScoreOutputReq) (res []*v1.UserScoreOutputRes, total int, err error) { func (s *sQuestionBank) UserScoreOutput(ctx context.Context, req *v1.UserScoreOutputReq) (res []*v1.UserScoreOutputRes, total int, err error) {
db := g.Model("user a").
RightJoin("total_score b", "a.jwcode = b.jwcode").
Fields("a.id", "a.user_name", "a.user_identity", "a.jwcode", "b.created_at", "b.score")
db := g.Model("user u"). //! 别名尽量别用a, b, c之类的
RightJoin("total_score ts", "u.jwcode = ts.jwcode").
Fields("u.id", "u.user_name", "u.user_identity", "u.jwcode", "ts.created_at", "ts.score")
// 添加查询条件 // 添加查询条件
if req.UserName != "" { if req.UserName != "" {
db = db.Where("a.user_name LIKE ?", "%"+req.UserName+"%")
db = db.WhereLike("u.user_name", "%"+req.UserName+"%")
} }
if req.UserIdentity != "" { if req.UserIdentity != "" {
db = db.Where("a.user_identity = ?", req.UserIdentity)
db = db.Where("u.user_identity = ?", req.UserIdentity)
} }
// 预编译正则:匹配8位数字(^表示开头,$表示结尾,\d{8}表示8位数字) // 预编译正则:匹配8位数字(^表示开头,$表示结尾,\d{8}表示8位数字)
@ -162,30 +156,9 @@ func (s *sQuestionBank) UserScoreOutput(ctx context.Context, req *v1.UserScoreOu
return nil, 0, fmt.Errorf("Jwcode必须是8位数字") return nil, 0, fmt.Errorf("Jwcode必须是8位数字")
} }
// 校验通过,添加查询条件 // 校验通过,添加查询条件
db = db.Where("a.jwcode = ?", req.Jwcode)
}
//// 1. 定义时间格式(根据业务实际格式调整)
//const timeLayout = "2006-01-02 15:04:05"
//// 2. 解析开始时间和结束时间(校验格式)
//var startTime, endTime time.Time
//
//if req.StartTime != "" {
// if startTime, err = time.Parse(timeLayout, req.StartTime); err != nil {
// return nil, 0, fmt.Errorf("开始时间格式错误,需为 %s", timeLayout)
// }
//}
//if req.EndTime != "" {
// if endTime, err = time.Parse(timeLayout, req.EndTime); err != nil {
// return nil, 0, fmt.Errorf("结束时间格式错误,需为 %s", timeLayout)
// }
//}
//// 3. 校验结束时间不能早于开始时间(两者都存在时)
//if req.StartTime != "" && req.EndTime != "" {
// if endTime.Before(startTime) { // 用time.Before()判断时间顺序
// return nil, 0, fmt.Errorf("结束时间不能早于开始时间")
// }
//}
db = db.Where("u.jwcode = ?", req.Jwcode)
}
if req.StartTime != "" && req.EndTime != "" { if req.StartTime != "" && req.EndTime != "" {
if req.StartTime > req.EndTime { if req.StartTime > req.EndTime {
return nil, 0, fmt.Errorf("结束时间不能早于开始时间") return nil, 0, fmt.Errorf("结束时间不能早于开始时间")
@ -193,11 +166,11 @@ func (s *sQuestionBank) UserScoreOutput(ctx context.Context, req *v1.UserScoreOu
} }
// 4.时间范围查询 // 4.时间范围查询
if req.StartTime != "" && req.EndTime != "" { if req.StartTime != "" && req.EndTime != "" {
db = db.Where("b.created_at BETWEEN ? AND ?", req.StartTime, req.EndTime)
db = db.Where("ts.created_at BETWEEN ? AND ?", req.StartTime, req.EndTime)
} else if req.StartTime != "" { } else if req.StartTime != "" {
db = db.Where("b.created_at >= ?", req.StartTime)
db = db.WhereGTE("ts.created_at", req.StartTime)
} else if req.EndTime != "" { } else if req.EndTime != "" {
db = db.Where("b.created_at <= ?", req.EndTime)
db = db.WhereLTE("ts.created_at ", req.EndTime)
} }
// 添加排序逻辑 // 添加排序逻辑
@ -211,7 +184,7 @@ func (s *sQuestionBank) UserScoreOutput(ctx context.Context, req *v1.UserScoreOu
func (s *sQuestionBank) buildUserScoreSortCondition(db *gdb.Model, req *v1.UserScoreOutputReq) *gdb.Model { func (s *sQuestionBank) buildUserScoreSortCondition(db *gdb.Model, req *v1.UserScoreOutputReq) *gdb.Model {
// 默认排序(按创建时间倒序) // 默认排序(按创建时间倒序)
if req.SortField == "" { if req.SortField == "" {
return db.OrderDesc("b.created_at")
return db.OrderDesc("ts.created_at")
} }
// 确定排序方向 // 确定排序方向
@ -223,12 +196,12 @@ func (s *sQuestionBank) buildUserScoreSortCondition(db *gdb.Model, req *v1.UserS
// 根据排序字段构建排序条件 // 根据排序字段构建排序条件
switch req.SortField { switch req.SortField {
case "score": case "score":
return db.Order("b.score " + order)
return db.Order("ts.score " + order)
case "created_at": case "created_at":
return db.Order("b.created_at " + order)
return db.Order("ts.created_at " + order)
default: default:
// 默认按创建时间倒序 // 默认按创建时间倒序
return db.OrderDesc("b.created_at")
return db.OrderDesc("ts.created_at")
} }
} }

Loading…
Cancel
Save