fusenapi/server/product/internal/logic/getproductinfologic.go
2023-07-05 19:00:33 +08:00

337 lines
12 KiB
Go

package logic
import (
"encoding/json"
"errors"
"fmt"
"fusenapi/constants"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"fusenapi/utils/format"
"fusenapi/utils/image"
"strconv"
"strings"
"gorm.io/gorm"
"context"
"fusenapi/server/product/internal/svc"
"fusenapi/server/product/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetProductInfoLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetProductInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetProductInfoLogic {
return &GetProductInfoLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetProductInfoLogic) GetProductInfo(req *types.GetProductInfoReq, userinfo *auth.UserInfo) (resp *basic.Response) {
//获取产品信息
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")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product info")
}
if req.Size > 0 {
req.Size = image.GetCurrentSize(req.Size)
}
materialIdSlice, err := format.StrSlicToInt64Slice(strings.Split(*productInfo.MaterialIds, ","))
if err != nil {
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))
for _, v := range materialIdSlice {
if title, ok := constants.MAP_MATERIAL[v]; ok {
materials = append(materials, Material{
Id: v,
Title: title,
})
}
}
//尺寸列表[这里要处理数据中的title]
sizeList, err := l.svcCtx.AllModels.FsProductSize.GetAllByStatus(l.ctx, int64(constants.FAQ_STATUS_ON), 1, "id,title,capacity,cover,sort,parts_can_deleted")
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product size list")
}
sizeIds := make([]int64, 0, len(sizeList))
for _, v := range sizeList {
sizeIds = append(sizeIds, v.Id)
}
//获取产品标签
tagInfo, err := l.svcCtx.AllModels.FsTags.FindOne(l.ctx, *productInfo.Type)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "tag info is not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get tag info")
}
typeName := *tagInfo.Title
//获取该尺寸下的模型数据
model3dList, err := l.svcCtx.AllModels.FsProductModel3d.GetAllBySizeIdsTag(l.ctx, sizeIds, constants.TAG_MODEL)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product 3d model list")
}
model3dIds := make([]int64, 0, len(model3dList))
mapModel3dWithSizeIdIndex := make(map[int64]int) //sizeid为key
for k, v := range model3dList {
model3dIds = append(model3dIds, v.Id)
mapModel3dWithSizeIdIndex[*v.SizeId] = k
}
//通过产品id和模型id获取模板信息
productTemplateList, err := l.svcCtx.AllModels.FsProductTemplateV2.FindAllByProductIdModelIds(l.ctx, model3dIds, productInfo.Id)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product template list")
}
//获取模板包含的model_id
mapTemplateModelId := make(map[int64]struct{})
tagIds := make([]int64, 0, len(productTemplateList))
for _, v := range productTemplateList {
mapTemplateModelId[v.Id] = struct{}{}
if v.Tag != nil && *v.Tag != "" {
tagId, err := strconv.ParseInt(*v.Tag, 10, 64)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "tag is not a number")
}
tagIds = append(tagIds, tagId)
}
}
//过滤没有模板的尺寸数据
sizeListRsp := make([]types.SizeItem, 0, len(sizeList))
for _, v := range sizeList {
model3dIndex, ok := mapModel3dWithSizeIdIndex[v.Id]
if !ok {
continue
}
if _, ok = mapTemplateModelId[model3dList[model3dIndex].Id]; !ok {
continue
}
var title types.SizeTitle
if err = json.Unmarshal([]byte(*v.Title), &title); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to decode size info`s title")
}
var modelInfo map[string]interface{}
if err = json.Unmarshal([]byte(*model3dList[model3dIndex].ModelInfo), &modelInfo); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse model info")
}
cover := ""
if modelInfo["cover"] != nil {
coverArr := strings.Split(modelInfo["cover"].(string), ".")
cover = modelInfo["cover"].(string)
if req.Size >= 200 {
cover = fmt.Sprintf("%s_%d.%s", coverArr[0], req.Size, coverArr[1])
}
}
sizeListRsp = append(sizeListRsp, types.SizeItem{
Id: v.Id,
Title: title,
Capacity: *v.Capacity,
Cover: cover,
Sort: *v.Sort,
PartsCanDeleted: *v.PartsCanDeleted > 0,
})
}
//获取标签列表
tagList, err := l.svcCtx.AllModels.FsTags.GetAllByIdsWithoutStatus(l.ctx, tagIds)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get tag list")
}
//获取全部模型信息
allModel3dList, err := l.svcCtx.AllModels.FsProductModel3d.GetAll(l.ctx)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get all 3d model list")
}
mapAllmodel3d := make(map[int64]int)
optionTemplateIds := make([]int64, 0, len(allModel3dList))
lightIds := make([]int64, 0, len(allModel3dList))
for k, v := range allModel3dList {
mapAllmodel3d[v.Id] = k
optionTemplateIds = append(optionTemplateIds, *v.OptionTemplate)
lightIds = append(lightIds, *v.Light)
}
//获取公共模板信息
optionTemplateList, err := l.svcCtx.AllModels.FsProductTemplateV2.FindAllByIdsWithoutStatus(l.ctx, optionTemplateIds, "id,material_img")
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get option template list")
}
mapOptionTemplate := make(map[int64]int)
for k, v := range optionTemplateList {
mapOptionTemplate[v.Id] = k
}
//获取灯光信息
lightList, err := l.svcCtx.AllModels.FsProductModel3dLight.GetAllByIdsWithoutStatus(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
}
//循环处理组装模板信息
template484List := make([]interface{}, 0, len(productTemplateList))
for _, v := range productTemplateList {
allModel3dIndex, ok := mapAllmodel3d[*v.ModelId]
if !ok {
continue
}
//如果是配件信息就跳过,不返回
if *allModel3dList[allModel3dIndex].Tag == constants.TAG_PARTS {
continue
}
//未编辑模板信息的数据跳过
if v.TemplateInfo == nil || *v.TemplateInfo == "" {
continue
}
model3dInfo := allModel3dList[allModel3dIndex]
//解码template info
var templateInfo map[string]interface{}
if err = json.Unmarshal([]byte(*v.TemplateInfo), &templateInfo); 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 req.Size >= 200 {
coverArr := strings.Split(templateInfo["cover"].(string), ".")
cover = fmt.Sprintf("%s_%d.%s", coverArr[0], req.Size, coverArr[1])
}
templateInfo["cover"] = cover
delete(templateInfo, "isPublic")
delete(templateInfo, "name")
}
//解码模型数据
var modelInfo map[string]interface{}
if err = json.Unmarshal([]byte(*model3dInfo.ModelInfo), &modelInfo); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse template info")
}
modelInfo["id"] = allModel3dList[allModel3dIndex].Id
//解码灯光数据
var lightInfo 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 {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse light info")
}
}
//配件备选项
modelPartIds, err := format.StrSlicToInt64Slice(strings.Split(*model3dInfo.PartList, ","))
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to parse 3d model`s part_list")
}
partList := make([]interface{}, 0, len(modelPartIds))
for _, partId := range modelPartIds {
//判断配件信息是否正常
key, ok := mapAllmodel3d[partId]
if !ok || *allModel3dList[key].Status != 1 {
continue
}
var thisInfo map[string]interface{}
temBytes, _ := json.Marshal(allModel3dList[key])
_ = json.Unmarshal(temBytes, &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;
}
}
//按照材质和尺寸来存放模板信息
$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)
}