Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop

This commit is contained in:
momo 2023-10-07 18:37:04 +08:00
commit 3f78cfd824
28 changed files with 260 additions and 2022 deletions

View File

@ -22,6 +22,7 @@ type FsAddress struct {
Ctime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"ctime"` // 创建时间
Utime *time.Time `gorm:"index;default:'0000-00-00 00:00:00';" json:"utime"` // 更新时间
Ltime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"ltime"` // 上次被使用的时间
IsDefault *int64 `gorm:"default:0;" json:"is_default"` // 1默认值,0非默认值
}
type FsAddressModel struct {
db *gorm.DB

View File

@ -14,7 +14,7 @@ func (a *FsAddressModel) GetOne(ctx context.Context, addressId int64, userId int
}
func (a *FsAddressModel) GetUserAllAddress(ctx context.Context, userId int64) (resp []FsAddress, err error) {
err = a.db.WithContext(ctx).Model(&FsAddress{}).Where("`user_id` = ? and `status` = 1", userId).Order("`ltime` DESC").Find(&resp).Error
err = a.db.WithContext(ctx).Model(&FsAddress{}).Where("`user_id` = ? and `status` = 1", userId).Order("`ctime` DESC").Find(&resp).Error
if err != nil {
return nil, err
}
@ -37,26 +37,11 @@ func (a *FsAddressModel) CreateOne(ctx context.Context, address *FsAddress) (res
Country: address.Country,
ZipCode: address.ZipCode,
Status: address.Status,
IsDefault: address.IsDefault,
Ctime: &now,
Utime: &now,
Ltime: &now,
}
// lastOne := &FsAddress{}
// err = tx.Where("user_id = ?", lastOne.UserId).Order("ltime ASC").Take(&lastOne).Error
// if err == gorm.ErrRecordNotFound {
// result.Ltime = &now
// return tx.Model(&FsAddress{}).Create(result).Error
// }
// if err != nil {
// return err
// }
// // 根据lastOne处理时间
// ltime := (*lastOne.Ltime).Add(-time.Second)
// result.Ltime = &ltime
return tx.Model(&FsAddress{}).Create(result).Error
})
@ -80,44 +65,46 @@ func (a *FsAddressModel) UpdateAddress(ctx context.Context, address *FsAddress)
return err
}
func (a *FsAddressModel) SettingUserDefaultAddress(ctx context.Context, userId int64, addressId int64, isDefault int64) (err error) {
func (a *FsAddressModel) SettingUserDefaultAddressMutex(ctx context.Context, userId int64, addressId int64, isDefault int64) (err error) {
err = a.db.WithContext(ctx).Model(&FsAddress{}).Transaction(func(tx *gorm.DB) error {
logx.Info("address_id:", addressId, " set default ", isDefault)
now := time.Now().UTC()
err = tx.Where("`address_id` = ? and `user_id` = ? and `status` = 1 ", addressId, userId).Take(nil).Error
if err != nil {
return err
}
if isDefault == 0 {
err = tx.Model(&FsAddress{}).Where("`address_id` = ? and `user_id` = ? and `status` = 1 and `ltime` > ?", addressId, userId, now.AddDate(10, 0, 0)).
UpdateColumn("ltime", now).
err = tx.Where("`user_id` = ? and `status` = 1 and `is_default` = 1", userId).
UpdateColumn("is_default", 0).
UpdateColumn("utime", now).Error
if err != nil {
return err
}
} else {
err = tx.Where("`address_id` = ? and `user_id` = ? and `status` = 1", addressId, userId).
UpdateColumn("ltime", now.AddDate(250, 0, 0)).
UpdateColumn("utime", now).Error
if err != nil {
return err
}
err = tx.Model(&FsAddress{}).Where("`address_id` != ? and `user_id` = ? and `status` = 1 and `ltime` > ?", addressId, userId, now.AddDate(10, 0, 0)).
UpdateColumn("is_default", isDefault).
UpdateColumn("ltime", now).
UpdateColumn("utime", now).Error
if err != nil {
return err
}
return nil
})
return err
}
func (a *FsAddressModel) SettingUserDefaultAddress(ctx context.Context, userId int64, addressId int64, isDefault int64) (err error) {
err = a.db.WithContext(ctx).Model(&FsAddress{}).Transaction(func(tx *gorm.DB) error {
logx.Info("address_id:", addressId, " set default ", isDefault)
now := time.Now().UTC()
err = tx.Where("`address_id` = ? and `user_id` = ? and `status` = 1", addressId, userId).
UpdateColumn("is_default", isDefault).
UpdateColumn("ltime", now).
UpdateColumn("utime", now).Error
if err != nil {
return err
}
return nil
@ -138,7 +125,8 @@ func (a *FsAddressModel) UpdateUsedAddress(ctx context.Context, addressId int64,
err = a.db.WithContext(ctx).Model(&FsAddress{}).Transaction(func(tx *gorm.DB) error {
logx.Info("address_id:", addressId, " update used")
now := time.Now().UTC()
err = tx.Where("`address_id` = ? and `user_id` = ? and `status` = 1 and `ltime` < ?", addressId, userId, now).
err = tx.Where("`address_id` = ? and `user_id` = ? and `status` = 1", addressId, userId).
UpdateColumn("utime", now).
UpdateColumn("ltime", now).Error
if err != nil {
return err

View File

@ -0,0 +1,36 @@
package main
import (
"flag"
"fmt"
"net/http"
"time"
"fusenapi/utils/auth"
"fusenapi/utils/fsconfig"
"fusenapi/server/collection/internal/config"
"fusenapi/server/collection/internal/handler"
"fusenapi/server/collection/internal/svc"
"github.com/zeromicro/go-zero/rest"
)
var configFile = flag.String("f", "etc/collection.yaml", "the config file")
func main() {
flag.Parse()
var c config.Config
fsconfig.StartNacosConfig(*configFile, &c, nil)
c.Timeout = int64(time.Second * 15)
server := rest.MustNewServer(c.RestConf, rest.WithCustomCors(auth.FsCors, func(w http.ResponseWriter) {
}))
defer server.Stop()
ctx := svc.NewServiceContext(c)
handler.RegisterHandlers(server, ctx)
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
server.Start()
}

View File

@ -0,0 +1,10 @@
Name: collection
Host: 0.0.0.0
Port: 8888
Timeout: 15000 #服务超时时间(毫秒)
SourceMysql: fsreaderwriter:XErSYmLELKMnf3Dh@tcp(fusen.cdmigcvz3rle.us-east-2.rds.amazonaws.com:3306)/fusen
SourceRabbitMq: ""
Auth:
AccessSecret: fusen2023
AccessExpire: 2592000
RefreshAfter: 1592000

View File

@ -0,0 +1,13 @@
package config
import (
"fusenapi/server/collection/internal/types"
"github.com/zeromicro/go-zero/rest"
)
type Config struct {
rest.RestConf
SourceMysql string
Auth types.Auth
SourceRabbitMq string
}

View File

@ -6,27 +6,27 @@ import (
"fusenapi/utils/basic"
"fusenapi/server/product/internal/logic"
"fusenapi/server/product/internal/svc"
"fusenapi/server/product/internal/types"
"fusenapi/server/collection/internal/logic"
"fusenapi/server/collection/internal/svc"
"fusenapi/server/collection/internal/types"
)
func GetProductInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
func CollectProductHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.GetProductInfoReq
var req types.CollectProductReq
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewGetProductInfoLogic(r.Context(), svcCtx)
l := logic.NewCollectProductLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.GetProductInfo(&req, userinfo)
resp := l.CollectProduct(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)

View File

@ -0,0 +1,22 @@
// Code generated by goctl. DO NOT EDIT.
package handler
import (
"net/http"
"fusenapi/server/collection/internal/svc"
"github.com/zeromicro/go-zero/rest"
)
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
[]rest.Route{
{
Method: http.MethodPost,
Path: "/api/collection/collect_product",
Handler: CollectProductHandler(serverCtx),
},
},
)
}

View File

@ -6,20 +6,20 @@ import (
"context"
"fusenapi/server/product/internal/svc"
"fusenapi/server/product/internal/types"
"fusenapi/server/collection/internal/svc"
"fusenapi/server/collection/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetSizeByProductLogic struct {
type CollectProductLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetSizeByProductLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetSizeByProductLogic {
return &GetSizeByProductLogic{
func NewCollectProductLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CollectProductLogic {
return &CollectProductLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
@ -27,10 +27,10 @@ func NewGetSizeByProductLogic(ctx context.Context, svcCtx *svc.ServiceContext) *
}
// 处理进入前逻辑w,r
// func (l *GetSizeByProductLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
// func (l *CollectProductLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
// }
func (l *GetSizeByProductLogic) GetSizeByProduct(req *types.Request, userinfo *auth.UserInfo) (resp *basic.Response) {
func (l *CollectProductLogic) CollectProduct(req *types.CollectProductReq, userinfo *auth.UserInfo) (resp *basic.Response) {
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
// userinfo 传入值时, 一定不为null
@ -38,6 +38,6 @@ func (l *GetSizeByProductLogic) GetSizeByProduct(req *types.Request, userinfo *a
}
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
// func (l *GetSizeByProductLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
// func (l *CollectProductLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
// // httpx.OkJsonCtx(r.Context(), w, resp)
// }

View File

@ -0,0 +1,26 @@
package svc
import (
"fusenapi/initalize"
"fusenapi/model/gmodel"
"fusenapi/server/collection/internal/config"
"gorm.io/gorm"
)
type ServiceContext struct {
Config config.Config
MysqlConn *gorm.DB
AllModels *gmodel.AllModelsGen
RabbitMq *initalize.RabbitMqHandle
}
func NewServiceContext(c config.Config) *ServiceContext {
conn := initalize.InitMysql(c.SourceMysql)
return &ServiceContext{
Config: c,
MysqlConn: conn,
AllModels: gmodel.NewAllModels(initalize.InitMysql(c.SourceMysql)),
RabbitMq: initalize.InitRabbitMq(c.SourceRabbitMq, nil),
}
}

View File

@ -0,0 +1,82 @@
// Code generated by goctl. DO NOT EDIT.
package types
import (
"fusenapi/utils/basic"
)
type CollectProductReq struct {
ProductId int64 `json:"product_id"`
Logo string `json:"logo"`
SelectColorIndex int64 `json:"select_color_index"`
TemplateTag string `json:"template_tag"`
}
type Request struct {
}
type Response struct {
Code int `json:"code"`
Message string `json:"msg"`
Data interface{} `json:"data"`
}
type Auth struct {
AccessSecret string `json:"accessSecret"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
}
type File struct {
Filename string `fsfile:"filename"`
Header map[string][]string `fsfile:"header"`
Size int64 `fsfile:"size"`
Data []byte `fsfile:"data"`
}
type Meta struct {
TotalCount int64 `json:"total_count"`
PageCount int64 `json:"page_count"`
CurrentPage int `json:"current_page"`
PerPage int `json:"per_page"`
}
// Set 设置Response的Code和Message值
func (resp *Response) Set(Code int, Message string) *Response {
return &Response{
Code: Code,
Message: Message,
}
}
// Set 设置整个Response
func (resp *Response) SetWithData(Code int, Message string, Data interface{}) *Response {
return &Response{
Code: Code,
Message: Message,
Data: Data,
}
}
// SetStatus 设置默认StatusResponse(内部自定义) 默认msg, 可以带data, data只使用一个参数
func (resp *Response) SetStatus(sr *basic.StatusResponse, data ...interface{}) *Response {
newResp := &Response{
Code: sr.Code,
}
if len(data) == 1 {
newResp.Data = data[0]
}
return newResp
}
// SetStatusWithMessage 设置默认StatusResponse(内部自定义) 非默认msg, 可以带data, data只使用一个参数
func (resp *Response) SetStatusWithMessage(sr *basic.StatusResponse, msg string, data ...interface{}) *Response {
newResp := &Response{
Code: sr.Code,
Message: msg,
}
if len(data) == 1 {
newResp.Data = data[0]
}
return newResp
}

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/product/internal/logic"
"fusenapi/server/product/internal/svc"
"fusenapi/server/product/internal/types"
)
func DesignGatherHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.DesignGatherReq
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewDesignGatherLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.DesignGather(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/product/internal/logic"
"fusenapi/server/product/internal/svc"
"fusenapi/server/product/internal/types"
)
func GetLastProductDesignHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.Request
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewGetLastProductDesignLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.GetLastProductDesign(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/product/internal/logic"
"fusenapi/server/product/internal/svc"
"fusenapi/server/product/internal/types"
)
func GetProductDesignHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.GetProductDesignReq
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewGetProductDesignLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.GetProductDesign(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/product/internal/logic"
"fusenapi/server/product/internal/svc"
"fusenapi/server/product/internal/types"
)
func GetRenderDesignHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.GetRenderDesignReq
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewGetRenderDesignLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.GetRenderDesign(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/product/internal/logic"
"fusenapi/server/product/internal/svc"
"fusenapi/server/product/internal/types"
)
func GetSizeByProductHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.Request
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewGetSizeByProductLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.GetSizeByProduct(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/product/internal/logic"
"fusenapi/server/product/internal/svc"
"fusenapi/server/product/internal/types"
)
func OtherProductListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.OtherProductListReq
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewOtherProductListLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.OtherProductList(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -12,46 +12,11 @@ import (
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
[]rest.Route{
{
Method: http.MethodGet,
Path: "/api/product/get-size-by-product",
Handler: GetSizeByProductHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/api/product/design",
Handler: GetProductDesignHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/api/product/design-gather",
Handler: DesignGatherHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/api/product/info",
Handler: GetProductInfoHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/api/product/save-design",
Handler: SaveDesignHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/api/product/other-list",
Handler: OtherProductListHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/api/product/tag_product_list",
Handler: GetTagProductListHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/api/product/render_design",
Handler: GetRenderDesignHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/api/product/get_model_by_pid",
@ -97,11 +62,6 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/api/product/get_render_setting_by_pid",
Handler: GetRenderSettingByPidHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/api/product/get_last_product_design",
Handler: GetLastProductDesignHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/api/product/recommand",

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/product/internal/logic"
"fusenapi/server/product/internal/svc"
"fusenapi/server/product/internal/types"
)
func SaveDesignHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.SaveDesignReq
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewSaveDesignLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.SaveDesign(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -1,159 +0,0 @@
package logic
import (
"context"
"encoding/json"
"errors"
"fusenapi/model/gmodel"
"fusenapi/server/product/internal/svc"
"fusenapi/server/product/internal/types"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"fusenapi/utils/encryption_decryption"
"fusenapi/utils/id_generator"
"fusenapi/utils/ip"
"net/http"
"time"
"gorm.io/gorm"
"github.com/zeromicro/go-zero/core/logx"
)
type DesignGatherLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
ipAddr string
}
func NewDesignGatherLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DesignGatherLogic {
return &DesignGatherLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
// 处理进入前逻辑w,r
func (l *DesignGatherLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
//获取ip地址
ipAddr, err := ip.GetClientIP(r)
if err != nil {
logx.Error(err)
return
// return resp.SetStatusWithMessage(basic.CodeServiceErr, "client ip is not available")
}
l.ipAddr = ipAddr
}
func (l *DesignGatherLogic) DesignGather(req *types.DesignGatherReq, userinfo *auth.UserInfo) (resp *basic.Response) {
if l.ipAddr == "" {
return resp.SetStatusWithMessage(basic.CodeServiceErr, "client ip is not available")
}
encryptWebsetting, err := l.svcCtx.AllModels.FsWebSet.FindValueByKey(l.ctx, "is_encrypt")
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "web setting is_encrypt is not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get web setting")
}
var postInfo map[string]interface{}
//不加密
if encryptWebsetting.Value == nil || *encryptWebsetting.Value == "0" {
if err = json.Unmarshal([]byte(req.Data), &postInfo); err != nil {
return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse json data,format may be invalid")
}
} else { //加密的
//解密数据
desData, err := encryption_decryption.CBCDecrypt(req.Data)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "failed to decryption data")
}
if err = json.Unmarshal([]byte(desData), &postInfo); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse json data,format may be invalid")
}
}
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "client ip is not available")
}
postInfo["client_ip"] = l.ipAddr
var (
optionalId int64
sizeId int64
productId int64
templateId int64
materialId int64
cover string
info string
clientNo string
)
//校验数据
if _, ok := postInfo["optional_id"].(float64); !ok {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "invalid param optional_id")
}
optionalId = int64(postInfo["optional_id"].(float64))
if _, ok := postInfo["size_id"].(float64); !ok {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "invalid param size_id")
}
sizeId = int64(postInfo["size_id"].(float64))
if _, ok := postInfo["product_id"].(float64); !ok {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "invalid param product_id")
}
productId = int64(postInfo["product_id"].(float64))
if _, ok := postInfo["template_id"].(float64); !ok {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "invalid param template_id")
}
templateId = int64(postInfo["template_id"].(float64))
if _, ok := postInfo["material_id"].(float64); !ok {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "invalid param material_id")
}
materialId = int64(postInfo["material_id"].(float64))
if _, ok := postInfo["client_no"].(string); !ok {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "invalid param client_no")
}
clientNo = postInfo["client_no"].(string)
if postInfo["info"] == nil {
info = ""
} else {
jsonInfoBytes, _ := json.Marshal(postInfo["info"])
info = string(jsonInfoBytes)
}
if postInfo["cover"] != nil {
cover = postInfo["cover"].(string)
}
//保存数据
designSn, err := id_generator.GenSnowFlakeId()
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to generate design sn")
}
now := time.Now().UTC().Unix()
err = l.svcCtx.AllModels.FsProductDesignGather.Create(l.ctx, &gmodel.FsProductDesignGather{
Sn: &designSn,
UserId: &userinfo.UserId,
ProductId: &productId,
TemplateId: &templateId,
MaterialId: &materialId,
SizeId: &sizeId,
OptionalId: &optionalId,
Cover: &cover,
Info: &info,
Utime: &now,
ClientIp: &l.ipAddr,
ClientNo: &clientNo,
})
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeSaveErr, "failed to save data")
}
return resp.SetStatusWithMessage(basic.CodeOK, "success", types.DesignGatherRsp{
Sn: designSn,
})
}

View File

@ -1,106 +0,0 @@
package logic
import (
"context"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"fusenapi/server/product/internal/svc"
"fusenapi/server/product/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetLastProductDesignLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetLastProductDesignLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetLastProductDesignLogic {
return &GetLastProductDesignLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetLastProductDesignLogic) GetLastProductDesign(req *types.Request, userinfo *auth.UserInfo) (resp *basic.Response) {
if !userinfo.IsUser() {
return resp.SetStatusAddMessage(basic.CodeUnAuth, "please sign in")
}
//获取用户信息
// user, err := l.svcCtx.AllModels.FsUser.FindUserById(l.ctx, userinfo.UserId)
// if err != nil {
// if errors.Is(err, gorm.ErrRecordNotFound) {
// return resp.SetStatusWithMessage(basic.CodeUnAuth, "user not found")
// }
// logx.Error(err)
// return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get user info")
// }
// //若没打开了个性化渲染按钮
// if *user.IsOpenRender != 1 {
// return resp.SetStatusWithMessage(basic.CodeOK, "success:IsOpenRender switch is closed")
// }
//查询用户最近下单成功的数据
// orderInfo, err := l.svcCtx.AllModels.FsOrder.FindLastSuccessOneOrder(l.ctx, user.Id, int64(constants.STATUS_NEW_NOT_PAY))
// if err != nil {
// if errors.Is(err, gorm.ErrRecordNotFound) {
// return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "none of order is found")
// }
// logx.Error(err)
// return resp.SetStatusAddMessage(basic.CodeDbSqlErr, "failed to get your last order")
// }
//获取该订单相关设计信息
// orderDetail, err := l.svcCtx.AllModels.FsOrderDetail.GetOneOrderDetailByOrderId(l.ctx, orderInfo.Id)
// if err != nil {
// if errors.Is(err, gorm.ErrRecordNotFound) {
// return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "order detail is not found")
// }
// logx.Error(err)
// return resp.SetStatusAddMessage(basic.CodeDbSqlErr, "failed to get order detail")
// }
// //获取设计模板详情便于获得design_id
// orderDetailTemplate, err := l.svcCtx.AllModels.FsOrderDetailTemplate.FindOne(l.ctx, *orderDetail.OrderDetailTemplateId)
// if err != nil {
// if errors.Is(err, gorm.ErrRecordNotFound) {
// return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "order detail template is not found")
// }
// logx.Error(err)
// return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get order detail template")
// }
//最后一次设计不存在,则不返回该设计相关数据
// if *orderDetailTemplate.DesignId <= 0 {
// return resp.SetStatusWithMessage(basic.CodeOK, "success:last design id is not set")
// }
//获取设计数据
// productDesign, err := l.svcCtx.AllModels.FsProductDesign.FindOne(l.ctx, *orderDetailTemplate.DesignId, user.Id)
// if err != nil {
// if errors.Is(err, gorm.ErrRecordNotFound) {
// return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "product design is not found")
// }
// logx.Error(err)
// return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product design")
// }
// 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 resp.SetStatusWithMessage(basic.CodeOK, "success", types.GetLastProductDesignRsp{
Id: 1,
OptionalId: 1,
SizeId: 1,
LogoColor: 1,
Info: nil,
})
}

View File

@ -1,92 +0,0 @@
package logic
import (
"errors"
"fusenapi/model/gmodel"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"gorm.io/gorm"
"context"
"fusenapi/server/product/internal/svc"
"fusenapi/server/product/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetProductDesignLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetProductDesignLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetProductDesignLogic {
return &GetProductDesignLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetProductDesignLogic) GetProductDesign(req *types.GetProductDesignReq, userinfo *auth.UserInfo) (resp *basic.Response) {
if userinfo.GetIdType() != auth.IDTYPE_User {
return resp.SetStatusWithMessage(basic.CodeUnAuth, "please sign in first")
}
if req.Sn == "" {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "param sn is required")
}
//获取设计数据
productDesignModel := gmodel.NewFsProductDesignModel(l.svcCtx.MysqlConn)
designInfo, err := productDesignModel.FindOneBySn(l.ctx, req.Sn, userinfo.UserId)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "design info is not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get design info")
}
//获取产品尺寸信息
productSizeModel := gmodel.NewFsProductSizeModel(l.svcCtx.MysqlConn)
sizeInfo, err := productSizeModel.FindOne(l.ctx, *designInfo.SizeId)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeServiceErr, "product size info is not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get product size info")
}
//获取模板信息
productTemplateV2Model := gmodel.NewFsProductTemplateV2Model(l.svcCtx.MysqlConn)
productTemplateV2Info, err := productTemplateV2Model.FindOne(l.ctx, *designInfo.TemplateId)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "template info is not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get template info")
}
//获取产品模型信息
productModel3dModel := gmodel.NewFsProductModel3dModel(l.svcCtx.MysqlConn)
model3dInfo, err := productModel3dModel.FindOne(l.ctx, *designInfo.OptionalId)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "product 3D model info is not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get product 3D model info")
}
optionalId := *designInfo.OptionalId
if *model3dInfo.Status == 0 && *sizeInfo.Status == 1 && *productTemplateV2Info.Status == 1 && *productTemplateV2Info.IsDel == 0 {
optionalId = 0
}
return resp.SetStatusWithMessage(basic.CodeOK, "success", types.GetProductDesignRsp{
ProductId: *designInfo.ProductId,
TemplateId: *designInfo.TemplateId,
//MaterialId: *designInfo.MaterialId,
SizeId: *designInfo.SizeId,
OptionalId: optionalId,
Cover: *designInfo.Cover,
Info: *designInfo.Info,
})
}

View File

@ -1,535 +0,0 @@
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/encryption_decryption"
"fusenapi/utils/format"
"fusenapi/utils/image"
"fusenapi/utils/step_price"
"strconv"
"strings"
"gorm.io/gorm"
"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")
}
//材料列表
materials := make([]types.MaterialItem, 0, len(materialIdSlice))
for _, v := range materialIdSlice {
if title, ok := constants.MAP_MATERIAL[v]; ok {
materials = append(materials, types.MaterialItem{
Id: v,
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]gmodel.FsProductModel3d) //sizeid为key
for _, v := range model3dList {
model3dIds = append(model3dIds, v.Id)
mapModel3dWithSizeIdIndex[*v.SizeId] = v
}
//通过产品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.ModelId] = struct{}{}
if v.TemplateTag != nil && *v.TemplateTag != "" {
tagId, err := strconv.ParseInt(*v.TemplateTag, 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 {
model3dInfo, ok := mapModel3dWithSizeIdIndex[v.Id]
if !ok {
continue
}
if _, ok = mapTemplateModelId[model3dInfo.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 parse size info`s title")
}
var modelInfo map[string]interface{}
if model3dInfo.ModelInfo != nil && *model3dInfo.ModelInfo != "" {
if err = json.Unmarshal([]byte(*model3dInfo.ModelInfo), &modelInfo); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse model info")
}
}
cover := ""
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])
}
}
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")
}
mapTag := make(map[string]gmodel.FsTags)
for _, v := range tagList {
mapTag[fmt.Sprintf("%d", v.Id)] = v
}
//获取全部模型信息
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]gmodel.FsProductModel3d)
optionTemplateIds := make([]int64, 0, len(allModel3dList))
lightIds := make([]int64, 0, len(allModel3dList))
for _, v := range allModel3dList {
mapAllmodel3d[v.Id] = v
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]gmodel.FsProductTemplateV2)
for _, v := range optionTemplateList {
mapOptionTemplate[v.Id] = v
}
//获取灯光信息
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]gmodel.FsProductModel3dLight)
for _, v := range lightList {
mapLight[v.Id] = v
}
//材料尺寸模板
mapMaterialSizeTmp := make(map[string][]interface{})
//循环阶梯价计算
type MaterialSizePrice struct {
Items []interface{} `json:"items"`
MinPrice float64 `json:"min_price"`
MaxPrice float64 `json:"max_price"`
}
mapMaterialSizePrice := make(map[string]*MaterialSizePrice)
//循环处理组装模板信息
for _, tmp := range productTemplateList {
model3dInfo, ok := mapAllmodel3d[*tmp.ModelId]
if !ok {
continue
}
//如果是配件信息就跳过,不返回
if *model3dInfo.Tag == constants.TAG_PARTS {
continue
}
//未编辑模板信息的数据跳过
if tmp.TemplateInfo == nil || *tmp.TemplateInfo == "" {
continue
}
//解码template info
var templateInfoRsp map[string]interface{}
if tmp.TemplateInfo != nil && *tmp.TemplateInfo != "" {
if err = json.Unmarshal([]byte(*tmp.TemplateInfo), &templateInfoRsp); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse template info")
}
}
if templateInfoRsp["cover"] != nil && templateInfoRsp["cover"].(string) != "" {
cover := templateInfoRsp["cover"].(string)
if req.Size >= 200 {
coverArr := strings.Split(templateInfoRsp["cover"].(string), ".")
cover = fmt.Sprintf("%s_%d.%s", coverArr[0], req.Size, coverArr[1])
}
templateInfoRsp["cover"] = cover
delete(templateInfoRsp, "isPublic")
delete(templateInfoRsp, "name")
}
//解码模型数据
var modelInfoRsp map[string]interface{}
if model3dInfo.ModelInfo != nil && *model3dInfo.ModelInfo != "" {
if err = json.Unmarshal([]byte(*model3dInfo.ModelInfo), &modelInfoRsp); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse model info")
}
}
modelInfoRsp["id"] = model3dInfo.Id
//解码灯光数据
var lightInfoRsp interface{}
lightInfo, ok := mapLight[*model3dInfo.Light]
if ok && lightInfo.Info != nil && *lightInfo.Info != "" {
if err = json.Unmarshal([]byte(*lightInfo.Info), &lightInfoRsp); 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")
}
partListRsp := make([]interface{}, 0, len(modelPartIds))
for _, partId := range modelPartIds {
//判断配件信息是否正常
temModelInfo, ok := mapAllmodel3d[partId]
if !ok || *temModelInfo.Status != 1 {
continue
}
var thisInfo map[string]interface{}
temBytes, _ := json.Marshal(temModelInfo)
_ = json.Unmarshal(temBytes, &thisInfo)
thisInfo["material_img"] = ""
if *temModelInfo.OptionTemplate != 0 {
if optionTemplateInfo, ok := mapOptionTemplate[*temModelInfo.OptionTemplate]; ok {
thisInfo["material_img"] = *optionTemplateInfo.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)
}
tagName := ""
if tagData, ok := mapTag[*tmp.TemplateTag]; ok {
tagName = *tagData.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)
minPriceStr := fmt.Sprintf("%.2f", float64(stepPriceSlice[lenStepPrice-1])/100)
minPrice, _ := strconv.ParseFloat(minPriceStr, 64)
maxPriceStr := fmt.Sprintf("%.2f", float64(stepPriceSlice[0])/100)
maxPrice, _ := strconv.ParseFloat(maxPriceStr, 64)
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 = minPrice
mapMaterialSizePrice[mapMaterialSizePriceKey].MaxPrice = maxPrice
} else {
items := map[string]interface{}{
"num": *priceItem.MinBuyNum,
"total_num": *priceItem.MinBuyNum * (*priceItem.EachBoxNum),
"price": price,
}
mapMaterialSizePrice[mapMaterialSizePriceKey] = &MaterialSizePrice{
Items: []interface{}{items},
MinPrice: minPrice,
MaxPrice: maxPrice,
}
}
*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 = true
isRemoveBg = true
lastDesign = l.getLastDesign(user)
}
var renderDesign interface{}
if req.HaveCloudRendering == true {
renderDesign = l.getRenderDesign(req.ClientNo)
}
//查询是否是加密的(不太合理)
encryptWebsetting, err := l.svcCtx.AllModels.FsWebSet.FindValueByKey(l.ctx, "is_encrypt")
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "web setting is_encrypt is not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get web setting")
}
//不加密
rspData := 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,
Prices: mapMaterialSizePrice,
LastDesign: lastDesign,
RenderDesign: renderDesign,
Colors: color_list.GetColor(),
}
if encryptWebsetting.Value == nil || *encryptWebsetting.Value == "0" {
return resp.SetStatusWithMessage(basic.CodeOK, "success", rspData)
}
bytesData, _ := json.Marshal(rspData)
enData, err := encryption_decryption.CBCEncrypt(string(bytesData))
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to encryption response data")
}
return resp.SetStatusWithMessage(basic.CodeOK, "success", enData)
}
// 获取渲染设计
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",
OrderBy: "`id` DESC",
})
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": 1,
"info": 1,
"logo_color": 1,
"material_id": 1,
"optional_id": 1,
"size_id": 1,
}
}
// 获取按照材料跟尺寸分类的模板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)
}

