diff --git a/model/gmodel/fs_product_design_gather_logic.go b/model/gmodel/fs_product_design_gather_logic.go index e68225aa..a008e6d3 100644 --- a/model/gmodel/fs_product_design_gather_logic.go +++ b/model/gmodel/fs_product_design_gather_logic.go @@ -1,2 +1,9 @@ package gmodel -// TODO: 使用model的属性做你想做的 \ No newline at end of file + +import "context" + +// TODO: 使用model的属性做你想做的 + +func (g *FsProductDesignGatherModel) Create(ctx context.Context, data *FsProductDesignGather) error { + return g.db.WithContext(ctx).Create(&data).Error +} diff --git a/model/gmodel/fs_product_design_logic.go b/model/gmodel/fs_product_design_logic.go index afd82d0b..23c0aa69 100755 --- a/model/gmodel/fs_product_design_logic.go +++ b/model/gmodel/fs_product_design_logic.go @@ -28,3 +28,6 @@ func (d *FsProductDesignModel) GetAllByIdsWithoutStatus(ctx context.Context, ids } return } +func (d *FsProductDesignModel) Create(ctx context.Context, data *FsProductDesign) error { + return d.db.WithContext(ctx).Model(&FsProductDesign{}).Create(&data).Error +} diff --git a/model/gmodel/var_gen.go b/model/gmodel/var_gen.go index 01ef144f..9ee69c43 100644 --- a/model/gmodel/var_gen.go +++ b/model/gmodel/var_gen.go @@ -41,7 +41,6 @@ type AllModelsGen struct { FsMapLibrary *FsMapLibraryModel // fs_map_library 贴图库 FsMenu *FsMenuModel // fs_menu 后台菜单 FsMigration *FsMigrationModel // fs_migration 版本库 - FsOrder *FsOrderModel // fs_order FsOrderAffiliate *FsOrderAffiliateModel // fs_order_affiliate 订单附属表-流程控制时间等 FsOrderDetail *FsOrderDetailModel // fs_order_detail 订单详细表 FsOrderDetailTemplate *FsOrderDetailTemplateModel // fs_order_detail_template 订单模板详细表 @@ -50,6 +49,7 @@ type AllModelsGen struct { FsProduct *FsProductModel // fs_product 产品表 FsProductCopy1 *FsProductCopy1Model // fs_product_copy1 产品表 FsProductDesign *FsProductDesignModel // fs_product_design 产品设计表 + FsProductDesignGather *FsProductDesignGatherModel // fs_product_design_gather FsProductModel3d *FsProductModel3dModel // fs_product_model3d 产品模型表 FsProductModel3dLight *FsProductModel3dLightModel // fs_product_model3d_light 模型-灯光组表 FsProductOption *FsProductOptionModel // fs_product_option 产品选项表(已废弃) @@ -120,7 +120,6 @@ func NewAllModels(gdb *gorm.DB) *AllModelsGen { FsMapLibrary: NewFsMapLibraryModel(gdb), FsMenu: NewFsMenuModel(gdb), FsMigration: NewFsMigrationModel(gdb), - FsOrder: NewFsOrderModel(gdb), FsOrderAffiliate: NewFsOrderAffiliateModel(gdb), FsOrderDetail: NewFsOrderDetailModel(gdb), FsOrderDetailTemplate: NewFsOrderDetailTemplateModel(gdb), @@ -129,6 +128,7 @@ func NewAllModels(gdb *gorm.DB) *AllModelsGen { FsProduct: NewFsProductModel(gdb), FsProductCopy1: NewFsProductCopy1Model(gdb), FsProductDesign: NewFsProductDesignModel(gdb), + FsProductDesignGather: NewFsProductDesignGatherModel(gdb), FsProductModel3d: NewFsProductModel3dModel(gdb), FsProductModel3dLight: NewFsProductModel3dLightModel(gdb), FsProductOption: NewFsProductOptionModel(gdb), diff --git a/server/product/internal/handler/designgatherhandler.go b/server/product/internal/handler/designgatherhandler.go new file mode 100644 index 00000000..ca3b8296 --- /dev/null +++ b/server/product/internal/handler/designgatherhandler.go @@ -0,0 +1,78 @@ +package handler + +import ( + "errors" + "net/http" + + "github.com/zeromicro/go-zero/core/logx" + "github.com/zeromicro/go-zero/rest/httpx" + + "fusenapi/utils/auth" + "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 ( + // 定义错误变量 + err error + // 定义用户信息变量 + userinfo *auth.UserInfo + ) + // 解析JWT token,并对空用户进行判断 + claims, err := svcCtx.ParseJwtToken(r) + // 如果解析JWT token出错,则返回未授权的JSON响应并记录错误消息 + if err != nil { + httpx.OkJsonCtx(r.Context(), w, &basic.Response{ + Code: 401, // 返回401状态码,表示未授权 + Message: "unauthorized", // 返回未授权信息 + }) + logx.Info("unauthorized:", err.Error()) // 记录错误日志 + return + } + + if claims != nil { + // 从token中获取对应的用户信息 + userinfo, err = auth.GetUserInfoFormMapClaims(claims) + // 如果获取用户信息出错,则返回未授权的JSON响应并记录错误消息 + if err != nil { + httpx.OkJsonCtx(r.Context(), w, &basic.Response{ + Code: 401, + Message: "unauthorized", + }) + logx.Info("unauthorized:", err.Error()) + return + } + } else { + // 如果claims为nil,则认为用户身份为白板用户 + userinfo = &auth.UserInfo{UserId: 0, GuestId: 0} + } + + var req types.DesignGatherReq + // 如果端点有请求结构体,则使用httpx.Parse方法从HTTP请求体中解析请求数据 + if err := httpx.Parse(r, &req); err != nil { + httpx.OkJsonCtx(r.Context(), w, &basic.Response{ + Code: 510, + Message: "parameter error", + }) + logx.Info(err) + return + } + // 创建一个业务逻辑层实例 + l := logic.NewDesignGatherLogic(r.Context(), svcCtx) + resp := l.DesignGather(&req, userinfo, r) + // 如果响应不为nil,则使用httpx.OkJsonCtx方法返回JSON响应; + if resp != nil { + httpx.OkJsonCtx(r.Context(), w, resp) + } else { + err := errors.New("server logic is error, resp must not be nil") + httpx.ErrorCtx(r.Context(), w, err) + logx.Error(err) + } + } +} diff --git a/server/product/internal/handler/routes.go b/server/product/internal/handler/routes.go index 847df645..48ef724f 100644 --- a/server/product/internal/handler/routes.go +++ b/server/product/internal/handler/routes.go @@ -32,6 +32,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { Path: "/product/design", Handler: GetProductDesignHandler(serverCtx), }, + { + Method: http.MethodPost, + Path: "/product/design-gather", + Handler: DesignGatherHandler(serverCtx), + }, }, ) } diff --git a/server/product/internal/logic/designgatherlogic.go b/server/product/internal/logic/designgatherlogic.go new file mode 100644 index 00000000..38d075b5 --- /dev/null +++ b/server/product/internal/logic/designgatherlogic.go @@ -0,0 +1,142 @@ +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" + "gorm.io/gorm" + "net/http" + "time" + + "github.com/zeromicro/go-zero/core/logx" +) + +type DesignGatherLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewDesignGatherLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DesignGatherLogic { + return &DesignGatherLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *DesignGatherLogic) DesignGather(req *types.DesignGatherReq, userinfo *auth.UserInfo, r *http.Request) (resp *basic.Response) { + 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") + } + } + //获取ip地址 + ipAddr, err := ip.GetClientIP(r) + if err != nil { + logx.Error(err) + return resp.SetStatusWithMessage(basic.CodeServiceErr, "client ip is not available") + } + postInfo["client_ip"] = 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().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: &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, + }) +} diff --git a/server/product/internal/types/types.go b/server/product/internal/types/types.go index 04901fbb..8662df52 100644 --- a/server/product/internal/types/types.go +++ b/server/product/internal/types/types.go @@ -95,6 +95,14 @@ type GetProductDesignRsp struct { Info string `json:"info"` } +type DesignGatherReq struct { + Data string `json:"data"` +} + +type DesignGatherRsp struct { + Sn string `json:"sn"` +} + type Request struct { } diff --git a/server_api/product.api b/server_api/product.api index f016a52c..7445bf18 100644 --- a/server_api/product.api +++ b/server_api/product.api @@ -22,6 +22,9 @@ service product { //获取保存的设计信息 @handler GetProductDesignHandler get /product/design(GetProductDesignReq) returns (response); + //产品设计数据采集 + @handler DesignGatherHandler + post /product/design-gather (DesignGatherReq) returns (response); } //获取产品列表 @@ -106,4 +109,11 @@ type GetProductDesignRsp { 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"` } \ No newline at end of file diff --git a/utils/basic/basic.go b/utils/basic/basic.go index 58a78932..292f7111 100644 --- a/utils/basic/basic.go +++ b/utils/basic/basic.go @@ -37,6 +37,9 @@ var ( CodeDbCreateErr = &StatusResponse{5004, "failed to create record in database"} // 数据库中创建记录失败 CodeDbSqlErr = &StatusResponse{5005, "database error"} // 数据库错误 CodeJsonErr = &StatusResponse{5006, "JSON error"} // JSON解析错误 + + CodeAesCbcEncryptionErr = &StatusResponse{5106, "encryption data err"} // 加密数据失败 + CodeAesCbcDecryptionErr = &StatusResponse{5107, "decryption data err"} // 解密数据失败 ) type Response struct { diff --git a/utils/ip/remote_addr.go b/utils/ip/remote_addr.go index 5c861f3f..37a200bf 100644 --- a/utils/ip/remote_addr.go +++ b/utils/ip/remote_addr.go @@ -1 +1,25 @@ package ip + +import ( + "net" + "net/http" + "strings" +) + +// 获取客户端ip地址 +func GetClientIP(r *http.Request) (ip string, err error) { + xForwardedFor := r.Header.Get("X-Forwarded-For") + ip = strings.TrimSpace(strings.Split(xForwardedFor, ",")[0]) + if ip != "" { + return ip, nil + } + ip = strings.TrimSpace(r.Header.Get("X-Real-Ip")) + if ip != "" { + return ip, nil + } + ip, _, err = net.SplitHostPort(strings.TrimSpace(r.RemoteAddr)) + if err != nil { + return "", err + } + return ip, nil +}