利用ElementUI配置商品的规格参数

需求:商品可以设置多个规格,需要自动生成对应规格的所有组合,并设置该规格商品的图片、价格、库存等数据。

javascript 复制代码
<template>
  <div class="sku-list">
    <template v-if="!disabled">
      <div class="sku-list-head">
        <el-button type="primary" size="mini" @click="addSkuRow"
        >添加规格</el-button
        >
      </div>
      <div
        class="sku-list-item"
        v-for="(item, index) in skuData.attrList"
        :key="index"
      >
        <div class="sku-list-item-main">
          <div class="sku-list-item__layout">
            <span class="span">规格名</span>
            <el-input
              size="small"
              v-model="item.attrName"
              class="input"
            ></el-input>
          </div>
          <div class="sku-list-item__layout">
            <span class="span">规格值</span>
            <div class="sku-list-item-tags">
              <el-tag
                class="sku-list-item-tag"
                closable
                @close="removeSkuAttr(index, i)"
                v-for="(subitem, i) in item.attrValue"
                :key="i"
              >{{ subitem.attrValue }}</el-tag
              >
              <el-button
                size="small"
                icon="el-icon-plus"
                @click="addSkuAttr(index)"
              >添加</el-button
              >
            </div>
          </div>
        </div>
        <el-button
          type="text"
          size="small"
          class="sku-list-item-removeBtn"
          @click="removeSkuRow(index)"
        >删除规格</el-button
        >
      </div>
    </template>
    <el-table border :data="skuData.skuList">
      <el-table-column label="规格图片" align="center" width="120">

      </el-table-column>
      <el-table-column
        label="规格名称"
        align="center"
        prop="attrPath"
      ></el-table-column>
      <el-table-column label="规格售价" align="center">
        <template slot-scope="scope">
          <el-input-number v-model="scope.row.priceCost" :precision="2" :min="0.01"/>
        </template>
      </el-table-column>
<!--      <el-table-column label="销售价格" align="center">-->
<!--        <template slot-scope="scope">-->
<!--          <el-input-->
<!--            :readonly="disabled"-->
<!--            v-model="scope.row.priceCash"-->
<!--          ></el-input>-->
<!--        </template>-->
<!--      </el-table-column>-->
<!--      <el-table-column label="划线价格" align="center">-->
<!--        <template slot-scope="scope">-->
<!--          <el-input-->
<!--            :readonly="disabled"-->
<!--            v-model="scope.row.priceOriginal"-->
<!--          ></el-input>-->
<!--        </template>-->
<!--      </el-table-column>-->
      <el-table-column label="规格库存" align="center">
        <template slot-scope="scope">
          <el-input-number v-model="scope.row.stock" :min="0" :max="999999"/>
        </template>
      </el-table-column>
      <!-- <el-table-column label="商品预警值" align="center">
        <template slot-scope="scope">
          <el-input :readonly="disabled" v-model="scope.row.stock"></el-input>
        </template>
      </el-table-column> -->
      <!-- <el-table-column v-if="!disabled" label="操作" align="center">
        <template>
          <el-button type="text" size="small">删除</el-button>
          <el-button type="text" size="small">上移</el-button>
        </template>
      </el-table-column> -->
    </el-table>
  </div>
</template>

