Vue 商品管理模块(添加,修改)

商品添加功能

点击添加商品展示编辑框
在这里插入图片描述

在这里插入图片描述
因为添加商品代码比较多所以新建一个Add.vue组件
在这里插入图片描述

index.js 中配置路由

 {
                path: '/goods',
                component: () =>
                    import ('../components/goods/List.vue')
            },
            {
                path: '/goods/add',
                component: () =>
                    import ('../components/goods/Add.vue')
            },
        ]
 <el-button type="primary" @click="goAddPage">添加商品</el-button>
// 点击添加商品跳转到添加商品页面
    goAddPage(){
        this.$router.push('/goods/add')
    }

elementui 步骤条

<el-steps :active="active" finish-status="success">
  <el-step title="步骤 1"></el-step>
  <el-step title="步骤 2"></el-step>
  <el-step title="步骤 3"></el-step>
</el-steps>

左侧的标签页
在这里插入图片描述

给tebs增加全局的样式 global.css
在这里插入图片描述

.el-steps {
    margin: 15px 0;
}

.el-step__title {
    font-size: 13px;
}
<!-- 提示信息 closable=>不能关闭的-->
      <el-alert title="添加商品信息" type="info" show-icon :closable="false" center> </el-alert>
      <!-- 步骤条 space 步骤条宽度-->
      <el-steps :active="activeIndex" finish-status="success" align-center :space="200">
        <el-step title="基本信息"></el-step>
        <el-step title="商品参数"></el-step>
        <el-step title="商品属性"></el-step>
        <el-step title="商品图片"></el-step>
        <el-step title="商品内容"></el-step>
        <el-step title="完成"></el-step>
      </el-steps>

      <!-- 标签页-->
      <el-tabs tab-position="left" style="height: 200px">
        <el-tab-pane label="基本信息">1</el-tab-pane>
        <el-tab-pane label="商品参数">2</el-tab-pane>
        <el-tab-pane label="商品属性">3</el-tab-pane>
        <el-tab-pane label="商品图片">4</el-tab-pane>
        <el-tab-pane label="商品内容">5</el-tab-pane>
       
      </el-tabs>

效果
在这里插入图片描述

现在让标签页和步骤条关联起来
把标签页的取值和步骤条的取值设为一样的,就可以了

在这里插入图片描述

<!-- 提示信息 closable=>不能关闭的-->
      <el-alert title="添加商品信息" type="info" show-icon :closable="false" center> </el-alert>
      <!-- 步骤条 space 步骤条宽度-->
      <el-steps :active="activeIndex" finish-status="success" align-center :space="200">
        <el-step title="基本信息"></el-step>
        <el-step title="商品参数"></el-step>
        <el-step title="商品属性"></el-step>
        <el-step title="商品图片"></el-step>
        <el-step title="商品内容"></el-step>
        <el-step title="完成"></el-step>
      </el-steps>

      <!-- 标签页 这里的activeIndex 获取的就是name的值-->
      <el-tabs v-model="activeIndex" tab-position="left" style="height: 200px">
        <el-tab-pane label="基本信息" name="0">1</el-tab-pane>
        <el-tab-pane label="商品参数" name="1">2</el-tab-pane>
        <el-tab-pane label="商品属性" name="2">3</el-tab-pane>
        <el-tab-pane label="商品图片" name="3">4</el-tab-pane>
        <el-tab-pane label="商品内容" name="4">5</el-tab-pane>
       
      </el-tabs>

在这里插入图片描述
这里会报错,需要数值0而不是字符串
获取的值随便减去一个数值js会隐式转换成数值

<!-- 步骤条 space 步骤条宽度-->
      <el-steps :active="activeIndex-0" finish-status="success" align-center :space="200">

在这里插入图片描述

