前端开发Vue项目实战:电商后台管理系统(六)------ 商品管理模块 --- 分类参数功能

本文详细介绍了使用Vue.js组件化开发商品参数管理功能,包括商品分类级联选择、参数列表展示、动态参数与静态属性管理、参数添加、修改、删除等操作,并结合Git进行版本控制。涉及Vue组件、Element UI、级联选择框Cascader、Table表格、Dialog对话框以及Git命令行操作。
摘要由CSDN通过智能技术生成
git checkout -b goods_params

git push -u origin goods_params

1. 参数管理概述

商品参数用于显示商品的固定的特征信息,可以通过电商平台商品详情页面直观的看到;
动态参数供用户在购买商品时候可以进行动态选择;
静态属性供用户查看这个商品的详细信息,是只读的;
在这里插入图片描述

2. 初始化分类参数组件页面

  • 新建文件 components/goods/Params.vue
  • 通过路由组件挂载到页面中
    在这里插入图片描述
<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>
            <!-- 警告区域 -->
            <el-alert  show-icon title="注意:只允许为第三级分类设置相关参数!" type="warning" :closable="false">
            </el-alert>
            <!-- 选择商品分类区域-->
            <el-row class="cat_opt">
                <el-col>
                    <span>选择商品分类:</span>
                    <!-- 选择商品分类的级联选择框 -->
                </el-col>
            </el-row>
        </el-card>
    </div>
</template>

<script>
export default {
    data() {
        return {}
    },
    created() {},
    methods: {},
}
</script>

<style lang="less" scoped>
.cat_opt {
    margin: 20px 0;
}
</style>

3. 选择商品分类模块

3.1 获取商品分类列表数据

在这里插入图片描述

export default {
  data() {
    return {
      // 商品分类列表
      cateList: []
    }
  },
  created() {
    this.getCateList()
  },
  methods: {
    // 获取所有的商品分类列表
    async getCateList(){
      const { data: result } = await this.$http.get('categories')
      if (result.meta.status !== 200) {
        return this.$message.error('获取商品分类列表失败!')
      }
      this.cateList = result.data
    }
  }
}
3.2 商品分类级联选择框cascader
<!-- 选择商品分类的级联选择框 -->
 <el-cascader v-model="selectedCateKeys" :options="catalist" :props="cataProps" 
      @change="handleChange" clearable change-on-select></el-cascader>


  //级联选择框配置属性
    cataProps: {
        expandTrigger: 'hover',
        checkStrictly: true,
        value: 'cat_id', //选中的是哪个属性值
        label: 'cat_name', //看到的是哪个属性值
        children: 'children', //父子节点间通过哪个属性实现嵌套
    },
    //级联选择框双向绑定到的数组
    selectedCateKeys:[],


//控制级联选择框的选中范围
//级联选择框选中框变化,会触发这个函数
handleChange(){
    if(this.selectedCateKeys.length !== 3){
        //选中的不是三级分类,重置数组为空
        this.selectedCateKeys = [] 
        return
    }
},

4. 分类参数Tabs页签

在这里插入图片描述

4.1 渲染Tabs页签
<!-- tab页签区域 -->
<el-tabs v-model="activeName" @tab-click="handleTabClick">
    <el-tab-pane label="动态参数" name="first">动态参数</el-tab-pane>
    <el-tab-pane label="静态属性" name="second">静态属性</el-tab-pane>
</el-tabs>


     //被激活的页签的名称
     activeName:'first'

	// Tab页签点击事件的处理函数
	handleTabClick() {
	  console.log(this.activeName)
	}

4.2 添加参数和添加属性按钮

<!-- 添加动态参数的面板 -->
<el-tab-pane label="动态参数" name="first">
    <!-- 添加参数的按钮 -->
    <el-button type="primary" size="mini" :disabled="isBtnDisabled">添加参数</el-button>
    </el-tab-pane>