<script>
export default {
  model: {
    prop: "skuData",
    event: "changeSku",
  },
  props: {
    // skuData: {
    //   type: Object,
    //   default: () => ({}),
    // },
    disabled: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      skuData: {
        attrList: [],
        skuList: [],
        initSkuList: []
      }
    };
  },
  watch: {
    "skuData.attrList": {
      handler() {
        if (!this.disabled) {
          this.$set(this.skuData, "skuList", this.getTable());
        }
      },
      deep: true,
      immediate: true,
    },
  },
  methods: {
    // 添加规格行
    addSkuRow(i) {
      // const attrList = this.skuData.attrList;
      // if (attrList === undefined) {
      //   const list = [{
      //     attrName: "",
      //     attrValue: []
      //   }]
      //   this.skuData.attrList = list;
      // } else {
      //   attrList.push({
      //     attrName: "",
      //     attrValue: []
      //   });
      // }
      this.skuData.attrList.push({
        attrName: "",
        attrValue: []
      })
      this.$emit("changeSku", this.skuData);
    },

    // 删除规格行
    removeSkuRow(i) {
      this.skuData.attrList.splice(i, 1);
      this.$emit("changeSku", this.skuData);
    },
    // 删除规格属性值
    removeSkuAttr(a, b) {
      this.skuData.attrList[a].attrValue.splice(b, 1);
      this.$emit("changeSku", this.skuData);
    },
    // 添加规格属性值
    addSkuAttr(i) {
      this.$prompt("请输入规格值", "添加规格值", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        inputPattern: /\S+/,
        inputErrorMessage: "规格值不能为空",
        closeOnClickModal: false,
      }).then(({ value }) => {
        this.skuData.attrList[i].attrValue.push({
          attrValue: value,
        });
        this.$emit("changeSku", this.skuData);
      });
    },
    onUploadImgSuccess(res, file, row) {
      if (!file) {
        return;
      }
      row.icon = file;
      this.$emit("changeSku", this.skuData);
    },
    getTable() {
      const table = [];
      const attrValueAry = [];
      const arr = [];
      const tmpSkuData = (this.skuData.attrList || []).filter(
        (d) => d.attrName !== "" && d.attrValue.length > 0
      );
      if (!tmpSkuData || tmpSkuData.length === 0) {
        return [];
      }

      tmpSkuData.forEach((item) => {
        attrValueAry.push(item.attrValue);
      });

      function func(skuArr = [], i) {
        for (let j = 0; j < attrValueAry[i].length; j++) {
          if (i < attrValueAry.length - 1) {
            skuArr[i] = attrValueAry[i][j];
            func(skuArr, i + 1);
          } else {
            arr.push([...skuArr, attrValueAry[i][j]]);
          }
        }
      }
      func([], 0);
      arr.forEach((item) => {
        let attrPath = "";
        // const findItem = {};
        // const tableItem = {};
        item.forEach((d, idx) => {
          attrPath += `${tmpSkuData[idx].attrName}:${d.attrValue};`;
        });
        attrPath = attrPath.slice(0, attrPath.length - 1);
        const findItem =
          this.skuData.initSkuList.find((item) => {
            return attrPath.includes(item.attrPath);
          }) || {};

        const tableItem = Object.assign(
          {
            priceCost: 0,
            priceCash: 0,
            priceOriginal: 0,
            stock: 0,
            icon: null,
          },
          findItem,
          {
            attrPath,
          }
        );
        table.push(tableItem);
      });
      return table;
    },
  },
};
</script>

<style lang="scss" scoped>
.sku-list {
  &-head {
    margin-bottom: 10px;
  }
  &-item {
    display: flex;
    align-items: center;
    border: 1px solid #eee;
    border-radius: 5px;
    margin-bottom: 20px;
    padding: 20px 50px;

    &-main {
      flex: 1;
    }
    &-removeBtn {
      margin-left: 20px;
      color: #f56c6c;
    }
    &__layout {
      display: flex;
      align-items: center;
      margin-bottom: 20px;
      &:last-child {
        margin-bottom: 0;
      }
      .input {
        width: 240px;
      }
      .span {
        font-size: 13px;
        font-weight: bold;
        margin-right: 10px;
      }
    }
    &-tags {
      flex: 1;
    }
    &-tag {
      margin-bottom: 10px;
      margin-right: 10px;
    }
  }
}
</style>
相关推荐
蟾宫曲5 小时前
在 Vue3 项目中实现计时器组件的使用(Vite+Vue3+Node+npm+Element-plus,附测试代码)
前端·npm·vue3·vite·element-plus·计时器
秋雨凉人心5 小时前
简单发布一个npm包
前端·javascript·webpack·npm·node.js
liuxin334455665 小时前
学籍管理系统:实现教育管理现代化
java·开发语言·前端·数据库·安全
qq13267029405 小时前
运行Zr.Admin项目(前端)
前端·vue2·zradmin前端·zradmin vue·运行zradmin·vue2版本zradmin
魏时烟6 小时前
css文字折行以及双端对齐实现方式
前端·css
哥谭居民00017 小时前
将一个组件的propName属性与父组件中的variable变量进行双向绑定的vue3(组件传值)
javascript·vue.js·typescript·npm·node.js·css3
踢足球的,程序猿7 小时前
Android native+html5的混合开发
javascript
2401_882726487 小时前
低代码配置式组态软件-BY组态
前端·物联网·低代码·前端框架·编辑器·web
web130933203987 小时前
ctfshow-web入门-文件包含(web82-web86)条件竞争实现session会话文件包含
前端·github
胡西风_foxww7 小时前
【ES6复习笔记】迭代器(10)
前端·笔记·迭代器·es6·iterator