<template>
  <div>
    <!-- 面包屑导航-->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>商品管理</el-breadcrumb-item>
      <el-breadcrumb-item>添加商品</el-breadcrumb-item>
    </el-breadcrumb>

    <!-- 卡片试图-->
    <el-card>
      <!-- 提示信息 closable=>不能关闭的-->
      <el-alert title="添加商品信息" type="info" show-icon :closable="false" center> </el-alert>
      <!-- 步骤条 space 步骤条宽度-->
      <el-steps :active="activeIndex-0" finish-status="success" align-center :space="200">
        <el-step title="基本信息"></el-step>
        <el-step title="商品参数"></el-step>
        <el-step title="商品属性"></el-step>
        <el-step title="商品图片"></el-step>
        <el-step title="商品内容"></el-step>
        <el-step title="完成"></el-step>
      </el-steps>

      <!-- 标签页 这里的activeIndex 获取的就是name的值-->
      <el-tabs v-model="activeIndex" tab-position="left" style="height: 200px">
        <el-tab-pane label="基本信息" name="0">1</el-tab-pane>
        <el-tab-pane label="商品参数" name="1">2</el-tab-pane>
        <el-tab-pane label="商品属性" name="2">3</el-tab-pane>
        <el-tab-pane label="商品图片" name="3">4</el-tab-pane>
        <el-tab-pane label="商品内容" name="4">5</el-tab-pane>
       
      </el-tabs>
    </el-card>
  </div>
</template>

<script>
export default {
  data() {
    return {
      activeIndex: 0,
    }
  },
}
</script>

基本信息

控制label在输入框的上方
label-position='top'

限制输入的值是数值
v-model.number
 <!-- 标签页 这里的activeIndex 获取的就是name的值-->
      <el-form :model="addForm" :rules="addFormRules" ref="addFormRef" label-width="100px" label-position='top'>
        <el-tabs v-model="activeIndex" tab-position="left">
          <el-tab-pane label="基本信息" name="0">
            <el-form-item label="商品名称" prop="goods_name">
              <el-input v-model="addForm.goods_name"></el-input>
            </el-form-item>
            <el-form-item label="商品价格" prop="goods_price">
              <el-input v-model.number="addForm.goods_name"></el-input>
            </el-form-item>
            <el-form-item label="商品重量" prop="goods_weight">
              <el-input v-model.number="addForm.goods_name"></el-input>
            </el-form-item>
            <el-form-item label="商品数量" prop="goods_number">
              <el-input v-model.number="addForm.goods_name"></el-input>
            </el-form-item>
            <el-form-item label="商品分类" >
             
            </el-form-item>
          </el-tab-pane>
          <el-tab-pane label="商品参数" name="1">2</el-tab-pane>
          <el-tab-pane label="商品属性" name="2">3</el-tab-pane>
          <el-tab-pane label="商品图片" name="3">4</el-tab-pane>
          <el-tab-pane label="商品内容" name="4">5</el-tab-pane>
        </el-tabs>
      </el-form>

elementui 级联选择器

<el-cascader
    v-model="value"
    :options="options"
    :props="{ expandTrigger: 'hover' }"
    @change="handleChange"></el-cascader>

响应的数据格式

