一個(gè)商品SKU是怎么生成的

首先說(shuō)一說(shuō)什么是SKU。匀奏。鞭衩。。娃善。论衍。。自己百度去聚磺。坯台。。

類似京東上面瘫寝,未來(lái)人類S5這個(gè)臺(tái)筆記本

都是S5這個(gè)型號(hào)蜒蕾,但是因?yàn)镃PU,顯卡,內(nèi)存焕阿,硬盤(pán)等不同咪啡,價(jià)格也不一樣。CPU,顯卡暮屡,內(nèi)存撤摸,硬盤(pán)等屬性組合成的一個(gè)唯一的商品,就可以用一個(gè)SKU來(lái)表示,像圖上就有10個(gè)SKU褒纲。一系列的SKU可以歸到一個(gè)SPU下進(jìn)行管理准夷。

那么一個(gè)SKU是怎么生成的呢?下面結(jié)合自己的一些經(jīng)驗(yàn)莺掠,說(shuō)說(shuō)一些電商平臺(tái)的大致產(chǎn)品結(jié)構(gòu)以及SKU的生成方式衫嵌。

1.阿里速賣通平臺(tái),阿里國(guó)際站

這兩個(gè)平臺(tái)同一個(gè)爸爸,基本差不多彻秆。要?jiǎng)?chuàng)建一個(gè)商品需要先選一個(gè)類目楔绞,類目下面掛了一堆的屬性,屬性上又掛了一堆的屬性值唇兑。屬性分為銷售屬性和非銷售屬性(銷售屬性就是類似顏色墓律,尺寸這些單個(gè)SKU獨(dú)有的,非銷售屬性就是多個(gè)SKU共有的幔亥,比如同一個(gè)品牌型號(hào)“未來(lái)人類S5”)耻讽。非銷售屬性有必填和非必填,可以是單選帕棉,多選针肥,文本等。銷售屬性就是構(gòu)成SKU的關(guān)鍵香伴。比如說(shuō)有銷售屬性顏色和尺寸慰枕,顏色屬性下有很多屬性值(紅,黃即纲,藍(lán)等等)具帮,尺寸(1,2,3,4等等)也是。當(dāng)顏色選了紅,黃蜂厅,尺寸選了1,2匪凡,那么就應(yīng)該生成2x2=4個(gè)SKU,每個(gè)SKU有各自的價(jià)格掘猿,庫(kù)存等病游。保存SKU的時(shí)候會(huì)與對(duì)應(yīng)的銷售屬性相關(guān)聯(lián)。
大致的數(shù)據(jù)模型如下

當(dāng)然稠通,實(shí)際比這更加復(fù)雜(比如產(chǎn)品的圖片衬衬,單個(gè)SKU的圖片,多個(gè)SKU共同的圖片,非銷售屬性可以自定義添加分類不具有的改橘。滋尉。。)

2.eBay
跟上面兩個(gè)平臺(tái)類似飞主,創(chuàng)建一個(gè)產(chǎn)品也要先選一個(gè)分類兼砖,分類下面也是有很多屬性,屬性有很多屬性值既棺。讽挟。。丸冕,不同的地方是eBay沒(méi)有區(qū)分銷售屬性和非銷售屬性(或者說(shuō)全部是非銷售屬性)耽梅,也允許添加自定義屬性和屬性值。eBay上SKU是手動(dòng)添加的胖烛,SKU上的屬性(SKU上的屬性暫且都叫做銷售屬性)也是自定義的眼姐。比如說(shuō)添加了一個(gè)SKU A,價(jià)格和數(shù)量這兩個(gè)是必須的,還可以手動(dòng)加個(gè)顏色屬性佩番,然后填上屬性值紅色众旗。當(dāng)然,若果增加一個(gè)SKU B趟畏,那么這個(gè)SKU也會(huì)有顏色這個(gè)屬性贡歧,屬性值可以自定義。最后校驗(yàn)這些SKU的屬性值組合起來(lái)是否唯一赋秀。

