diff --git a/api/v1/.gitkeep b/api/v1/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/api/v1/coupon/coupon.go b/api/v1/coupon/coupon.go new file mode 100644 index 0000000..fa36d49 --- /dev/null +++ b/api/v1/coupon/coupon.go @@ -0,0 +1,24 @@ +package coupon + +import "github.com/gogf/gf/v2/os/gtime" + +type GetCouponListReq struct { + PageNo int `v:"required#页码不能为空" dc:"页码"` + PageSize int `v:"required#页面大小不能为空" dc:"页面大小"` +} + +type GetCouponReq struct { + Id int `v:"required#优惠券id不能为空" dc:"优惠券id"` +} + +type DeleteCouponReq struct { + Id int `v:"required#优惠券id不能为空" dc:"优惠券id"` +} + +type InsertCouponReq struct { + Id int `dc:"优惠券id"` + Title string `v:"required#优惠券名字不能为空" dc:"优惠券名字"` + Image string `v:"required#优惠券图片不能为空" dc:"优惠券图片"` + StartTime *gtime.Time `v:"required#优惠券生效时间不能为空" dc:"生效时间"` + EndTime *gtime.Time `v:"required#优惠券失效时间不能为空" dc:"失效时间"` +} diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index fd9dbba..41afd81 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -1,6 +1,7 @@ package cmd import ( + "CouponBackendGo/internal/controller/coupon" "CouponBackendGo/internal/controller/couponusers" "CouponBackendGo/internal/logic/middleware" "context" @@ -28,6 +29,10 @@ var ( group.POST("/is-eligible-user", couponusers.NewCouponUsers().IsEligibleUser) //判断用户是否满足领取条件 group.POST("/issue-coupon-to-users", couponusers.NewCouponUsers().IssueCouponUser) //给单个用户发放卡券 group.POST("/add-record", couponusers.NewCouponUsers().AddRecord) //添加用户选择武器记录 + group.POST("/get-coupon-list", coupon.Coupon().GetCouponList) //获取卡券列表 + group.POST("/get-coupon", coupon.Coupon().GetCoupon) //获取卡券 + group.POST("/delete-coupon", coupon.Coupon().DeleteCoupon) //删除卡券 + group.POST("/insert-coupon", coupon.Coupon().InsertCoupon) //添加卡券 }) s.Run() return nil diff --git a/internal/controller/.gitkeep b/internal/controller/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/internal/controller/coupon/coupon.go b/internal/controller/coupon/coupon.go new file mode 100644 index 0000000..8c544b4 --- /dev/null +++ b/internal/controller/coupon/coupon.go @@ -0,0 +1,105 @@ +package coupon + +import ( + "CouponBackendGo/api/v1/coupon" + "CouponBackendGo/internal/model/dto" + "CouponBackendGo/internal/service" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/ghttp" +) + +type cCoupon struct{} + +func Coupon() *cCoupon { + return &cCoupon{} +} + +func (c cCoupon) GetCouponList(r *ghttp.Request) { + var req *coupon.GetCouponListReq + if err := r.Parse(&req); err != nil { + r.Response.WriteJsonExit(dto.Result{ + Code: 400, + Message: err.Error(), + }) + } + res, err := service.Coupon().GetCouponList(r.Context(), req.PageNo, req.PageSize) + total, err := service.Coupon().GetCouponListTotal(r.Context()) + if err != nil { + r.Response.WriteJsonExit(dto.Result{ + Code: 400, + Message: err.Error(), + }) + } + r.Response.WriteJsonExit(dto.Result{ + Code: 200, + Message: "success", + Data: g.Map{ + "list": res, + "total": total, + }, + }) +} + +func (c cCoupon) GetCoupon(r *ghttp.Request) { + var req *coupon.GetCouponReq + if err := r.Parse(&req); err != nil { + r.Response.WriteJsonExit(dto.Result{ + Code: 400, + Message: err.Error(), + }) + } + res, err := service.Coupon().GetCoupon(r.Context(), req.Id) + if err != nil { + r.Response.WriteJsonExit(dto.Result{ + Code: 400, + Message: err.Error(), + }) + } + r.Response.WriteJsonExit(dto.Result{ + Code: 200, + Message: "success", + Data: res, + }) +} + +func (c cCoupon) DeleteCoupon(r *ghttp.Request) { + var req *coupon.DeleteCouponReq + if err := r.Parse(&req); err != nil { + r.Response.WriteJsonExit(dto.Result{ + Code: 400, + Message: err.Error(), + }) + } + err := service.Coupon().DeleteCoupon(r.Context(), req.Id) + if err != nil { + r.Response.WriteJsonExit(dto.Result{ + Code: 400, + Message: err.Error(), + }) + } + r.Response.WriteJsonExit(dto.Result{ + Code: 200, + Message: "success", + }) +} + +func (c cCoupon) InsertCoupon(r *ghttp.Request) { + var req *coupon.InsertCouponReq + if err := r.Parse(&req); err != nil { + r.Response.WriteJsonExit(dto.Result{ + Code: 400, + Message: err.Error(), + }) + } + err := service.Coupon().InsertCoupon(r.Context(), req) + if err != nil { + r.Response.WriteJsonExit(dto.Result{ + Code: 400, + Message: err.Error(), + }) + } + r.Response.WriteJsonExit(dto.Result{ + Code: 200, + Message: "success", + }) +} diff --git a/internal/dao/.gitkeep b/internal/dao/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/internal/logic/.gitkeep b/internal/logic/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/internal/logic/coupon/coupon.go b/internal/logic/coupon/coupon.go new file mode 100644 index 0000000..6d3f1d3 --- /dev/null +++ b/internal/logic/coupon/coupon.go @@ -0,0 +1,158 @@ +package coupon + +import ( + "CouponBackendGo/api/v1/coupon" + "CouponBackendGo/internal/dao" + "CouponBackendGo/internal/model/do" + "CouponBackendGo/internal/model/dto" + "CouponBackendGo/internal/service" + "context" + "encoding/json" + "fmt" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +type ( + sCoupon struct{} +) + +func init() { + service.RegisterCoupon(New()) +} + +func New() service.ICoupon { + return &sCoupon{} +} + +func (s *sCoupon) GetCouponList(ctx context.Context, pageNo int, pageSize int) (couponList []*dto.DtoCoupon, err error) { + // 从Redis中获取数据 + value, _ := g.Redis().Get(ctx, fmt.Sprintf("%d-%d couponlist", pageNo, pageSize)) + if value.String() != "" { + // 如果Redis中有数据,尝试解析为Coupon列表 + err = json.Unmarshal(value.Bytes(), &couponList) //反序列化 + couponlist, cnt := UpdateCoupon(ctx, couponList) + + if cnt > 0 { + // 将修改后的卡券列表序列化并存储到Redis,更新频繁变更的数据 + couponListJson, _ := json.Marshal(couponlist) + _, err = g.Redis().Set(ctx, fmt.Sprintf("%d-%d couponlist", pageNo, pageSize), couponListJson) + } + + if err != nil { + return nil, err + } + return couponlist, err + } + + // 如果Redis中没有数据,查询数据库 + err = dao.Coupon.Ctx(ctx).Where("deleted", 0).Order("updated_at desc, end_time desc").Page(pageNo, pageSize).Scan(&couponList) + couponList = InitCoupon(ctx, couponList) + couponList, _ = UpdateCoupon(ctx, couponList) + if err != nil { + return nil, err + } + + // 将查询到的卡券列表序列化并存储到Redis,更新频繁变更的数据 + couponListJson, _ := json.Marshal(couponList) + _, err = g.Redis().Set(ctx, fmt.Sprintf("%d-%d couponlist", pageNo, pageSize), couponListJson) + + return +} + +func InitCoupon(ctx context.Context, couponList []*dto.DtoCoupon) []*dto.DtoCoupon { + for _, v := range couponList { + v.Status = 0 //待使用期 + if v.StartTime.Unix() <= gtime.Now().Unix() { + if v.EndTime.Unix() <= gtime.Now().Unix() { + v.Status = 2 //使用期后 + v.Count, _ = dao.CouponUsers.Ctx(ctx).Where("coupon_id", v.Id).Count() + } else { + v.Status = 1 //使用期中 + } + } + } + return couponList +} + +func UpdateCoupon(ctx context.Context, couponList []*dto.DtoCoupon) ([]*dto.DtoCoupon, int) { + cnt := 0 + for _, v := range couponList { + if v.Status != 2 { + if v.StartTime.Unix() > gtime.Now().Unix() { + v.Status = 0 + } else if v.EndTime.Unix() <= gtime.Now().Unix() { + v.Status = 2 + cnt++ + } else { + v.Status = 1 + } + v.Count, _ = dao.CouponUsers.Ctx(ctx).Where("coupon_id", v.Id).Count() + } + } + return couponList, cnt +} + +func (s *sCoupon) GetCouponListTotal(ctx context.Context) (total int, err error) { + total, err = dao.Coupon.Ctx(ctx).Where("deleted", 0).Count() + if err != nil { + return 0, err + } + return +} + +func (s *sCoupon) GetCoupon(ctx context.Context, id int) (coupon *dto.DtoCoupon, err error) { + err = dao.Coupon.Ctx(ctx).WherePri(id).Scan(&coupon) + if err != nil { + return nil, err + } + return +} + +func (s *sCoupon) DeleteCoupon(ctx context.Context, id int) (err error) { + _, err = dao.Coupon.Ctx(ctx).Data(do.Coupon{ + Deleted: 1, + }).WherePri(id).Update() + if err != nil { + return err + } + + // 软删除数据后,删除所有缓存 + keys, err := g.Redis().Keys(ctx, "*-* couponlist") + if len(keys) > 0 { + _, err = g.Redis().Del(ctx, keys...) + } + + return +} + +func (s *sCoupon) InsertCoupon(ctx context.Context, req *coupon.InsertCouponReq) (err error) { + if req.Id == 0 { + _, err = dao.Coupon.Ctx(ctx).Data(do.Coupon{ + Title: req.Title, + Cover: req.Image, + ImgUrl: req.Image, + StartTime: req.StartTime.Unix(), + EndTime: req.EndTime.Unix(), + }).Insert() + } else { + _, err = dao.Coupon.Ctx(ctx).Data(do.Coupon{ + Title: req.Title, + Cover: req.Image, + ImgUrl: req.Image, + StartTime: req.StartTime.Unix(), + EndTime: req.EndTime.Unix(), + }).WherePri(req.Id).Update() + } + if err != nil { + return err + } + + // 新增&编辑数据后,删除所有缓存 + keys, err := g.Redis().Keys(ctx, "*-* couponlist") + if len(keys) > 0 { + _, err = g.Redis().Del(ctx, keys...) + } + + return +} diff --git a/internal/logic/logic.go b/internal/logic/logic.go index 18ff594..aeef37e 100644 --- a/internal/logic/logic.go +++ b/internal/logic/logic.go @@ -5,6 +5,7 @@ package logic import ( + _ "CouponBackendGo/internal/logic/coupon" _ "CouponBackendGo/internal/logic/couponusers" _ "CouponBackendGo/internal/logic/middleware" ) diff --git a/internal/model/.gitkeep b/internal/model/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/internal/model/do/.gitkeep b/internal/model/do/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/internal/model/dto/dto_coupon.go b/internal/model/dto/dto_coupon.go new file mode 100644 index 0000000..dad97df --- /dev/null +++ b/internal/model/dto/dto_coupon.go @@ -0,0 +1,15 @@ +package dto + +import "github.com/gogf/gf/v2/os/gtime" + +type DtoCoupon struct { + Id uint `json:"id" orm:"db:default;table:coupon;column:id" description:"ID"` // ID + Title string `json:"title" orm:"db:default;table:coupon;column:title" description:"名字"` // 名字 + Cover string `json:"cover" orm:"db:default;table:coupon;column:cover" description:"封面小图片"` // 封面小图片 + ImgUrl string `json:"imgUrl" orm:"db:default;table:coupon;column:img_url" description:"放大看全图"` // 放大看全图 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"db:default;table:coupon;column:updated_at" description:"更新时间"` // 更新时间 + StartTime *gtime.Time `json:"startTime" description:"有效期起始"` // 有效期起始 + EndTime *gtime.Time `json:"endTime" description:"有效期截止"` // 有效期截止 + Status int `json:"status" description:"卡券状态"` // 卡券状态 + Count int `json:"count" description:"持有人数"` // 持有人数 +} diff --git a/internal/model/entity/.gitkeep b/internal/model/entity/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/internal/service/.gitkeep b/internal/service/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/internal/service/coupon.go b/internal/service/coupon.go new file mode 100644 index 0000000..7c266bd --- /dev/null +++ b/internal/service/coupon.go @@ -0,0 +1,37 @@ +// ================================================================================ +// 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 ( + "CouponBackendGo/api/v1/coupon" + "CouponBackendGo/internal/model/dto" + "context" +) + +type ( + ICoupon interface { + GetCouponList(ctx context.Context, pageNo int, pageSize int) (couponList []*dto.DtoCoupon, err error) + GetCouponListTotal(ctx context.Context) (total int, err error) + GetCoupon(ctx context.Context, id int) (coupon *dto.DtoCoupon, err error) + DeleteCoupon(ctx context.Context, id int) (err error) + InsertCoupon(ctx context.Context, req *coupon.InsertCouponReq) (err error) + } +) + +var ( + localCoupon ICoupon +) + +func Coupon() ICoupon { + if localCoupon == nil { + panic("implement not found for interface ICoupon, forgot register?") + } + return localCoupon +} + +func RegisterCoupon(i ICoupon) { + localCoupon = i +}