This commit is contained in:
laodaming
2023-07-06 17:43:07 +08:00
parent c1de53c098
commit 2b1728aac5
12 changed files with 436 additions and 128 deletions

View File

@@ -2,8 +2,20 @@ package logic
import (
"context"
"encoding/json"
"errors"
"fmt"
"fusenapi/constants"
"fusenapi/model/gmodel"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"fusenapi/utils/color_list"
"fusenapi/utils/format"
"fusenapi/utils/image"
"fusenapi/utils/step_price"
"gorm.io/gorm"
"strconv"
"strings"
"fusenapi/server/product/internal/svc"
"fusenapi/server/product/internal/types"
@@ -27,7 +39,7 @@ func NewGetProductInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Ge
func (l *GetProductInfoLogic) GetProductInfo(req *types.GetProductInfoReq, userinfo *auth.UserInfo) (resp *basic.Response) {
//获取产品信息
/*productInfo, err := l.svcCtx.AllModels.FsProduct.FindOneBySn(l.ctx, req.Pid)
productInfo, err := l.svcCtx.AllModels.FsProduct.FindOneBySn(l.ctx, req.Pid)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the product is not exists")
@@ -43,15 +55,11 @@ func (l *GetProductInfoLogic) GetProductInfo(req *types.GetProductInfoReq, useri
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to parse product material Id list")
}
type Material struct {
Id int64 `json:"id"`
Title string `json:"title"`
}
//材料列表
materials := make([]Material, 0, len(materialIdSlice))
materials := make([]types.MaterialItem, 0, len(materialIdSlice))
for _, v := range materialIdSlice {
if title, ok := constants.MAP_MATERIAL[v]; ok {
materials = append(materials, Material{
materials = append(materials, types.MaterialItem{
Id: v,
Title: title,
})
@@ -130,10 +138,10 @@ func (l *GetProductInfoLogic) GetProductInfo(req *types.GetProductInfoReq, useri
return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse model info")
}
cover := ""
if modelInfo["cover"] != nil {
coverArr := strings.Split(modelInfo["cover"].(string), ".")
if modelInfo["cover"] != nil && modelInfo["cover"].(string) != "" {
cover = modelInfo["cover"].(string)
if req.Size >= 200 {
coverArr := strings.Split(modelInfo["cover"].(string), ".")
cover = fmt.Sprintf("%s_%d.%s", coverArr[0], req.Size, coverArr[1])
}
}
@@ -152,6 +160,10 @@ func (l *GetProductInfoLogic) GetProductInfo(req *types.GetProductInfoReq, useri
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get tag list")
}
mapTag := make(map[string]int)
for k, v := range tagList {
mapTag[fmt.Sprintf("%d", v.Id)] = k
}
//获取全部模型信息
allModel3dList, err := l.svcCtx.AllModels.FsProductModel3d.GetAll(l.ctx)
if err != nil {
@@ -186,10 +198,18 @@ func (l *GetProductInfoLogic) GetProductInfo(req *types.GetProductInfoReq, useri
for k, v := range lightList {
mapLight[v.Id] = k
}
//材料尺寸模板
mapMaterialSizeTmp := make(map[string][]interface{})
//循环阶梯价计算
type MaterialSizePrice struct {
Items []interface{} `json:"items"`
MinPrice string `json:"min_price"`
MaxPrice string `json:"max_price"`
}
mapMaterialSizePrice := make(map[string]*MaterialSizePrice)
//循环处理组装模板信息
template484List := make([]interface{}, 0, len(productTemplateList))
for _, v := range productTemplateList {
allModel3dIndex, ok := mapAllmodel3d[*v.ModelId]
for _, tmp := range productTemplateList {
allModel3dIndex, ok := mapAllmodel3d[*tmp.ModelId]
if !ok {
continue
}
@@ -198,38 +218,38 @@ func (l *GetProductInfoLogic) GetProductInfo(req *types.GetProductInfoReq, useri
continue
}
//未编辑模板信息的数据跳过
if v.TemplateInfo == nil || *v.TemplateInfo == "" {
if tmp.TemplateInfo == nil || *tmp.TemplateInfo == "" {
continue
}
model3dInfo := allModel3dList[allModel3dIndex]
//解码template info
var templateInfo map[string]interface{}
if err = json.Unmarshal([]byte(*v.TemplateInfo), &templateInfo); err != nil {
var templateInfoRsp map[string]interface{}
if err = json.Unmarshal([]byte(*tmp.TemplateInfo), &templateInfoRsp); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse template info")
}
if templateInfo["cover"] != nil && templateInfo["cover"].(string) != "" {
cover := templateInfo["cover"].(string)
if templateInfoRsp["cover"] != nil && templateInfoRsp["cover"].(string) != "" {
cover := templateInfoRsp["cover"].(string)
if req.Size >= 200 {
coverArr := strings.Split(templateInfo["cover"].(string), ".")
coverArr := strings.Split(templateInfoRsp["cover"].(string), ".")
cover = fmt.Sprintf("%s_%d.%s", coverArr[0], req.Size, coverArr[1])
}
templateInfo["cover"] = cover
delete(templateInfo, "isPublic")
delete(templateInfo, "name")
templateInfoRsp["cover"] = cover
delete(templateInfoRsp, "isPublic")
delete(templateInfoRsp, "name")
}
//解码模型数据
var modelInfo map[string]interface{}
if err = json.Unmarshal([]byte(*model3dInfo.ModelInfo), &modelInfo); err != nil {
var modelInfoRsp map[string]interface{}
if err = json.Unmarshal([]byte(*model3dInfo.ModelInfo), &modelInfoRsp); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse template info")
}
modelInfo["id"] = allModel3dList[allModel3dIndex].Id
modelInfoRsp["id"] = allModel3dList[allModel3dIndex].Id
//解码灯光数据
var lightInfo interface{}
var lightInfoRsp interface{}
lightIndex, ok := mapLight[*model3dInfo.Light]
if ok && lightList[lightIndex].Info != nil && *lightList[lightIndex].Info != "" {
if err = json.Unmarshal([]byte(*lightList[lightIndex].Info), &lightInfo); err != nil {
if err = json.Unmarshal([]byte(*lightList[lightIndex].Info), &lightInfoRsp); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse light info")
}
@@ -240,7 +260,7 @@ func (l *GetProductInfoLogic) GetProductInfo(req *types.GetProductInfoReq, useri
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to parse 3d model`s part_list")
}
partList := make([]interface{}, 0, len(modelPartIds))
partListRsp := make([]interface{}, 0, len(modelPartIds))
for _, partId := range modelPartIds {
//判断配件信息是否正常
key, ok := mapAllmodel3d[partId]
@@ -250,77 +270,236 @@ func (l *GetProductInfoLogic) GetProductInfo(req *types.GetProductInfoReq, useri
var thisInfo map[string]interface{}
temBytes, _ := json.Marshal(allModel3dList[key])
_ = json.Unmarshal(temBytes, &thisInfo)
thisInfo["material_img"] = ""
if *allModel3dList[key].OptionTemplate != 0 {
if optionTemplateIndex, ok := mapOptionTemplate[*allModel3dList[key].OptionTemplate]; ok {
thisInfo["material_img"] = *optionTemplateList[optionTemplateIndex].MaterialImg
}
} else {
tmpv2, err := l.svcCtx.AllModels.FsProductTemplateV2.FindOneByModelId(l.ctx, partId)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
} else {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product template")
}
}
thisInfo["material_img"] = *tmpv2.MaterialImg
}
partListRsp = append(partListRsp, thisInfo)
}
}*/
//**************************************************
/*
//循环处理组装模板信息
foreach ($templates as $temp) {
foreach ($modelPart as $row) {
//判断配件信息是否正常
if (isset($models[$row]) && !empty($models[$row]) && $models[$row]['status'] == 1) {
$thisInfo = $models[$row];
$thisInfo['id'] = $models[$row]['id'];
if (!empty($models[$row]['option_template']) && !is_null($models[$row]['option_template'])) {
$thisInfo['material_img'] = $optionTemlateData[$models[$row]['option_template']]['material_img'];
} else {
$thisInfo['material_img'] = ProductTemplateV2::find()->where(['model_id' => $row])->select(['material_img'])->scalar();
}
$thisInfo['model_info'] = json_decode($thisInfo['model_info'], true);
$partArr[] = $thisInfo;
}
}
tagName := ""
if tagIndex, ok := mapTag[*tmp.Tag]; ok {
tagName = *tagList[tagIndex].Title
}
//按照材质和尺寸来存放模板信息
mapMaterialSizeTmpKey := l.getMapMaterialSizeTmpKey(*productInfo.MaterialIds, *model3dInfo.SizeId)
mapMaterialSizeTmp[mapMaterialSizeTmpKey] = append(mapMaterialSizeTmp[mapMaterialSizeTmpKey], map[string]interface{}{
"id": tmp.Id,
"title": *tmp.Title,
"templateData": templateInfoRsp,
"modelData": modelInfoRsp,
"lightData": lightInfoRsp,
"partList": partListRsp,
"tag_name": tagName,
})
}
//产品价格查询
productPriceList, err := l.svcCtx.AllModels.FsProductPrice.GetAllByProductIdStatus(l.ctx, productInfo.Id, 1)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product price list")
}
for _, priceItem := range productPriceList {
stepNumSlice, err := format.StrSlicToIntSlice(strings.Split(*priceItem.StepNum, ","))
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "split step num err")
}
stepPriceSlice, err := format.StrSlicToIntSlice(strings.Split(*priceItem.StepPrice, ","))
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "split step price err")
}
lenStepNum := len(stepNumSlice)
lenStepPrice := len(stepPriceSlice)
if lenStepNum == 0 {
return resp.SetStatusWithMessage(basic.CodeServiceErr, "count of step num is empty")
}
for *priceItem.MinBuyNum < int64(stepNumSlice[lenStepNum-1]+5) {
price := step_price.GetCentStepPrice(int(*priceItem.MinBuyNum), stepNumSlice, stepPriceSlice)
mapMaterialSizePriceKey := l.getMapMaterialSizePriceKey(*priceItem.MaterialId, *priceItem.SizeId)
if _, ok := mapMaterialSizePrice[mapMaterialSizePriceKey]; ok {
mapMaterialSizePrice[mapMaterialSizePriceKey].Items = append(mapMaterialSizePrice[mapMaterialSizePriceKey].Items, map[string]interface{}{
"num": *priceItem.MinBuyNum,
"total_num": *priceItem.MinBuyNum * (*priceItem.EachBoxNum),
"price": price,
})
mapMaterialSizePrice[mapMaterialSizePriceKey].MinPrice = fmt.Sprintf("%.2f", float64(stepPriceSlice[lenStepPrice-1])/100)
mapMaterialSizePrice[mapMaterialSizePriceKey].MaxPrice = fmt.Sprintf("%.2f", float64(stepPriceSlice[0])/100)
} else {
items := map[string]interface{}{
"num": *priceItem.MinBuyNum,
"total_num": *priceItem.MinBuyNum * (*priceItem.EachBoxNum),
"price": price,
}
mapMaterialSizePrice[mapMaterialSizePriceKey] = &MaterialSizePrice{
Items: []interface{}{items},
MinPrice: fmt.Sprintf("%.2f", float64(stepPriceSlice[lenStepPrice-1])/100),
MaxPrice: fmt.Sprintf("%.2f", float64(stepPriceSlice[0])/100),
}
}
*priceItem.MinBuyNum++
}
}
isLowRendering := false
isRemoveBg := false
var lastDesign interface{}
if userinfo.UserId != 0 {
//获取用户信息
user, err := l.svcCtx.AllModels.FsUser.FindUserById(l.ctx, userinfo.UserId)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "user info not found")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get user info")
}
isLowRendering = *user.IsLowRendering > 0
isRemoveBg = *user.IsRemoveBg > 0
lastDesign = l.getLastDesign(user)
}
var renderDesign interface{}
if req.HaveCloudRendering == true {
renderDesign = l.getRenderDesign(req.ClientNo)
}
return resp.SetStatusWithMessage(basic.CodeOK, "success", types.GetProductInfoRsp{
Id: productInfo.Id,
Type: *productInfo.Type,
Title: *productInfo.Title,
IsEnv: *productInfo.IsProtection,
IsMicro: *productInfo.IsMicrowave,
TypeName: typeName,
IsLowRendering: isLowRendering,
IsRemoveBg: isRemoveBg,
Materials: materials,
Sizes: sizeListRsp,
Templates: mapMaterialSizeTmp,
Price: mapMaterialSizePrice,
LastDesign: lastDesign,
RenderDesign: renderDesign,
Colors: color_list.GetColor(),
})
//按照材质和尺寸来存放模板信息
$product['templates']["{$materialId}_{$models[$temp['model_id']]['size_id']}"][] = [
'id' => $temp['id'],
'title' => $temp['title'],
'templateData' => $info,
'modelData' => $modelData,
'lightData' => $lightData,
'partList' => $partArr,
'tag_name' => isset($tags[$temp['tag']]) ? $tags[$temp['tag']]['title'] : '',
];
}
//产品价格查询
$prices = ProductPrice::find()
->andFilterWhere(['product_id' => $product['id']])
->statusOn(ProductPrice::STATUS_ON)
->asArray()
->all();
//循环阶梯价计算
foreach ($prices as $price) {
$price['step_num'] = explode(',', $price['step_num']);
$price['step_price'] = explode(',', $price['step_price']);
while ($price['min_buy_num'] < end($price['step_num']) + 5) {
$product['prices']["{$price['material_id']}_{$price['size_id']}"]['items'][] = [
'num' => intval($price['min_buy_num']),
'total_num' => $price['min_buy_num'] * $price['each_box_num'],
'price' => ProductPriceService::getPrice($price['min_buy_num'], $price['step_num'], $price['step_price'])
];
$price['min_buy_num'] += 1;
}
$product['prices']["{$price['material_id']}_{$price['size_id']}"]['min_price'] = floatval(end($price['step_price']) / 100);
$product['prices']["{$price['material_id']}_{$price['size_id']}"]['max_price'] = floatval(reset($price['step_price']) / 100);
}
//这里加一个字段返回数据格式为最新的设计(只有当又用户信息是才会又这个)
$uid = intval(\Yii::$app->getUser()->id);
$product['last_design'] = (new ProductService())->getLastDesign($uid);
$product['render_design'] = $haveCloudRendering == 'true' ? (new ProductService())->getRenderDesign($clientNo) : null;
//获取色系数据
$product['colors'] = ProductService::getColor();
//获取用户信息
$userInfo = User::find()->where(['id' => $uid])->asArray()->one();
$product['is_low_rendering'] = $userInfo && $userInfo['is_low_rendering'] ? true : false;
$product['is_remove_bg'] = $userInfo && $userInfo['is_remove_bg'] ? true : false;*/
return resp.SetStatus(basic.CodeOK)
}
// 获取渲染设计
func (l *GetProductInfoLogic) getRenderDesign(clientNo string) interface{} {
if clientNo == "" {
return nil
}
renderDesign, err := l.svcCtx.AllModels.FsProductRenderDesign.FindOneRenderDesignByParams(l.ctx, gmodel.FindOneRenderDesignByParamsReq{
ClientNo: &clientNo,
Fields: "id,info,material_id,optional_id,size_id,template_id",
SortType: 2,
})
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil
}
logx.Error(err)
return nil
}
var info interface{}
if renderDesign.Info != nil && *renderDesign.Info != "" {
if err = json.Unmarshal([]byte(*renderDesign.Info), &info); err != nil {
logx.Error(err)
return nil
}
}
return map[string]interface{}{
"id": renderDesign.Id,
"info": info,
"material_id": *renderDesign.MaterialId,
"optional_id": *renderDesign.OptionalId,
"size_id": *renderDesign.SizeId,
"template_id": *renderDesign.TemplateId,
}
}
// 获取用户最新设计
func (l *GetProductInfoLogic) getLastDesign(userInfo gmodel.FsUser) interface{} {
//查询用户最近下单成功的数据
orderInfo, err := l.svcCtx.AllModels.FsOrder.FindLastSuccessOneOrder(l.ctx, userInfo.Id, int64(constants.STATUS_NEW_NOT_PAY))
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil
}
logx.Error(err)
return nil
}
//获取该订单相关设计信息
orderDetail, err := l.svcCtx.AllModels.FsOrderDetail.GetOneOrderDetailByOrderId(l.ctx, orderInfo.Id)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil
}
logx.Error(err)
return nil
}
//获取设计模板详情便于获得design_id
orderDetailTemplate, err := l.svcCtx.AllModels.FsOrderDetailTemplate.FindOne(l.ctx, *orderDetail.OrderDetailTemplateId)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil
}
logx.Error(err)
return nil
}
//若没打开了个性化渲染按钮或者最后一次设计不存在,则不返回该设计相关数据
if *userInfo.IsOpenRender != 1 || *orderDetailTemplate.DesignId <= 0 {
return nil
}
//获取设计数据
productDesign, err := l.svcCtx.AllModels.FsProductDesign.FindOne(l.ctx, *orderDetailTemplate.DesignId, userInfo.Id)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil
}
logx.Error(err)
return nil
}
var info interface{}
if productDesign.Info != nil && *productDesign.Info != "" {
if err := json.Unmarshal([]byte(*productDesign.Info), &info); err != nil {
logx.Error(err)
return nil
}
}
var logoColor interface{}
if productDesign.LogoColor != nil && *productDesign.LogoColor != "" {
if err := json.Unmarshal([]byte(*productDesign.LogoColor), &logoColor); err != nil {
logx.Error(err)
return nil
}
}
return map[string]interface{}{
"id": productDesign.Id,
"info": info,
"logo_color": logoColor,
"material_id": *productDesign.MaterialId,
"optional_id": *productDesign.OptionalId,
"size_id": *productDesign.SizeId,
}
}
// 获取按照材料跟尺寸分类的模板map key
func (l *GetProductInfoLogic) getMapMaterialSizeTmpKey(materialIds string, sizeId int64) string {
return fmt.Sprintf("%s_%d", materialIds, sizeId)
}
// 获取按照材料跟尺寸分类的价格map key
func (l *GetProductInfoLogic) getMapMaterialSizePriceKey(materialId int64, sizeId int64) string {
return fmt.Sprintf("%d_%d", materialId, sizeId)
}