@@ -2,6 +2,7 @@ package logic
import (
"errors"
"fmt"
"fusenapi/model/gmodel"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
@@ -74,107 +75,193 @@ func (l *GetTagProductListLogic) GetTagProductList(req *types.GetTagProductListR
for _ , v := range tagList {
typeIds = append ( typeIds , v . Id )
}
//查询符合的产品列表
pIsDel := int64 ( 0 )
pStatus := int64 ( 1 )
pIsShelf := int64 ( 1 )
pReq := gmodel . GetProduct ListByParamsReq {
Type : typeIds ,
IsDel : & pIsDel ,
IsShelf : & pIsSh elf ,
Status : & pStatus ,
OrderBy : "`sort` DESC" ,
}
//获取产品列表
productList , err := l . svcCtx . AllModels . FsProduct . GetProductListByParams ( l . ctx , pReq )
if err != nil {
logx . Error ( err )
return resp . SetStatusWithMessage ( basic . CodeServiceErr , "failed to get product list" )
}
//提取产品ids
productIds := make ( [ ] int64 , 0 , len ( productList ) )
for _ , v := range productList {
productIds = append ( productIds , v . Id )
}
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" )
}
//存储产品最小价格
mapProductMinPrice := make ( map [ int64 ] int64 )
for _ , v := range productPriceList {
priceStrSlic := strings . Split ( v . Price , "," )
priceSlice , err := format . StrSlicToIntSlice ( priceStrSlic )
var (
productList [ ] gmodel . FsProduct //产品列表( select 字段需要看查询的地方)
recommendProductList [ ] gmodel . FsProduct //tag推荐产品列表( select 字段需要看查询的地方)
mapProduct = make ( map [ int64 ] int ) //产品map
productPriceList [ ] gmodel . GetPrice ListByProductIdsRsp //产品价格列表( select 字段需要看查询的地方)
mapProductMinPrice = make ( map [ int64 ] int64 ) //产品最小价格map
productTemplatesV2 [ ] gmodel . FsProductTemplateV2 //产品模板列表( select 字段需要看查询的地方)
productSizeCountList [ ] gmod el. CountProductSizeByStatusRsp //产品尺寸数量列表( select 字段需要看查询的地方)
mapProductSizeCount = make ( map [ int64 ] int64 ) //产品尺寸数量map
mapProductTemplate = make ( map [ int64 ] struct { } ) //产品模板map
)
//携带推荐产品
if req . WithRecommendProduct {
//提取tag推荐产品
allTagRecommendProductIds := make ( [ ] int64 , 0 , len ( tagList ) * 5 )
for _ , v := range tagList {
if v . RecommendProduct == nil || * v . RecommendProduct == "" {
continue
}
sl , err := format . StrSlicToInt64Slice ( strings . Split ( * v . RecommendProductSort , "," ) )
if err ! = nil {
logx . Error ( err )
return resp . SetStatusWithMessage ( basic . CodeServiceErr , fmt . Sprintf ( "failed to parse recommend product ids,id=%d" , v . Id ) )
}
allTagRecommendProductIds = append ( allTagRecommendProductIds , sl ... )
}
//获取推荐的产品列表
recommendProductList , err = l . svcCtx . AllModels . FsProduct . FindAllOnlyByIds ( l . ctx , allTagRecommendProductIds )
if err != nil {
logx . Error ( err )
return resp . SetStatusWithMessage ( basic . CodeService Err , err . Error ( ) )
return resp . SetStatusWithMessage ( basic . CodeDbSql Err , "failed to get tag recommend products" )
}
if len ( priceSlice ) == 0 {
continue
}
//携带产品
if req . WithProduct {
//查询符合的产品列表
pIsDel := int64 ( 0 )
pStatus := int64 ( 1 )
pIsShelf := int64 ( 1 )
pReq := gmodel . GetProductListByParamsReq {
Type : typeIds ,
IsDel : & pIsDel ,
IsShelf : & pIsShelf ,
Status : & pStatus ,
OrderBy : "`sort` DESC" ,
}
//获取产品列表
productList , err = l . svcCtx . AllModels . FsProduct . GetProductListByParams ( l . ctx , pReq )
if err != nil {
logx . Error ( err )
return resp . SetStatusWithMessage ( basic . CodeServiceErr , "failed to get product list" )
}
sort . Ints ( priceSlice )
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" )
}
mapProductTemplate := make ( map [ int64 ] struct { } )
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" )
}
mapProductSizeCount := make ( map [ int64 ] int64 )
for _ , v := range productSizeCountList {
mapP roductSizeCount [ v . ProductId] = v . Num
//任意一个不为空
if len ( productList ) != 0 || len ( recommendProductList ) != 0 {
//提取产品ids
productIds := make ( [ ] int64 , 0 , len ( productList ) )
for k , v := range productList {
productIds = append ( productIds , v . Id )
mapProduct[ v . Id ] = k
}
//合并产品列表
for _ , v := range recommendProductList {
//存在则不并入
if _ , ok := mapProduct [ v . Id ] ; ok {
continue
}
productList = append ( productList , v )
mapProduct [ v . Id ] = len ( productList ) - 1
}
//获取产品价格列表
p roductPriceList , err = l . svcCtx . AllModels . FsProductPrice . GetSimplePriceListBy ProductIds ( 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 )
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
}
}
//map tag菜单
mapTagLevel := make ( map [ string ] * types . TagItem )
minLevel := int64 ( 0 ) //记录最小等级数字
for _ , tagInfo := range tagList {
if minLevel == 0 && * tagInfo . Level > 0 {
minLevel = * tagInfo . Level
}
if minLevel > * tagInfo . Level {
minLevel = * tagInfo . Level
}
//获取分类产品列表
productListRsp := l . getTagProducts ( getTagProductsReq {
TagId : tagInfo . Id ,
ProductList : productList ,
MapProductMinPrice : mapProductMinPrice ,
MapProductTemplate : mapProductTemplate ,
MapProductSizeCount : mapProductSizeCount ,
Size : req . Size ,
User : user ,
} )
//加入分类
tagTem := types . TagItem {
TagProductList : productListRsp ,
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 , 100 ) ,
TagProductList : nil ,
TagRecommendProductList : 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 , 100 ) ,
}
//当前tag保存入map
//携带产品
if req . WithProduct {
//获取分类产品列表
productListRsp := l . getTagProducts ( getTagProductsReq {
TagId : tagInfo . Id ,
ProductList : productList ,
MapProductMinPrice : mapProductMinPrice ,
MapProductTemplate : mapProductTemplate ,
MapProductSizeCount : mapProductSizeCount ,
Size : req . Size ,
User : user ,
} )
//赋值
tagTem . TagProductList = productListRsp
}
//获取推荐产品列表
if req . WithRecommendProduct && tagInfo . RecommendProduct != nil && * tagInfo . RecommendProduct != "" {
//上面解析过,这里就无需判断错误
recommendProductIds , _ := format . StrSlicToInt64Slice ( strings . Split ( * tagInfo . RecommendProduct , "," ) )
//推荐产品的排序
recommendProductIdsSort , err := format . StrSlicToInt64Slice ( strings . Split ( * tagInfo . RecommendProductSort , "," ) )
if err != nil {
logx . Error ( err )
return nil
}
if len ( recommendProductIds ) != len ( recommendProductIdsSort ) {
return resp . SetStatusWithMessage ( basic . CodeServiceErr , fmt . Sprintf ( "length of recommend product id is neq length of recommend sort,id= %d" , tagInfo . Id ) )
}
recommendProductListRsp := l . getTagRecommendProducts ( getTagRecommendProductsReq {
TagInfo : tagInfo ,
ProductList : productList ,
MapProduct : mapProduct ,
MapProductMinPrice : mapProductMinPrice ,
MapProductTemplate : mapProductTemplate ,
MapProductSizeCount : mapProductSizeCount ,
RecommendProductIds : recommendProductIds ,
RecommendProductIdsSort : recommendProductIdsSort ,
Size : req . Size ,
User : user ,
} )
//赋值
tagTem . TagRecommendProductList = recommendProductListRsp
}
//加入分类
mapTagLevel [ * tagInfo . LevelPrefix ] = & tagTem
}
//组装等级从属关系
return resp . SetStatusWithMessage ( basic . CodeOK , "success" , types . GetTagProductListRsp {
TotalCategory : len ( mapTagLevel ) ,
TagList : l . organizationLevelRelation ( mapTagLevel ) , //组装等级从属关系
} )
}
//排序推荐产品结构体
type sortRecommendProduct struct {
ProductId int64
Sort int64
}
//组织等级从属关系
func ( l * GetTagProductListLogic ) organizationLevelRelation ( mapTagLevel map [ string ] * types . TagItem ) [ ] types . TagItem {
mapTop := make ( map [ string ] struct { } )
for prefix , tagItem := range mapTagLevel {
prefix = strings . Trim ( prefix , " " )
//最上级没有父级
if ! strings . Contains ( prefix , "/" ) {
mapTop [ prefix ] = struct { } { }
continue
}
prefixSlice := strings . Split ( prefix , "/" )
@@ -183,30 +270,98 @@ func (l *GetTagProductListLogic) GetTagProductList(req *types.GetTagProductListR
if parent , ok := mapTagLevel [ parentPrefix ] ; ok {
parent . ChildTagList = append ( parent . ChildTagList , tagItem )
//排序
sort . Slice ( parent . ChildTagList , func ( i , j int ) bool {
sort . SliceStable ( parent . ChildTagList , func ( i , j int ) bool {
return parent . ChildTagList [ i ] . Sort < parent . ChildTagList [ j ] . Sort
} )
mapTagLevel [ parentPrefix ] = parent
}
}
//最终值提取最高级别那一层出来
tag ListRsp := make ( [ ] types . TagItem , 0 , len ( mapTagLevel ) )
for _ , v := range mapTagLevel {
if v . Level != minLevel {
continue
}
tagListRsp = append ( tagListRsp , * v )
rsp List := make ( [ ] types . TagItem , 0 , len ( mapTagLevel ) )
for prefix , _ := range mapTop {
rspList = append ( rspList , * mapTagLevel [ prefix ] )
}
//排序
sort . Slice ( tag ListRsp , func ( i , j int ) bool {
return tag ListRsp [ i ] . Sort < tag ListRsp [ j ] . Sort
} )
return resp . SetStatusWithMessage ( basic . CodeOK , "success" , types . GetTagProductListRsp {
TotalCategory : len ( mapTagLevel ) ,
TagList : tagListRsp ,
sort . SliceStable ( rsp List, func ( i , j int ) bool {
return rsp List[ i ] . Sort < rsp List[ j ] . Sort
} )
return rspList
}
//获取tag推荐产品列表
type getTagRecommendProductsReq struct {
TagInfo gmodel . FsTags
ProductList [ ] gmodel . FsProduct
MapProduct map [ int64 ] int
MapProductMinPrice map [ int64 ] int64
MapProductTemplate map [ int64 ] struct { }
MapProductSizeCount map [ int64 ] int64
RecommendProductIds [ ] int64
RecommendProductIdsSort [ ] int64
Size uint32
User gmodel . FsUser
}
func ( l * GetTagProductListLogic ) getTagRecommendProducts ( req getTagRecommendProductsReq ) ( productListRsp [ ] types . TagProduct ) {
//排序
sortList := make ( [ ] sortRecommendProduct , 0 , len ( req . RecommendProductIds ) )
for sortIndex , pid := range req . RecommendProductIds {
sortList = append ( sortList , sortRecommendProduct {
ProductId : pid ,
Sort : req . RecommendProductIdsSort [ sortIndex ] ,
} )
}
sort . SliceStable ( sortList , func ( i , j int ) bool {
return sortList [ i ] . Sort < sortList [ j ] . Sort
} )
productListRsp = make ( [ ] types . TagProduct , 0 , len ( sortList ) )
for _ , sortVal := range sortList {
productIndex , ok := req . MapProduct [ sortVal . ProductId ]
if ! ok {
continue
}
productInfo := req . ProductList [ productIndex ]
minPrice , ok := req . MapProductMinPrice [ productInfo . Id ]
_ , tmpOk := req . MapProductTemplate [ productInfo . Id ]
//无最小价格则不显示 || 没有模板也不显示
if ! ok || ! tmpOk {
continue
}
sizeNum := int64 ( 0 )
if mapSizeNum , ok := req . MapProductSizeCount [ productInfo . Id ] ; ok {
sizeNum = mapSizeNum
}
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 ,
}
//千人千面处理
r := image . ThousandFaceImageFormatReq {
Size : int ( req . Size ) ,
IsThousandFace : 0 ,
Cover : * productInfo . Cover ,
CoverImg : * productInfo . CoverImg ,
CoverDefault : * productInfo . CoverImg ,
ProductId : productInfo . Id ,
UserId : req . User . Id ,
}
if req . User . Id != 0 {
r . IsThousandFace = int ( * req . User . IsThousandFace )
}
image . ThousandFaceImageFormat ( & r )
item . Cover = r . Cover
item . CoverImg = r . CoverImg
item . CoverDefault = r . CoverDefault
//加入切片
productListRsp = append ( productListRsp , item )
}
return productListRsp
}
// 获取对应tag的产品列表
type getTagProductsReq struct {
TagId int64