Vue项目

vue sku商品规格模板之后台管理系统篇

2020-08-29  本文已影响0人  MrHong_bfea

刚看到设计稿的时候,还是有点懵的,查询了百度后就开始有了灵感和思路了,下面就来看看实现的效果吧,这个是vue+element-ui的后台管理系统,用到的是element的ui。
前面步骤一到二是上传图片,第三步才是商品sku模板的开始。
1.下图是我们看到模板的第一步(添加规格类型),就是不论什么规格都是自己拟定义


image.png

2.下图是我们看到的第二步,增加规格的名称


image.png
image.png
3.下图是我们看到的增加的sku,要多少规格名称和规格的sku都自己拟定就OK拉!
image.png
image.png

4.这是第三步点击下一步后的第四步,也就是生成了sku的模板了,我们可以在后面输入该规格的库存和价格,当然这个库存和价格都是可以自己拟定的。


image.png
5.下面就来看一下代码的演示效果吧!
-这是第三步和第四步的html代码
<div v-show="shopStepActive==3" class="stepThird" style="width:100%">
          <el-button
            type="primary"
            icon="el-icon-circle-plus"
            class="addSpecificaType"
            @click="_addSpecifoca"
          >添加规格类型</el-button>
          <div v-for="(item,index) in templateData" :key="`item${index}`" class="itemTag">
            <div class="outerBorder">
              <div class="close" @click="_deleteTemplateData(index)">
                <i class="el-icon-error" />
              </div>
              <div class="inputMar">
                <el-input v-model="item.name" placeholder="请输入规格名称,如尺寸;" style="width:300px" />
                <!-- <el-button type="primary" @click="_addSizeName">添加</el-button> -->
              </div>
              <div v-show="item.name">
                <el-tag
                  v-for="tag in item.dynamicTags"
                  :key="`${tag}index`"
                  closable
                  :disable-transitions="false"
                  @close="handleClose(tag, item)"
                >{{ tag }}</el-tag>
                <el-input
                  v-if="item.tagInputVisible"
                  :ref="'saveTagInput'+index"
                  v-model="item.tagInputValue"
                  v-focus="item.focusState"
                  class="input-new-tag"
                  size="small"
                  @keyup.enter.native="handleInputConfirm(item, index)"
                  @blur="handleInputConfirm(item, index)"
                />
                <el-button
                  v-else
                  class="button-new-tag"
                  size="small"
                  @click="_addshowInput(item, index)"
                >+ {{ item.name }}</el-button>
              </div>
            </div>
          </div>
        </div>
        <div v-show="shopStepActive==4" class="stepFour">
          <div class="stepFour__name">
            <div
              v-for="(nameItem,nameIndex) in templateNameList"
              :key="`nameItem${nameIndex}`"
              class="item"
            >{{ nameItem }}</div>
          </div>
          <div v-show="newTemplateData.length>0" class="stepFour__box">
            <div
              v-for="(item,index) in newTemplateData"
              :key="`item${index}`"
              class="stepFour__box__panel"
            >
              <div
                v-for="(childItem,childIndex) in item"
                :key="`childItem${childIndex}`"
                class="item"
              >
                <span
                  v-show="childIndex!=(item.length-1) && childIndex!=(item.length-2)"
                >{{ childItem }}</span>
                <el-input
                  v-show="childIndex==(item.length-2)"
                  v-model="childItem.stockNum"
                  oninput="value=value.replace(/[^\d.]/g,'')"
                  placeholder="输入库存"
                  style="width:100%"
                />
                <el-input
                  v-show="childIndex==(item.length-1)"
                  v-model="childItem.price"
                  oninput="value=value.replace(/[^\d.]/g,'')"
                  placeholder="输入价格"
                  style="width:100%"
                />
              </div>
            </div>
          </div>
        </div>
    <div class="rigEnd">
        <el-button
          v-show="shopStepActive!=1"
          type="text"
          class="previousBtn"
          @click="_previousStep"
        >上一步</el-button>
        <el-button v-show="shopStepActive!=4" type="primary" class="saveBtn" @click="_nextStep">下一步</el-button>
        <el-button
          v-show="shopStepActive==4"
          type="primary"
          class="saveBtn"
          @click="_saveTemplate"
        >保存</el-button>
      </div>

-下面是scss的代码,样式可自行修改

.stepThird{
    .addSpecificaType{
      margin-bottom: 10px;
    }
    .itemTag{
      margin-bottom: 20px;
      .outerBorder{
        width: 100%;
        border: 1px solid #eee;
        border-radius: 5px;
        padding: 10px;
        box-sizing: border-box;
        position: relative;
        .close{
          position: absolute;
          right: 0;
          top: 0;
          i{
            font-size: 20px;
            cursor: pointer;
          }
        }
        .inputMar{
          margin-bottom: 10px;
        }
      }
    }
  }
  .stepFour{
    width: 100%;
    margin: auto;
    &__name{
        width: 100%;
        box-sizing: border-box;
        border: 1px solid #eee;
        display: flex;
        align-items: center;
      .item{
        flex: 1;
        width: 120px;
        height: 50px;
        line-height: 50px;
        text-align: center;
        font-size: 14px;
        border-right: 1px solid #eee;
        padding: 0 10px;
        box-sizing: border-box;
      }
    }
    &__box{
      &__panel{
        width: 100%;
        box-sizing: border-box;
        border: 1px solid #eee;
        display: flex;
        align-items: center;
        .item{
          flex: 1;
          width: 120px;
          height: 50px;
          line-height: 50px;
          text-align: center;
          font-size: 14px;
          border-right: 1px solid #eee;
          padding: 0 10px;
          box-sizing: border-box;
        }
      }
    }
  }