View File

@ -1,73 +0,0 @@
package logic
import (
"encoding/json"
"errors"
"fusenapi/model/gmodel"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"gorm.io/gorm"
"strings"
"context"
"fusenapi/server/product/internal/svc"
"fusenapi/server/product/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetRenderDesignLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetRenderDesignLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetRenderDesignLogic {
return &GetRenderDesignLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetRenderDesignLogic) GetRenderDesign(req *types.GetRenderDesignReq, userinfo *auth.UserInfo) (resp *basic.Response) {
req.Sn = strings.Trim(req.Sn, " ")
if req.Sn == "" {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "err param:sn is empty")
}
renderDesign, err := l.svcCtx.AllModels.FsProductRenderDesign.FindOneRenderDesignByParams(l.ctx, gmodel.FindOneRenderDesignByParamsReq{
Sn: &req.Sn,
Fields: "id,info,material_id,optional_id,size_id,template_id",
OrderBy: "`id` DESC",
})
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "render design is not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get render design info")
}
var color []string
if renderDesign.LogoColor != nil && *renderDesign.LogoColor != "" {
if err = json.Unmarshal([]byte(*renderDesign.LogoColor), &color); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse render logo color")
}
}
var info interface{}
if renderDesign.Info != nil && *renderDesign.Info != "" {
if err = json.Unmarshal([]byte(*renderDesign.Info), &info); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse render design info")
}
}
return resp.SetStatusWithMessage(basic.CodeOK, "success", types.GetRenderDesignRsp{
Id: renderDesign.Id,
Info: info,
OptionalId: *renderDesign.OptionalId,
SizeId: *renderDesign.SizeId,
TemplateId: *renderDesign.TemplateId,
LogoColor: color,
})
}

