package jd // 这里函数取得的信息,除了与自身实体相关的ID(比如PARENT ID),都已经转换成了本地ID了 import ( "fmt" "unicode/utf8" "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/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" "github.com/astaxie/beego" ) const ( DefBrandID = 35247 DefJdCategoryID = 20362 DefJdCategoryID4Jxgy = 22410 // 其他国产水果 ) type tSkuInfoExt struct { model.SkuName JdCatID int64 `orm:"column(jd_cat_id)"` // 商家类别 JdCategoryID int `orm:"column(jd_category_id)"` // 到家类别 SkuCatID int64 `orm:"column(sku_cat_id)"` // 商家特殊类别 Comment string `orm:"size(255)" json:"comment"` } var ( skuAddParamsKeyMap = map[string]int{ jdapi.KeyUpcCode: 1, } ) func getDefJdCategoryID() int { if beego.BConfig.RunMode == "jxgy" { return DefJdCategoryID4Jxgy } return DefJdCategoryID } func (p *PurchaseHandler) CreateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error) { var jdPid int64 if cat.ParentID != 0 { pCat := &model.SkuCategory{} pCat.ID = cat.ParentID if err = dao.GetEntity(db, pCat); err == nil { jdPid = pCat.JdID } else { return err } } if globals.EnableStoreWrite { result, err2 := getAPI("").AddShopCategory(jdPid, cat.Name, int(cat.Level), cat.Seq, userName) if err = err2; err == nil { if jdID := utils.Str2Int64WithDefault(result, 0); jdID != 0 { cat.JdID = jdID } } } return err } func jdCat2Jx(jdCat *jdapi.CategoryInfo) (jxCat *partner.BareCategoryInfo) { return &partner.BareCategoryInfo{ VendorCatID: utils.Int64ToStr(jdCat.Id), Level: jdCat.Level, Name: jdCat.Name, Seq: jdCat.Sort, } } func (p *PurchaseHandler) GetAllCategories(ctx *jxcontext.Context, vendorOrgCode string) (cats []*partner.BareCategoryInfo, err error) { result, err := getAPI(vendorOrgCode).QueryCategoriesByOrgCode() if err == nil { catMap := make(map[int64]*partner.BareCategoryInfo) level := 1 for { processedCount := 0 for _, jdCat := range result { if jdCat.Level == level { processedCount++ jxCat := jdCat2Jx(jdCat) if level == 1 { cats = append(cats, jxCat) } else { parentCat := catMap[jdCat.ParentId] if parentCat != nil { parentCat.Children = append(parentCat.Children, jxCat) } } catMap[jdCat.Id] = jxCat } } if processedCount == 0 { break } level++ } } return cats, err } func (p *PurchaseHandler) UpdateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error { if globals.EnableStoreWrite { return getAPI("").UpdateShopCategory(cat.JdID, cat.Name) } return nil } func (p *PurchaseHandler) DeleteCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error { if globals.EnableStoreWrite { return getAPI("").DelShopCategory(cat.JdID) } return nil } func (p *PurchaseHandler) ReorderCategories(db *dao.DaoDB, parentCatID int, userName string) (err error) { var parentJDID int64 if parentCatID != 0 { cat := &model.SkuCategory{} cat.ID = parentCatID if err = dao.GetEntity(db, cat); err != nil { return err } parentJDID = cat.JdID } var cats []*model.SkuCategory if err = dao.GetRows(db, &cats, ` SELECT * FROM sku_category WHERE parent_id = ? AND deleted_at = ? ORDER BY seq`, parentCatID, utils.DefaultTimeValue); err == nil { jdCatIDs := make([]int64, len(cats)) for k, v := range cats { jdCatIDs[k] = v.JdID } if globals.EnableStoreWrite { err = getAPI("").ChangeShopCategoryOrder(parentJDID, jdCatIDs) } } return err } func (p *PurchaseHandler) cuSku(db *dao.DaoDB, sku *model.Sku, handler func(skuExt *tSkuInfoExt, price int, skuName string, shopCategories []int64, addParams map[string]interface{}) (string, error)) (err error) { var skuInfoExt tSkuInfoExt err = dao.GetRow(nil, &skuInfoExt, ` SELECT t2.*, t3.jd_id jd_cat_id, IF(t2.jd_category_id > 0, t2.jd_category_id, t3.jd_category_id) jd_category_id, t4.jd_id sku_cat_id FROM sku t1 JOIN sku_name t2 ON t1.name_id = t2.id JOIN sku_category t3 ON t2.category_id = t3.id LEFT JOIN sku_category t4 ON t1.category_id = t4.id WHERE t1.id = ? `, sku.ID) if err == nil { shopCategories := []int64{skuInfoExt.JdCatID} // SPU只支持SPU的商家分类,不支持单独SKU的,去除SKU的分类 // if skuInfoExt.SkuCatID != 0 { // shopCategories = append(shopCategories, skuInfoExt.SkuCatID) // } if skuInfoExt.JdCategoryID == 0 { skuInfoExt.JdCategoryID = getDefJdCategoryID() } if skuInfoExt.BrandID == 0 { skuInfoExt.BrandID = DefBrandID } addParams := map[string]interface{}{} if skuInfoExt.IsGlobal == 0 { //如果不是全国可售,要查可售区域 sellPlaces, err2 := dao.GetSellCities(db, skuInfoExt.ID, model.VendorIDJD) if err = err2; err == nil && len(sellPlaces) > 0 { sellCites := make([]int, len(sellPlaces)) for k, v := range sellPlaces { sellCites[k] = v.JdCode } addParams["sellCities"] = sellCites } } if addParams["sellCities"] == nil { addParams["sellCities"] = []int{0} } if skuInfoExt.DescImg != "" { addParams[jdapi.KeyProductDesc] = fmt.Sprintf(`一张图片`, skuInfoExt.DescImg) addParams[jdapi.KeyIfViewDesc] = 0 } else { addParams[jdapi.KeyIfViewDesc] = 1 } if err == nil { skuName := jxutils.ComposeSkuName(skuInfoExt.Prefix, skuInfoExt.Name, sku.Comment, skuInfoExt.Unit, sku.SpecQuality, sku.SpecUnit, jdapi.MaxSkuNameCharCount) skuPrice := jxutils.CaculateSkuPrice(skuInfoExt.Price, sku.SpecQuality, sku.SpecUnit, skuInfoExt.Unit) if skuInfoExt.Upc != "" { addParams[jdapi.KeyUpcCode] = skuInfoExt.Upc } result, err2 := handler(&skuInfoExt, skuPrice, skuName, shopCategories, addParams) if err = err2; err == nil { if jdID := utils.Str2Int64WithDefault(result, 0); jdID != 0 { sku.JdID = jdID } } } } return err } func (p *PurchaseHandler) CreateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) { return p.cuSku(db, sku, func(skuExt *tSkuInfoExt, price int, skuName string, shopCategories []int64, addParams map[string]interface{}) (vendorSkuID string, err error) { if skuExt.IsSpu == 0 { if globals.EnableStoreWrite { vendorSkuID, err = getAPI("").AddSku(utils.Int2Str(sku.ID), skuExt.JdCategoryID, shopCategories, skuExt.BrandID, skuName, price, jxutils.IntWeight2Float(sku.Weight), []string{skuExt.Img}, jxStatus2jdStatus(sku.Status), true, addParams) if err != nil { if jdSkuID := jdapi.GetJdSkuIDFromError(err); jdSkuID > 0 { vendorSkuID = utils.Int64ToStr(jdSkuID) err = nil } } } } else { vendorSkuID, err = p.syncSkuNameAsSpu(db, sku, skuExt, price, skuName, shopCategories, addParams) } return vendorSkuID, err }) } func (p *PurchaseHandler) ReadSku(vendorSkuID string) (skuNameExt *model.SkuNameExt, err error) { jdSkuID := utils.Str2Int64(vendorSkuID) skuList, _, err := getAPI("").QuerySkuInfos(&jdapi.QuerySkuParam{ SkuID: jdSkuID, }) if err == nil { if len(skuList) >= 1 { skuNameExt = &model.SkuNameExt{} if imgList, err2 := getAPI("").QueryListBySkuIds(&jdapi.QueryListBySkuIdsParam{ SkuIDs: []int64{jdSkuID}, }); err2 == nil && len(imgList) > 0 { skuNameExt.Img = imgList[0].SourceImgURL } sku := skuList[0] prefix, name, comment, specUnit, unit, specQuality := jxutils.SplitSkuName(sku.SkuName) if name == "" { name = sku.SkuName unit = "份" specUnit = "g" } skuNameExt.Prefix = prefix skuNameExt.Name = name skuNameExt.Unit = unit skuNameExt.Price = sku.SkuPrice skuNameExt.Skus = []*model.Sku{ &model.Sku{ SpecQuality: specQuality, SpecUnit: specUnit, Weight: jxutils.FloatWeight2Int(float32(sku.Weight)), JdID: sku.SkuID, Status: jdStatus2jxStatus(sku.FixedStatus), Comment: comment, }, } skuNameExt.Skus[0].ID = int(utils.Str2Int64(sku.OutSkuID)) db := dao.GetDB() shopCategories := sku.ShopCategories if len(shopCategories) > 0 { skuCat := &model.SkuCategory{} skuCat.JdID = shopCategories[0] if dao.GetEntity(db, skuCat, "JdID") == nil { skuNameExt.CategoryID = skuCat.ID } } sellCities := sku.SellCities for _, v := range sellCities { if v == 0 { skuNameExt.IsGlobal = 1 } } if len(sellCities) == 0 || skuNameExt.IsGlobal == 1 { skuNameExt.IsGlobal = 1 } else { var places []*model.Place if err = dao.GetRows(db, &places, "SELECT * FROM place WHERE jd_code IN ("+dao.GenQuestionMarks(len(sellCities))+") AND level = 2", sellCities); err == nil { skuNameExt.Places = make([]int, len(places)) for k, v := range places { skuNameExt.Places[k] = v.Code } } } } else { err = partner.ErrCanNotFindItem } } return skuNameExt, err } func (p *PurchaseHandler) UpdateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) { return p.cuSku(db, sku, func(skuExt *tSkuInfoExt, price int, skuName string, shopCategories []int64, addParams map[string]interface{}) (vendorSkuID string, err error) { params := utils.MergeMaps(addParams) params[jdapi.KeyCategoryId] = skuExt.JdCategoryID params[jdapi.KeyShopCategories] = shopCategories params[jdapi.KeyBrandId] = skuExt.BrandID params[jdapi.KeySkuName] = skuName params[jdapi.KeyWeight] = jxutils.IntWeight2Float(sku.Weight) params[jdapi.KeyImages] = []string{skuExt.Img} params[jdapi.KeyFixedStatus] = jxStatus2jdStatus(sku.Status) if skuExt.IsSpu == 0 { if globals.EnableStoreWrite { vendorSkuID, err = getAPI("").UpdateSku(utils.Int2Str(sku.ID), params) } } else { vendorSkuID, err = p.syncSkuNameAsSpu(db, sku, skuExt, price, skuName, shopCategories, addParams) } return vendorSkuID, err }) } func (p *PurchaseHandler) DeleteSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) { params := map[string]interface{}{ jdapi.KeyFixedStatus: jdapi.SkuFixedStatusDeleted, } sql := ` SELECT t2.* FROM sku t1 JOIN sku_name t2 ON t1.name_id = t2.id WHERE t1.id = ? ` var skuExt tSkuInfoExt err = dao.GetRow(db, &skuExt, sql, sku.ID) if err == nil { if skuExt.IsSpu == 0 { if globals.EnableStoreWrite { _, err = getAPI("").UpdateSku(utils.Int2Str(sku.ID), params) } } else { _, err = p.syncSkuNameAsSpu(db, sku, &skuExt, 0, "", nil, nil) } } return err } func (p *PurchaseHandler) RefreshAllSkusID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error) { globals.SugarLogger.Debugf("jd RefreshAllSkusID") db := dao.GetDB() var skuPairs []*jdapi.SkuIDPair const stepCount = 2 rootTask := tasksch.NewSeqTask("jd RefreshAllSkusID", ctx, func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { switch step { case 0: err = dao.GetRows(db, &skuPairs, ` SELECT t1.id out_sku_id, t1.jd_id sku_id FROM sku t1 WHERE t1.deleted_at = ? `, utils.DefaultTimeValue) default: taskName := "RefreshAllSkusID update id" if step != stepCount-1 { taskName = "RefreshAllSkusID update uuid" } task1 := tasksch.NewParallelTask(taskName, tasksch.NewParallelConfig().SetIsContinueWhenError(true).SetBatchSize(jdapi.MaxBatchSize4BatchUpdateOutSkuId), ctx, func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { skuPairs := make([]*jdapi.SkuIDPair, len(batchItemList)) for k, v := range batchItemList { pair := v.(*jdapi.SkuIDPair) skuPairs[k] = &jdapi.SkuIDPair{ SkuId: pair.SkuId, OutSkuId: pair.OutSkuId, } if step != stepCount-1 { skuPairs[k].OutSkuId = utils.GetUUID() } } globals.SugarLogger.Debug(utils.Format4Output(skuPairs, false)) if globals.EnableStoreWrite { _, err = getAPI("").BatchUpdateOutSkuId(skuPairs) } return nil, err }, skuPairs) rootTask.AddChild(task1).Run() _, err = task1.GetResult(0) } return nil, err }, stepCount) tasksch.HandleTask(rootTask, parentTask, false).Run() if !isAsync { _, err = rootTask.GetResult(0) } return rootTask.ID, err } func splitAddParams(addParams map[string]interface{}) (spuAddParams, skuAddParams map[string]interface{}) { if addParams != nil { spuAddParams = make(map[string]interface{}) skuAddParams = make(map[string]interface{}) for key := range addParams { if skuAddParamsKeyMap[key] == 1 { skuAddParams[key] = addParams[key] } else { spuAddParams[key] = addParams[key] } } } return spuAddParams, skuAddParams } // 这个处理JD SPU,补丁形式 func (p *PurchaseHandler) syncSkuNameAsSpu(db *dao.DaoDB, sku *model.Sku, skuExt *tSkuInfoExt, price int, skuName string, shopCategories []int64, addParams map[string]interface{}) (vendorSkuID string, err error) { // SPU的SKU NAME不需要规格信息 skuName = jxutils.ComposeSkuName(skuExt.Prefix, skuExt.Name, sku.Comment, "", 0, "", 0) skuNameJdID := skuExt.JdID globals.SugarLogger.Debugf("syncSkuNameAsSpu1 sku.id=%d, bareSkuName:%s, skuName:%s, skuNameJdID:%d", sku.ID, skuExt.Name, skuName, skuNameJdID) spuAddParams, skuAddParams := splitAddParams(addParams) if !jxutils.IsEmptyID(skuNameJdID) && sku.JdSyncStatus&model.SyncFlagDeletedMask != 0 { // 删除SKU if globals.EnableStoreWrite { err = getAPI("").UpdateSkuBaseInfo(utils.Int2Str(skuExt.ID), utils.Int2Str(sku.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusDeleted)) } } if err == nil { updateFields := []string{} if skuExt.JdSyncStatus&model.SyncFlagDeletedMask != 0 { sql := ` SELECT COUNT(*) ct FROM sku t1 WHERE t1.name_id = ? AND (t1.status <> ? OR t1.jd_sync_status <> 0) ` var count struct { Ct int } if err = dao.GetRow(db, &count, sql, sku.NameID, model.SkuStatusDeleted); err != nil { return "", err } if count.Ct <= 1 && sku.JdSyncStatus&model.SyncFlagDeletedMask != 0 { // 1就是最后删的那个 updateFields = append(updateFields, model.FieldJdSyncStatus) if globals.EnableStoreWrite { if err = getAPI("").UpdateSpu(utils.Int2Str(skuExt.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusOffline)); err == nil { err = getAPI("").UpdateSpu(utils.Int2Str(skuExt.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusDeleted)) } } } } else if skuExt.JdSyncStatus&model.SyncFlagNewMask != 0 && jxutils.IsEmptyID(skuNameJdID) { if globals.EnableStoreWrite { spuName := jxutils.ComposeSpuName(skuExt.Prefix, skuExt.Name, 0) skus := []map[string]interface{}{ map[string]interface{}{ jdapi.KeyOutSkuId: utils.Int2Str(sku.ID), jdapi.KeySkuName: skuName, jdapi.KeyFixedStatus: jxStatus2jdStatus(sku.Status), jdapi.KeySkuPrice: price, jdapi.KeyWeight: jxutils.IntWeight2Float(sku.Weight), jdapi.KeyIsSale: true, jdapi.FakeKeySpecAttr: composeSkuSpec(sku.SpecQuality, sku.SpecUnit, skuExt.Unit), }, } skus[0] = utils.MergeMaps(skus[0], skuAddParams) updateFields = append(updateFields, model.FieldJdSyncStatus) if globals.EnableStoreWrite { vendorSpuID, skuPairs, err2 := getAPI("").AddSpu(utils.Int2Str(skuExt.ID), skuExt.JdCategoryID, shopCategories, skuExt.BrandID, spuName, []string{skuExt.Img}, jxStatus2jdStatus(skuExt.Status), spuAddParams, skus) if err = err2; err == nil { skuExt.JdID = vendorSpuID // skuNameJdID = skuExt.JdID // 这个是故意去掉的,这样之后的首次SKU修改操作就会被忽略,下一条语句也就可以不用了 // sku.JdSyncStatus &= ^model.SyncFlagNewMask vendorSkuID = utils.Int64ToStr(skuPairs[0].SkuId) updateFields = append(updateFields, model.FieldJdID) } } } } else if skuExt.JdSyncStatus&model.SyncFlagModifiedMask != 0 { params := utils.MergeMaps(map[string]interface{}{ jdapi.KeySpuName: jxutils.ComposeSpuName(skuExt.Prefix, skuExt.Name, 0), jdapi.KeyShopCategories: shopCategories, jdapi.KeyCategoryId: skuExt.JdCategoryID, jdapi.KeyBrandId: skuExt.BrandID, jdapi.KeyImages: []string{skuExt.Img}, jdapi.KeyFixedStatus: jxStatus2jdStatus(skuExt.Status), }, spuAddParams) updateFields = append(updateFields, model.FieldJdSyncStatus) if globals.EnableStoreWrite { err = getAPI("").UpdateSpu(utils.Int2Str(skuExt.ID), params) } } if err == nil { if skuExt.JdSyncStatus != 0 && len(updateFields) > 0 { skuExt.JdSyncStatus = 0 _, err = dao.UpdateEntity(db, &skuExt.SkuName, updateFields...) globals.SugarLogger.Debugf("syncSkuNameAsSpu4 sku.id=%d, skuName:%s, skuName:%s", sku.ID, skuExt.Name, utils.Format4Output(&skuExt.SkuName, false)) } } } if err == nil && !jxutils.IsEmptyID(skuNameJdID) { if sku.JdSyncStatus&model.SyncFlagNewMask != 0 { // 非首次新增SKU if globals.EnableStoreWrite { vendorSkuID2, err2 := getAPI("").AppendSku(utils.Int2Str(skuExt.ID), utils.Int2Str(sku.ID), skuName, price, jxutils.IntWeight2Float(sku.Weight), []string{skuExt.Img}, jxStatus2jdStatus(sku.Status), true, composeSkuSpec(sku.SpecQuality, sku.SpecUnit, skuExt.Unit), skuAddParams) if err = err2; err == nil { vendorSkuID = utils.Int64ToStr(vendorSkuID2) } } } else if sku.JdSyncStatus&model.SyncFlagModifiedMask != 0 { params := make(map[string]interface{}) params[jdapi.KeySkuName] = skuName params[jdapi.KeyImages] = []string{skuExt.Img} params[jdapi.KeyFixedStatus] = jxStatus2jdStatus(sku.Status) params[jdapi.KeyWeight] = jxutils.IntWeight2Float(sku.Weight) params[jdapi.KeySkuPrice] = price if globals.EnableStoreWrite { err = getAPI("").UpdateSkuBaseInfo(utils.Int2Str(skuExt.ID), utils.Int2Str(sku.ID), utils.MergeMaps(params, skuAddParams)) if sku.JdSyncStatus&model.SyncFlagSpecMask != 0 { skuIndex := sku.SkuIndex if skuIndex > 0 { saleAttrValue := composeSkuSpec(sku.SpecQuality, sku.SpecUnit, skuExt.Unit) globals.SugarLogger.Debugf("syncSkuNameAsSpu outSuperId:%d, saleAttrId:%d, saleAttrValueId:%d, saleAttrValueName:%s", skuExt.ID, jdapi.SaleAttrIDBase, jdapi.SaleAttrValueIDBase+skuIndex-1, saleAttrValue) err = getAPI("").UpdateSpuSaleAttr(utils.Int2Str(skuExt.ID), utils.Int2Str(jdapi.SaleAttrIDBase), "", utils.Int2Str(jdapi.SaleAttrValueIDBase+skuIndex-1), saleAttrValue) } } } } if err == nil { sku.JdSyncStatus = 0 } } return vendorSkuID, err } func composeSkuSpec(specQuality float32, specUnit, unit string) string { prefix := "" if unit == model.SpecialUnit { prefix = "约" } value := prefix + jxutils.ComposeSkuSpec(specQuality, specUnit) suffix := "/" + unit if utf8.RuneCountInString(value) <= 8-utf8.RuneCountInString(suffix) { value += suffix } return value } func jdStatus2jxStatus(jdStatus int) (jxStatus int) { switch jdStatus { case jdapi.SkuFixedStatusOnline: jxStatus = model.SkuStatusNormal case jdapi.SkuFixedStatusOffline: jxStatus = model.SkuStatusDontSale case jdapi.SkuFixedStatusDeleted: jxStatus = model.SkuStatusDeleted } return jxStatus } func jxStatus2jdStatus(jxStatus int) (jdStatus int) { switch jxStatus { case model.SkuStatusNormal: jdStatus = jdapi.SkuFixedStatusOnline case model.SkuStatusDontSale: jdStatus = jdapi.SkuFixedStatusOffline case model.SkuStatusDeleted: jdStatus = jdapi.SkuFixedStatusDeleted } return jdStatus } func (p *PurchaseHandler) getVendorCategories(level int, pid int64) (vendorCats []*model.SkuVendorCategory, err error) { cats, err := getAPI("").QueryChildCategoriesForOP(pid) if err != nil { return nil, err } for _, v := range cats { if v.Status == 1 { cat := &model.SkuVendorCategory{ VendorID: model.VendorIDJD, Name: v.Name, Level: level, VendorCategoryID: utils.Int64ToStr(v.Id), } if level > 1 { cat.ParentID = utils.Int64ToStr(v.ParentId) if level == 3 { cat.IsLeaf = 1 } } vendorCats = append(vendorCats, cat) if level < 3 { childVendorCats, err2 := p.getVendorCategories(level+1, v.Id) if err2 == nil && len(childVendorCats) > 0 { vendorCats = append(vendorCats, childVendorCats...) } else { cat.IsLeaf = 1 } } } } return vendorCats, nil } func (p *PurchaseHandler) GetVendorCategories(ctx *jxcontext.Context) (vendorCats []*model.SkuVendorCategory, err error) { vendorCats, err = p.getVendorCategories(1, 0) return vendorCats, err } func (p *PurchaseHandler) GetSkus(ctx *jxcontext.Context, skuID int, vendorSkuID, skuName string) (skuNameList []*partner.SkuNameInfo, err error) { param := &jdapi.QuerySkuParam{ SkuID: utils.Str2Int64WithDefault(vendorSkuID, 0), SkuName: skuName, IsFilterDel: jdapi.IsFilterDelTrue, PageNo: 1, PageSize: jdapi.MaxSkuIDsCount4QueryListBySkuIds, // 为了同时取图,这个值不要大于jdapi.MaxSkuIDsCount4QueryListBySkuIds } for { skuList, _, err2 := getAPI("").QuerySkuInfos(param) if err = err2; err != nil { return nil, err } if len(skuList) > 0 { batchSkuNameList := make([]*partner.SkuNameInfo, len(skuList)) for k, v := range skuList { batchSkuNameList[k] = vendorSku2Jx(v) } setSkuNameListPic(batchSkuNameList) skuNameList = append(skuNameList, batchSkuNameList...) } if len(skuList) < param.PageSize { break } param.PageNo++ } return skuNameList, err } func setSkuNameListPic(skuNameList []*partner.SkuNameInfo) []*partner.SkuNameInfo { jdSkuIDs := make([]int64, len(skuNameList)) for k, v := range skuNameList { jdSkuIDs[k] = utils.Str2Int64(v.SkuList[0].VendorSkuID) } imgMap := make(map[int64]*jdapi.ImgHandleQueryResult) if imgList, err2 := getAPI("").QueryListBySkuIds(&jdapi.QueryListBySkuIdsParam{ SkuIDs: jdSkuIDs, }); err2 == nil { for _, v := range imgList { if v.ImgType == jdapi.ImgTypeMain { imgResult := imgMap[v.SkuID] if imgResult == nil || imgResult.IsMain < v.IsMain { imgMap[v.SkuID] = v } } } } // 使用扒页面方式获取商品图片 if false { var leftJdSkuIDs []int64 for _, v := range jdSkuIDs { if imgMap[v] == nil { leftJdSkuIDs = append(leftJdSkuIDs, v) } } task := tasksch.NewParallelTask("jd setSkuNameListPic", nil, jxcontext.AdminCtx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { jdSkuID := batchItemList[0].(int64) imgList, err := getAPI("").GetSkuPageImageInfo(jdSkuID) if err == nil && len(imgList) > 0 { retVal = [][]string{ []string{utils.Int64ToStr(jdSkuID), imgList[0].Big}, } } return retVal, err }, leftJdSkuIDs) task.Run() if resultList, err := task.GetResult(0); err == nil { for _, v := range resultList { strList := v.([]string) imgMap[utils.Str2Int64(strList[0])] = &jdapi.ImgHandleQueryResult{ SourceImgURL: strList[1], } } } } // 设置商品图片 for _, v := range skuNameList { if imgResult := imgMap[utils.Str2Int64(v.SkuList[0].VendorSkuID)]; imgResult != nil { v.PictureList = []string{imgResult.SourceImgURL} } } return skuNameList } func vendorSku2Jx(vendorSku *jdapi.SkuMain) (skuName *partner.SkuNameInfo) { prefix, name, comment, specUnit, unit, specQuality := jxutils.SplitSkuName(vendorSku.SkuName) weight := int(vendorSku.Weight * 1000) if weight <= 0 { weight = jxutils.FormatSkuWeight(specQuality, specUnit) } skuID := int(utils.Str2Int64WithDefault(vendorSku.OutSkuID, 0)) vendorSkuID := utils.Int64ToStr(vendorSku.SkuID) skuName = &partner.SkuNameInfo{ NameID: skuID, VendorNameID: vendorSkuID, VendorCatIDList: []string{utils.Int64ToStr(vendorSku.CategoryID)}, Prefix: prefix, Name: name, Unit: unit, SkuList: []*partner.SkuInfo{ &partner.SkuInfo{ StoreSkuInfo: partner.StoreSkuInfo{ VendorSkuID: vendorSkuID, SkuID: skuID, VendorPrice: int64(vendorSku.SkuPrice), Status: jdStatus2jxStatus(vendorSku.FixedStatus), }, SkuName: vendorSku.SkuName, Comment: comment, SpecQuality: float64(specQuality), SpecUnit: specUnit, Weight: weight, }, }, } return skuName }