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 }