{
    "data": [
        {
            "cat_id": 1,
            "cat_name": "大家电",
            "cat_pid": 0,
            "cat_level": 0,
            "cat_deleted": false,
            "children": [
                {
                    "cat_id": 3,
                    "cat_name": "电视",
                    "cat_pid": 1,
                    "cat_level": 1,
                    "cat_deleted": false,
                    "children": [
                        {
                            "cat_id": 6,
                            "cat_name": "曲面电视",
                            "cat_pid": 3,
                            "cat_level": 2,
                            "cat_deleted": false
                        },
                        {
                            "cat_id": 7,
                            "cat_name": "海信",
                            "cat_pid": 3,
                            "cat_level": 2,
                            "cat_deleted": false
                        }
                    ]
                }
            ]
        }
    ],
<el-form-item label="商品分类">
<el-cascader v-model="addForm.goods_cat" :options="cateList" :props="cascaderProps" @change="handleChange"></el-cascader>
</el-form-item>
<script>
export default {
  data() {
    return {
    // 默认选中第0个
      activeIndex: '0'
      // 添加商品的表单对象
      addForm: {
          goods_name:'',
          goods_price:null,
          goods_weight:null,
          goods_number:null,
          // 商品分类数组
          goods_cat:[]

      },
      addFormRules: {
        goods_name: [{ required: true, message: '请输入商品名称', trigger: 'blur' }],
        goods_price: [{ required: true, message: '请输入商品价格', trigger: 'blur' }],
        goods_weight: [{ required: true, message: '请输入商品重量', trigger: 'blur' }],
        goods_number: [{ required: true, message: '请输入商品数量', trigger: 'blur' }],
      },

      // 分类数组
      cateList: [],
      // 级联选择器的配置
      cascaderProps:{
          label:'cat_name',
          value:'cat_id',
          children:'children',
          expandTrigger:'hover'
      }
    }
  },
  created() {
    this.getCateList()
  },
  methods: {
    // 获取分类列表
    async getCateList() {
      const { data: res } = await this.$http.get('categories')
      if (res.meta.status !== 200) {
        return this.$message.error('获取商品分类失败')
      }
      this.cateList = res.data
      console.log(this.cateList)
    },
    // 监听级联选择器的改变事件
    handleChange(){

    }
  },
}
</script>

在这里插入图片描述

在这里插入图片描述

<el-tabs v-model="activeIndex" tab-position="left" :before-leave="beforeTabLeave">
// 监听级联选择器的改变事件
    handleChange(){
        if(this.addForm.goods_cat.length!==3){
            this.addForm.goods_cat = []
        }
    },
    // tabs切换之前会触发 去往哪个标签页  oldActiveName之前的标签页
    beforeTabLeave(activeName,oldActiveName){
        if(this.addForm.goods_cat.length !==3){
            this.$message.error('请先选择商品分类!')
            return false
        }
    }

选择商品分类后要展示其商品参数和商品属性
在这里插入图片描述

在这里插入图片描述

elementui 中tab 被选中时触发,也就是进行切换的时候
在这里插入图片描述

 <el-tabs v-model="activeIndex" tab-position="left" :before-leave="beforeTabLeave" @tab-click = "tabClicked">

获取动态参数和静态属性,对数据进行处理

// 动态参数
      manyData:[],
      // 静态参数
      onlyData:[],
   // tabs标签页切换时会执行 (显示商品的参数和属性)
    async tabClicked(){
        // 判断是否点击动态参数还是静态属性,因为点击其它的不需要
        // 动态参数
        if(this.activeIndex==='1'){
            const {data:res} = await this.$http.get(`categories/${this.cateId}/attributes`,{
                params:{sel:'many'}
            })
            if(res.meta.status !== 200){
                return this.$message.error('获取动态参数失败')
            }
      
            res.data.forEach(item => {
                item.attr_vals = item.attr_vals ? item.attr_vals.split(' ') : []
            })
            this.manyData=res.data
        }
        // 静态属性
        else if(this.activeIndex==='2'){
            const {data:res} = await this.$http.get(`categories/${this.cateId}/attributes`,{
                params:{sel:'only'}
            })
            if(res.meta.status !== 200){
                return this.$message.error('获取静态属性失败')
            }

            this.onlyData=res.data
        }

    }
  },
  computed:{
      cateId(){
          return this.addForm.goods_cat.length===3 ? this.addForm.goods_cat[2] : null
      }
  }

要展示商品参数
在这里插入图片描述

在这里插入图片描述

 <el-tab-pane label="商品参数" name="1">
            <el-form-item v-for="item in manyData" :key="item.attr_id" :label="item.attr_name">
                                        <!-- 当前选中的数组 -->
              <el-checkbox-group v-model="item.attr_vals">
                <el-checkbox v-for="(value,i) in item.attr_vals" :key="i" :label="value" border></el-checkbox>
                
              </el-checkbox-group>
            </el-form-item>
          </el-tab-pane>

<style scoped>
.el-checkbox{
    margin-right: 10px;
}
</style>

静态属性

 <el-tab-pane label="商品属性" name="2">
            <el-form-item v-for="item in onlyData" :key="item.attr_id" :label="item.attr_name">
                <el-input v-model="item.attr_vals"></el-input>
            </el-form-item>
          </el-tab-pane>

