package logic import ( "encoding/json" "errors" "fusenapi/constants" "fusenapi/model/gmodel" "fusenapi/utils/auth" "fusenapi/utils/basic" "fusenapi/utils/format" "fusenapi/utils/image" "fusenapi/utils/step_price" "strings" "sync" "time" "context" "fusenapi/server/shopping-cart-confirmation/internal/svc" "fusenapi/server/shopping-cart-confirmation/internal/types" "github.com/zeromicro/go-zero/core/logx" ) type CartListLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewCartListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CartListLogic { return &CartListLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } // 获取用户购物车列表 func (l *CartListLogic) CartList(req *types.CartListReq, userinfo *auth.UserInfo) (resp *basic.Response) { if userinfo.GetIdType() != auth.IDTYPE_User { return resp.SetStatusWithMessage(basic.CodeUnAuth, "please login first") } //获取当前图片应该返回的尺寸大小 if req.Size > 0 { req.Size = image.GetCurrentSize(req.Size) } //获取用户购物车数据 cartRelativeData, err := l.getUserCartRelativeList(l.ctx, userinfo.UserId) if err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get cart list data") } if len(cartRelativeData.CartList) == 0 { return resp.SetStatusWithMessage(basic.CodeOK, "success") } //产品名map mapProduct := make(map[int64]int) for k, v := range cartRelativeData.ProductList { mapProduct[v.Id] = k } //产品尺寸size map mapProductSize := make(map[int64]int) for k, v := range cartRelativeData.ProductSizeList { mapProductSize[v.Id] = k } //设计map数据 mapProductDesign := make(map[int64]int) for k, v := range cartRelativeData.ProductDesignList { mapProductDesign[v.Id] = k } //产品模型map数据 mapProductModel3d := make(map[int64]int) for k, v := range cartRelativeData.ProductModel3dList { mapProductModel3d[v.Id] = k } //遍历组装数据 rspList := make([]types.CartListRsp, 0, len(cartRelativeData.CartList)) for _, v := range cartRelativeData.CartList { name := "" productSn := "" if productIndex, ok := mapProduct[*v.ProductId]; ok { name = *cartRelativeData.ProductList[productIndex].Title productSn = strings.ToLower(*cartRelativeData.ProductList[productIndex].Sn) } designSn := "" if designIndex, ok := mapProductDesign[*v.DesignId]; ok { designSn = strings.ToLower(*cartRelativeData.ProductDesignList[designIndex].Sn) } pcList, err := l.getPcList(cartRelativeData.ProductPriceList, *v.ProductId, *v.MaterialId, *v.SizeId) if err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to calculate step price") } d := types.CartListRsp{ Id: v.Id, Cover: *v.Cover, Name: name, Capacity: "", ETA: time.Now().UTC().AddDate(0, 0, 60).Format("2006-01-02 15:04:05"), Pcs: *v.BuyNum, ProductSn: productSn, DesignSn: designSn, Option: nil, IsCheck: *v.IsCheck, TsTime: v.TsTime.Format("2006-01-02 15:04:05"), PcsList: pcList, Size: nil, } var sizeList types.CartSizeItem if sizeIndex, ok := mapProductSize[*v.SizeId]; ok { d.Capacity = *cartRelativeData.ProductSizeList[sizeIndex].Capacity err = json.Unmarshal([]byte(*cartRelativeData.ProductSizeList[sizeIndex].Title), &sizeList) if err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to parse product size`s title") } d.Size = &sizeList } if model3dIndex, ok := mapProductModel3d[*v.OptionalId]; ok { d.Option = &types.CartOption{ Id: cartRelativeData.ProductModel3dList[model3dIndex].Id, Title: *cartRelativeData.ProductModel3dList[model3dIndex].Title, Price: float64(*cartRelativeData.ProductModel3dList[model3dIndex].Price) / float64(100), } } rspList = append(rspList, d) } return resp.SetStatusWithMessage(basic.CodeOK, "success", rspList) } type GetUserCartRelativeListRsp struct { CartList []gmodel.FsCart ProductDesignList []gmodel.FsProductDesign ProductSizeList []gmodel.FsProductSize ProductList []gmodel.FsProduct ProductModel3dList []gmodel.FsProductModel3d ProductTemplateV2List []gmodel.FsProductTemplateV2 ProductPriceList []gmodel.FsProductPrice } // 获取阶梯对应的价格 func (l *CartListLogic) getPcList(productPriceList []gmodel.FsProductPrice, productId int64, materialId int64, sizeId int64) (list []*types.PcsItem, err error) { for _, price := range productPriceList { if *price.ProductId != productId || *price.MaterialId != materialId || *price.SizeId != sizeId { continue } stepNumStrSlice := strings.Split(*price.StepNum, ",") stepNumSlice, err := format.StrSlicToIntSlice(stepNumStrSlice) if err != nil { return nil, err } stepPriceStrSlice := strings.Split(*price.StepPrice, ",") stepPriceSlice, err := format.StrSlicToIntSlice(stepPriceStrSlice) if err != nil { return nil, err } lenStepPriceSlice := len(stepPriceSlice) lenStepNumSlice := len(stepNumSlice) if lenStepPriceSlice == 0 || lenStepNumSlice == 0 { return nil, errors.New("step num or step price item count can`t be 0 ") } for int(*price.MinBuyNum) < stepNumSlice[lenStepNumSlice-1]+5 { list = append(list, &types.PcsItem{ Num: *price.MinBuyNum, TotalNum: *price.MinBuyNum * *price.EachBoxNum, Title: *price.Title, Price: step_price.GetStepPrice(int(*price.MinBuyNum), stepNumSlice, stepPriceSlice), }) *price.MinBuyNum++ } } return list, nil } // 获取用户购物车数据 func (l *CartListLogic) getUserCartRelativeList(ctx context.Context, userId int64) (resp GetUserCartRelativeListRsp, err error) { //购物车列表 cartModel := gmodel.NewFsCartModel(l.svcCtx.MysqlConn) cartList, err := cartModel.GetAllByUserId(ctx, userId, "ctime-desc") if err != nil { return GetUserCartRelativeListRsp{}, err } if len(cartList) == 0 { return } resp.CartList = cartList productIds := make([]int64, 0, len(cartList)) sizeIds := make([]int64, 0, len(cartList)) designIds := make([]int64, 0, len(cartList)) optionIds := make([]int64, 0, len(cartList)) templateIds := make([]int64, 0, len(cartList)) for _, v := range cartList { productIds = append(productIds, *v.ProductId) sizeIds = append(sizeIds, *v.SizeId) designIds = append(designIds, *v.DesignId) optionIds = append(optionIds, *v.OptionalId) templateIds = append(templateIds, *v.TemplateId) } //******************************协程并发开始*********************************** wait := sync.WaitGroup{} errChan := make(chan error) wait.Add(6) //注意要加协程这里要记得加 //获取产品数据1 go func() { defer wait.Done() productModel := gmodel.NewFsProductModel(l.svcCtx.MysqlConn) productList, err := productModel.GetProductListByIds(ctx, productIds, "") if err != nil { errChan <- err return } resp.ProductList = productList }() //获取尺寸数据2 go func() { defer wait.Done() productSizeModel := gmodel.NewFsProductSizeModel(l.svcCtx.MysqlConn) productSizeList, err := productSizeModel.GetAllByIds(ctx, sizeIds, "") if err != nil { errChan <- err } resp.ProductSizeList = productSizeList }() //获取设计列表3 go func() { defer wait.Done() productDesignModel := gmodel.NewFsProductDesignModel(l.svcCtx.MysqlConn) productDesignList, err := productDesignModel.GetAllByIds(ctx, designIds) if err != nil { errChan <- err } resp.ProductDesignList = productDesignList }() //获取配件列表4 go func() { defer wait.Done() productModel3dModel := gmodel.NewFsProductModel3dModel(l.svcCtx.MysqlConn) productModel3dList, err := productModel3dModel.GetAllByIdsTag(ctx, optionIds, constants.TAG_PARTS) if err != nil { errChan <- err } resp.ProductModel3dList = productModel3dList }() //获取模板信息5 go func() { defer wait.Done() productTemplateModel := gmodel.NewFsProductTemplateV2Model(l.svcCtx.MysqlConn) templateV2List, err := productTemplateModel.FindAllByIds(ctx, templateIds) if err != nil { errChan <- err } resp.ProductTemplateV2List = templateV2List }() //获取产品价格列表6 go func() { defer wait.Done() productPriceModel := gmodel.NewFsProductPriceModel(l.svcCtx.MysqlConn) productPriceList, err := productPriceModel.GetPriceListByProductIds(ctx, productIds) if err != nil { errChan <- err } resp.ProductPriceList = productPriceList }() //******************************协程并发结束*********************************** go func() { wait.Wait() close(errChan) }() //获取错误信息 for err = range errChan { if err != nil { return GetUserCartRelativeListRsp{}, err } } return resp, nil }