首先说一说什么是SKU。。。。。。。自己百度去。。。

类似京东上面,未来人类S5这个台笔记本(没错,我刚入手了)

都是S5这个型号,但是因为CPU,显卡,内存,硬盘等不同,价格也不一样。CPU,显卡,内存,硬盘等属性组合成的一个唯一的商品,就可以用一个SKU来表示,像图上就有10个SKU。一系列的SKU可以归到一个SPU下进行管理。

那么一个SKU是怎么生成的呢?下面结合自己的一些经验,说说一些电商平台的大致产品结构以及SKU的生成方式。

1.阿里速卖通平台,阿里国际站

这两个平台同一个爸爸,基本差不多。要创建一个商品需要先选一个类目,类目下面挂了一堆的属性,属性上又挂了一堆的属性值。属性分为销售属性和非销售属性(销售属性就是类似颜色,尺寸这些单个SKU独有的,非销售属性就是多个SKU共有的,比如同一个品牌型号“未来人类S5”)。非销售属性有必填和非必填,可以是单选,多选,文本等。销售属性就是构成SKU的关键。比如说有销售属性颜色和尺寸,颜色属性下有很多属性值(红,黄,蓝等等),尺寸(1,2,3,4等等)也是。当颜色选了红,黄,尺寸选了1,2,那么就应该生成2x2=4个SKU,每个SKU有各自的价格,库存等。保存SKU的时候会与对应的销售属性相关联。
大致的数据模型如下

当然,实际比这更加复杂(比如产品的图片,单个SKU的图片,多个SKU共同的图片,非销售属性可以自定义添加分类不具有的。。。)

2.eBay
跟上面两个平台类似,创建一个产品也要先选一个分类,分类下面也是有很多属性,属性有很多属性值。。。,不同的地方是eBay没有区分销售属性和非销售属性(或者说全部是非销售属性),也允许添加自定义属性和属性值。eBay上SKU是手动添加的,SKU上的属性(SKU上的属性暂且都叫做销售属性)也是自定义的。比如说添加了一个SKU A,价格和数量这两个是必须的,还可以手动加个颜色属性,然后填上属性值红色。当然,若果增加一个SKU B,那么这个SKU也会有颜色这个属性,属性值可以自定义。最后校验这些SKU的属性值组合起来是否唯一。

这样的优势就是可以随意控制SKU的数量,如果按照上面两个平台的规则,这里应该有4x4x1=16个SKU。这样自由度更高会不会使结构更加复杂呢?当然是NO,用上面的数据模型就可以搞定

3.Lazada,Linio平台
国际惯例,先选一个类目,类目下面一堆属性,有必填和非必填,属性下一堆属性值。最大的区别就是,一个产品只有一个SKU,属性不支持自定义。比如说要添加一个商品,有两种颜色,那么只能创建两个产品,这两个产品可能只有图片不一样(颜色不一样,可能没有颜色这个属性来选)

4.Wish平台
比较奇特,没有分类,产品有固定的属性,比如标题,描述,运费等。一个产品下可以有多个SKU,SKU的生成取决于固定的两大类属性,两个大类为:颜色和尺寸。比如颜色这个属性就是归类于颜色这个类,其他的属性(品牌,型号,容量等等归为尺寸这个大类)。尺寸类的属性值支持自定义,但只能选一个尺寸类属性(比如选了品牌就不能选容量,选了品牌后可以添加任意值)。两类属性不是必须同时存在,比如颜色选了红,可以不选尺寸类的属性,反之也一样。

忘记说了,一个SKU是靠一串唯一编码来标识的,比如1234A,1234B。一般来说一个平台下不会存在两个相同的SKU,或这一个店铺下不会存在两个相同的SKU。

大致的逻辑和数据模型就这些,接下来说说开发实现方面。

数据库大致就依靠上面的数据模型进行设计,编辑的时候,后端按照这些关联关系取出数据给到前端(我这边前后端未分离,页面还是后端渲染,但我还是把数据格式化为JSON再渲染到前端),保存的时候再进行相关的逻辑校验。因为后端的一些逻辑操作涉及后公司内部的业务,这里就不细说了。说说前端的具体细节,以速卖通的为例,用的是vue,前端拿到的数据如下

