zoukankan      html  css  js  c++  java
  • 商品列表和添加商品(六)

    实现的功能

    功能 详述
    商品列表 渲染组件和子路由;布局;获取和渲染商品列表;自定义格式化时间全局过滤器;搜索和清空;删除商品
    添加商品页 渲染组件和子路由;布局;步骤条纵向Tab页;步骤条和标签页联动
    基本信息表单 商品分类使用级联选择器,只允许选中三级阻止标签页切换
    动态参数页 复选框tag;根据不同tab页执行不同操作
    图片上传 渲染组件;图片上传图片删除图片预览
    富文本编辑器
    添加商品 深拷贝

    使用到的Element-ui组件

    组件名称_EN 注册 备注
    Steps Vue.use(Steps) 步骤条
    Step Vue.use(Step)
    CheckboxGroup Vue.use(CheckboxGroup) 多选框
    Checkbox Vue.use(Checkbox)
    Upload Vue.use(Upload) 上传

    使用到的依赖

    运行依赖,富文本编辑器vue-quill-editor

    // [main.js]
    // 导入富文本编辑器
    import VueQuillEditor from 'vue-quill-editor'
    // 导入富文本编辑器对应样式
    import 'quill/dist/quill.core.css' // import styles
    import 'quill/dist/quill.snow.css' // for snow theme
    import 'quill/dist/quill.bubble.css' // for bubble theme
    
    // 注册富文本编辑器
    Vue.use(VueQuillEditor)
    

    运行依赖,lodash深拷贝lodash

    // [Add.vue -> methods]
    import _ from 'lodash'
    

    一、商品列表

    1.渲染组件和子路由

    2.布局

    ①面包屑导航

    ②卡片视图

    ③栅格系统 搜索框 添加按钮

    ④表格

    ⑤分页

    3.获取渲染商品列表

    ①获取商品列表

    ②渲染商品列表

    1️⃣自定义格式化时间全局过滤器

    // [main.js]
    Vue.filter('dataFormat', function (originVal) {
      const dt = new Date(originVal)
      const y = dt.getFullYear()
      const m = (dt.getMonth() + 1 + '').padStart(2, '0')
      const d = (dt.getDate() + '').padStart(2, '0')
    
      const hh = (dt.getHours() + '').padStart(2, '0')
      const mm = (dt.getMinutes() + '').padStart(2, '0')
      const ss = (dt.getSeconds() + '').padStart(2, '0')
    
      return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
    
    })
    
    <!-- [GoodsList.vue] -->
    <el-table-column label="创建时间" width="140px">
        <template slot-scope="scope">{{scope.row.add_time | dataFormat}}</template>
    </el-table-column>
    

    4、搜索和清空

    5、根据Id删除商品

    6、添加商品页跳转

    1️⃣编程式导航

    // [GoodsList.vue]
    goAddpage(){
        this.$router.push('/goods/add')
    }
    // [index.js]
    const routes = [
        // ......
        {path:'/goods/add',component:Add},
        // ......
    ]
    

    二、添加商品页

    1.渲染组件和子路由

    2.布局

    ①面包屑导航

    ②卡片视图

    ③警告

    ④步骤条Steps

    :active="activeIndex-0":激活项

    <!-- [Add.vue] -->
    <!-- 步骤条 -->
    <el-steps :space="200" :active="activeIndex-0" finish-status="success" align-center>
        <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>
    
    // [Add.vue -> data]
    activeIndex: '0'
    
    /* [assets/css/global.css] */
    .el-steps{
        margin: 15px 0;
    }
    .el-step__title{
        font-size: 13px;
    }
    

    ⑤纵向标签页Tabs

    <!-- [Add.vue] -->
    <el-tabs
              :tab-position="'left'"
              v-model="activeIndex"
              :before-leave="beforeTabLeave"
              @tab-click="tabClicked"
            >
              <el-tab-pane label="基本信息" name="0"></el-tab-pane>
              <el-tab-pane label="商品参数" name="1"></el-tab-pane>
              <el-tab-pane label="商品图片" name="3"></el-tab-pane>
              <el-tab-pane label="商品内容" name="4"></el-tab-pane>
    </el-tabs>
    

    ⑥步骤条和标签页联动

    activeIndex: '0',

    步骤条:active

    ​ 转换activeIndex为数值

    标签页:v-model

    ​ 激活的name会绑定到v-model上

    ⑦表单

    使用form包裹tabs,el-tabs必须和el-tab-pane嵌套

    3、基本信息

    ①渲染基本信息表单

    1️⃣商品分类使用级联选择器,只允许选中三级

    // [Add.vue -> methods]
    // 级联选择器选中项变化
    handleChange() {
        // 选中的不是三级分类
        if (this.addForm.goods_cat.length !== 3) {
            this.addForm.goods_cat = []
        }
    }
    

    2️⃣阻止标签页切换

    :before-leave="beforeTabLeave":标签页属性,离开时触发

    oldActiveName:离开的标签页name

    activeName:进入的标签页name

    // [Add.vue -> methods]
    beforeTabLeave(activeName, oldActiveName) {
        if (oldActiveName === '0' && this.addForm.goods_cat.length !== 3) {
            this.$message.error('请先选择商品分类')
            return false
        }
    }
    

    ②获取商品分类数据

    4、动态参数

    ①获取动态参数

    @tab-click="tabClicked":标签页属性,点击时触发,可以获取activeIndex访问的tab面板

    // [Add.vue -> methods]
    async tabClicked() {
          if (this.activeIndex === '1') {
              // 访问动态参数面板
              // ......
          } else if (this.activeIndex === '2') {
              // 访问静态属性面板
              // ......
          }
        },
    

    ②渲染动态参数

    // [Add.vue -> methods]
    async tabClicked() {
        if (this.activeIndex === '1') {
            // ......
            res.data.forEach((item) => {
                item.attr_vals = 
                    item.attr_vals.length === 0 ? [] : item.attr_vals.split(',')
            })
        }
        // ......
    }
    
    <!-- [Add.vue] -->
    <el-tab-pane label="商品参数" name="1">
        <el-form-item :label="item.attr_name" v-for="item in manyTableData" :key="item.attr_id">
            <!-- 复选框组 -->
            <el-checkbox-group v-model="item.attr_vals">
                <el-checkbox :label="cb" v-for="(cb,i) in item.attr_vals" :key="i" border></el-checkbox>
            </el-checkbox-group>
        </el-form-item>
    </el-tab-pane>
    

    5、静态属性

    ①获取静态属性

    ②渲染静态属性

    6、图片上传

    action:图片上传的api地址

    :on-preview:图片预览

    :on-remove:删除图片

    :headers:上传的请求头

    :on-success:图片上传成功后处理操作

    ①渲染图片+上传

    <!-- [Add.vue] -->
    <el-tab-pane label="商品图片" name="3">
        <!-- 上传 -->
        <el-upload
                   :action="uploadURl"
                   :on-preview="handlePreview"
                   :on-remove="handleRemove"
                   list-type="picture"
                   :headers="headerObj"
                   :on-success="handleSuccess"
                   >
            <el-button size="small" type="primary">点击上传</el-button>
        </el-upload>
    </el-tab-pane>
    
    // [Add.vue -> data]
    uploadURl: 'http://127.0.0.1:8888/api/private/v1/upload',
    // 图片上传的headers请求头对象
    headerObj: {
        Authorization: window.sessionStorage.getItem('token'),
    },
    
    // [Add.vue -> methods]    
    // 监听图片上传成功
    handleSuccess(response) {
        // 1,拼接得到一个图片信息对象
        const picInfo = { pic: response.data.tmp_path }
        //2,将图片信息对象,push 到pics数组中
        this.addForm.pics.push(picInfo)
    },
    

    ②图片移除

    // 处理移除图片
    handleRemove(file) {
        // 1,获取将要删除的图片的临时路径
        const filePath = file.response.data.tmp_path
        // 2.从pics数组中,找到这个图片对应的索引值
        const i = this.addForm.pics.findIndex((x) => x.pic === filePath)
        // 3.调用数组的 splice方法,把图片信息对象,从pics数组中移除
        this.addForm.pics.splice(i, 1)
    },
    

    ③图片预览

    <!-- 图片预览 -->
    <el-dialog title="图片预览" :visible.sync="previewDialogVisible" width="50%">
        <img :src="previewPath" alt class="previewImg" />
    </el-dialog>
    
    // [Add.vue -> data]
    previewPath: '',
    previewDialogVisible: false
    
    // [Add.vue -> methods]    
    // 处理图片预览
    handlePreview(file) {
        this.previewPath = file.response.data.url
        this.previewDialogVisible = true
    }
    

    7、富文本编辑器

    <!-- [Add.vue] -->
    <el-tab-pane label="商品内容" name="4">
        <!-- 富文本编辑器 -->
        <quill-editor v-model="addForm.goods_introduce"></quill-editor>
        <el-button type="primary" class="btnAdd" @click="add">添加商品</el-button>
    </el-tab-pane>
    
    /* [assets/css/global.css] */
    .ql-editor{
        min-height: 300px;
    }
    

    8、添加商品

    表单预校验,校验通过发起请求

    ①预校验

    // [Add.vue -> methods]  
    // 添加商品
    async add() {
        // 预校验
        this.$refs.addFormRulesRef.validate((valid) => {
            if (!valid) return this.$message.error('请填写必要的表单项')
        })
        // ......
    }
    

    ②深拷贝

    级联选择器要求数组,请求要求字符串---->深拷贝

    // [Add.vue -> methods]  
    // 添加商品
    async add() {
        // ......
        
        // 执行添加的业务逻辑
        // 深拷贝 lodash  this.addForm双向绑定级联选择器会报错
        const form = _.cloneDeep(this.addForm)
        form.goods_cat = form.goods_cat.join(',')
        // ......
    }
    

    ③商品参数(动态参数+静态属性)

    // [Add.vue -> methods]  
    // 添加商品
    async add() {
        // ......
        // 处理动态参数
        this.manyTableData.forEach((item) => {
            const newInfo = {
                attr_id: item.attr_id,
                attr_value: item.attr_vals.join(','),
            }
            this.addForm.attrs.push(newInfo)
        })
        // 处理静态属性
        this.onlyTableData.forEach((item) => {
            const newInfo = {
                attr_id: item.attr_id,
                attr_value: item.attr_vals,
            }
            this.addForm.attrs.push(newInfo)
        })
        form.attrs = this.addForm.attrs
        // ......
    }
    

    ④发起请求

    // [Add.vue -> methods]  
    // 添加商品
    async add() {
        // ......
        // 发起请求
        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')
    }
    
  • 相关阅读:
    c# PrintDocument 设置自定义纸张大小的示例
    C#获取本地打印机列表,并将指定打印机设置为默认打印机
    水晶报表自定义纸张大小打印 (Crystal Report Print with custom paper size)
    c#打印机设置,取得打印机列表及相应打印机的所有纸张格式
    在C#中设置打印机纸张大小
    打印grid
    获取List集合中最大值的方法
    mysql使用索引优化查询效率
    mysql数据库中标的key的含义
    mysql数据库添加索引优化查询效率
  • 原文地址:https://www.cnblogs.com/wattmelon/p/13574042.html
Copyright © 2011-2022 走看看