Flutter SKU多规格商品选择器核心工具

        因为flutter刚兴起,然后很多插件虽然是一直在新增,但是还是很多插件没有,或者还是在测试版,没有正式版,于是只能自己撸一个了。

首先看看我们某个商品数据结构:

{
  "attributes": [],
  "goods_id": 1636,
  "goods_name": "珍珠奶茶",
  "image": "http://********/static/goods_images/Rlp6d1536542627.png",
  "multi_spec": [
    {
      "image": "http://********/static/goods_images/EQqf01536544612.png",
      "product_code": "",
      "sales_amount": 45,
      "spec_info_list": [
        {
          "spec_name": "规格",
          "spec_name_id": 336,
          "spec_value": "大杯",
          "spec_value_id": 1019
        },
        {
          "spec_name": "颜色",
          "spec_name_id": 337,
          "spec_value": "红色",
          "spec_value_id": 1021
        },
        {
          "spec_name": "重量",
          "spec_name_id": 338,
          "spec_value": "半斤",
          "spec_value_id": 1023
        }
      ],
      "specification_id": 1918,
      "stock": -1,
      "unit": "杯",
      "unit_price": 7
    },
    {
      "image": "http://********/static/goods_images/Fe30S1536544637.png",
      "product_code": "",
      "sales_amount": 16,
      "spec_info_list": [
        {
          "spec_name": "规格",
          "spec_name_id": 336,
          "spec_value": "中杯",
          "spec_value_id": 1020
        },
        {
          "spec_name": "颜色",
          "spec_name_id": 337,
          "spec_value": "绿色",
          "spec_value_id": 1022
        },
        {
          "spec_name": "重量",
          "spec_name_id": 338,
          "spec_value": "一斤",
          "spec_value_id": 1024
        }
      ],
      "specification_id": 1919,
      "stock": -1,
      "unit": "杯",
      "unit_price": 6
    },
    {
      "image": "http://********/static/goods_images/Fe30S1536544637.png",
      "product_code": "",
      "sales_amount": 16,
      "spec_info_list": [
        {
          "spec_name": "规格",
          "spec_name_id": 336,
          "spec_value": "中杯",
          "spec_value_id": 1020
        },
        {
          "spec_name": "颜色",
          "spec_name_id": 337,
          "spec_value": "红色",
          "spec_value_id": 1021
        },
        {
          "spec_name": "重量",
          "spec_name_id": 338,
          "spec_value": "一斤",
          "spec_value_id": 1024
        }
      ],
      "specification_id": 1919,
      "stock": -1,
      "unit": "杯",
      "unit_price": 6
    }
  ],
  "pack_cost": 0,
  "product_code": null,
  "sales_amount": 61,
  "stock": -2,
  "unit": null,
  "unit_price": null
}

multi_spec字段下就是这商品的所有规格搭配,spec_info_list字段下为组成该搭配的各规格值。
我们给分别给规格搭配和组成规格搭配的规格值做了 model :

///商品规格搭配,对应multi_spec的元素
class ShopGoodsMultiSpec {
    String image;
    String unit;
    int specificationId;
    List<ShopGoodsMultiSpecSpecInfo> specInfoList;
    int salesAmount;
    String productCode;
    int stock;
    double unitPrice;
 ///构造函数什么的省略.....
}
///组成规格搭配的规格值,对应spec_info_list的元素
class ShopGoodsMultiSpecSpecInfo {
    int specValueId;
    int specNameId;
    String specName;
    String specValue;
///构造函数什么的省略.....
}
贴上工具代码:
class SpecSkuUtil {
  List<String> allSpecKey = [];
  Map<String, ShopGoodsMultiSpec> allSpec = {};
  Map<String, Map<String, int>> allSpecValue = {};
  List<int> selectedIds = [];

  /// 实例化工具,传入所有规格搭配 list
  SpecSkuUtil(List<ShopGoodsMultiSpec> multiSpec) {
    for (ShopGoodsMultiSpec spec in multiSpec) {
      List valueIds = [];
      for (ShopGoodsMultiSpecSpecInfo spec_info in spec.specInfoList) {
        valueIds.add(spec_info.specValueId);
        allSpecValue.containsKey(spec_info.specName)
            ? allSpecValue[spec_info.specName][spec_info.specValue] = spec_info.specValueId
            : allSpecValue[spec_info.specName] = {spec_info.specValue:spec_info.specValueId};
      }
      valueIds.sort((a, b) => a.compareTo(b));
      valueIds = valueIds.map((id) {
        return id.toString();
      }).toList();
      allSpec[valueIds.join("-")] = spec;
      _createCollocations(valueIds);
    }
  }

  void _createCollocations(List strList) {
    void build(List candidate, String prefix, int index) {
      if (!allSpecKey.contains(prefix)) {
        allSpecKey.add(prefix);
      }
      for (int i = index; i < candidate.length; i++) {
        List tmp = new List()..addAll(candidate);
        build(tmp, (prefix == "" ? "" : prefix + "-") + tmp.removeAt(i), i);
      }
    }

    build(strList, "", 0);
  }

  /// 返回所有{规格名:{规格值:规格值 id}}
  Map<String, Map<String, int>> getAllSpecValue() {
    return allSpecValue;
  }

  /// 设置已选中的 规格值 id list
  void setSelectedIds(List<int> selectedIds) {
    this.selectedIds = selectedIds;
  }

  /// 检查某属性是否可选
  bool checkEnable(int id) {
    List tmp = List.from(selectedIds)..add(id);
    tmp.sort((a, b) => a.compareTo(b));
    return allSpecKey.contains(tmp.join("-"));
  }

  /// 获取规格搭配对象
  ShopGoodsMultiSpec getSpec() {
    selectedIds.sort((a, b) => a.compareTo(b));
    return allSpec[selectedIds.join("-")];
  }
}

核心原理就是,每个规格搭配下的规格值的任意 不重复使用元素 的无序组合 都能代表该规格搭配。
如:

a,b,c  能够生成的组合就是 [a, b, c, ab, ac, bc, abc]
那么,如果我们把每个规格搭配下的规格值的任意不重复使用元素的无序组合都收集在一个list (这里叫它allSpecKey) 中,我们在校验某个规格值是否可选时,只需要把已选择的规格值和待选择的规格值组合起来,然后判断这个组合是否在allSpecKey中就可确定待选择的规格值是否可选。
那么 在渲染每一个规格值按钮组件时,只需要调用checkEnable方法,就可以检查是否可选,getSpec方法可以在选择完一个规格搭配后拿取过个搭配对象。如果没选择完的话,返回的是 null,刚刚方便识别是否有选择完成。当然,每次选中一个规格值时一定要执行setSelectedIds设置一下已经选中的属性值列表。

本博客所有文章如无特别注明均为原创。作者:flutter教程网复制或转载请以超链接形式注明转自 Flutter教程网
原文地址《Flutter SKU多规格商品选择器核心工具
分享到:更多

相关推荐



Flutter教程网 官方QQ群:874592746

扫描下面二维码 加入Flutter教程网微信群:


关注公众号“Flutter前线”,各种Flutter项目实战经验技巧,干活知识,Flutter面试题答案,等你来领取。


发表评论

路人甲 表情
Ctrl+Enter快速提交

网友评论(1)

感谢您为大家分享Flutter相关资源,但请注明教程原作者和原文链接
CyJay 1年前 (2019-03-25) 回复