实现后的粗糙界面

  1. data: {
  2. properties: properties,
  3. skus: skus
  4. }

遍历properties,得到材质,颜色,发货地,套餐这些属性对象,接着遍历这些对象里的values属性,得到属性值对象,根据属性对象的selectedValues判断属性值是否选上(因为我是后端渲染的js变量,所以初始化的时候selectedValues里的数据直接引用的属性值对象,如果是非后端渲染的话,要根据skus里的属性和属性值去初始化selectedValues的数据,并且存的是属性值对象的引用)

  1. <tr v-for="(index,item) in properties">
  2. <td><strong>{{item.Name}}:</strong></td>
  3. <td>
  4. <label v-for="value in item.values"><input type="checkbox" :value="value" v-model="item.selectedValues"/>{{value.Name}}</label>
  5. <table class="list_table" v-if="item.Name!='发货地'&&item.selectedValues.length>0">
  6. <tbody>
  7. <tr>
  8. <th>{{item.Name}}</th>
  9. <th>自定义名称</th>
  10. <th v-if="item.Name=='颜色'">图片(无图片可以不填)</th>
  11. </tr>
  12. <tr v-for="selectedValue in item.selectedValues">
  13. <td>{{selectedValue.Name}}</td>
  14. <td>
  15. <input type="text" v-model="selectedValue.DefinitionName" maxlength="20"/>
  16. </td>
  17. <td v-if="item.Name=='颜色'">
  18. <div style="float: left">
  19. <input type="file" style="width: 63px;"/>
  20. </div>
  21. <div style="float: right">
  22. <a href="" rel="link" target="_blank">
  23. <img :src="selectedValue.ImageUrl" width="30" height="35"/>
  24. </a>
  25. </div>
  26. </td>
  27. </tr>
  28. </tbody>
  29. </table>
  30. </td>
  31. </tr>

因为selectedValues通过v-model绑定,当选中或取消一个属性值的时候后,selectedValues也会随着改变,selectedValues里的数据是直接引用属性值而不是拷贝一份数据,所以修改selectedValues中的数据也会直接反映到属性值上,实现了属性值的自定义。

那么怎么根据选中的属性值生成SKU呢?
SKU表格处的表头是要根据选中的属性动态更新的,可以这样做

  1. <tr>
  2. <th v-for="item in properties" v-if="item.selectedValues.length>0">{{item.Name}}</th>
  3. <th><span class="c_red">*</span>零售价</th>
  4. <th><span class="c_red">*</span>库存</th>
  5. <th>商品编码</th>
  6. </tr>

如果属性里的属性值都没有被选中(selectedValues.length==0),就不在表头显示这个属性。

SKU的初始显示

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

也是利用selectedValues.length让SKU的属性值列数与表头列数保持一致。因为SKU对象里的保存的是属性值Id和属性Id,需要一个方法去获取属性值的值

  1. getValueName: function (sku, property) {
  2. var valueName = "";
  3. $.each(sku.values,
  4. function () {
  5. var _this = this;
  6. if (this.propertyId == property.Id) {
  7. $.each(property.selectedValues, function () {
  8. if (_this.valueId == this.Id) {
  9. valueName = this.Name;
  10. return false;
  11. }
  12. });
  13. }
  14. });
  15. return valueName;
  16. }

你没有看错,这是JQ。。。

接下来就是SKU表格的更新了,我的做法是变更整块区域,就是给skus重新赋值。赋的新值从哪来呢?

将选中的属性值放到一个数组中

  1. var ori = [];
  2. $.each(vm.properties,
  3. function (index, item) {
  4. var selectValues = this.selectedValues;
  5. if (selectValues.length > 0) {
  6. ori.push(selectValues);
  7. }
  8. });

得到这种结构的数组

  1. [
  2. [
  3. {
  4. 'PropertyId': 10,
  5. 'Id': 477,
  6. 'Name': '铝',
  7. 'DefinitionName': '',
  8. 'ImageUrl': ''
  9. },
  10. {
  11. 'PropertyId': 10,
  12. 'Id': 529,
  13. 'Name': '帆布',
  14. 'DefinitionName': '',
  15. 'ImageUrl': ''
  16. }
  17. ],
  18. [
  19. {
  20. 'PropertyId': 200000828,
  21. 'Id': 201655809,
  22. 'Name': '壳+贴膜',
  23. 'DefinitionName': '',
  24. 'ImageUrl': ''
  25. },
  26. {
  27. 'PropertyId': 200000828,
  28. 'Id': 201655810,
  29. 'Name': '壳+挂绳',
  30. 'DefinitionName': '',
  31. 'ImageUrl': ''
  32. }
  33. ]
  34. ]

