10 Commits
38604e965d
...
68702e8af7
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
68702e8af7 |
11.17
修改了jwcode的属性 |
2 months ago |
|
|
ae17259454 |
11.17
EX导出删除了id字段 |
2 months ago |
|
|
1283fd1747 |
11.17
错题展示用户接口,查询条件补充 |
2 months ago |
|
|
f88b3e27e6 |
11.14
补充后台的跨域 |
2 months ago |
|
|
7f7c2a6df9 |
11.13
所有接口的功能都已全部实现 |
2 months ago |
|
|
4ef48d2d72 |
11.12
所有接口的基本功能都已实现 |
2 months ago |
|
|
7a22dd79e2 |
后台题目查询,更新,修改,删除接口
|
2 months ago |
|
|
a1b0b17c11 |
后台题目查询,更新,修改,删除接口
|
2 months ago |
|
|
ad4fef81da |
前台接口基本功能完成
|
2 months ago |
|
|
c50c45d74b |
测试远程仓库连接
|
2 months ago |
42 changed files with 2351 additions and 124 deletions
-
15Knowledge_Test_Go/api/hello/hello.go
-
12Knowledge_Test_Go/api/hello/v1/hello.go
-
149Knowledge_Test_Go/api/v1/questionBank.go
-
56Knowledge_Test_Go/go.mod
-
135Knowledge_Test_Go/go.sum
-
21Knowledge_Test_Go/hack/config.yaml
-
34Knowledge_Test_Go/internal/cmd/cmd.go
-
5Knowledge_Test_Go/internal/controller/hello/hello.go
-
13Knowledge_Test_Go/internal/controller/hello/hello_v1_hello.go
-
94Knowledge_Test_Go/internal/controller/knowledge.go
-
122Knowledge_Test_Go/internal/controller/questionBank.go
-
27Knowledge_Test_Go/internal/dao/course_recommend.go
-
75Knowledge_Test_Go/internal/dao/internal/course_recommend.go
-
99Knowledge_Test_Go/internal/dao/internal/question_bank.go
-
83Knowledge_Test_Go/internal/dao/internal/question_record.go
-
75Knowledge_Test_Go/internal/dao/internal/question_type.go
-
79Knowledge_Test_Go/internal/dao/internal/total_score.go
-
81Knowledge_Test_Go/internal/dao/internal/user.go
-
27Knowledge_Test_Go/internal/dao/question_bank.go
-
27Knowledge_Test_Go/internal/dao/question_record.go
-
27Knowledge_Test_Go/internal/dao/question_type.go
-
27Knowledge_Test_Go/internal/dao/total_score.go
-
27Knowledge_Test_Go/internal/dao/user.go
-
233Knowledge_Test_Go/internal/logic/knowledge/knowledge.go
-
15Knowledge_Test_Go/internal/logic/logic.go
-
471Knowledge_Test_Go/internal/logic/questionBank/questionBank.go
-
16Knowledge_Test_Go/internal/model/do/course_recommend.go
-
29Knowledge_Test_Go/internal/model/do/question_bank.go
-
21Knowledge_Test_Go/internal/model/do/question_record.go
-
16Knowledge_Test_Go/internal/model/do/question_type.go
-
19Knowledge_Test_Go/internal/model/do/total_score.go
-
20Knowledge_Test_Go/internal/model/do/user.go
-
11Knowledge_Test_Go/internal/model/entity/course_recommend.go
-
27Knowledge_Test_Go/internal/model/entity/question_bank.go
-
19Knowledge_Test_Go/internal/model/entity/question_record.go
-
11Knowledge_Test_Go/internal/model/entity/question_type.go
-
17Knowledge_Test_Go/internal/model/entity/total_score.go
-
18Knowledge_Test_Go/internal/model/entity/user.go
-
41Knowledge_Test_Go/internal/service/knowledge.go
-
47Knowledge_Test_Go/internal/service/question_bank.go
-
6Knowledge_Test_Go/main.go
-
128Knowledge_Test_Go/utility/response/response.go
@ -1,15 +0,0 @@ |
|||||
// =================================================================================
|
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
|
||||
// =================================================================================
|
|
||||
|
|
||||
package hello |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"Knowledge_Test_Go/api/hello/v1" |
|
||||
) |
|
||||
|
|
||||
type IHelloV1 interface { |
|
||||
Hello(ctx context.Context, req *v1.HelloReq) (res *v1.HelloRes, err error) |
|
||||
} |
|
||||
@ -1,12 +0,0 @@ |
|||||
package v1 |
|
||||
|
|
||||
import ( |
|
||||
"github.com/gogf/gf/v2/frame/g" |
|
||||
) |
|
||||
|
|
||||
type HelloReq struct { |
|
||||
g.Meta `path:"/hello" tags:"Hello" method:"get" summary:"You first hello api"` |
|
||||
} |
|
||||
type HelloRes struct { |
|
||||
g.Meta `mime:"text/html" example:"string"` |
|
||||
} |
|
||||
@ -0,0 +1,149 @@ |
|||||
|
package v1 |
||||
|
|
||||
|
// GetQuestionsReq 获取题目请求
|
||||
|
type GetQuestionsReq struct { |
||||
|
Page int `json:"page"` |
||||
|
PageSize int `json:"page_size"` |
||||
|
} |
||||
|
|
||||
|
// GetQuestionsRes 获取题目响应
|
||||
|
type GetQuestionsRes struct { |
||||
|
Id int `json:"id"` |
||||
|
Stem string `json:"stem"` |
||||
|
A string `json:"A"` |
||||
|
B string `json:"B"` |
||||
|
C string `json:"C"` |
||||
|
D string `json:"D"` |
||||
|
} |
||||
|
|
||||
|
// SubmitAnswersReq 提交答案请求
|
||||
|
type SubmitAnswersReq struct { |
||||
|
Jwcode int `v:"required" dc:"精网号"` |
||||
|
Answers []*AnswerItem `v:"required" dc:"答案列表"` |
||||
|
} |
||||
|
|
||||
|
// AnswerItem 答案项
|
||||
|
type AnswerItem struct { |
||||
|
QuestionId int `json:"questionId" dc:"题目ID"` |
||||
|
UserAnswer string `json:"userAnswer" dc:"用户答案"` |
||||
|
} |
||||
|
|
||||
|
// SubmitAnswersRes 提交答案响应
|
||||
|
type SubmitAnswersRes struct { |
||||
|
Score int `json:"score" dc:"得分"` |
||||
|
Total int `json:"total" dc:"总分"` |
||||
|
} |
||||
|
|
||||
|
// GetWrongQuestionsReq 获取错题请求
|
||||
|
type GetWrongQuestionsReq struct { |
||||
|
Jwcode int `v:"required" dc:"精网号(查询参数传递)"` |
||||
|
Page int `json:"page"` |
||||
|
PageSize int `json:"page_size"` |
||||
|
} |
||||
|
|
||||
|
// GetUserScoresReq 获取用户成绩请求
|
||||
|
type GetUserScoresReq struct { |
||||
|
Jwcode int `v:"required" dc:"精网号"` |
||||
|
} |
||||
|
|
||||
|
// GetUserScoresRes 获取用户成绩响应
|
||||
|
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"` |
||||
|
UserAnswer string `json:"userAnswer" dc:"用户答案"` |
||||
|
CorrectAnswer string `json:"correctAnswer" dc:"正确答案"` |
||||
|
} |
||||
|
|
||||
|
//------------------------------------------------------------------------------------------------------------
|
||||
|
|
||||
|
// QuestionOutputReq 获取题目列表请求
|
||||
|
type QuestionOutputReq struct { |
||||
|
Stem string `json:"stem"` |
||||
|
QuestionTypeId string `json:"question_type_id"` |
||||
|
CourseRecommendationId string `json:"course+recommendation_id"` |
||||
|
Page int `json:"page"` |
||||
|
PageSize int `json:"page_size"` |
||||
|
SortField string `json:"sort_field"` // 排序字段:error_count, error_rate, id
|
||||
|
SortOrder string `json:"sort_order"` // 排序方向:asc, desc
|
||||
|
} |
||||
|
|
||||
|
// QuestionOutputRes 题目输出
|
||||
|
type QuestionOutputRes struct { |
||||
|
Id int `json:"id"` |
||||
|
Stem string `json:"stem"` |
||||
|
A string `json:"A"` |
||||
|
B string `json:"B"` |
||||
|
C string `json:"C"` |
||||
|
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"` |
||||
|
} |
||||
|
|
||||
|
// QuestionUpdateReq 修改题目请求
|
||||
|
type QuestionUpdateReq struct { |
||||
|
Id int `json:"id"` |
||||
|
Stem string `json:"stem"` |
||||
|
A string `json:"A"` |
||||
|
B string `json:"B"` |
||||
|
C string `json:"C"` |
||||
|
D string `json:"D"` |
||||
|
CorrectAnswer string `json:"correct_answer"` |
||||
|
QuestionTypeId string `json:"question_type_id"` |
||||
|
CourseRecommendationId string `json:"course+recommendation_id"` |
||||
|
} |
||||
|
|
||||
|
// QuestionDelReq 删除题目请求
|
||||
|
type QuestionDelReq struct { |
||||
|
Id int `json:"id"` |
||||
|
} |
||||
|
|
||||
|
// UserScoreOutputRes 获取用户成绩列表响应
|
||||
|
type UserScoreOutputRes struct { |
||||
|
Id int `json:"id"` |
||||
|
UserName string `json:"user_name"` |
||||
|
UserIdentity string `json:"user_identity"` |
||||
|
Jwcode int `json:"jwcode"` |
||||
|
Score int `json:"score"` |
||||
|
CreatedAt string `json:"createdAt"` |
||||
|
} |
||||
|
|
||||
|
// UserScoreOutputReq 获取用户成绩列表请求
|
||||
|
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"` // 结束时间(提交时间范围)
|
||||
|
Page int `json:"page"` |
||||
|
PageSize int `json:"page_size"` |
||||
|
SortField string `json:"sort_field"` // 排序字段:score, created_at
|
||||
|
SortOrder string `json:"sort_order"` // 排序方向:asc, desc
|
||||
|
} |
||||
|
|
||||
|
// ErrorOutPutUserReq 获取错题用户列表请求
|
||||
|
type ErrorOutPutUserReq struct { |
||||
|
Id int `json:"id"` |
||||
|
} |
||||
|
type ErrorOutPutUserRes struct { |
||||
|
UserName string `json:"user_name"` |
||||
|
UserIdentity string `json:"user_identity"` |
||||
|
ErrorCount int `json:"error_count"` |
||||
|
} |
||||
@ -1,28 +1,50 @@ |
|||||
module Knowledge_Test_Go |
module Knowledge_Test_Go |
||||
|
|
||||
go 1.18 |
|
||||
|
go 1.24.0 |
||||
|
|
||||
require github.com/gogf/gf/v2 v2.7.1 |
|
||||
|
require ( |
||||
|
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.4 |
||||
|
github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.4 |
||||
|
github.com/gogf/gf/v2 v2.9.4 |
||||
|
github.com/xuri/excelize/v2 v2.10.0 |
||||
|
) |
||||
|
|
||||
require ( |
require ( |
||||
github.com/BurntSushi/toml v1.3.2 // indirect |
|
||||
|
github.com/BurntSushi/toml v1.5.0 // indirect |
||||
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect |
||||
github.com/clbanning/mxj/v2 v2.7.0 // indirect |
github.com/clbanning/mxj/v2 v2.7.0 // indirect |
||||
github.com/fatih/color v1.16.0 // indirect |
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect |
|
||||
github.com/go-logr/logr v1.2.3 // indirect |
|
||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect |
||||
|
github.com/emirpasic/gods v1.18.1 // indirect |
||||
|
github.com/fatih/color v1.18.0 // indirect |
||||
|
github.com/fsnotify/fsnotify v1.9.0 // indirect |
||||
|
github.com/go-logr/logr v1.4.3 // indirect |
||||
github.com/go-logr/stdr v1.2.2 // indirect |
github.com/go-logr/stdr v1.2.2 // indirect |
||||
github.com/gorilla/websocket v1.5.1 // indirect |
|
||||
|
github.com/go-sql-driver/mysql v1.7.1 // indirect |
||||
|
github.com/google/uuid v1.6.0 // indirect |
||||
|
github.com/gorilla/websocket v1.5.3 // indirect |
||||
github.com/grokify/html-strip-tags-go v0.1.0 // indirect |
github.com/grokify/html-strip-tags-go v0.1.0 // indirect |
||||
github.com/magiconair/properties v1.8.7 // indirect |
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect |
|
||||
|
github.com/magiconair/properties v1.8.10 // indirect |
||||
|
github.com/mattn/go-colorable v0.1.14 // indirect |
||||
github.com/mattn/go-isatty v0.0.20 // indirect |
github.com/mattn/go-isatty v0.0.20 // indirect |
||||
github.com/mattn/go-runewidth v0.0.9 // indirect |
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect |
|
||||
go.opentelemetry.io/otel v1.14.0 // indirect |
|
||||
go.opentelemetry.io/otel/sdk v1.14.0 // indirect |
|
||||
go.opentelemetry.io/otel/trace v1.14.0 // indirect |
|
||||
golang.org/x/net v0.24.0 // indirect |
|
||||
golang.org/x/sys v0.19.0 // indirect |
|
||||
golang.org/x/text v0.14.0 // indirect |
|
||||
|
github.com/mattn/go-runewidth v0.0.16 // indirect |
||||
|
github.com/olekukonko/errors v1.1.0 // indirect |
||||
|
github.com/olekukonko/ll v0.0.9 // indirect |
||||
|
github.com/olekukonko/tablewriter v1.1.0 // indirect |
||||
|
github.com/redis/go-redis/v9 v9.12.1 // indirect |
||||
|
github.com/richardlehane/mscfb v1.0.4 // indirect |
||||
|
github.com/richardlehane/msoleps v1.0.4 // indirect |
||||
|
github.com/rivo/uniseg v0.4.7 // indirect |
||||
|
github.com/tiendc/go-deepcopy v1.7.1 // indirect |
||||
|
github.com/xuri/efp v0.0.1 // indirect |
||||
|
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 // indirect |
||||
|
go.opentelemetry.io/auto/sdk v1.1.0 // indirect |
||||
|
go.opentelemetry.io/otel v1.38.0 // indirect |
||||
|
go.opentelemetry.io/otel/metric v1.38.0 // indirect |
||||
|
go.opentelemetry.io/otel/sdk v1.38.0 // indirect |
||||
|
go.opentelemetry.io/otel/trace v1.38.0 // indirect |
||||
|
golang.org/x/crypto v0.43.0 // indirect |
||||
|
golang.org/x/net v0.46.0 // indirect |
||||
|
golang.org/x/sys v0.37.0 // indirect |
||||
|
golang.org/x/text v0.30.0 // indirect |
||||
gopkg.in/yaml.v3 v3.0.1 // indirect |
gopkg.in/yaml.v3 v3.0.1 // indirect |
||||
) |
) |
||||
@ -1,52 +1,113 @@ |
|||||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= |
|
||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= |
|
||||
|
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= |
||||
|
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= |
||||
|
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= |
||||
|
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= |
||||
|
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= |
||||
|
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= |
||||
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= |
||||
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= |
||||
github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= |
github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= |
||||
github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= |
github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= |
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= |
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= |
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= |
|
||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= |
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= |
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= |
|
||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |
||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= |
||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= |
||||
|
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= |
||||
|
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= |
||||
|
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= |
||||
|
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= |
||||
|
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= |
||||
|
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= |
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= |
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= |
||||
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= |
|
||||
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= |
|
||||
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= |
||||
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= |
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= |
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= |
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= |
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= |
||||
github.com/gogf/gf/v2 v2.7.1 h1:Ukp7vzwh6VKnivEEx/xiMc61dL1HVZqCCHl//3GBRxc= |
|
||||
github.com/gogf/gf/v2 v2.7.1/go.mod h1:3oyGjyLHtSSo8kQ57Nj1TPdUNc0e2HS0A2J+KkXoW+I= |
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= |
|
||||
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= |
|
||||
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= |
|
||||
|
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= |
||||
|
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= |
||||
|
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.4 h1:ntAPahCjQwQ79CC6tI67QDgj17NTWp+lMd1SaL2jJhs= |
||||
|
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.4/go.mod h1:/350+9clTW5ktUvF+hePMN9yDknB2ipslqcx3Y2rLDQ= |
||||
|
github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.4 h1:iKXUQ+8TklSriAqOQjfwioI36zlByqrDqz4ISaRFvm8= |
||||
|
github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.4/go.mod h1:PYVwyQ0gN+w3wL7zKAoeUpy2WFs4/V8+Ls+eNsy7Uo0= |
||||
|
github.com/gogf/gf/v2 v2.9.4 h1:6vleEWypot9WBPncP2GjbpgAUeG6Mzb1YESb9nPMkjY= |
||||
|
github.com/gogf/gf/v2 v2.9.4/go.mod h1:Ukl+5HUH9S7puBmNLR4L1zUqeRwi0nrW4OigOknEztU= |
||||
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= |
||||
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= |
||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= |
||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= |
||||
|
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= |
||||
|
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= |
||||
github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= |
github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= |
||||
github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= |
github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= |
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= |
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= |
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= |
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= |
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= |
|
||||
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= |
||||
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= |
||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= |
||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= |
||||
|
github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= |
||||
|
github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= |
||||
|
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= |
||||
|
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= |
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= |
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= |
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= |
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= |
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= |
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= |
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= |
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= |
|
||||
|
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= |
||||
|
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= |
||||
|
github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM= |
||||
|
github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= |
||||
|
github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI= |
||||
|
github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g= |
||||
|
github.com/olekukonko/tablewriter v1.1.0 h1:N0LHrshF4T39KvI96fn6GT8HEjXRXYNDrDjKFDB7RIY= |
||||
|
github.com/olekukonko/tablewriter v1.1.0/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo= |
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= |
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= |
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= |
|
||||
go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= |
|
||||
go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= |
|
||||
go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= |
|
||||
go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= |
|
||||
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= |
|
||||
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= |
|
||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= |
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= |
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
|
||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= |
||||
|
github.com/redis/go-redis/v9 v9.12.1 h1:k5iquqv27aBtnTm2tIkROUDp8JBXhXZIVu1InSgvovg= |
||||
|
github.com/redis/go-redis/v9 v9.12.1/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= |
||||
|
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM= |
||||
|
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk= |
||||
|
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= |
||||
|
github.com/richardlehane/msoleps v1.0.4 h1:WuESlvhX3gH2IHcd8UqyCuFY5yiq/GR/yqaSM/9/g00= |
||||
|
github.com/richardlehane/msoleps v1.0.4/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= |
||||
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= |
||||
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= |
||||
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= |
||||
|
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= |
||||
|
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= |
||||
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= |
||||
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= |
||||
|
github.com/tiendc/go-deepcopy v1.7.1 h1:LnubftI6nYaaMOcaz0LphzwraqN8jiWTwm416sitff4= |
||||
|
github.com/tiendc/go-deepcopy v1.7.1/go.mod h1:4bKjNC2r7boYOkD2IOuZpYjmlDdzjbpTRyCx+goBCJQ= |
||||
|
github.com/xuri/efp v0.0.1 h1:fws5Rv3myXyYni8uwj2qKjVaRP30PdjeYe2Y6FDsCL8= |
||||
|
github.com/xuri/efp v0.0.1/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI= |
||||
|
github.com/xuri/excelize/v2 v2.10.0 h1:8aKsP7JD39iKLc6dH5Tw3dgV3sPRh8uRVXu/fMstfW4= |
||||
|
github.com/xuri/excelize/v2 v2.10.0/go.mod h1:SC5TzhQkaOsTWpANfm+7bJCldzcnU/jrhqkTi/iBHBU= |
||||
|
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 h1:+C0TIdyyYmzadGaL/HBLbf3WdLgC29pgyhTjAT/0nuE= |
||||
|
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ= |
||||
|
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= |
||||
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= |
||||
|
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= |
||||
|
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= |
||||
|
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= |
||||
|
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= |
||||
|
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= |
||||
|
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= |
||||
|
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= |
||||
|
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= |
||||
|
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= |
||||
|
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= |
||||
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= |
||||
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= |
||||
|
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= |
||||
|
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= |
||||
|
golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ= |
||||
|
golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs= |
||||
|
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= |
||||
|
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= |
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= |
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= |
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= |
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= |
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= |
|
||||
|
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= |
||||
|
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= |
||||
|
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= |
||||
|
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= |
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= |
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= |
||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= |
||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= |
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= |
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= |
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
||||
@ -1,13 +1,16 @@ |
|||||
|
|
||||
# CLI tool, only in development environment. |
# CLI tool, only in development environment. |
||||
# https://goframe.org/docs/cli |
|
||||
|
# https://goframe.org/pages/viewpage.action?pageId=3673173 |
||||
gfcli: |
gfcli: |
||||
|
# 工具编译配置 |
||||
|
build: |
||||
|
name: "Knowledge_Test_Go" |
||||
|
path: "./bin" |
||||
|
arch: "amd64" |
||||
|
system: "linux" |
||||
|
packSrc: "manifest/i18n" |
||||
|
|
||||
|
# dao生成 |
||||
gen: |
gen: |
||||
dao: |
dao: |
||||
- link: "mysql:root:12345678@tcp(127.0.0.1:3306)/test" |
|
||||
descriptionTag: true |
|
||||
|
|
||||
docker: |
|
||||
build: "-a amd64 -s linux -p temp -ew" |
|
||||
tagPrefixes: |
|
||||
- my.image.pub/my-app |
|
||||
|
- link: "mysql:root:123456@tcp(127.0.0.1:3306)/knowledge_test?loc=Local&parseTime=true" |
||||
|
tables: "" |
||||
@ -1,5 +0,0 @@ |
|||||
// =================================================================================
|
|
||||
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
|
||||
// =================================================================================
|
|
||||
|
|
||||
package hello |
|
||||
@ -1,13 +0,0 @@ |
|||||
package hello |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
"github.com/gogf/gf/v2/frame/g" |
|
||||
|
|
||||
"Knowledge_Test_Go/api/hello/v1" |
|
||||
) |
|
||||
|
|
||||
func (c *ControllerV1) Hello(ctx context.Context, req *v1.HelloReq) (res *v1.HelloRes, err error) { |
|
||||
g.RequestFromCtx(ctx).Response.Writeln("Hello World!") |
|
||||
return |
|
||||
} |
|
||||
@ -0,0 +1,94 @@ |
|||||
|
package controller |
||||
|
|
||||
|
import ( |
||||
|
"Knowledge_Test_Go/api/v1" |
||||
|
"Knowledge_Test_Go/internal/service" |
||||
|
"Knowledge_Test_Go/utility/response" |
||||
|
|
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
"github.com/gogf/gf/v2/net/ghttp" |
||||
|
) |
||||
|
|
||||
|
type CKnowledgeTest struct{} |
||||
|
|
||||
|
func NewKnowledgeTest() *CKnowledgeTest { |
||||
|
return &CKnowledgeTest{} |
||||
|
} |
||||
|
|
||||
|
// GetQuestions 获取题目列表
|
||||
|
func (c *CKnowledgeTest) GetQuestions(r *ghttp.Request) { |
||||
|
ctx := r.GetCtx() |
||||
|
var req *v1.GetQuestionsReq |
||||
|
if err := r.Parse(&req); err != nil { |
||||
|
response.JsonExit(r, 400, err.Error()) |
||||
|
} |
||||
|
res, total, err := service.KnowledgeTest().GetQuestions(ctx, req) |
||||
|
if err != nil { |
||||
|
response.JsonExit(r, 400, err.Error()) |
||||
|
} |
||||
|
response.JsonExit(r, 200, "success", g.Map{ |
||||
|
"list": res, |
||||
|
"total": total, |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
// GetUserScores 获取用户成绩
|
||||
|
func (c *CKnowledgeTest) GetUserScores(r *ghttp.Request) { |
||||
|
ctx := r.GetCtx() |
||||
|
var req *v1.GetUserScoresReq |
||||
|
if err := r.Parse(&req); err != nil { |
||||
|
response.JsonExit(r, 400, err.Error()) |
||||
|
} |
||||
|
res, err := service.KnowledgeTest().GetUserScores(ctx, req) |
||||
|
if err != nil { |
||||
|
response.JsonExit(r, 400, err.Error()) |
||||
|
} |
||||
|
response.JsonExit(r, 200, "success", res) |
||||
|
} |
||||
|
|
||||
|
// GetCourse 获取用户课程
|
||||
|
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() |
||||
|
var req v1.SubmitAnswersReq |
||||
|
if err := r.Parse(&req); err != nil { |
||||
|
response.JsonExit(r, 400, err.Error()) |
||||
|
} |
||||
|
res, err := service.KnowledgeTest().SubmitAnswers(ctx, &req) |
||||
|
if err != nil { |
||||
|
response.JsonExit(r, 400, err.Error()) |
||||
|
} |
||||
|
response.JsonExit(r, 200, "success", g.Map{ |
||||
|
"data": res, |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
// GetWrongQuestions 获取错题列表
|
||||
|
func (c *CKnowledgeTest) GetWrongQuestions(r *ghttp.Request) { |
||||
|
ctx := r.GetCtx() |
||||
|
var req *v1.GetWrongQuestionsReq |
||||
|
if err := r.Parse(&req); err != nil { |
||||
|
response.JsonExit(r, 400, err.Error()) |
||||
|
} |
||||
|
res, total, err := service.KnowledgeTest().GetWrongQuestions(ctx, req) |
||||
|
if err != nil { |
||||
|
response.JsonExit(r, 400, err.Error()) |
||||
|
} |
||||
|
response.JsonExit(r, 200, "success", g.Map{ |
||||
|
"list": res, |
||||
|
"total": total, |
||||
|
}) |
||||
|
} |
||||
@ -0,0 +1,122 @@ |
|||||
|
package controller |
||||
|
|
||||
|
import ( |
||||
|
"Knowledge_Test_Go/api/v1" |
||||
|
"Knowledge_Test_Go/internal/service" |
||||
|
"Knowledge_Test_Go/utility/response" |
||||
|
|
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
"github.com/gogf/gf/v2/net/ghttp" |
||||
|
) |
||||
|
|
||||
|
type CQuestionBank struct{} |
||||
|
|
||||
|
func NewQuestionBank() *CQuestionBank { |
||||
|
return &CQuestionBank{} |
||||
|
} |
||||
|
|
||||
|
// GetQuestions 获取题目列表
|
||||
|
func (c *CQuestionBank) GetQuestions(r *ghttp.Request) { |
||||
|
ctx := r.GetCtx() |
||||
|
var req *v1.QuestionOutputReq |
||||
|
if err := r.Parse(&req); err != nil { |
||||
|
response.JsonExit(r, 400, err.Error()) |
||||
|
} |
||||
|
res, total, err := service.QuestionBank().GetQuestions(ctx, req) |
||||
|
if err != nil { |
||||
|
response.JsonExit(r, 400, err.Error()) |
||||
|
} |
||||
|
response.JsonExit(r, 200, "success", g.Map{ |
||||
|
"list": res, |
||||
|
"total": total, |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
// QuestionUpdate 获取题目列表
|
||||
|
func (c *CQuestionBank) QuestionUpdate(r *ghttp.Request) { |
||||
|
ctx := r.GetCtx() |
||||
|
var req *v1.QuestionUpdateReq |
||||
|
if err := r.Parse(&req); err != nil { |
||||
|
response.JsonExit(r, 400, err.Error()) |
||||
|
} |
||||
|
res, err := service.QuestionBank().QuestionUpdate(ctx, req) |
||||
|
if err != nil { |
||||
|
response.JsonExit(r, 400, err.Error()) |
||||
|
} |
||||
|
response.JsonExit(r, 200, "success", g.Map{ |
||||
|
"list": res, |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
// QuestionDel 删除题目
|
||||
|
func (c *CQuestionBank) QuestionDel(r *ghttp.Request) { |
||||
|
ctx := r.GetCtx() |
||||
|
var req *v1.QuestionDelReq |
||||
|
if err := r.Parse(&req); err != nil { |
||||
|
response.JsonExit(r, 400, err.Error()) |
||||
|
} |
||||
|
res, err := service.QuestionBank().QuestionDel(ctx, req) |
||||
|
if err != nil { |
||||
|
response.JsonExit(r, 400, err.Error()) |
||||
|
} |
||||
|
response.JsonExit(r, 200, "success", g.Map{ |
||||
|
"list": res, |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
// UserScoreOutput 获取用户成绩列表
|
||||
|
func (c *CQuestionBank) UserScoreOutput(r *ghttp.Request) { |
||||
|
ctx := r.GetCtx() |
||||
|
var req *v1.UserScoreOutputReq |
||||
|
if err := r.Parse(&req); err != nil { |
||||
|
response.JsonExit(r, 400, err.Error()) |
||||
|
} |
||||
|
res, total, err := service.QuestionBank().UserScoreOutput(ctx, req) |
||||
|
if err != nil { |
||||
|
response.JsonExit(r, 400, err.Error()) |
||||
|
} |
||||
|
response.JsonExit(r, 200, "success", g.Map{ |
||||
|
"list": res, |
||||
|
"total": total, |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
// ErrorOutPutUser 错题统计出错用户
|
||||
|
func (c *CQuestionBank) ErrorOutPutUser(r *ghttp.Request) { |
||||
|
ctx := r.GetCtx() |
||||
|
var req *v1.ErrorOutPutUserReq |
||||
|
if err := r.Parse(&req); err != nil { |
||||
|
response.JsonExit(r, 400, err.Error()) |
||||
|
} |
||||
|
res, total, err := service.QuestionBank().ErrorOutPutUser(ctx, req) |
||||
|
if err != nil { |
||||
|
response.JsonExit(r, 400, err.Error()) |
||||
|
} |
||||
|
response.JsonExit(r, 200, "success", g.Map{ |
||||
|
"list": res, |
||||
|
"total": total, |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
// ExportQuestion 导出题目数据到 Excel
|
||||
|
func (c *CQuestionBank) ExportQuestion(r *ghttp.Request) { |
||||
|
ctx := r.GetCtx() |
||||
|
var req *v1.QuestionOutputReq |
||||
|
if err := r.Parse(&req); err != nil { |
||||
|
response.JsonExit(r, 400, err.Error()) |
||||
|
} |
||||
|
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) |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
// =================================================================================
|
||||
|
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package dao |
||||
|
|
||||
|
import ( |
||||
|
"Knowledge_Test_Go/internal/dao/internal" |
||||
|
) |
||||
|
|
||||
|
// internalCourseRecommendDao is internal type for wrapping internal DAO implements.
|
||||
|
type internalCourseRecommendDao = *internal.CourseRecommendDao |
||||
|
|
||||
|
// courseRecommendDao is the data access object for table course_recommend.
|
||||
|
// You can define custom methods on it to extend its functionality as you wish.
|
||||
|
type courseRecommendDao struct { |
||||
|
internalCourseRecommendDao |
||||
|
} |
||||
|
|
||||
|
var ( |
||||
|
// CourseRecommend is globally public accessible object for table course_recommend operations.
|
||||
|
CourseRecommend = courseRecommendDao{ |
||||
|
internal.NewCourseRecommendDao(), |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
// Fill with you ideas below.
|
||||
@ -0,0 +1,75 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
package internal |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"github.com/gogf/gf/v2/database/gdb" |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
) |
||||
|
|
||||
|
// CourseRecommendDao is the data access object for table course_recommend.
|
||||
|
type CourseRecommendDao struct { |
||||
|
table string // table is the underlying table name of the DAO.
|
||||
|
group string // group is the database configuration group name of current DAO.
|
||||
|
columns CourseRecommendColumns // columns contains all the column names of Table for convenient usage.
|
||||
|
} |
||||
|
|
||||
|
// CourseRecommendColumns defines and stores column names for table course_recommend.
|
||||
|
type CourseRecommendColumns struct { |
||||
|
Id string // 课程推荐主键
|
||||
|
CrName string // 课程推荐名称
|
||||
|
} |
||||
|
|
||||
|
// courseRecommendColumns holds the columns for table course_recommend.
|
||||
|
var courseRecommendColumns = CourseRecommendColumns{ |
||||
|
Id: "id", |
||||
|
CrName: "cr_name", |
||||
|
} |
||||
|
|
||||
|
// NewCourseRecommendDao creates and returns a new DAO object for table data access.
|
||||
|
func NewCourseRecommendDao() *CourseRecommendDao { |
||||
|
return &CourseRecommendDao{ |
||||
|
group: "default", |
||||
|
table: "course_recommend", |
||||
|
columns: courseRecommendColumns, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// DB retrieves and returns the underlying raw database management object of current DAO.
|
||||
|
func (dao *CourseRecommendDao) DB() gdb.DB { |
||||
|
return g.DB(dao.group) |
||||
|
} |
||||
|
|
||||
|
// Table returns the table name of current dao.
|
||||
|
func (dao *CourseRecommendDao) Table() string { |
||||
|
return dao.table |
||||
|
} |
||||
|
|
||||
|
// Columns returns all column names of current dao.
|
||||
|
func (dao *CourseRecommendDao) Columns() CourseRecommendColumns { |
||||
|
return dao.columns |
||||
|
} |
||||
|
|
||||
|
// Group returns the configuration group name of database of current dao.
|
||||
|
func (dao *CourseRecommendDao) Group() string { |
||||
|
return dao.group |
||||
|
} |
||||
|
|
||||
|
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
|
||||
|
func (dao *CourseRecommendDao) Ctx(ctx context.Context) *gdb.Model { |
||||
|
return dao.DB().Model(dao.table).Safe().Ctx(ctx) |
||||
|
} |
||||
|
|
||||
|
// Transaction wraps the transaction logic using function f.
|
||||
|
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
|
||||
|
// It commits the transaction and returns nil if function f returns nil.
|
||||
|
//
|
||||
|
// Note that, you should not Commit or Rollback the transaction in function f
|
||||
|
// as it is automatically handled by this function.
|
||||
|
func (dao *CourseRecommendDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { |
||||
|
return dao.Ctx(ctx).Transaction(ctx, f) |
||||
|
} |
||||
@ -0,0 +1,99 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
package internal |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"github.com/gogf/gf/v2/database/gdb" |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
) |
||||
|
|
||||
|
// QuestionBankDao is the data access object for table question_bank.
|
||||
|
type QuestionBankDao struct { |
||||
|
table string // table is the underlying table name of the DAO.
|
||||
|
group string // group is the database configuration group name of current DAO.
|
||||
|
columns QuestionBankColumns // columns contains all the column names of Table for convenient usage.
|
||||
|
} |
||||
|
|
||||
|
// QuestionBankColumns defines and stores column names for table question_bank.
|
||||
|
type QuestionBankColumns struct { |
||||
|
Id string // 题库主键
|
||||
|
Stem string // 题干
|
||||
|
A string // A选项
|
||||
|
B string // B选项
|
||||
|
C string // C选项
|
||||
|
D string // D选项
|
||||
|
CorrectAnswer string // 正确答案
|
||||
|
QuestionTypeId string // 题目类型
|
||||
|
CourseRecommendationId string // 课程推荐
|
||||
|
CitationCount string // 引用次数
|
||||
|
ErrorCount string // 错误次数
|
||||
|
CreatedAt string // 创建时间
|
||||
|
UpdatedAt string // 修改时间
|
||||
|
Isdel string // 逻辑删(1为删除)
|
||||
|
} |
||||
|
|
||||
|
// questionBankColumns holds the columns for table question_bank.
|
||||
|
var questionBankColumns = QuestionBankColumns{ |
||||
|
Id: "id", |
||||
|
Stem: "stem", |
||||
|
A: "A", |
||||
|
B: "B", |
||||
|
C: "C", |
||||
|
D: "D", |
||||
|
CorrectAnswer: "correct_answer", |
||||
|
QuestionTypeId: "question_type_id", |
||||
|
CourseRecommendationId: "course_recommendation_id", |
||||
|
CitationCount: "citation_count", |
||||
|
ErrorCount: "error_count", |
||||
|
CreatedAt: "created_at", |
||||
|
UpdatedAt: "updated_at", |
||||
|
Isdel: "isdel", |
||||
|
} |
||||
|
|
||||
|
// NewQuestionBankDao creates and returns a new DAO object for table data access.
|
||||
|
func NewQuestionBankDao() *QuestionBankDao { |
||||
|
return &QuestionBankDao{ |
||||
|
group: "default", |
||||
|
table: "question_bank", |
||||
|
columns: questionBankColumns, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// DB retrieves and returns the underlying raw database management object of current DAO.
|
||||
|
func (dao *QuestionBankDao) DB() gdb.DB { |
||||
|
return g.DB(dao.group) |
||||
|
} |
||||
|
|
||||
|
// Table returns the table name of current dao.
|
||||
|
func (dao *QuestionBankDao) Table() string { |
||||
|
return dao.table |
||||
|
} |
||||
|
|
||||
|
// Columns returns all column names of current dao.
|
||||
|
func (dao *QuestionBankDao) Columns() QuestionBankColumns { |
||||
|
return dao.columns |
||||
|
} |
||||
|
|
||||
|
// Group returns the configuration group name of database of current dao.
|
||||
|
func (dao *QuestionBankDao) Group() string { |
||||
|
return dao.group |
||||
|
} |
||||
|
|
||||
|
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
|
||||
|
func (dao *QuestionBankDao) Ctx(ctx context.Context) *gdb.Model { |
||||
|
return dao.DB().Model(dao.table).Safe().Ctx(ctx) |
||||
|
} |
||||
|
|
||||
|
// Transaction wraps the transaction logic using function f.
|
||||
|
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
|
||||
|
// It commits the transaction and returns nil if function f returns nil.
|
||||
|
//
|
||||
|
// Note that, you should not Commit or Rollback the transaction in function f
|
||||
|
// as it is automatically handled by this function.
|
||||
|
func (dao *QuestionBankDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { |
||||
|
return dao.Ctx(ctx).Transaction(ctx, f) |
||||
|
} |
||||
@ -0,0 +1,83 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
package internal |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"github.com/gogf/gf/v2/database/gdb" |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
) |
||||
|
|
||||
|
// QuestionRecordDao is the data access object for table question_record.
|
||||
|
type QuestionRecordDao struct { |
||||
|
table string // table is the underlying table name of the DAO.
|
||||
|
group string // group is the database configuration group name of current DAO.
|
||||
|
columns QuestionRecordColumns // columns contains all the column names of Table for convenient usage.
|
||||
|
} |
||||
|
|
||||
|
// QuestionRecordColumns defines and stores column names for table question_record.
|
||||
|
type QuestionRecordColumns struct { |
||||
|
Id string // 题目记录主键
|
||||
|
Jwcode string // 精网号
|
||||
|
QuestionBankId string // 题目id
|
||||
|
UserAnswer string // 用户答案
|
||||
|
IsCorrect string // 是否正确(0为正确)
|
||||
|
CreatedAt string // 提交时间
|
||||
|
} |
||||
|
|
||||
|
// questionRecordColumns holds the columns for table question_record.
|
||||
|
var questionRecordColumns = QuestionRecordColumns{ |
||||
|
Id: "id", |
||||
|
Jwcode: "jwcode", |
||||
|
QuestionBankId: "question_bank_id", |
||||
|
UserAnswer: "user_answer", |
||||
|
IsCorrect: "is_correct", |
||||
|
CreatedAt: "created_at", |
||||
|
} |
||||
|
|
||||
|
// NewQuestionRecordDao creates and returns a new DAO object for table data access.
|
||||
|
func NewQuestionRecordDao() *QuestionRecordDao { |
||||
|
return &QuestionRecordDao{ |
||||
|
group: "default", |
||||
|
table: "question_record", |
||||
|
columns: questionRecordColumns, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// DB retrieves and returns the underlying raw database management object of current DAO.
|
||||
|
func (dao *QuestionRecordDao) DB() gdb.DB { |
||||
|
return g.DB(dao.group) |
||||
|
} |
||||
|
|
||||
|
// Table returns the table name of current dao.
|
||||
|
func (dao *QuestionRecordDao) Table() string { |
||||
|
return dao.table |
||||
|
} |
||||
|
|
||||
|
// Columns returns all column names of current dao.
|
||||
|
func (dao *QuestionRecordDao) Columns() QuestionRecordColumns { |
||||
|
return dao.columns |
||||
|
} |
||||
|
|
||||
|
// Group returns the configuration group name of database of current dao.
|
||||
|
func (dao *QuestionRecordDao) Group() string { |
||||
|
return dao.group |
||||
|
} |
||||
|
|
||||
|
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
|
||||
|
func (dao *QuestionRecordDao) Ctx(ctx context.Context) *gdb.Model { |
||||
|
return dao.DB().Model(dao.table).Safe().Ctx(ctx) |
||||
|
} |
||||
|
|
||||
|
// Transaction wraps the transaction logic using function f.
|
||||
|
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
|
||||
|
// It commits the transaction and returns nil if function f returns nil.
|
||||
|
//
|
||||
|
// Note that, you should not Commit or Rollback the transaction in function f
|
||||
|
// as it is automatically handled by this function.
|
||||
|
func (dao *QuestionRecordDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { |
||||
|
return dao.Ctx(ctx).Transaction(ctx, f) |
||||
|
} |
||||
@ -0,0 +1,75 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
package internal |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"github.com/gogf/gf/v2/database/gdb" |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
) |
||||
|
|
||||
|
// QuestionTypeDao is the data access object for table question_type.
|
||||
|
type QuestionTypeDao struct { |
||||
|
table string // table is the underlying table name of the DAO.
|
||||
|
group string // group is the database configuration group name of current DAO.
|
||||
|
columns QuestionTypeColumns // columns contains all the column names of Table for convenient usage.
|
||||
|
} |
||||
|
|
||||
|
// QuestionTypeColumns defines and stores column names for table question_type.
|
||||
|
type QuestionTypeColumns struct { |
||||
|
Id string // 题库类型主键
|
||||
|
QuestionTypeName string // 题目类型名称
|
||||
|
} |
||||
|
|
||||
|
// questionTypeColumns holds the columns for table question_type.
|
||||
|
var questionTypeColumns = QuestionTypeColumns{ |
||||
|
Id: "id", |
||||
|
QuestionTypeName: "question_type_name", |
||||
|
} |
||||
|
|
||||
|
// NewQuestionTypeDao creates and returns a new DAO object for table data access.
|
||||
|
func NewQuestionTypeDao() *QuestionTypeDao { |
||||
|
return &QuestionTypeDao{ |
||||
|
group: "default", |
||||
|
table: "question_type", |
||||
|
columns: questionTypeColumns, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// DB retrieves and returns the underlying raw database management object of current DAO.
|
||||
|
func (dao *QuestionTypeDao) DB() gdb.DB { |
||||
|
return g.DB(dao.group) |
||||
|
} |
||||
|
|
||||
|
// Table returns the table name of current dao.
|
||||
|
func (dao *QuestionTypeDao) Table() string { |
||||
|
return dao.table |
||||
|
} |
||||
|
|
||||
|
// Columns returns all column names of current dao.
|
||||
|
func (dao *QuestionTypeDao) Columns() QuestionTypeColumns { |
||||
|
return dao.columns |
||||
|
} |
||||
|
|
||||
|
// Group returns the configuration group name of database of current dao.
|
||||
|
func (dao *QuestionTypeDao) Group() string { |
||||
|
return dao.group |
||||
|
} |
||||
|
|
||||
|
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
|
||||
|
func (dao *QuestionTypeDao) Ctx(ctx context.Context) *gdb.Model { |
||||
|
return dao.DB().Model(dao.table).Safe().Ctx(ctx) |
||||
|
} |
||||
|
|
||||
|
// Transaction wraps the transaction logic using function f.
|
||||
|
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
|
||||
|
// It commits the transaction and returns nil if function f returns nil.
|
||||
|
//
|
||||
|
// Note that, you should not Commit or Rollback the transaction in function f
|
||||
|
// as it is automatically handled by this function.
|
||||
|
func (dao *QuestionTypeDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { |
||||
|
return dao.Ctx(ctx).Transaction(ctx, f) |
||||
|
} |
||||
@ -0,0 +1,79 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
package internal |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"github.com/gogf/gf/v2/database/gdb" |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
) |
||||
|
|
||||
|
// TotalScoreDao is the data access object for table total_score.
|
||||
|
type TotalScoreDao struct { |
||||
|
table string // table is the underlying table name of the DAO.
|
||||
|
group string // group is the database configuration group name of current DAO.
|
||||
|
columns TotalScoreColumns // columns contains all the column names of Table for convenient usage.
|
||||
|
} |
||||
|
|
||||
|
// TotalScoreColumns defines and stores column names for table total_score.
|
||||
|
type TotalScoreColumns struct { |
||||
|
Id string // 总成绩主键
|
||||
|
Jwcode string // 精网号
|
||||
|
Score string // 成绩
|
||||
|
CreatedAt string // 提交时间
|
||||
|
} |
||||
|
|
||||
|
// totalScoreColumns holds the columns for table total_score.
|
||||
|
var totalScoreColumns = TotalScoreColumns{ |
||||
|
Id: "id", |
||||
|
Jwcode: "jwcode", |
||||
|
Score: "score", |
||||
|
CreatedAt: "created_at", |
||||
|
} |
||||
|
|
||||
|
// NewTotalScoreDao creates and returns a new DAO object for table data access.
|
||||
|
func NewTotalScoreDao() *TotalScoreDao { |
||||
|
return &TotalScoreDao{ |
||||
|
group: "default", |
||||
|
table: "total_score", |
||||
|
columns: totalScoreColumns, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// DB retrieves and returns the underlying raw database management object of current DAO.
|
||||
|
func (dao *TotalScoreDao) DB() gdb.DB { |
||||
|
return g.DB(dao.group) |
||||
|
} |
||||
|
|
||||
|
// Table returns the table name of current dao.
|
||||
|
func (dao *TotalScoreDao) Table() string { |
||||
|
return dao.table |
||||
|
} |
||||
|
|
||||
|
// Columns returns all column names of current dao.
|
||||
|
func (dao *TotalScoreDao) Columns() TotalScoreColumns { |
||||
|
return dao.columns |
||||
|
} |
||||
|
|
||||
|
// Group returns the configuration group name of database of current dao.
|
||||
|
func (dao *TotalScoreDao) Group() string { |
||||
|
return dao.group |
||||
|
} |
||||
|
|
||||
|
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
|
||||
|
func (dao *TotalScoreDao) Ctx(ctx context.Context) *gdb.Model { |
||||
|
return dao.DB().Model(dao.table).Safe().Ctx(ctx) |
||||
|
} |
||||
|
|
||||
|
// Transaction wraps the transaction logic using function f.
|
||||
|
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
|
||||
|
// It commits the transaction and returns nil if function f returns nil.
|
||||
|
//
|
||||
|
// Note that, you should not Commit or Rollback the transaction in function f
|
||||
|
// as it is automatically handled by this function.
|
||||
|
func (dao *TotalScoreDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { |
||||
|
return dao.Ctx(ctx).Transaction(ctx, f) |
||||
|
} |
||||
@ -0,0 +1,81 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
package internal |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"github.com/gogf/gf/v2/database/gdb" |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
) |
||||
|
|
||||
|
// UserDao is the data access object for table user.
|
||||
|
type UserDao struct { |
||||
|
table string // table is the underlying table name of the DAO.
|
||||
|
group string // group is the database configuration group name of current DAO.
|
||||
|
columns UserColumns // columns contains all the column names of Table for convenient usage.
|
||||
|
} |
||||
|
|
||||
|
// UserColumns defines and stores column names for table user.
|
||||
|
type UserColumns struct { |
||||
|
Id string // 用户主键
|
||||
|
UserName string // 用户名称
|
||||
|
Jwcode string // 精网号
|
||||
|
UserIdentity string // 用户身份
|
||||
|
CreatedAt string // 创建时间
|
||||
|
} |
||||
|
|
||||
|
// userColumns holds the columns for table user.
|
||||
|
var userColumns = UserColumns{ |
||||
|
Id: "id", |
||||
|
UserName: "user_name", |
||||
|
Jwcode: "jwcode", |
||||
|
UserIdentity: "user_identity", |
||||
|
CreatedAt: "created_at", |
||||
|
} |
||||
|
|
||||
|
// NewUserDao creates and returns a new DAO object for table data access.
|
||||
|
func NewUserDao() *UserDao { |
||||
|
return &UserDao{ |
||||
|
group: "default", |
||||
|
table: "user", |
||||
|
columns: userColumns, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// DB retrieves and returns the underlying raw database management object of current DAO.
|
||||
|
func (dao *UserDao) DB() gdb.DB { |
||||
|
return g.DB(dao.group) |
||||
|
} |
||||
|
|
||||
|
// Table returns the table name of current dao.
|
||||
|
func (dao *UserDao) Table() string { |
||||
|
return dao.table |
||||
|
} |
||||
|
|
||||
|
// Columns returns all column names of current dao.
|
||||
|
func (dao *UserDao) Columns() UserColumns { |
||||
|
return dao.columns |
||||
|
} |
||||
|
|
||||
|
// Group returns the configuration group name of database of current dao.
|
||||
|
func (dao *UserDao) Group() string { |
||||
|
return dao.group |
||||
|
} |
||||
|
|
||||
|
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
|
||||
|
func (dao *UserDao) Ctx(ctx context.Context) *gdb.Model { |
||||
|
return dao.DB().Model(dao.table).Safe().Ctx(ctx) |
||||
|
} |
||||
|
|
||||
|
// Transaction wraps the transaction logic using function f.
|
||||
|
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
|
||||
|
// It commits the transaction and returns nil if function f returns nil.
|
||||
|
//
|
||||
|
// Note that, you should not Commit or Rollback the transaction in function f
|
||||
|
// as it is automatically handled by this function.
|
||||
|
func (dao *UserDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { |
||||
|
return dao.Ctx(ctx).Transaction(ctx, f) |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
// =================================================================================
|
||||
|
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package dao |
||||
|
|
||||
|
import ( |
||||
|
"Knowledge_Test_Go/internal/dao/internal" |
||||
|
) |
||||
|
|
||||
|
// internalQuestionBankDao is internal type for wrapping internal DAO implements.
|
||||
|
type internalQuestionBankDao = *internal.QuestionBankDao |
||||
|
|
||||
|
// questionBankDao is the data access object for table question_bank.
|
||||
|
// You can define custom methods on it to extend its functionality as you wish.
|
||||
|
type questionBankDao struct { |
||||
|
internalQuestionBankDao |
||||
|
} |
||||
|
|
||||
|
var ( |
||||
|
// QuestionBank is globally public accessible object for table question_bank operations.
|
||||
|
QuestionBank = questionBankDao{ |
||||
|
internal.NewQuestionBankDao(), |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
// Fill with you ideas below.
|
||||
@ -0,0 +1,27 @@ |
|||||
|
// =================================================================================
|
||||
|
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package dao |
||||
|
|
||||
|
import ( |
||||
|
"Knowledge_Test_Go/internal/dao/internal" |
||||
|
) |
||||
|
|
||||
|
// internalQuestionRecordDao is internal type for wrapping internal DAO implements.
|
||||
|
type internalQuestionRecordDao = *internal.QuestionRecordDao |
||||
|
|
||||
|
// questionRecordDao is the data access object for table question_record.
|
||||
|
// You can define custom methods on it to extend its functionality as you wish.
|
||||
|
type questionRecordDao struct { |
||||
|
internalQuestionRecordDao |
||||
|
} |
||||
|
|
||||
|
var ( |
||||
|
// QuestionRecord is globally public accessible object for table question_record operations.
|
||||
|
QuestionRecord = questionRecordDao{ |
||||
|
internal.NewQuestionRecordDao(), |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
// Fill with you ideas below.
|
||||
@ -0,0 +1,27 @@ |
|||||
|
// =================================================================================
|
||||
|
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package dao |
||||
|
|
||||
|
import ( |
||||
|
"Knowledge_Test_Go/internal/dao/internal" |
||||
|
) |
||||
|
|
||||
|
// internalQuestionTypeDao is internal type for wrapping internal DAO implements.
|
||||
|
type internalQuestionTypeDao = *internal.QuestionTypeDao |
||||
|
|
||||
|
// questionTypeDao is the data access object for table question_type.
|
||||
|
// You can define custom methods on it to extend its functionality as you wish.
|
||||
|
type questionTypeDao struct { |
||||
|
internalQuestionTypeDao |
||||
|
} |
||||
|
|
||||
|
var ( |
||||
|
// QuestionType is globally public accessible object for table question_type operations.
|
||||
|
QuestionType = questionTypeDao{ |
||||
|
internal.NewQuestionTypeDao(), |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
// Fill with you ideas below.
|
||||
@ -0,0 +1,27 @@ |
|||||
|
// =================================================================================
|
||||
|
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package dao |
||||
|
|
||||
|
import ( |
||||
|
"Knowledge_Test_Go/internal/dao/internal" |
||||
|
) |
||||
|
|
||||
|
// internalTotalScoreDao is internal type for wrapping internal DAO implements.
|
||||
|
type internalTotalScoreDao = *internal.TotalScoreDao |
||||
|
|
||||
|
// totalScoreDao is the data access object for table total_score.
|
||||
|
// You can define custom methods on it to extend its functionality as you wish.
|
||||
|
type totalScoreDao struct { |
||||
|
internalTotalScoreDao |
||||
|
} |
||||
|
|
||||
|
var ( |
||||
|
// TotalScore is globally public accessible object for table total_score operations.
|
||||
|
TotalScore = totalScoreDao{ |
||||
|
internal.NewTotalScoreDao(), |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
// Fill with you ideas below.
|
||||
@ -0,0 +1,27 @@ |
|||||
|
// =================================================================================
|
||||
|
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package dao |
||||
|
|
||||
|
import ( |
||||
|
"Knowledge_Test_Go/internal/dao/internal" |
||||
|
) |
||||
|
|
||||
|
// internalUserDao is internal type for wrapping internal DAO implements.
|
||||
|
type internalUserDao = *internal.UserDao |
||||
|
|
||||
|
// userDao is the data access object for table user.
|
||||
|
// You can define custom methods on it to extend its functionality as you wish.
|
||||
|
type userDao struct { |
||||
|
internalUserDao |
||||
|
} |
||||
|
|
||||
|
var ( |
||||
|
// User is globally public accessible object for table user operations.
|
||||
|
User = userDao{ |
||||
|
internal.NewUserDao(), |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
// Fill with you ideas below.
|
||||
@ -0,0 +1,233 @@ |
|||||
|
package knowledge |
||||
|
|
||||
|
import ( |
||||
|
v1 "Knowledge_Test_Go/api/v1" |
||||
|
"Knowledge_Test_Go/internal/dao" |
||||
|
"Knowledge_Test_Go/internal/model/do" |
||||
|
"Knowledge_Test_Go/internal/service" |
||||
|
"context" |
||||
|
"fmt" |
||||
|
|
||||
|
"github.com/gogf/gf/v2/database/gdb" |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
"github.com/gogf/gf/v2/util/gconv" |
||||
|
) |
||||
|
|
||||
|
type sKnowledgeTest struct{} |
||||
|
|
||||
|
func init() { |
||||
|
service.RegisterKnowledgeTest(&sKnowledgeTest{}) |
||||
|
} |
||||
|
|
||||
|
// GetQuestions 获取题目列表
|
||||
|
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") |
||||
|
err = db.Page(req.Page, req.PageSize).ScanAndCount(&res, &total, false) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
// -----------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
||||
|
// GetUserScores 获取用户成绩
|
||||
|
func (s *sKnowledgeTest) GetUserScores(ctx context.Context, req *v1.GetUserScoresReq) (res []*v1.GetUserScoresRes, err error) { |
||||
|
err = g.Model("total_score").Fields("score").Where("jwcode=?", req.Jwcode).Ctx(ctx).Scan(&res) |
||||
|
if err != nil { |
||||
|
return nil, fmt.Errorf("获取用户成绩失败: %w", err) |
||||
|
} |
||||
|
return res, nil |
||||
|
} |
||||
|
|
||||
|
// -----------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
||||
|
// 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"). // DISTINCT去重
|
||||
|
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 { |
||||
|
return nil, fmt.Errorf("答案列表不能为空") |
||||
|
} |
||||
|
|
||||
|
// 获取所有题目ID
|
||||
|
questionIds := make([]interface{}, len(req.Answers)) |
||||
|
for i, answer := range req.Answers { |
||||
|
questionIds[i] = answer.QuestionId |
||||
|
} |
||||
|
|
||||
|
// 批量查询题目
|
||||
|
var questions []*do.QuestionBank |
||||
|
err := dao.QuestionBank.Ctx(ctx). |
||||
|
Where(dao.QuestionBank.Columns().Id, questionIds). |
||||
|
Where(dao.QuestionBank.Columns().Isdel, 0). |
||||
|
Scan(&questions) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
// 构建题目ID到正确答案的映射
|
||||
|
questionMap := make(map[int]string) |
||||
|
for _, q := range questions { |
||||
|
questionMap[gconv.Int(q.Id)] = gconv.String(q.CorrectAnswer) |
||||
|
} |
||||
|
|
||||
|
// 计算分数并准备记录数据
|
||||
|
score := 0 |
||||
|
total := len(req.Answers) * 2 // 每题2分
|
||||
|
records := make([]*do.QuestionRecord, 0, len(req.Answers)) |
||||
|
|
||||
|
// 收集所有被回答的题目ID(用于更新引用次数)
|
||||
|
allAnsweredQuestionIds := make([]int, 0, len(req.Answers)) |
||||
|
// 收集错误题目的ID(用于更新错误次数)
|
||||
|
errorQuestionIds := make([]int, 0) |
||||
|
|
||||
|
for _, answer := range req.Answers { |
||||
|
correctAnswer, exists := questionMap[answer.QuestionId] |
||||
|
if !exists { |
||||
|
continue |
||||
|
} |
||||
|
|
||||
|
// 记录所有被回答的题目
|
||||
|
allAnsweredQuestionIds = append(allAnsweredQuestionIds, answer.QuestionId) |
||||
|
|
||||
|
isCorrect := 0 // 0为正确
|
||||
|
if answer.UserAnswer == correctAnswer { |
||||
|
score += 2 |
||||
|
} else { |
||||
|
isCorrect = 1 // 1为错误
|
||||
|
errorQuestionIds = append(errorQuestionIds, answer.QuestionId) |
||||
|
} |
||||
|
|
||||
|
records = append(records, &do.QuestionRecord{ |
||||
|
Jwcode: req.Jwcode, |
||||
|
QuestionBankId: answer.QuestionId, |
||||
|
UserAnswer: answer.UserAnswer, |
||||
|
IsCorrect: isCorrect, |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
// 批量保存记录(使用事务确保原子性)
|
||||
|
err = dao.QuestionRecord.Ctx(ctx).Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { |
||||
|
// 批量插入答题记录
|
||||
|
if len(records) > 0 { |
||||
|
_, err := tx.Model(dao.QuestionRecord.Table()).Data(records).Insert() |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 更新所有被回答题目的引用次数
|
||||
|
if len(allAnsweredQuestionIds) > 0 { |
||||
|
_, err := tx.Model(dao.QuestionBank.Table()). |
||||
|
Where(dao.QuestionBank.Columns().Id, allAnsweredQuestionIds). |
||||
|
Increment(dao.QuestionBank.Columns().CitationCount, 1) |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 更新错误题目的错误次数
|
||||
|
if len(errorQuestionIds) > 0 { |
||||
|
_, err := tx.Model(dao.QuestionBank.Table()). |
||||
|
Where(dao.QuestionBank.Columns().Id, errorQuestionIds). |
||||
|
Increment(dao.QuestionBank.Columns().ErrorCount, 1) |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 计算并更新所有被回答题目的错误率
|
||||
|
if len(allAnsweredQuestionIds) > 0 { |
||||
|
err := s.updateErrorRatesInTransaction(ctx, tx, allAnsweredQuestionIds) |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 插入总成绩记录
|
||||
|
_, err = tx.Model(dao.TotalScore.Table()).Data(&do.TotalScore{ |
||||
|
Jwcode: req.Jwcode, |
||||
|
Score: score, |
||||
|
}).Insert() |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
|
||||
|
return nil |
||||
|
}) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
return &v1.SubmitAnswersRes{ |
||||
|
Score: score, |
||||
|
Total: total, |
||||
|
}, nil |
||||
|
} |
||||
|
|
||||
|
// updateErrorRatesInTransaction 在事务中更新错误率(简化版)
|
||||
|
func (s *sKnowledgeTest) updateErrorRatesInTransaction(ctx context.Context, tx gdb.TX, questionIds []int) error { |
||||
|
if len(questionIds) == 0 { |
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
// 使用GF的Raw方法
|
||||
|
_, err := tx.Model(dao.QuestionBank.Table()). |
||||
|
Where(dao.QuestionBank.Columns().Id, questionIds). |
||||
|
Data(g.Map{ |
||||
|
"error_rate": gdb.Raw("CASE WHEN citation_count = 0 THEN 0 ELSE ROUND((error_count * 100.0) / citation_count) END"), |
||||
|
}). |
||||
|
Update() |
||||
|
|
||||
|
if err != nil { |
||||
|
return fmt.Errorf("更新错误率失败: %w", err) |
||||
|
} |
||||
|
|
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
// -----------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
||||
|
// GetWrongQuestions 获取错题列表
|
||||
|
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) |
||||
|
return |
||||
|
} |
||||
@ -1,15 +1,10 @@ |
|||||
// =================================================================================
|
|
||||
|
// ==========================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
|
||||
|
// ==========================================================================
|
||||
|
|
||||
package hello |
|
||||
|
package logic |
||||
|
|
||||
import ( |
import ( |
||||
"Knowledge_Test_Go/api/hello" |
|
||||
|
_ "Knowledge_Test_Go/internal/logic/knowledge" |
||||
|
_ "Knowledge_Test_Go/internal/logic/questionBank" |
||||
) |
) |
||||
|
|
||||
type ControllerV1 struct{} |
|
||||
|
|
||||
func NewV1() hello.IHelloV1 { |
|
||||
return &ControllerV1{} |
|
||||
} |
|
||||
@ -0,0 +1,471 @@ |
|||||
|
package questionBank |
||||
|
|
||||
|
import ( |
||||
|
v1 "Knowledge_Test_Go/api/v1" |
||||
|
"Knowledge_Test_Go/internal/service" |
||||
|
"Knowledge_Test_Go/utility/response" |
||||
|
"context" |
||||
|
"fmt" |
||||
|
"regexp" |
||||
|
"strconv" |
||||
|
|
||||
|
"github.com/gogf/gf/v2/database/gdb" |
||||
|
"github.com/gogf/gf/v2/errors/gerror" |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
"github.com/gogf/gf/v2/net/ghttp" |
||||
|
|
||||
|
"github.com/xuri/excelize/v2" |
||||
|
) |
||||
|
|
||||
|
type sQuestionBank struct{} |
||||
|
|
||||
|
func init() { |
||||
|
service.RegisterQuestionBank(&sQuestionBank{}) |
||||
|
} |
||||
|
|
||||
|
// GetQuestions 获取题目列表
|
||||
|
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 字段
|
||||
|
|
||||
|
// 添加查询条件
|
||||
|
if req.Stem != "" { |
||||
|
// 对题干进行模糊查询
|
||||
|
db = db.Where("a.stem LIKE ?", "%"+req.Stem+"%") |
||||
|
} |
||||
|
|
||||
|
if req.QuestionTypeId != "" { |
||||
|
// 对题目类型ID进行精准查询
|
||||
|
db = db.Where("a.question_type_id = ?", req.QuestionTypeId) |
||||
|
} |
||||
|
|
||||
|
if req.CourseRecommendationId != "" { |
||||
|
// 对课程推荐ID进行精准查询
|
||||
|
db = db.Where("a.course_recommendation_id = ?", req.CourseRecommendationId) |
||||
|
} |
||||
|
|
||||
|
// 添加排序逻辑
|
||||
|
db = s.buildSortCondition(db, req) |
||||
|
|
||||
|
err = db.Page(req.Page, req.PageSize).ScanAndCount(&res, &total, false) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
// buildSortCondition 构建排序条件
|
||||
|
func (s *sQuestionBank) buildSortCondition(db *gdb.Model, req *v1.QuestionOutputReq) *gdb.Model { |
||||
|
// 默认排序(按ID倒序)
|
||||
|
if req.SortField == "" { |
||||
|
return db.OrderDesc("a.id") |
||||
|
} |
||||
|
|
||||
|
// 确定排序方向
|
||||
|
order := "DESC" |
||||
|
if req.SortOrder == "asc" { |
||||
|
order = "ASC" |
||||
|
} |
||||
|
|
||||
|
// 根据排序字段构建排序条件
|
||||
|
switch req.SortField { |
||||
|
case "error_count": |
||||
|
return db.Order("a.error_count " + order) |
||||
|
case "error_rate": |
||||
|
return db.Order("a.error_rate " + order) |
||||
|
case "id": |
||||
|
return db.Order("a.id " + order) |
||||
|
default: |
||||
|
// 默认按ID倒序
|
||||
|
return db.OrderDesc("a.id") |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
||||
|
// QuestionUpdate 修改题目
|
||||
|
func (s *sQuestionBank) QuestionUpdate(ctx context.Context, req *v1.QuestionUpdateReq) (res string, err error) { |
||||
|
// 准备数据
|
||||
|
data := g.Map{ |
||||
|
"stem": req.Stem, |
||||
|
"a": req.A, |
||||
|
"b": req.B, |
||||
|
"c": req.C, |
||||
|
"d": req.D, |
||||
|
"correct_answer": req.CorrectAnswer, |
||||
|
"question_type_id": req.QuestionTypeId, |
||||
|
"course_recommendation_id": req.CourseRecommendationId, |
||||
|
} |
||||
|
|
||||
|
if req.Id == 0 { |
||||
|
// 新增记录
|
||||
|
result, err := g.Model("question_bank").Data(data).Insert() |
||||
|
if err != nil { |
||||
|
return "新增失败", err |
||||
|
} |
||||
|
|
||||
|
// 获取新增的ID
|
||||
|
id, _ := result.LastInsertId() |
||||
|
return fmt.Sprintf("新增成功,ID: %d", id), nil |
||||
|
} else { |
||||
|
// 更新记录
|
||||
|
_, err := g.Model("question_bank").Where("id = ?", req.Id).Data(data).Update() |
||||
|
if err != nil { |
||||
|
return "更新失败", err |
||||
|
} |
||||
|
|
||||
|
// 检查是否真的更新了记录
|
||||
|
count, _ := g.Model("question_bank").Where("id = ?", req.Id).Count() |
||||
|
if count == 0 { |
||||
|
return "更新失败,记录不存在", nil |
||||
|
} |
||||
|
|
||||
|
return fmt.Sprintf("更新成功,ID: %d", req.Id), nil |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
||||
|
// QuestionDel 删除题目
|
||||
|
func (s *sQuestionBank) QuestionDel(ctx context.Context, req *v1.QuestionDelReq) (res string, err error) { |
||||
|
_, err = g.Model("question_bank").Where("id = ?", req.Id).Data("isdel", 1).Update() |
||||
|
if err != nil { |
||||
|
return "删除失败", err |
||||
|
} |
||||
|
return "删除成功", err |
||||
|
} |
||||
|
|
||||
|
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
||||
|
// UserScoreOutput 获取用户成绩列表
|
||||
|
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 LIKE ?", "%"+req.UserName+"%") |
||||
|
} |
||||
|
|
||||
|
if req.UserIdentity != "" { |
||||
|
db = db.Where("a.user_identity = ?", req.UserIdentity) |
||||
|
} |
||||
|
|
||||
|
// 预编译正则:匹配8位数字(^表示开头,$表示结尾,\d{8}表示8位数字)
|
||||
|
var jwcodeRegex = regexp.MustCompile(`^\d{8}$`) |
||||
|
|
||||
|
if req.Jwcode != "" { // 假设字符串类型的默认值是空串
|
||||
|
// 校验:长度8位且全为数字
|
||||
|
if !jwcodeRegex.MatchString(req.Jwcode) { |
||||
|
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("结束时间不能早于开始时间")
|
||||
|
// }
|
||||
|
//}
|
||||
|
if req.StartTime != "" && req.EndTime != "" { |
||||
|
if req.StartTime > req.EndTime { |
||||
|
return nil, 0, fmt.Errorf("结束时间不能早于开始时间") |
||||
|
} |
||||
|
} |
||||
|
// 4.时间范围查询
|
||||
|
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 = s.buildUserScoreSortCondition(db, req) |
||||
|
|
||||
|
err = db.Page(req.Page, req.PageSize).ScanAndCount(&res, &total, false) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
// buildUserScoreSortCondition 构建用户成绩排序条件
|
||||
|
func (s *sQuestionBank) buildUserScoreSortCondition(db *gdb.Model, req *v1.UserScoreOutputReq) *gdb.Model { |
||||
|
// 默认排序(按创建时间倒序)
|
||||
|
if req.SortField == "" { |
||||
|
return db.OrderDesc("b.created_at") |
||||
|
} |
||||
|
|
||||
|
// 确定排序方向
|
||||
|
order := "DESC" |
||||
|
if req.SortOrder == "asc" { |
||||
|
order = "ASC" |
||||
|
} |
||||
|
|
||||
|
// 根据排序字段构建排序条件
|
||||
|
switch req.SortField { |
||||
|
case "score": |
||||
|
return db.Order("b.score " + order) |
||||
|
case "created_at": |
||||
|
return db.Order("b.created_at " + order) |
||||
|
default: |
||||
|
// 默认按创建时间倒序
|
||||
|
return db.OrderDesc("b.created_at") |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
||||
|
// ErrorOutPutUser 错题统计出错用户
|
||||
|
func (s *sQuestionBank) ErrorOutPutUser(ctx context.Context, req *v1.ErrorOutPutUserReq) (res []*v1.ErrorOutPutUserRes, total int, err error) { |
||||
|
// 参数验证
|
||||
|
if req.Id == 0 { |
||||
|
return nil, 0, gerror.New("题目ID不能为空") |
||||
|
} |
||||
|
|
||||
|
// 直接在数据库层面按 jwcode 分组统计
|
||||
|
err = g.Model("question_record r"). |
||||
|
LeftJoin("user u", "r.jwcode = u.jwcode"). |
||||
|
Where("r.question_bank_id = ?", req.Id). |
||||
|
Where("r.is_correct = 1"). |
||||
|
Fields("r.jwcode", "u.user_name", "u.user_identity", "COUNT(*) as error_count"). |
||||
|
Group("r.jwcode", "u.user_name", "u.user_identity"). |
||||
|
OrderDesc("error_count"). |
||||
|
Scan(&res) |
||||
|
|
||||
|
if err != nil { |
||||
|
return nil, 0, gerror.Wrap(err, "查询错题用户统计失败") |
||||
|
} |
||||
|
|
||||
|
total = len(res) |
||||
|
return res, total, nil |
||||
|
} |
||||
|
|
||||
|
// -------------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
||||
|
// ExportQuestion 导出题目数据到 Excel
|
||||
|
func (s *sQuestionBank) ExportQuestion(r *ghttp.Request, ctx context.Context, req *v1.QuestionOutputReq) { |
||||
|
// === 1. 数据查询和验证 ===
|
||||
|
var result []*v1.QuestionOutputRes |
||||
|
|
||||
|
// 查询总数
|
||||
|
_, total, err := service.QuestionBank().GetQuestions(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, _ := s.GetQuestions(ctx, req) |
||||
|
result = append(result, res[:]...) |
||||
|
num += 1000 |
||||
|
if num > total { |
||||
|
break |
||||
|
} |
||||
|
req.Page++ |
||||
|
} |
||||
|
|
||||
|
// === 3. 创建 Excel 文件 ===
|
||||
|
excelFile := excelize.NewFile() |
||||
|
sheetName := "Sheet1" |
||||
|
fileName := "题目数据导出.xlsx" |
||||
|
|
||||
|
// === 4. 设置表头 ===
|
||||
|
headers := []string{"序号", "题干", "选项A", "选项B", "选项C", "选项D", "正确答案", "题目类型", "推荐课程", "引用次数", "错误次数", "错误率"} |
||||
|
for i, header := range headers { |
||||
|
col := string('A' + i) |
||||
|
excelFile.SetCellValue(sheetName, col+"1", header) |
||||
|
} |
||||
|
|
||||
|
// === 5. 写入数据 ===
|
||||
|
rowIndex := 2 |
||||
|
for _, question := range result { |
||||
|
excelFile.SetCellValue(sheetName, "A"+strconv.Itoa(rowIndex), rowIndex-1) |
||||
|
excelFile.SetCellValue(sheetName, "B"+strconv.Itoa(rowIndex), question.Stem) |
||||
|
excelFile.SetCellValue(sheetName, "C"+strconv.Itoa(rowIndex), question.A) |
||||
|
excelFile.SetCellValue(sheetName, "D"+strconv.Itoa(rowIndex), question.B) |
||||
|
excelFile.SetCellValue(sheetName, "E"+strconv.Itoa(rowIndex), question.C) |
||||
|
excelFile.SetCellValue(sheetName, "F"+strconv.Itoa(rowIndex), question.D) |
||||
|
excelFile.SetCellValue(sheetName, "G"+strconv.Itoa(rowIndex), question.CorrectAnswer) |
||||
|
excelFile.SetCellValue(sheetName, "H"+strconv.Itoa(rowIndex), question.QuestionTypeName) |
||||
|
excelFile.SetCellValue(sheetName, "I"+strconv.Itoa(rowIndex), question.CrName) |
||||
|
excelFile.SetCellValue(sheetName, "J"+strconv.Itoa(rowIndex), question.CitationCount) |
||||
|
excelFile.SetCellValue(sheetName, "K"+strconv.Itoa(rowIndex), question.ErrorCount) |
||||
|
excelFile.SetCellValue(sheetName, "L"+strconv.Itoa(rowIndex), strconv.Itoa(question.ErrorRate)+"%") |
||||
|
|
||||
|
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", "L"+strconv.Itoa(lastRow), style) |
||||
|
|
||||
|
// 设置列宽
|
||||
|
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) // 统计信息
|
||||
|
|
||||
|
// === 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{"序号", "用户名", "用户身份", "精网号", "成绩", "提交时间"} |
||||
|
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.UserName) |
||||
|
excelFile.SetCellValue(sheetName, "C"+strconv.Itoa(rowIndex), userScore.UserIdentity) |
||||
|
excelFile.SetCellValue(sheetName, "D"+strconv.Itoa(rowIndex), userScore.Jwcode) |
||||
|
excelFile.SetCellValue(sheetName, "E"+strconv.Itoa(rowIndex), userScore.Score) |
||||
|
excelFile.SetCellValue(sheetName, "F"+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", 20) // 用户名
|
||||
|
excelFile.SetColWidth(sheetName, "C", "C", 15) // 用户身份
|
||||
|
excelFile.SetColWidth(sheetName, "D", "D", 15) // 精网号
|
||||
|
excelFile.SetColWidth(sheetName, "E", "E", 10) // 成绩
|
||||
|
excelFile.SetColWidth(sheetName, "F", "F", 20) // 创建时间
|
||||
|
|
||||
|
// === 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()) |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
// =================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package do |
||||
|
|
||||
|
import ( |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
) |
||||
|
|
||||
|
// CourseRecommend is the golang structure of table course_recommend for DAO operations like Where/Data.
|
||||
|
type CourseRecommend struct { |
||||
|
g.Meta `orm:"table:course_recommend, do:true"` |
||||
|
Id interface{} // 课程推荐主键
|
||||
|
CrName interface{} // 课程推荐名称
|
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
// =================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package do |
||||
|
|
||||
|
import ( |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
"github.com/gogf/gf/v2/os/gtime" |
||||
|
) |
||||
|
|
||||
|
// QuestionBank is the golang structure of table question_bank for DAO operations like Where/Data.
|
||||
|
type QuestionBank struct { |
||||
|
g.Meta `orm:"table:question_bank, do:true"` |
||||
|
Id interface{} // 题库主键
|
||||
|
Stem interface{} // 题干
|
||||
|
A interface{} // A选项
|
||||
|
B interface{} // B选项
|
||||
|
C interface{} // C选项
|
||||
|
D interface{} // D选项
|
||||
|
CorrectAnswer interface{} // 正确答案
|
||||
|
QuestionTypeId interface{} // 题目类型
|
||||
|
CourseRecommendationId interface{} // 课程推荐
|
||||
|
CitationCount interface{} // 引用次数
|
||||
|
ErrorCount interface{} // 错误次数
|
||||
|
CreatedAt *gtime.Time // 创建时间
|
||||
|
UpdatedAt *gtime.Time // 修改时间
|
||||
|
Isdel interface{} // 逻辑删(1为删除)
|
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
// =================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package do |
||||
|
|
||||
|
import ( |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
"github.com/gogf/gf/v2/os/gtime" |
||||
|
) |
||||
|
|
||||
|
// QuestionRecord is the golang structure of table question_record for DAO operations like Where/Data.
|
||||
|
type QuestionRecord struct { |
||||
|
g.Meta `orm:"table:question_record, do:true"` |
||||
|
Id interface{} // 题目记录主键
|
||||
|
Jwcode interface{} // 精网号
|
||||
|
QuestionBankId interface{} // 题目id
|
||||
|
UserAnswer interface{} // 用户答案
|
||||
|
IsCorrect interface{} // 是否正确(0为正确)
|
||||
|
CreatedAt *gtime.Time // 提交时间
|
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
// =================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package do |
||||
|
|
||||
|
import ( |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
) |
||||
|
|
||||
|
// QuestionType is the golang structure of table question_type for DAO operations like Where/Data.
|
||||
|
type QuestionType struct { |
||||
|
g.Meta `orm:"table:question_type, do:true"` |
||||
|
Id interface{} // 题库类型主键
|
||||
|
QuestionTypeName interface{} // 题目类型名称
|
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
// =================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package do |
||||
|
|
||||
|
import ( |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
"github.com/gogf/gf/v2/os/gtime" |
||||
|
) |
||||
|
|
||||
|
// TotalScore is the golang structure of table total_score for DAO operations like Where/Data.
|
||||
|
type TotalScore struct { |
||||
|
g.Meta `orm:"table:total_score, do:true"` |
||||
|
Id interface{} // 总成绩主键
|
||||
|
Jwcode interface{} // 精网号
|
||||
|
Score interface{} // 成绩
|
||||
|
CreatedAt *gtime.Time // 提交时间
|
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
// =================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package do |
||||
|
|
||||
|
import ( |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
"github.com/gogf/gf/v2/os/gtime" |
||||
|
) |
||||
|
|
||||
|
// User is the golang structure of table user for DAO operations like Where/Data.
|
||||
|
type User struct { |
||||
|
g.Meta `orm:"table:user, do:true"` |
||||
|
Id interface{} // 用户主键
|
||||
|
UserName interface{} // 用户名称
|
||||
|
Jwcode interface{} // 精网号
|
||||
|
UserIdentity interface{} // 用户身份
|
||||
|
CreatedAt *gtime.Time // 创建时间
|
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
// =================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package entity |
||||
|
|
||||
|
// CourseRecommend is the golang structure for table course_recommend.
|
||||
|
type CourseRecommend struct { |
||||
|
Id int `json:"id" orm:"id" ` // 课程推荐主键
|
||||
|
CrName string `json:"crName" orm:"cr_name" ` // 课程推荐名称
|
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
// =================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package entity |
||||
|
|
||||
|
import ( |
||||
|
"github.com/gogf/gf/v2/os/gtime" |
||||
|
) |
||||
|
|
||||
|
// QuestionBank is the golang structure for table question_bank.
|
||||
|
type QuestionBank struct { |
||||
|
Id int `json:"id" orm:"id" ` // 题库主键
|
||||
|
Stem string `json:"stem" orm:"stem" ` // 题干
|
||||
|
A string `json:"a" orm:"A" ` // A选项
|
||||
|
B string `json:"b" orm:"B" ` // B选项
|
||||
|
C string `json:"c" orm:"C" ` // C选项
|
||||
|
D string `json:"d" orm:"D" ` // D选项
|
||||
|
CorrectAnswer string `json:"correctAnswer" orm:"correct_answer" ` // 正确答案
|
||||
|
QuestionTypeId int `json:"questionTypeId" orm:"question_type_id" ` // 题目类型
|
||||
|
CourseRecommendationId int `json:"courseRecommendationId" orm:"course_recommendation_id" ` // 课程推荐
|
||||
|
CitationCount int `json:"citationCount" orm:"citation_count" ` // 引用次数
|
||||
|
ErrorCount int `json:"errorCount" orm:"error_count" ` // 错误次数
|
||||
|
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" ` // 创建时间
|
||||
|
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" ` // 修改时间
|
||||
|
Isdel int `json:"isdel" orm:"isdel" ` // 逻辑删(1为删除)
|
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
// =================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package entity |
||||
|
|
||||
|
import ( |
||||
|
"github.com/gogf/gf/v2/os/gtime" |
||||
|
) |
||||
|
|
||||
|
// QuestionRecord is the golang structure for table question_record.
|
||||
|
type QuestionRecord struct { |
||||
|
Id int `json:"id" orm:"id" ` // 题目记录主键
|
||||
|
Jwcode int `json:"jwcode" orm:"jwcode" ` // 精网号
|
||||
|
QuestionBankId int `json:"questionBankId" orm:"question_bank_id" ` // 题目id
|
||||
|
UserAnswer string `json:"userAnswer" orm:"user_answer" ` // 用户答案
|
||||
|
IsCorrect int `json:"isCorrect" orm:"is_correct" ` // 是否正确(0为正确)
|
||||
|
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" ` // 提交时间
|
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
// =================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package entity |
||||
|
|
||||
|
// QuestionType is the golang structure for table question_type.
|
||||
|
type QuestionType struct { |
||||
|
Id int `json:"id" orm:"id" ` // 题库类型主键
|
||||
|
QuestionTypeName string `json:"questionTypeName" orm:"question_type_name" ` // 题目类型名称
|
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
// =================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package entity |
||||
|
|
||||
|
import ( |
||||
|
"github.com/gogf/gf/v2/os/gtime" |
||||
|
) |
||||
|
|
||||
|
// TotalScore is the golang structure for table total_score.
|
||||
|
type TotalScore struct { |
||||
|
Id int `json:"id" orm:"id" ` // 总成绩主键
|
||||
|
Jwcode int `json:"jwcode" orm:"jwcode" ` // 精网号
|
||||
|
Score int `json:"score" orm:"score" ` // 成绩
|
||||
|
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" ` // 提交时间
|
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
// =================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package entity |
||||
|
|
||||
|
import ( |
||||
|
"github.com/gogf/gf/v2/os/gtime" |
||||
|
) |
||||
|
|
||||
|
// User is the golang structure for table user.
|
||||
|
type User struct { |
||||
|
Id int `json:"id" orm:"id" ` // 用户主键
|
||||
|
UserName string `json:"userName" orm:"user_name" ` // 用户名称
|
||||
|
Jwcode string `json:"jwcode" orm:"jwcode" ` // 精网号
|
||||
|
UserIdentity string `json:"userIdentity" orm:"user_identity" ` // 用户身份
|
||||
|
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" ` // 创建时间
|
||||
|
} |
||||
@ -0,0 +1,41 @@ |
|||||
|
// ================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// You can delete these comments if you wish manually maintain this interface file.
|
||||
|
// ================================================================================
|
||||
|
|
||||
|
package service |
||||
|
|
||||
|
import ( |
||||
|
v1 "Knowledge_Test_Go/api/v1" |
||||
|
"context" |
||||
|
) |
||||
|
|
||||
|
type ( |
||||
|
IKnowledgeTest interface { |
||||
|
// GetQuestions 获取题目列表
|
||||
|
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 获取错题列表
|
||||
|
GetWrongQuestions(ctx context.Context, req *v1.GetWrongQuestionsReq) (res []*v1.GetWrongQuestionsRes, total int, err error) |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
var ( |
||||
|
localKnowledgeTest IKnowledgeTest |
||||
|
) |
||||
|
|
||||
|
func KnowledgeTest() IKnowledgeTest { |
||||
|
if localKnowledgeTest == nil { |
||||
|
panic("implement not found for interface IKnowledgeTest, forgot register?") |
||||
|
} |
||||
|
return localKnowledgeTest |
||||
|
} |
||||
|
|
||||
|
func RegisterKnowledgeTest(i IKnowledgeTest) { |
||||
|
localKnowledgeTest = i |
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
// ================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// You can delete these comments if you wish manually maintain this interface file.
|
||||
|
// ================================================================================
|
||||
|
|
||||
|
package service |
||||
|
|
||||
|
import ( |
||||
|
v1 "Knowledge_Test_Go/api/v1" |
||||
|
"context" |
||||
|
|
||||
|
"github.com/gogf/gf/v2/net/ghttp" |
||||
|
) |
||||
|
|
||||
|
type ( |
||||
|
IQuestionBank interface { |
||||
|
// GetQuestions 获取题目列表
|
||||
|
GetQuestions(ctx context.Context, req *v1.QuestionOutputReq) (res []*v1.QuestionOutputRes, total int, err error) |
||||
|
// QuestionUpdate 修改题目
|
||||
|
QuestionUpdate(ctx context.Context, req *v1.QuestionUpdateReq) (res string, err error) |
||||
|
// QuestionDel 删除题目
|
||||
|
QuestionDel(ctx context.Context, req *v1.QuestionDelReq) (res string, err error) |
||||
|
// UserScoreOutput 获取用户成绩列表
|
||||
|
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) |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
var ( |
||||
|
localQuestionBank IQuestionBank |
||||
|
) |
||||
|
|
||||
|
func QuestionBank() IQuestionBank { |
||||
|
if localQuestionBank == nil { |
||||
|
panic("implement not found for interface IQuestionBank, forgot register?") |
||||
|
} |
||||
|
return localQuestionBank |
||||
|
} |
||||
|
|
||||
|
func RegisterQuestionBank(i IQuestionBank) { |
||||
|
localQuestionBank = i |
||||
|
} |
||||
@ -0,0 +1,128 @@ |
|||||
|
package response |
||||
|
|
||||
|
import ( |
||||
|
"net/http" |
||||
|
|
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
"github.com/gogf/gf/v2/net/ghttp" |
||||
|
"github.com/gogf/gf/v2/util/gconv" |
||||
|
) |
||||
|
|
||||
|
// JsonRes 数据返回通用JSON数据结构
|
||||
|
type JsonRes struct { |
||||
|
Code int `json:"code"` // 错误码((0:成功, 1:失败, >1:错误码))
|
||||
|
Message string `json:"msg"` // 提示信息
|
||||
|
Data interface{} `json:"data"` // 返回数据(业务接口定义具体数据结构)
|
||||
|
// Redirect string `json:"redirect"` // 引导客户端跳转到指定路由
|
||||
|
} |
||||
|
|
||||
|
// Json 返回标准JSON数据。
|
||||
|
func Json(r *ghttp.Request, code int, message string, data ...interface{}) { |
||||
|
var responseData interface{} |
||||
|
if len(data) > 0 { |
||||
|
responseData = data[0] |
||||
|
} else { |
||||
|
responseData = g.Map{} |
||||
|
} |
||||
|
r.Response.WriteJson(JsonRes{ |
||||
|
Code: code, |
||||
|
Message: message, |
||||
|
Data: responseData, |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
// JsonExit 返回标准JSON数据并退出当前HTTP执行函数。
|
||||
|
func JsonExit(r *ghttp.Request, code int, message string, data ...interface{}) { |
||||
|
if code == http.StatusBadRequest { |
||||
|
g.Log().Error(r.Context(), code, message) |
||||
|
} |
||||
|
Json(r, code, message, data...) |
||||
|
r.Exit() |
||||
|
} |
||||
|
|
||||
|
func dataReturn(r *ghttp.Request, code int, req ...interface{}) *JsonRes { |
||||
|
var msg string |
||||
|
var data interface{} |
||||
|
if len(req) > 0 { |
||||
|
msg = gconv.String(req[0]) |
||||
|
} |
||||
|
if len(req) > 1 { |
||||
|
data = req[1] |
||||
|
} |
||||
|
// msg = GetCodeMsg(code, msg)
|
||||
|
if code != 1 && !gconv.Bool(r.GetCtxVar("api_code")) { |
||||
|
code = 0 |
||||
|
} |
||||
|
response := &JsonRes{ |
||||
|
// ID: r.GetCtxVar("RequestId").String(),
|
||||
|
Code: code, |
||||
|
Message: msg, |
||||
|
Data: data, |
||||
|
} |
||||
|
r.SetParam("apiReturnRes", response) |
||||
|
return response |
||||
|
} |
||||
|
|
||||
|
// Auth 认证失败
|
||||
|
func Auth(r *ghttp.Request) { |
||||
|
res := dataReturn(r, 999, "请登录") |
||||
|
r.Response.WriteJsonExit(res) |
||||
|
} |
||||
|
|
||||
|
// AuthBlack Auth 认证失败 被冻结拉黑
|
||||
|
func AuthBlack(r *ghttp.Request) { |
||||
|
res := dataReturn(r, 888, "您的账号被冻结拉黑,请联系管理员") |
||||
|
r.Response.WriteJsonExit(res) |
||||
|
} |
||||
|
|
||||
|
// JsonRedirect 返回标准JSON数据引导客户端跳转。
|
||||
|
func JsonRedirect(r *ghttp.Request, code int, message, redirect string, data ...interface{}) { |
||||
|
responseData := interface{}(nil) |
||||
|
if len(data) > 0 { |
||||
|
responseData = data[0] |
||||
|
} |
||||
|
r.Response.WriteJson(JsonRes{ |
||||
|
Code: code, |
||||
|
Message: message, |
||||
|
Data: responseData, |
||||
|
// Redirect: redirect,
|
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
// JsonRedirectExit 返回标准JSON数据引导客户端跳转,并退出当前HTTP执行函数。
|
||||
|
func JsonRedirectExit(r *ghttp.Request, code int, message, redirect string, data ...interface{}) { |
||||
|
JsonRedirect(r, code, message, redirect, data...) |
||||
|
r.Exit() |
||||
|
} |
||||
|
|
||||
|
func SuccessWithData(r *ghttp.Request, data interface{}) { |
||||
|
res := dataReturn(r, 1, "ok", data) |
||||
|
r.Response.WriteJsonExit(res) |
||||
|
} |
||||
|
|
||||
|
// JsonResponse 数据返回通用JSON数据结构
|
||||
|
type JsonResponse struct { |
||||
|
// ID string `json:"id"` //
|
||||
|
Code int `json:"code"` // 错误码((1:成功, 0:失败, >1:错误码))
|
||||
|
Message string `json:"message"` // 提示信息
|
||||
|
Data interface{} `json:"data,omitempty"` // 返回数据(业务接口定义具体数据结构)
|
||||
|
Redirect string `json:"redirect,omitempty"` // 引导客户端跳转到指定路由
|
||||
|
} |
||||
|
|
||||
|
/*错误,只有错误信息,错误码0*/ |
||||
|
func Error(msg string) *JsonRes { |
||||
|
return &JsonRes{ |
||||
|
Code: 400, // 错误码
|
||||
|
Message: msg, // 错误信息
|
||||
|
Data: nil, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*成功,有数据*/ |
||||
|
func SuccessWithDataNoReq(data interface{}) *JsonRes { |
||||
|
return &JsonRes{ |
||||
|
Code: 200, |
||||
|
Message: "success", |
||||
|
Data: data, |
||||
|
} |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue