220 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			220 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package logic
 | ||
| 
 | ||
| import (
 | ||
| 	"errors"
 | ||
| 	"fusenapi/model/gmodel"
 | ||
| 	"fusenapi/utils/auth"
 | ||
| 	"fusenapi/utils/basic"
 | ||
| 	"fusenapi/utils/format"
 | ||
| 	"gorm.io/gorm"
 | ||
| 	"sort"
 | ||
| 	"strings"
 | ||
| 
 | ||
| 	"context"
 | ||
| 
 | ||
| 	"fusenapi/server/product/internal/svc"
 | ||
| 	"fusenapi/server/product/internal/types"
 | ||
| 
 | ||
| 	"github.com/zeromicro/go-zero/core/logx"
 | ||
| )
 | ||
| 
 | ||
| type HomePageRecommendProductListLogic struct {
 | ||
| 	logx.Logger
 | ||
| 	ctx    context.Context
 | ||
| 	svcCtx *svc.ServiceContext
 | ||
| }
 | ||
| 
 | ||
| func NewHomePageRecommendProductListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *HomePageRecommendProductListLogic {
 | ||
| 	return &HomePageRecommendProductListLogic{
 | ||
| 		Logger: logx.WithContext(ctx),
 | ||
| 		ctx:    ctx,
 | ||
| 		svcCtx: svcCtx,
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| func (l *HomePageRecommendProductListLogic) HomePageRecommendProductList(req *types.HomePageRecommendProductListReq, userinfo *auth.UserInfo) (resp *basic.Response) {
 | ||
| 	//查询用户信息(不用判断存在)
 | ||
| 	_, err := l.svcCtx.AllModels.FsUser.FindUserById(l.ctx, userinfo.UserId)
 | ||
| 	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
 | ||
| 		logx.Error(err)
 | ||
| 		return resp.SetStatusWithMessage(basic.CodeServiceErr, "get user info err")
 | ||
| 	}
 | ||
| 	var (
 | ||
| 		merchantInfo                *gmodel.FsMerchantCategory
 | ||
| 		recommendProductList        []gmodel.FsProduct                       //产品列表(select 字段需要看查询的地方)
 | ||
| 		productOptionalPartList     []gmodel.GetGroupPartListByProductIdsRsp //产品配件列表
 | ||
| 		mapProductHaveOptionFitting = make(map[int64]struct{})               //是否有配件map
 | ||
| 		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.MerchantType > 0 {
 | ||
| 		merchantInfo, err = l.svcCtx.AllModels.FsMerchantCategory.FindOne(l.ctx, req.MerchantType)
 | ||
| 		if err != nil {
 | ||
| 			if errors.Is(err, gorm.ErrRecordNotFound) {
 | ||
| 				return resp.SetStatusWithMessage(basic.CodeOK, "the merchant category is not exists", []interface{}{})
 | ||
| 			}
 | ||
| 			logx.Error(err)
 | ||
| 			return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get merchant category")
 | ||
| 		}
 | ||
| 	} else {
 | ||
| 		//获取默认的那个
 | ||
| 		merchantInfo, err = l.svcCtx.AllModels.FsMerchantCategory.FindDefualtOne(l.ctx)
 | ||
| 		if err != nil {
 | ||
| 			if errors.Is(err, gorm.ErrRecordNotFound) {
 | ||
| 				return resp.SetStatusWithMessage(basic.CodeOK, "the default merchant category is not exists", []interface{}{})
 | ||
| 			}
 | ||
| 			logx.Error(err)
 | ||
| 			return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get default merchant category")
 | ||
| 		}
 | ||
| 	}
 | ||
| 	if *merchantInfo.RecommendProduct == "" {
 | ||
| 		return resp.SetStatusWithMessage(basic.CodeOK, "success", []interface{}{})
 | ||
| 	}
 | ||
| 	recommendProductIds, err := format.StrSlicToInt64Slice(strings.Split(*merchantInfo.RecommendProduct, ","))
 | ||
| 	if err != nil {
 | ||
| 		logx.Error(err)
 | ||
| 		return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to parse recommend product")
 | ||
| 	}
 | ||
| 	//获取列表推荐产品
 | ||
| 	recommendProductList, err = l.svcCtx.AllModels.FsProduct.GetProductListByIds(l.ctx, recommendProductIds, "sort-desc")
 | ||
| 	if err != nil {
 | ||
| 		logx.Error(err)
 | ||
| 		return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product list")
 | ||
| 	}
 | ||
| 	if len(recommendProductList) == 0 {
 | ||
| 		return resp.SetStatusWithMessage(basic.CodeOK, "success", []interface{}{})
 | ||
| 	}
 | ||
| 	productIds := make([]int64, 0, len(recommendProductList))
 | ||
| 	for _, product := range recommendProductList {
 | ||
| 		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")
 | ||
| 	}
 | ||
| 	//存储有配件的map
 | ||
| 	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)
 | ||
| 	if err != nil {
 | ||
| 		logx.Error(err)
 | ||
| 		return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get product min price list")
 | ||
| 	}
 | ||
| 	//存储产品最小价格
 | ||
| 	for _, v := range productPriceList {
 | ||
| 		priceStrSlic := strings.Split(v.Price, ",")
 | ||
| 		priceSlice, err := format.StrSlicToIntSlice(priceStrSlic)
 | ||
| 		if err != nil {
 | ||
| 			logx.Error(err)
 | ||
| 			return resp.SetStatusWithMessage(basic.CodeServiceErr, err.Error())
 | ||
| 		}
 | ||
| 		if len(priceSlice) == 0 {
 | ||
| 			continue
 | ||
| 		}
 | ||
| 		sort.Ints(priceSlice)
 | ||
| 		if min, ok := mapProductMinPrice[v.ProductId]; ok {
 | ||
| 			if min > int64(priceSlice[0]) {
 | ||
| 				mapProductMinPrice[v.ProductId] = int64(priceSlice[0])
 | ||
| 			}
 | ||
| 		} else {
 | ||
| 			mapProductMinPrice[v.ProductId] = int64(priceSlice[0])
 | ||
| 		}
 | ||
| 	}
 | ||
| 	//获取模板(只是获取产品product_id)
 | ||
| 	productTemplatesV2, err = l.svcCtx.AllModels.FsProductTemplateV2.FindAllByProductIds(l.ctx, productIds, "", "product_id")
 | ||
| 	if err != nil {
 | ||
| 		logx.Error(err)
 | ||
| 		return resp.SetStatusWithMessage(basic.CodeServiceErr, "get product template_v2 err")
 | ||
| 	}
 | ||
| 	for _, v := range productTemplatesV2 {
 | ||
| 		mapProductTemplate[*v.ProductId] = struct{}{}
 | ||
| 	}
 | ||
| 	//获取产品尺寸数量
 | ||
| 	productSizeCountList, err = l.svcCtx.AllModels.FsProductSize.GetGroupProductSizeByStatus(l.ctx, productIds, 1)
 | ||
| 	if err != nil {
 | ||
| 		logx.Error(err)
 | ||
| 		return resp.SetStatusWithMessage(basic.CodeServiceErr, "get product size count err")
 | ||
| 	}
 | ||
| 	for _, v := range productSizeCountList {
 | ||
| 		mapProductSizeCount[v.ProductId] = v.Num
 | ||
| 	}
 | ||
| 	//获取产品标签相关属性
 | ||
| 	productTagPropList, err := l.svcCtx.AllModels.FsProductTagProp.GetTagPropByProductIdsWithProductTag(l.ctx, productIds)
 | ||
| 	if err != nil {
 | ||
| 		logx.Error(err)
 | ||
| 		return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product tag property")
 | ||
| 	}
 | ||
| 	mapTagProp := make(map[int64][]types.CoverDefaultItem)
 | ||
| 	for _, v := range productTagPropList {
 | ||
| 		mapTagProp[*v.ProductId] = append(mapTagProp[*v.ProductId], types.CoverDefaultItem{
 | ||
| 			Tag:   v.TemplateTag,
 | ||
| 			Cover: *v.Cover,
 | ||
| 		})
 | ||
| 	}
 | ||
| 	//组装返回
 | ||
| 	listRsp := make([]types.HomePageRecommendProductListRsp, 0, len(recommendProductList))
 | ||
| 	for _, productInfo := range recommendProductList {
 | ||
| 		minPrice, ok := mapProductMinPrice[productInfo.Id]
 | ||
| 		_, tmpOk := mapProductTemplate[productInfo.Id]
 | ||
| 		//无最小价格则不显示 || 没有模板也不显示
 | ||
| 		if !ok || !tmpOk {
 | ||
| 			continue
 | ||
| 		}
 | ||
| 		sizeNum := int64(0)
 | ||
| 		if mapSizeNum, ok := mapProductSizeCount[productInfo.Id]; ok {
 | ||
| 			sizeNum = mapSizeNum
 | ||
| 		}
 | ||
| 		//有无可选配件
 | ||
| 		haveOptionalFitting := false
 | ||
| 		if _, ok = mapProductHaveOptionFitting[productInfo.Id]; ok {
 | ||
| 			haveOptionalFitting = true
 | ||
| 		}
 | ||
| 		item := types.HomePageRecommendProductListRsp{
 | ||
| 			Id:                  productInfo.Id,
 | ||
| 			Sn:                  *productInfo.Sn,
 | ||
| 			Title:               *productInfo.Title,
 | ||
| 			Cover:               *productInfo.Cover,
 | ||
| 			CoverDefault:        []types.CoverDefaultItem{},
 | ||
| 			SizeNum:             uint32(sizeNum),
 | ||
| 			MinPrice:            minPrice,
 | ||
| 			HaveOptionalFitting: haveOptionalFitting,
 | ||
| 		}
 | ||
| 		if _, ok = mapTagProp[productInfo.Id]; ok {
 | ||
| 			item.CoverDefault = mapTagProp[productInfo.Id]
 | ||
| 		}
 | ||
| 		//千人千面处理
 | ||
| 		/*r := image.ThousandFaceImageFormatReq{
 | ||
| 			Size:           int(req.Size),
 | ||
| 			IsThousandFace: 0,
 | ||
| 			Cover:          *productInfo.Cover,
 | ||
| 			CoverImg:       *productInfo.CoverImg,
 | ||
| 			CoverDefault:   *productInfo.CoverImg,
 | ||
| 			ProductId:      productInfo.Id,
 | ||
| 			UserId:         user.Id,
 | ||
| 		}
 | ||
| 		if user.Id != 0 {
 | ||
| 			r.IsThousandFace = int(*user.IsThousandFace)
 | ||
| 		}
 | ||
| 		image.ThousandFaceImageFormat(&r)
 | ||
| 		item.Cover = r.Cover
 | ||
| 		item.CoverDefault = r.CoverDefault*/
 | ||
| 		//加入分类产品切片
 | ||
| 		listRsp = append(listRsp, item)
 | ||
| 	}
 | ||
| 	return resp.SetStatusWithMessage(basic.CodeOK, "success", listRsp)
 | ||
| }
 |