商品图片

在这里插入图片描述
action:服务器要上传后台API的地址

<el-upload
  class="upload-demo"
  action="https://jsonplaceholder.typicode.com/posts/"
  :on-preview="handlePreview"
  :on-remove="handleRemove"
  :file-list="fileList"
  list-type="picture">
  <el-button size="small" type="primary">点击上传</el-button>
  <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload>
<el-tab-pane label="商品图片" name="3">
            <!--action指定图片要上传的后台APL地址 handlePreview实现图片的预览 -->
            <el-upload :action="uploadUrl" :on-preview="handlePreview" :on-remove="handleRemove" list-type="picture" :headers="headerObj">
              <el-button size="small" type="primary">点击上传</el-button>
            </el-upload>
          </el-tab-pane>
</el-card>
    <!-- 图片预览-->
    <el-dialog title="图片预览" :visible.sync="previewVisible" width="50%" >
      <img :src="previewPath" class="preview-img">
    </el-dialog>
 // 上传图片的URL地址
      uploadUrl: '后台地址',
      // 文件上传时请求头
      headerObj: {
        Authorization: JSON.parse(sessionStorage.getItem('userInfo')).token,
      },
      previewVisible:false,
      // 展示图片的路径
      previewPath:'',
// 图片预览
    handlePreview(file) {
        this.previewPath=file.url
        this.previewVisible=true
    },

使商品和图片产生关联,因为图片最终是要传递给后端的

<el-upload :action="uploadUrl" :on-preview="handlePreview" :on-remove="handleRemove" list-type="picture" :headers="headerObj" :on-success="handleSuccess"> 
 // 添加商品的表单对象
      addForm: {
        goods_name: '',
        goods_price: null,
        goods_weight: null,
        goods_number: null,
        // 商品所属分类数组
        goods_cat: [],
        //图片的数组
        pics:[],
      },
// 移除图片回调
    handleRemove(file) {
        // 1.获取将要删除的图片的临时路径
        const filePath = file.response.data.tmp_path
        // 2. 从pics数组中找到这个图片对应的索引值
        const i = this.addForm.pics.findIndex(item=>{
            item.pic===filePath
        })
        // 3. 从pics数组中移除
        this.addForm.pics.splice(i,1)
    },
    // 监听图片上传成功
    handleSuccess(response){
      this.addForm.pics.push({
          pic:response.data.tmp_path
      })
      console.log(this.addForm)
  },

实现富文本编辑器

在这里插入图片描述

基于Vue的Vue-Quill-Editor富文本编辑器

下载quill(Vue-Quill-Editor需要依赖)
 npm install quill --save
 
 下载Vue-Quill-Editor
 npm install vue-quill-editor --save

main.js 中导入

import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';
Vue.component('QuillEditor', quillEditor)

main.js中

//导入富文本编辑器
import VueQuillEditor from 'vue-quill-editor'
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';
Vue.use(VueQuillEditor)

global.css

.ql-editor {
    min-height: 300px;
}

add_Form

// 富文本添加的说明(商品内容)
        goods_introduce:''
 <el-tab-pane label="商品内容" name="4">
              <quill-editor  v-model="addForm.goods_introduce"></quill-editor>
          </el-tab-pane>

实现商品添加功能

在这里插入图片描述
在这里插入图片描述

商品内容填写完需要有一个添加商品的按钮
在这里插入图片描述

<el-tab-pane label="商品内容" name="4">
              <quill-editor  v-model="addForm.goods_introduce"></quill-editor>
              <!--添加按钮-->
              <el-button type="primary" class="btn-add">添加商品</el-button>
          </el-tab-pane>
.btn-add{
    margin-top: 15px;
}

准备请求前的数据
1.处理商品所属分类数组
不能直接将该数组直接用逗号转换,会导致级联选择器绑定的goods_cat发生异常
可以使用lodash 工具进行深拷贝

npm i -save lodash \\全局安装

引入