這樣的優(yōu)勢(shì)就是可以隨意控制SKU的數(shù)量利朵,如果按照上面兩個(gè)平臺(tái)的規(guī)則,這里應(yīng)該有4x4x1=16個(gè)SKU猎莲。這樣自由度更高會(huì)不會(huì)使結(jié)構(gòu)更加復(fù)雜呢绍弟?當(dāng)然是NO,用上面的數(shù)據(jù)模型就可以搞定

3.Lazada,Linio平臺(tái)
國(guó)際慣例著洼,先選一個(gè)類目樟遣,類目下面一堆屬性而叼,有必填和非必填,屬性下一堆屬性值豹悬。最大的區(qū)別就是葵陵,一個(gè)產(chǎn)品只有一個(gè)SKU,屬性不支持自定義屿衅。比如說(shuō)要添加一個(gè)商品埃难,有兩種顏色莹弊,那么只能創(chuàng)建兩個(gè)產(chǎn)品涤久,這兩個(gè)產(chǎn)品可能只有圖片不一樣(顏色不一樣,可能沒(méi)有顏色這個(gè)屬性來(lái)選)

4.Wish平臺(tái)
比較奇特忍弛,沒(méi)有分類响迂,產(chǎn)品有固定的屬性,比如標(biāo)題细疚,描述蔗彤,運(yùn)費(fèi)等。一個(gè)產(chǎn)品下可以有多個(gè)SKU疯兼,SKU的生成取決于固定的兩大類屬性然遏,兩個(gè)大類為:顏色和尺寸。比如顏色這個(gè)屬性就是歸類于顏色這個(gè)類吧彪,其他的屬性(品牌待侵,型號(hào),容量等等歸為尺寸這個(gè)大類)姨裸。尺寸類的屬性值支持自定義秧倾,但只能選一個(gè)尺寸類屬性(比如選了品牌就不能選容量,選了品牌后可以添加任意值)傀缩。兩類屬性不是必須同時(shí)存在那先,比如顏色選了紅,可以不選尺寸類的屬性赡艰,反之也一樣售淡。

忘記說(shuō)了,一個(gè)SKU是靠一串唯一編碼來(lái)標(biāo)識(shí)的慷垮,比如1234A勋又,1234B。一般來(lái)說(shuō)一個(gè)平臺(tái)下不會(huì)存在兩個(gè)相同的SKU换帜,或這一個(gè)店鋪下不會(huì)存在兩個(gè)相同的SKU楔壤。

大致的邏輯和數(shù)據(jù)模型就這些,接下來(lái)說(shuō)說(shuō)開(kāi)發(fā)實(shí)現(xiàn)方面惯驼。

數(shù)據(jù)庫(kù)大致就依靠上面的數(shù)據(jù)模型進(jìn)行設(shè)計(jì)蹲嚣,編輯的時(shí)候递瑰,后端按照這些關(guān)聯(lián)關(guān)系取出數(shù)據(jù)給到前端(我這邊前后端未分離,頁(yè)面還是后端渲染隙畜,但我還是把數(shù)據(jù)格式化為JSON再渲染到前端)抖部,保存的時(shí)候再進(jìn)行相關(guān)的邏輯校驗(yàn)。因?yàn)楹蠖说囊恍┻壿嫴僮魃婕昂蠊緝?nèi)部的業(yè)務(wù)议惰,這里就不細(xì)說(shuō)了慎颗。說(shuō)說(shuō)前端的具體細(xì)節(jié),以速賣通的為例言询,用的是vue俯萎,前端拿到的數(shù)據(jù)如下

屬性數(shù)據(jù),(變量properties)
sku數(shù)據(jù)(變量skus)

實(shí)現(xiàn)后的粗糙界面

data: {
            properties: properties,
            skus: skus
        }

