阅读 189

SKU实现 记录一下

SKU实现 记录一下吧 免得以后有用又忘记了

首先我们先将SKU解刨成4个步骤

  1. 添加规格 规格值
  2. 生成 table 头部
  3. 生成 table 数据
  4. 合并单元格

我这里借鉴了一下萤火商城的实现

  1. 添加规格 规格值

    // 这里 id 是我前台生成的 但我总感觉哪里有问题(反正以后改,把 UUID 去掉即可)
    // 添加规格值也差不多
    function addSpecs() {
        if (!specsFormData.specsName) return message.warning('规格名不能为空!');
        if (!specsFormData.specsValue) return message.warning('规格值不能为空!');
        formData.specsTree.push({
          ...specsFormData,
          specsValue: '',
          specsValues: [
            {
              specsValName: specsFormData.specsValue,
              specsValId: buildUUID(),
            },
          ],
          specsId: buildUUID(),
        });
        specsTreeForm.value.resetFields();
        tableRender();
     }
    复制代码
  2. 生成 table 头部

    // 1. 我们监听规格变化 将规格提取成 ant-desgin 想要的格式
    // 2. tableColumns 是最终合并出的结果
    const tableSpecsColTitle = ref([]);
    
    const tableColumns = computed(() => {
       return [...tableSpecsColTitle.value, ...columns];
    });
    
    watch(formData.specsTree, (arr) => {
       tableSpecsColTitle.value = arr.map((v, i) => ({
         title: v.specsName,
         dataIndex: `skuProps.${i}.value.name`,
         width: '80px',
       }));
    });
    复制代码
  3. 生成 table 数据

    // 这一步比较麻烦
    // 有点难以讲解
    // 反正就想当于 
    // 第一步 成组织 将所有values按层级提取出来
    // 生成笛卡尔  这个笛卡尔怎么解释呢 反正就是生成层级数据 知道他干什么的就行了
    // skuKey 这个字段很关键 就是这三个值的 id 联合
    
    function tableRender() {
        // 整理所有的规格组
        const specsGroupArr = buildSpecsGroup();
        // 生成笛卡尔数据集合
        const cartesianList = cartesianProductOf(specsGroupArr);
        // TODO 合并单元格
        // 生成 SKU 字段名
        buildSkuColumns();
        // 生成 SKU 列表数据
        const skuList = buildSkuList(cartesianList);
        formData.tableTree = skuList;
    }
    
    function buildSpecsGroup() {
        const specGroupArr = [];
        formData.specsTree.forEach((specGroup) => {
          const itemArr = [];
          specGroup.specsValues.forEach((value) => {
            itemArr.push(value as never);
          });
          specGroupArr.push(itemArr as never);
        });
        return specGroupArr;
      }
    
      function buildSkuColumns() {}
    
      function buildSkuList(cartesianList) {
        // 生成新的skuList
        const newSkuList = [];
        const specsList = formData.specsTree;
        for (let i = 0; i < cartesianList.length; i++) {
          const newSkuItem = {
            ...defaultSKU,
            key: i,
            // skuKey用于合并旧记录
            skuKey: cartesianList[i].map((item) => item.specsValId).join('_'),
            // skuKeys用于传参给后端
            skuProps: cartesianList[i].map((item, specsIndex) => {
              const specsItem = specsList[specsIndex];
              return {
                group: {
                  name: specsItem.specsName,
                  id: specsItem.specsId,
                },
                value: {
                  name: item.specsValName,
                  id: item.specsValId,
                },
              };
            }),
          };
          newSkuList.push(newSkuItem as never);
        }
        // 兼容旧的sku数据
        return oldSkuList(newSkuList);
      }
    
      // 合并已存在的sku数据
      function oldSkuList(newSkuList) {
        const oldSkuList = formData.tableTree.concat();
        if (!oldSkuList.length || !newSkuList.length) {
          return newSkuList;
        }
        for (const index in newSkuList) {
          // 查找符合的旧记录
          let oldSkuItem = {};
          if (oldSkuList.length === newSkuList.length) {
            oldSkuItem = cloneDeep(oldSkuList[index]);
          } else {
            oldSkuItem = oldSkuList.find((item) => {
              return item.skuKey === newSkuList[index].skuKey;
            });
          }
          // 写入新纪录
          newSkuList[index] = {
            ...newSkuList[index],
            ...pick(oldSkuItem, Object.keys(defaultSKU)),
          };
        }
        return newSkuList;
      }
    
      /**
       * 生成笛卡尔积数据
       * cartesianProductOf([arr1, arr2, arr3 ...])
       */
      const cartesianProductOf = (arrays) => {
        if (!arrays.length) {
          return [];
        }
        return Array.prototype.reduce.call(
          arrays,
          (arr1, arr2) => {
            var ret = [];
            arr1.forEach((v1) => {
              arr2.forEach((v2) => {
                ret.push(v1.concat([v2]));
              });
            });
            return ret;
          },
          [[]],
        );
      };
    复制代码

差不多就这些吧 合并单元格 也简单 根据 skukey 去解析就OK了

到时候在写吧

文章分类
前端
文章标签