.rigEnd {
    display: flex;
    justify-content: flex-end;
    .previousBtn{
      color: #333;
      margin-right: 20px;
    }
    .saveBtn{
      width: 200px;
      height: 46px;
    }
  }

-就着我们来定义变量

//自定义指令v-focus
directives: {
    focus: {
      // 根据focusState的状态改变是否聚焦focus
      update: function(el, value) {
        // 第二个参数传进来的是个json
        if (value) {
          el.focus()
        }
      }
    }
  },
data(){
  return {
      //步骤
      shopStepActive: 3,
      //每一个sku规格的数据
      templateData: [],
      //  每一个sku规格里面拟定的数据如:颜色里面的[红色,蓝色,黄色]这些
      dynamicTags: [],
      // 这个是第四步步骤里的for循环的颜色的模板名称,如[颜色,尺寸,库存,价格]
      templateNameList: []
      // 这个是第四步步骤里的for循环的数据,如[红色,S,11个,56元]
      newTemplateData: []
  }
}

-接着就是我们需要定义方法处理数据了

// 添加规格类型
    _addSpecifoca() {
      this.templateData.push({
        name: '',
        dynamicTags: [],
        tagInputVisible: false,
        tagInputValue: '',
        focusState: false
      })
    },
// 删除商品规格
    _deleteTemplateData(index) {
      this.templateData.splice(index, 1)
    },
// 删除单个标签
    handleClose(tag, item) {
      item.dynamicTags.splice(item.dynamicTags.indexOf(tag), 1)
    },
// 按下enter或者失去焦点的时候触发Input里面的值到<el-tag>
    handleInputConfirm(item, index) {
      const tagInputValue = item.tagInputValue
      if (tagInputValue) {
        if (item.dynamicTags.indexOf(tagInputValue) === -1) {
          item.dynamicTags.push(tagInputValue)
        } else {
          Message.warning('请勿重复输入')
        }
      }
      item.tagInputVisible = false
      item.tagInputValue = ''
    },
// 点击变成输入框
    _addshowInput(item, index) {
      item.tagInputVisible = true
      this.$nextTick(() => {
        item.focusState = true
        //   this.$refs.saveTagInput[index].$refs.input.focus()
      })
    },
 // 多数组求笛卡儿积function cartesianProduct(array){
    recursionData(array) {
      return array.reduce(
        function(a, b) {
          return a
            .map(function(x) {
              return b.map(function(y) {
                return x.concat(y)
              })
            })
            .reduce(function(a, b) {
              return a.concat(b)
            }, [])
        },
        [[]]
      )
    },
// 下一步步骤
    _nextStep() {
      this.newTemplateData = []
      this.templateNameList = []
      this.shopStepActive++
      const array = []
      if (this.shopStepActive === 4) {
        this.templateData.forEach(element => {
          this.templateNameList.push(element.name)
          array.push(element.dynamicTags)
        })
        this.newTemplateData = this.recursionData(array).filter(item => {
          item.push({ stockNum: '' }, { price: '' })
          return item
        })
        console.log(this.newTemplateData)
        this.templateNameList.push('库存', '价格')
      }
    },
// 上一步
    _previousStep() {
      this.shopStepActive--
    }

-最后一个保存的方法是看下后台需要我们传的数据,首先我们来看看后台需要我们传的数据是什么

"sku":[
  {
  "price":"1000.00",
  "stock":"100",
  "item_id":[{"keyName": "颜色","keyVal": "白色"},{"keyName": "内存","keyVal": "128G"}]
  },
  {
  "price":"3000.00",
  "stock":"80",
  "item_id":[{"keyName": "颜色","keyVal": "黑色"},{"keyName": "内存","keyVal": "512G"}]
  },
  {
  "price":"3000.00",
  "stock":"50",
  "item_id":[{"keyName": "颜色","keyVal": "蓝色"},{"keyName": "内存","keyVal": "1024G"}]
  }
 ]

-最后我们再编写一个方法来完成保存需要给的后台的数据

// 保存添加的模板
    _saveTemplate() {
      var newVal = []
      const sku = this.newTemplateData.reduce((c, item) => {
        newVal = []
        for (let k = 0; k < item.length - 2; k++) {
          newVal.push({
            keyName: [...this.templateNameList][k],
            keyVal: item[k]
          })
        }
        return c.concat({
          price: item[item.length - 1].price,
          stockNum: item[item.length - 2].stockNum,
          item_id: [...newVal]
        })
      }, [])
      console.log(sku)
    },

大功告成,每个方法都有注释,就不全部介绍了,这就是我们的Vue+element的sku商品规格模板。只要思路清晰了,就可以搞,加油。
最后希望能帮到大家。

上一篇下一篇

猜你喜欢

热点阅读