Browse Source

11.13

所有接口的功能都已全部实现
wangguixi/feature-20251107144650-股票知识测评
wangguixi 2 months ago
parent
commit
7f7c2a6df9
  1. 22
      Knowledge_Test_Go/api/v1/questionBank.go
  2. 2
      Knowledge_Test_Go/internal/cmd/cmd.go
  3. 42
      Knowledge_Test_Go/internal/controller/knowledge.go
  4. 13
      Knowledge_Test_Go/internal/controller/questionBank.go
  5. 39
      Knowledge_Test_Go/internal/logic/knowledge/knowledge.go
  6. 150
      Knowledge_Test_Go/internal/logic/questionBank/questionBank.go
  7. 2
      Knowledge_Test_Go/internal/service/knowledge.go
  8. 4
      Knowledge_Test_Go/internal/service/question_bank.go

22
Knowledge_Test_Go/api/v1/questionBank.go

@ -51,6 +51,16 @@ type GetUserScoresRes struct {
Score int `json:"score"`
}
// GetCourseReq 获取用户课程请求
type GetCourseReq struct {
Jwcode int `v:"required" dc:"精网号"`
}
// GetCourseRes 获取用户课程响应
type GetCourseRes struct {
CrName []string `json:"cr_name"`
}
// GetWrongQuestionsRes 错题详情
type GetWrongQuestionsRes struct {
GetQuestionsRes `json:"question"`
@ -103,8 +113,8 @@ type QuestionDelReq struct {
Id int `json:"id"`
}
// UserScoreOutput 用户成绩输出
type UserScoreOutput struct {
// UserScoreOutputRes 获取用户成绩列表响应
type UserScoreOutputRes struct {
Id int `json:"id"`
UserName string `json:"user_name"`
UserIdentity string `json:"user_identity"`
@ -115,9 +125,11 @@ type UserScoreOutput struct {
// UserScoreOutputReq 获取用户成绩列表请求
type UserScoreOutputReq struct {
//UserName string `json:"user_name"`
//UserIdentity string `json:"user_identity"`
//Jwcode int `json:"jwcode"`
UserName string `json:"user_name"` // 用户名(精准查询)
UserIdentity string `json:"user_identity"` // 用户身份(过滤)
Jwcode int `json:"jwcode"` // 精网号(精准查询)
StartTime string `json:"start_time"` // 开始时间(提交时间范围)
EndTime string `json:"end_time"` // 结束时间(提交时间范围)
Page int `json:"page"`
PageSize int `json:"page_size"`
}

2
Knowledge_Test_Go/internal/cmd/cmd.go

@ -27,6 +27,7 @@ var (
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) // 获取课程
})
// 后台路由组
@ -40,6 +41,7 @@ var (
group.POST("/user/score", controller.NewQuestionBank().UserScoreOutput) // 获取用户成绩
group.POST("/questions/user", controller.NewQuestionBank().ErrorOutPutUser) // 获取错题用户列表
group.POST("/questions/export", controller.NewQuestionBank().ExportQuestion) // 导出题目数据到 Excel
group.POST("/user/export", controller.NewQuestionBank().ExportUserScore) //导出用户成绩到 Excel
})
s.Run()

42
Knowledge_Test_Go/internal/controller/knowledge.go

@ -46,6 +46,20 @@ func (c *cKnowledgeTest) GetUserScores(r *ghttp.Request) {
response.JsonExit(r, 200, "success", res)
}
// GetScores 获取课程推荐
func (c *cKnowledgeTest) GetCourse(r *ghttp.Request) {
ctx := r.GetCtx()
var req *v1.GetCourseReq
if err := r.Parse(&req); err != nil {
response.JsonExit(r, 400, err.Error())
}
res, err := service.KnowledgeTest().GetCourse(ctx, req)
if err != nil {
response.JsonExit(r, 400, err.Error())
}
response.JsonExit(r, 200, "success", res)
}
// SubmitAnswers 提交答案
func (c *cKnowledgeTest) SubmitAnswers(r *ghttp.Request) {
ctx := r.GetCtx()
@ -78,31 +92,3 @@ func (c *cKnowledgeTest) GetWrongQuestions(r *ghttp.Request) {
"total": total,
})
}
//
//// GetUserScores 获取用户成绩
//func (c *KnowledgeTest) GetUserScores(r *ghttp.Request) {
// var req v1.GetUserScoresReq
// if err := r.Parse(&req); err != nil {
// r.Response.WriteJson(g.Map{
// "code": 500,
// "msg": err.Error(),
// })
// return
// }
//
// res, err := knowledge.NewKnowledgeTestLogic(r.Context()).GetUserScores(&req)
// if err != nil {
// r.Response.WriteJson(g.Map{
// "code": 500,
// "msg": err.Error(),
// })
// return
// }
//
// r.Response.WriteJson(g.Map{
// "code": 200,
// "msg": "success",
// "data": res,
// })
//}*/