<!-- 添加静态属性的面板 -->
<el-tab-pane label="静态属性" name="second">
    <!-- 添加属性的按钮 -->
    <el-button type="primary" size="mini" :disabled="isBtnDisabled">添加属性</el-button>
    </el-tab-pane>


computed: {
  // 如果按钮需要被禁用,返回true,否则返回false
  isBtnDisabled() {
    if (this.selectedCateKeys.length !== 3) {
      return true
    }
    return false
  }
}
4.3 获取参数列表数据(切换面板)

在这里插入图片描述

<!-- tab页签区域   v-model双向数据绑定--当前激活的name页签-->
<el-tabs v-model="activeName" @tab-click="handleTabClick">
    <!-- 添加动态参数的面板 -->
    <el-tab-pane label="动态参数" name="many">
        <!-- 添加参数的按钮 -->
        <el-button type="primary" size="mini" :disabled="isBtnDisabled">添加参数</el-button>
        </el-tab-pane>
    <!-- 添加静态属性的面板 -->
    <el-tab-pane label="静态属性" name="only">
        <!-- 添加属性的按钮 -->
        <el-button type="primary" size="mini" :disabled="isBtnDisabled">添加属性</el-button>
        </el-tab-pane>
</el-tabs>


data() {
        return {
            //被激活的页签的名称
            activeName:'many',
            //动态参数数据
            manyTableData,
            //静态属性数据
            onlyTableData,
        }
    },

methods: {
        //级联选择框选中项变化,会触发这个函数
        handleChange() {
            this.getParamsData()
        },
        //tab页签点击事件的处理函数
        handleTabClick(){
            this.getParamsData()
        },
        //获取参数的列表数据
        async getParamsData(){
             if (this.selectedCateKeys.length !== 3) {
                //选中的不是三级分类,重置数组为空
                this.selectedCateKeys = []
                return
            }
            //选中的是三级分类
            //根据所选的分类id,和当前所处的面板,获取对应的参数
            const {data:res} = await this.$http.get(`categories/${this.cateId}/attributes`, {params:{sel:this.activeName}})
            if(res.meta.status !== 200){
                 return this.$message.error('获取参数列表失败!')
            }
            //成功获取数据
            if(this.activeName === 'many'){
                this.manyTableData = res.data
            }else {
                this.onlyTableData = res.data
            }
        },
    },
computed:{
        //如果按钮需要被禁用,返回true,否则flase
        isBtnDisabled(){
            if (this.selectedCateKeys.length !== 3) {
                return true
            }
            return false
        },
        //当前选中的三级分类的id
        cateId(){
            if (this.selectedCateKeys.length == 3) {
                //选中的第三级分类,返回对应id
                return this.selectedCateKeys[2]
            }
            return null
        },

    },
4.4 动态参数和静态属性Table表格
<!-- 添加动态参数的面板 -->
<el-tab-pane label="动态参数" name="many">
    <!-- 添加参数的按钮 -->
    <el-button type="primary" size="mini" :disabled="isBtnDisabled">添加参数</el-button>
    <!-- 动态参数表格 -->
    <el-table :data="manyTableData" border stripe>
        <!-- 展开行 -->
        <el-table-column type="expand"></el-table-column>
        <!-- 索引列 -->
        <el-table-column type="index"></el-table-column>
        <el-table-column label="参数名称" prop="attr_name"></el-table-column>
        <el-table-column label="操作">
            <template slot-scope="scope">
                <el-button type="primary" icon="el-icon-edit" size="mini">编辑</el-button>
                <el-button type="danger" icon="el-icon-delete" size="mini">删除</el-button>
            </template>
        </el-table-column>
    </el-table>
