sku(Stock Keeping Unit 库存量单位)即库存进出计量的基本单元,购物类项目在下单是需要选择不同的商品规格,同时查询有没有库存。思路参考淘宝sku算法浅析,使用了provider作为状态管理。
后台数据
{
"skus": [
{"sku": "5.5寸;16G;红色", "color": Colors.red, "price": 101, "count": 10},
{"sku": "5.5寸;16G;黄色", "color": Colors.yellow, "price": 102, "count": 1},
{"sku": "5.5寸;32G;黑色", "color": Colors.black, "price": 103, "count": 6},
{"sku": "5.5寸;32G;红色", "color": Colors.red, "price": 104, "count": 0},
{"sku": "5.5寸;32G;黄色", "color": Colors.yellow, "price": 105, "count": 0},
{"sku": "4.7寸;16G;黑色", "color": Colors.black, "price": 106, "count": 16},
{"sku": "4.7寸;16G;红色", "color": Colors.red, "price": 107, "count": 17},
{"sku": "4.7寸;16G;黄色", "color": Colors.yellow, "price": 108, "count": 18},
{"sku": "4.7寸;32G;黑色", "color": Colors.black, "price": 109, "count": 0},
{"sku": "4.7寸;32G;红色", "color": Colors.red, "price": 110, "count": 20},
{"sku": "4.7寸;32G;黄色", "color": Colors.yellow, "price": 111, "count": 21},
{"sku": "6.0寸;16G;黑色", "color": Colors.black, "price": 112, "count": 0},
{"sku": "6.0寸;16G;红色", "color": Colors.red, "price": 113, "count": 23},
{"sku": "6.0寸;16G;黄色", "color": Colors.yellow, "price": 114, "count": 24},
{"sku": "6.0寸;32G;黑色", "color": Colors.black, "price": 115, "count": 0},
{"sku": "6.0寸;32G;红色", "color": Colors.red, "price": 116, "count": 26},
{"sku": "6.0寸;32G;黄色", "color": Colors.yellow, "price": 117, "count": 27}
],
"goods": [
{
"name": "尺寸",
"items": ["5.5寸", "4.7寸", "6.0寸"]
},
{
"name": "内存",
"items": ["16G", "32G"]
},
{
"name": "颜色",
"items": ["黑色", "红色", "黄色"]
}
]
}
sku算法
class SkuUtil {
/**
* 算法入口
*
* @param initData 所有库存的hashMap组合
* @return 拆分所有组合产生的所有情况(生成客户端自己的字典)
*/
static Map skuCollection(Map initData) {
//用户返回数据
Map result = new Map();
// 遍历所有库存
for (var subKey in initData.keys) {
SkuModel skuModel = initData[subKey];
// print(">>>>subKey:" + subKey);
//根据;拆分key的组合
List skuKeyAttrs = subKey.split(";");
//获取所有的组合
List> combArr = combInArray(skuKeyAttrs);
// print("combArr+>>>:" + combArr.toString());
// 对应所有组合添加到结果集里面
for (int i = 0; i < combArr.length; i++) {
add2SKUResult(result, combArr[i], skuModel);
}
// 将原始的库存组合也添加进入结果集里面
String key = join(";", skuKeyAttrs);
result[key] = skuModel;
}
return result;
}
static String join(String delimiter, List tokens) {
StringBuffer sb = StringBuffer();
bool firstTime = true;
for (var token in tokens) {
if (firstTime) {
firstTime = false;
} else {
sb.write(delimiter);
}
sb.write(token);
}
return sb.toString();
}
/**
* 获取所有的组合放到ArrayList里面
*
* @param skuKeyAttrs 单个key被; 拆分的数组
* @return ArrayList
*/
static List> combInArray(List skuKeyAttrs) {
if (skuKeyAttrs == null || skuKeyAttrs.length <= 0) return null;
int len = skuKeyAttrs.length;
List> aResult = List>();
for (int n = 1; n < len; n++) {
List> aaFlags = getCombFlags(len, n);
for (int i = 0; i < aaFlags.length; i++) {
List aFlag = aaFlags[i];
List aComb = new List();
for (int j = 0; j < aFlag.length; j++) {
if (aFlag[j] == 1) {
aComb.add(skuKeyAttrs[j]);
}
}
aResult.add(aComb);
}
}
return aResult;
}
/**
* 算法拆分组合 用1和0 的移位去做控制
* (这块需要你打印才能看的出来)
*
* @param len
* @param n
* @return
*/
static List> getCombFlags(int len, int n) {
if (n <= 0) {
return new List>();
}
List> aResult = List>();
List aFlag = List(len);
bool bNext = true;
int iCnt1 = 0;
//初始化
for (int i = 0; i < len; i++) {
aFlag[i] = i < n ? 1 : 0;
}
aResult.add(List.from(aFlag));
while (bNext) {
iCnt1 = 0;
for (int i = 0; i < len - 1; i++) {
if (aFlag[i] == 1 && aFlag[i + 1] == 0) {
for (int j = 0; j < i; j++) {
aFlag[j] = j < iCnt1 ? 1 : 0;
}
aFlag[i] = 0;
aFlag[i + 1] = 1;
List aTmp = List.from(aFlag);
aResult.add(aTmp);
if (!join("", aTmp).substring(len - n).contains("0")) {
bNext = false;
}
break;
}
if (aFlag[i] == 1) {
iCnt1++;
}
}
}
return aResult;
}
/**
* 添加到数据集合
*
* @param result
* @param newKeyList
* @param skuModel
*/
static void add2SKUResult(Map result, List newKeyList, SkuModel skuModel) {
// print("--->>>>newKeyList" + newKeyList.toString());
String key = join2(";", newKeyList);
// print("key: " + key);
if (result.keys.contains(key)) {
result[key].price = skuModel.price;
result[key].sku = skuModel.sku;
result[key].price = skuModel.price;
result[key].color = skuModel.color;
result[key].count = result[key].count + skuModel.count;
} else {
result[key] =
SkuModel(price: skuModel.price, color: skuModel.color, count: skuModel.count, sku: skuModel.sku);
}
// print("result:>>" + result.toString());
}
static String join2(String delimiter, Iterable tokens) {
StringBuffer sb = StringBuffer();
var it = tokens.iterator;
if (it.moveNext()) {
sb.write(it.current);
while (it.moveNext()) {
sb.write(delimiter);
sb.write(it.current);
}
}
return sb.toString();
}
}
大概就是把规格拆分组合成各种规则,存到map作为key,value就是规则对应的商品价格数量颜色等,这样点击按钮是去mac中找,没有找到或者库存为0,按钮不可点击。
组成的各种key
项目地址FlutterSkuDemo