求笛卡尔积后(后面有求笛卡尔积参考链接)

  1. var ret = descartes(ori);
  1. [
  2. [
  3. {
  4. 'PropertyId': 10,
  5. 'Id': 477,
  6. 'Name': '铝',
  7. 'DefinitionName': '',
  8. 'ImageUrl': ''
  9. },
  10. {
  11. 'PropertyId': 200000828,
  12. 'Id': 201655809,
  13. 'Name': '壳+贴膜',
  14. 'DefinitionName': '',
  15. 'ImageUrl': ''
  16. }
  17. ],
  18. [
  19. {
  20. 'PropertyId': 10,
  21. 'Id': 477,
  22. 'Name': '铝',
  23. 'DefinitionName': '',
  24. 'ImageUrl': ''
  25. },
  26. {
  27. 'PropertyId': 200000828,
  28. 'Id': 201655810,
  29. 'Name': '壳+挂绳',
  30. 'DefinitionName': '',
  31. 'ImageUrl': ''
  32. }
  33. ],
  34. [
  35. {
  36. 'PropertyId': 10,
  37. 'Id': 529,
  38. 'Name': '帆布',
  39. 'DefinitionName': '',
  40. 'ImageUrl': ''
  41. },
  42. {
  43. 'PropertyId': 200000828,
  44. 'Id': 201655809,
  45. 'Name': '壳+贴膜',
  46. 'DefinitionName': '',
  47. 'ImageUrl': ''
  48. }
  49. ],
  50. [
  51. {
  52. 'PropertyId': 10,
  53. 'Id': 529,
  54. 'Name': '帆布',
  55. 'DefinitionName': '',
  56. 'ImageUrl': ''
  57. },
  58. {
  59. 'PropertyId': 200000828,
  60. 'Id': 201655810,
  61. 'Name': '壳+挂绳',
  62. 'DefinitionName': '',
  63. 'ImageUrl': ''
  64. }
  65. ]
  66. ]

大前端也用上了算法有木有,这里需要弄明白拿到的是什么数据,需要的是什么数据,然后就去想实现就OK了。
想要的数据已经拿到,重新构建skus

  1. for (var i = 0; i < ret.length; i++) {
  2. var sku = {SkuCode: "", SkuPrice: "", StockQuantity: ""};
  3. sku.values = [];
  4. $.each(ret[i],
  5. function () {
  6. sku.values.push({propertyId: this.PropertyId, valueId: this.Id});
  7. });
  8. vmSkus.push(sku);
  9. }

到此,更新SKU表格的代码已经实现,数据驱动视图更新,很清晰。但是什么时候去触发这个更新呢(何时去重新构建skus)? 很简单嘛,就是勾选或取消勾选属性值的时候去触发更新操作。勾选或取消勾选我们能直接从selectedValues.length上得到反馈,然后使用vue 的watch就可以实现了。但是selectedValues是properties数组中元素的一个属性,vue的watch是无法用在数组元素的某一个字段上的(至少目前我发现是这样的),那么暴力一点,直接watch整个properties数组并且加上deep:true。这样是可以实现,但是当修改自定义属性的时候也会触发变更(业务会提刀来见的)。

最终解决方案

  1. computed:{
  2. allCheckedLength:function(){
  3. var length=0;
  4. $.each(this.properties,function(){
  5. length+=this.selectedValues.length;
  6. });
  7. return length;
  8. }
  9. }
 
  1. watch: {
  2. 'allCheckedLength': {
  3. handler: 'reBuild'
  4. }
  5. }

reBuild就是重新构建的方法。