遍歷properties运杭,得到材質(zhì)夫啊,顏色,發(fā)貨地辆憔,套餐這些屬性對(duì)象撇眯,接著遍歷這些對(duì)象里的values屬性,得到屬性值對(duì)象,根據(jù)屬性對(duì)象的selectedValues判斷屬性值是否選上(因?yàn)槲沂呛蠖虽秩镜膉s變量,所以初始化的時(shí)候selectedValues里的數(shù)據(jù)直接引用的屬性值對(duì)象虱咧,如果是非后端渲染的話熊榛,要根據(jù)skus里的屬性和屬性值去初始化selectedValues的數(shù)據(jù),并且存的是屬性值對(duì)象的引用)

<tr v-for="(index,item) in properties">
        <td><strong>{{item.Name}}:</strong></td>
        <td>

            <label v-for="value in item.values"><input type="checkbox" :value="value" v-model="item.selectedValues"/>{{value.Name}}</label>

            <table class="list_table" v-if="item.Name!='發(fā)貨地'&&item.selectedValues.length>0">
                <tbody>
                <tr>
                    <th>{{item.Name}}</th>
                    <th>自定義名稱</th>
                    <th v-if="item.Name=='顏色'">圖片(無(wú)圖片可以不填)</th>
                </tr>

                <tr v-for="selectedValue in item.selectedValues">
                    <td>{{selectedValue.Name}}</td>
                    <td>
                        <input type="text" v-model="selectedValue.DefinitionName" maxlength="20"/>
                    </td>
                    <td v-if="item.Name=='顏色'">
                        <div style="float: left">
                            <input type="file"  style="width: 63px;"/>
                        </div>
                        <div style="float: right">
                            <a href="" rel="link" target="_blank">
                                ![](selectedValue.ImageUrl)
                            </a>
                        </div>
                    </td>
                </tr>

                </tbody>
            </table>
        </td>
    </tr>

因?yàn)閟electedValues通過(guò)v-model綁定腕巡,當(dāng)選中或取消一個(gè)屬性值的時(shí)候后玄坦,selectedValues也會(huì)隨著改變,selectedValues里的數(shù)據(jù)是直接引用屬性值而不是拷貝一份數(shù)據(jù)逸雹,所以修改selectedValues中的數(shù)據(jù)也會(huì)直接反映到屬性值上营搅,實(shí)現(xiàn)了屬性值的自定義。

那么怎么根據(jù)選中的屬性值生成SKU呢梆砸?
SKU表格處的表頭是要根據(jù)選中的屬性動(dòng)態(tài)更新的转质,可以這樣做

<tr>
      <th v-for="item in properties" v-if="item.selectedValues.length>0">{{item.Name}}</th>
      <th><span class="c_red">*</span>零售價(jià)</th>
      <th><span class="c_red">*</span>庫(kù)存</th>
      <th>商品編碼</th>
 </tr>

如果屬性里的屬性值都沒(méi)有被選中(selectedValues.length==0),就不在表頭顯示這個(gè)屬性帖世。

SKU的初始顯示

<tr v-for="sku in skus">
        <td v-for="item in properties" v-if="item.selectedValues.length>0">{{getValueName(sku,item)}}</td>
        <td>US $<input type="text" v-model="sku.SkuPrice" class="w50" maxlength="9"/><span name="productUnitTips"></span></td>
        <td><input type="text" v-model="sku.StockQuantity" class="w50" maxlength="9"/></td>
        <td><input type="text" v-model="sku.SkuCode" class="w180" maxlength="20"/></td>
</tr>

也是利用selectedValues.length讓SKU的屬性值列數(shù)與表頭列數(shù)保持一致休蟹。因?yàn)镾KU對(duì)象里的保存的是屬性值Id和屬性Id,需要一個(gè)方法去獲取屬性值的值

getValueName: function (sku, property) {
                var valueName = "";
                $.each(sku.values,
                        function () {
                            var _this = this;
                            if (this.propertyId == property.Id) {
                                $.each(property.selectedValues, function () {
                                    if (_this.valueId == this.Id) {
                                        valueName = this.Name;
                                        return false;
                                    }
                                });
                            }
                        });
                return valueName;

            }

