diff --git a/business/jxstore/cms/cms.go b/business/jxstore/cms/cms.go index 218ddb956..e9669e1a7 100644 --- a/business/jxstore/cms/cms.go +++ b/business/jxstore/cms/cms.go @@ -18,19 +18,14 @@ import ( "git.rosy.net.cn/jx-callback/business/partner" "git.rosy.net.cn/baseapi/utils" - "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" - "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" - "github.com/qiniu/api.v7/storage" ) const ( - qiniuTokenExpires = 300 // 七牛TOKEN有效时间,5分钟 - SendMsgTypeOpenStoreRequest = "openStoreRequest" ) @@ -51,14 +46,6 @@ var ( } ) -type UploadResTokenInfo struct { - Token string `json:"token,omitempty"` - Expires uint64 `json:"expires,omitempty"` - FileName string `json:"fileName,omitempty"` - Hit bool `json:"hit,omitempty"` - Img string `json:"img,omitempty"` -} - func InitServiceInfo(version string, buildTime time.Time, gitCommit string) { buildTimeStr := "" if !utils.IsTimeZero(buildTime) { @@ -108,71 +95,6 @@ func GetServiceInfo(ctx *jxcontext.Context) interface{} { return serviceInfo } -func GetQiniuUploadToken(ctx *jxcontext.Context, suffix, hashCode string) (upTokenInfo *UploadResTokenInfo, err error) { - imgURL := "" - if hashCode != "" { - imgURL, _ = GetDataResource(ctx, hashCode) - } - - putPolicy := storage.PutPolicy{ - Scope: globals.QiniuBucket, - Expires: qiniuTokenExpires, - } - upTokenInfo = &UploadResTokenInfo{ - Token: putPolicy.UploadToken(api.QiniuAPI), - Expires: putPolicy.Expires, - FileName: jxutils.GenPicFileName(suffix), - Hit: imgURL != "", - Img: imgURL, - } - return upTokenInfo, err -} - -func RegisterDataResource(ctx *jxcontext.Context, name, resourceURL, mimeType, hashCode string) (dataRes *model.DataResource, err error) { - if model.ValideMimeTypes[mimeType] == 0 { - return nil, fmt.Errorf("MIME type:%s非法", mimeType) - } - dataRes = &model.DataResource{ - Name: name, - HashCode: hashCode, - ResoureType: mimeType, - MainURL: resourceURL, - } - vendorID := jxutils.GuessDataResourceVendor(resourceURL) - switch vendorID { - case model.VendorIDQiNiuCloud: - dataRes.QiniuURL = resourceURL - case model.VendorIDEBAI: - dataRes.EbaiURL = resourceURL - case model.VendorIDMTWM: - dataRes.MtwmURL = resourceURL - } - - dao.WrapAddIDCULEntity(dataRes, ctx.GetUserName()) - if err = dao.CreateEntity(dao.GetDB(), dataRes); err != nil { - dataRes = nil - } - return dataRes, err -} - -func GetDataResource(ctx *jxcontext.Context, hashCode string) (resourceURL string, err error) { - db := dao.GetDB() - dataRes, err := dao.GetDataResource(db, hashCode, "") - if err != nil { - if dao.IsNoRowsError(err) { - skuName, err2 := dao.GetSkuNameByHashCode(db, hashCode) - if err = err2; err == nil { - resourceURL = skuName.Img - } else if dao.IsNoRowsError(err) { - err = nil - } - } - } else { - resourceURL = dataRes.MainURL - } - return resourceURL, err -} - func GetPlaces(ctx *jxcontext.Context, keyword string, includeDisabled bool, params map[string]interface{}) ([]*model.Place, error) { sql := ` SELECT * diff --git a/business/jxstore/cms/cms_test.go b/business/jxstore/cms/cms_test.go index c874fdc6f..1fc84a4f7 100644 --- a/business/jxstore/cms/cms_test.go +++ b/business/jxstore/cms/cms_test.go @@ -1,11 +1,6 @@ package cms import ( - "fmt" - "testing" - - "git.rosy.net.cn/baseapi/utils" - "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/jx-callback/globals/api2" "git.rosy.net.cn/jx-callback/globals/testinit" @@ -20,19 +15,3 @@ func init() { testinit.Init() api2.Init() } - -func TestGetQiniuUploadToken(t *testing.T) { - token, err := GetQiniuUploadToken(jxcontext.AdminCtx, "", "") - if err != nil { - t.Fatal(err) - } - fmt.Print(token) -} - -func TestGetDataResource(t *testing.T) { - dataRes, err := GetDataResource(jxcontext.AdminCtx, "1D3E4A8259F359FB4CF47D541843950D") - if err != nil { - t.Fatal(err) - } - t.Log(utils.Format4Output(dataRes, false)) -} diff --git a/business/jxstore/cms/sku.go b/business/jxstore/cms/sku.go index d06080696..f5219ff81 100644 --- a/business/jxstore/cms/sku.go +++ b/business/jxstore/cms/sku.go @@ -9,8 +9,8 @@ import ( "git.rosy.net.cn/baseapi/platformapi/ebaiapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/jxutils/datares" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" - "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/business/partner" @@ -569,21 +569,29 @@ func AddSkuName(ctx *jxcontext.Context, skuNameExt *model.SkuNameExt, userName s } if globals.EnableStoreWrite { - imgContent, imgMD5, err := jxutils.DownloadFileByURL(skuNameExt.Img) - if err != nil { + // imgContent, imgMD5, err := jxutils.DownloadFileByURL(skuNameExt.Img) + // if err != nil { + // return nil, err + // } + // if skuNameExt.ImgHashCode == "" { + // skuNameExt.ImgHashCode = imgMD5 + // } else if skuNameExt.ImgHashCode != imgMD5 { + // return nil, errors.New("图片HASH值不同") + // } + // imgHintMap, err := UploadImg2Platforms(ctx, nil, skuNameExt.Img, imgContent, "") + // if err != nil { + // return nil, err + // } + // skuNameExt.ImgEbai = imgHintMap[model.VendorIDEBAI] + dataRes, err2 := datares.TryRegisterDataResource(ctx, skuNameExt.Name, skuNameExt.Img, true, true, false) + if err = err2; err != nil { return nil, err } - if skuNameExt.ImgHashCode == "" { - skuNameExt.ImgHashCode = imgMD5 - } else if skuNameExt.ImgHashCode != imgMD5 { - return nil, errors.New("图片HASH值不同") + skuNameExt.ImgHashCode = dataRes.HashCode + skuNameExt.ImgEbai = dataRes.EbaiURL + if skuNameExt.Img2 != "" { + datares.TryRegisterDataResource(ctx, skuNameExt.Name, skuNameExt.Img2, true, true, true) } - imgHintMap, err := UploadImg2Platforms(ctx, nil, skuNameExt.Img, imgContent, "") - if err != nil { - return nil, err - } - // skuNameExt.ImgWeimob = imgHintMap[model.VendorIDWSC] - skuNameExt.ImgEbai = imgHintMap[model.VendorIDEBAI] if skuNameExt.DescImg != "" && getAndSetEbaiUploadRTFShopID() != "" { skuNameExt.DescImgEbai, err = api.EbaiAPI.SkuUploadRTF(getAndSetEbaiUploadRTFShopID(), ebaiapi.BuildRFTFromImgs(skuNameExt.DescImg)) @@ -664,8 +672,6 @@ func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interf _, hasPlaces := payload["places"] if len(valid) > 0 || hasPlaces { globals.SugarLogger.Debugf("UpdateSkuName valid:%s", utils.Format4Output(valid, false)) - dao.Begin(db) - defer dao.Rollback(db) if upc, _ := valid["upc"].(string); upc != "" { skuName := &model.SkuName{ Upc: upc, @@ -680,26 +686,34 @@ func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interf } if globals.EnableStoreWrite { if valid["img"] != nil { - imgContent, imgMD5, err2 := jxutils.DownloadFileByURL(valid["img"].(string)) + // imgContent, imgMD5, err2 := jxutils.DownloadFileByURL(valid["img"].(string)) + // if err = err2; err != nil { + // return 0, err + // } + // valid["ImgHashCode"] = imgMD5 + // imgHintMap, err := UploadImg2Platforms(ctx, nil, valid["img"].(string), imgContent, "") + // if err != nil { + // return 0, err + // } + // // valid["ImgWeimob"] = imgHintMap[model.VendorIDWSC] + // valid["ImgEbai"] = imgHintMap[model.VendorIDEBAI] + dataRes, err2 := datares.TryRegisterDataResource(ctx, skuName.Name, valid["img"].(string), true, true, false) if err = err2; err != nil { return 0, err } - valid["ImgHashCode"] = imgMD5 - imgHintMap, err := UploadImg2Platforms(ctx, nil, valid["img"].(string), imgContent, "") - if err != nil { - dao.Rollback(db) - return 0, err - } - // valid["ImgWeimob"] = imgHintMap[model.VendorIDWSC] - valid["ImgEbai"] = imgHintMap[model.VendorIDEBAI] + valid["ImgHashCode"] = dataRes.HashCode + valid["ImgEbai"] = dataRes.EbaiURL } + if valid["img2"] != nil { + datares.TryRegisterDataResource(ctx, skuName.Name, valid["img2"].(string), true, true, true) + } + if valid["descImg"] != nil { descImg := valid["descImg"].(string) if descImg != "" { if getAndSetEbaiUploadRTFShopID() != "" { valid["descImgEbai"], err = api.EbaiAPI.SkuUploadRTF(getAndSetEbaiUploadRTFShopID(), ebaiapi.BuildRFTFromImgs(descImg)) if err != nil { - dao.Rollback(db) return 0, err } } @@ -708,6 +722,13 @@ func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interf } } } + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() if num, err = dao.UpdateEntityLogicallyAndUpdateSyncStatus(db, skuName, valid, userName, nil, model.FieldJdSyncStatus, model.SyncFlagModifiedMask); err == nil && num == 1 { if utils.Interface2Int64WithDefault(payload["isGlobal"], 0) == 0 && payload["places"] != nil { if places, ok := payload["places"].([]interface{}); ok { @@ -720,6 +741,7 @@ func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interf placeBind.NameID = nameID err = dao.CreateEntity(db, placeBind) } else { + dao.Rollback(db) return 0, errors.New("地点代码非法") } } @@ -736,12 +758,14 @@ func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interf if err = err2; err == nil && len(skuIDs) > 0 { _, err = SetStoreSkuSyncStatus2(db, nil, partner.GetSingleStoreVendorIDs(), skuIDs, model.SyncFlagModifiedMask) } - if err == nil { - dao.Commit(db) - _, err = CurVendorSync.SyncSku(ctx, db, nameID, -1, false, false, userName) - } } } + if err == nil { + dao.Commit(db) + _, err = CurVendorSync.SyncSku(ctx, db, nameID, -1, false, false, userName) + } else { + dao.Rollback(db) + } } } return num, err @@ -1013,35 +1037,6 @@ func GetVendorSku(ctx *jxcontext.Context, vendorID int, vendorSkuID string) (sku return nil, ErrCanNotFindVendor } -func UploadImg2Platforms(ctx *jxcontext.Context, parentTask tasksch.ITask, imgURL string, imgData []byte, imgName string) (imgHintMap map[int]string, err error) { - task := tasksch.NewParallelTask("UploadImg2Platforms", nil, ctx, - func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - vendorID := batchItemList[0].(int) - if handler := partner.GetPurchasePlatformFromVendorID(vendorID); handler != nil { - imgHint, err2 := handler.UploadImg(ctx, imgURL, imgData, imgName) - if err = err2; err == nil { - return [][]interface{}{ - []interface{}{ - vendorID, - imgHint, - }, - }, nil - } - } - return nil, err - }, []int{model.VendorIDEBAI}) - tasksch.HandleTask(task, parentTask, false).Run() - resultList, err := task.GetResult(0) - if err == nil { - imgHintMap = make(map[int]string) - for _, v := range resultList { - vList := v.([]interface{}) - imgHintMap[vList[0].(int)] = vList[1].(string) - } - } - return imgHintMap, err -} - func SortCategorySkus(ctx *jxcontext.Context, catID int, skuIDList []int) (err error) { db := dao.GetDB() userName := ctx.GetUserName() diff --git a/business/jxstore/initdata/initdata.go b/business/jxstore/initdata/initdata.go index 3df00a301..f3dc5accc 100644 --- a/business/jxstore/initdata/initdata.go +++ b/business/jxstore/initdata/initdata.go @@ -15,6 +15,7 @@ import ( "git.rosy.net.cn/baseapi/platformapi/jdapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/jxutils/datares" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" "git.rosy.net.cn/jx-callback/business/model" @@ -340,6 +341,26 @@ func UploadEbaiImg4SkuName(ctx *jxcontext.Context, nameIDs []int, isAsync, isCon return hint, err } +func UploadImg4Vendors(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (hint string, err error) { + dataResList, err := dao.GetNeedUploadDataResource(dao.GetDB()) + if err != nil { + return "", err + } + rootTask := tasksch.NewParallelTask("UploadImg4Vendors", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError).SetParallelCount(5), ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + dataRes := batchItemList[0].(*model.DataResource) + _, err = datares.UploadImage2Vendors(ctx, task, dataRes, nil, false) + return nil, err + }, dataResList) + tasksch.ManageTask(rootTask).Run() + if !isAsync { + _, err = rootTask.GetResult(0) + } else { + hint = rootTask.ID + } + return hint, err +} + func getSkuNameKey(prefix, name, comment, specUnit, unit string, specQuality float32) string { return fmt.Sprintf("%s-%s-%f-%s-%s", prefix, name, specQuality, specUnit, unit) } diff --git a/business/jxutils/datares/datares.go b/business/jxutils/datares/datares.go new file mode 100644 index 000000000..fb64baafe --- /dev/null +++ b/business/jxutils/datares/datares.go @@ -0,0 +1,265 @@ +package datares + +import ( + "fmt" + "strings" + "time" + + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/model/dao" + "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/globals" + "git.rosy.net.cn/jx-callback/globals/api" + "github.com/qiniu/api.v7/storage" +) + +const ( + qiniuTokenExpires = 300 // 七牛TOKEN有效时间,5分钟 + dataResCacheTimeout = 24 * time.Hour +) + +var ( + dataResCache jxutils.SyncMapWithTimeout +) + +type UploadResTokenInfo struct { + Token string `json:"token,omitempty"` + Expires uint64 `json:"expires,omitempty"` + FileName string `json:"fileName,omitempty"` + Hit bool `json:"hit,omitempty"` + Img string `json:"img,omitempty"` +} + +func GetQiniuUploadToken(ctx *jxcontext.Context, suffix, hashCode string) (upTokenInfo *UploadResTokenInfo, err error) { + imgURL := "" + if hashCode != "" { + imgURL, _ = GetDataResource(ctx, hashCode) + } + + putPolicy := storage.PutPolicy{ + Scope: globals.QiniuBucket, + Expires: qiniuTokenExpires, + } + upTokenInfo = &UploadResTokenInfo{ + Token: putPolicy.UploadToken(api.QiniuAPI), + Expires: putPolicy.Expires, + FileName: jxutils.GenPicFileName(suffix), + Hit: imgURL != "", + Img: imgURL, + } + dataResCache.StoreWithTimeout(imgURL, hashCode, dataResCacheTimeout) + return upTokenInfo, err +} + +func suffix2MimeType(suffix string) (mimeType string) { + suffix = strings.Trim(suffix, ". ") + for k, v := range model.ValidMimeTypes { + for _, v2 := range v { + if v2 == suffix { + mimeType = k + break + } + } + } + return mimeType +} + +func getMimeTypeFromURL(resourceURL string) (mimeType string) { + index := strings.LastIndex(resourceURL, ".") + if index >= 0 { + mimeType = suffix2MimeType(resourceURL[index:]) + } + return mimeType +} + +func RegisterDataResource(ctx *jxcontext.Context, name, resourceURL, mimeType, hashCode string, resBinary []byte, isUpload2Vendor, isAsync bool) (dataRes *model.DataResource, err error) { + if model.ValidMimeTypes[mimeType] == nil { + return nil, fmt.Errorf("MIME type:%s非法", mimeType) + } + dataRes = &model.DataResource{ + Name: name, + HashCode: hashCode, + ResoureType: mimeType, + MainURL: resourceURL, + IsVendor: int8(utils.Bool2Int(isUpload2Vendor)), + } + + vendorID := jxutils.GuessDataResourceVendor(resourceURL) + switch vendorID { + case model.VendorIDQiNiuCloud: + dataRes.QiniuURL = resourceURL + case model.VendorIDEBAI: + dataRes.EbaiURL = resourceURL + } + + dao.WrapAddIDCULEntity(dataRes, ctx.GetUserName()) + if err = dao.CreateEntity(dao.GetDB(), dataRes); err != nil { + if dao.IsDuplicateError(err) { + dataRes, err = dao.GetDataResource(dao.GetDB(), dataRes.HashCode, dataRes.MainURL) + } else { + dataRes = nil + } + return dataRes, err + } + if isUpload2Vendor { + // 忽略上传错误 + UploadImage2Vendors(ctx, nil, dataRes, resBinary, isAsync) + } + return dataRes, err +} + +func TryRegisterDataResource(ctx *jxcontext.Context, name, resourceURL string, isAllowDownLoad, isUpload2Vendor, isAsync bool) (dataRes *model.DataResource, err error) { + dataRes = &model.DataResource{ + MainURL: resourceURL, + } + db := dao.GetDB() + err = dao.GetEntity(db, dataRes, "MainURL") + if err != nil { + if !dao.IsNoRowsError(err) { + return nil, err + } + } else { + return dataRes, nil + } + value, ok := dataResCache.Load(resourceURL) + var hashCode string + var resBinary []byte + if !ok { + if !isAllowDownLoad { + return nil, nil + } + if resBinary, hashCode, err = jxutils.DownloadFileByURL(resourceURL); err != nil { + return nil, err + } + } else { + hashCode = value.(string) + } + return RegisterDataResource(ctx, name, resourceURL, getMimeTypeFromURL(resourceURL), hashCode, resBinary, isUpload2Vendor, isAsync) +} + +func GetDataResource(ctx *jxcontext.Context, hashCode string) (resourceURL string, err error) { + db := dao.GetDB() + dataRes, err := dao.GetDataResource(db, hashCode, "") + if err != nil { + if dao.IsNoRowsError(err) { + skuName, err2 := dao.GetSkuNameByHashCode(db, hashCode) + if err = err2; err == nil { + resourceURL = skuName.Img + } else if dao.IsNoRowsError(err) { + err = nil + } + } + } else { + resourceURL = dataRes.MainURL + } + return resourceURL, err +} + +// 这个函数,可能部分平台成功,部分失败 +func UploadImage2Vendors(ctx *jxcontext.Context, parentTask tasksch.ITask, dataRes *model.DataResource, imgData []byte, isAsync bool) (hint string, err error) { + var vendorIDs []int + if dataRes.EbaiURL == "" { + vendorIDs = append(vendorIDs, model.VendorIDEBAI) + } + if dataRes.MtwmURL == "" { + vendorIDs = append(vendorIDs, model.VendorIDMTWM) + } + if len(vendorIDs) > 0 { + imgName := jxutils.GetShortNameFromURL(dataRes.MainURL) + task := tasksch.NewParallelTask(fmt.Sprintf("UploadImage2Vendors:%s,%s", dataRes.Name, dataRes.MainURL), nil, ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + step := batchItemList[0].(int) + switch step { + case 0: + if imgData == nil { + if imgData, _, err = jxutils.DownloadFileByURL(dataRes.MainURL); err != nil { + return "", err + } + } + case 1: + uploadTask := tasksch.NewParallelTask(fmt.Sprintf("UploadImage2Vendors:%s,%s Upload", dataRes.Name, dataRes.MainURL), + tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + vendorID := batchItemList[0].(int) + if handler := partner.GetPurchasePlatformFromVendorID(vendorID); handler != nil { + imgHint, err2 := handler.UploadImg(ctx, dataRes.MainURL, imgData, imgName) + if err = err2; err == nil { + retVal = [][]interface{}{ + []interface{}{ + vendorID, + imgHint, + }, + } + } + } + return retVal, err + }, vendorIDs) + tasksch.HandleTask(uploadTask, task, false).Run() + resultList, err2 := uploadTask.GetResult(0) + err = err2 + if len(resultList) > 0 { + db := dao.GetDB() + for _, v := range resultList { + result := v.([]interface{}) + vendorID := result[0].(int) + imgHint := result[1].(string) + updateField := "" + if vendorID == model.VendorIDEBAI { + dataRes.EbaiURL = imgHint + updateField = "EbaiURL" + } else if vendorID == model.VendorIDMTWM { + dataRes.MtwmURL = imgHint + updateField = "MtwmURL" + } + dao.UpdateEntity(db, dataRes, updateField) + } + retVal = resultList + } + } + return retVal, err + }, []int{0, 1}) + tasksch.HandleTask(task, parentTask, false).Run() + if !isAsync { + resultList, err2 := task.GetResult(0) + if err = err2; err == nil { + hint = utils.Int2Str(len(resultList)) + } + } else { + hint = task.GetID() + } + } + return hint, err +} + +// func UploadImg2Platforms(ctx *jxcontext.Context, parentTask tasksch.ITask, imgURL string, imgData []byte, imgName string) (imgHintMap map[int]string, err error) { +// task := tasksch.NewParallelTask("UploadImg2Platforms", nil, ctx, +// func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { +// vendorID := batchItemList[0].(int) +// if handler := partner.GetPurchasePlatformFromVendorID(vendorID); handler != nil { +// imgHint, err2 := handler.UploadImg(ctx, imgURL, imgData, imgName) +// if err = err2; err == nil { +// return [][]interface{}{ +// []interface{}{ +// vendorID, +// imgHint, +// }, +// }, nil +// } +// } +// return nil, err +// }, []int{model.VendorIDEBAI}) +// tasksch.HandleTask(task, parentTask, false).Run() +// resultList, err := task.GetResult(0) +// if err == nil { +// imgHintMap = make(map[int]string) +// for _, v := range resultList { +// vList := v.([]interface{}) +// imgHintMap[vList[0].(int)] = vList[1].(string) +// } +// } +// return imgHintMap, err +// } diff --git a/business/jxutils/datares/datares_test.go b/business/jxutils/datares/datares_test.go new file mode 100644 index 000000000..563c495c1 --- /dev/null +++ b/business/jxutils/datares/datares_test.go @@ -0,0 +1,44 @@ +package datares + +import ( + "fmt" + "testing" + + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/globals/api2" + "git.rosy.net.cn/jx-callback/globals/testinit" + + _ "git.rosy.net.cn/jx-callback/business/partner/purchase/ebai" + _ "git.rosy.net.cn/jx-callback/business/partner/purchase/jd" + _ "git.rosy.net.cn/jx-callback/business/partner/purchase/mtwm" +) + +func init() { + testinit.Init() + api2.Init() +} + +func TestGetQiniuUploadToken(t *testing.T) { + token, err := GetQiniuUploadToken(jxcontext.AdminCtx, "", "") + if err != nil { + t.Fatal(err) + } + fmt.Print(token) +} + +func TestGetDataResource(t *testing.T) { + dataRes, err := GetDataResource(jxcontext.AdminCtx, "1D3E4A8259F359FB4CF47D541843950D") + if err != nil { + t.Fatal(err) + } + t.Log(utils.Format4Output(dataRes, false)) +} + +func TestTryRegisterDataResource(t *testing.T) { + dataRes, err := TryRegisterDataResource(jxcontext.AdminCtx, "test", "http://image.jxc4.com/image/8552261fb928be10f6406b13dc29570e.jpg", true, true, false) + if err != nil { + t.Fatal(err) + } + t.Log(utils.Format4Output(dataRes, false)) +} diff --git a/business/jxutils/jxutils.go b/business/jxutils/jxutils.go index 414a90ead..f0f13a41e 100644 --- a/business/jxutils/jxutils.go +++ b/business/jxutils/jxutils.go @@ -35,9 +35,6 @@ var ( model.VendorIDJD: []string{ "img30.360buyimg.com", }, - model.VendorIDMTWM: []string{ - "", - }, model.VendorIDEBAI: []string{ "image-star.elemecdn.com", }, @@ -734,3 +731,11 @@ func BatchString2Slice(strs ...string) (strList []string) { } return strList } + +func GetShortNameFromURL(strURL string) (shortName string) { + index := strings.LastIndex(strURL, "/") + if index > 0 { + shortName = strURL[index+1:] + } + return shortName +} diff --git a/business/model/common.go b/business/model/common.go index 63430f605..c3c26db93 100644 --- a/business/model/common.go +++ b/business/model/common.go @@ -1,12 +1,13 @@ package model var ( - ValideMimeTypes = map[string]int{ - "image/jpeg": 1, - "image/png": 1, + ValidMimeTypes = map[string][]string{ + "image/jpeg": []string{"jpeg", "jpg"}, + "image/png": []string{"png"}, + "image/gif": []string{"gif"}, - "video/mpeg": 1, - "video/mp4": 1, + "video/mpeg": []string{"mpeg", "mpg"}, + "video/mp4": []string{"mp4", "m4v"}, } ) @@ -17,6 +18,7 @@ type DataResource struct { ResoureType string `orm:"size(48)" json:"resoureType"` // 资料的mime type Name string `orm:"size(48);index" json:"name"` + IsVendor int8 `json:"isVendor"` // 是否是平台需要的(平台需要才会上传到平台) MainURL string `orm:"size(512);column(main_url);unique" json:"mainURL"` QiniuURL string `orm:"size(512);column(qiniu_url);index" json:"qiniuURL"` diff --git a/business/model/dao/common.go b/business/model/dao/common.go index 6c01fdadb..579ee9eb1 100644 --- a/business/model/dao/common.go +++ b/business/model/dao/common.go @@ -8,16 +8,25 @@ func GetDataResource(db *DaoDB, hashCode, fullURL string) (dataRes *model.DataRe sql := ` SELECT t1.* FROM data_resource t1 - WHERE 1 = 1` + WHERE 0 = 1` sqlParams := []interface{}{} if hashCode != "" { - sql += " AND t1.hash_code = ?" + sql += " OR t1.hash_code = ?" sqlParams = append(sqlParams, hashCode) } if fullURL != "" { - sql += " AND (t1.main_url = ? OR t1.qiniu_url = ? OR t1.ebai_url = ? OR t1.mtwm_url = ?)" + sql += " OR t1.main_url = ? OR t1.qiniu_url = ? OR t1.ebai_url = ? OR t1.mtwm_url = ?" sqlParams = append(sqlParams, fullURL, fullURL, fullURL, fullURL) } err = GetRow(db, &dataRes, sql, sqlParams...) return dataRes, err } + +func GetNeedUploadDataResource(db *DaoDB) (dataRes *model.DataResource, err error) { + sql := ` + SELECT t1.* + FROM data_resource t1 + WHERE t1.is_vendor = 1 AND (t1.ebai_url = '' OR t1.mtwm_url = '')` + err = GetRow(db, &dataRes, sql) + return dataRes, err +} diff --git a/business/partner/purchase/ebai/ebai.go b/business/partner/purchase/ebai/ebai.go index 022f9946a..779020e8f 100644 --- a/business/partner/purchase/ebai/ebai.go +++ b/business/partner/purchase/ebai/ebai.go @@ -45,8 +45,11 @@ func (p *PurchaseHandler) GetVendorID() int { } func (p *PurchaseHandler) UploadImg(ctx *jxcontext.Context, imgURL string, imgData []byte, imgName string) (imgHint string, err error) { + globals.SugarLogger.Debugf("ebai UploadImg imgURL:%s, imgName:%s", imgURL, imgName) if globals.EnableEbaiStoreWrite { imgHint, err = api.EbaiAPI.PictureUpload(imgURL, imgData) + } else { + imgHint = imgURL + ".ebai" } return imgHint, err } diff --git a/business/partner/purchase/mtwm/mtwm.go b/business/partner/purchase/mtwm/mtwm.go index 7f2a99956..1854d5c57 100644 --- a/business/partner/purchase/mtwm/mtwm.go +++ b/business/partner/purchase/mtwm/mtwm.go @@ -3,6 +3,7 @@ package mtwm import ( "fmt" "strings" + "sync" "git.rosy.net.cn/baseapi/platformapi/mtwmapi" "git.rosy.net.cn/baseapi/utils" @@ -11,6 +12,7 @@ import ( "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/partner" "git.rosy.net.cn/jx-callback/business/partner/putils" + "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" ) @@ -21,6 +23,9 @@ var ( type PurchaseHandler struct { partner.BasePurchasePlatform putils.DefSingleStorePlatform + + poiCode4UploadImg string + locker sync.RWMutex } func init() { @@ -162,5 +167,43 @@ func skuStatusJX2Mtwm(status int) int { } func (p *PurchaseHandler) UploadImg(ctx *jxcontext.Context, imgURL string, imgData []byte, imgName string) (imgHint string, err error) { + globals.SugarLogger.Debugf("mtwm UploadImg imgURL:%s, imgName:%s", imgURL, imgName) + poiCode4UploadImg := p.getUploadImgPoiCode() + if poiCode4UploadImg == "" { + return "", fmt.Errorf("找不到一个美团门店来上传图片") + } + if globals.EnableMtwmStoreWrite { + if imgData != nil { + imgHint, err = api.MtwmAPI.ImageUpload(poiCode4UploadImg, imgName, imgData) + } else { + imgHint, err = api.MtwmAPI.ImageUploadByURL(poiCode4UploadImg, imgName, imgURL) + } + } else { + imgHint = utils.GetUpperUUID() + } return imgHint, err } + +func (p *PurchaseHandler) getUploadImgPoiCode() (poiCode string) { + p.locker.RLock() + poiCode = p.poiCode4UploadImg + p.locker.RUnlock() + if poiCode != "" { + return poiCode + } + + p.locker.Lock() + poiCode = p.poiCode4UploadImg + if poiCode != "" { + p.locker.Unlock() + return poiCode + } + + defer p.locker.Unlock() + storeIDs, err := api.MtwmAPI.PoiGetIDs() + if err == nil && len(storeIDs) > 0 { + poiCode = storeIDs[0] + } + p.poiCode4UploadImg = poiCode + return poiCode +} diff --git a/business/userstore/food_recipe.go b/business/userstore/food_recipe.go index 1f7218922..7291d4ab8 100644 --- a/business/userstore/food_recipe.go +++ b/business/userstore/food_recipe.go @@ -3,8 +3,11 @@ package userstore import ( "fmt" + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/baseapi/utils/errlist" "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/jxutils/datares" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" @@ -112,8 +115,9 @@ func CreateFoodRecipe(ctx *jxcontext.Context, foodRecipe *model.FoodRecipe, item if err = updateFoodRecipeItemAndStep(ctx, db, foodRecipe.ID, itemList, stepList); err != nil { return err } - dao.Commit(db) + + tryRegisterDataRes4Recipe(ctx, foodRecipe.Name, foodRecipe.Img, stepList) return err } @@ -170,9 +174,28 @@ func UpdateFoodRecipe(ctx *jxcontext.Context, recipeID int, mapData map[string]i } dao.Commit(db) + tryRegisterDataRes4Recipe(ctx, localRecipe.Name, utils.Interface2String(valid["img"]), stepList) return err } +func tryRegisterDataRes4Recipe(ctx *jxcontext.Context, name, mainImg string, stepList []*FoodRecipeStepParam) (err error) { + imgList := []string{} + if mainImg != "" { + imgList = append(imgList, mainImg) + } + for _, v := range stepList { + if v.Img != "" { + imgList = append(imgList, v.Img) + } + } + errList := errlist.New() + for _, v := range imgList { + _, err := datares.TryRegisterDataResource(ctx, name, v, true, false, true) + errList.AddErr(err) + } + return errList.GetErrListAsOne() +} + func QueryFoodRecipes(ctx *jxcontext.Context, keyword, authorID string, offset, pageSize int) (recipeInfo *model.PagedInfo, err error) { _, userID := ctx.GetMobileAndUserID() recipeList, totalCount, err := dao.QueryFoodRecipes(dao.GetDB(), keyword, 0, authorID, userID, offset, pageSize) diff --git a/controllers/cms.go b/controllers/cms.go index 94dcd24dd..ef306edc5 100644 --- a/controllers/cms.go +++ b/controllers/cms.go @@ -6,6 +6,7 @@ import ( "git.rosy.net.cn/jx-callback/business/jxstore/cms" "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/jxutils/configindb" + "git.rosy.net.cn/jx-callback/business/jxutils/datares" "git.rosy.net.cn/jx-callback/business/msghub" "git.rosy.net.cn/jx-callback/globals/api" "github.com/astaxie/beego" @@ -99,7 +100,7 @@ func (c *CmsController) GetServiceInfo() { // @router /GetQiniuUploadToken [get] func (c *CmsController) GetQiniuUploadToken() { c.callGetQiniuUploadToken(func(params *tCmsGetQiniuUploadTokenParams) (retVal interface{}, errCode string, err error) { - retVal, err = cms.GetQiniuUploadToken(params.Ctx, params.Suffix, params.HashCode) + retVal, err = datares.GetQiniuUploadToken(params.Ctx, params.Suffix, params.HashCode) return retVal, "", err }) } @@ -116,7 +117,7 @@ func (c *CmsController) GetQiniuUploadToken() { // @router /RegisterDataResource [post] func (c *CmsController) RegisterDataResource() { c.callRegisterDataResource(func(params *tCmsRegisterDataResourceParams) (retVal interface{}, errCode string, err error) { - retVal, err = cms.RegisterDataResource(params.Ctx, params.Name, params.ResourceURL, params.MimeType, params.HashCode) + retVal, err = datares.RegisterDataResource(params.Ctx, params.Name, params.ResourceURL, params.MimeType, params.HashCode, nil, false, true) return retVal, "", err }) } diff --git a/controllers/init_data.go b/controllers/init_data.go index 139c94a9c..ae0fd6353 100644 --- a/controllers/init_data.go +++ b/controllers/init_data.go @@ -93,6 +93,21 @@ func (c *InitDataController) UploadEbaiImg4SkuName() { }) } +// @Title 将资源上传到平台(当前为饿百与美团) +// @Description 将资源上传到平台(当前为饿百与美团) +// @Param token header string true "认证token" +// @Param isAsync formData bool false "是否异步操作" +// @Param isContinueWhenError formData bool false "单个同步失败是否继续,缺省false" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /UploadImage4Vendors [post] +func (c *InitDataController) UploadImage4Vendors() { + c.callUploadImage4Vendors(func(params *tInitdataUploadImage4VendorsParams) (retVal interface{}, errCode string, err error) { + retVal, err = initdata.UploadImg4Vendors(params.Ctx, params.IsAsync, params.IsContinueWhenError) + return retVal, "", err + }) +} + // @Title 从饿百店建商品 // @Description 从饿百店建商品 // @Param token header string true "认证token" diff --git a/routers/commentsRouter_controllers.go b/routers/commentsRouter_controllers.go index 6d552356d..70a1da094 100644 --- a/routers/commentsRouter_controllers.go +++ b/routers/commentsRouter_controllers.go @@ -565,6 +565,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:InitDataController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:InitDataController"], + beego.ControllerComments{ + Method: "UploadImage4Vendors", + Router: `/UploadImage4Vendors`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:InitDataController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:InitDataController"], beego.ControllerComments{ Method: "UploadWeimobImg4SkuName",