From f91c79e9a0ea18e72c4b91f6e739bfd19d244c41 Mon Sep 17 00:00:00 2001 From: lijikun Date: Tue, 31 Dec 2024 17:07:20 +0800 Subject: [PATCH 1/3] =?UTF-8?q?12.31=E6=97=A5,=E5=B0=86=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E7=94=A8=E6=88=B7jwcode=E5=B9=B6=E5=9B=9E=E6=98=BE=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E7=9B=B4=E6=8E=A5=E5=AF=BC=E5=85=A5=E5=B9=B6=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0=EF=BC=8C=E4=BB=A5=E5=8F=8A=E4=BC=A0=E5=88=B0=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=E4=B8=80=E4=B8=AA=E6=95=B0=E7=BB=84=E5=B9=B6=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0=E4=B8=A4=E4=B8=AA=E6=8E=A5=E5=8F=A3,=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E6=9C=AA=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/v1/couponusers/couponUsers.go | 23 ++++++++++-- internal/cmd/cmd.go | 13 ++++--- internal/controller/couponusers/couponUsers.go | 31 ++++++++++++----- internal/logic/couponusers/couponUsers.go | 48 ++++++++++++++++++++++---- internal/service/couponusers.go | 6 ++-- 5 files changed, 98 insertions(+), 23 deletions(-) diff --git a/api/v1/couponusers/couponUsers.go b/api/v1/couponusers/couponUsers.go index d205dcd..720f00c 100644 --- a/api/v1/couponusers/couponUsers.go +++ b/api/v1/couponusers/couponUsers.go @@ -1,5 +1,6 @@ package couponusers +// GetCouponUsersReq 查询卡券用户 type GetCouponUsersReq struct { CouponId int `json:"couponId" v:"required#卡券id不能为空" dc:"卡券id"` Jwcode int `json:"jwcode" dc:"查询条件中的精网号"` @@ -8,6 +9,7 @@ type GetCouponUsersReq struct { PageSize int `json:"pageSize" v:"required#分页信息不能为空" dc:"每页数量"` } +// GetCouponUsersRes 查询卡券用户 type GetCouponUsersRes struct { Name string `json:"name" dc:"姓名"` Jwcode int `json:"jwcode" dc:"精网号"` @@ -15,24 +17,41 @@ type GetCouponUsersRes struct { ShopName string `json:"shopName" dc:"门店"` } +// DelCouponUserByJwcodeReq 删除卡券用户 type DelCouponUserByJwcodeReq struct { CouponId int `json:"couponId" v:"required#卡券id不能为空" dc:"卡券id"` Jwcode int `json:"jwcode" v:"required#精网号不能为空" dc:"精网号"` } +// InsertCouponUserReq 给多个用户发放卡券 导入excel type InsertCouponUserReq struct { - CouponId int `json:"couponId" v:"required#卡券id不能为空" dc:"卡券id"` - Jwcodes []int `json:"jwcodes" v:"required#精网号不能为空" dc:"精网号"` + CouponId int `json:"couponId" v:"required#卡券id不能为空" dc:"卡券id"` + //Jwcodes []int `json:"jwcodes" v:"required#精网号不能为空" dc:"精网号"` +} + +// InsertCouponUserByJwcodeStrReq 给多个用户发放卡券 传jwcodes字符串 +type InsertCouponUserByJwcodeStrReq struct { + CouponId int `json:"couponId" v:"required#卡券id不能为空" dc:"卡券id"` + Jwcodes string `json:"jwcodes" v:"required#精网号不能为空" dc:"精网号"` } +// IssueCouponUserReq 给单个用户发放卡券 type IssueCouponUserReq struct { CouponId int `json:"couponId" v:"required#卡券id不能为空" dc:"卡券id"` } +// IsEligibleUserReq 检测用户是否有抽取资格,是否已抽取 type IsEligibleUserReq struct { CouponIds []int `json:"couponIds" v:"required#用于检测是否已抽取,不能为空" dc:"能抽出的卡券id"` } +// AddRecordReq 添加武器 +type AddRecordReq struct { + CouponId int `json:"couponId" dc:"卡券id"` + Name string `json:"name" dc:"选择武器名称"` +} + +// InsertCouponUserRes 判断能否抽取卡券,给单个用户发放卡券 用于存放满足条件的精网号 type InsertCouponUserRes struct { Jwcode int `json:"jwcode" dc:"精网号"` } diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index 36c557d..85491f2 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -19,10 +19,15 @@ var ( s := g.Server() s.Group("/api/coupon_backend", func(group *ghttp.RouterGroup) { group.Middleware(middleware.MiddlewareCORS) - group.POST("/get-coupon-users", couponusers.NewCouponUsers().GetCouponUsers) // 获取拥有卡券的用户列表 - group.POST("/delete-coupon-user", couponusers.NewCouponUsers().DeleteCouponUserByJwcode) //删除用户卡券 - group.POST("/import-excel", couponusers.NewCouponUsers().InsertJwcodeByExcel) // 通过excel导入jwcode - group.POST("/insert-coupon-user", couponusers.NewCouponUsers().InsertCouponUser) //给用户发放卡券 + //group.POST("/get-coupon-users", couponusers.NewCouponUsers().GetCouponUsers) // 获取拥有卡券的用户列表 + //group.POST("/delete-coupon-user", couponusers.NewCouponUsers().DeleteCouponUserByJwcode) //删除用户卡券 + //group.POST("/import-excel", couponusers.NewCouponUsers().InsertJwcodeByExcel) // 通过excel导入jwcode + //group.POST("/insert-coupon-user", couponusers.NewCouponUsers().InsertCouponUser) //给用户发放卡券 + group.POST("/get-coupon-users", couponusers.NewCouponUsers().GetCouponUsers) // 获取拥有卡券的用户列表 + group.POST("/delete-coupon-user", couponusers.NewCouponUsers().DeleteCouponUserByJwcode) //删除用户卡券 + group.POST("/insert-coupon-users-by-excel", couponusers.NewCouponUsers().InsertCouponUserByExcel) // 通过excel导入jwcode并发放卡券 + //group.POST("/insert-coupon-user", couponusers.NewCouponUsers().InsertCouponUser) //给用户发放卡券 + group.POST("/insert-coupon-users-by-str", couponusers.NewCouponUsers().InsertCouponUserByJwcodeStr) //通过jwcodes字符串导入jwcode并发放卡券 //近期使用 group.POST("/insert-users-to-redis", couponusers.NewCouponUsers().InsertJwcodesToRedisByExcel) //导入满足条件的用户jwcode到redis group.POST("/is-eligible-user", couponusers.NewCouponUsers().IsEligibleUser) //判断用户是否满足领取条件 diff --git a/internal/controller/couponusers/couponUsers.go b/internal/controller/couponusers/couponUsers.go index 702b42f..46a3070 100644 --- a/internal/controller/couponusers/couponUsers.go +++ b/internal/controller/couponusers/couponUsers.go @@ -60,7 +60,14 @@ func (c *CouponUsers) DeleteCouponUserByJwcode(r *ghttp.Request) { } // 接受前端传来的excel表格,并解析,返回jwcode切片,可以有重复的,在插入时进行验证,如果有重复的,只插入一次 -func (c *CouponUsers) InsertJwcodeByExcel(r *ghttp.Request) { +func (c *CouponUsers) InsertCouponUserByExcel(r *ghttp.Request) { + /*解析请求*/ + var req *couponusers.InsertCouponUserReq + if err := r.Parse(&req); err != nil { + r.Response.WriteJsonExit(dto.Error(err.Error())) + } + /*解析请求*/ + // 从请求中获取文件 file, _, err := r.FormFile("excelFile") if err != nil { @@ -80,24 +87,32 @@ func (c *CouponUsers) InsertJwcodeByExcel(r *ghttp.Request) { r.Response.WriteJsonExit(dto.Error("获取的文件为空")) } - jwcodes, err := service.CouponUsers().InsertJwcodeByExcel(file) + /*调用方法解析excel文件,并将解析出结果传入另一个函数去发放卡券*/ + result, err := service.CouponUsers().InsertJwcodeByExcel(r.Context(), file, req.CouponId) + //错误处理 if err != nil { r.Response.WriteJsonExit(dto.Error(err.Error())) } + //没报错,但插入数据0条 + if result == 0 { + r.Response.WriteJsonExit(dto.Error("发放失败,发放了0人")) + } //成功处理 - r.Response.WriteJsonExit(dto.SuccessWithData(jwcodes)) + r.Response.WriteJsonExit(dto.SuccessWithMsg(fmt.Sprintf("发放成功,发放了%d人", result))) + /*调用方法解析excel文件,并将解析出结果传入另一个函数去发放卡券*/ } -// 给用户发放卡券 -func (c *CouponUsers) InsertCouponUser(r *ghttp.Request) { +// 传入jwcodes字符串,解析并发放卡券 +func (c *CouponUsers) InsertCouponUserByJwcodeStr(r *ghttp.Request) { // 解析请求 - var req *couponusers.InsertCouponUserReq + var req *couponusers.InsertCouponUserByJwcodeStrReq if err := r.Parse(&req); err != nil { r.Response.WriteJsonExit(dto.Error(err.Error())) } - result, err := service.CouponUsers().InsertCouponUsersByJwcodes(r.Context(), req.Jwcodes, req.CouponId) + result, err := service.CouponUsers().InsertCouponUsersByJwcodeStr(r.Context(), req.Jwcodes, req.CouponId) + //错误处理 if err != nil { r.Response.WriteJsonExit(dto.Error(err.Error())) @@ -111,7 +126,7 @@ func (c *CouponUsers) InsertCouponUser(r *ghttp.Request) { } /*近期使用*/ -// 导入满足条件的用户jwcode到redis +// 导入满足条件的用户jwcode到redis //不导入到redis了,导入到数据库表中 func (c *CouponUsers) InsertJwcodesToRedisByExcel(r *ghttp.Request) { // 从请求中获取文件 file, _, err := r.FormFile("EligibleJwcodesExcel") diff --git a/internal/logic/couponusers/couponUsers.go b/internal/logic/couponusers/couponUsers.go index 35ca174..ab64668 100644 --- a/internal/logic/couponusers/couponUsers.go +++ b/internal/logic/couponusers/couponUsers.go @@ -109,11 +109,13 @@ func (s *sCouponUsers) DeleteCouponUserByJwcode(ctx context.Context, couponId, j } // 通过excel导入精网号 -func (s *sCouponUsers) InsertJwcodeByExcel(file multipart.File) (jwcodes []int, err error) { +func (s *sCouponUsers) InsertJwcodeByExcel(ctx context.Context, file multipart.File, couponId int) (num int, err error) { + // func (s *sCouponUsers) InsertJwcodeByExcel(file multipart.File) (jwcodes []int, err error) { + //打开文件并返回一个excelize.File对象,用于读取和操作Excel文件的内容 f, err := excelize.OpenReader(file) if err != nil { - return nil, errors.New("打开文件失败") + return 0, errors.New("打开文件失败") } // 延时关闭文件 defer func(f *excelize.File) { @@ -126,15 +128,16 @@ func (s *sCouponUsers) InsertJwcodeByExcel(file multipart.File) (jwcodes []int, //读取所有工作表名称 GetSheetMap := f.GetSheetMap() if len(GetSheetMap) == 0 { - return nil, errors.New("没有工作表") + return 0, errors.New("没有工作表") } rows, err := f.GetRows("Sheet1") if err != nil { - return nil, err + return 0, err } // 将每行的第一列转换为int,并添加到切片中 + var jwcodes []int for i, row := range rows { //跳过第一行 if i == 0 { @@ -154,15 +157,46 @@ func (s *sCouponUsers) InsertJwcodeByExcel(file multipart.File) (jwcodes []int, //将字符串转换为整数 jwcode, err := strconv.Atoi(jwcodeStr) if err != nil { - return nil, errors.New("参数转换失败") + return 0, errors.New("参数转换失败") } jwcodes = append(jwcodes, jwcode) /*参数校验*/ } - return //返回jwcodes切片 + + /*给用户发放卡券*/ + num, err = s.InsertCouponUsersByJwcodes(ctx, jwcodes, couponId) + /*给用户发放卡券*/ + + //return //返回jwcodes切片 + return num, err +} + +// 传来jwcodes字符串,解析并发放卡券 +func (s *sCouponUsers) InsertCouponUsersByJwcodeStr(ctx context.Context, jwcodeStr string, couponId int) (num int, err error) { + //将字符串转换为切片 + jwcodes := strings.Split(jwcodeStr, ",") + //转换成int + var jwcodesInt []int + for _, jwcode := range jwcodes { + //参数校验,检查jwcode是否为非空字符串 + if jwcode == "" { + continue + } + jwcodeInt, err := strconv.Atoi(jwcode) + if err != nil { + return 0, errors.New("参数转换失败") + } + jwcodesInt = append(jwcodesInt, jwcodeInt) + } + + /*给用户发放卡券*/ + num, err = s.InsertCouponUsersByJwcodes(ctx, jwcodesInt, couponId) + /*给用户发放卡券*/ + + return } -// 根据精网号发放用户优惠券 +// 根据精网号发放用户优惠券,群发 //不被controller层调用了,但不能删除 func (s *sCouponUsers) InsertCouponUsersByJwcodes(ctx context.Context, jwcodes []int, couponId int) (num int, err error) { //去重 m := make(map[int]bool) diff --git a/internal/service/couponusers.go b/internal/service/couponusers.go index 39a65ec..16abb7d 100644 --- a/internal/service/couponusers.go +++ b/internal/service/couponusers.go @@ -19,8 +19,10 @@ type ( // 根据jwcode,优惠券id删除用户 DeleteCouponUserByJwcode(ctx context.Context, couponId int, jwcode int) (result sql.Result, err error) // 通过excel导入精网号 - InsertJwcodeByExcel(file multipart.File) (jwcodes []int, err error) - // 根据精网号发放用户优惠券 + InsertJwcodeByExcel(ctx context.Context, file multipart.File, couponId int) (num int, err error) + // 传来jwcodes字符串,解析并发放卡券 + InsertCouponUsersByJwcodeStr(ctx context.Context, jwcodeStr string, couponId int) (num int, err error) + // 根据精网号发放用户优惠券,群发 //不被controller层调用了,但不能删除 InsertCouponUsersByJwcodes(ctx context.Context, jwcodes []int, couponId int) (num int, err error) // 导入满足条件的用户jwcode到redis //不上传到redis了,上传到数据库表,到时候直接从表里查 InsertJwcodesToRedisByExcel(file multipart.File) (err error) From b46556d4ea0a137f022e7ede604defd12180d423 Mon Sep 17 00:00:00 2001 From: lijikun Date: Tue, 31 Dec 2024 18:55:13 +0800 Subject: [PATCH 2/3] =?UTF-8?q?12.31=E6=97=A5,=E5=88=A0=E9=99=A4=E6=89=93?= =?UTF-8?q?=E5=8D=B0=E6=97=A5=E5=BF=97,=E5=AF=BC=E5=87=BAexcel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/controller/couponusers/couponUsers.go | 5 ++- internal/logic/couponusers/couponUsers.go | 54 +++++++++++++++++++++++++- internal/service/couponusers.go | 4 +- 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/internal/controller/couponusers/couponUsers.go b/internal/controller/couponusers/couponUsers.go index 46a3070..eb8a398 100644 --- a/internal/controller/couponusers/couponUsers.go +++ b/internal/controller/couponusers/couponUsers.go @@ -165,7 +165,6 @@ func (c *CouponUsers) IsEligibleUser(r *ghttp.Request) { if err := r.Parse(&req); err != nil { r.Response.WriteJsonExit(dto.Error(err.Error())) } - fmt.Println(req.CouponIds) /*解析token,获取jwcode*/ token := r.Header.Get("token") @@ -225,9 +224,11 @@ func (c *CouponUsers) IssueCouponUser(r *ghttp.Request) { // 导出拥有卡券的用户 func (c *CouponUsers) ExportCouponUsers(r *ghttp.Request) { var req *couponusers.GetCouponUsersReq + // 解析请求参数 if err := r.Parse(&req); err != nil { r.Response.WriteJsonExit(dto.Error(err.Error())) } - //查询数据,创建excel文件,设置表头,写入数据,设置文件名,保存到缓冲区并返回,设置响应头,指定内容类型为excel文件,指定文件名为fileName,将buffer中的内容写入到响应 + //查询数据,创建excel文件,设置表头,写入数据,设置文件名,保存到缓冲区并返回,设置响应头,指定内容类型为excel文件,指定文件名为fileName,将buffer中的内容写入响应 + service.CouponUsers().ExportCouponUsers(r, req.CouponId, req.Jwcode, req.Name, req.PageNo, req.PageSize) } diff --git a/internal/logic/couponusers/couponUsers.go b/internal/logic/couponusers/couponUsers.go index ab64668..6c49180 100644 --- a/internal/logic/couponusers/couponUsers.go +++ b/internal/logic/couponusers/couponUsers.go @@ -3,16 +3,19 @@ package couponusers import ( "CouponBackendGo/api/v1/couponusers" "CouponBackendGo/internal/dao" + "CouponBackendGo/internal/model/dto" "CouponBackendGo/internal/service" "context" "database/sql" "errors" "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/os/gtime" "github.com/xuri/excelize/v2" "mime/multipart" "strconv" "strings" + "time" ) type sCouponUsers struct{} @@ -386,6 +389,55 @@ func (s *sCouponUsers) IssueCouponToUser(ctx context.Context, jwcode, couponId i /*未编写*/ // 导出拥有卡券的用户列表 -func (s *sCouponUsers) ExportCouponUsers() { +func (s *sCouponUsers) ExportCouponUsers(r *ghttp.Request, couponId, jwcode int, name string, pageNo, pageSize int) { + //调用查询 + users, err := s.GetCouponUsersByCondition(r.Context(), couponId, jwcode, name, pageNo, pageSize) + if err != nil { + r.Response.WriteJsonExit(dto.Error("查询失败:" + err.Error())) + return + } + if len(users) == 0 { + r.Response.WriteJsonExit(dto.Error("查询结果为空")) + return + } + + //创建 Excel文件 + excelFile := excelize.NewFile() //默认会创建一个Sheet1 + sheetName := "Sheet1" + //设置表头 + headers := []string{"序号", "精网号", "姓名", "部门", "门店"} + for i, header := range headers { + col := string('A' + i) //将索引转换为 Excel列名 + excelFile.SetCellValue(sheetName, col+"1", header) + } + + /*写入数据*/ + rowIndex := 2 //从第二行开始写入数据 + for _, user := range users { + excelFile.SetCellValue(sheetName, "A"+strconv.Itoa(rowIndex), rowIndex-1) //序号 + excelFile.SetCellValue(sheetName, "B"+strconv.Itoa(rowIndex), user.Jwcode) //精网号 + excelFile.SetCellValue(sheetName, "C"+strconv.Itoa(rowIndex), user.Name) //姓名 + excelFile.SetCellValue(sheetName, "D"+strconv.Itoa(rowIndex), user.DeptName) //部门 + excelFile.SetCellValue(sheetName, "E"+strconv.Itoa(rowIndex), user.ShopName) //门店 + rowIndex++ + } + /*写入数据*/ + + //设置文件名 + fileName := "Users_" + time.Now().Format("20060102150405") + ".xlsx" + + //保存到缓冲区并返回 + buffer, err := excelFile.WriteToBuffer() + if err != nil { + r.Response.WriteJsonExit(dto.Error("生成Excel文件失败:" + err.Error())) + return + } + + // 设置响应头,指定内容类型为Excel文件 + r.Response.Header().Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") + // 设置响应头,指定文件名为fileName + r.Response.Header().Set("Content-Disposition", "attachment; filename="+fileName) + // 将buffer中的内容写入响应 + r.Response.Write(buffer.Bytes()) } diff --git a/internal/service/couponusers.go b/internal/service/couponusers.go index 16abb7d..3768a9e 100644 --- a/internal/service/couponusers.go +++ b/internal/service/couponusers.go @@ -10,6 +10,8 @@ import ( "context" "database/sql" "mime/multipart" + + "github.com/gogf/gf/v2/net/ghttp" ) type ( @@ -32,7 +34,7 @@ type ( IssueCouponToUser(ctx context.Context, jwcode int, couponId int) (err error) /*未编写*/ // 导出拥有卡券的用户列表 - ExportCouponUsers() + ExportCouponUsers(r *ghttp.Request, couponId int, jwcode int, name string, pageNo int, pageSize int) } ) From 589e8ad8282eafd82c73bdac0faf1b9308412d2c Mon Sep 17 00:00:00 2001 From: lijikun Date: Tue, 31 Dec 2024 19:31:15 +0800 Subject: [PATCH 3/3] =?UTF-8?q?12.31=E6=97=A5,=E5=88=A0=E9=99=A4=E6=89=93?= =?UTF-8?q?=E5=8D=B0=E6=97=A5=E5=BF=97,=E5=AF=BC=E5=87=BAexcel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/cmd/cmd.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index 85491f2..916cd4b 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -28,6 +28,7 @@ var ( group.POST("/insert-coupon-users-by-excel", couponusers.NewCouponUsers().InsertCouponUserByExcel) // 通过excel导入jwcode并发放卡券 //group.POST("/insert-coupon-user", couponusers.NewCouponUsers().InsertCouponUser) //给用户发放卡券 group.POST("/insert-coupon-users-by-str", couponusers.NewCouponUsers().InsertCouponUserByJwcodeStr) //通过jwcodes字符串导入jwcode并发放卡券 + group.POST("export-coupon-users", couponusers.NewCouponUsers().ExportCouponUsers) //导出拥有卡券的用户列表 //近期使用 group.POST("/insert-users-to-redis", couponusers.NewCouponUsers().InsertJwcodesToRedisByExcel) //导入满足条件的用户jwcode到redis group.POST("/is-eligible-user", couponusers.NewCouponUsers().IsEligibleUser) //判断用户是否满足领取条件