View File

@ -1,142 +0,0 @@
package logic
import (
"context"
"errors"
"fusenapi/model/gmodel"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"fusenapi/utils/format"
"fusenapi/utils/image"
"strings"
"gorm.io/gorm"
"fusenapi/server/product/internal/svc"
"fusenapi/server/product/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type OtherProductListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewOtherProductListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *OtherProductListLogic {
return &OtherProductListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *OtherProductListLogic) OtherProductList(req *types.OtherProductListReq, userinfo *auth.UserInfo) (resp *basic.Response) {
if req.Num <= 0 || req.Num > 100 {
req.Num = 4
}
if req.Size > 0 {
req.Size = image.GetCurrentSize(req.Size)
}
//获取用户信息
user, 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.CodeDbSqlErr, "failed to get user info")
}
tagInfo, err := l.svcCtx.AllModels.FsTags.FindOne(l.ctx, req.Cid)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the tag info is not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get tage info")
}
if *tagInfo.Status != 1 {
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "tage info is not available")
}
if tagInfo.RecommendProduct == nil || *tagInfo.RecommendProduct == "" {
return resp.SetStatusWithMessage(basic.CodeOK, "success")
}
pids, err := format.StrSlicToInt64Slice(strings.Split(*tagInfo.RecommendProduct, ","))
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to parse recommend product")
}
list, err := l.getRandom(pids, int(req.Num))
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get random list")
}
if req.Size <= 0 {
return resp.SetStatusWithMessage(basic.CodeOK, "success,", list)
}
//千人前面处理
for _, v := range list {
r := &image.ThousandFaceImageFormatReq{
Size: int(req.Size),
IsThousandFace: 0,
Cover: v.Cover,
CoverImg: v.CoverImg,
CoverDefault: "",
ProductId: v.Id,
UserId: user.Id,
}
if user.Id > 0 {
r.IsThousandFace = 1
}
image.ThousandFaceImageFormat(r)
v.Cover = r.Cover
v.CoverImg = r.CoverImg
v.CoverDefault = r.CoverDefault
}
return resp.SetStatusWithMessage(basic.CodeOK, "success,", list)
}
func (l *OtherProductListLogic) getRandom(productIds []int64, limit int) (result []types.OtherProductListRsp, err error) {
if len(productIds) == 0 {
return
}
//获取推荐产品信息
recommendProductList, err := l.svcCtx.AllModels.FsProduct.GetRandomProductListInIds(l.ctx, productIds, limit)
if err != nil {
return nil, err
}
if len(recommendProductList) == 0 {
return
}
mapProduct := make(map[int64]int)
newProductIds := make([]int64, 0, len(recommendProductList))
for k, v := range recommendProductList {
newProductIds = append(newProductIds, v.Id)
mapProduct[v.Id] = k
}
//查询最新的sku
reqStatus := int64(1)
productTemplateIds, err := l.svcCtx.AllModels.FsProductTemplateV2.GetProductTemplateListByParams(l.ctx, gmodel.GetProductTemplateListByParamsReq{
ProductIds: newProductIds,
GroupBy: "product_id",
OrderBy: "id DESC,sort DESC",
Fields: "product_id,max(id) as id",
Status: &reqStatus,
})
if err != nil {
return nil, err
}
for _, v := range productTemplateIds {
productIndex, ok := mapProduct[*v.ProductId]
if !ok {
continue
}
productInfo := recommendProductList[productIndex]
result = append(result, types.OtherProductListRsp{
Title: *productInfo.Title,
Cover: *productInfo.Cover,
CoverImg: *productInfo.CoverImg,
Sn: *productInfo.Sn,
Id: *v.ProductId,
SkuId: v.Id,
})
}
return result, nil
}

