From e6ef2aa659945eb223a87b7b6f68043bbae1c974 Mon Sep 17 00:00:00 2001 From: dhy <1452562016@qq.com> Date: Thu, 19 Dec 2024 10:27:40 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A0=B9=E6=8D=AEid=E5=AF=BC=E5=87=BA=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E7=9A=84=E4=BD=9C=E7=AD=94=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- link_homework/go.mod | 8 ++ link_homework/go.sum | 21 ++++- link_homework/internal/cmd/cmd.go | 2 + link_homework/internal/controller/record/export.go | 91 ++++++++++++++++++++++ 4 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 link_homework/internal/controller/record/export.go diff --git a/link_homework/go.mod b/link_homework/go.mod index f524a4a..083f87f 100644 --- a/link_homework/go.mod +++ b/link_homework/go.mod @@ -3,10 +3,12 @@ module link_homework go 1.21.13 require ( + github.com/360EntSecGroup-Skylar/excelize v1.4.1 github.com/gogf/gf/contrib/drivers/mysql/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/golang-jwt/jwt/v4 v4.5.1 + github.com/xuri/excelize/v2 v2.9.0 ) require ( @@ -26,13 +28,19 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/olekukonko/tablewriter v0.0.5 // 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/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/metric v1.24.0 // indirect go.opentelemetry.io/otel/sdk 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/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect diff --git a/link_homework/go.sum b/link_homework/go.sum index 4654ea2..4f13b90 100644 --- a/link_homework/go.sum +++ b/link_homework/go.sum @@ -1,4 +1,5 @@ -github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/360EntSecGroup-Skylar/excelize v1.4.1 h1:l55mJb6rkkaUzOpSsgEeKYtS6/0gHwBYyfo5Jcjv/Ks= +github.com/360EntSecGroup-Skylar/excelize v1.4.1/go.mod h1:vnax29X2usfl7HHkBrX5EvSCJcmH3dT9luvxzu8iGAE= github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= @@ -50,17 +51,31 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= 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/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 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/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.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= 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.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= 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/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= @@ -69,6 +84,10 @@ 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/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= 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/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/link_homework/internal/cmd/cmd.go b/link_homework/internal/cmd/cmd.go index 169917a..a7c3a17 100644 --- a/link_homework/internal/cmd/cmd.go +++ b/link_homework/internal/cmd/cmd.go @@ -43,6 +43,8 @@ var ( group.POST("/edit-homework", homework.Homework().EditHomework) group.ALL("/get-article-list", article.Article().GetArticleList) group.ALL("/get-live-list", live.Live().GetLiveList) + //导出excel + group.ALL("/export-record", record.NewExportRecord().ExportRecordByCondition) }) //客户端 s.Group("/api/homework_client", func(group *ghttp.RouterGroup) { diff --git a/link_homework/internal/controller/record/export.go b/link_homework/internal/controller/record/export.go new file mode 100644 index 0000000..8be353f --- /dev/null +++ b/link_homework/internal/controller/record/export.go @@ -0,0 +1,91 @@ +package record + +import ( + "github.com/360EntSecGroup-Skylar/excelize" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/ghttp" + "link_homework/api/v1/record" + "link_homework/internal/model/dto" + "link_homework/internal/service" + "strconv" + "time" +) + +// ManageRecord 处理记录的相关操作 +type ExportRecord struct{} + +func NewExportRecord() *ExportRecord { + return &ExportRecord{} +} + +// ExportRecordByCondition 导出记录 +func (m *ExportRecord) ExportRecordByCondition(r *ghttp.Request) { + var req record.GetRecordByConditionReq + // 解析查询条件 + if err := r.Parse(&req); err != nil { + r.Response.WriteJsonExit(dto.Error("参数解析失败: " + err.Error())) + return + } + + // 调用查询服务 + records, err := service.Record().GetRecordByCondition( + r.Context(), + req.Id, req.Jwcode, req.DeptId, req.ShopId, req.PageNo, req.PageSize, + ) + if err != nil { + g.Log().Error(r.Context(), "查询记录失败: ", err) + r.Response.WriteJsonExit(dto.Error("查询记录失败: " + err.Error())) + return + } + + if len(records) == 0 { + g.Log().Warning(r.Context(), "查询结果为空: 参数 = ", req) + r.Response.WriteJsonExit(dto.Error("查询结果为空")) + return + } + // 创建 Excel 文件 + excelFile := excelize.NewFile() // 默认会创建一个 Sheet1 + sheetName := "Sheet1" // 使用默认的 Sheet1 + + // 设置表头 + headers := []string{"序号", "精网号", "名字", "部门ID", "部门名称", "门店ID", "门店名称", "题目ID", "题目类型", "题目名称", "简答题标题", "作答内容", "提交时间"} + for i, header := range headers { + col := string('A' + i) // 将索引转换为 Excel 列名 + excelFile.SetCellValue(sheetName, col+"1", header) + } + + // 写入数据 + 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++ + } + } + + // 设置文件名 + fileName := "Records_" + time.Now().Format("20060102150405") + ".xlsx" + + // 保存到缓冲区并返回 + buffer, err := excelFile.WriteToBuffer() + if err != nil { + r.Response.WriteJsonExit(dto.Error("生成 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()) +}