</el-tab-pane>
<!-- 添加静态属性的面板 -->
<el-tab-pane label="静态属性" name="only">
    <!-- 添加属性的按钮 -->
    <el-button type="primary" size="mini" :disabled="isBtnDisabled">添加属性</el-button>
    <!-- 静态属性表格 -->
    <el-table :data="onlyTableData" border stripe>
        <!-- 展开行 -->
        <el-table-column type="expand"></el-table-column>
        <!-- 索引列 -->
        <el-table-column type="index"></el-table-column>
        <el-table-column label="属性名称" prop="attr_name"></el-table-column>
        <el-table-column label="操作">
            <template slot-scope="scope">
                <el-button type="primary" icon="el-icon-edit" size="mini">编辑</el-button>
                <el-button type="danger" icon="el-icon-delete" size="mini">删除</el-button>
            </template>
        </el-table-column>
    </el-table>

</el-tab-pane>

5. 添加参数模块

5.1 添加参数对话框dialog
<!-- 添加参数的按钮 -->
<el-button type="primary" size="mini" :disabled="isBtnDisabled" @click="adddialogVisible=true">添加参数</el-button>
<!-- 添加属性的按钮 -->
<el-button type="primary" size="mini" :disabled="isBtnDisabled" @click="adddialogVisible=true">添加属性</el-button>


<!-- 添加参数对话框 -->
 <el-dialog :title="'添加' + titleText" :visible.sync="adddialogVisible" width="50%" @close="addDialogClosed">
     <el-form :model="addForm" :rules="addFormRules" ref="addFormRef" label-width="80px">
         <el-form-item :label="titleText" prop="attr_name">
             <el-input v-model="addForm.attr_name"></el-input>
         </el-form-item>
     </el-form>
     <span slot="footer" class="dialog-footer">
         <el-button @click="adddialogVisible = false">取 消</el-button>
         <el-button type="primary" @click="adddialogVisible = false">确 定</el-button>
     </span>
 </el-dialog>


    data() {
        return {
            //控制添加对话框的显示与隐藏
            adddialogVisible: false,
            //添加参数的表单数据对象
            addForm:{
                attr_name:''
            },
            //添加表单的验证规则对象
            addFormRules:{
                attr_name:[{ required: true, message: '请输入参数名称', trigger: 'blur' }],
            },
       }
 },


    methods: {
        //监听添加分类对话框的关闭事件
        addDialogClosed(){
            this.$refs.addFormRef.resetFields()
        },
     }


    computed: {
        //动态计算标题的文本
        titleText() {
            if (this.activeName === 'many') {
                return '动态参数'
            } else {
                return '静态属性'
            }
        },
    },
5.2 添加操作

在这里插入图片描述

<el-button type="primary" @click="addParams">确 定</el-button>

        //点击确定添加参数
        addParams(){
            this.$refs.addFormRef.validate(async (valid) => {
                //valid会返回一个布尔值,如果true就表示校验通过,反之false
                //validate是element-ui表单的一个验证方法
                if (!valid) return //失败了,直接return

                //验证成功,发起添加用户的网络请求
                const { data: res } = await this.$http.post(`categories/${this.cateId}/attributes`,{
                    attr_name: this.addForm.attr_name,
                    attr_sel: this.activeName,
                })
                if (res.meta.status != 201) {
                    this.$message.error('添加参数失败!')
                }
                this.$message.success('添加参数成功!')
                //隐藏添加用户的对话框
                this.addDialogVisible = false
                //重新获取用户列表数据
                this.getParamsData()
            })
        },

6. 修改参数模块

6.1 修改参数对话框dialog
<el-button type="primary" icon="el-icon-edit" size="mini" @click="showEditDialog(scope.row.attr_id)">编辑</el-button>