你沒(méi)有看錯(cuò),這是JQ日矫。赂弓。。

接下來(lái)就是SKU表格的更新了哪轿,我的做法是變更整塊區(qū)域盈魁,就是給skus重新賦值。賦的新值從哪來(lái)呢窃诉?

將選中的屬性值放到一個(gè)數(shù)組中

               var ori = [];
                $.each(vm.properties,
                        function (index, item) {
                            var selectValues = this.selectedValues;
                            if (selectValues.length > 0) {
                                ori.push(selectValues);
                            }
                        });

得到這種結(jié)構(gòu)的數(shù)組

[
  [
    {
      'PropertyId': 10,
      'Id': 477,
      'Name': '鋁',
      'DefinitionName': '',
      'ImageUrl': ''
    },
    {
      'PropertyId': 10,
      'Id': 529,
      'Name': '帆布',
      'DefinitionName': '',
      'ImageUrl': ''
    }
  ],
  [
    {
      'PropertyId': 200000828,
      'Id': 201655809,
      'Name': '殼+貼膜',
      'DefinitionName': '',
      'ImageUrl': ''
    },
    {
      'PropertyId': 200000828,
      'Id': 201655810,
      'Name': '殼+掛繩',
      'DefinitionName': '',
      'ImageUrl': ''
    }
  ]
]

求笛卡爾積后(后面有求笛卡爾積參考鏈接)

var ret = descartes(ori);
[
  [
    {
      'PropertyId': 10,
      'Id': 477,
      'Name': '鋁',
      'DefinitionName': '',
      'ImageUrl': ''
    },
    {
      'PropertyId': 200000828,
      'Id': 201655809,
      'Name': '殼+貼膜',
      'DefinitionName': '',
      'ImageUrl': ''
    }
  ],
  [
    {
      'PropertyId': 10,
      'Id': 477,
      'Name': '鋁',
      'DefinitionName': '',
      'ImageUrl': ''
    },
    {
      'PropertyId': 200000828,
      'Id': 201655810,
      'Name': '殼+掛繩',
      'DefinitionName': '',
      'ImageUrl': ''
    }
  ],
  [
    {
      'PropertyId': 10,
      'Id': 529,
      'Name': '帆布',
      'DefinitionName': '',
      'ImageUrl': ''
    },
    {
      'PropertyId': 200000828,
      'Id': 201655809,
      'Name': '殼+貼膜',
      'DefinitionName': '',
      'ImageUrl': ''
    }
  ],
  [
    {
      'PropertyId': 10,
      'Id': 529,
      'Name': '帆布',
      'DefinitionName': '',
      'ImageUrl': ''
    },
    {
      'PropertyId': 200000828,
      'Id': 201655810,
      'Name': '殼+掛繩',
      'DefinitionName': '',
      'ImageUrl': ''
    }
  ]
]

大前端也用上了算法有木有杨耙,這里需要弄明白拿到的是什么數(shù)據(jù)赤套,需要的是什么數(shù)據(jù),然后就去想實(shí)現(xiàn)就OK了珊膜。
想要的數(shù)據(jù)已經(jīng)拿到容握,重新構(gòu)建skus

         for (var i = 0; i < ret.length; i++) {
                    var sku = {SkuCode: "", SkuPrice: "", StockQuantity: ""};
                    sku.values = [];
                    $.each(ret[i],
                            function () {
                                sku.values.push({propertyId: this.PropertyId, valueId: this.Id});
                            });
                    vmSkus.push(sku);
            }

