From b8333ecaf8de8231e4e53f2540c928a20ec47c5b Mon Sep 17 00:00:00 2001 From: laodaming <11058467+laudamine@user.noreply.gitee.com> Date: Thu, 20 Jul 2023 11:08:35 +0800 Subject: [PATCH 1/6] fix --- model/gmodel/fs_product_model3d_logic.go | 15 ++ .../internal/logic/getproductlistlogic.go | 2 +- .../internal/logic/gettagproductlistlogic.go | 149 +++++++++++------- server/product/internal/types/types.go | 23 +-- server_api/product.api | 23 +-- 5 files changed, 128 insertions(+), 84 deletions(-) diff --git a/model/gmodel/fs_product_model3d_logic.go b/model/gmodel/fs_product_model3d_logic.go index fde41568..1c86db83 100755 --- a/model/gmodel/fs_product_model3d_logic.go +++ b/model/gmodel/fs_product_model3d_logic.go @@ -75,3 +75,18 @@ func (d *FsProductModel3dModel) GetAll(ctx context.Context) (resp []FsProductMod err = d.db.WithContext(ctx).Model(&FsProductModel3d{}).Find(&resp).Error return resp, err } + +type GetGroupPartListByProductIdsRsp struct { + PartList string `json:"part_list"` + ProductId int64 `json:"product_id"` +} + +func (d *FsProductModel3dModel) GetGroupPartListByProductIds(ctx context.Context, productIds []int64) (resp []GetGroupPartListByProductIdsRsp, err error) { + if len(productIds) == 0 { + return + } + err = d.db.WithContext(ctx).Model(&FsProductModel3d{}). + Select("product_id,group_concat(part_list) as part_list"). + Group("product_id").Find(&resp).Error + return resp, err +} diff --git a/server/product/internal/logic/getproductlistlogic.go b/server/product/internal/logic/getproductlistlogic.go index 4e0c04e0..6e27315d 100644 --- a/server/product/internal/logic/getproductlistlogic.go +++ b/server/product/internal/logic/getproductlistlogic.go @@ -45,7 +45,7 @@ func (l *GetProductListLogic) GetProductList(req *types.GetProductListReq, useri } return resp.SetStatusWithMessage(basic.CodeOK, "success", demo) } - if req.Page <= 0{ + if req.Page <= 0 { req.Page = constants.DEFAULT_PAGE } //获取合适尺寸 diff --git a/server/product/internal/logic/gettagproductlistlogic.go b/server/product/internal/logic/gettagproductlistlogic.go index b357c026..87baf49b 100644 --- a/server/product/internal/logic/gettagproductlistlogic.go +++ b/server/product/internal/logic/gettagproductlistlogic.go @@ -60,7 +60,7 @@ func (l *GetTagProductListLogic) GetTagProductList(req *types.GetTagProductListR return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "param cid is invalid:record not found") } logx.Error(err) - return resp.SetStatusWithMessage(basic.CodeDbSqlErr,"failed to get tag info") + return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get tag info") } tReq.LevelPrefixLeftLike = *tagData.LevelPrefix } @@ -77,13 +77,15 @@ func (l *GetTagProductListLogic) GetTagProductList(req *types.GetTagProductListR typeIds = append(typeIds, v.Id) } var ( - productList []gmodel.FsProduct //产品列表(select 字段需要看查询的地方) - productPriceList []gmodel.GetPriceListByProductIdsRsp //产品价格列表(select 字段需要看查询的地方) - mapProductMinPrice = make(map[int64]int64) //产品最小价格map - productTemplatesV2 []gmodel.FsProductTemplateV2 //产品模板列表(select 字段需要看查询的地方) - productSizeCountList []gmodel.CountProductSizeByStatusRsp //产品尺寸数量列表(select 字段需要看查询的地方) - mapProductSizeCount = make(map[int64]int64) //产品尺寸数量map - mapProductTemplate = make(map[int64]struct{}) //产品模板map + productList []gmodel.FsProduct //产品列表(select 字段需要看查询的地方) + productOptionalPartList []gmodel.GetGroupPartListByProductIdsRsp //产品配件列表 + mapProductHaveOptionFitting = make(map[int64]struct{}) + productPriceList []gmodel.GetPriceListByProductIdsRsp //产品价格列表(select 字段需要看查询的地方) + mapProductMinPrice = make(map[int64]int64) //产品最小价格map + productTemplatesV2 []gmodel.FsProductTemplateV2 //产品模板列表(select 字段需要看查询的地方) + productSizeCountList []gmodel.CountProductSizeByStatusRsp //产品尺寸数量列表(select 字段需要看查询的地方) + mapProductSizeCount = make(map[int64]int64) //产品尺寸数量map + mapProductTemplate = make(map[int64]struct{}) //产品模板map ) //携带产品 if req.WithProduct { @@ -104,9 +106,23 @@ func (l *GetTagProductListLogic) GetTagProductList(req *types.GetTagProductListR logx.Error(err) return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get product list") } - productIds := make([]int64,0,len(productList)) - for _,product := range productList{ - productIds = append(productIds,product.Id) + productIds := make([]int64, 0, len(productList)) + for _, product := range productList { + productIds = append(productIds, product.Id) + } + //获取商品可选配件 + productOptionalPartList, err = l.svcCtx.AllModels.FsProductModel3d.GetGroupPartListByProductIds(l.ctx, productIds) + if err != nil { + logx.Error(err) + return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product part list") + } + for _, partList := range productOptionalPartList { + partList.PartList = strings.Trim(partList.PartList, " ") + partList.PartList = strings.Trim(partList.PartList, ",") + if partList.PartList == "" { + continue + } + mapProductHaveOptionFitting[partList.ProductId] = struct{}{} } //获取产品价格列表 productPriceList, err = l.svcCtx.AllModels.FsProductPrice.GetSimplePriceListByProductIds(l.ctx, productIds) @@ -151,22 +167,23 @@ func (l *GetTagProductListLogic) GetTagProductList(req *types.GetTagProductListR mapTagLevel := make(map[string]*types.TagItem) //处理tags数据 if err = l.dealWithTagMenuData(dealWithTagMenuDataReq{ - TagList: tagList, - WithProduct: req.WithProduct, - ProductList: productList, - MapProductMinPrice: mapProductMinPrice, - MapProductTemplate: mapProductTemplate, - MapProductSizeCount: mapProductSizeCount, - MapTagLevel: mapTagLevel, - Size: req.Size, - user: user, + TagList: tagList, + WithProduct: req.WithProduct, + ProductList: productList, + MapProductMinPrice: mapProductMinPrice, + MapProductTemplate: mapProductTemplate, + MapProductSizeCount: mapProductSizeCount, + MapTagLevel: mapTagLevel, + MapProductHaveOptionFitting: mapProductHaveOptionFitting, + Size: req.Size, + user: user, }); err != nil { logx.Error(err) return resp.SetStatusAddMessage(basic.CodeServiceErr, "failed to deal with tag data") } return resp.SetStatusWithMessage(basic.CodeOK, "success", types.GetTagProductListRsp{ TotalCategoryProduct: len(productList), - TagList: l.organizationLevelRelation(mapTagLevel), //组装等级从属关系 + TagList: l.organizationLevelRelation(mapTagLevel), //组装等级从属关系 }) } @@ -178,41 +195,43 @@ type sortRecommendProduct struct { // 处理tag菜单数据 type dealWithTagMenuDataReq struct { - TagList []gmodel.FsTags - WithProduct bool - ProductList []gmodel.FsProduct - MapProductMinPrice map[int64]int64 - MapProductTemplate map[int64]struct{} - MapProductSizeCount map[int64]int64 - MapTagLevel map[string]*types.TagItem - Size uint32 - user gmodel.FsUser + TagList []gmodel.FsTags + WithProduct bool + ProductList []gmodel.FsProduct + MapProductMinPrice map[int64]int64 + MapProductTemplate map[int64]struct{} + MapProductSizeCount map[int64]int64 + MapTagLevel map[string]*types.TagItem + MapProductHaveOptionFitting map[int64]struct{} + Size uint32 + user gmodel.FsUser } func (l *GetTagProductListLogic) dealWithTagMenuData(req dealWithTagMenuDataReq) error { for _, tagInfo := range req.TagList { tagTem := types.TagItem{ - TagProductList: nil, - TypeName: *tagInfo.Title, - TypeId: tagInfo.Id, - Level: *tagInfo.Level, - LevelPrefix: *tagInfo.LevelPrefix, - Icon: *tagInfo.Icon, - Sort: *tagInfo.Sort, - Description: *tagInfo.Description, - ChildTagList: make([]*types.TagItem, 0, 50), + TagProductList: nil, + TypeName: *tagInfo.Title, + TypeId: tagInfo.Id, + Level: *tagInfo.Level, + LevelPrefix: *tagInfo.LevelPrefix, + Icon: *tagInfo.Icon, + Sort: *tagInfo.Sort, + Description: *tagInfo.Description, + ChildTagList: make([]*types.TagItem, 0, 50), } //携带产品 if req.WithProduct { //获取分类产品列表 productListRsp := l.getTagProducts(getTagProductsReq{ - TagId: tagInfo.Id, - ProductList: req.ProductList, - MapProductMinPrice: req.MapProductMinPrice, - MapProductTemplate: req.MapProductTemplate, - MapProductSizeCount: req.MapProductSizeCount, - Size: req.Size, - User: req.user, + TagId: tagInfo.Id, + ProductList: req.ProductList, + MapProductMinPrice: req.MapProductMinPrice, + MapProductTemplate: req.MapProductTemplate, + MapProductSizeCount: req.MapProductSizeCount, + MapProductHaveOptionFitting: req.MapProductHaveOptionFitting, + Size: req.Size, + User: req.user, }) //赋值 tagTem.TagProductList = productListRsp @@ -257,15 +276,17 @@ func (l *GetTagProductListLogic) organizationLevelRelation(mapTagLevel map[strin }) return rspList } + // 获取对应tag的产品列表 type getTagProductsReq struct { - TagId int64 - ProductList []gmodel.FsProduct - MapProductMinPrice map[int64]int64 - MapProductTemplate map[int64]struct{} - MapProductSizeCount map[int64]int64 - Size uint32 - User gmodel.FsUser + TagId int64 + ProductList []gmodel.FsProduct + MapProductMinPrice map[int64]int64 + MapProductTemplate map[int64]struct{} + MapProductSizeCount map[int64]int64 + MapProductHaveOptionFitting map[int64]struct{} + Size uint32 + User gmodel.FsUser } func (l *GetTagProductListLogic) getTagProducts(req getTagProductsReq) (productListRsp []types.TagProduct) { @@ -286,15 +307,21 @@ func (l *GetTagProductListLogic) getTagProducts(req getTagProductsReq) (productL if mapSizeNum, ok := req.MapProductSizeCount[productInfo.Id]; ok { sizeNum = mapSizeNum } + //有无可选配件 + haveOptionalFitting := false + if _, ok = req.MapProductHaveOptionFitting[productInfo.Id]; ok { + haveOptionalFitting = true + } item := types.TagProduct{ - ProductId: productInfo.Id, - Sn: *productInfo.Sn, - Title: *productInfo.Title, - Intro: *productInfo.Intro, - IsEnv: *productInfo.IsProtection, - IsMicro: *productInfo.IsMicrowave, - SizeNum: uint32(sizeNum), - MiniPrice: minPrice, + ProductId: productInfo.Id, + Sn: *productInfo.Sn, + Title: *productInfo.Title, + Intro: *productInfo.Intro, + IsEnv: *productInfo.IsProtection, + IsMicro: *productInfo.IsMicrowave, + SizeNum: uint32(sizeNum), + MiniPrice: minPrice, + HaveOptionalFitting: haveOptionalFitting, } //千人千面处理 r := image.ThousandFaceImageFormatReq{ diff --git a/server/product/internal/types/types.go b/server/product/internal/types/types.go index b1e3d42f..ad786d19 100644 --- a/server/product/internal/types/types.go +++ b/server/product/internal/types/types.go @@ -268,17 +268,18 @@ type TagItem struct { } type TagProduct struct { - ProductId int64 `json:"product_id"` - Sn string `json:"sn"` - Title string `json:"title"` - Cover string `json:"cover"` - Intro string `json:"intro"` - CoverImg string `json:"cover_img"` - IsEnv int64 `json:"is_env"` - IsMicro int64 `json:"is_micro"` - SizeNum uint32 `json:"size_num"` - MiniPrice int64 `json:"mini_price"` - CoverDefault string `json:"cover_default"` + ProductId int64 `json:"product_id"` + Sn string `json:"sn"` + Title string `json:"title"` + Cover string `json:"cover"` + Intro string `json:"intro"` + CoverImg string `json:"cover_img"` + IsEnv int64 `json:"is_env"` + IsMicro int64 `json:"is_micro"` + SizeNum uint32 `json:"size_num"` + MiniPrice int64 `json:"mini_price"` + CoverDefault string `json:"cover_default"` + HaveOptionalFitting bool `json:"have_optional_fitting"` } type GetRenderDesignReq struct { diff --git a/server_api/product.api b/server_api/product.api index 1d7f60a7..b31a5fe9 100644 --- a/server_api/product.api +++ b/server_api/product.api @@ -311,17 +311,18 @@ type TagItem { ChildTagList []*TagItem `json:"child_tag_list"` } type TagProduct { - ProductId int64 `json:"product_id"` - Sn string `json:"sn"` - Title string `json:"title"` - Cover string `json:"cover"` - Intro string `json:"intro"` - CoverImg string `json:"cover_img"` - IsEnv int64 `json:"is_env"` - IsMicro int64 `json:"is_micro"` - SizeNum uint32 `json:"size_num"` - MiniPrice int64 `json:"mini_price"` - CoverDefault string `json:"cover_default"` + ProductId int64 `json:"product_id"` + Sn string `json:"sn"` + Title string `json:"title"` + Cover string `json:"cover"` + Intro string `json:"intro"` + CoverImg string `json:"cover_img"` + IsEnv int64 `json:"is_env"` + IsMicro int64 `json:"is_micro"` + SizeNum uint32 `json:"size_num"` + MiniPrice int64 `json:"mini_price"` + CoverDefault string `json:"cover_default"` + HaveOptionalFitting bool `json:"have_optional_fitting"` } //获取云渲染设计方案信息 type GetRenderDesignReq { From fd93688d27bfca2c2d384875288ae45a5a87fda6 Mon Sep 17 00:00:00 2001 From: laodaming <11058467+laudamine@user.noreply.gitee.com> Date: Thu, 20 Jul 2023 11:09:20 +0800 Subject: [PATCH 2/6] fix --- server/product/internal/logic/gettagproductlistlogic.go | 1 + 1 file changed, 1 insertion(+) diff --git a/server/product/internal/logic/gettagproductlistlogic.go b/server/product/internal/logic/gettagproductlistlogic.go index 87baf49b..d1c034e1 100644 --- a/server/product/internal/logic/gettagproductlistlogic.go +++ b/server/product/internal/logic/gettagproductlistlogic.go @@ -116,6 +116,7 @@ func (l *GetTagProductListLogic) GetTagProductList(req *types.GetTagProductListR logx.Error(err) return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product part list") } + //存储有配件的map for _, partList := range productOptionalPartList { partList.PartList = strings.Trim(partList.PartList, " ") partList.PartList = strings.Trim(partList.PartList, ",") From 4a2230d90cdbf3d0e78d1beffe0a1ff9153e9c4f Mon Sep 17 00:00:00 2001 From: laodaming <11058467+laudamine@user.noreply.gitee.com> Date: Thu, 20 Jul 2023 12:27:07 +0800 Subject: [PATCH 3/6] fix --- model/gmodel/var_gen.go | 2 ++ server/product/internal/handler/routes.go | 5 +++++ server/product/internal/types/types.go | 10 ++++++++++ server_api/product.api | 5 ++++- 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/model/gmodel/var_gen.go b/model/gmodel/var_gen.go index 192e34c8..a5916431 100644 --- a/model/gmodel/var_gen.go +++ b/model/gmodel/var_gen.go @@ -60,6 +60,7 @@ type AllModelsGen struct { FsProductModel3dLight *FsProductModel3dLightModel // fs_product_model3d_light 模型-灯光组表 FsProductOption *FsProductOptionModel // fs_product_option 产品选项表(已废弃) FsProductPrice *FsProductPriceModel // fs_product_price 阶梯价格表 + FsProductRecommend *FsProductRecommendModel // fs_product_recommend 推荐商品表 FsProductRenderDesign *FsProductRenderDesignModel // fs_product_render_design FsProductScene *FsProductSceneModel // fs_product_scene 产品场景表 FsProductSize *FsProductSizeModel // fs_product_size 产品尺寸表 @@ -149,6 +150,7 @@ func NewAllModels(gdb *gorm.DB) *AllModelsGen { FsProductModel3dLight: NewFsProductModel3dLightModel(gdb), FsProductOption: NewFsProductOptionModel(gdb), FsProductPrice: NewFsProductPriceModel(gdb), + FsProductRecommend: NewFsProductRecommendModel(gdb), FsProductRenderDesign: NewFsProductRenderDesignModel(gdb), FsProductScene: NewFsProductSceneModel(gdb), FsProductSize: NewFsProductSizeModel(gdb), diff --git a/server/product/internal/handler/routes.go b/server/product/internal/handler/routes.go index 669d7cef..dd11f8fe 100644 --- a/server/product/internal/handler/routes.go +++ b/server/product/internal/handler/routes.go @@ -107,6 +107,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { Path: "/api/product/get_last_product_design", Handler: GetLastProductDesignHandler(serverCtx), }, + { + Method: http.MethodPost, + Path: "/api/product/save_recommend_product", + Handler: SaveRecommendProductHandler(serverCtx), + }, }, ) } diff --git a/server/product/internal/types/types.go b/server/product/internal/types/types.go index ad786d19..f10feab7 100644 --- a/server/product/internal/types/types.go +++ b/server/product/internal/types/types.go @@ -376,6 +376,16 @@ type GetLastProductDesignRsp struct { Info interface{} `json:"info"` } +type SaveRecommendProductReq struct { + ProductList []RecommendProductItem `json:"product_list"` +} + +type RecommendProductItem struct { + ProductId int64 `json:"product_id"` + Sort int64 `json:"sort"` + Status int64 `json:"status,options=0|1"` +} + type Request struct { } diff --git a/server_api/product.api b/server_api/product.api index b31a5fe9..a1db4ad2 100644 --- a/server_api/product.api +++ b/server_api/product.api @@ -69,6 +69,9 @@ service product { @handler GetLastProductDesignHandler get /api/product/get_last_product_design(request) returns (response); //*********************产品详情分解接口结束*********************** + //*********************推荐产品接口开始×××××××××××××××××××××××××× + + //*********************推荐产品接口结束×××××××××××××××××××××××××× } //获取产品列表 @@ -412,4 +415,4 @@ type GetLastProductDesignRsp { SizeId int64 `json:"size_id"` LogoColor interface{} `json:"logo_color"` Info interface{} `json:"info"` -} \ No newline at end of file +} From 52d47f78acc77c1b3dbdd4bad7ab8f6d4479d149 Mon Sep 17 00:00:00 2001 From: Hiven Date: Thu, 20 Jul 2023 14:43:59 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E8=8E=B7=E5=8F=96=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E8=AE=A2=E5=8D=95=E5=88=97=E8=A1=A8=E6=8E=A5=E5=8F=A3,?= =?UTF-8?q?=E4=BB=A5=E5=8F=8A=E5=B7=A5=E5=85=B7=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + constants/order.go | 5 + constants/paging.go | 3 + model/gmodel/fs_order_detail_logic.go | 4 + model/gmodel/fs_order_logic.go | 75 +++++++++ .../handler/getuserorderlisthandler.go | 78 ++++++++++ server/orders/internal/handler/routes.go | 5 + .../internal/logic/getuserorderlistlogic.go | 146 ++++++++++++++++++ server/orders/internal/types/types.go | 41 +++++ server/orders/orders_test.go | 7 + server_api/orders.api | 48 ++++++ utils/format/time.go | 11 ++ utils/handler/gormHandler.go | 146 ++++++++++++++++++ 13 files changed, 570 insertions(+) create mode 100644 server/orders/internal/handler/getuserorderlisthandler.go create mode 100644 server/orders/internal/logic/getuserorderlistlogic.go create mode 100644 server/orders/orders_test.go create mode 100644 utils/format/time.go create mode 100644 utils/handler/gormHandler.go diff --git a/.gitignore b/.gitignore index 0d6d3ba3..9a4b0c48 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ *.vsix __debug_bin +__debug_bin* .idea .vscode diff --git a/constants/order.go b/constants/order.go index 64549a44..08fe2bac 100644 --- a/constants/order.go +++ b/constants/order.go @@ -121,3 +121,8 @@ const ( // 云仓完成 STATUS_FONT_COMPLETED_CLOUD Order = 8 ) + +// 订单取消时间 +const ( + CANCLE_ORDER_EXPIRE int64 = 48 * 3600 +) diff --git a/constants/paging.go b/constants/paging.go index 638a38de..a700ca96 100644 --- a/constants/paging.go +++ b/constants/paging.go @@ -8,3 +8,6 @@ const DEFAULT_PAGE_SIZE = 20 // 最大每页显示数量 const MAX_PAGE_SIZE = 300 + +// 最大分页 +const MAX_PAGE = 100 diff --git a/model/gmodel/fs_order_detail_logic.go b/model/gmodel/fs_order_detail_logic.go index 840a57f9..0513dfa6 100755 --- a/model/gmodel/fs_order_detail_logic.go +++ b/model/gmodel/fs_order_detail_logic.go @@ -24,3 +24,7 @@ func (d *FsProductDesignModel) FindOne(ctx context.Context, id int64, userId int err = d.db.WithContext(ctx).Model(&FsProductDesign{}).Where("`id` = ? and `user_id` = ? and `status` = ?", id, userId, 1).First(&resp).Error return resp, err } + +func (m *FsOrderDetailModel) TableName() string { + return m.name +} diff --git a/model/gmodel/fs_order_logic.go b/model/gmodel/fs_order_logic.go index ef332996..eda7880c 100755 --- a/model/gmodel/fs_order_logic.go +++ b/model/gmodel/fs_order_logic.go @@ -3,8 +3,11 @@ package gmodel import ( "context" "fusenapi/constants" + "reflect" "time" + "fusenapi/utils/handler" + "gorm.io/gorm" ) @@ -51,3 +54,75 @@ func (o *FsOrderModel) FindLastSuccessOneOrder(ctx context.Context, userId int64 err = o.db.WithContext(ctx).Model(&FsOrder{}).Where("`user_id` = ? and `status` > ?", userId, statusGt).Order("id DESC").Take(&order).Error return order, err } + +// 分页查询的订单 +func (o *FsOrderModel) FindPageListByPage(ctx context.Context, rowBuilder *gorm.DB, page *int64, pageSize *int64, filterMap map[string]string, orderBy string) ([]*FsOrderRel, error) { + var resp []*FsOrderRel + // 过滤 + if filterMap != nil { + rowBuilder = rowBuilder.Scopes(handler.FilterData(filterMap)) + } + + // 排序 + if orderBy != "" { + var fieldsMap = make(map[string]struct{}) + s := reflect.TypeOf(&FsOrder{}).Elem() //通过反射获取type定义 + for i := 0; i < s.NumField(); i++ { + fieldsMap[s.Field(i).Tag.Get("json")] = struct{}{} + } + rowBuilder = rowBuilder.Scopes(handler.OrderCheck(orderBy, fieldsMap)) + } + + // 分页 + rowBuilder = rowBuilder.Scopes(handler.Paginate(page, pageSize)) + + // 结果 + result := rowBuilder.WithContext(ctx).Find(&resp) + if result.Error != nil { + return nil, result.Error + } else { + return resp, nil + } +} + +type FsOrderRel struct { + FsOrder + FsOrderDetails []FsOrderDetails `gorm:"foreignKey:order_id;references:id"` +} + +type FsOrderDetails struct { + FsOrderDetail + FsOrderDetailTemplateInfo FsOrderDetailTemplate `gorm:"foreignKey:id;references:order_detail_template_id"` + FsProductInfo FsProduct `gorm:"foreignKey:id;references:product_id"` +} + +func (m *FsOrderModel) RowSelectBuilder(selectData []string) *gorm.DB { + var rowBuilder = m.db.Table(m.name) + + if selectData != nil { + rowBuilder = rowBuilder.Select(selectData) + } else { + rowBuilder = rowBuilder.Select("*") + } + return rowBuilder +} + +func (m *FsOrderModel) FindCount(ctx context.Context, countBuilder *gorm.DB, filterMap map[string]string) (int64, error) { + var count int64 + + // 过滤 + if filterMap != nil { + countBuilder = countBuilder.Scopes(handler.FilterData(filterMap)) + } + + result := countBuilder.WithContext(ctx).Limit(1).Count(&count) + if result.Error != nil { + return 0, result.Error + } else { + return count, nil + } +} + +func (m *FsOrderModel) TableName() string { + return m.name +} diff --git a/server/orders/internal/handler/getuserorderlisthandler.go b/server/orders/internal/handler/getuserorderlisthandler.go new file mode 100644 index 00000000..89309f16 --- /dev/null +++ b/server/orders/internal/handler/getuserorderlisthandler.go @@ -0,0 +1,78 @@ +package handler + +import ( + "errors" + "net/http" + + "github.com/zeromicro/go-zero/core/logx" + "github.com/zeromicro/go-zero/rest/httpx" + + "fusenapi/utils/auth" + "fusenapi/utils/basic" + + "fusenapi/server/orders/internal/logic" + "fusenapi/server/orders/internal/svc" + "fusenapi/server/orders/internal/types" +) + +func GetUserOrderListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + + var ( + // 定义错误变量 + err error + // 定义用户信息变量 + userinfo *auth.UserInfo + ) + // 解析JWT token,并对空用户进行判断 + claims, err := svcCtx.ParseJwtToken(r) + // 如果解析JWT token出错,则返回未授权的JSON响应并记录错误消息 + if err != nil { + httpx.OkJsonCtx(r.Context(), w, &basic.Response{ + Code: 401, // 返回401状态码,表示未授权 + Message: "unauthorized", // 返回未授权信息 + }) + logx.Info("unauthorized:", err.Error()) // 记录错误日志 + return + } + + if claims != nil { + // 从token中获取对应的用户信息 + userinfo, err = auth.GetUserInfoFormMapClaims(claims) + // 如果获取用户信息出错,则返回未授权的JSON响应并记录错误消息 + if err != nil { + httpx.OkJsonCtx(r.Context(), w, &basic.Response{ + Code: 401, + Message: "unauthorized", + }) + logx.Info("unauthorized:", err.Error()) + return + } + } else { + // 如果claims为nil,则认为用户身份为白板用户 + userinfo = &auth.UserInfo{UserId: 0, GuestId: 0} + } + + var req types.GetUserOrderListReq + // 如果端点有请求结构体,则使用httpx.Parse方法从HTTP请求体中解析请求数据 + if err := httpx.Parse(r, &req); err != nil { + httpx.OkJsonCtx(r.Context(), w, &basic.Response{ + Code: 510, + Message: "parameter error", + }) + logx.Info(err) + return + } + // 创建一个业务逻辑层实例 + l := logic.NewGetUserOrderListLogic(r.Context(), svcCtx) + resp := l.GetUserOrderList(&req, userinfo) + // 如果响应不为nil,则使用httpx.OkJsonCtx方法返回JSON响应; + if resp != nil { + httpx.OkJsonCtx(r.Context(), w, resp) + } else { + err := errors.New("server logic is error, resp must not be nil") + httpx.ErrorCtx(r.Context(), w, err) + logx.Error(err) + } + } +} diff --git a/server/orders/internal/handler/routes.go b/server/orders/internal/handler/routes.go index 467c0530..e22a9566 100644 --- a/server/orders/internal/handler/routes.go +++ b/server/orders/internal/handler/routes.go @@ -22,6 +22,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { Path: "/api/order/detail", Handler: GetOrderDetailHandler(serverCtx), }, + { + Method: http.MethodGet, + Path: "/api/user/order-list", + Handler: GetUserOrderListHandler(serverCtx), + }, }, ) } diff --git a/server/orders/internal/logic/getuserorderlistlogic.go b/server/orders/internal/logic/getuserorderlistlogic.go new file mode 100644 index 00000000..28f8e4a8 --- /dev/null +++ b/server/orders/internal/logic/getuserorderlistlogic.go @@ -0,0 +1,146 @@ +package logic + +import ( + "context" + "errors" + "fusenapi/constants" + "fusenapi/model/gmodel" + "fusenapi/utils/auth" + "fusenapi/utils/basic" + "fusenapi/utils/format" + "math" + + "fusenapi/server/orders/internal/svc" + "fusenapi/server/orders/internal/types" + + "github.com/zeromicro/go-zero/core/logx" + "gorm.io/gorm" +) + +type GetUserOrderListLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewGetUserOrderListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserOrderListLogic { + return &GetUserOrderListLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *GetUserOrderListLogic) GetUserOrderList(req *types.GetUserOrderListReq, userinfo *auth.UserInfo) (resp *basic.Response) { + // 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data) + // userinfo 传入值时, 一定不为null + orderDetailModel := gmodel.NewFsOrderDetailModel(l.svcCtx.MysqlConn) + orderModel := gmodel.NewFsOrderModel(l.svcCtx.MysqlConn) + rowBuilder := orderModel.RowSelectBuilder(nil) + if userinfo == nil || userinfo.UserId == 0 { + return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "order not found") + } + + // 查询条件 + var page = req.Page + var pageSize = req.PageSize + var listRes []*gmodel.FsOrderRel + rowBuilder = rowBuilder.Where("user_id =?", userinfo.UserId).Where("status =?", req.Status) + + // 查询总数 + total, err := orderModel.FindCount(l.ctx, rowBuilder, nil) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "order not found") + } + logx.Error(err) + return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get order info") + } + + // 查询数据 + if total > 0 { + rowBuilder = rowBuilder.Preload("FsOrderDetails", func(dbPreload *gorm.DB) *gorm.DB { + return dbPreload.Table(orderDetailModel.TableName()).Preload("FsOrderDetailTemplateInfo").Preload("FsProductInfo") + }) + listRes, err = orderModel.FindPageListByPage(l.ctx, rowBuilder, &page, &pageSize, nil, "") + } + + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "order not found") + } + logx.Error(err) + return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get order info") + } + listResLen := len(listRes) + + var respList []types.Items + if listResLen > 0 { + // 数据处理 + for _, item := range listRes { + var pbData types.Items + pbData.ID = item.Id + pbData.Sn = *item.Sn + pbData.UserID = *item.UserId + pbData.TotalAmount = *item.TotalAmount + pbData.Ctime = format.TimeIntToFormat(*item.Ctime) + pbData.Status = *item.Status + pbData.DeliveryMethod = *item.DeliveryMethod + pbData.TsTime = format.TimeToFormat(*item.TsTime) + pbData.IsPayCompleted = *item.IsPayCompleted + pbData.DeliverSn = *item.DeliverSn + + var pcsBox int64 + var pcs int64 + var productList []*types.Product + if len(item.FsOrderDetails) > 0 { + for _, fsOrderDetailItem := range item.FsOrderDetails { + fsOrderDetailBuyNum := *fsOrderDetailItem.FsOrderDetail.BuyNum + fsOrderDetailEachBoxNum := *fsOrderDetailItem.FsOrderDetailTemplateInfo.EachBoxNum + pcs = pcs + fsOrderDetailBuyNum + pcsBoxNum := fsOrderDetailBuyNum / fsOrderDetailEachBoxNum + var csBoxNumF int64 + if (fsOrderDetailBuyNum % fsOrderDetailEachBoxNum) > 0 { + csBoxNumF = 1 + } + pcsBox = pcsBox + pcsBoxNum + csBoxNumF + + var product types.Product + product.Cover = *fsOrderDetailItem.Cover + product.Fitting = *fsOrderDetailItem.OptionalTitle + product.OptionPrice = *fsOrderDetailItem.OptionPrice + product.OrderDetailTemplateId = *fsOrderDetailItem.OrderDetailTemplateId + product.OrderId = *fsOrderDetailItem.OrderId + product.Pcs = fsOrderDetailBuyNum + product.PcsBox = pcsBox + product.Price = *fsOrderDetailItem.FsOrderDetail.Amount + product.ProductId = *fsOrderDetailItem.OptionPrice + //product.Size = *fsOrderDetailItem.FsProductInfo.s + product.Title = *fsOrderDetailItem.FsProductInfo.Title + + productList = append(productList, &product) + } + pbData.ProductList = productList + } + + pbData.PcsBox = pcsBox + pbData.Pcs = pcs + pbData.SurplusAt = *item.Ctime + constants.CANCLE_ORDER_EXPIRE + pbData.LogisticsStatus = 1 + pbData.Deposit = *item.TotalAmount / 2 + pbData.Remaining = pbData.Deposit + respList = append(respList, pbData) + } + + } + + return resp.SetStatusWithMessage(basic.CodeOK, "success", types.GetUserOrderListRsp{ + Items: respList, + Meta: types.Meta{ + TotalCount: total, + PageCount: int64(math.Ceil(float64(total) / float64(pageSize))), + CurrentPage: int(page), + PerPage: int(pageSize), + }, + }) +} diff --git a/server/orders/internal/types/types.go b/server/orders/internal/types/types.go index 703e7835..32ce3df9 100644 --- a/server/orders/internal/types/types.go +++ b/server/orders/internal/types/types.go @@ -76,6 +76,47 @@ type Deposit struct { TransNo string `json:"trans_no"` } +type GetUserOrderListReq struct { + Page int64 `form:"page"` // 分页 + PageSize int64 `form:"page_size"` // 每页数量 + Status int64 `form:"status"` // 状态筛选 + Time int64 `form:"time"` // 时间筛选 + Total int64 `form:"total"` // 总数 + Size int64 `form:"size"` // 图片尺寸 +} + +type GetUserOrderListRsp struct { + Items []Items `json:"items"` + Meta Meta `json:"_meta"` +} + +type StatusTimes struct { + Key int `json:"key"` + Time string `json:"time"` +} + +type Items struct { + ID int64 `json:"id"` + Sn string `json:"sn"` + UserID int64 `json:"user_id"` + TotalAmount int64 `json:"total_amount"` + Ctime string `json:"ctime"` + Status int64 `json:"status"` + DeliveryMethod int64 `json:"delivery_method"` + TsTime string `json:"ts_time"` + IsPayCompleted int64 `json:"is_pay_completed"` + DeliverSn string `json:"deliver_sn"` + PcsBox int64 `json:"pcs_box"` + Pcs int64 `json:"pcs"` + SurplusAt int64 `json:"surplus_at"` + LogisticsStatus int64 `json:"logistics_status"` + StatusTimes []*StatusTimes `json:"status_times"` + Deposit int64 `json:"deposit"` + Remaining int64 `json:"remaining"` + ProductList []*Product `json:"productList"` + IsStop int64 `json:"is_stop"` +} + type Request struct { } diff --git a/server/orders/orders_test.go b/server/orders/orders_test.go new file mode 100644 index 00000000..ef649768 --- /dev/null +++ b/server/orders/orders_test.go @@ -0,0 +1,7 @@ +package main + +import "testing" + +func TestMain(t *testing.T) { + main() +} diff --git a/server_api/orders.api b/server_api/orders.api index 3bb63dde..e3015778 100644 --- a/server_api/orders.api +++ b/server_api/orders.api @@ -16,6 +16,10 @@ service orders { //获取订单详情 @handler GetOrderDetailHandler get /api/order/detail (GetOrderDetailReq) returns (response); + + //获取订单列表 + @handler GetUserOrderListHandler + get /api/user/order-list (GetUserOrderListReq) returns (response); } //获取订单发票 @@ -82,4 +86,48 @@ type PayInfo { type Deposit { Method string `json:"method"` TransNo string `json:"trans_no"` +} + +// 获取订单列表 +type ( + GetUserOrderListReq { + Page int64 `form:"page"` // 分页 + PageSize int64 `form:"page_size"` // 每页数量 + Status int64 `form:"status"` // 状态筛选 + Time int64 `form:"time"` // 时间筛选 + Total int64 `form:"total"` // 总数 + Size int64 `form:"size"` // 图片尺寸 + } + + GetUserOrderListRsp { + Items []Items `json:"items"` + Meta Meta `json:"_meta"` + } +) + +type StatusTimes { + Key int `json:"key"` + Time string `json:"time"` +} + +type Items { + ID int64 `json:"id"` + Sn string `json:"sn"` + UserID int64 `json:"user_id"` + TotalAmount int64 `json:"total_amount"` + Ctime string `json:"ctime"` + Status int64 `json:"status"` + DeliveryMethod int64 `json:"delivery_method"` + TsTime string `json:"ts_time"` + IsPayCompleted int64 `json:"is_pay_completed"` + DeliverSn string `json:"deliver_sn"` + PcsBox int64 `json:"pcs_box"` + Pcs int64 `json:"pcs"` + SurplusAt int64 `json:"surplus_at"` + LogisticsStatus int64 `json:"logistics_status"` + StatusTimes []*StatusTimes `json:"status_times"` + Deposit int64 `json:"deposit"` + Remaining int64 `json:"remaining"` + ProductList []*Product `json:"productList"` + IsStop int64 `json:"is_stop"` } \ No newline at end of file diff --git a/utils/format/time.go b/utils/format/time.go new file mode 100644 index 00000000..17666331 --- /dev/null +++ b/utils/format/time.go @@ -0,0 +1,11 @@ +package format + +import "time" + +func TimeToFormat(t time.Time) string { + return time.Time(t).Format("2006-01-02 15:04:05") +} + +func TimeIntToFormat(unixTime int64) string { + return time.Unix(unixTime, 0).Format("2006-01-02 15:04:05") +} diff --git a/utils/handler/gormHandler.go b/utils/handler/gormHandler.go new file mode 100644 index 00000000..d239931e --- /dev/null +++ b/utils/handler/gormHandler.go @@ -0,0 +1,146 @@ +package handler + +import ( + "encoding/json" + "fmt" + "fusenapi/constants" + "strconv" + "strings" + "unicode" + + "gorm.io/gorm" +) + +// FilterData 条件过滤 +func FilterData(filterMap map[string]string) func(db *gorm.DB) *gorm.DB { + return func(db *gorm.DB) *gorm.DB { + // 组合索引 + db = db.Where("id <> ?", 0) + for fieldName, item := range filterMap { + options := strings.Split(item, "|") + conditionKey := options[1] + + var conditionValueType string + if len(options) == 3 { + conditionValueType = options[2] + } + + var conditionValue interface{} + + if conditionKey == "=" || conditionKey == "<>" || conditionKey == ">=" || conditionKey == "<=" { + conditionStr := options[0] + if conditionValueType == "string" { + conditionValue = options[0] + } else { + if ss := CheckIsDigit(conditionStr); ss != 0 { + conditionValue = ss + } else { + conditionValue = options[0] + } + } + } else { + var conditionArrNew []int64 + conditionArr := strings.Split(options[0], ",") + for _, s := range conditionArr { + if ss := CheckIsDigit(s); ss != 0 { + conditionArrNew = append(conditionArrNew, ss) + } + } + if len(conditionArrNew) > 0 { + conditionValue = conditionArrNew + } else { + conditionValue = conditionArr + } + } + + switch conditionKey { + case "LIKE": + db = db.Where(fmt.Sprintf("%v LIKE ?", fieldName), fmt.Sprintf("%%%v%%", conditionValue)) + case "BETWEEN": + db = db.Where(fmt.Sprintf("%v BETWEEN ? AND ?", fieldName), conditionValue.([]interface{})[0], conditionValue.([]interface{})[1]) + default: + db = db.Where(fmt.Sprintf("%v %v ?", fieldName, conditionKey), conditionValue) + } + } + return db + } +} + +// OrderCheck 公共排序--检测 +func OrderCheck(orderData string, fields map[string]struct{}) func(db *gorm.DB) *gorm.DB { + return func(db *gorm.DB) *gorm.DB { + var orderType = "desc" + if orderData != "" { + var sortData []map[string]interface{} + _ = json.Unmarshal([]byte(orderData), &sortData) + + sortCount := len(sortData) + for i := 0; i < sortCount; i++ { + data := sortData[i] + prop, existProp := data["prop"] + sort, existSort := data["order"] + if existProp && existSort { + propData := strings.TrimSpace(prop.(string)) + sortData := strings.TrimSpace(sort.(string)) + if propData != "" && sortData != "" { + // 判断数据库字段 + _, existFields := fields[propData] + if existFields { + if sortData == "descending" || sortData == "desc" { + orderType = "desc" + } else { + orderType = "asc" + } + db.Order(fmt.Sprintf("%v %v", prop, orderType)) + } + } + } + } + return db + } else { + return db.Order("id asc") + } + } +} + +// Paginate 公共分页 +func Paginate(page *int64, pageSize *int64) func(db *gorm.DB) *gorm.DB { + return func(db *gorm.DB) *gorm.DB { + page, _ := strconv.Atoi(strconv.FormatInt(*page, 10)) + + switch { + case page == 0: + page = constants.DEFAULT_PAGE + case page > constants.MAX_PAGE: + page = constants.MAX_PAGE + } + + pageSize, _ := strconv.Atoi(strconv.FormatInt(*pageSize, 10)) + switch { + case pageSize > constants.MAX_PAGE_SIZE: + pageSize = constants.MAX_PAGE_SIZE + case pageSize <= 0: + pageSize = constants.DEFAULT_PAGE_SIZE + } + + offset := (page - 1) * pageSize + return db.Offset(offset).Limit(pageSize) + } +} + +// CheckIsDigit 判断int +func CheckIsDigit(s string) int64 { + isDigit := true + for _, r := range s { + if !unicode.IsDigit(r) { + isDigit = false + break + } + } + if isDigit { + ss, _ := strconv.ParseInt(s, 10, 64) + return ss + } else { + return 0 + } +} From f2eec528ce3c95485776ae4f67075d29bd2f437b Mon Sep 17 00:00:00 2001 From: Hiven Date: Thu, 20 Jul 2023 14:46:13 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/orders/internal/types/types.go | 40 +++++++++++++-------------- server_api/orders.api | 40 +++++++++++++-------------- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/server/orders/internal/types/types.go b/server/orders/internal/types/types.go index 32ce3df9..ca77da8f 100644 --- a/server/orders/internal/types/types.go +++ b/server/orders/internal/types/types.go @@ -90,31 +90,31 @@ type GetUserOrderListRsp struct { Meta Meta `json:"_meta"` } -type StatusTimes struct { +type StatusTime struct { Key int `json:"key"` Time string `json:"time"` } type Items struct { - ID int64 `json:"id"` - Sn string `json:"sn"` - UserID int64 `json:"user_id"` - TotalAmount int64 `json:"total_amount"` - Ctime string `json:"ctime"` - Status int64 `json:"status"` - DeliveryMethod int64 `json:"delivery_method"` - TsTime string `json:"ts_time"` - IsPayCompleted int64 `json:"is_pay_completed"` - DeliverSn string `json:"deliver_sn"` - PcsBox int64 `json:"pcs_box"` - Pcs int64 `json:"pcs"` - SurplusAt int64 `json:"surplus_at"` - LogisticsStatus int64 `json:"logistics_status"` - StatusTimes []*StatusTimes `json:"status_times"` - Deposit int64 `json:"deposit"` - Remaining int64 `json:"remaining"` - ProductList []*Product `json:"productList"` - IsStop int64 `json:"is_stop"` + ID int64 `json:"id"` + Sn string `json:"sn"` + UserID int64 `json:"user_id"` + TotalAmount int64 `json:"total_amount"` + Ctime string `json:"ctime"` + Status int64 `json:"status"` + DeliveryMethod int64 `json:"delivery_method"` + TsTime string `json:"ts_time"` + IsPayCompleted int64 `json:"is_pay_completed"` + DeliverSn string `json:"deliver_sn"` + PcsBox int64 `json:"pcs_box"` + Pcs int64 `json:"pcs"` + SurplusAt int64 `json:"surplus_at"` + LogisticsStatus int64 `json:"logistics_status"` + StatusTimes []*StatusTime `json:"status_times"` + Deposit int64 `json:"deposit"` + Remaining int64 `json:"remaining"` + ProductList []*Product `json:"productList"` + IsStop int64 `json:"is_stop"` } type Request struct { diff --git a/server_api/orders.api b/server_api/orders.api index e3015778..f2fd298c 100644 --- a/server_api/orders.api +++ b/server_api/orders.api @@ -105,29 +105,29 @@ type ( } ) -type StatusTimes { +type StatusTime { Key int `json:"key"` Time string `json:"time"` } type Items { - ID int64 `json:"id"` - Sn string `json:"sn"` - UserID int64 `json:"user_id"` - TotalAmount int64 `json:"total_amount"` - Ctime string `json:"ctime"` - Status int64 `json:"status"` - DeliveryMethod int64 `json:"delivery_method"` - TsTime string `json:"ts_time"` - IsPayCompleted int64 `json:"is_pay_completed"` - DeliverSn string `json:"deliver_sn"` - PcsBox int64 `json:"pcs_box"` - Pcs int64 `json:"pcs"` - SurplusAt int64 `json:"surplus_at"` - LogisticsStatus int64 `json:"logistics_status"` - StatusTimes []*StatusTimes `json:"status_times"` - Deposit int64 `json:"deposit"` - Remaining int64 `json:"remaining"` - ProductList []*Product `json:"productList"` - IsStop int64 `json:"is_stop"` + ID int64 `json:"id"` + Sn string `json:"sn"` + UserID int64 `json:"user_id"` + TotalAmount int64 `json:"total_amount"` + Ctime string `json:"ctime"` + Status int64 `json:"status"` + DeliveryMethod int64 `json:"delivery_method"` + TsTime string `json:"ts_time"` + IsPayCompleted int64 `json:"is_pay_completed"` + DeliverSn string `json:"deliver_sn"` + PcsBox int64 `json:"pcs_box"` + Pcs int64 `json:"pcs"` + SurplusAt int64 `json:"surplus_at"` + LogisticsStatus int64 `json:"logistics_status"` + StatusTimes []*StatusTime `json:"status_times"` + Deposit int64 `json:"deposit"` + Remaining int64 `json:"remaining"` + ProductList []*Product `json:"productList"` + IsStop int64 `json:"is_stop"` } \ No newline at end of file From 9ff4468778177515b2178d47b64271fd5ea33bc6 Mon Sep 17 00:00:00 2001 From: laodaming <11058467+laudamine@user.noreply.gitee.com> Date: Thu, 20 Jul 2023 14:56:28 +0800 Subject: [PATCH 6/6] fix --- model/gmodel/fs_product_logic.go | 6 +- model/gmodel/fs_product_recommend_gen.go | 21 +++++++ model/gmodel/fs_product_recommend_logic.go | 46 +++++++++++++++ server/product/internal/handler/routes.go | 5 -- .../logic/getrecommandproductlistlogic.go | 58 ++++++++++++++++--- server/product/internal/types/types.go | 11 +--- server_api/product.api | 5 +- 7 files changed, 126 insertions(+), 26 deletions(-) create mode 100644 model/gmodel/fs_product_recommend_gen.go create mode 100644 model/gmodel/fs_product_recommend_logic.go diff --git a/model/gmodel/fs_product_logic.go b/model/gmodel/fs_product_logic.go index 009181db..95c301ce 100755 --- a/model/gmodel/fs_product_logic.go +++ b/model/gmodel/fs_product_logic.go @@ -72,7 +72,11 @@ func (p *FsProductModel) GetRandomProductList(ctx context.Context, limit int) (r Where("`is_del` =? and `is_shelf` = ?", 0, 1).Order("RAND()").Limit(limit).Find(&resp).Error return resp, err } - +func (p *FsProductModel) GetIgnoreRandomProductList(ctx context.Context, limit int, notInProductIds []int64) (resp []FsProduct, err error) { + err = p.db.WithContext(ctx).Model(&FsProduct{}). + Where("`is_del` =? and `is_shelf` = ? and `id` not in(?)", 0, 1, notInProductIds).Order("RAND()").Limit(limit).Find(&resp).Error + return resp, err +} func (p *FsProductModel) FindAllOnlyByIds(ctx context.Context, ids []int64) (resp []FsProduct, err error) { err = p.db.WithContext(ctx).Model(&FsProduct{}).Where("`id` IN (?)", ids).Find(&resp).Error return resp, err diff --git a/model/gmodel/fs_product_recommend_gen.go b/model/gmodel/fs_product_recommend_gen.go new file mode 100644 index 00000000..b70ba056 --- /dev/null +++ b/model/gmodel/fs_product_recommend_gen.go @@ -0,0 +1,21 @@ +package gmodel + +import ( + "gorm.io/gorm" +) + +// fs_product_recommend 推荐商品表 +type FsProductRecommend struct { + Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` // + ProductId *int64 `gorm:"unique_key;default:0;" json:"product_id"` // 产品ID + Status *int64 `gorm:"default:1;" json:"status"` // 状态 1正常 0不正常 + Ctime *int64 `gorm:"default:0;" json:"ctime"` // 添加时间 +} +type FsProductRecommendModel struct { + db *gorm.DB + name string +} + +func NewFsProductRecommendModel(db *gorm.DB) *FsProductRecommendModel { + return &FsProductRecommendModel{db: db, name: "fs_product_recommend"} +} diff --git a/model/gmodel/fs_product_recommend_logic.go b/model/gmodel/fs_product_recommend_logic.go new file mode 100644 index 00000000..3de52d5c --- /dev/null +++ b/model/gmodel/fs_product_recommend_logic.go @@ -0,0 +1,46 @@ +package gmodel + +import ( + "context" + "errors" + "gorm.io/gorm" +) + +type GetRecommendProductListReq struct { + Ctx context.Context + Page int + Limit int + OrderBy string + Status *int64 +} + +func (r *FsProductRecommendModel) GetRecommendProductList(req GetRecommendProductListReq) (resp []FsProductRecommend, total int64, err error) { + db := r.db.WithContext(req.Ctx).Model(&FsProductRecommend{}) + if req.Status != nil { + db = db.Where("`status` = ?", *req.Status) + } + if req.OrderBy != "" { + db = db.Order(req.OrderBy) + } + if err = db.Limit(1).Count(&total).Error; err != nil { + return nil, 0, err + } + offset := (req.Page - 1) * req.Limit + err = db.Offset(offset).Limit(req.Limit).Find(&resp).Error + return resp, total, err +} +func (r *FsProductRecommendModel) GetIgnoreRandomRecommendProductList(ctx context.Context, limit int, idNotInt []int64) (resp []FsProductRecommend, err error) { + err = r.db.WithContext(ctx).Model(&FsProductRecommend{}).Where("`product_id` not in(?)", idNotInt).Order("RAND()").Limit(limit).Find(&resp).Error + return resp, err +} +func (r *FsProductRecommendModel) CreateOrUpdate(ctx context.Context, productId int64, data *FsProductRecommend) error { + var info FsProductRecommend + err := r.db.WithContext(ctx).Model(&FsProductRecommend{}).Where("`product_id` = ?", productId).Take(&info).Error + if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { + return err + } + if info.Id == 0 { + return r.db.WithContext(ctx).Model(&FsProductRecommend{}).Create(data).Error + } + return r.db.WithContext(ctx).Model(&FsProductRecommend{}).Where("`product_id` = ?", productId).Updates(data).Error +} diff --git a/server/product/internal/handler/routes.go b/server/product/internal/handler/routes.go index dd11f8fe..669d7cef 100644 --- a/server/product/internal/handler/routes.go +++ b/server/product/internal/handler/routes.go @@ -107,11 +107,6 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { Path: "/api/product/get_last_product_design", Handler: GetLastProductDesignHandler(serverCtx), }, - { - Method: http.MethodPost, - Path: "/api/product/save_recommend_product", - Handler: SaveRecommendProductHandler(serverCtx), - }, }, ) } diff --git a/server/product/internal/logic/getrecommandproductlistlogic.go b/server/product/internal/logic/getrecommandproductlistlogic.go index 80176d90..68f4cb29 100644 --- a/server/product/internal/logic/getrecommandproductlistlogic.go +++ b/server/product/internal/logic/getrecommandproductlistlogic.go @@ -30,18 +30,54 @@ func NewGetRecommandProductListLogic(ctx context.Context, svcCtx *svc.ServiceCon } func (l *GetRecommandProductListLogic) GetRecommandProductList(req *types.GetRecommandProductListReq, userinfo *auth.UserInfo) (resp *basic.Response) { - req.Num = 8 //目前写死 + req.Num = 4 //写死4个 if req.Size > 0 { req.Size = image.GetCurrentSize(req.Size) } - //随机取产品列表 - productList, err := l.svcCtx.AllModels.FsProduct.GetRandomProductList(l.ctx, int(req.Num)) + productInfo, err := l.svcCtx.AllModels.FsProduct.FindOneBySn(l.ctx, req.Sn) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "detail`s product is not found") + } + logx.Error(err) + return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get detail product info") + } + //随机取产品列表(不包含详情产品) + recommendList, err := l.svcCtx.AllModels.FsProductRecommend.GetIgnoreRandomRecommendProductList(l.ctx, int(req.Num), []int64{productInfo.Id}) if err != nil { logx.Error(err) - return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get random recommend product list") + return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get random recommend list") } - if len(productList) == 0 { - return resp.SetStatusWithMessage(basic.CodeOK, "success") + //需要填充时需要忽略的id + ignoreProductIds := make([]int64, 0, len(recommendList)+1) + ignoreProductIds = append(ignoreProductIds, productInfo.Id) + recommendProductIds := make([]int64, 0, len(recommendList)) + for _, v := range recommendList { + ignoreProductIds = append(ignoreProductIds, *v.ProductId) + recommendProductIds = append(recommendProductIds, *v.ProductId) + } + //获取推荐产品列表 + recommendProductList, err := l.svcCtx.AllModels.FsProduct.GetProductListByIds(l.ctx, recommendProductIds, "") + if err != nil { + logx.Error(err) + return resp.SetStatus(basic.CodeDbSqlErr, "failed to get recommend product list") + } + //在合并之前记住推荐的产品 + mapRecommend := make(map[int64]struct{}) + for _, v := range recommendProductList { + mapRecommend[v.Id] = struct{}{} + } + //小于请求的数量则需要从产品表中随机填补上 + lenRecommendProduct := len(recommendProductList) + if lenRecommendProduct < int(req.Num) { + appendNum := int(req.Num) - lenRecommendProduct + productList, err := l.svcCtx.AllModels.FsProduct.GetIgnoreRandomProductList(l.ctx, appendNum, ignoreProductIds) + if err != nil { + logx.Error(err) + return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product list") + } + //合并列表 + recommendProductList = append(recommendProductList, productList...) } //获取用户信息(不用判断存在) user, err := l.svcCtx.AllModels.FsUser.FindUserById(l.ctx, userinfo.UserId) @@ -49,8 +85,8 @@ func (l *GetRecommandProductListLogic) GetRecommandProductList(req *types.GetRec logx.Error(err) return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get user") } - list := make([]types.GetRecommandProductListRsp, 0, len(productList)) - for _, v := range productList { + list := make([]types.GetRecommandProductListRsp, 0, len(recommendProductList)) + for _, v := range recommendProductList { r := image.ThousandFaceImageFormatReq{ Size: int(req.Size), IsThousandFace: 0, @@ -63,7 +99,12 @@ func (l *GetRecommandProductListLogic) GetRecommandProductList(req *types.GetRec if user.Id != 0 { r.IsThousandFace = int(*user.IsThousandFace) } + //千人前面处理 image.ThousandFaceImageFormat(&r) + isRecommend := int64(0) + if _, ok := mapRecommend[v.Id]; ok { + isRecommend = 1 + } list = append(list, types.GetRecommandProductListRsp{ Id: v.Id, Sn: *v.Sn, @@ -73,6 +114,7 @@ func (l *GetRecommandProductListLogic) GetRecommandProductList(req *types.GetRec CoverImg: r.CoverImg, CoverDefault: r.CoverDefault, Intro: *v.Intro, + IsRecommend: isRecommend, }) } return resp.SetStatusWithMessage(basic.CodeOK, "success", list) diff --git a/server/product/internal/types/types.go b/server/product/internal/types/types.go index f10feab7..3b611579 100644 --- a/server/product/internal/types/types.go +++ b/server/product/internal/types/types.go @@ -242,6 +242,7 @@ type GetRecommandProductListRsp struct { CoverImg string `json:"cover_img"` CoverDefault string `json:"cover_default"` Intro string `json:"intro"` + IsRecommend int64 `json:"is_recommend"` } type GetTagProductListReq struct { @@ -376,16 +377,6 @@ type GetLastProductDesignRsp struct { Info interface{} `json:"info"` } -type SaveRecommendProductReq struct { - ProductList []RecommendProductItem `json:"product_list"` -} - -type RecommendProductItem struct { - ProductId int64 `json:"product_id"` - Sort int64 `json:"sort"` - Status int64 `json:"status,options=0|1"` -} - type Request struct { } diff --git a/server_api/product.api b/server_api/product.api index a1db4ad2..9c214c82 100644 --- a/server_api/product.api +++ b/server_api/product.api @@ -70,7 +70,7 @@ service product { get /api/product/get_last_product_design(request) returns (response); //*********************产品详情分解接口结束*********************** //*********************推荐产品接口开始×××××××××××××××××××××××××× - + //*********************推荐产品接口结束×××××××××××××××××××××××××× } @@ -291,6 +291,7 @@ type GetRecommandProductListRsp { CoverImg string `json:"cover_img"` CoverDefault string `json:"cover_default"` Intro string `json:"intro"` + IsRecommend int64 `json:"is_recommend"` } //获取分类产品列表 type GetTagProductListReq { @@ -415,4 +416,4 @@ type GetLastProductDesignRsp { SizeId int64 `json:"size_id"` LogoColor interface{} `json:"logo_color"` Info interface{} `json:"info"` -} +} \ No newline at end of file