<!-- 修改参数对话框 -->
 <el-dialog :title="'修改' + titleText" :visible.sync="editdialogVisible" width="50%" @close="editDialogClosed">
     <el-form :model="editForm" :rules="editFormRules" ref="editFormRef" label-width="80px">
         <el-form-item :label="titleText" prop="attr_name">
             <el-input v-model="editForm.attr_name"></el-input>
         </el-form-item>
     </el-form>
     <span slot="footer" class="dialog-footer">
         <el-button @click="editdialogVisible = false">取 消</el-button>
         <el-button type="primary" @click="editParams">确 定</el-button>
     </span>
 </el-dialog>

            //控制修改对话框的显示隐藏
            editdialogVisible:false,
            //修改的表单数据对象
            editForm:{},
            //修改表单的验证规则对象
            editFormRules:{
                attr_name: [{ required: true, message: '请输入参数名称', trigger: 'blur' }],
            },
6.2 修改参数操作

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

//点击按钮,展示修改的对话框
async showEditDialog(attr_id) {
    const { data: res } = await this.$http.get(`categories/${this.cateId}/attributes/${attr_id}`, { params: { attr_sel: this.activeName } })
    if (res.meta.status != 200) {
        this.$message.error('获取参数信息失败!')
    }
    this.editForm = res.data
    this.editdialogVisible = true
},
//重置修改的表单
editDialogClosed() {
    this.$refs.editFormRef.resetFields()
},
//点击按钮,修改参数信息
editParams() {
    this.$refs.editFormRef.validate(async (valid) => {
        if (!valid) return
        const { data: res } = await this.$http.put(`categories/${this.cateId}/attributes/${this.editForm.attr_id}`, {
            attr_name: this.editForm.attr_name,
            attr_sel: this.activeName,
        })
        if (res.meta.status !== 200) {
            return this.$message.error('修改参数失败!')
        }
        this.$message.success('修改参数成功!')
        this.getParamsData() 
        this.editDialogVisible = false
    })
},

7. 删除参数模块

在这里插入图片描述

<el-button type="danger" icon="el-icon-delete" size="mini" @click="removeParams(scope.row.attr_id)">删除</el-button>

        async removeParams(attr_id) {
            const confirmResult = await this.$confirm('此操作将永久删除该参数, 是否继续?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning',
            }).catch((error) => error)

            if (confirmResult !== 'confirm') {
                return this.$message.info('已取消删除')
            }
            const { data: res } = await this.$http.delete(`categories/${this.cateId}/attributes/${attr_id}`)
            if (res.meta.status !== 200) {
                return this.$message.error('删除参数失败!')
            }
            this.$message.success('删除参数成功!')
            this.getParamsData()
        },

8. 渲染参数下的可选项

//获取参数的列表数据
async getParamsData() {
    //打印出来的数据见下图,attr_vals是一个字符串,需要将其分割成数组
    console.log(res.data)
}

在这里插入图片描述

8.1 渲染Tag标签
res.data.forEach(item => {
    item.attr_vals = item.attr_vals.split(' ')
})
console.log(res.data)

在这里插入图片描述

<!-- 展开行 -->
<el-table-column type="expand">
<template slot-scope="scope">
   <el-tag v-for="(item, i) in scope.row.attr_vals" :key="i" closable="">{{item}}</el-tag>
</template>
</el-table-column>


//获取参数的列表数据
async getParamsData() {
    res.data.forEach(item => {
        //三元表达式,判断数组是否为空,不等于空才进行分割,如果等于空返回空数组
        item.attr_vals = item.attr_vals ? item.attr_vals.split(' ') : []
    })
},
8.2 按钮与文本框切换显示(文本框自动获取焦点)

在这里插入图片描述
为每一行数据提供单独的inputVisible和inputValue