13
Knowledge_Test_Go/internal/controller/questionBank.go

@ -107,3 +107,16 @@ func (c *cQuestionBank) ExportQuestion(r *ghttp.Request) {
}
service.QuestionBank().ExportQuestion(r, ctx, req)
}
// ExportUserScore 导出用户成绩到 Excel
func (c *cQuestionBank) ExportUserScore(r *ghttp.Request) {
ctx := r.GetCtx()
var req *v1.UserScoreOutputReq
if err := r.Parse(&req); err != nil {
response.JsonExit(r, 400, err.Error())
return
}
// 调用服务层的导出方法
service.QuestionBank().ExportUserScore(r, ctx, req)
}

39
Knowledge_Test_Go/internal/logic/knowledge/knowledge.go

@ -39,6 +39,45 @@ func (s *sKnowledgeTest) GetUserScores(ctx context.Context, req *v1.GetUserScore
// -----------------------------------------------------------------------------------------------------------------------------------------------
// GetCourse 获取用户课程
func (s *sKnowledgeTest) GetCourse(ctx context.Context, req *v1.GetCourseReq) (res []*v1.GetCourseRes, err error) {
// 使用临时结构体接收数据
type Course struct {
CrName string `json:"cr_name"`
}
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").
Ctx(ctx).
Scan(&courses)
if err != nil {
return nil, fmt.Errorf("查询课程名称失败: %w", err)
}
// 提取纯字符串
courseNames := make([]string, 0, len(courses))
for _, course := range courses {
courseNames = append(courseNames, course.CrName)
}
// 创建响应
res = append(res, &v1.GetCourseRes{
CrName: courseNames,
})
return res, nil
}
// -----------------------------------------------------------------------------------------------------------------------------------------------
// SubmitAnswers 提交答案并计算分数
func (s *sKnowledgeTest) SubmitAnswers(ctx context.Context, req *v1.SubmitAnswersReq) (*v1.SubmitAnswersRes, error) {
if len(req.Answers) == 0 {

150
Knowledge_Test_Go/internal/logic/questionBank/questionBank.go

@ -123,10 +123,36 @@ func (s *sQuestionBank) QuestionDel(ctx context.Context, req *v1.QuestionDelReq)
//-------------------------------------------------------------------------------------------------------------------------------
// UserScoreOutput 获取用户成绩列表
func (s *sQuestionBank) UserScoreOutput(ctx context.Context, req *v1.UserScoreOutputReq) (res []*v1.UserScoreOutput, 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")
// 添加查询条件
if req.UserName != "" {
db = db.Where("a.user_name = ?", req.UserName)
}
if req.UserIdentity != "" {
db = db.Where("a.user_identity = ?", req.UserIdentity)
}
if req.Jwcode != 0 {
db = db.Where("a.jwcode = ?", req.Jwcode)
}
// 时间范围查询
if req.StartTime != "" && req.EndTime != "" {
db = db.Where("b.created_at BETWEEN ? AND ?", req.StartTime, req.EndTime)
} else if req.StartTime != "" {
db = db.Where("b.created_at >= ?", req.StartTime)
} else if req.EndTime != "" {
db = db.Where("b.created_at <= ?", req.EndTime)
}
// 添加排序,默认按创建时间倒序
db = db.OrderDesc("b.created_at")
err = db.Page(req.Page, req.PageSize).ScanAndCount(&res, &total, false)
return
}
@ -200,7 +226,7 @@ func (s *sQuestionBank) ExportQuestion(r *ghttp.Request, ctx context.Context, re
fileName := "题目数据导出.xlsx"
// === 4. 设置表头 ===
headers := []string{"ID", "题干", "选项A", "选项B", "选项C", "选项D", "正确答案", "题目类型", "推荐课程", "引用次数", "错误次数", "错误率"}
headers := []string{"序号", "ID", "题干", "选项A", "选项B", "选项C", "选项D", "正确答案", "题目类型", "推荐课程", "引用次数", "错误次数", "错误率"}
for i, header := range headers {
col := string('A' + i)
excelFile.SetCellValue(sheetName, col+"1", header)
@ -245,13 +271,119 @@ func (s *sQuestionBank) ExportQuestion(r *ghttp.Request, ctx context.Context, re
excelFile.SetCellStyle(sheetName, "A1", "L"+strconv.Itoa(lastRow), style)
// 设置列宽
excelFile.SetColWidth(sheetName, "A", "A", 10) // ID
excelFile.SetColWidth(sheetName, "B", "B", 40) // 题干
excelFile.SetColWidth(sheetName, "C", "F", 20) // 选项A-D
excelFile.SetColWidth(sheetName, "G", "G", 12) // 正确答案
excelFile.SetColWidth(sheetName, "H", "H", 15) // 题目类型
excelFile.SetColWidth(sheetName, "I", "I", 20) // 推荐课程
excelFile.SetColWidth(sheetName, "J", "L", 12) // 统计信息
excelFile.SetColWidth(sheetName, "B", "B", 10) // ID
excelFile.SetColWidth(sheetName, "C", "C", 40) // 题干
excelFile.SetColWidth(sheetName, "D", "G", 20) // 选项A-D
excelFile.SetColWidth(sheetName, "H", "H", 12) // 正确答案
excelFile.SetColWidth(sheetName, "I", "I", 15) // 题目类型
excelFile.SetColWidth(sheetName, "J", "J", 20) // 推荐课程
excelFile.SetColWidth(sheetName, "K", "M", 12) // 统计信息
// === 7. 输出 Excel 文件 ===
buffer, err := excelFile.WriteToBuffer()
if err != nil {
response.JsonExit(r, 400, "生成Excel文件失败", err.Error())
return
}
// 设置响应头
r.Response.Header().Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
r.Response.Header().Set("Content-Disposition", "attachment; filename="+fileName)
r.Response.Write(buffer.Bytes())
}
//-------------------------------------------------------------------------------------------------------------------------------
// ExportUserScore 导出用户成绩数据到 Excel
func (s *sQuestionBank) ExportUserScore(r *ghttp.Request, ctx context.Context, req *v1.UserScoreOutputReq) {
// === 1. 数据查询和验证 ===
var result []*v1.UserScoreOutputRes
// 查询总数
_, total, err := service.QuestionBank().UserScoreOutput(ctx, req)
if err != nil {
response.JsonExit(r, 400, "查询失败", err.Error())
return
}
// 数据量验证
if total == 0 {
response.JsonExit(r, 400, "查询结果为空")
return
}
if total > 20000 {
response.JsonExit(r, 400, "导出数据过多,请添加筛选条件后再导出")
return
}
// === 2. 分批查询数据 ===
var num int
req.PageSize = 1000
for {
res, total, err := service.QuestionBank().UserScoreOutput(ctx, req)
if err != nil {
response.JsonExit(r, 400, "分批查询失败", err.Error())
return
}
result = append(result, res...)
num += req.PageSize
if num >= total {
break
}
req.Page++
}
// === 3. 创建 Excel 文件 ===
excelFile := excelize.NewFile()
sheetName := "Sheet1"
fileName := "用户成绩导出.xlsx"
// === 4. 设置表头 ===
headers := []string{"序号", "ID", "用户名", "用户身份", "精网号", "成绩", "创建时间"}
for i, header := range headers {
col := string('A' + i)
excelFile.SetCellValue(sheetName, col+"1", header)
}
// === 5. 写入数据 ===
rowIndex := 2
for _, userScore := range result {
excelFile.SetCellValue(sheetName, "A"+strconv.Itoa(rowIndex), rowIndex-1)
excelFile.SetCellValue(sheetName, "B"+strconv.Itoa(rowIndex), userScore.Id)
excelFile.SetCellValue(sheetName, "C"+strconv.Itoa(rowIndex), userScore.UserName)
excelFile.SetCellValue(sheetName, "D"+strconv.Itoa(rowIndex), userScore.UserIdentity)
excelFile.SetCellValue(sheetName, "E"+strconv.Itoa(rowIndex), userScore.Jwcode)
excelFile.SetCellValue(sheetName, "F"+strconv.Itoa(rowIndex), userScore.Score)
excelFile.SetCellValue(sheetName, "G"+strconv.Itoa(rowIndex), userScore.CreatedAt)
rowIndex++
}
// === 6. 样式设置 ===
lastRow := rowIndex - 1
// 创建样式
style, err := excelFile.NewStyle(&excelize.Style{
Alignment: &excelize.Alignment{
Horizontal: "center",
Vertical: "center",
},
})
if err != nil {
response.JsonExit(r, 400, "创建样式失败", err.Error())
return
}
// 应用样式
excelFile.SetCellStyle(sheetName, "A1", "F"+strconv.Itoa(lastRow), style)
// 设置列宽
excelFile.SetColWidth(sheetName, "B", "B", 10) // ID
excelFile.SetColWidth(sheetName, "C", "C", 20) // 用户名
excelFile.SetColWidth(sheetName, "D", "D", 15) // 用户身份
excelFile.SetColWidth(sheetName, "E", "E", 15) // 精网号
excelFile.SetColWidth(sheetName, "F", "F", 10) // 成绩
excelFile.SetColWidth(sheetName, "G", "G", 20) // 创建时间
// === 7. 输出 Excel 文件 ===
buffer, err := excelFile.WriteToBuffer()

2
Knowledge_Test_Go/internal/service/knowledge.go

@ -16,6 +16,8 @@ type (
GetQuestions(ctx context.Context, req *v1.GetQuestionsReq) (res []*v1.GetQuestionsRes, total int, err error)
// GetUserScores 获取用户成绩
GetUserScores(ctx context.Context, req *v1.GetUserScoresReq) (res []*v1.GetUserScoresRes, err error)
// GetCourse 获取用户课程
GetCourse(ctx context.Context, req *v1.GetCourseReq) (res []*v1.GetCourseRes, err error)
// SubmitAnswers 提交答案并计算分数
SubmitAnswers(ctx context.Context, req *v1.SubmitAnswersReq) (*v1.SubmitAnswersRes, error)
// GetWrongQuestions 获取错题列表

4
Knowledge_Test_Go/internal/service/question_bank.go

@ -21,11 +21,13 @@ type (
// QuestionDel 删除题目
QuestionDel(ctx context.Context, req *v1.QuestionDelReq) (res string, err error)
// UserScoreOutput 获取用户成绩列表
UserScoreOutput(ctx context.Context, req *v1.UserScoreOutputReq) (res []*v1.UserScoreOutput, total int, err error)
UserScoreOutput(ctx context.Context, req *v1.UserScoreOutputReq) (res []*v1.UserScoreOutputRes, total int, err error)
// ErrorOutPutUser 错题统计出错用户
ErrorOutPutUser(ctx context.Context, req *v1.ErrorOutPutUserReq) (res []*v1.ErrorOutPutUserRes, total int, err error)
// ExportQuestion 导出题目数据到 Excel
ExportQuestion(r *ghttp.Request, ctx context.Context, req *v1.QuestionOutputReq)
// ExportUserScore 导出用户成绩数据到 Excel
ExportUserScore(r *ghttp.Request, ctx context.Context, req *v1.UserScoreOutputReq)
}
)

Loading…
Cancel
Save