HM后台(四点二)
一,商品管理中的商品参数页面搭建

1.1,商品参数组件的路由配置
{ path: '/home', component: Home, // 重定向 redirect: '/welcome', children: [ { path: '/welcome', component: Welcome }, { path: '/users', component: User }, { path: '/rights', component: Rights }, { path: '/roles', component: Roles }, { path: '/categories', component: Cate }, { path: '/params', component: Params } ] }
1.2,页面一加载,发送请求,获取所有的商品分类列表数据
mounted() { 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) },
<!-- 面包屑导航区域 -->
<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 style="margin-top:20px">
<!-- 警告区域 -->
<el-alert
show-icon
title="注意:只允许为第三级分类设置相关参数!"
type="warning"
:closable="false"
></el-alert>
<!-- 选择商品分类区域 -->
<el-row class="cat_opt">
<el-col>
<span>选择商品分类:</span>
<!-- 选择商品分类的级联选择框 -->
<el-cascader
:options="catelist"
:props="cateProps"
v-model="selectedCateKeys"
@change="handleChange"
>
</el-cascader>
</el-col>
</el-row>
</el-card>
在data中定义属性
data() { return { // 商品分类列表 catelist: [], // 级联选择框的配置对象 cateProps: { value: 'cat_id', label: 'cat_name', children: 'children', expandTrigger: 'click', checkStrictly: true }, // 级联选择框双向绑定到的数组 selectedCateKeys: []
1.3, 选项卡页面搭建



<!-- tab页标签区域 -->
<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中定义
// 被激活的页签的名称 activeName: 'many',
// tab 页签点击事件的处理函数 handleTabClick() { console.log(this.activeName) },
如果用户选中了三级分类,则按钮是高亮的,如果没选中,则按钮禁用,computed计算
computed:{ // 如果按钮需要被禁用,则返回true,否则返回false isBtnDisabled() { if (this.selectedCateKeys.length !== 3) { return true } return false } },
级联选择框的选中事件触发,发送参数列表请求(需要收集三级的id)
请求参数

计算三级分类id
// 当前选中的三级分类的Id cateId() { if (this.selectedCateKeys.length === 3) { return this.selectedCateKeys[2] } return null }
// 级联选择框选中项变化,会触发这个函数 async handleChange() { // 判断是否是三级分类,然后发送请求,获取参数列表 if (this.selectedCateKeys.length !== 3) { this.selectedCateKeys = [] return } // 是三级分类 // 根据所选分类的Id,和当前所处的面板,获取对应的参数 const { data: res } = await this.$http.get(`categories/${this.cateId}`, { params: { sel: this.activeName } }) if (res.meta.status === 200) { // console.log(res) } else { this.$message.error('获取数据失败') } //console.log(this.selectedCateKeys) },
1.4, 此时,三类分类的id已收集,如果用户在触发选中tabs的时候,也要发送参数分类请求,分别获取动态参数的数据和静态属性的数据
我们需要把发送请求,获取的数据单独封装一个函数,在级联选中三级id时,或者触发选中tabs时调用该函数

// 获取参数的列表数据 async getParamsData() { // 判断是否是三级分类,然后发送请求,获取参数列表 if (this.selectedCateKeys.length !== 3) { this.selectedCateKeys = [] return } // 是三级分类 // 根据所选分类的Id,和当前所处的面板,获取对应的参数 const { data: res } = await this.$http.get(`categories/${this.cateId}`, { params: { sel: this.activeName } }) if (res.meta.status === 200) { // console.log(res) // 判断tabs的名称,分别获取不同的数据 if (this.activeName === 'many') { this.manyTableData = res.data } else if (this.activeName === 'only') { this.onlyTableData = res.data } } else { this.$message.error('获取数据失败') } // console.log(this.selectedCateKeys) }
在两个时间点调用该函数
// 级联选择框选中项变化,会触发这个函数 handleChange() { this.getParamsData() },
// tab 页签点击事件的处理函数 handleTabClick() { this.getParamsData() // console.log(this.activeName) },
在data中定义获取的数据
// 动态参数的数据 manyTableData: [], // 静态属性的数据 onlyTableData: [], }
1.5, 动态参数表格和静态属性表格搭建

<!-- tab页标签区域 -->
<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-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="{row,$index}">
<el-button size="mini" type="primary" icon="el-icon-edit" >编辑</el-button>
<el-button size="mini" type="danger" icon="el-icon-delete" >删除</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="{row,$index}">
<el-button size="mini" type="primary" icon="el-icon-edit" >编辑</el-button>
<el-button size="mini" type="danger" icon="el-icon-delete" >删除</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
1.6,点击添加参数或者添加属性按钮,弹出添加参数的对话框

titleText() { // 判断tabs的名称 if (this.activeName === 'many') { return '动态参数' } else { return '静态属性' } }
<!-- 添加参数的对话框 -->
<el-dialog
:title="`添加${titleText}`"
:visible.sync="addDialogVisible"
width="50%"
@close="addDialogClosed"
>
<!-- 添加参数的对话框 -->
<el-form
:model="addForm"
:rules="addFormRules"
ref="addFormRef"
label-width="100px"
>
<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中定义
addDialogVisible: false, // 收集动态/静态的属性 addForm: { attr_name: '' }, // 添加表单的验证规则对象 addFormRules: { attr_name: [ { required: true, message: '请输入参数名称', trigger: 'blur' } ] },
关闭dialog,清空参数
// 监听添加对话框的关闭事件 addDialogClosed() { this.$refs.addFormRef.resetFields() }
<span slot="footer" class="dialog-footer"> <el-button @click="addDialogVisible = false">取 消</el-button> <el-button type="primary" @click="addParams" >确 定</el-button > </span> </el-dialog>
// 点击确定按钮,添加参数 addParams() { this.$refs.addFormRef.validate(async valid => { if (!valid) 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) { return this.$message.error('添加参数失败!') } this.$message.success('添加参数成功!') this.addDialogVisible = false // 重新发送获取参数列表的请求 this.getParamsData() }) },
1.8,点击编辑按钮,弹出修改的dialog

点击编辑按钮,弹出修改框
<el-table-column label="操作"> <template slot-scope="{ row, $index }"> <el-button size="mini" type="primary" icon="el-icon-edit" @click="showEditDialog()" >编辑</el-button >
// 点击编辑按钮,弹出修改dialog showEditDialog() { this.editDialogVisible = true }
<!-- 修改参数的对话框 -->
<el-dialog
:title="'修改' + titleText"
:visible.sync="editDialogVisible"
width="50%"
@close="editDialogClosed"
>
<!-- 添加参数的对话框 -->
<el-form
:model="editForm"
:rules="editFormRules"
ref="editFormRef"
label-width="100px"
>
<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="editDialogVisible = false">确定</el-button>
>确 定</el-button
>
</span>
</el-dialog>
在data中定义
// 控制修改对话框的显示与隐藏 editDialogVisible: false, // 修改的表单数据对象 editForm: { }, // 修改表单的验证规则对象 editFormRules: { attr_name: [ { required: true, message: '请输入参数名称', trigger: 'blur' } ] }
1.9,点击编辑按钮,根据属性id和分类id来发送请求,获取修改表单的数据
请求参数

// 点击编辑按钮,弹出修改dialog async showEditDialog(attrId) { // 根据参数id和父级分类id来发送请求 const {data :res} = await this.$http.get(`categories/${this.cateId}/attributes/${attrId}`,{params:{attr_sel:this.activeName}}) if(res.meta.status ===200){ this.editForm = res.data this.editDialogVisible = true }else{ this.$message.error('请求失败') } }
关闭修改的dialog,清空数据
<!-- 修改参数的对话框 -->
<el-dialog
:title="'修改' + titleText"
:visible.sync="editDialogVisible"
width="50%"
@close="editDialogClosed"
>
// 重置修改的表单 editDialogClosed() { this.$refs.editFormRef.resetFields() },
1.10,编辑弹框,点击确定按钮,发送请求,是否编辑成功
请求参数

// 编辑提交按钮,发送请求 async editParams(){ // 表单校验 this.$refs.editFormRef.validate((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){ this.$message.success('编辑成功') this.editDialogVisible = true // 重新发送请求,获取新的参数列表 this.getParamsData() }else{ this.$message.error('编辑失败') } }) }
1.11, 点击删除按钮,发送请求,删除属性
<el-button size="mini" type="danger" icon="el-icon-delete" @click="removeParams(row.attr_id)" >删除</el-button > </template>
// 点击删除按钮,发送请求,删除属性 async removeParams(attrId){ // messageBox弹出删除框 const result = await this.$confirm('此操作将永久删除该属性, 是否继续?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).catch((error)=>error) // 点击确定 if(result = 'confirm'){ // 发送删除请求 const {data:res} = await this.$http.delete(`categories/${this.cateId}/attributes/${attrId}`) if(res.meta.status ===200){ this.$message.success('删除成功') // 重新发送请求,获取最新的参数列表 this.getParamsData() } } }

// 获取参数的列表数据 async getParamsData() { // 判断是否是三级分类,然后发送请求,获取参数列表 if (this.selectedCateKeys.length !== 3) { this.selectedCateKeys = [] return } // 是三级分类 // 根据所选分类的Id,和当前所处的面板,获取对应的参数 const { data: res } = await this.$http.get(`categories/${this.cateId}`, { params: { sel: this.activeName } }) if (res.meta.status === 200) { // 将attr_vals参数值整理成数组,字符串分割成数组 res.data.forEach(item =>{ item.attr_vals = item.attr_vals.split(',') }) // console.log(res) // 判断tabs的名称,分别获取不同的数据 if (this.activeName === 'many') { this.manyTableData = res.data } else if (this.activeName === 'only') { this.onlyTableData = res.data } } else { this.$message.error('获取数据失败') } // console.log(this.selectedCateKeys) },
<!-- 动态参数表格 -->
<el-table :data="manyTableData" border stripe>
<!-- 展开行 -->
<el-table-column type="expand">
<template slot-scope="{row, $index}">
<el-tag type="danger" size="normal" closable
v-for="(item, index) in row.attr_vals" :key="index"
>{{item}}</el-tag>
</template>
</el-table-column>
此时有个小bug,新增一个参数,那个会在attr_vals中新增一个空字符串,页面呈现的效果


那么怎么办呢,我们需要在将attr_vals属性整理成数组时,需要判断下是不是空窜
// 获取参数的列表数据 async getParamsData() { // 判断是否是三级分类,然后发送请求,获取参数列表 if (this.selectedCateKeys.length !== 3) { this.selectedCateKeys = [] return } // 是三级分类 // 根据所选分类的Id,和当前所处的面板,获取对应的参数 const { data: res } = await this.$http.get(`categories/${this.cateId}`, { params: { sel: this.activeName } }) if (res.meta.status === 200) { // 将attr_vals参数值整理成数组,字符串分割成数组 res.data.forEach(item => { item.attr_vals = item.attr_vals ? item.attr_vals.split(',') : [] })
此时的效果

1.13,动态编辑标签,添加添加button按钮,变成input,input失去焦点或者enter键,变成button按钮

<!-- 输入框 -->
<el-input
class="input-new-tag"
v-if="inputVisible"
v-model="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"
>+ New Tag</el-button
>
在data中定义
inputVisible: false, inputValue: ''
定义函数
// input框失去焦点或者按下enter,触发 handleInputConfirm() { console.log('ok') }, // 点击添加按钮,变成input框 showInput(){ this.inputVisible = true }
此时有个小bug,表格中遍历了数据,当你点击button按钮,变成input框,下一行的情况也是这样,因为inputVisible,inputValue这两个属性是组件公共的,我们需要在请求列表参数
的时候,对每一个列表添加这两个属性,此时他们是每个参数的,不是公共的

// 获取参数的列表数据 async getParamsData() { // 判断是否是三级分类,然后发送请求,获取参数列表 if (this.selectedCateKeys.length !== 3) { this.selectedCateKeys = [] return } // 是三级分类 // 根据所选分类的Id,和当前所处的面板,获取对应的参数 const { data: res } = await this.$http.get(`categories/${this.cateId}`, { params: { sel: this.activeName } }) if (res.meta.status === 200) { // 将attr_vals参数值整理成数组,字符串分割成数组 res.data.forEach(item => { item.attr_vals = item.attr_vals ? item.attr_vals.split(',') : [] // 往每一个参数列表添加inputVisible,inputValue item.inputVisible = false item.inputValue = '' }) // console.log(res) // 判断tabs的名称,分别获取不同的数据 if (this.activeName === 'many') { this.manyTableData = res.data } else if (this.activeName === 'only') { this.onlyTableData = res.data } } else { this.$message.error('获取数据失败') } // console.log(this.selectedCateKeys) },
页面改造
<!-- 输入框 -->
<el-input
class="input-new-tag"
v-if="inputVisible"
v-model="row.inputValue"
ref="saveTagInput"
size="small"
@keyup.enter.native="handleInputConfirm(row)"
@blur="handleInputConfirm(row)"
>
</el-input>
那么data中的定义属性就可删除了
inputVisible: false, inputValue: ''

button变成input自动获取焦点
// 点击添加按钮,变成input框 showInput() { this.inputVisible = true // 让文本框自动获得焦点 // $nextTick 方法的作用,就是当页面上元素被重新渲染之后,才会指定回调函数中的代码 this.$nextTick(_ => { this.$refs.saveTagInput.$refs.input.focus() }) }
当input失去焦点或者enter键,我们需要将参数保存到参数值数组attr_vals中,并发送请求,保存到数据库中
请求参数

注,此时attr_vals,是一个数组,我们需要将他改造成字符串,用jion方法
// input框失去焦点或者按下enter,触发 async handleInputConfirm(row) { // console.log('ok') // 判断空格 if (row.inputValue.trim()) { // 将新增的属性添加到attr_vals数组中 row.attr_vals.push(row.inputValue) // 变成button按钮 this.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.code === 200) { this.$message.error('添加参数成功') } } },
<!-- 展开行 -->
<el-table-column type="expand">
<template slot-scope="{ row, $index }">
<el-tag
type="danger"
size="normal"
closable
@close="handleClose(index, row)"
v-for="(item, index) in row.attr_vals"
:key="index"
>{{ item }}</el-tag
>
// 将对 attr_vals 的操作,保存到数据库 async saveAttrVals(row) { // 发送请求,将他添加到数据库中 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.code === 200) { this.$message.error('添加参数成功') } else { this.$message.error('添加失败') } }
// tag按钮删除操作哦 handleClose(index, row) { row.attr_vals.splice(index, 1) // 发送请求,提交参数 this.saveAttrVals(row) },
// input框失去焦点或者按下enter,触发 async handleInputConfirm(row) { // console.log('ok') // 判断空格 if (row.inputValue.trim()) { // 将新增的属性添加到attr_vals数组中 row.attr_vals.push(row.inputValue) // 变成button按钮 this.inputVisible = false // 发送请求,提交参数 this.saveAttrVals(row) } },
// 获取参数的列表数据 async getParamsData() { // 判断是否是三级分类,然后发送请求,获取参数列表 if (this.selectedCateKeys.length !== 3) { this.selectedCateKeys = [] this.manyTableData = [] this.onlyTableData = [] return } // 是三级分类 // 根据所选分类的Id,和当前所处的面板,获取对应的参数 const { data: res } = await this.$http.get(`categories/${this.cateId}`, { params: { sel: this.activeName } }) if (res.meta.status === 200) { // 将attr_vals参数值整理成数组,字符串分割成数组 res.data.forEach(item => { item.attr_vals = item.attr_vals ? item.attr_vals.split(',') : [] // 往每一个参数列表添加inputVisible,inputValue item.inputVisible = false item.inputValue = '' }) // console.log(res) // 判断tabs的名称,分别获取不同的数据 if (this.activeName === 'many') { this.manyTableData = res.data } else if (this.activeName === 'only') { this.onlyTableData = res.data } } else { this.$message.error('获取数据失败') } // console.log(this.selectedCateKeys) },


浙公网安备 33010602011771号