<script>
import _ from 'lodash'
export default {
<el-button type="primary" class="btn-add" @click="addGoods()">添加商品</el-button>
// 添加商品功能
  addGoods(){
      this.$refs.addFormRef.validate(async valid=>{
          if(!valid){
              return
          }
          // 准备请求前的数据
          //1.处理商品所属分类数组
        //   不能直接将该数组直接用逗号转换,会导致级联选择器绑定的goods_cat发生异常
          // this,addForm.goods_cat = this.addForm.goods_cat.join(',')
          // 可以使用lodash 工具进行深拷贝
          const form = _.cloneDeep(this.addForm) // 深拷贝
          form.goods_cat = form.goods_cat.join(',')

          //处理动态参数 
        this.manyData.forEach(item=>{
            form.attrs.push({
                attr_id:item.attr_id,
                attr_value:item.attr_vals.join(' ')
            })
        })

        // 处理静态属性
        this.onlyData.forEach(item=>{
            form.attrs.push({
                attr_id:item.attr_id,
                attr_value:item.attr_vals
            })
        })

        // 发送请求
        
          const {data:res} = await this.$http.post('goods',form)
          if(res.meta.status !== 201){
              return this.$message.error('添加商品失败')
          }
          this.$message.success('添加商品成功!')
          this.$router.push('/goods')
      })

修改商品信息

在这里插入图片描述

在这里插入图片描述

编辑商品的页面和添加商品的页面一样,所以复制一个Add.vue
重命名为Edit.vue
在这里插入图片描述
index.js

{
                path: '/goods/edit',
                component: () =>
                    import ('../components/goods/Edit.vue')
            },

在商品列表List.vue中实现路由的跳转到Edit.vue

<template slot-scope="scope">
            <el-button size="mini" type="primary" icon="el-icon-edit" @click="geEditpage(scope.row.goods_id)"></el-button>
            <el-button size="mini" type="danger" icon="el-icon-delete" @click="removeById(scope.row.goods_id)"></el-button>
// 跳转到修改商品页面
    geEditpage(id){
        this.$router.push('/goods/edit?id='+id)
    }

Edit.vue
addForm 批量改为 editForm

created() {
    this.getGoodsById()
  },

根据id获取商品信息实现数据的回显

 // 根据id获取商品信息
    async getGoodsById(){
      const{data:res} = await this.$http.get(`goods/${this.$route.query.id}`)
      if(res.meta.status !== 200){
          return this.$message.error('获取商品信息失败')
      }
      this.editForm=res.data
      console.log(this.editForm)

    },

此时会发现商品分类数据没有显示出来,因为后端返回的商品分类式字符串,实际上我们需要的数据类型式数组
在这里插入图片描述

// 对商品分类数据进行处理,转换为数组,此时数组中的元素还是字符串类型map再对数组中数据进行转换
      res.data.goods_cat=res.data.goods_cat.split(',').map(item=>{
        return item*1

此时图片也没有展示出来
返回的数据类型是这个造型
在这里插入图片描述
elementui 中 用以展示图片列表在这里插入图片描述

<!--action指定图片要上传的后台APL地址 handlePreview实现图片的预览 -->
            <el-upload :action="uploadUrl" :on-preview="handlePreview" :on-remove="handleRemove" list-type="picture" :headers="headerObj" :on-success="handleSuccess" :file-list="fileList"> 
              <el-button size="small" type="primary">点击上传</el-button>
            </el-upload>

在返回的图片数据中没有pic(图片的临时路径)这个属性,提交修改的时候需要跟之前一样
在这里插入图片描述

 // 根据id获取商品信息
    async getGoodsById(){
      const{data:res} = await this.$http.get(`goods/${this.$route.query.id}`)
      if(res.meta.status !== 200){
          return this.$message.error('获取商品信息失败')
      }
      this.editForm=res.data
      
      
      // 对商品分类数据进行处理,转换为数组,此时数组中的元素还是字符串类型map再对数组中数据进行转换
      res.data.goods_cat=res.data.goods_cat.split(',').map(item=>{
        return item*1
      })
      
      // 对图片数据进行处理 使其可以回显
      res.data.pics.forEach(item=>{
        this.fileList.push({
          name:item.pics_id,
          url:item.pics_big_url.replace('127.0.0.1','www.tangxiaoyang.vip'),
          temp_path:item.pics_big
        })
        // 增加字段保存临时路径 这样在图片移除的时候就会包含临时路径
        item.pic=item.pics_big
      })
      this.editForm=res.data

    },
  // 移除图片回调
    handleRemove(file) {
        // 1.获取将要删除的图片的临时路径  ()
        //              服务器图片          新增图片
        const filePath = file.tmp_path || file.response.data.tmp_path
        // 2. 从pics数组中找到这个图片对应的索引值
        const i = this.editForm.pics.findIndex(item=>{
            item.pic===filePath
        })
        // 3. 从pics数组中移除
        this.editForm.pics.splice(i,1)
        
    },
 // 修改商品功能
  editGoods(){
      this.$refs.editFormRef.validate(async valid=>{
          if(!valid){
              return
          }
          // 准备请求前的数据
          //1.处理商品所属分类数组
        //   不能直接将该数组直接用逗号转换,会导致级联选择器绑定的goods_cat发生异常
          // this,editForm.goods_cat = this.editForm.goods_cat.join(',')
          // 可以使用lodash 工具进行深拷贝
          const form = _.cloneDeep(this.editForm) // 深拷贝
          form.goods_cat = form.goods_cat.join(',')

          //处理动态参数 
        this.manyData.forEach(item=>{
            form.attrs.push({
                attr_id:item.attr_id,
                attr_value:item.attr_vals.join(' ')
            })
        })

        // 处理静态属性
        this.onlyData.forEach(item=>{
            form.attrs.push({
                attr_id:item.attr_id,
                attr_value:item.attr_vals
            })
        })

        // 发送请求
          const {data:res} = await this.$http.post(`goods/${this.editForm.goods_id}`,form)
          if(res.meta.status !== 200){
              return this.$message.error('修改商品失败')
          }
          this.$message.success('修改商品成功!')
          this.$router.push('/goods')
      })
  }

完整代码

<template>
  <div>
    <!-- 面包屑导航-->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>商品管理</el-breadcrumb-item>
      <el-breadcrumb-item>修改商品</el-breadcrumb-item>
    </el-breadcrumb>

    <!-- 卡片试图-->
    <el-card>
      <!-- 提示信息 closable=>不能关闭的-->
      <el-alert title="修改商品信息" type="info" show-icon :closable="false" center> </el-alert>
      <!-- 步骤条 space 步骤条宽度-->
      <el-steps :active="activeIndex - 0" finish-status="success" align-center :space="200">
        <el-step title="基本信息"></el-step>
        <el-step title="商品参数"></el-step>
        <el-step title="商品属性"></el-step>
        <el-step title="商品图片"></el-step>
        <el-step title="商品内容"></el-step>
        <el-step title="完成"></el-step>
      </el-steps>

      <!-- 标签页 这里的activeIndex 获取的就是name的值-->
      <el-form :model="editForm" :rules="editFormRules" ref="editFormRef" label-width="100px" label-position="top">
        <el-tabs v-model="activeIndex" tab-position="left" :before-leave="beforeTabLeave" @tab-click="tabClicked">
          <el-tab-pane label="基本信息" name="0">
            <el-form-item label="商品名称" prop="goods_name">
              <el-input v-model="editForm.goods_name"></el-input>
            </el-form-item>
            <el-form-item label="商品价格" prop="goods_price">
              <el-input v-model.number="editForm.goods_price" type="number"></el-input>
            </el-form-item>
            <el-form-item label="商品重量" prop="goods_weight" >
              <el-input v-model.number="editForm.goods_weight" type="number"></el-input>
            </el-form-item>
            <el-form-item label="商品数量" prop="goods_number" >
              <el-input v-model.number="editForm.goods_number" type="number"></el-input>
            </el-form-item>
            <el-form-item label="商品分类">
              <el-cascader v-model="editForm.goods_cat" :options="cateList" :props="cascaderProps" @change="handleChange"></el-cascader>
            </el-form-item>
          </el-tab-pane>
          <el-tab-pane label="商品参数" name="1">
            <el-form-item v-for="item in manyData" :key="item.attr_id" :label="item.attr_name">
              <!-- 当前选中的数组 -->
              <el-checkbox-group v-model="item.attr_vals">
                <el-checkbox v-for="(value, i) in item.attr_vals" :key="i" :label="value" border></el-checkbox>
              </el-checkbox-group>
            </el-form-item>
          </el-tab-pane>
          <el-tab-pane label="商品属性" name="2">
            <el-form-item v-for="item in onlyData" :key="item.attr_id" :label="item.attr_name">
              <el-input v-model="item.attr_vals"></el-input>
            </el-form-item>
          </el-tab-pane>
          <el-tab-pane label="商品图片" name="3">
            <!--action指定图片要上传的后台APL地址 handlePreview实现图片的预览 -->
            <el-upload :action="uploadUrl" :on-preview="handlePreview" :on-remove="handleRemove" list-type="picture" :headers="headerObj" :on-success="handleSuccess" :file-list="fileList"> 
              <el-button size="small" type="primary">点击上传</el-button>
            </el-upload>
          </el-tab-pane>
          <el-tab-pane label="商品内容" name="4">
              <quill-editor  v-model="editForm.goods_introduce"></quill-editor>
              <!--添加按钮-->
              <el-button type="primary" class="btn-add" @click="editGoods()">修改商品</el-button>
          </el-tab-pane>
        </el-tabs>
      </el-form>
    </el-card>

    <!-- 图片预览-->
    <el-dialog title="图片预览" :visible.sync="previewVisible" width="50%" >
      <img :src="previewPath" class="preview-img">
    </el-dialog>
  </div>
</template>

<script>
import _ from 'lodash'
export default {
  data() {
    return {
      activeIndex: '0',
      // 添加商品的表单对象
      editForm: {
        goods_name: '',
        goods_price: null,
        goods_weight: null,
        goods_number: null,
        // 商品所属分类数组
        goods_cat: [],
        //图片的数组
        pics:[],
        // 富文本添加的说明(商品内容)
        goods_introduce:'',
        // 商品的参数
        attrs:[]
      },
      editFormRules: {
        goods_name: [{ required: true, message: '请输入商品名称', trigger: 'blur' }],
        goods_price: [{ required: true, message: '请输入商品价格', trigger: 'blur' }],
        goods_weight: [{ required: true, message: '请输入商品重量', trigger: 'blur' }],
        goods_number: [{ required: true, message: '请输入商品数量', trigger: 'blur' }],
      },

      // 分类数组
      cateList: [],
      // 级联选择器的配置
      cascaderProps: {
        label: 'cat_name',
        value: 'cat_id',
        children: 'children',
        expandTrigger: 'hover',
      },
      // 动态参数
      manyData: [],
      // 静态参数
      onlyData: [],
      // 上传图片的URL地址
      uploadUrl: 'http://www.tangxiaoyang.vip:8888/api/v2/upload',
      // 文件上传时请求头
      headerObj: {
        Authorization: JSON.parse(sessionStorage.getItem('userInfo')).token,
      },
      previewVisible:false,
      // 展示图片的路径
      previewPath:'',
      fileList:[]
    }
  },
  created() {
    this.getCateList()
    this.getGoodsById()
  },
  methods: {

    // 根据id获取商品信息
    async getGoodsById(){
      const{data:res} = await this.$http.get(`goods/${this.$route.query.id}`)
      if(res.meta.status !== 200){
          return this.$message.error('获取商品信息失败')
      }
      this.editForm=res.data
      
      
      // 对商品分类数据进行处理,转换为数组,此时数组中的元素还是字符串类型map再对数组中数据进行转换
      res.data.goods_cat=res.data.goods_cat.split(',').map(item=>{
        return item*1
      })
      
      // 对图片数据进行处理 使其可以回显
      res.data.pics.forEach(item=>{
        this.fileList.push({
          name:item.pics_id,
          url:item.pics_big_url.replace('127.0.0.1','www.tangxiaoyang.vip'),
          temp_path:item.pics_big
        })
        // 增加字段保存临时路径 这样在图片移除的时候就会包含临时路径
        item.pic=item.pics_big
      })
      this.editForm=res.data

    },

    // 获取分类列表
    async getCateList() {
      const { data: res } = await this.$http.get('categories')
      if (res.meta.status !== 200) {
        return this.$message.error('获取商品分类失败')
      }
      this.cateList = res.data
    },
    // 监听级联选择器的改变事件
    handleChange() {
      if (this.editForm.goods_cat.length !== 3) {
        this.editForm.goods_cat = []
      }
    },
    // tabs切换之前会触发 去往哪个标签页  oldActiveName之前的标签页
    beforeTabLeave(activeName, oldActiveName) {
      if (this.editForm.goods_cat.length !== 3) {
        this.$message.error('请先选择商品分类!')
        return false
      }
    },
    // tabs标签页切换时会执行 (显示商品的参数和属性)
    async tabClicked() {
      // 判断是否点击动态参数还是静态属性,因为点击其它的不需要
      // 动态参数
      if (this.activeIndex === '1') {
        const { data: res } = await this.$http.get(`categories/${this.cateId}/attributes`, {
          params: { sel: 'many' },
        })
        if (res.meta.status !== 200) {
          return this.$message.error('获取动态参数失败')
        }

        res.data.forEach((item) => {
          item.attr_vals = item.attr_vals ? item.attr_vals.split(' ') : []
        })
        this.manyData = res.data
      
      }
      // 静态属性
      else if (this.activeIndex === '2') {
        const { data: res } = await this.$http.get(`categories/${this.cateId}/attributes`, {
          params: { sel: 'only' },
        })
        if (res.meta.status !== 200) {
          return this.$message.error('获取静态属性失败')
        }

        this.onlyData = res.data
      }
    },
    // 图片预览
    handlePreview(file) {
        this.previewPath=file.url
        this.previewVisible=true
    },
    // 移除图片回调
    handleRemove(file) {
        // 1.获取将要删除的图片的临时路径  ()
        //              服务器图片          新增图片
        const filePath = file.tmp_path || file.response.data.tmp_path
        // 2. 从pics数组中找到这个图片对应的索引值
        const i = this.editForm.pics.findIndex(item=>{
            item.pic===filePath
        })
        // 3. 从pics数组中移除
        this.editForm.pics.splice(i,1)
        
    },
    // 监听图片上传成功
    handleSuccess(response){
      this.editForm.pics.push({
          pic:response.data.tmp_path
      })
      
  },
  // 修改商品功能
  editGoods(){
      this.$refs.editFormRef.validate(async valid=>{
          if(!valid){
              return
          }
          // 准备请求前的数据
          //1.处理商品所属分类数组
        //   不能直接将该数组直接用逗号转换,会导致级联选择器绑定的goods_cat发生异常
          // this,editForm.goods_cat = this.editForm.goods_cat.join(',')
          // 可以使用lodash 工具进行深拷贝
          const form = _.cloneDeep(this.editForm) // 深拷贝
          form.goods_cat = form.goods_cat.join(',')

          //处理动态参数 
        this.manyData.forEach(item=>{
            form.attrs.push({
                attr_id:item.attr_id,
                attr_value:item.attr_vals.join(' ')
            })
        })

        // 处理静态属性
        this.onlyData.forEach(item=>{
            form.attrs.push({
                attr_id:item.attr_id,
                attr_value:item.attr_vals
            })
        })

        // 发送请求
          const {data:res} = await this.$http.post(`goods/${this.editForm.goods_id}`,form)
          if(res.meta.status !== 200){
              return this.$message.error('修改商品失败')
          }
          this.$message.success('修改商品成功!')
          this.$router.push('/goods')
      })
  }
  },
  
  computed: {
    cateId() {
      return this.editForm.goods_cat.length === 3 ? this.editForm.goods_cat[2] : null
    },
  },
}
</script>

<style scoped>
.el-checkbox {
  margin-right: 10px;
}
.preview-img{
    width: 100%;
}

.btn-add{
    margin-top: 15px;
}
</style>
  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

季布,

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值