Browse Source

12月19日晚 问题基本解决,日志关闭.前端退出登入token问题尚待解决

dev_ljk
lijikun 5 months ago
parent
commit
c5ae52c38d
  1. 7
      link_homework/go.mod
  2. 17
      link_homework/go.sum
  3. 13
      link_homework/internal/cmd/cmd.go
  4. 9
      link_homework/internal/controller/clientPage/clientPage.go
  5. 5
      link_homework/internal/controller/record/export.go
  6. 205
      link_homework/internal/controller/record/manageRecord.go
  7. 7
      link_homework/internal/logic/client/client.go
  8. 5
      link_homework/internal/logic/record/record.go
  9. 28
      link_homework/main.go
  10. 10
      link_homework/manifest/config/config.yaml
  11. 8
      link_homework/manifest/deploy/kustomize/overlays/develop/configmap.yaml
  12. 28
      link_homework/utility/utility.go

7
link_homework/go.mod

@ -8,7 +8,7 @@ require (
github.com/gogf/gf/contrib/nosql/redis/v2 v2.8.1 github.com/gogf/gf/contrib/nosql/redis/v2 v2.8.1
github.com/gogf/gf/v2 v2.8.1 github.com/gogf/gf/v2 v2.8.1
github.com/golang-jwt/jwt/v4 v4.5.1 github.com/golang-jwt/jwt/v4 v4.5.1
github.com/xuri/excelize/v2 v2.9.0
github.com/golang-jwt/jwt/v5 v5.2.1
) )
require ( require (
@ -31,16 +31,11 @@ require (
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/redis/go-redis/v9 v9.7.0 // indirect github.com/redis/go-redis/v9 v9.7.0 // 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/rivo/uniseg v0.4.7 // indirect
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d // indirect
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 // indirect
go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel v1.24.0 // indirect
go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect
go.opentelemetry.io/otel/sdk v1.24.0 // indirect go.opentelemetry.io/otel/sdk v1.24.0 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect
golang.org/x/crypto v0.30.0 // indirect
golang.org/x/net v0.32.0 // indirect golang.org/x/net v0.32.0 // indirect
golang.org/x/sys v0.28.0 // indirect golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect golang.org/x/text v0.21.0 // indirect

17
link_homework/go.sum

@ -35,6 +35,8 @@ github.com/gogf/gf/v2 v2.8.1 h1:1oVQg3G5OgCats4qWFTH3pHLe92nfUQeUDta05tUs1g=
github.com/gogf/gf/v2 v2.8.1/go.mod h1:6iYuZZ+A0ZcH8+4MDS/P0SvTPCvKzRvyAsY1kbkJYJc= github.com/gogf/gf/v2 v2.8.1/go.mod h1:6iYuZZ+A0ZcH8+4MDS/P0SvTPCvKzRvyAsY1kbkJYJc=
github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
@ -59,23 +61,12 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E= github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E=
github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
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.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/stretchr/testify v1.2.3-0.20181224173747-660f15d67dbb/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.3-0.20181224173747-660f15d67dbb/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d h1:llb0neMWDQe87IzJLS4Ci7psK/lVsjIS2otl+1WyRyY=
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
github.com/xuri/excelize/v2 v2.9.0 h1:1tgOaEq92IOEumR1/JfYS/eR0KHOCsRv/rYXXh6YJQE=
github.com/xuri/excelize/v2 v2.9.0/go.mod h1:uqey4QBZ9gdMeWApPLdhm9x+9o2lq4iVmjiLfBS5hdE=
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 h1:hPVCafDV85blFTabnqKgNhDCkJX25eik94Si9cTER4A=
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
@ -84,10 +75,6 @@ go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucg
go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY=
golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

13
link_homework/internal/cmd/cmd.go

@ -29,15 +29,14 @@ var (
group.POST("/logout", auth.NewLoginController().Logout) group.POST("/logout", auth.NewLoginController().Logout)
}) })
s.Group("/api/homework_manage", func(group *ghttp.RouterGroup) { s.Group("/api/homework_manage", func(group *ghttp.RouterGroup) {
group.Middleware(middleware.MiddlewareCORS)
//group.Middleware(middleware.MiddlewareIsLogin)
//group.Middleware(middleware.MiddlewareCORS)
group.Middleware(middleware.MiddlewareIsLogin)
//gfToken.Middleware(ctx, group) //gfToken.Middleware(ctx, group)
//直接写接口,不用再分组 //直接写接口,不用再分组
group.POST("/getrecordlist", record.NewManageRecord().GetRecordList) group.POST("/getrecordlist", record.NewManageRecord().GetRecordList)
group.POST("/getrecordbycondition", record.NewManageRecord().GetRecordByCondition) group.POST("/getrecordbycondition", record.NewManageRecord().GetRecordByCondition)
group.POST("/getdeptinfo", record.NewManageRecord().GetDeptInfo) group.POST("/getdeptinfo", record.NewManageRecord().GetDeptInfo)
group.POST("/getshopinfo", record.NewManageRecord().GetShopInfo) group.POST("/getshopinfo", record.NewManageRecord().GetShopInfo)
group.POST("/exceleexport", record.NewManageRecord().ExeclExport)
group.POST("/get-homework-list", homework.Homework().GetHomeworkList) group.POST("/get-homework-list", homework.Homework().GetHomeworkList)
group.POST("/get-homework", homework.Homework().GetHomework) group.POST("/get-homework", homework.Homework().GetHomework)
group.POST("/add-homework", homework.Homework().AddHomework) group.POST("/add-homework", homework.Homework().AddHomework)
@ -45,12 +44,14 @@ var (
group.ALL("/get-article-list", article.Article().GetArticleList) group.ALL("/get-article-list", article.Article().GetArticleList)
group.ALL("/get-live-list", live.Live().GetLiveList) group.ALL("/get-live-list", live.Live().GetLiveList)
//导出excel //导出excel
group.ALL("/export-record", record.NewExportRecord().ExportRecordByCondition)
//group.ALL("/export-record", record.NewExportRecord().ExportRecordByCondition)
//group.POST("/exceleexport", record.NewManageRecord().ExeclExport)
group.ALL("export-record", record.NewManageRecord().ExportRecordByCondition)
}) })
//客户端 //客户端
s.Group("/api/homework_client", func(group *ghttp.RouterGroup) { s.Group("/api/homework_client", func(group *ghttp.RouterGroup) {
group.Middleware(middleware.MiddlewareCORS)
//group.Middleware(middleware.MiddlewareIsLogin)
//group.Middleware(middleware.MiddlewareCORS)
group.Middleware(middleware.MiddlewareIsLogin)
//gfToken.Middleware(ctx, group) //gfToken.Middleware(ctx, group)
//直接写接口,不用再分组 //直接写接口,不用再分组
group.POST("/gethomeworklist", clientPage.NewClientPage().GetHomeworkList) group.POST("/gethomeworklist", clientPage.NewClientPage().GetHomeworkList)

9
link_homework/internal/controller/clientPage/clientPage.go

@ -17,8 +17,13 @@ func NewClientPage() *ClientPage {
// 查询作业列表 // 查询作业列表
func (c *ClientPage) GetHomeworkList(r *ghttp.Request) { func (c *ClientPage) GetHomeworkList(r *ghttp.Request) {
//请求中不需要携带任何参数 //请求中不需要携带任何参数
token := r.Get("token").String()
//token := r.Request.Header.Get("token")
token := r.Header.Get("token")
//fmt.Println("======")
//fmt.Println(token)
//fmt.Println("------")
jwcode, err := utility.GetJwcodeJSON(token) jwcode, err := utility.GetJwcodeJSON(token)
//fmt.Println(token)
if err != nil { if err != nil {
r.Response.WriteJsonExit(dto.Result{ r.Response.WriteJsonExit(dto.Result{
Code: 400, Code: 400,
@ -63,7 +68,7 @@ func (c *ClientPage) GetHomeworkQuestion(r *ghttp.Request) {
} }
func (c *ClientPage) CommitHomework(r *ghttp.Request) { func (c *ClientPage) CommitHomework(r *ghttp.Request) {
token := r.Get("token").String()
token := r.Request.Header.Get("token")
jwcode, err := utility.GetJwcodeJSON(token) jwcode, err := utility.GetJwcodeJSON(token)
if err != nil { if err != nil {
r.Response.WriteJsonExit(dto.Result{ r.Response.WriteJsonExit(dto.Result{

5
link_homework/internal/controller/record/export.go

@ -2,7 +2,6 @@ package record
import ( import (
"github.com/360EntSecGroup-Skylar/excelize" "github.com/360EntSecGroup-Skylar/excelize"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/net/ghttp"
"link_homework/api/v1/record" "link_homework/api/v1/record"
"link_homework/internal/model/dto" "link_homework/internal/model/dto"
@ -33,13 +32,13 @@ func (m *ExportRecord) ExportRecordByCondition(r *ghttp.Request) {
req.Id, req.Jwcode, req.DeptId, req.ShopId, req.PageNo, req.PageSize, req.Id, req.Jwcode, req.DeptId, req.ShopId, req.PageNo, req.PageSize,
) )
if err != nil { if err != nil {
g.Log().Error(r.Context(), "查询记录失败: ", err)
//g.Log().Error(r.Context(), "查询记录失败: ", err)
r.Response.WriteJsonExit(dto.Error("查询记录失败: " + err.Error())) r.Response.WriteJsonExit(dto.Error("查询记录失败: " + err.Error()))
return return
} }
if len(records) == 0 { if len(records) == 0 {
g.Log().Warning(r.Context(), "查询结果为空: 参数 = ", req)
//g.Log().Warning(r.Context(), "查询结果为空: 参数 = ", req)
r.Response.WriteJsonExit(dto.Error("查询结果为空")) r.Response.WriteJsonExit(dto.Error("查询结果为空"))
return return
} }

205
link_homework/internal/controller/record/manageRecord.go

@ -6,9 +6,8 @@ import (
"link_homework/api/v1/record" "link_homework/api/v1/record"
"link_homework/internal/model/dto" "link_homework/internal/model/dto"
"link_homework/internal/service" "link_homework/internal/service"
"log"
"net/http"
"strconv" "strconv"
"time"
) )
type ManageRecord struct{} type ManageRecord struct{}
@ -102,168 +101,74 @@ func (m *ManageRecord) GetShopInfo(r *ghttp.Request) {
}) })
} }
func (m *ManageRecord) ExeclExport(r *ghttp.Request) {
//获取前端传来的参数
// ExportRecordByCondition 导出记录
func (m *ManageRecord) ExportRecordByCondition(r *ghttp.Request) {
var req record.GetRecordByConditionReq var req record.GetRecordByConditionReq
// 解析查询条件
if err := r.Parse(&req); err != nil { if err := r.Parse(&req); err != nil {
r.Response.WriteJsonExit(dto.Result{
Code: 400,
Message: err.Error(),
})
r.Response.WriteJsonExit(dto.Error("参数解析失败: " + err.Error()))
return
} }
//获取数据
data, err := service.Record().GetRecordByCondition(r.Context(), req.Id, req.Jwcode, req.DeptId, req.ShopId, req.PageNo, req.PageSize)
if err != nil {
r.Response.WriteJsonExit(dto.Result{
Code: 400,
Message: err.Error(),
})
}
//创建文件
f := excelize.NewFile()
sheet := "Sheet1"
f.NewSheet(sheet)
////创建表头
//var header []string
////for _, field :=range reflect.Type(record.GetRecordListRes{}){
//// header = append(header, field.Name)
////}
//for i := 0; i < reflect.TypeOf(record.GetRecordListRes{}).NumField(); i++ {
// header = append(header, reflect.TypeOf(record.GetRecordListRes{}).Field(i).Name)
//}
headers := []string{"精网号", "用户名字", "部门名", "门店名", "答案详情", "提交时间"}
headerStyle, err := f.NewStyle(`{"font":{"bold":true},"fill":{"type":"solid","color":"#4F81BD"}}`)
// 调用查询服务
records, err := service.Record().GetRecordByCondition(
r.Context(),
req.Id, req.Jwcode, req.DeptId, req.ShopId, req.PageNo, req.PageSize,
)
if err != nil { if err != nil {
r.Response.WriteJsonExit(dto.Result{
Code: 400,
Message: err.Error(),
})
}
for i, header := range headers {
cellName := getExcelColumnName(i) + "1"
f.SetCellValue(sheet, cellName, header)
f.SetCellStyle(sheet, cellName, cellName, headerStyle)
//g.Log().Error(r.Context(), "查询记录失败: ", err)
r.Response.WriteJsonExit(dto.Error("查询记录失败: " + err.Error()))
return
} }
//填充数据
for rowIndex, row := range data {
// 假设 data 是一个 []GetRecordListRes 类型的切片
rowData := row //.(record.GetRecordListRes) // 类型断言(这里需要确保 data 的类型是正确的)
// 或者使用反射,但更推荐使用标签和直接映射
f.SetCellValue(sheet, getExcelColumnName(0)+strconv.Itoa(rowIndex+2), rowData.Jwcode)
f.SetCellValue(sheet, getExcelColumnName(1)+strconv.Itoa(rowIndex+2), rowData.Name)
f.SetCellValue(sheet, getExcelColumnName(2)+strconv.Itoa(rowIndex+2), rowData.DeptName)
f.SetCellValue(sheet, getExcelColumnName(3)+strconv.Itoa(rowIndex+2), rowData.ShopName)
f.SetCellValue(sheet, getExcelColumnName(4)+strconv.Itoa(rowIndex+2), rowData.Reply)
f.SetCellValue(sheet, getExcelColumnName(5)+strconv.Itoa(rowIndex+2), rowData.Reply[0].UpdatedAt.Format("2006-01-02 15:04:05"))
if len(records) == 0 {
//g.Log().Warning(r.Context(), "查询结果为空: 参数 = ", req)
r.Response.WriteJsonExit(dto.Error("查询结果为空"))
return
} }
// 创建 Excel 文件
excelFile := excelize.NewFile() // 默认会创建一个 Sheet1
sheetName := "Sheet1" // 使用默认的 Sheet1
////定义表头样式,font:定义字体样式,如字体类型、字体大小、字体颜色等,Arial:字体家族为Arial.
////fill:定义填充样式,如背景色
//const (
// headerStyleJSON = `{
// "font": {
// "bold": true,
// "italic": false,
// "family": "Arial",
// "size": 14,
// "color": "#FFFFFF" //更换成你想要的字体font
// },
// "fill": {
// "type": "solid",
// "color": "#4F81BD" // 更换为你想要的背景色
// }
// }`
//)
////填充表头
//headerStyle, err := f.NewStyle(headerStyleJSON)
//if err != nil {
// r.Response.WriteJsonExit(dto.Result{
// Code: 400,
// Message: err.Error(),
// })
//}
//
//for i, v := range header {
// cell := fmt.Sprintf("%s%d", getExcelColumnName(i), 1)
// f.SetCellValue(sheet, cell, v)
// f.SetCellStyle(sheet, cell, cell, headerStyle)
//}
//
////填充数据
//for i, row := range data {
// for j, col := range header {
// cell := fmt.Sprintf("%s%d", getExcelColumnName(j), i+2)
// //f.SetCellValue(sheet, cell, row[col])
// f.SetCellValue(sheet, cell, row.FieldByName(col).Interface())
// }
//}
//设置默认打开的sheet
f.SetActiveSheet(f.GetSheetIndex(sheet))
// 将 Excel 文件作为 HTTP 响应发送给客户端
r.Response.Header().Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
r.Response.Header().Set("Content-Disposition", "attachment; filename=data.xlsx")
r.Response.WriteHeader(http.StatusOK)
if _, err := f.WriteTo(r.Response.Writer); err != nil { //这里有问题,说左右值数量不同,我加了个_
// 处理错误(注意:这里可能无法再发送 JSON 响应,因为响应头已经发送)
log.Printf("Error writing Excel file to response: %v", err)
// 设置表头
headers := []string{"序号", "精网号", "名字", "部门ID", "部门名称", "门店ID", "门店名称", "题目ID", "题目类型", "题目名称", "简答题标题", "作答内容", "提交时间"}
for i, header := range headers {
col := string('A' + i) // 将索引转换为 Excel 列名
excelFile.SetCellValue(sheetName, col+"1", header)
} }
////保存文件
//if err := f.SaveAs("data.xlsx"); err != nil {
// r.Response.WriteJsonExit(dto.Result{
// Code: 400,
// Message: err.Error(),
// })
//}
//
//r.Response.WriteJsonExit(dto.Result{
// Code: 200,
// Message: "success",
// Data: "data.xlsx",
//})
}
//func getExcelColumnName(index int) string {
// var result string
// for index > 0 {
// index--
// result = string('A'+index%26) + result
// index /= 26
// }
// return result
//}
// getExcelColumnName 将整数索引转换为 Excel 列名
func getExcelColumnName(index int) string {
if index <= 0 {
return ""
// 写入数据
rowIndex := 2 // 从第二行开始写入数据
for _, record := range records {
for _, reply := range record.Reply { // 遍历每个 `Reply`
excelFile.SetCellValue(sheetName, "A"+strconv.Itoa(rowIndex), rowIndex-1)
excelFile.SetCellValue(sheetName, "B"+strconv.Itoa(rowIndex), record.Jwcode)
excelFile.SetCellValue(sheetName, "C"+strconv.Itoa(rowIndex), record.Name)
excelFile.SetCellValue(sheetName, "D"+strconv.Itoa(rowIndex), record.DeptId)
excelFile.SetCellValue(sheetName, "E"+strconv.Itoa(rowIndex), record.DeptName)
excelFile.SetCellValue(sheetName, "F"+strconv.Itoa(rowIndex), record.ShopId)
excelFile.SetCellValue(sheetName, "G"+strconv.Itoa(rowIndex), record.ShopName)
excelFile.SetCellValue(sheetName, "H"+strconv.Itoa(rowIndex), reply.FormId)
excelFile.SetCellValue(sheetName, "I"+strconv.Itoa(rowIndex), reply.Type)
excelFile.SetCellValue(sheetName, "J"+strconv.Itoa(rowIndex), reply.Description)
excelFile.SetCellValue(sheetName, "K"+strconv.Itoa(rowIndex), reply.ContentTitle)
excelFile.SetCellValue(sheetName, "L"+strconv.Itoa(rowIndex), reply.Content)
excelFile.SetCellValue(sheetName, "M"+strconv.Itoa(rowIndex), reply.UpdatedAt.String())
rowIndex++
}
} }
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
var columnName string
// 设置文件名
fileName := "Records_" + time.Now().Format("20060102150405") + ".xlsx"
for index > 0 {
// 取余数得到当前位的字母
remainder := index % 26
// 将字母添加到结果字符串的前面
columnName = string(letters[remainder-1]) + columnName
// 去掉已经处理过的最低位(因为 Excel 列名是从 1 开始计数的,所以这里要减 1)
// 但由于我们是从后往前构建字符串,所以实际上是在下一次循环中处理 index/26 的结果
index = (index - remainder) / 26
// 由于上面的计算中 index-remainder 可能是 26 的倍数(当 remainder 为 0 时),这样会导致 index 多减 1,
// 所以当 remainder 为 0 时,我们需要将 index 加回 1(或者等价地,不执行 index-- 操作)。
// 但由于我们在循环中每次都会执行 index = (index - remainder) / 26,并且当 remainder 为 0 时,
// (index - 0) / 26 实际上就是 index / 26,这是正确的。因此,我们不需要在这里对 remainder 为 0 的情况进行特殊处理。
// 这里的注释主要是为了解释为什么上面的计算是正确的,以及为什么不需要对 remainder 为 0 的情况进行额外处理。
// 保存到缓冲区并返回
buffer, err := excelFile.WriteToBuffer()
if err != nil {
r.Response.WriteJsonExit(dto.Error("生成 Excel 文件失败: " + err.Error()))
return
} }
return columnName
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())
} }

7
link_homework/internal/logic/client/client.go

@ -2,7 +2,6 @@ package client
import ( import (
"context" "context"
"fmt"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/os/gtime"
"link_homework/api/v1/ClientPage" "link_homework/api/v1/ClientPage"
@ -21,19 +20,19 @@ func (s *sClient) ClientGetHomeworkList(ctx context.Context, jwcode int) (homewo
err = dao.ActivityInteractiveGroup.Ctx(ctx).Fields("id", "name", "DATE_FORMAT(end_date, '%Y-%m-%d') as end_date"). err = dao.ActivityInteractiveGroup.Ctx(ctx).Fields("id", "name", "DATE_FORMAT(end_date, '%Y-%m-%d') as end_date").
Where("end_date>?", gtime.Now()).OrderDesc("end_date").Scan(&homeworkList) Where("end_date>?", gtime.Now()).OrderDesc("end_date").Scan(&homeworkList)
if err != nil { if err != nil {
fmt.Println("作业列表查询失败:", err)
//fmt.Println("作业列表查询失败:", err)
return return
} }
for i, item := range homeworkList { for i, item := range homeworkList {
var count int var count int
count, err = dao.ActivityInteractiveRecord.Ctx(ctx).Where("group_id=?", item.Id).Where("jwcode", jwcode).Count() //只有精网号和作业id查出来的结果是所需要的结果的题目数倍数 count, err = dao.ActivityInteractiveRecord.Ctx(ctx).Where("group_id=?", item.Id).Where("jwcode", jwcode).Count() //只有精网号和作业id查出来的结果是所需要的结果的题目数倍数
if err != nil { if err != nil {
fmt.Println("提交记录数查询失败:", err)
//fmt.Println("提交记录数查询失败:", err)
return return
} }
num, err1 := dao.ActivityInteractiveForm.Ctx(ctx).Where("group_id", item.Id).Count() num, err1 := dao.ActivityInteractiveForm.Ctx(ctx).Where("group_id", item.Id).Count()
if err1 != nil { if err1 != nil {
fmt.Println("题目数查询失败:", err1)
//fmt.Println("题目数查询失败:", err1)
return return
} }
homeworkList[i].Submit = count / num homeworkList[i].Submit = count / num

5
link_homework/internal/logic/record/record.go

@ -3,7 +3,6 @@ package record
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
pkgRecord "link_homework/api/v1/record" pkgRecord "link_homework/api/v1/record"
"link_homework/internal/dao" "link_homework/internal/dao"
@ -34,7 +33,7 @@ func (s *sRecord) GetRecordList(ctx context.Context, groupId, pageNo, pageSize i
return nil, errors.New("无条件查jwcode失败") return nil, errors.New("无条件查jwcode失败")
} }
fmt.Println(record)
//fmt.Println(record)
//根据jwcode在member_info表中查询姓名(name), 部门id(deptId), 部门名(deptName), 门店id(shopId), 门店名(shopName) //根据jwcode在member_info表中查询姓名(name), 部门id(deptId), 部门名(deptName), 门店id(shopId), 门店名(shopName)
for i, info := range record { for i, info := range record {
err = g.DB("cms").Model("member_info").Fields("jwcode", "name", "deptId", "deptName", "shopId", "shopName"). err = g.DB("cms").Model("member_info").Fields("jwcode", "name", "deptId", "deptName", "shopId", "shopName").
@ -61,7 +60,7 @@ func (s *sRecord) GetRecordList(ctx context.Context, groupId, pageNo, pageSize i
} }
} }
record[i].Reply = recordInfo record[i].Reply = recordInfo
fmt.Println(record)
//fmt.Println(record)
} }
return return
} }

28
link_homework/main.go

@ -1,15 +1,12 @@
package main package main
import ( import (
"fmt"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
_ "link_homework/internal/packed" _ "link_homework/internal/packed"
"github.com/gogf/gf/v2/os/gctx"
_ "link_homework/internal/packed"
_ "github.com/gogf/gf/contrib/drivers/mysql/v2" _ "github.com/gogf/gf/contrib/drivers/mysql/v2"
_ "github.com/gogf/gf/contrib/nosql/redis/v2" _ "github.com/gogf/gf/contrib/nosql/redis/v2"
"github.com/gogf/gf/v2/os/gctx"
"link_homework/internal/cmd" "link_homework/internal/cmd"
@ -20,45 +17,46 @@ func main() {
ctx := gctx.GetInitCtx() ctx := gctx.GetInitCtx()
//启动日志 //启动日志
g.Log().Info(ctx, "服务启动中")
//g.Log().Info(ctx, "服务启动中")
//检查数据库链接 //检查数据库链接
// 检查默认数据库链接 // 检查默认数据库链接
db := g.DB() db := g.DB()
if err := db.PingMaster(); err != nil { if err := db.PingMaster(); err != nil {
g.Log().Fatal(ctx, "默认数据库链接失败,请检查数据库链接配置")
//g.Log().Fatal(ctx, "默认数据库链接失败,请检查数据库链接配置")
return return
} }
g.Log().Info(ctx, "默认数据库链接成功")
//g.Log().Info(ctx, "默认数据库链接成功")
// 检查 CMS 数据库链接 // 检查 CMS 数据库链接
cmsDb := g.DB("cms") cmsDb := g.DB("cms")
if err := cmsDb.PingMaster(); err != nil { if err := cmsDb.PingMaster(); err != nil {
g.Log().Fatal(ctx, "CMS 数据库链接失败,请检查数据库链接配置")
//g.Log().Fatal(ctx, "CMS 数据库链接失败,请检查数据库链接配置")
return return
} }
g.Log().Info(ctx, "CMS 数据库链接成功")
//g.Log().Info(ctx, "CMS 数据库链接成功")
// 检查 Redis 配置并连接 // 检查 Redis 配置并连接
// 如果配置中存在 Redis 配置,初始化 Redis 客户端 // 如果配置中存在 Redis 配置,初始化 Redis 客户端
// 打印 Redis 配置,确保它加载正确 // 打印 Redis 配置,确保它加载正确
redisConfig, err := g.Cfg().Get(ctx, "redis.default")
//redisConfig, err := g.Cfg().Get(ctx, "redis.default")
_, err := g.Cfg().Get(ctx, "redis.default")
if err != nil { if err != nil {
fmt.Println("获取 Redis 配置失败:", err)
//fmt.Println("获取 Redis 配置失败:", err)
return return
} }
fmt.Printf("Redis 配置:%v\n", redisConfig)
//fmt.Printf("Redis 配置:%v\n", redisConfig)
// 测试 Redis 连接 // 测试 Redis 连接
_, err = g.Redis().Do(ctx, "PING") _, err = g.Redis().Do(ctx, "PING")
if err != nil { if err != nil {
g.Log().Fatal(ctx, fmt.Sprintf("Redis 链接失败: %v", err))
//g.Log().Fatal(ctx, fmt.Sprintf("Redis 链接失败: %v", err))
return return
} }
g.Log().Info(ctx, "Redis 链接成功")
//g.Log().Info(ctx, "Redis 链接成功")
//启动主命令逻辑 //启动主命令逻辑
cmd.Main.Run(ctx) cmd.Main.Run(ctx)
//服务启动完成日志 //服务启动完成日志
g.Log().Info(ctx, "服务启动完成")
//g.Log().Info(ctx, "服务启动完成")
} }

10
link_homework/manifest/config/config.yaml

@ -3,18 +3,18 @@ server:
address: ":8080" address: ":8080"
# https://goframe.org/docs/core/glog-config # https://goframe.org/docs/core/glog-config
logger:
level : "all"
stdout: true
#logger:
# level : "all"
# stdout: true
# https://goframe.org/docs/core/gdb-config-file # https://goframe.org/docs/core/gdb-config-file
database: database:
default: default:
link: "mysql:live:p4jMAMShNM8HTrbX@tcp(39.101.133.168:3306)/live?charset=utf8mb4&parseTime=True&loc=Local" link: "mysql:live:p4jMAMShNM8HTrbX@tcp(39.101.133.168:3306)/live?charset=utf8mb4&parseTime=True&loc=Local"
debug: true
# debug: true
cms: cms:
link: "mysql:cms:AF42R3ib6YkFaemm@tcp(39.101.133.168:3306)/cms?charset=utf8mb4&parseTime=True&loc=Local" link: "mysql:cms:AF42R3ib6YkFaemm@tcp(39.101.133.168:3306)/cms?charset=utf8mb4&parseTime=True&loc=Local"
debug: true
# debug: true
# redis配置 # redis配置
redis: redis:

8
link_homework/manifest/deploy/kustomize/overlays/develop/configmap.yaml

@ -8,7 +8,7 @@ data:
address: ":8000" address: ":8000"
openapiPath: "/api.json" openapiPath: "/api.json"
swaggerPath: "/swagger" swaggerPath: "/swagger"
logger:
level : "all"
stdout: true
#
# logger:
# level : "all"
# stdout: true

28
link_homework/utility/utility.go

@ -63,16 +63,16 @@ func selectBaseUrl(hashKey string) *dto.Result {
// 获取 jwcode // 获取 jwcode
// 获取 jwcode // 获取 jwcode
func GetJwcodeJSON(token string) (int, error) { // 返回类型为 int func GetJwcodeJSON(token string) (int, error) { // 返回类型为 int
ctx := gctx.New()
//ctx := gctx.New()
// 1. 获取基础 URL // 1. 获取基础 URL
urlResult := getUrl(consts.URL_KEY, consts.URL_HASH_KEY) urlResult := getUrl(consts.URL_KEY, consts.URL_HASH_KEY)
if urlResult.Code != 200 { if urlResult.Code != 200 {
g.Log().Errorf(ctx, "获取基础 URL 失败: %s", urlResult.Message)
//g.Log().Errorf(ctx, "获取基础 URL 失败: %s", urlResult.Message)
return 0, errors.New("获取基础 URL 失败: " + urlResult.Message) return 0, errors.New("获取基础 URL 失败: " + urlResult.Message)
} }
baseUrl := urlResult.Data.(string) baseUrl := urlResult.Data.(string)
g.Log().Debugf(ctx, "成功获取基础 URL: %s", baseUrl)
//g.Log().Debugf(ctx, "成功获取基础 URL: %s", baseUrl)
// 2. 拼接完整的 URL // 2. 拼接完整的 URL
url := baseUrl + "/api/v2/member/info" url := baseUrl + "/api/v2/member/info"
@ -81,7 +81,7 @@ func GetJwcodeJSON(token string) (int, error) { // 返回类型为 int
// 3. 创建 HTTP 请求 // 3. 创建 HTTP 请求
req, err := http.NewRequest("POST", url, requestBody) req, err := http.NewRequest("POST", url, requestBody)
if err != nil { if err != nil {
g.Log().Errorf(ctx, "HTTP 请求创建失败: %v", err)
//g.Log().Errorf(ctx, "HTTP 请求创建失败: %v", err)
return 0, fmt.Errorf("HTTP 请求创建失败: %w", err) return 0, fmt.Errorf("HTTP 请求创建失败: %w", err)
} }
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
@ -90,37 +90,37 @@ func GetJwcodeJSON(token string) (int, error) { // 返回类型为 int
client := &http.Client{} client := &http.Client{}
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
g.Log().Errorf(ctx, "HTTP 请求失败: %v", err)
//g.Log().Errorf(ctx, "HTTP 请求失败: %v", err)
return 0, fmt.Errorf("HTTP 请求失败: %w", err) return 0, fmt.Errorf("HTTP 请求失败: %w", err)
} }
defer resp.Body.Close() defer resp.Body.Close()
// 5. 检查 HTTP 状态码 // 5. 检查 HTTP 状态码
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
g.Log().Errorf(ctx, "HTTP 状态码错误: %d", resp.StatusCode)
//g.Log().Errorf(ctx, "HTTP 状态码错误: %d", resp.StatusCode)
return 0, fmt.Errorf("HTTP 状态码错误: %d", resp.StatusCode) return 0, fmt.Errorf("HTTP 状态码错误: %d", resp.StatusCode)
} }
// 6. 读取并解析响应体 // 6. 读取并解析响应体
body, err := ioutil.ReadAll(resp.Body) body, err := ioutil.ReadAll(resp.Body)
if err != nil { if err != nil {
g.Log().Errorf(ctx, "读取响应失败: %v", err)
//g.Log().Errorf(ctx, "读取响应失败: %v", err)
return 0, fmt.Errorf("读取响应失败: %w", err) return 0, fmt.Errorf("读取响应失败: %w", err)
} }
g.Log().Debugf(ctx, "响应体内容: %s", string(body))
//g.Log().Debugf(ctx, "响应体内容: %s", string(body))
// 7. 解析 JSON 数据 // 7. 解析 JSON 数据
var jsonResponse map[string]interface{} var jsonResponse map[string]interface{}
if err = json.Unmarshal(body, &jsonResponse); err != nil { if err = json.Unmarshal(body, &jsonResponse); err != nil {
g.Log().Errorf(ctx, "解析 JSON 失败: %v", err)
//g.Log().Errorf(ctx, "解析 JSON 失败: %v", err)
return 0, fmt.Errorf("解析 JSON 失败: %w", err) return 0, fmt.Errorf("解析 JSON 失败: %w", err)
} }
g.Log().Debugf(ctx, "解析后的 JSON: %+v", jsonResponse)
//g.Log().Debugf(ctx, "解析后的 JSON: %+v", jsonResponse)
// 8. 提取 data 节点 // 8. 提取 data 节点
data, ok := jsonResponse["data"].(map[string]interface{}) data, ok := jsonResponse["data"].(map[string]interface{})
if !ok { if !ok {
g.Log().Errorf(ctx, "响应体中没有 data 节点,完整响应: %+v", jsonResponse)
//g.Log().Errorf(ctx, "响应体中没有 data 节点,完整响应: %+v", jsonResponse)
return 0, errors.New("响应体中没有 data 节点") return 0, errors.New("响应体中没有 data 节点")
} }
@ -129,14 +129,14 @@ func GetJwcodeJSON(token string) (int, error) { // 返回类型为 int
if ok { if ok {
jwcodeInt, err := strconv.Atoi(jwcode) // 将字符串转换为整数 jwcodeInt, err := strconv.Atoi(jwcode) // 将字符串转换为整数
if err != nil { if err != nil {
g.Log().Errorf(ctx, "解析 jwcode 字段失败: %v", err)
//g.Log().Errorf(ctx, "解析 jwcode 字段失败: %v", err)
return 0, fmt.Errorf("解析 jwcode 字段失败: %w", err) return 0, fmt.Errorf("解析 jwcode 字段失败: %w", err)
} }
g.Log().Infof(ctx, "成功获取 jwcode: %d", jwcodeInt)
//g.Log().Infof(ctx, "成功获取 jwcode: %d", jwcodeInt)
return jwcodeInt, nil return jwcodeInt, nil
} }
// 如果 jwcode 不是字符串,记录错误日志 // 如果 jwcode 不是字符串,记录错误日志
g.Log().Errorf(ctx, "data 节点中没有 jwcode 字段,或字段格式不正确,data: %+v", data)
//g.Log().Errorf(ctx, "data 节点中没有 jwcode 字段,或字段格式不正确,data: %+v", data)
return 0, errors.New("响应体中没有有效的 jwcode 字段") return 0, errors.New("响应体中没有有效的 jwcode 字段")
} }
Loading…
Cancel
Save