View File

@ -1,169 +0,0 @@
package logic
import (
"encoding/json"
"errors"
"fmt"
"fusenapi/constants"
"fusenapi/model/gmodel"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"fusenapi/utils/encryption_decryption"
"fusenapi/utils/id_generator"
"image"
"image/gif"
"image/jpeg"
"image/png"
"net/http"
"os"
"path"
"time"
"github.com/google/uuid"
"github.com/nfnt/resize"
"gorm.io/gorm"
"context"
"fusenapi/server/product/internal/svc"
"fusenapi/server/product/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type SaveDesignLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewSaveDesignLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SaveDesignLogic {
return &SaveDesignLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *SaveDesignLogic) SaveDesign(req *types.SaveDesignReq, userinfo *auth.UserInfo) (resp *basic.Response) {
if userinfo.GetIdType() != auth.IDTYPE_User {
return resp.SetStatusWithMessage(basic.CodeUnAuth, "please sign in first")
}
//查询是否是加密的(不太合理)
encryptWebsetting, err := l.svcCtx.AllModels.FsWebSet.FindValueByKey(l.ctx, "is_encrypt")
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "web setting is_encrypt is not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get web setting")
}
var postInfo types.SaveDesignReqRealStruct
//不加密
if encryptWebsetting.Value == nil || *encryptWebsetting.Value == "0" {
if err = json.Unmarshal([]byte(req.Data), &postInfo); err != nil {
return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse json data,format may be invalid")
}
} else { //加密的
//解密数据
desData, err := encryption_decryption.CBCDecrypt(req.Data)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "failed to decryption data")
}
if err = json.Unmarshal([]byte(desData), &postInfo); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse json data")
}
}
infoBytes, _ := json.Marshal(postInfo.Data)
info := string(infoBytes)
now := time.Now().UTC()
logoColorBytes, _ := json.Marshal(postInfo.Data.Logo.Colors)
logoColor := string(logoColorBytes)
saveData := gmodel.FsProductDesign{
UserId: &userinfo.UserId,
ProductId: &postInfo.ProductId,
TemplateId: &postInfo.TemplateId,
SizeId: &postInfo.SizeId,
OptionalId: &postInfo.OptionalId,
Cover: &postInfo.Cover,
Info: &info,
Utime: &now,
LogoColor: &logoColor,
PageGuid: &postInfo.PageGuid,
}
switch postInfo.Sn {
case "": //新增
status := int64(1)
postInfo.Sn, err = id_generator.GenSnowFlakeId()
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to gen sn ")
}
saveData.Status = &status
saveData.Sn = &postInfo.Sn
err = l.svcCtx.AllModels.FsProductDesign.Create(l.ctx, &saveData)
default: //更新
err = l.svcCtx.AllModels.FsProductDesign.UpdateBySn(l.ctx, postInfo.Sn, &saveData)
}
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to save design")
}
if postInfo.Cover == "" {
return resp.SetStatusWithMessage(basic.CodeOK, "success", types.SaveDesignRsp{Sn: postInfo.Sn})
}
// TODO 图片待优化处理
/*if err = l.CreateStepThumbnailImage(l.ctx, postInfo.Cover); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to create step thumbnail image ")
}*/
return resp.SetStatusWithMessage(basic.CodeOK, "success", types.SaveDesignRsp{Sn: postInfo.Sn})
}
// 创建阶梯缩略图
func (l *SaveDesignLogic) CreateStepThumbnailImage(ctx context.Context, coverImage string) error {
httpRsp, err := http.Get(coverImage)
if err != nil {
return err
}
defer httpRsp.Body.Close()
coverImg, _, err := image.Decode(httpRsp.Body)
if err != nil {
return err
}
coverImgOrgWith := coverImg.Bounds().Dx()
coverImgOrgHeight := coverImg.Bounds().Dy()
fileExt := path.Ext(coverImage)
for _, size := range constants.IMAGE_CROPPING_STEP_SIZE {
//尺寸大于原图
if size > coverImgOrgWith {
continue
}
//缩放比例按照宽度来设定
scale := size / coverImgOrgWith
height := scale * coverImgOrgHeight
tmpImage := resize.Resize(uint(size), uint(height), coverImg, resize.Lanczos3)
fileName := fmt.Sprintf("%s_%d_%s", uuid.New().String(), size, fileExt)
targetFile, err := os.Create(fileName)
if err != nil {
return err
}
defer targetFile.Close()
switch fileExt {
case ".png":
err = png.Encode(targetFile, tmpImage)
case ".jpg", ".jpeg":
err = jpeg.Encode(targetFile, tmpImage, &jpeg.Options{Quality: 100})
case ".gif":
err = gif.Encode(targetFile, tmpImage, nil)
default:
err = errors.New("unSupport image format")
}
if err != nil {
return err
}
}
return nil
}

