From ea1335607a9c3e85407acf5938c2d7817e7ed4bb Mon Sep 17 00:00:00 2001
From: laodaming <11058467+laudamine@user.noreply.gitee.com>
Date: Tue, 17 Oct 2023 15:33:46 +0800
Subject: [PATCH 01/11] =?UTF-8?q?=E6=95=B4=E5=90=88=E7=9B=AE=E5=89=8D?=
=?UTF-8?q?=E6=96=B0=E7=9A=84=E8=AF=A6=E6=83=85=E6=8E=A5=E5=8F=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
model/gmodel/fs_product_model3d_logic.go | 17 +-
model/gmodel/fs_product_template_v2_logic.go | 19 +-
.../handler/getproductdetailhandler.go | 35 ++
server/product/internal/handler/routes.go | 5 +
.../internal/logic/getproductdetaillogic.go | 365 ++++++++++++++++++
.../logic/getrecommandproductlistlogic.go | 8 +-
.../internal/logic/getsizebypidlogic.go | 17 +-
.../internal/logic/gettagproductlistlogic.go | 8 +-
.../homepagerecommendproductlistlogic.go | 8 +-
server/product/internal/types/types.go | 64 +++
server_api/product.api | 86 +++--
11 files changed, 568 insertions(+), 64 deletions(-)
create mode 100644 server/product/internal/handler/getproductdetailhandler.go
create mode 100644 server/product/internal/logic/getproductdetaillogic.go
diff --git a/model/gmodel/fs_product_model3d_logic.go b/model/gmodel/fs_product_model3d_logic.go
index 92a54a39..ced105c5 100755
--- a/model/gmodel/fs_product_model3d_logic.go
+++ b/model/gmodel/fs_product_model3d_logic.go
@@ -173,12 +173,7 @@ func (d *FsProductModel3dModel) GetAllByProductIdsTags(ctx context.Context, prod
}
// 获取每个产品最低价格
-func (d *FsProductModel3dModel) GetProductMinPrice(ctx context.Context, productIds []int64, mapProductMinPrice map[int64]int64) error {
- //获取产品模型价格列表
- modelList, err := d.GetAllByProductIdsTags(ctx, productIds, []int{constants.TAG_MODEL, constants.TAG_PARTS}, "id,product_id,price,tag,part_id,step_price")
- if err != nil {
- return errors.New("failed to get model list")
- }
+func (d *FsProductModel3dModel) GetProductMinPrice(modelList []FsProductModel3d, mapProductMinPrice map[int64]int64) error {
mapModelMinPrice := make(map[int64]int64)
//每个模型/配件存储最小价格
for _, modelInfo := range modelList {
@@ -189,7 +184,7 @@ func (d *FsProductModel3dModel) GetProductMinPrice(ctx context.Context, productI
continue
}
var stepPrice StepPriceJsonStruct
- if err = json.Unmarshal(*modelInfo.StepPrice, &stepPrice); err != nil {
+ if err := json.Unmarshal(*modelInfo.StepPrice, &stepPrice); err != nil {
return errors.New(fmt.Sprintf("failed to parse model step price:%d", modelInfo.Id))
}
lenRange := len(stepPrice.PriceRange)
@@ -226,3 +221,11 @@ func (d *FsProductModel3dModel) GetProductMinPrice(ctx context.Context, productI
}
return nil
}
+func (d *FsProductModel3dModel) GetAllByProductIdTags(ctx context.Context, productId int64, tags []int64, fields ...string) (resp []FsProductModel3d, err error) {
+ db := d.db.WithContext(ctx).Model(&FsProductModel3d{}).Where("`product_id`= ? and `tag` in(?) and `status` = ?", productId, tags, 1)
+ if len(fields) != 0 {
+ db = db.Select(fields[0])
+ }
+ err = db.Find(&resp).Error
+ return resp, err
+}
diff --git a/model/gmodel/fs_product_template_v2_logic.go b/model/gmodel/fs_product_template_v2_logic.go
index 1462d7b9..3bacf94b 100755
--- a/model/gmodel/fs_product_template_v2_logic.go
+++ b/model/gmodel/fs_product_template_v2_logic.go
@@ -18,15 +18,16 @@ func (t *FsProductTemplateV2Model) FindAllByProductIds(ctx context.Context, prod
err = db.Find(&resp).Error
return resp, err
}
-func (t *FsProductTemplateV2Model) FindAllByIds(ctx context.Context, ids []int64) (resp []FsProductTemplateV2, err error) {
+func (t *FsProductTemplateV2Model) FindAllByIds(ctx context.Context, ids []int64, fields ...string) (resp []FsProductTemplateV2, err error) {
if len(ids) == 0 {
return
}
- err = t.db.WithContext(ctx).Model(&FsProductTemplateV2{}).Where("`id` in (?) and `is_del` = ? and `status` = ?", ids, 0, 1).Find(&resp).Error
- if err != nil {
- return nil, err
+ db := t.db.WithContext(ctx).Model(&FsProductTemplateV2{}).Where("`id` in (?) and `is_del` = ? and `status` = ?", ids, 0, 1)
+ if len(fields) != 0 {
+ db = db.Select(fields[0])
}
- return
+ err = db.Find(&resp).Error
+ return resp, err
}
func (t *FsProductTemplateV2Model) FindAllByIdsWithoutStatus(ctx context.Context, ids []int64, fields ...string) (resp []FsProductTemplateV2, err error) {
if len(ids) == 0 {
@@ -179,3 +180,11 @@ func (t *FsProductTemplateV2Model) FindAllByProductIdsTemplateTag(ctx context.Co
err = db.Find(&resp).Error
return resp, err
}
+func (t *FsProductTemplateV2Model) FindAllByFittingIds(ctx context.Context, fittingIds []int64, fields ...string) (resp []FsProductTemplateV2, err error) {
+ db := t.db.WithContext(ctx).Model(&FsProductTemplateV2{}).Where("`model_id` in(?) and `status` = ? and `is_del` = ? ", fittingIds, 1, 0)
+ if len(fields) != 0 {
+ db = db.Select(fields[0])
+ }
+ err = db.Find(&resp).Error
+ return resp, err
+}
diff --git a/server/product/internal/handler/getproductdetailhandler.go b/server/product/internal/handler/getproductdetailhandler.go
new file mode 100644
index 00000000..ef0a1725
--- /dev/null
+++ b/server/product/internal/handler/getproductdetailhandler.go
@@ -0,0 +1,35 @@
+package handler
+
+import (
+ "net/http"
+ "reflect"
+
+ "fusenapi/utils/basic"
+
+ "fusenapi/server/product/internal/logic"
+ "fusenapi/server/product/internal/svc"
+ "fusenapi/server/product/internal/types"
+)
+
+func GetProductDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+
+ var req types.GetProductDetailReq
+ userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
+ if err != nil {
+ return
+ }
+
+ // 创建一个业务逻辑层实例
+ l := logic.NewGetProductDetailLogic(r.Context(), svcCtx)
+
+ rl := reflect.ValueOf(l)
+ basic.BeforeLogic(w, r, rl)
+
+ resp := l.GetProductDetail(&req, userinfo)
+
+ if !basic.AfterLogic(w, r, rl, resp) {
+ basic.NormalAfterLogic(w, r, resp)
+ }
+ }
+}
diff --git a/server/product/internal/handler/routes.go b/server/product/internal/handler/routes.go
index 2d0b468c..589462eb 100644
--- a/server/product/internal/handler/routes.go
+++ b/server/product/internal/handler/routes.go
@@ -72,6 +72,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/api/product/home_page_recommend",
Handler: HomePageRecommendProductListHandler(serverCtx),
},
+ {
+ Method: http.MethodGet,
+ Path: "/api/product/get_product_detail",
+ Handler: GetProductDetailHandler(serverCtx),
+ },
},
)
}
diff --git a/server/product/internal/logic/getproductdetaillogic.go b/server/product/internal/logic/getproductdetaillogic.go
new file mode 100644
index 00000000..9fde3ed2
--- /dev/null
+++ b/server/product/internal/logic/getproductdetaillogic.go
@@ -0,0 +1,365 @@
+package logic
+
+import (
+ "encoding/json"
+ "errors"
+ "fusenapi/constants"
+ "fusenapi/model/gmodel"
+ "fusenapi/utils/auth"
+ "fusenapi/utils/basic"
+ "fusenapi/utils/color_list"
+ "fusenapi/utils/format"
+ "fusenapi/utils/s3url_to_s3id"
+ "fusenapi/utils/template_switch_info"
+ "gorm.io/gorm"
+ "strings"
+
+ "context"
+
+ "fusenapi/server/product/internal/svc"
+ "fusenapi/server/product/internal/types"
+
+ "github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetProductDetailLogic struct {
+ logx.Logger
+ ctx context.Context
+ svcCtx *svc.ServiceContext
+}
+
+func NewGetProductDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetProductDetailLogic {
+ return &GetProductDetailLogic{
+ Logger: logx.WithContext(ctx),
+ ctx: ctx,
+ svcCtx: svcCtx,
+ }
+}
+
+// 处理进入前逻辑w,r
+// func (l *GetProductDetailLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
+// }
+
+func (l *GetProductDetailLogic) GetProductDetail(req *types.GetProductDetailReq, userinfo *auth.UserInfo) (resp *basic.Response) {
+ if req.ProductId <= 0 {
+ return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "err param:product id is invalid")
+ }
+ req.TemplateTag = strings.Trim(req.TemplateTag, " ")
+ if req.TemplateTag == "" {
+ return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "err param:template tag is invalid")
+ }
+ //获取产品信息
+ productInfo, err := l.svcCtx.AllModels.FsProduct.FindOne(l.ctx, req.ProductId)
+ if err != nil {
+ if errors.Is(err, gorm.ErrRecordNotFound) {
+ return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the product is not exists")
+ }
+ logx.Error(err)
+ return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product info")
+ }
+ if *productInfo.Status != 1 {
+ return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "the product status is unNormal")
+ }
+ if *productInfo.IsShelf != 1 {
+ return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "the product status is off shelf")
+ }
+ if *productInfo.IsDel == 1 {
+ return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "the product status is deleted")
+ }
+ //获取产品类型
+ productTag, err := l.svcCtx.AllModels.FsTags.FindOne(l.ctx, *productInfo.Type)
+ if err != nil {
+ if errors.Is(err, gorm.ErrRecordNotFound) {
+ return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the product`s tag is not exists")
+ }
+ logx.Error(err)
+ return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product tag info")
+ }
+ //获取模板标签颜色选择信息
+ templateTagColorInfo, err := l.GetTemplateTagColor(req, userinfo)
+ if err != nil {
+ return resp.SetStatusWithMessage(basic.CodeServiceErr, err.Error())
+ }
+ //获取产品尺寸列表
+ sizeList, err := l.svcCtx.AllModels.FsProductSize.GetAllByProductIds(l.ctx, []int64{req.ProductId}, "is_hot DESC,sort ASC")
+ if err != nil {
+ logx.Error(err)
+ return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get size list")
+ }
+ //获取模型+配件信息
+ modelList, err := l.svcCtx.AllModels.FsProductModel3d.GetAllByProductIdTags(l.ctx, req.ProductId, []int64{constants.TAG_MODEL, constants.TAG_PARTS})
+ if err != nil {
+ logx.Error(err)
+ return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get model list")
+ }
+ mapSizeKeyModel := make(map[int64]int) //模型(不包含配件)sizeId为key
+ mapFitting := make(map[int64]int) //配件
+ publicFittingOptionTemplateIds := make([]int64, 0, len(modelList)) //配件配置了公共模板的模板id
+ notPublicFittingOptionTemplateFittingIds := make([]int64, 0, len(modelList)) //配件没有配置公共模板的配件id
+ lightIds := make([]int64, 0, len(modelList))
+ for k, v := range modelList {
+ switch *v.Tag {
+ case constants.TAG_MODEL: //模型的
+ mapSizeKeyModel[*v.SizeId] = k
+ if *v.Light > 0 {
+ lightIds = append(lightIds, *v.Light)
+ }
+ case constants.TAG_PARTS: //配件的
+ mapFitting[v.Id] = k
+ if *v.OptionTemplate > 0 {
+ publicFittingOptionTemplateIds = append(publicFittingOptionTemplateIds, *v.OptionTemplate)
+ } else {
+ notPublicFittingOptionTemplateFittingIds = append(notPublicFittingOptionTemplateFittingIds, v.Id)
+ }
+ }
+ }
+ //获取没有绑定公共模板的配件贴图
+ notPublicFittingOptionTemplateList, err := l.svcCtx.AllModels.FsProductTemplateV2.FindAllByFittingIds(l.ctx, notPublicFittingOptionTemplateFittingIds, "id,model_id,material_img")
+ if err != nil {
+ logx.Error(err)
+ return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get fitting material image list")
+ }
+ mapNotPublicFittingOptionTemplateMaterialImage := make(map[int64]string) //model_id为key
+ for _, v := range notPublicFittingOptionTemplateList {
+ mapNotPublicFittingOptionTemplateMaterialImage[*v.ModelId] = *v.MaterialImg
+ }
+ //获取配件绑定的公共模板列表
+ publicFittingOptionTemplateList, err := l.svcCtx.AllModels.FsProductTemplateV2.FindAllByIds(l.ctx, publicFittingOptionTemplateIds, "id,model_id,material_img")
+ if err != nil {
+ logx.Error(err)
+ return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get fitting optional template list")
+ }
+ mapPublicFittingOptionTemplate := make(map[int64]string) //模板id为key
+ for _, v := range publicFittingOptionTemplateList {
+ mapPublicFittingOptionTemplate[v.Id] = *v.MaterialImg
+ }
+ //获取灯光列表
+ lightList, err := l.svcCtx.AllModels.FsProductModel3dLight.GetAllByIds(l.ctx, lightIds)
+ if err != nil {
+ logx.Error(err)
+ return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get light list")
+ }
+ mapLight := make(map[int64]int)
+ for k, v := range lightList {
+ mapLight[v.Id] = k
+ }
+ //获取产品模板列表
+ templateList, err := l.svcCtx.AllModels.FsProductTemplateV2.FindAllByProductIdsTemplateTag(l.ctx, []int64{req.ProductId}, req.TemplateTag, "")
+ if err != nil {
+ logx.Error(err)
+ return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get template list")
+ }
+ mapModelIdKeyTemplate := make(map[int64]int)
+ for k, v := range templateList {
+ mapModelIdKeyTemplate[*v.ModelId] = k
+ }
+ //记录产品最低价
+ mapProductMinPrice := make(map[int64]int64)
+ if err = l.svcCtx.AllModels.FsProductModel3d.GetProductMinPrice(modelList, mapProductMinPrice); err != nil {
+ logx.Error(err)
+ return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get product min price")
+ }
+ //整理返回
+ rspSizeList := make([]types.SizeInfo, 0, len(sizeList))
+ for _, sizeInfo := range sizeList {
+ var sizeTitle interface{}
+ if err = json.Unmarshal([]byte(*sizeInfo.Title), &sizeTitle); err != nil {
+ logx.Error(err)
+ return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse size title")
+ }
+ //尺寸下最低价
+ minPrice := ""
+ if price, ok := mapProductMinPrice[*sizeInfo.ProductId]; ok {
+ minPrice = format.CentitoDollar(price, 3)
+ }
+ var modelInfoRsp types.ModelInfo
+ var TemplateInfoRsp interface{}
+ var FittingListRsp = make([]types.FittingInfo, 0, 10)
+ if modelIndex, ok := mapSizeKeyModel[sizeInfo.Id]; ok {
+ modelInfo := modelList[modelIndex]
+ //模板信息
+ if templateIndex, ok := mapModelIdKeyTemplate[modelInfo.Id]; ok {
+ templateInfo := templateList[templateIndex]
+ //获取开关信息
+ TemplateInfoRsp = template_switch_info.GetTemplateSwitchInfo(templateInfo.Id, templateInfo.TemplateInfo, *templateInfo.MaterialImg)
+ }
+ //赋值id
+ modelInfoRsp.Id = modelInfo.Id
+ //模型设计信息
+ var modelDesignInfo interface{}
+ if modelInfo.ModelInfo != nil && *modelInfo.ModelInfo != "" {
+ if err = json.Unmarshal([]byte(*modelInfo.ModelInfo), &modelDesignInfo); err != nil {
+ logx.Error(err)
+ return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse model design info")
+ }
+ //赋值
+ modelInfoRsp.ModelDesignInfo = modelDesignInfo
+ }
+ //灯光信息
+ if lightIndex, ok := mapLight[*modelInfo.Light]; ok {
+ lightInfo := lightList[lightIndex]
+ var lightDesignInfo interface{}
+ if lightInfo.Info != nil && *lightInfo.Info != "" {
+ if err = json.Unmarshal([]byte(*lightInfo.Info), &lightDesignInfo); err != nil {
+ logx.Error(err)
+ return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse light design info")
+ }
+ //赋值
+ modelInfoRsp.LightInfo = types.LightInfo{
+ Id: lightInfo.Id,
+ LightName: *lightInfo.Name,
+ LightDesignInfo: lightDesignInfo,
+ }
+ }
+ }
+ optionalFittingIdsStr := strings.Trim(*modelInfo.PartList, " ")
+ optionalFittingIdsStr = strings.Trim(optionalFittingIdsStr, ",")
+ //配件信息
+ if optionalFittingIdsStr != "" {
+ optionalFittingIds, err := format.StrSlicToInt64Slice(strings.Split(optionalFittingIdsStr, ","))
+ if err != nil {
+ logx.Error(err)
+ return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to split optional fitting list")
+ }
+ //可选配件
+ for _, optionFittingId := range optionalFittingIds {
+ fittingIndex, ok := mapFitting[optionFittingId]
+ if !ok {
+ continue
+ }
+ fittingInfo := modelList[fittingIndex]
+ var fittingDesignInfo interface{}
+ if fittingInfo.ModelInfo == nil || *fittingInfo.ModelInfo == "" {
+ continue
+ }
+ if err = json.Unmarshal([]byte(*fittingInfo.ModelInfo), &fittingDesignInfo); err != nil {
+ logx.Error(err)
+ return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse fitting design info")
+ }
+ //是否默认显示配件
+ isDefault := int64(0)
+ if optionFittingId == *modelInfo.PartId {
+ isDefault = 1
+ }
+ //配件贴图
+ FittingMaterialImg := ""
+ //贴图,如果绑定了公共模板,则获取公共模板的贴图数据(待优化)
+ if *fittingInfo.OptionTemplate > 0 {
+ if image, ok := mapPublicFittingOptionTemplate[*fittingInfo.OptionTemplate]; ok {
+ FittingMaterialImg = image
+ }
+ } else { //否则取该配件下的模板贴图
+ if image, ok := mapNotPublicFittingOptionTemplateMaterialImage[fittingInfo.Id]; ok {
+ FittingMaterialImg = image
+ }
+ }
+ FittingListRsp = append(FittingListRsp, types.FittingInfo{
+ Id: fittingInfo.Id,
+ IsHot: *fittingInfo.IsHot,
+ MaterialImage: FittingMaterialImg,
+ DesignInfo: fittingDesignInfo,
+ Price: format.CentitoDollar(*fittingInfo.Price, 3),
+ Name: *fittingInfo.Name,
+ IsDefault: isDefault,
+ })
+ }
+
+ }
+ }
+ rspSizeList = append(rspSizeList, types.SizeInfo{
+ Id: sizeInfo.Id,
+ Title: sizeTitle,
+ Capacity: *sizeInfo.Capacity,
+ PartsCanDeleted: *sizeInfo.PartsCanDeleted,
+ IsHot: *sizeInfo.IsHot,
+ MinPrice: minPrice,
+ TemplateInfo: TemplateInfoRsp,
+ ModelInfo: modelInfoRsp,
+ FittingList: FittingListRsp,
+ })
+ }
+ return resp.SetStatusWithMessage(basic.CodeOK, "success", types.GetProductDetailRsp{
+ TemplateTagColorInfo: templateTagColorInfo,
+ ProductInfo: types.ProductInfo{
+ Id: productInfo.Id,
+ ProductType: *productInfo.Type,
+ ProductTypeName: *productTag.Title,
+ Title: *productInfo.Title,
+ IsEnv: *productInfo.IsProtection,
+ IsMicro: *productInfo.IsMicrowave,
+ IsCustomization: *productInfo.IsCustomization,
+ },
+ BaseColors: color_list.GetColor(),
+ SizeList: rspSizeList,
+ })
+}
+
+// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
+// func (l *GetProductDetailLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
+// // httpx.OkJsonCtx(r.Context(), w, resp)
+// }
+func (l *GetProductDetailLogic) GetTemplateTagColor(req *types.GetProductDetailReq, userinfo *auth.UserInfo) (resp types.TemplateTagColorInfo, err error) {
+ if req.SelectColorIndex < 0 {
+ return types.TemplateTagColorInfo{}, errors.New("param selected_color_index is invalid")
+ }
+ //根据logo查询素材资源
+ resourceId := s3url_to_s3id.GetS3ResourceIdFormUrl(req.Logo)
+ if resourceId == "" {
+ return types.TemplateTagColorInfo{}, errors.New("param logo is invalid")
+ }
+ var (
+ userMaterial *gmodel.FsUserMaterial
+ templateTagInfo *gmodel.FsProductTemplateTags
+ )
+ //获取模板标签信息
+ templateTagInfo, err = l.svcCtx.AllModels.FsProductTemplateTags.FindOneByTagName(l.ctx, req.TemplateTag)
+ if err != nil {
+ if errors.Is(err, gorm.ErrRecordNotFound) {
+ return types.TemplateTagColorInfo{}, errors.New("the template tag is not exists")
+ }
+ logx.Error(err)
+ return types.TemplateTagColorInfo{}, errors.New("failed to get template tag info")
+ }
+ userMaterial, err = l.svcCtx.AllModels.FsUserMaterial.FindOneByLogoResourceId(l.ctx, resourceId)
+ if err != nil {
+ if errors.Is(err, gorm.ErrRecordNotFound) {
+ return types.TemplateTagColorInfo{}, errors.New("the logo is not found")
+ }
+ logx.Error(err)
+ return types.TemplateTagColorInfo{}, errors.New("failed to get user material")
+ }
+ if userMaterial.Metadata == nil || len(*userMaterial.Metadata) == 0 {
+ return types.TemplateTagColorInfo{}, errors.New("the user material is empty")
+ }
+ //解析用户素材元数据
+ var metaData map[string]interface{}
+ if err = json.Unmarshal(*userMaterial.Metadata, &metaData); err != nil {
+ logx.Error(err)
+ return types.TemplateTagColorInfo{}, errors.New("failed to parse user metadata")
+ }
+ var mapMaterialTemplateTag map[string][][]string
+ b, _ := json.Marshal(metaData["template_tag"])
+ if err = json.Unmarshal(b, &mapMaterialTemplateTag); err != nil {
+ logx.Error(err)
+ return types.TemplateTagColorInfo{}, errors.New("invalid format of metadata`s template_tag")
+ }
+ colors, ok := mapMaterialTemplateTag[req.TemplateTag]
+ if !ok {
+ return types.TemplateTagColorInfo{}, errors.New("the template tag is not found from this logo material`s metadata")
+ }
+ if req.SelectColorIndex >= len(colors) {
+ return types.TemplateTagColorInfo{}, errors.New("select color index is out of range !!")
+ }
+ var templateTagGroups interface{}
+ if templateTagInfo.Groups != nil && *templateTagInfo.Groups != "" {
+ if err = json.Unmarshal([]byte(*templateTagInfo.Groups), &templateTagGroups); err != nil {
+ logx.Error(err)
+ return types.TemplateTagColorInfo{}, errors.New("failed to parse template tag`s groups info")
+ }
+ }
+ return types.TemplateTagColorInfo{
+ Colors: colors,
+ SelectedColorIndex: req.SelectColorIndex,
+ TemplateTagGroups: templateTagGroups,
+ }, nil
+}
diff --git a/server/product/internal/logic/getrecommandproductlistlogic.go b/server/product/internal/logic/getrecommandproductlistlogic.go
index 2877ef95..0debe6e8 100644
--- a/server/product/internal/logic/getrecommandproductlistlogic.go
+++ b/server/product/internal/logic/getrecommandproductlistlogic.go
@@ -3,6 +3,7 @@ package logic
import (
"encoding/json"
"errors"
+ "fusenapi/constants"
"fusenapi/model/gmodel"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
@@ -93,7 +94,12 @@ func (l *GetRecommandProductListLogic) GetRecommandProductList(req *types.GetRec
}
//获取产品最低价
mapProductMinPrice := make(map[int64]int64)
- if err = l.svcCtx.AllModels.FsProductModel3d.GetProductMinPrice(l.ctx, productIds, mapProductMinPrice); err != nil {
+ modelList, err := l.svcCtx.AllModels.FsProductModel3d.GetAllByProductIdsTags(l.ctx, []int64{productInfo.Id}, []int{constants.TAG_MODEL, constants.TAG_PARTS}, "id,size_id,product_id,price,tag,part_id,step_price")
+ if err != nil {
+ logx.Error(err)
+ return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get model list")
+ }
+ if err = l.svcCtx.AllModels.FsProductModel3d.GetProductMinPrice(modelList, mapProductMinPrice); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product min price")
}
diff --git a/server/product/internal/logic/getsizebypidlogic.go b/server/product/internal/logic/getsizebypidlogic.go
index 46d81e4f..d83e4dd7 100644
--- a/server/product/internal/logic/getsizebypidlogic.go
+++ b/server/product/internal/logic/getsizebypidlogic.go
@@ -74,25 +74,26 @@ func (l *GetSizeByPidLogic) GetSizeByPid(req *types.GetSizeByPidReq, userinfo *a
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get size list")
}
sizeIds := make([]int64, 0, len(sizeList))
- productIds := make([]int64, 0, len(sizeList))
for _, v := range sizeList {
sizeIds = append(sizeIds, v.Id)
- productIds = append(productIds, *v.ProductId)
}
//获取产品价格列表
mapProductMinPrice := make(map[int64]int64)
- if err = l.svcCtx.AllModels.FsProductModel3d.GetProductMinPrice(l.ctx, productIds, mapProductMinPrice); err != nil {
- logx.Error(err)
- return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product min price")
- }
- //获取对应模型数据
- modelList, err := l.svcCtx.AllModels.FsProductModel3d.GetAllBySizeIdsTag(l.ctx, sizeIds, constants.TAG_MODEL, "id,size_id")
+ //获取产品模型
+ modelList, err := l.svcCtx.AllModels.FsProductModel3d.GetAllByProductIdsTags(l.ctx, []int64{productInfo.Id}, []int{constants.TAG_MODEL, constants.TAG_PARTS}, "id,size_id,product_id,price,tag,part_id,step_price")
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get model list")
}
+ if err = l.svcCtx.AllModels.FsProductModel3d.GetProductMinPrice(modelList, mapProductMinPrice); err != nil {
+ logx.Error(err)
+ return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product min price")
+ }
mapSizeModel := make(map[int64]int) //size id为key
for k, v := range modelList {
+ if *v.Tag != constants.TAG_MODEL {
+ continue
+ }
mapSizeModel[*v.SizeId] = k
}
//处理
diff --git a/server/product/internal/logic/gettagproductlistlogic.go b/server/product/internal/logic/gettagproductlistlogic.go
index eae2abfb..4ffae478 100644
--- a/server/product/internal/logic/gettagproductlistlogic.go
+++ b/server/product/internal/logic/gettagproductlistlogic.go
@@ -3,6 +3,7 @@ package logic
import (
"encoding/json"
"errors"
+ "fusenapi/constants"
"fusenapi/model/gmodel"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
@@ -228,8 +229,13 @@ func (l *GetTagProductListLogic) getProductRelationInfo(req getProductRelationIn
CoverMetadata: req.MapResourceMetadata[*v.Cover],
})
}
+ modelList, err := l.svcCtx.AllModels.FsProductModel3d.GetAllByProductIdsTags(l.ctx, productIds, []int{constants.TAG_MODEL, constants.TAG_PARTS}, "id,size_id,product_id,price,tag,part_id,step_price")
+ if err != nil {
+ logx.Error(err)
+ return nil, errors.New("failed to get model list")
+ }
//获取产品最低价格
- if err = l.svcCtx.AllModels.FsProductModel3d.GetProductMinPrice(l.ctx, productIds, req.MapProductMinPrice); err != nil {
+ if err = l.svcCtx.AllModels.FsProductModel3d.GetProductMinPrice(modelList, req.MapProductMinPrice); err != nil {
logx.Error(err)
return nil, errors.New("failed to get product min price")
}
diff --git a/server/product/internal/logic/homepagerecommendproductlistlogic.go b/server/product/internal/logic/homepagerecommendproductlistlogic.go
index a4447811..f0bf6206 100644
--- a/server/product/internal/logic/homepagerecommendproductlistlogic.go
+++ b/server/product/internal/logic/homepagerecommendproductlistlogic.go
@@ -3,6 +3,7 @@ package logic
import (
"encoding/json"
"errors"
+ "fusenapi/constants"
"fusenapi/model/gmodel"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
@@ -113,7 +114,12 @@ func (l *HomePageRecommendProductListLogic) HomePageRecommendProductList(req *ty
}
//获取产品最低价格
mapProductMinPrice := make(map[int64]int64)
- if err = l.svcCtx.AllModels.FsProductModel3d.GetProductMinPrice(l.ctx, productIds, mapProductMinPrice); err != nil {
+ modelList, err := l.svcCtx.AllModels.FsProductModel3d.GetAllByProductIdsTags(l.ctx, productIds, []int{constants.TAG_MODEL, constants.TAG_PARTS}, "id,size_id,product_id,price,tag,part_id,step_price")
+ if err != nil {
+ logx.Error(err)
+ return resp.SetStatusWithMessage(basic.CodeServiceErr, "get product model list err")
+ }
+ if err = l.svcCtx.AllModels.FsProductModel3d.GetProductMinPrice(modelList, mapProductMinPrice); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get product min price")
}
diff --git a/server/product/internal/types/types.go b/server/product/internal/types/types.go
index 05455455..cfee8e8c 100644
--- a/server/product/internal/types/types.go
+++ b/server/product/internal/types/types.go
@@ -191,6 +191,70 @@ type HomePageRecommendProductListRsp struct {
IsCustomization int64 `json:"is_customization"`
}
+type GetProductDetailReq struct {
+ ProductId int64 `form:"product_id"` //产品id
+ TemplateTag string `form:"template_tag"` //模板标签
+ SelectColorIndex int `form:"select_color_index"` //模板标签颜色索引
+ Logo string `form:"logo"` //logo地址
+}
+
+type GetProductDetailRsp struct {
+ TemplateTagColorInfo TemplateTagColorInfo `json:"template_tag_color_info"` //标签颜色信息
+ ProductInfo ProductInfo `json:"product_info"` //产品基本信息
+ BaseColors interface{} `json:"base_colors"` //一些返回写死的颜色
+ SizeList []SizeInfo `json:"size_list"` //尺寸相关信息
+}
+
+type SizeInfo struct {
+ Id int64 `json:"id"` //尺寸id
+ Title interface{} `json:"title"` //尺寸标题信息
+ Capacity string `json:"capacity"` //尺寸名称
+ PartsCanDeleted int64 `json:"parts_can_deleted"` //配件是否可删除
+ IsHot int64 `json:"is_hot"` //是否热门
+ MinPrice string `json:"min_price"` //最低价
+ TemplateInfo interface{} `json:"template_info"` //模板相关信息
+ ModelInfo ModelInfo `json:"model_info"` //模型相关信息
+ FittingList []FittingInfo `json:"fitting_List"` //配件相关信息
+}
+
+type FittingInfo struct {
+ Id int64 `json:"id"` //配件id
+ IsHot int64 `json:"is_hot"` //是否热门
+ MaterialImage string `json:"material_image"` //配件材质图
+ DesignInfo interface{} `json:"design_info"` //配件设计信息
+ Price string `json:"price"` //配件价格
+ Name string `json:"name"` //配件名
+ IsDefault int64 `json:"is_default"` //是否默认的配件
+}
+
+type ModelInfo struct {
+ Id int64 `json:"id"` //模型id
+ ModelDesignInfo interface{} `json:"design_info"` //模型设计信息
+ LightInfo LightInfo `json:"light_info"` //灯光信息
+}
+
+type LightInfo struct {
+ Id int64 `json:"id"` //灯光id
+ LightName string `json:"light_name"` //灯光组名称
+ LightDesignInfo interface{} `json:"light_design_info"` //灯光设计信息
+}
+
+type ProductInfo struct {
+ Id int64 `json:"id"` //产品id
+ ProductType int64 `json:"product_type"` //产品类型id
+ ProductTypeName string `json:"product_type_name"` //产品类型名称
+ Title string `json:"title"` //产品标题
+ IsEnv int64 `json:"is_env"` //是否环保
+ IsMicro int64 `json:"is_micro"` //是否可微波炉
+ IsCustomization int64 `json:"is_customization"` //是否可定制产品
+}
+
+type TemplateTagColorInfo struct {
+ Colors [][]string `json:"colors"` //传入logo对应的算法颜色组
+ SelectedColorIndex int `json:"selected_color_index"` //选择的模板标签的颜色索引值
+ TemplateTagGroups interface{} `json:"template_tag_groups"` //模板标签分组信息
+}
+
type Request struct {
}
diff --git a/server_api/product.api b/server_api/product.api
index 5f586731..b1bfb0b6 100644
--- a/server_api/product.api
+++ b/server_api/product.api
@@ -227,55 +227,59 @@ type HomePageRecommendProductListRsp {
}
//获取产品详情(重构版)
-type GetProductDetailReq{
- ProductId int64 `form:"product_id"`//产品id
- TemplateTag string `form:"template_tag"` //模板标签
- SelectColorIndex int `form:"select_color_index"` //模板标签颜色索引
+type GetProductDetailReq {
+ ProductId int64 `form:"product_id"` //产品id
+ TemplateTag string `form:"template_tag"` //模板标签
+ SelectColorIndex int `form:"select_color_index"` //模板标签颜色索引
+ Logo string `form:"logo"` //logo地址
}
-type GetProductDetailRsp{
+type GetProductDetailRsp {
TemplateTagColorInfo TemplateTagColorInfo `json:"template_tag_color_info"` //标签颜色信息
- ProductInfo ProductInfo `json:"product_info"` //产品基本信息
- BaseColors interface{} `json:"base_colors"` //一些返回写死的颜色
- SizeInfo SizeInfo `json:"size_info"` //尺寸相关信息
+ ProductInfo ProductInfo `json:"product_info"` //产品基本信息
+ BaseColors interface{} `json:"base_colors"` //一些返回写死的颜色
+ SizeList []SizeInfo `json:"size_list"` //尺寸相关信息
}
-type SizeInfo{
- SizeId int64 `json:"size_id"`
- Title interface{} `json:"title"`
- Capacity string `json:"capacity"`
- PartsCanDeleted bool `json:"parts_can_deleted"`
- ModelId int64 `json:"model_id"`
- IsHot int64 `json:"is_hot"`
- MinPrice string `json:"min_price"`
- IsDefault bool `json:"is_default"`
- TemplateInfo TemplateInfo `json:"template_info"`
- ModelInfo ModelInfo `json:"model_info"`
+type SizeInfo {
+ Id int64 `json:"id"` //尺寸id
+ Title interface{} `json:"title"` //尺寸标题信息
+ Capacity string `json:"capacity"` //尺寸名称
+ PartsCanDeleted int64 `json:"parts_can_deleted"` //配件是否可删除
+ IsHot int64 `json:"is_hot"` //是否热门
+ MinPrice string `json:"min_price"` //最低价
+ TemplateInfo interface{} `json:"template_info"` //模板相关信息
+ ModelInfo ModelInfo `json:"model_info"` //模型相关信息
+ FittingList []FittingInfo `json:"fitting_List"` //配件相关信息
}
-type ModelInfo{
- ModelId int64 `json:"model_id"` //模型id
+type FittingInfo {
+ Id int64 `json:"id"` //配件id
+ IsHot int64 `json:"is_hot"` //是否热门
+ MaterialImage string `json:"material_image"` //配件材质图
+ DesignInfo interface{} `json:"design_info"` //配件设计信息
+ Price string `json:"price"` //配件价格
+ Name string `json:"name"` //配件名
+ IsDefault int64 `json:"is_default"` //是否默认的配件
+}
+type ModelInfo {
+ Id int64 `json:"id"` //模型id
ModelDesignInfo interface{} `json:"design_info"` //模型设计信息
- LightInfo LightInfo `json:"light_info"` //灯光信息
+ LightInfo LightInfo `json:"light_info"` //灯光信息
}
-type LightInfo{
- LightId int64 `json:"light_id"` //灯光id
- LightName string `json:"light_name"` //灯光组名称
+type LightInfo {
+ Id int64 `json:"id"` //灯光id
+ LightName string `json:"light_name"` //灯光组名称
LightDesignInfo interface{} `json:"light_design_info"` //灯光设计信息
}
-type TemplateInfo {
- TemplateSwitchInfo interface{} `json:"template_switch_info"` //对应模板标签下模板的开关信息,同列表页
- CombineIsVisible bool `json:"combine_is_visible"` //合图开关是否开启
- Material string `json:"material"` //默认素材
-}
-type ProductInfo{
- ProductId int64 `json:"product_id"` //产品id
- ProductType int64 `json:"product_type"` //产品类型id
+type ProductInfo {
+ Id int64 `json:"id"` //产品id
+ ProductType int64 `json:"product_type"` //产品类型id
ProductTypeName string `json:"product_type_name"` //产品类型名称
- Title string `json:"title"` //产品标题
- IsEnv int64 `json:"is_env"` //是否环保
- IsMicro int64 `json:"is_micro"` //是否可微波炉
- IsCustomization int64 `json:"is_customization"` //是否可定制产品
+ Title string `json:"title"` //产品标题
+ IsEnv int64 `json:"is_env"` //是否环保
+ IsMicro int64 `json:"is_micro"` //是否可微波炉
+ IsCustomization int64 `json:"is_customization"` //是否可定制产品
}
-type TemplateTagColorInfo{
- Colors []string `json:"colors"`
- SelectedColorIndex int `json:"selected_color_index"`
- TemplateTagGroups interface{} `json:"template_tag_groups"`
+type TemplateTagColorInfo {
+ Colors [][]string `json:"colors"` //传入logo对应的算法颜色组
+ SelectedColorIndex int `json:"selected_color_index"` //选择的模板标签的颜色索引值
+ TemplateTagGroups interface{} `json:"template_tag_groups"` //模板标签分组信息
}
\ No newline at end of file
From 68a31236b37045f201c8437856aa1e487f933a50 Mon Sep 17 00:00:00 2001
From: laodaming <11058467+laudamine@user.noreply.gitee.com>
Date: Tue, 17 Oct 2023 15:40:44 +0800
Subject: [PATCH 02/11] =?UTF-8?q?=E6=95=B4=E5=90=88=E7=9B=AE=E5=89=8D?=
=?UTF-8?q?=E6=96=B0=E7=9A=84=E8=AF=A6=E6=83=85=E6=8E=A5=E5=8F=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
server/websocket/internal/handler/routes.go | 5 +++++
server/websocket/internal/types/types.go | 4 ++++
server_api/websocket.api | 7 +++++++
3 files changed, 16 insertions(+)
diff --git a/server/websocket/internal/handler/routes.go b/server/websocket/internal/handler/routes.go
index 8a2c5bd1..4eefa507 100644
--- a/server/websocket/internal/handler/routes.go
+++ b/server/websocket/internal/handler/routes.go
@@ -27,6 +27,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/api/websocket/common_notify",
Handler: CommonNotifyHandler(serverCtx),
},
+ {
+ Method: http.MethodPost,
+ Path: "/api/websocket/close_websocket",
+ Handler: CloseWebsocketHandler(serverCtx),
+ },
},
)
}
diff --git a/server/websocket/internal/types/types.go b/server/websocket/internal/types/types.go
index 1bcd95d5..316ac30d 100644
--- a/server/websocket/internal/types/types.go
+++ b/server/websocket/internal/types/types.go
@@ -25,6 +25,10 @@ type CommonNotifyReq struct {
Data map[string]interface{} `json:"data"` //后端与前端约定好的数据
}
+type CloseWebsocketReq struct {
+ Wid string `json:"wid"`
+}
+
type Request struct {
}
diff --git a/server_api/websocket.api b/server_api/websocket.api
index b3c38975..43a39910 100644
--- a/server_api/websocket.api
+++ b/server_api/websocket.api
@@ -18,6 +18,9 @@ service websocket {
//通用回调接口
@handler CommonNotifyHandler
post /api/websocket/common_notify(CommonNotifyReq) returns (response);
+ //关闭某个连接
+ @handler CloseWebsocketHandler
+ post /api/websocket/close_websocket(CloseWebsocketReq) returns (response);
}
//websocket数据交互[
@@ -39,4 +42,8 @@ type CommonNotifyReq {
UserId int64 `json:"user_id,optional"` //用户id
GuestId int64 `json:"guest_id,optional"` //游客id
Data map[string]interface{} `json:"data"` //后端与前端约定好的数据
+}
+//关闭连接
+type CloseWebsocketReq {
+ Wid string `json:"wid"`
}
\ No newline at end of file
From e9255389e23e1c2d56d0959453ef67756736fa1c Mon Sep 17 00:00:00 2001
From: laodaming <11058467+laudamine@user.noreply.gitee.com>
Date: Tue, 17 Oct 2023 15:40:55 +0800
Subject: [PATCH 03/11] fix
---
.../internal/handler/closewebsockethandler.go | 35 +++++++++++++
.../internal/logic/closewebsocketlogic.go | 50 +++++++++++++++++++
2 files changed, 85 insertions(+)
create mode 100644 server/websocket/internal/handler/closewebsockethandler.go
create mode 100644 server/websocket/internal/logic/closewebsocketlogic.go
diff --git a/server/websocket/internal/handler/closewebsockethandler.go b/server/websocket/internal/handler/closewebsockethandler.go
new file mode 100644
index 00000000..b6f755e8
--- /dev/null
+++ b/server/websocket/internal/handler/closewebsockethandler.go
@@ -0,0 +1,35 @@
+package handler
+
+import (
+ "net/http"
+ "reflect"
+
+ "fusenapi/utils/basic"
+
+ "fusenapi/server/websocket/internal/logic"
+ "fusenapi/server/websocket/internal/svc"
+ "fusenapi/server/websocket/internal/types"
+)
+
+func CloseWebsocketHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+
+ var req types.CloseWebsocketReq
+ userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
+ if err != nil {
+ return
+ }
+
+ // 创建一个业务逻辑层实例
+ l := logic.NewCloseWebsocketLogic(r.Context(), svcCtx)
+
+ rl := reflect.ValueOf(l)
+ basic.BeforeLogic(w, r, rl)
+
+ resp := l.CloseWebsocket(&req, userinfo)
+
+ if !basic.AfterLogic(w, r, rl, resp) {
+ basic.NormalAfterLogic(w, r, resp)
+ }
+ }
+}
diff --git a/server/websocket/internal/logic/closewebsocketlogic.go b/server/websocket/internal/logic/closewebsocketlogic.go
new file mode 100644
index 00000000..72a5ef7c
--- /dev/null
+++ b/server/websocket/internal/logic/closewebsocketlogic.go
@@ -0,0 +1,50 @@
+package logic
+
+import (
+ "fusenapi/utils/auth"
+ "fusenapi/utils/basic"
+
+ "context"
+
+ "fusenapi/server/websocket/internal/svc"
+ "fusenapi/server/websocket/internal/types"
+
+ "github.com/zeromicro/go-zero/core/logx"
+)
+
+type CloseWebsocketLogic struct {
+ logx.Logger
+ ctx context.Context
+ svcCtx *svc.ServiceContext
+}
+
+func NewCloseWebsocketLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CloseWebsocketLogic {
+ return &CloseWebsocketLogic{
+ Logger: logx.WithContext(ctx),
+ ctx: ctx,
+ svcCtx: svcCtx,
+ }
+}
+
+// 处理进入前逻辑w,r
+// func (l *CloseWebsocketLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
+// }
+
+func (l *CloseWebsocketLogic) CloseWebsocket(req *types.CloseWebsocketReq, userinfo *auth.UserInfo) (resp *basic.Response) {
+ //获取连接
+ value, ok := mapConnPool.Load(req.Wid)
+ if !ok {
+ return resp.SetStatusAddMessage(basic.CodeRequestParamsErr, "wid connection is not exists")
+ }
+ ws, ok := value.(wsConnectItem)
+ if !ok {
+ return resp.SetStatusWithMessage(basic.CodeServiceErr, "渲染回调断言websocket连接失败")
+ }
+ ws.close()
+ return resp.SetStatus(basic.CodeOK, "断开成功")
+}
+
+// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
+// func (l *CloseWebsocketLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
+// // httpx.OkJsonCtx(r.Context(), w, resp)
+// }
From 0c5a5a466f24d3ed18d3509ed1b7730bad5ee485 Mon Sep 17 00:00:00 2001
From: laodaming <11058467+laudamine@user.noreply.gitee.com>
Date: Tue, 17 Oct 2023 15:56:48 +0800
Subject: [PATCH 04/11] fix
---
server/product/internal/types/types.go | 2 +-
server_api/product.api | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/server/product/internal/types/types.go b/server/product/internal/types/types.go
index cfee8e8c..c65d2c09 100644
--- a/server/product/internal/types/types.go
+++ b/server/product/internal/types/types.go
@@ -214,7 +214,7 @@ type SizeInfo struct {
MinPrice string `json:"min_price"` //最低价
TemplateInfo interface{} `json:"template_info"` //模板相关信息
ModelInfo ModelInfo `json:"model_info"` //模型相关信息
- FittingList []FittingInfo `json:"fitting_List"` //配件相关信息
+ FittingList []FittingInfo `json:"fitting_list"` //配件相关信息
}
type FittingInfo struct {
diff --git a/server_api/product.api b/server_api/product.api
index b1bfb0b6..691297dc 100644
--- a/server_api/product.api
+++ b/server_api/product.api
@@ -248,7 +248,7 @@ type SizeInfo {
MinPrice string `json:"min_price"` //最低价
TemplateInfo interface{} `json:"template_info"` //模板相关信息
ModelInfo ModelInfo `json:"model_info"` //模型相关信息
- FittingList []FittingInfo `json:"fitting_List"` //配件相关信息
+ FittingList []FittingInfo `json:"fitting_list"` //配件相关信息
}
type FittingInfo {
Id int64 `json:"id"` //配件id
From c79a1aab492c11e94b62c6e24cb1a22828e91392 Mon Sep 17 00:00:00 2001
From: laodaming <11058467+laudamine@user.noreply.gitee.com>
Date: Tue, 17 Oct 2023 16:19:44 +0800
Subject: [PATCH 05/11] fix
---
.../internal/logic/getproductdetaillogic.go | 39 +++++++++++++++++--
server/product/internal/types/types.go | 1 +
.../internal/logic/ws_render_image.go | 4 --
server_api/product.api | 1 +
4 files changed, 37 insertions(+), 8 deletions(-)
diff --git a/server/product/internal/logic/getproductdetaillogic.go b/server/product/internal/logic/getproductdetaillogic.go
index 9fde3ed2..12f4c528 100644
--- a/server/product/internal/logic/getproductdetaillogic.go
+++ b/server/product/internal/logic/getproductdetaillogic.go
@@ -159,6 +159,12 @@ func (l *GetProductDetailLogic) GetProductDetail(req *types.GetProductDetailReq,
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get product min price")
}
+ //获取默认渲染的尺寸
+ defaultSize, err := l.getRenderDefaultSize(req.ProductId, req.TemplateTag)
+ if err != nil {
+ logx.Error(err)
+ return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get default size")
+ }
//整理返回
rspSizeList := make([]types.SizeInfo, 0, len(sizeList))
for _, sizeInfo := range sizeList {
@@ -266,8 +272,13 @@ func (l *GetProductDetailLogic) GetProductDetail(req *types.GetProductDetailReq,
}
}
+ isDefaultSize := int64(0)
+ if sizeInfo.Id == defaultSize {
+ isDefaultSize = 1
+ }
rspSizeList = append(rspSizeList, types.SizeInfo{
Id: sizeInfo.Id,
+ IsDefault: isDefaultSize,
Title: sizeTitle,
Capacity: *sizeInfo.Capacity,
PartsCanDeleted: *sizeInfo.PartsCanDeleted,
@@ -294,10 +305,30 @@ func (l *GetProductDetailLogic) GetProductDetail(req *types.GetProductDetailReq,
})
}
-// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
-// func (l *GetProductDetailLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
-// // httpx.OkJsonCtx(r.Context(), w, resp)
-// }
+// 获取列表页默认渲染的尺寸(同列表页)
+func (l *GetProductDetailLogic) getRenderDefaultSize(productId int64, templateTag string) (sizeId int64, err error) {
+ //获取模板
+ productTemplate, err := l.svcCtx.AllModels.FsProductTemplateV2.FindOneCloudRenderByProductIdTemplateTag(l.ctx, productId, templateTag, "sort ASC", "model_id")
+ if err != nil {
+ if errors.Is(err, gorm.ErrRecordNotFound) {
+ return 0, errors.New("找不到对应开启云渲染模板")
+ }
+ logx.Error(err)
+ return 0, errors.New("获取对应开启云渲染模板失败")
+ }
+ //根据模板找到模型
+ model3d, err := l.svcCtx.AllModels.FsProductModel3d.FindOne(l.ctx, *productTemplate.ModelId, "size_id")
+ if err != nil {
+ if errors.Is(err, gorm.ErrRecordNotFound) {
+ return 0, errors.New("找不到对应模型")
+ }
+ logx.Error(err)
+ return 0, errors.New("获取对应模型失败")
+ }
+ return *model3d.SizeId, nil
+}
+
+// 获取对应模板标签颜色信息
func (l *GetProductDetailLogic) GetTemplateTagColor(req *types.GetProductDetailReq, userinfo *auth.UserInfo) (resp types.TemplateTagColorInfo, err error) {
if req.SelectColorIndex < 0 {
return types.TemplateTagColorInfo{}, errors.New("param selected_color_index is invalid")
diff --git a/server/product/internal/types/types.go b/server/product/internal/types/types.go
index c65d2c09..cb6e6448 100644
--- a/server/product/internal/types/types.go
+++ b/server/product/internal/types/types.go
@@ -207,6 +207,7 @@ type GetProductDetailRsp struct {
type SizeInfo struct {
Id int64 `json:"id"` //尺寸id
+ IsDefault int64 `json:"is_default"` //是否默认显示
Title interface{} `json:"title"` //尺寸标题信息
Capacity string `json:"capacity"` //尺寸名称
PartsCanDeleted int64 `json:"parts_can_deleted"` //配件是否可删除
diff --git a/server/websocket/internal/logic/ws_render_image.go b/server/websocket/internal/logic/ws_render_image.go
index 7b3d2f7d..f9c96331 100644
--- a/server/websocket/internal/logic/ws_render_image.go
+++ b/server/websocket/internal/logic/ws_render_image.go
@@ -145,10 +145,6 @@ func (w *wsConnectItem) consumeRenderImageData() {
// 执行渲染任务
func (w *wsConnectItem) renderImage(renderImageData websocket_data.RenderImageReqMsg) {
- /* if renderImageData.RenderData.Logo == "" {
- w.renderErrResponse(renderImageData.RenderId, renderImageData.RequestId, renderImageData.RenderData.TemplateTag, "", "请传入logo", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, 0, 0, 0)
- return
- }*/
if !strings.Contains(renderImageData.RenderData.Logo, "storage.fusenpack.com") {
w.renderErrResponse(renderImageData.RenderId, renderImageData.RequestId, renderImageData.RenderData.TemplateTag, "", "非法的logo", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, 0, 0, 0)
return
diff --git a/server_api/product.api b/server_api/product.api
index 691297dc..8180ee6b 100644
--- a/server_api/product.api
+++ b/server_api/product.api
@@ -241,6 +241,7 @@ type GetProductDetailRsp {
}
type SizeInfo {
Id int64 `json:"id"` //尺寸id
+ IsDefault int64 `json:"is_default"` //是否默认显示
Title interface{} `json:"title"` //尺寸标题信息
Capacity string `json:"capacity"` //尺寸名称
PartsCanDeleted int64 `json:"parts_can_deleted"` //配件是否可删除
From bfe0ee06523dd453bf6d3b629dc399fc58d6230e Mon Sep 17 00:00:00 2001
From: laodaming <11058467+laudamine@user.noreply.gitee.com>
Date: Tue, 17 Oct 2023 17:08:30 +0800
Subject: [PATCH 06/11] fix
---
.../internal/logic/getproductdetaillogic.go | 110 ++++++++++--------
1 file changed, 60 insertions(+), 50 deletions(-)
diff --git a/server/product/internal/logic/getproductdetaillogic.go b/server/product/internal/logic/getproductdetaillogic.go
index 12f4c528..a2dea1da 100644
--- a/server/product/internal/logic/getproductdetaillogic.go
+++ b/server/product/internal/logic/getproductdetaillogic.go
@@ -180,7 +180,7 @@ func (l *GetProductDetailLogic) GetProductDetail(req *types.GetProductDetailReq,
}
var modelInfoRsp types.ModelInfo
var TemplateInfoRsp interface{}
- var FittingListRsp = make([]types.FittingInfo, 0, 10)
+ var FittingListRsp []types.FittingInfo
if modelIndex, ok := mapSizeKeyModel[sizeInfo.Id]; ok {
modelInfo := modelList[modelIndex]
//模板信息
@@ -221,55 +221,9 @@ func (l *GetProductDetailLogic) GetProductDetail(req *types.GetProductDetailReq,
optionalFittingIdsStr := strings.Trim(*modelInfo.PartList, " ")
optionalFittingIdsStr = strings.Trim(optionalFittingIdsStr, ",")
//配件信息
- if optionalFittingIdsStr != "" {
- optionalFittingIds, err := format.StrSlicToInt64Slice(strings.Split(optionalFittingIdsStr, ","))
- if err != nil {
- logx.Error(err)
- return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to split optional fitting list")
- }
- //可选配件
- for _, optionFittingId := range optionalFittingIds {
- fittingIndex, ok := mapFitting[optionFittingId]
- if !ok {
- continue
- }
- fittingInfo := modelList[fittingIndex]
- var fittingDesignInfo interface{}
- if fittingInfo.ModelInfo == nil || *fittingInfo.ModelInfo == "" {
- continue
- }
- if err = json.Unmarshal([]byte(*fittingInfo.ModelInfo), &fittingDesignInfo); err != nil {
- logx.Error(err)
- return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse fitting design info")
- }
- //是否默认显示配件
- isDefault := int64(0)
- if optionFittingId == *modelInfo.PartId {
- isDefault = 1
- }
- //配件贴图
- FittingMaterialImg := ""
- //贴图,如果绑定了公共模板,则获取公共模板的贴图数据(待优化)
- if *fittingInfo.OptionTemplate > 0 {
- if image, ok := mapPublicFittingOptionTemplate[*fittingInfo.OptionTemplate]; ok {
- FittingMaterialImg = image
- }
- } else { //否则取该配件下的模板贴图
- if image, ok := mapNotPublicFittingOptionTemplateMaterialImage[fittingInfo.Id]; ok {
- FittingMaterialImg = image
- }
- }
- FittingListRsp = append(FittingListRsp, types.FittingInfo{
- Id: fittingInfo.Id,
- IsHot: *fittingInfo.IsHot,
- MaterialImage: FittingMaterialImg,
- DesignInfo: fittingDesignInfo,
- Price: format.CentitoDollar(*fittingInfo.Price, 3),
- Name: *fittingInfo.Name,
- IsDefault: isDefault,
- })
- }
-
+ FittingListRsp, err = l.GetModelOptionalFittings(l.ctx, optionalFittingIdsStr, mapFitting, mapPublicFittingOptionTemplate, mapNotPublicFittingOptionTemplateMaterialImage, modelInfo, modelList)
+ if err != nil {
+ return resp.SetStatusWithMessage(basic.CodeServiceErr, err.Error())
}
}
isDefaultSize := int64(0)
@@ -305,6 +259,62 @@ func (l *GetProductDetailLogic) GetProductDetail(req *types.GetProductDetailReq,
})
}
+// 获取模型可选配件列表
+func (l *GetProductDetailLogic) GetModelOptionalFittings(ctx context.Context, optionalFittingIdsStr string, mapFitting map[int64]int, mapPublicFittingOptionTemplate, mapNotPublicFittingOptionTemplateMaterialImage map[int64]string, modelInfo gmodel.FsProductModel3d, modelList []gmodel.FsProductModel3d) (resp []types.FittingInfo, err error) {
+ if optionalFittingIdsStr == "" {
+ return
+ }
+ optionalFittingIds, err := format.StrSlicToInt64Slice(strings.Split(optionalFittingIdsStr, ","))
+ if err != nil {
+ logx.Error(err)
+ return nil, errors.New("failed to split optional fitting list")
+ }
+ resp = make([]types.FittingInfo, 0, len(optionalFittingIds))
+ //可选配件
+ for _, optionFittingId := range optionalFittingIds {
+ fittingIndex, ok := mapFitting[optionFittingId]
+ if !ok {
+ continue
+ }
+ fittingInfo := modelList[fittingIndex]
+ var fittingDesignInfo interface{}
+ if fittingInfo.ModelInfo == nil || *fittingInfo.ModelInfo == "" {
+ continue
+ }
+ if err = json.Unmarshal([]byte(*fittingInfo.ModelInfo), &fittingDesignInfo); err != nil {
+ logx.Error(err)
+ return nil, errors.New("failed to parse fitting design info")
+ }
+ //是否默认显示配件
+ isDefault := int64(0)
+ if optionFittingId == *modelInfo.PartId {
+ isDefault = 1
+ }
+ //配件贴图
+ FittingMaterialImg := ""
+ //贴图,如果绑定了公共模板,则获取公共模板的贴图数据(待优化)
+ if *fittingInfo.OptionTemplate > 0 {
+ if image, ok := mapPublicFittingOptionTemplate[*fittingInfo.OptionTemplate]; ok {
+ FittingMaterialImg = image
+ }
+ } else { //否则取该配件下的模板贴图
+ if image, ok := mapNotPublicFittingOptionTemplateMaterialImage[fittingInfo.Id]; ok {
+ FittingMaterialImg = image
+ }
+ }
+ resp = append(resp, types.FittingInfo{
+ Id: fittingInfo.Id,
+ IsHot: *fittingInfo.IsHot,
+ MaterialImage: FittingMaterialImg,
+ DesignInfo: fittingDesignInfo,
+ Price: format.CentitoDollar(*fittingInfo.Price, 3),
+ Name: *fittingInfo.Name,
+ IsDefault: isDefault,
+ })
+ }
+ return resp, nil
+}
+
// 获取列表页默认渲染的尺寸(同列表页)
func (l *GetProductDetailLogic) getRenderDefaultSize(productId int64, templateTag string) (sizeId int64, err error) {
//获取模板
From 68cf3a10d61c97d0093ffcc31a5b75acb3e965a6 Mon Sep 17 00:00:00 2001
From: laodaming <11058467+laudamine@user.noreply.gitee.com>
Date: Tue, 17 Oct 2023 17:25:34 +0800
Subject: [PATCH 07/11] fix
---
.../product/internal/logic/getproductdetaillogic.go | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/server/product/internal/logic/getproductdetaillogic.go b/server/product/internal/logic/getproductdetaillogic.go
index a2dea1da..724e6797 100644
--- a/server/product/internal/logic/getproductdetaillogic.go
+++ b/server/product/internal/logic/getproductdetaillogic.go
@@ -278,12 +278,11 @@ func (l *GetProductDetailLogic) GetModelOptionalFittings(ctx context.Context, op
}
fittingInfo := modelList[fittingIndex]
var fittingDesignInfo interface{}
- if fittingInfo.ModelInfo == nil || *fittingInfo.ModelInfo == "" {
- continue
- }
- if err = json.Unmarshal([]byte(*fittingInfo.ModelInfo), &fittingDesignInfo); err != nil {
- logx.Error(err)
- return nil, errors.New("failed to parse fitting design info")
+ if fittingInfo.ModelInfo != nil && *fittingInfo.ModelInfo != "" {
+ if err = json.Unmarshal([]byte(*fittingInfo.ModelInfo), &fittingDesignInfo); err != nil {
+ logx.Error(err)
+ return nil, errors.New("failed to parse fitting design info")
+ }
}
//是否默认显示配件
isDefault := int64(0)
From b90f56502d0d7eeab0e3f40f99f92d998e29ff9b Mon Sep 17 00:00:00 2001
From: laodaming <11058467+laudamine@user.noreply.gitee.com>
Date: Tue, 17 Oct 2023 17:49:49 +0800
Subject: [PATCH 08/11] fix
---
server/websocket/internal/logic/datatransferlogic.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/server/websocket/internal/logic/datatransferlogic.go b/server/websocket/internal/logic/datatransferlogic.go
index ce77f9b8..b7dd3978 100644
--- a/server/websocket/internal/logic/datatransferlogic.go
+++ b/server/websocket/internal/logic/datatransferlogic.go
@@ -472,7 +472,7 @@ func (w *wsConnectItem) allocationProcessing(data []byte) {
//获取工厂实例
processor := w.newAllocationProcessor(parseInfo.T)
if processor == nil {
- logx.Error("未知消息类型:", string(data))
+ //logx.Error("未知消息类型:", string(data))
return
}
//执行工厂方法
From aa1ab9937a180050c754e67a0e2d8d936a042bf0 Mon Sep 17 00:00:00 2001
From: laodaming <11058467+laudamine@user.noreply.gitee.com>
Date: Tue, 17 Oct 2023 18:16:11 +0800
Subject: [PATCH 09/11] fix
---
model/gmodel/fs_user_info_logic.go | 4 ++--
.../internal/logic/getproducttemplatetagslogic.go | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/model/gmodel/fs_user_info_logic.go b/model/gmodel/fs_user_info_logic.go
index 0521b912..ce76d7cb 100644
--- a/model/gmodel/fs_user_info_logic.go
+++ b/model/gmodel/fs_user_info_logic.go
@@ -79,9 +79,9 @@ func (m *FsUserInfoModel) GetProfile(ctx context.Context, pkey string, userId in
}
return info, nil
}
-func (m *FsUserInfoModel) FindOneByUser(ctx context.Context, userId, guestId int64) (resp *FsUserInfo, err error) {
+func (m *FsUserInfoModel) FindOneByUser(ctx context.Context, userId, guestId int64, module string) (resp *FsUserInfo, err error) {
if userId > 0 {
- err = m.db.WithContext(ctx).Model(&FsUserInfo{}).Where("user_id = ?", userId).Take(&resp).Error
+ err = m.db.WithContext(ctx).Model(&FsUserInfo{}).Where("user_id = ? and module = ?", userId, module).Take(&resp).Error
} else {
err = m.db.WithContext(ctx).Model(&FsUserInfo{}).Where("user_id = ? and guest_id = ?", userId, guestId).Take(&resp).Error
}
diff --git a/server/product-template-tag/internal/logic/getproducttemplatetagslogic.go b/server/product-template-tag/internal/logic/getproducttemplatetagslogic.go
index 47803452..31e0576f 100644
--- a/server/product-template-tag/internal/logic/getproducttemplatetagslogic.go
+++ b/server/product-template-tag/internal/logic/getproducttemplatetagslogic.go
@@ -70,7 +70,7 @@ func (l *GetProductTemplateTagsLogic) GetProductTemplateTags(req *types.GetProdu
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "logo info`s metadata is not set")
}
//获取userInfo信息
- userProfile, err := l.svcCtx.AllModels.FsUserInfo.FindOneByUser(l.ctx, userinfo.UserId, userinfo.GuestId)
+ userProfile, err := l.svcCtx.AllModels.FsUserInfo.FindOneByUser(l.ctx, userinfo.UserId, userinfo.GuestId, "profile")
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "user profile info is not found")
From 6ae2cce870ad4178464a3f982bfbdf199ee28c85 Mon Sep 17 00:00:00 2001
From: momo <1012651275@qq.com>
Date: Tue, 17 Oct 2023 18:32:43 +0800
Subject: [PATCH 10/11] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9E=E8=AE=A2=E5=8D=95?=
=?UTF-8?q?=E5=8F=91=E7=A5=A8,=E4=B8=8B=E5=8D=95=E5=9C=B0=E5=9D=80?=
=?UTF-8?q?=E8=B0=83=E6=95=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
constants/invoice_html.go | 68 ++--
constants/orders.go | 7 +
model/gmodel/fs_admin_role_gen.go | 2 +-
model/gmodel/fs_department_gen.go | 1 +
model/gmodel/fs_font_gen.go | 4 +-
model/gmodel/fs_order_gen.go | 3 +
model/gmodel/fs_order_logic.go | 11 +-
model/gmodel/fs_order_trade_gen.go | 1 +
model/gmodel/fs_product_gen.go | 1 +
server/order/internal/config/config.go | 9 +
.../internal/handler/orderinvoicehandler.go | 35 ++
server/order/internal/handler/routes.go | 5 +
.../logic/createprepaymentbydepositlogic.go | 18 +-
.../order/internal/logic/orderinvoicelogic.go | 57 +++
server/order/internal/svc/servicecontext.go | 9 +-
server/order/internal/types/types.go | 15 +-
server/order/invoice.html | 281 +++++++++++++++
.../internal/logic/logocombinelogic.go | 8 +-
server_api/order.api | 22 +-
service/repositories/order.go | 337 +++++++++++++++++-
utils/basic/basic.go | 1 +
utils/order/order.go | 7 +-
utils/order/order_invoice.go | 5 +
23 files changed, 848 insertions(+), 59 deletions(-)
create mode 100644 server/order/internal/handler/orderinvoicehandler.go
create mode 100644 server/order/internal/logic/orderinvoicelogic.go
create mode 100644 server/order/invoice.html
create mode 100644 utils/order/order_invoice.go
diff --git a/constants/invoice_html.go b/constants/invoice_html.go
index d6181ef1..6e4417a8 100644
--- a/constants/invoice_html.go
+++ b/constants/invoice_html.go
@@ -1,6 +1,6 @@
package constants
-const INVOICE_TEMPLATE = `
+const INVOICE_TEMPLATE_01 = `
@@ -192,29 +192,34 @@ const INVOICE_TEMPLATE = `
+`
+
+const INVOICE_TEMPLATE_02 = `
+`
+const INVOICE_TEMPLATE_03 = `
@@ -223,24 +228,24 @@ const INVOICE_TEMPLATE = `
Quantity |
Total |
-
- Plastic bowl |
- $01.00 |
- 20,000 Units |
- $99.00 |
-
-
- Paper bag with handlexxxxxxxxxxxxxxx second line |
- $01.00 |
- 20,000 Units |
- $99.00 |
-
+ %v
+`
+
+const INVOICE_TEMPLATE_0301 = `
+
+ %v |
+ %v |
+ %v Units |
+ %v |
+
+`
+const INVOICE_TEMPLATE_04 = `
Subtotal |
- $198.00 |
+ %v |
Shipping Fee |
@@ -248,21 +253,23 @@ const INVOICE_TEMPLATE = `
Tax |
- $0.00 |
+ %v |
Total |
- $198.00 |
+ %v |
- Deposit Requested |
- $99.00 |
+ %v |
+ %v |
- Deposit Due |
- $99.00 |
+ %v |
+ %v |
+`
+const INVOICE_TEMPLATE_05 = `
@@ -270,15 +277,18 @@ const INVOICE_TEMPLATE = `
Notes: |
- ICBC |
+ %v |
Thank you for your business ! |
- Account No. :****4589 |
+ Account No. :%v |
+ `
+const INVOICE_TEMPLATE_06 = `