到此,更新SKU表格的代碼已經(jīng)實(shí)現(xiàn)车柠,數(shù)據(jù)驅(qū)動(dòng)視圖更新剔氏,很清晰。但是什么時(shí)候去觸發(fā)這個(gè)更新呢(何時(shí)去重新構(gòu)建skus)? 很簡(jiǎn)單嘛竹祷,就是勾選或取消勾選屬性值的時(shí)候去觸發(fā)更新操作谈跛。勾選或取消勾選我們能直接從selectedValues.length上得到反饋,然后使用vue 的watch就可以實(shí)現(xiàn)了溶褪。但是selectedValues是properties數(shù)組中元素的一個(gè)屬性币旧,vue的watch是無(wú)法用在數(shù)組元素的某一個(gè)字段上的(至少目前我發(fā)現(xiàn)是這樣的)践险,那么暴力一點(diǎn)猿妈,直接watch整個(gè)properties數(shù)組并且加上deep:true。這樣是可以實(shí)現(xiàn)巍虫,但是當(dāng)修改自定義屬性的時(shí)候也會(huì)觸發(fā)變更(業(yè)務(wù)會(huì)提刀來(lái)見(jiàn)的)彭则。

最終解決方案

computed:{
            allCheckedLength:function(){
               var length=0;
                $.each(this.properties,function(){
                    length+=this.selectedValues.length;
                });
               return length;
            }
  }
watch: {
            'allCheckedLength': {
                handler: 'reBuild'
            }
        }

reBuild就是重新構(gòu)建的方法。

demo

Java 笛卡爾積算法的簡(jiǎn)單實(shí)現(xiàn)
Cartesian product of multiple arrays in JavaScript

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末占遥,一起剝皮案震驚了整個(gè)濱河市俯抖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瓦胎,老刑警劉巖芬萍,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異搔啊,居然都是意外死亡柬祠,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)负芋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)漫蛔,“玉大人,你說(shuō)我怎么就攤上這事旧蛾∶Ч辏” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵锨天,是天一觀的道長(zhǎng)毯盈。 經(jīng)常有香客問(wèn)我,道長(zhǎng)病袄,這世上最難降的妖魔是什么搂赋? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任迟赃,我火速辦了婚禮,結(jié)果婚禮上厂镇,老公的妹妹穿的比我還像新娘纤壁。我一直安慰自己,他們只是感情好捺信,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布酌媒。 她就那樣靜靜地躺著,像睡著了一般迄靠。 火紅的嫁衣襯著肌膚如雪秒咨。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,760評(píng)論 1 289
  • 那天掌挚,我揣著相機(jī)與錄音雨席,去河邊找鬼。 笑死吠式,一個(gè)胖子當(dāng)著我的面吹牛陡厘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播特占,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼糙置,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了是目?” 一聲冷哼從身側(cè)響起谤饭,我...
    開(kāi)封第一講書(shū)人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎懊纳,沒(méi)想到半個(gè)月后揉抵,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嗤疯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年冤今,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片身弊。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡辟汰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出阱佛,到底是詐尸還是另有隱情帖汞,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布凑术,位于F島的核電站翩蘸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏淮逊。R本人自食惡果不足惜催首,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一扶踊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧郎任,春花似錦秧耗、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至霉猛,卻和暖如春尺锚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背惜浅。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工瘫辩, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人坛悉。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓伐厌,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親吹散。 傳聞我的和親對(duì)象是個(gè)殘疾皇子弧械,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 每天逛淘寶和京東的時(shí)候八酒,映入眼簾的都是品類繁多的商品空民,但是當(dāng)我們選擇分類或者直接搜索的時(shí)候,按條件篩選時(shí)羞迷,系統(tǒng)卻往...
    自媒體_鄭在別處閱讀 16,684評(píng)論 2 77
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,742評(píng)論 25 707
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理界轩,服務(wù)發(fā)現(xiàn),斷路器衔瓮,智...
    卡卡羅2017閱讀 134,628評(píng)論 18 139
  • 帥_0452閱讀 146評(píng)論 0 0
  • 也許是射手座天生愛(ài)自由浊猾,也許是我太沒(méi)責(zé)任感,總而言之热鞍,我真的好怕被一個(gè)事情長(zhǎng)久的束縛葫慎。 從銀行離開(kāi),許多人都說(shuō)佩服...
    雪靈溪閱讀 491評(píng)論 1 2