View File

@ -5,180 +5,6 @@ import (
"fusenapi/utils/basic"
)
type GetSizeByProductRsp struct {
Id int64 `json:"id"`
Name string `json:"name"`
Children []Children `json:"children"`
}
type Children struct {
Id int64 `json:"id"`
Name string `json:"name"`
Cycle int `json:"cycle"`
ChildrenList []ChildrenObj `json:"children"`
}
type ChildrenObj struct {
Id int64 `json:"id"`
Name string `json:"name"`
PriceList []PriceObj `json:"price_list"`
}
type PriceObj struct {
Num int `json:"num"`
Price float64 `json:"price"`
}
type GetProductDesignReq struct {
Sn string `form:"sn"`
}
type GetProductDesignRsp struct {
ProductId int64 `json:"product_id"`
TemplateId int64 `json:"template_id"`
SizeId int64 `json:"size_id"`
OptionalId int64 `json:"optional_id"`
Cover string `json:"cover"`
Info string `json:"info"`
}
type DesignGatherReq struct {
Data string `json:"data"`
}
type DesignGatherRsp struct {
Sn string `json:"sn"`
}
type GetProductInfoReq struct {
Pid string `form:"pid"`
Size uint32 `form:"size"`
ClientNo string `form:"client_no"`
HaveCloudRendering bool `form:"haveCloudRendering,optional"`
}
type GetProductInfoRsp struct {
Id int64 `json:"id"`
Type int64 `json:"type"`
Title string `json:"title"`
IsEnv int64 `json:"isEnv"`
IsMicro int64 `json:"isMicro"`
TypeName string `json:"typeName"`
IsLowRendering bool `json:"is_low_rendering"`
IsRemoveBg bool `json:"is_remove_bg"`
Materials []MaterialItem `json:"materials"`
Sizes []SizeItem `json:"sizes"`
Templates interface{} `json:"templates"`
Prices interface{} `json:"prices"`
LastDesign interface{} `json:"last_design"`
RenderDesign interface{} `json:"render_design"`
Colors interface{} `json:"colors"`
}
type SizeItem struct {
Id int64 `json:"id"`
Title SizeTitle `json:"title"`
Capacity string `json:"capacity"`
Cover string `json:"cover"`
Sort int64 `json:"sort"`
PartsCanDeleted bool `json:"parts_can_deleted"`
}
type SizeTitle struct {
Cm string `json:"cm"`
Inch string `json:"inch"`
}
type MaterialItem struct {
Id int64 `json:"id"`
Title string `json:"title"`
}
type SaveDesignReq struct {
Data string `json:"data"` //加密信息
}
type SaveDesignRsp struct {
Sn string `json:"sn"`
}
type SaveDesignReqRealStruct struct {
ProductId int64 `json:"product_id"`
SizeId int64 `json:"size_id"`
OptionalId int64 `json:"optional_id"`
TemplateId int64 `json:"template_id"`
Sn string `json:"sn"`
Data DesignData `json:"data"`
Cover string `json:"cover"`
PageGuid string `json:"pageGuid"`
}
type DesignData struct {
MainColor ColorFill `json:"MainColor"`
SecondaryColor ColorFill `json:"SecondaryColor"`
Logo DesignLogo `json:"Logo"`
Slogan DesignSlogan `json:"Slogan"`
QRcode DesignQRcode `json:"QRcode"`
Website DesignWebsite `json:"Website"`
Phone DesignPhone `json:"Phone"`
Address DesignAddress `json:"Address"`
}
type DesignAddress struct {
Text string `json:"text"`
IfShow bool `json:"ifShow"`
}
type DesignPhone struct {
Text string `json:"text"`
IfShow bool `json:"ifShow"`
}
type DesignWebsite struct {
Text string `json:"text"`
IfShow bool `json:"ifShow"`
}
type DesignQRcode struct {
Text string `json:"text"`
SvgPath string `json:"svgPath"`
IfShow bool `json:"ifShow"`
}
type DesignSlogan struct {
Text string `json:"text"`
IfShow bool `json:"ifShow"`
}
type DesignLogo struct {
Material string `json:"material"`
MaterialName string `json:"materialName"`
MaterialTime string `json:"materialTime"`
Fill string `json:"fill"`
FillName string `json:"fill_name"`
Colors []string `json:"colors"`
}
type ColorFill struct {
Fill string `json:"fill"`
}
type OtherProductListReq struct {
Cid int64 `form:"cid"`
Num int64 `form:"num"`
Size uint32 `form:"size"`
}
type OtherProductListRsp struct {
Title string `json:"title"`
Cover string `json:"cover"`
CoverImg string `json:"cover_img"`
CoverDefault string `json:"cover_default"`
Sn string `json:"sn"`
Id int64 `json:"id"`
SkuId int64 `json:"sku_id"`
}
type GetRecommandProductListReq struct {
Size int32 `form:"size,optional"`
Num int64 `form:"num,optional"`
@ -243,19 +69,6 @@ type CoverDefaultItem struct {
CoverMetadata interface{} `json:"cover_metadata"`
}
type GetRenderDesignReq struct {
Sn string `form:"sn"`
}
type GetRenderDesignRsp struct {
Id int64 `json:"id"`
Info interface{} `json:"info"`
OptionalId int64 `json:"optional_id"`
SizeId int64 `json:"size_id"`
TemplateId int64 `json:"template_id"`
LogoColor []string `json:"logo_color"`
}
type GetModelByPidReq struct {
Pid string `form:"pid"` //实际上是产品sn
}
@ -360,14 +173,6 @@ type GetRenderSettingByPidRsp struct {
Colors interface{} `json:"colors"`
}
type GetLastProductDesignRsp struct {
Id int64 `json:"id"`
OptionalId int64 `json:"optional_id"`
SizeId int64 `json:"size_id"`
LogoColor interface{} `json:"logo_color"`
Info interface{} `json:"info"`
}
type HomePageRecommendProductListReq struct {
Size uint32 `form:"size"`
MerchantType int64 `form:"merchant_type"`

23
server_api/collection.api Normal file
View File

@ -0,0 +1,23 @@
syntax = "v1"
info (
title: "collection"// TODO: add title
desc: "收藏服务"// TODO: add description
author: ""
email: ""
)
import "basic.api"
service collection {
//收藏产品
@handler CollectProductHandler
post /api/collection/collect_product(CollectProductReq) returns (response);
}
//收藏产品
type CollectProductReq {
ProductId int64 `json:"product_id"`
Logo string `json:"logo"`
SelectColorIndex int64 `json:"select_color_index"`
TemplateTag string `json:"template_tag"`
}

View File

@ -10,31 +10,9 @@ info (
import "basic.api"
service product {
//获取分类下的产品以及尺寸
@handler GetSizeByProductHandler
get /api/product/get-size-by-product(request) returns (response);
//获取保存的设计信息
@handler GetProductDesignHandler
get /api/product/design(GetProductDesignReq) returns (response);
//产品设计数据采集
@handler DesignGatherHandler
post /api/product/design-gather(DesignGatherReq) returns (response);
//获取产品信息
@handler GetProductInfoHandler
get /api/product/info(GetProductInfoReq) returns (response);
//保存设计信息
@handler SaveDesignHandler
post /api/product/save-design(SaveDesignReq) returns (response);
//其他产品推荐列表
@handler OtherProductListHandler
get /api/product/other-list(OtherProductListReq) returns (response);
//获取分类产品列表
@handler GetTagProductListHandler
get /api/product/tag_product_list(GetTagProductListReq) returns (response);
//*********************产品详情分解接口开始***********************
//获取云渲染设计方案信息
@handler GetRenderDesignHandler
get /api/product/render_design(GetRenderDesignReq) returns (response);
//获取产品模型信息
@handler GetModelByPidHandler
get /api/product/get_model_by_pid(GetModelByPidReq) returns (response);
@ -62,178 +40,14 @@ service product {
//获取产品渲染设置
@handler GetRenderSettingByPidHandler
get /api/product/get_render_setting_by_pid(GetRenderSettingByPidReq) returns (response);
//获取产品千人千面设计方案
@handler GetLastProductDesignHandler
get /api/product/get_last_product_design(request) returns (response);
//获取详情页推荐产品列表
@handler GetRecommandProductListHandler
get /api/product/recommand(GetRecommandProductListReq) returns (response);
//获取列表页推荐产品列表
@handler HomePageRecommendProductListHandler
get /api/product/home_page_recommend(HomePageRecommendProductListReq) returns (response);
//*********************产品详情分解接口结束***********************
//*********************推荐产品接口开始××××××××××××××××××××××××××
//*********************推荐产品接口结束××××××××××××××××××××××××××
}
//获取分类下的产品以及尺寸
type GetSizeByProductRsp {
Id int64 `json:"id"`
Name string `json:"name"`
Children []Children `json:"children"`
}
type Children {
Id int64 `json:"id"`
Name string `json:"name"`
Cycle int `json:"cycle"`
ChildrenList []ChildrenObj `json:"children"`
}
type ChildrenObj {
Id int64 `json:"id"`
Name string `json:"name"`
PriceList []PriceObj `json:"price_list"`
}
type PriceObj {
Num int `json:"num"`
Price float64 `json:"price"`
}
//获取保存的设计信息
type GetProductDesignReq {
Sn string `form:"sn"`
}
type GetProductDesignRsp {
ProductId int64 `json:"product_id"`
TemplateId int64 `json:"template_id"`
//MaterialId int64 `json:"material_id"`
SizeId int64 `json:"size_id"`
OptionalId int64 `json:"optional_id"`
Cover string `json:"cover"`
Info string `json:"info"`
}
//产品设计数据采集
type DesignGatherReq {
Data string `json:"data"`
}
type DesignGatherRsp {
Sn string `json:"sn"`
}
//获取产品信息
type GetProductInfoReq {
Pid string `form:"pid"`
Size uint32 `form:"size"`
ClientNo string `form:"client_no"`
HaveCloudRendering bool `form:"haveCloudRendering,optional"`
}
type GetProductInfoRsp {
Id int64 `json:"id"`
Type int64 `json:"type"`
Title string `json:"title"`
IsEnv int64 `json:"isEnv"`
IsMicro int64 `json:"isMicro"`
TypeName string `json:"typeName"`
IsLowRendering bool `json:"is_low_rendering"`
IsRemoveBg bool `json:"is_remove_bg"`
Materials []MaterialItem `json:"materials"`
Sizes []SizeItem `json:"sizes"`
Templates interface{} `json:"templates"`
Prices interface{} `json:"prices"`
LastDesign interface{} `json:"last_design"`
RenderDesign interface{} `json:"render_design"`
Colors interface{} `json:"colors"`
}
type SizeItem {
Id int64 `json:"id"`
Title SizeTitle `json:"title"`
Capacity string `json:"capacity"`
Cover string `json:"cover"`
Sort int64 `json:"sort"`
PartsCanDeleted bool `json:"parts_can_deleted"`
}
type SizeTitle {
Cm string `json:"cm"`
Inch string `json:"inch"`
}
type MaterialItem {
Id int64 `json:"id"`
Title string `json:"title"`
}
//保存设计信息
type SaveDesignReq {
Data string `json:"data"` //加密信息
}
type SaveDesignRsp {
Sn string `json:"sn"`
}
//保存设计信息(解密结构体)
type SaveDesignReqRealStruct {
ProductId int64 `json:"product_id"`
SizeId int64 `json:"size_id"`
OptionalId int64 `json:"optional_id"`
TemplateId int64 `json:"template_id"`
Sn string `json:"sn"`
Data DesignData `json:"data"`
Cover string `json:"cover"`
PageGuid string `json:"pageGuid"`
}
type DesignData {
MainColor ColorFill `json:"MainColor"`
SecondaryColor ColorFill `json:"SecondaryColor"`
Logo DesignLogo `json:"Logo"`
Slogan DesignSlogan `json:"Slogan"`
QRcode DesignQRcode `json:"QRcode"`
Website DesignWebsite `json:"Website"`
Phone DesignPhone `json:"Phone"`
Address DesignAddress `json:"Address"`
}
type DesignAddress {
Text string `json:"text"`
IfShow bool `json:"ifShow"`
}
type DesignPhone {
Text string `json:"text"`
IfShow bool `json:"ifShow"`
}
type DesignWebsite {
Text string `json:"text"`
IfShow bool `json:"ifShow"`
}
type DesignQRcode {
Text string `json:"text"`
SvgPath string `json:"svgPath"`
IfShow bool `json:"ifShow"`
}
type DesignSlogan {
Text string `json:"text"`
IfShow bool `json:"ifShow"`
}
type DesignLogo {
Material string `json:"material"`
MaterialName string `json:"materialName"`
MaterialTime string `json:"materialTime"`
Fill string `json:"fill"`
FillName string `json:"fill_name"`
Colors []string `json:"colors"`
}
type ColorFill {
Fill string `json:"fill"`
}
//其他产品推荐列表
type OtherProductListReq {
Cid int64 `form:"cid"`
Num int64 `form:"num"`
Size uint32 `form:"size"`
}
type OtherProductListRsp {
Title string `json:"title"`
Cover string `json:"cover"`
CoverImg string `json:"cover_img"`
CoverDefault string `json:"cover_default"`
Sn string `json:"sn"`
Id int64 `json:"id"`
SkuId int64 `json:"sku_id"`
}
//获取详情页推荐产品列表
type GetRecommandProductListReq {
Size int32 `form:"size,optional"`
@ -294,19 +108,6 @@ type CoverDefaultItem {
Cover string `json:"cover"`
CoverMetadata interface{} `json:"cover_metadata"`
}
//获取云渲染设计方案信息
type GetRenderDesignReq {
Sn string `form:"sn"`
}
type GetRenderDesignRsp {
Id int64 `json:"id"`
Info interface{} `json:"info"`
OptionalId int64 `json:"optional_id"`
SizeId int64 `json:"size_id"`
TemplateId int64 `json:"template_id"`
LogoColor []string `json:"logo_color"`
}
//获取产品模型信息
type GetModelByPidReq {
Pid string `form:"pid"` //实际上是产品sn
@ -404,14 +205,6 @@ type GetRenderSettingByPidRsp {
LastDesign bool `json:"last_design"` //是否拥有千人千面设计方案
Colors interface{} `json:"colors"`
}
//获取产品千人千面设计方案
type GetLastProductDesignRsp {
Id int64 `json:"id"`
OptionalId int64 `json:"optional_id"`
SizeId int64 `json:"size_id"`
LogoColor interface{} `json:"logo_color"`
Info interface{} `json:"info"`
}
//获取列表页推荐产品(返回是这个维度数组)
type HomePageRecommendProductListReq {
Size uint32 `form:"size"`