<!-- 输入文本框 -->
<el-input class="input-new-tag"  v-if="scope.row.inputVisible" v-model="scope.row.inputValue" 
ref="saveTagInput"  size="small" @keyup.enter.native="handleInputConfirm"  @blur="handleInputConfirm">
</el-input>
<!-- 添加按钮 -->
<el-button v-else class="button-new-tag" size="small" @click="showInput(scope.row)">+ New Tag</el-button>


        //获取参数的列表数据
        async getParamsData() {
            res.data.forEach((item) => {
                //三元表达式,判断数组是否为空,不等于空才进行分割,如果等于空返回空数组
                item.attr_vals = item.attr_vals ? item.attr_vals.split(' ') : []
                //控制文本框的显示隐藏
                item.inputVisible = false
                //文本框中输入的值
                item.inputValue = ''
            })
        }


        //文本框失去焦点或者按下enter都会触发
        handleInputConfirm(){
        },
        //点击按钮,展示文本输入框
        showInput(row) {
        //重置为true,页面元素还没有被渲染,页面展示的还是按钮不是文本输入框
            row.inputVisible = true
            //$nextTick方法的作用:当页面上元素被重新渲染之后,才会指定回调函数中的代码
            this.$nextTick((_) => {
                //第一个$refs是拿到组件saveTagInput,该组件中通过$refs拿到HTML元素input,而input自带focus方法
                this.$refs.saveTagInput.$refs.input.focus()
            })
        },
8.3 文本框与按钮的切换显示

在这里插入图片描述

//文本框失去焦点或者按下enter都会触发
async handleInputConfirm(row) {
    if (row.inputValue.trim().length === 0) {
        row.inputValue = ''
        //隐藏文本输入框
        row.inputVisible = false
        return
    }
    //没有return,证明有输入内容,进行后续处理
    row.attr_vals.push(row.inputValue.trim())
    row.inputValue = ''
    row.inputVisible = false
    
    //发起请求保存这次操作
    const {data:res} = await this.$http.put(`categories/${this.cateId}/attributes/${row.attr_id}`,{
        attr_name:row.attr_name,
        attr_sel:row.attr_sel,
        attr_vals:row.attr_vals.join(''),
    })
    if (res.meta.status !== 200) {
        return this.$message.error('修改参数项失败!')
    }
    this.$message.success('修改参数项成功!')
},
8.4 删除参数下可选项
<!-- 循环渲染tag标签 -->
<el-tag v-for="(item, index) in scope.row.attr_vals" :key="index" closable @close="handleClose(index,scope.row)">{{item}}</el-tag>

// 文本框失去焦点,或按下Enter键,都会触发
handleInputConfirm(row) {
  // console.log('ok')
  if (row.inputValue.trim().length === 0) {
    row.inputValue = ''
    row.inputVisible = false
    return
  }
  // 如果没有return,则说明有输入的内容,需要做后续的处理
  row.attr_vals.push(row.inputValue.trim())
  row.inputValue = ''
  row.inputVisible = false
  this.saveAttrVals(row)
},
    // 删除对应的参数可选项
handleClose(i, row) {
  row.attr_vals.splice(i, 1)
  this.saveAttrVals(row)
},
// 将对 attr_vals的操作,保存到数据库
async saveAttrVals(row) {
  // 需要发起请求保存操作
  const { data: result } = await this.$http.put(`categories/${this.cateId}/attributes/${row.attr_id}`, {
    attr_name: row.attr_name,
    attr_sel: row.attr_sel,
    attr_vals: row.attr_vals.join(' ')
  })
  if (result.meta.status !== 200) {
    return this.$message.error('修改参数项失败!')
  }
  this.$message.success('修改参数项成功!')
}

9. 清空表格数据

选中的不是三级分类设置,清空表格数据

// 获取参数的列表数据
async getParamsData() {
  // console.log(this.selectedCateKeys)
  // 选中的不是三级分类,就重置数组
  if (this.selectedCateKeys.length !== 3) {
    this.selectedCateKeys = []
    this.manyTableData = []
    this.onlyTableData = []
  }
}

静态属性表格中展开行效果直接将静态参数的展开行html复制过去

10. 提交代码

git branch
git add .
git commit -m "完成了分类参数的开发"
git push
git checkout master
git merge goods_params
git push

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值