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

刚看到设计稿的时候,还是有点懵的,查询了百度后就开始有了灵感和思路了,下面就来看看实现的效果吧,这个是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商品规格模板。只要思路清晰了,就可以搞,加油。
最后希望能帮到大家。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,752评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,100评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,244评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,099评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,210评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,307评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,346评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,133评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,546评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,849评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,019评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,702评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,331评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,030评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,260评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,871评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,898评论 2 351