一个商品SKU是怎么生成的的更多相关文章

  1. 工具类:每次随机生成有销售库存有实际库存的1个店铺商品和对应的2个店铺商品sku

    # coding:utf-8 # @fileName :2.每次随机生成有销售库存有实际库存的1个店铺商品和对应的2个店铺商品sku.py # @createTime :2020/4/4 10:33 ...

  2. B2C电子商务系统研发——商品SKU分析和设计(一)

    一.SKU及相关概念定义 在设计商品SKU之前,首先让我们熟悉一下SKU和相关的一些概念. # 什么是SKU: SKU=Stock Keeping Unit(库存量单位) 同一型号的商品,或者说是同一 ...

  3. B2C电子商务系统研发——商品SKU分析和设计(二)

    转:http://www.cnblogs.com/winstonyan/archive/2012/01/07/2315886.html 上文谈到5种商品SKU设计模式,本文将做些细化说明. 笔者研究过 ...

  4. vue+element 实现商品sku效果

    在网上搜索了很久,没有发现合适sku编辑的文章,只能自己写一个vue+element 的sku编辑功能.实现的效果如下图 除成本.售价.库存.货号这几个写死的属性外,可自行添加/删除商品属性,自行添加 ...

  5. 电商ERP系统——商品SKU与库存设计

    面试题经常问道,如何设计库存,哪些库存呢?分类属性的库存:不同颜色 不同尺码的属性的库存,这时候需要针对具体的SKU商品创建表. 总体思路 1.商品关联商品类别,商品类别关联多个商品属性,其中指定某几 ...

  6. 商品sku规格选择效果,没有商品的不能选中,选择顺序不影响展示结果

    <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...

  7. jquery实现商品sku多属性选择(商品详情页)

    转载于https://blog.csdn.net/csdn924618338/article/details/51455595 实现效果 源码 <!DOCTYPE HTML> <ht ...

  8. JSON C# Class Generator是一个从JSON文本中生成C#内的应用程序

    JSON C# Class Generator是一个从JSON文本中生成C#内的应用程序 .NET平台开源项目速览(18)C#平台JSON实体类生成器JSON C# Class Generator   ...

  9. 商品sku的排列组合

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

随机推荐

  1. 移植MonkeyRunner的图片对照和获取子图功能的实现-UiAutomator/Robotium篇

    依据前一篇文章<移植MonkeyRunner的图片对照和获取子图功能的实现-Appium篇>所述,由于Appium和MonkeyRunner有一个共同点--代码控制流程都是在client实 ...

  2. 测试整合之王Unitils

    16.4.1  Unitils概述(1) Unitils测试框架目的是让单元测试变得更加容易和可维护.Unitils构建在DbUnit与EasyMock项目之上并与JUnit和TestNG相结合.支持 ...

  3. div下拉框(待改善)

    不说话,直接上代码,其中函数dealchose()没有实现,各位就不必纠结了 <%@ page language="java" import="java.util. ...

  4. javascript---》Fcuntion对象

    Function 对象的valueOf() 和 toString() 方法.返回函数的源代码,调试时有用 Function 对象的 length 属性返回函数期望的参数个数------>接受任意 ...

  5. java:注解(一)

    什么是注解 注解(Annotation),也叫(metadata)元数据.一种代码级别的说明.它是JDK1.5及以后版本引入的一个特性,与类.接口.枚举是在同一个层次.它可以声明在包.类.字段.方法. ...

  6. 算法 Heap sort

    // ------------------------------------------------------------------------------------------------- ...

  7. SQL检索语句及过滤语句

    首先推荐一款比较好用的数据库管理软件:navicat premium. 数据库中最重要的检索功能:SELECT语句 1.检索单个列:select 列名 from 表名: 2.检索多个列:select ...

  8. 自己编译GCC(compile gcc from source)

    有的时候,我不是第一次遇到这种时候,编译内核时报出编译器BUG.如果是ubuntu还好一点,默认软件仓库中就有好几个GCC,换一换总能找到一个好使的,实在不行还有个Tooltrain的ppa,但Deb ...

  9. java操作pdf

    使用pdf模板生成pdf 1,工具 Adobe Acrobat X Pro 2,pom文件配置 <dependency> <groupId>com.itextpdf</g ...

  10. 过滤XSS的HTMLPurifier使用

    什么是HTMLPurifier? 在php里解决XSS最简单的方法是使用htmlspecialchars转义xml实体,但对于需要使用xml的时候就搏手无策了. HTML Purifier是基于php ...