package repositories import ( "context" "encoding/json" "errors" "fusenapi/constants" "fusenapi/model/gmodel" "fusenapi/utils/curl" "fusenapi/utils/file" "fusenapi/utils/hash" "time" "github.com/aws/aws-sdk-go/aws/session" "github.com/zeromicro/go-zero/core/logc" "github.com/zeromicro/go-zero/core/logx" "gorm.io/gorm" ) func NewImageHandle(gormDB *gorm.DB, bLMServiceUrl *string, awsSession *session.Session) ImageHandle { return &defaultImageHandle{ MysqlConn: gormDB, BLMServiceUrl: bLMServiceUrl, AwsSession: awsSession, } } type ( defaultImageHandle struct { MysqlConn *gorm.DB BLMServiceUrl *string AwsSession *session.Session } ImageHandle = interface { // 获取logo最新信息 LogoInfo(ctx context.Context, in *LogoInfoReq) (*LogoInfoRes, error) // logo信息 LogoInfoSet(ctx context.Context, in *LogoInfoSetReq) (*LogoInfoSetRes, error) // logo合图 LogoCombine(ctx context.Context, in *LogoCombineReq) (*LogoCombineRes, error) // logo裁剪 LogoStandard(ctx context.Context, in *LogoStandardReq) (*LogoStandardRes, error) } ) /* 获取logo最新信息 */ type ( LogoInfoReq struct { UserId int64 `json:"user_id"` GuestId int64 `json:"guest_id"` } LogoInfoRes struct { Metadata *string `json:"metadata"` LogoUrl *string `json:"logo_url"` UserInfoMetadata *string `json:"user_info_metadata"` } ) func (l *defaultImageHandle) LogoInfo(ctx context.Context, in *LogoInfoReq) (*LogoInfoRes, error) { var metadata *string var logoUrl *string var userInfoMetadata *string // 更新用户信息 var module = "profile" userInfoGorm := l.MysqlConn.Where("module = ?", module) userInfo := gmodel.FsUserInfo{} if in.UserId > 0 { userInfoGorm.Where("user_id = ?", in.UserId) userInfo.UserId = &in.UserId } else { userInfoGorm.Where("guest_id = ?", in.GuestId) userInfo.GuestId = &in.GuestId } resFirst := userInfoGorm.First(&userInfo) err := resFirst.Error if err != nil { if err != gorm.ErrRecordNotFound { logc.Errorf(ctx, "FsUserInfo First err:%+v", err) return nil, err } } if userInfo.Id != 0 { tmp := string(*userInfo.Metadata) userInfoMetadata = &tmp } var userMaterialInfo gmodel.FsUserMaterial userMaterialModel := gmodel.NewFsUserMaterialModel(l.MysqlConn) if userInfo.Id == 0 { userMaterialInfo, err = userMaterialModel.FindLatestOne(ctx, in.UserId, in.GuestId) if err != gorm.ErrRecordNotFound { logc.Errorf(ctx, "FsUserMaterial FindLatestOne err:%+v", err) return nil, err } } else { if userInfo.Metadata != nil { var metadata map[string]interface{} err = json.Unmarshal([]byte(*userInfo.Metadata), &metadata) if err != nil { logc.Errorf(ctx, "userInfo.Metadata Unmarshal err:%+v", err) return nil, err } logoSelectedId, isEx := metadata["logo_selected_id"] if isEx { var materialId int64 = int64(logoSelectedId.(float64)) userMaterialInfos, err := userMaterialModel.FindOneById(ctx, materialId) if err != nil { if err != gorm.ErrRecordNotFound { logc.Errorf(ctx, "FsUserInfo First err:%+v", err) return nil, err } } if userMaterialInfos.Id != 0 { userMaterialInfo = *userMaterialInfos } } } } if userMaterialInfo.Id == 0 { userMaterialInfoDefault, err := userMaterialModel.FindOneById(ctx, 0) if err != nil { if err != gorm.ErrRecordNotFound { logc.Errorf(ctx, "userMaterialModel FindOneById defaul err:%+v", err) return nil, err } } metadataB := string(*userMaterialInfoDefault.Metadata) metadata = &metadataB logoUrl = userMaterialInfoDefault.ResourceUrl } else { metadataB := string(*userMaterialInfo.Metadata) metadata = &metadataB logoUrl = userMaterialInfo.ResourceUrl } return &LogoInfoRes{ Metadata: metadata, LogoUrl: logoUrl, UserInfoMetadata: userInfoMetadata, }, nil } /* 获取logo最新信息 */ /* logo信息 */ type ( LogoInfoSetReq struct { LogoUrl string `json:"logo_url"` } LogoInfoSetRes struct { Res string `json:"res"` } ) func (l *defaultImageHandle) LogoInfoSet(ctx context.Context, in *LogoInfoSetReq) (*LogoInfoSetRes, error) { var resultBLM constants.BLMServiceUrlResult postMap := make(map[string]string, 1) postMap["logo_url"] = in.LogoUrl logc.Infof(ctx, "算法请求--LOGO基础信息--开始时间:%v", time.Now().UTC()) err := curl.NewClient(ctx, &curl.Config{ BaseUrl: *l.BLMServiceUrl, Url: constants.BLMServiceUrlLogoFeatureExtraction, }).PostJson(postMap, &resultBLM) logc.Infof(ctx, "算法请求--LOGO基础信息--结束时间:%v", time.Now().UTC()) if err != nil { logx.Error(err) return nil, err } if resultBLM.Code != "200" { err = errors.New(resultBLM.Msg) logx.Error(err) return nil, err } return &LogoInfoSetRes{ Res: resultBLM.Data.(string), }, nil } /* logo信息 */ /* logo合图 */ type ( LogoCombineReq struct { UserId int64 `json:"user_id"` GuestId int64 `json:"guest_id"` TemplateId int64 `json:"template_id"` TemplateTag string `json:"template_tag"` Website string `json:"website"` // 合图参数 Slogan string `json:"slogan"` // 合图参数 Address string `json:"address"` // 合图参数 Phone string `json:"phone"` // 合图参数 Qrcode string `json:"qrcode"` // 合图参数 LogoUrl string `json:"logo_url"` // 合图参数 } LogoCombineRes struct { ResourceId string ResourceUrl *string Metadata *string DiffTimeLogoCombine int64 DiffTimeUploadFile int64 } ) func (l *defaultImageHandle) LogoCombine(ctx context.Context, in *LogoCombineReq) (*LogoCombineRes, error) { // 查询logo最新基础信息 resLogoInfo, err := l.LogoInfo(ctx, &LogoInfoReq{ UserId: in.UserId, GuestId: in.GuestId, }) if err != nil { logx.Error(err) return nil, err } // 根据hash 查询数据资源 var hashKeyData = *in hashKeyData.GuestId = 0 hashKeyData.UserId = 0 hashKeyData.LogoUrl = *resLogoInfo.LogoUrl var hashKeyDataMap map[string]interface{} hashKeyDataB, _ := json.Marshal(hashKeyData) json.Unmarshal(hashKeyDataB, &hashKeyDataMap) var resourceId string = hash.JsonHashKey(hashKeyDataMap) resourceModel := gmodel.NewFsResourceModel(l.MysqlConn) resourceInfo, err := resourceModel.FindOneById(ctx, resourceId) if err == nil && resourceInfo.ResourceId != "" { return &LogoCombineRes{ ResourceId: resourceId, ResourceUrl: resourceInfo.ResourceUrl, }, nil } else { if err != nil { if !errors.Is(err, gorm.ErrRecordNotFound) { logx.Error(err) return nil, err } } } // 没有查到,先根据模版id 查询模版数据 请求算法数据 productTemplateV2Model := gmodel.NewFsProductTemplateV2Model(l.MysqlConn) productTemplateV2Info, err := productTemplateV2Model.FindOne(ctx, in.TemplateId) if err != nil { logc.Errorf(ctx, "productTemplateV2Model.FindOne:%v", err) return nil, err } productTemplateTagInfo, err := gmodel.NewFsProductTemplateTagsModel(l.MysqlConn).FindOneByTagName(ctx, in.TemplateTag, "groups") if err != nil { logc.Errorf(ctx, "NewFsProductTemplateTagsModel.FindOneByTagName:%v", err) return nil, err } var groupOptions map[string]interface{} var materialList []interface{} if productTemplateV2Info.TemplateInfo != nil { var templateInfo map[string]interface{} err = json.Unmarshal([]byte(*productTemplateV2Info.TemplateInfo), &templateInfo) if err != nil { logx.Error(err) return nil, err } mapMaterialList, existMaterialList := templateInfo["materialList"] if !existMaterialList { err = errors.New("materialList is null") logc.Errorf(ctx, "materialList err:%v", err) return nil, err } materialList = mapMaterialList.([]interface{}) mapGroupOptions, existGroupOptions := templateInfo["groupOptions"] if !existGroupOptions { err = errors.New("groupOptions is null") logc.Errorf(ctx, "groupOptions err:%v", err) return nil, err } groupOptions = mapGroupOptions.(map[string]interface{}) } var moduleDataMap = make(map[string]interface{}, 4) moduleDataMap["id"] = productTemplateV2Info.Id moduleDataMap["material"] = productTemplateV2Info.MaterialImg moduleDataMap["groupOptions"] = groupOptions moduleDataMap["materialList"] = materialList var tagDataMap []interface{} err = json.Unmarshal([]byte(*productTemplateTagInfo.Groups), &tagDataMap) if err != nil { logc.Errorf(ctx, "Unmarshal tagDataMap:%v", err) return nil, err } var combineParam map[string]interface{} json.Unmarshal([]byte(*resLogoInfo.Metadata), &combineParam) combineParam["template_tagid"] = in.TemplateTag combineParam["website"] = in.Website combineParam["slogan"] = in.Slogan combineParam["phone"] = in.Phone combineParam["address"] = in.Address combineParam["qrcode"] = in.Qrcode var postMap = make(map[string]interface{}, 2) postMap["module_data"] = moduleDataMap postMap["tag_data"] = tagDataMap postMap["param_data"] = combineParam logc.Infof(ctx, "合图--算法请求--合图--开始时间:%v", time.Now().UTC()) var startTimeLogoCombine = time.Now().UnixMilli() //合图--处理--开始时间 var resultBLM constants.BLMServiceUrlResult err = curl.NewClient(ctx, &curl.Config{ BaseUrl: *l.BLMServiceUrl, Url: constants.BLMServiceUrlLogoCombine, }).PostJson(postMap, &resultBLM) logc.Infof(ctx, "合图--算法请求--合图--结束时间:%v", time.Now().UTC()) endTimeLogoCombine := time.Now().UnixMilli() //合图--处理--开始时间 diffTimeLogoCombine := endTimeLogoCombine - startTimeLogoCombine //合图--处理--中间差 logc.Infof(ctx, "合图--算法请求--合图--业务耗时:%d", diffTimeLogoCombine) if err != nil { logx.Error(err) return nil, err } if resultBLM.Code != "200" { err = errors.New(resultBLM.Msg) logx.Error(err) return nil, err } var resultStr string = resultBLM.Data.(string) var resultData map[string]interface{} err = json.Unmarshal([]byte(resultStr), &resultData) if err != nil || resultData == nil { logx.Error(err) return nil, err } var fileBase = resultData["result"].(string) // 上传文件 var upload = file.Upload{ Ctx: ctx, MysqlConn: l.MysqlConn, AwsSession: l.AwsSession, } logc.Infof(ctx, "合图--上传文件--开始时间:%v", time.Now().UTC()) var startTimeUploadFile = time.Now().UnixMilli() //合图--上传--开始时间 uploadRes, err := upload.UploadFileByBase64(&file.UploadBaseReq{ Source: "combine-image", FileHash: resourceId, FileData: fileBase, UploadBucket: 1, ApiType: 2, UserId: in.UserId, GuestId: in.GuestId, }) logc.Infof(ctx, "合图--上传文件--结束时间:%v", time.Now().UTC()) endTimeUploadFile := time.Now().UnixMilli() //合图--处理--开始时间 diffTimeUploadFile := endTimeUploadFile - startTimeUploadFile //合图--处理--中间差 logc.Infof(ctx, "合图--上传文件--业务耗时:%d", diffTimeUploadFile) if err != nil { logx.Error(err) return nil, err } return &LogoCombineRes{ ResourceId: uploadRes.ResourceId, ResourceUrl: &uploadRes.ResourceUrl, DiffTimeLogoCombine: diffTimeLogoCombine, DiffTimeUploadFile: diffTimeUploadFile, }, nil } /* logo合图 */ type ( LogoStandardReq struct { IsRemoveBg string `json:"is_remove_bg"` LogoFile string `json:"logo_file"` Width string `json:"width"` Height string `json:"height"` Proportion string `json:"proportion"` } LogoStandardRes struct { ResourceId string ResourceUrl string IsmaxProportion bool ImgColor []string } LogoStandardMetaData struct { Param LogoStandardReq `json:"param"` Result LogoStandardRes `json:"result"` } ) /* 图片裁剪 */ func (l *defaultImageHandle) LogoStandard(ctx context.Context, in *LogoStandardReq) (*LogoStandardRes, error) { var ismaxProportion bool var imgColor []string var logoStandardMetaData LogoStandardMetaData var hashKeyDataMap map[string]interface{} hashKeyDataB, _ := json.Marshal(in) json.Unmarshal(hashKeyDataB, &hashKeyDataMap) var resourceId string = hash.JsonHashKey(hashKeyDataMap) resourceModel := gmodel.NewFsResourceModel(l.MysqlConn) resourceInfo, err := resourceModel.FindOneById(ctx, resourceId) if err == nil && resourceInfo.ResourceId != "" { if resourceInfo.Metadata != nil { json.Unmarshal([]byte(*resourceInfo.Metadata), &logoStandardMetaData) } // 取出参数 ismaxProportion = logoStandardMetaData.Result.IsmaxProportion imgColor = logoStandardMetaData.Result.ImgColor return &LogoStandardRes{ ResourceId: resourceInfo.ResourceId, ResourceUrl: *resourceInfo.ResourceUrl, IsmaxProportion: ismaxProportion, ImgColor: imgColor, }, nil } else { if err != nil { if !errors.Is(err, gorm.ErrRecordNotFound) { logx.Error(err) return nil, err } } } var resultBLM constants.BLMServiceUrlResult var postMap = make(map[string]interface{}, 5) postMap["is_remove_bg"] = in.IsRemoveBg postMap["logo_file"] = in.LogoFile postMap["width"] = in.Width postMap["height"] = in.Height postMap["proportion"] = in.Proportion logc.Infof(ctx, "算法请求--去背景--开始时间:%v", time.Now().UTC()) err = curl.NewClient(ctx, &curl.Config{ BaseUrl: *l.BLMServiceUrl, Url: constants.BLMServiceUrlLogoRemovebg, }).PostJson(postMap, &resultBLM) logc.Infof(ctx, "算法请求--去背景--结束时间:%v", time.Now().UTC()) if err != nil { logx.Error(err) return nil, err } if resultBLM.Code != "200" { err = errors.New(resultBLM.Msg) logx.Error(err) return nil, err } var resultStr string = resultBLM.Data.(string) var resultData map[string]interface{} err = json.Unmarshal([]byte(resultStr), &resultData) if err != nil || resultData == nil { logx.Error(err) return nil, err } var fileBase = resultData["nobg_url"].(string) ismaxProportion = resultData["ismax_proportion"].(bool) for _, v := range resultData["img_color"].([]interface{}) { imgColor = append(imgColor, v.(string)) } var logoStandardRes LogoStandardRes logoStandardRes.IsmaxProportion = ismaxProportion logoStandardRes.ImgColor = imgColor logoStandardMetaData.Param = *in logoStandardMetaData.Result = logoStandardRes metadataB, err := json.Marshal(logoStandardMetaData) if err != nil { logx.Error(err) return nil, err } var metadata = string(metadataB) // 上传文件 var upload = file.Upload{ Ctx: ctx, MysqlConn: l.MysqlConn, AwsSession: l.AwsSession, } uploadRes, err := upload.UploadFileByBase64(&file.UploadBaseReq{ Source: "combine-removebg", FileHash: resourceId, FileData: fileBase, UploadBucket: 1, ApiType: 2, Metadata: metadata, }) if err != nil { logx.Error(err) return nil, err } return &LogoStandardRes{ ResourceId: uploadRes.ResourceId, ResourceUrl: uploadRes.ResourceUrl, IsmaxProportion: ismaxProportion, ImgColor: imgColor, }, nil } /* 图片裁剪 */