VUE项目-第十一天
01-反馈
姓名 意见或建议
*** 老师辛苦了
*** 老湿你在角色权限那关键部位(角色分配一二三级权限那儿)讲的有点快啊,跟不上咧
- 代码:听不会 看不会 实践 敲一遍
02-回顾
- 权限分配
- 获取所有的权限 rightTree
- 获取当前角色拥有的权限(不含父级,第三级) rightCheckedList
- 默认选中拥有的权限
- 修改权限:不能自动获取数据
- 主动的去获取选中(包含半选)的权限:tree的dom上提供方法
- getCheckedKeys getHalfCheckedKeys
- 最后合并 提交 即可
- 学习 jQuery (zepto.js) bootstrap vue element-ui
- 树状控件
- 数据格式:[{id:'',authName:'',children:[{children:[{},{}]},{}]},{},{}]
- 显示label: props = {label:'authName'}
- 树状表格
- 级联选择器
03-分类参数-组件基础布局
<el-card>
<el-alert
title="注意:只有第三级分类才能设置参数。"
type="warning"
show-icon>
</el-alert>
<el-form style="margin: 15px 0">
<el-form-item label="选择商品分类:">
<el-cascader
expand-trigger="hover"
:options="categoryList"
v-model="categoryValues"
@change="handleChange">
</el-cascader>
</el-form-item>
</el-form>
<!-- activeName 就是当前选中的tab的name的值 -->
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="动态参数" name="many">
<el-button type="success" :disabled="disabled">添加动态参数</el-button>
</el-tab-pane>
<el-tab-pane label="静态参数" name="only">
<el-button type="success" :disabled="disabled">添加静态参数</el-button>
</el-tab-pane>
</el-tabs>
</el-card>
data () {
return {
// 分类级联相关的数据
categoryList: [],
categoryValues: [],
// tabs相关的数据
activeName: 'many',
disabled: true
}
},
methods: {
handleChange () {
}
}
04-分类参数-分类级联选择器
<el-cascader
expand-trigger="hover"
:options="categoryList"
v-model="categoryValues"
:props="{value:'cat_id',label:'cat_name'}"
@change="handleChange">
</el-cascader>
async getData () {
// 获取三级分类数据 且赋值给级联组件
const {data: {data, meta}} = await this.$http.get('categories')
if (meta.status !== 200) return this.$message.error('获取分类数据失败')
console.log(data)
this.categoryList = data
}
05-分类参数-获取参数列表准备
- 需求:根据当前选中的tab去加载对应的(动态、静态)列表数据
- 时机:选择了三级分类的时候,切换tab的时候 回去调用 getParams的函数获取参数列表
- 细节:
-
只有选择了三级分类才加载数据
-
怎么通过传参的方式去区别动态还是静态 通过接口文档去判断
-
categories/:id/attributes id是三级分类的ID
-
区别动态还是静态 :通过 sel 的参数 many动态 only静态
-
发现:activeName 就是需要的数据
getParams () { // 获取参数列表数据 获取的两种 // 传递的数据需要准备 三级分类ID 当前选中的参数类型 动态 静态 activeName // 三级分类ID 首先要判断是否有三级分类 const len = this.categoryValues.length if (len === 3) { // 选了三级 const id = this.categoryValues[len - 1] // 发请求获取数据 console.log(id) this.disabled = false } else { // 没选三级 // 清空当前不符合要求的选择 this.categoryValues = [] this.disabled = true } }
-
获取数据:
// 发请求获取数据
const {data: {data, meta}} = await this.$http.get(`categories/${id}/attributes`, {
params: {sel: this.activeName}
})
if (meta.status !== 200) return this.$message.error('获取参数数据失败')
// 参数列表获取成功 显示列表 依赖数据 data定义数据
// 给谁赋值数据??? 根据当前选中的tab去给 manyAttrs onlyAttrs 赋值
// 根据当前的 activeName 去找到对应的列表 赋值
this[`${this.activeName}Attrs`] = data
// 动态参数列表
manyAttrs: [],
// 静态参数列表
onlyAttrs: []
06-分类参数-渲染动态参数列表
<el-table :data="manyAttrs">
<el-table-column type="expand">
<template slot-scope="scope">
<el-tag v-for="(item,i) in scope.row.attr_vals.split(',')" :key="i" size="normal" closable>{{item}}</el-tag>
</template>
</el-table-column>
<el-table-column label="属性名称" prop="attr_name"></el-table-column>
<el-table-column label="操作" width="120px">
<template slot-scope="scope">
<el-button icon="el-icon-edit" circle></el-button>
<el-button icon="el-icon-delete" circle></el-button>
</template>
</el-table-column>
</el-table>
07-分类参数-渲染静态参数列表
<el-table :data="onlyAttrs">
<el-table-column type="index" width="100px" align="center"></el-table-column>
<el-table-column label="属性名称" prop="attr_name"></el-table-column>
<el-table-column label="属性值">
<template slot-scope="scope">
<el-tag size="normal" style="width: 300px">{{scope.row.attr_vals}}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="120px">
<template slot-scope="scope">
<el-button icon="el-icon-edit" circle></el-button>
<el-button icon="el-icon-delete" circle></el-button>
</template>
</el-table-column>
</el-table>
08-分类参数-添加参数
- 添加动态的参数 和 添加静态的参数 对话框可以使用同一个
- 只是:标题不一致 提交时候参数的类型不一致
准备一个对话框:
<!-- 添加参数对话框 -->
<el-dialog :title="activeName==='many'?'添加动态参数':'添加静态参数'" width="400px" :visible.sync="addDialogFormVisible">
<el-form ref="addForm" :model="addForm" :rules="addRules" label-width="100px" autocomplete="off">
<el-form-item label="参数名称" prop="attr_name">
<el-input v-model="addForm.attr_name"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="addDialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="addSubmit()">确 定</el-button>
</div>
</el-dialog>
提交:
showAddDialog () {
this.addDialogFormVisible = true
this.$nextTick(() => {
this.$refs.addForm.resetFields()
})
},
addSubmit () {
// 提交添加的参数
this.$refs.addForm.validate(async valid =>{
if (valid) {
// 发请求
// 获取第三级分类的ID
const id = this.categoryValues[2]
const {data: {meta}} = await this.$http.post(`categories/${id}/attributes`, {
attr_name: this.addForm.attr_name,
attr_sel: this.activeName
})
if (meta.status !== 201) return this.$message.error('添加参数失败')
this.$message.success('添加参数成功')
// 更新列表
this.getParams()
// 关闭对话框
this.addDialogFormVisible = false
}
})
},
数据:
// 对话框相关数据
addDialogFormVisible: false,
addForm: {
attr_name: ''
},
addRules: {
attr_name: [
{required: true, message: '参数名称必填', trigger: 'blur'}
]
}
09-分类参数-删除动态参数
11-分类参数-删除静态参数
- 根据后台的要求 需要分类的ID 和参数的ID 并不需要参数类型
- (动态 静态)删除方法是可以在一个函数实现
绑定事件
@click="delParams(scope.row.attr_id)"
// 删除参数
delParams (attrId) {
this.$confirm('是否删除该参数?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
// :id 传 分类的ID
const id = this.categoryValues[2]
// :attrid 就是当前的参数ID
const {data: {meta}} = await this.$http.delete(`categories/${id}/attributes/${attrId}`)
if (meta.status !== 200) return this.$message.error('删除参数失败')
this.$message.success('删除参数成功')
// 更新当前的列表
this.getParams()
}).catch(() => {})
},
10-分类参数-修改动态参数值
在进行功能开发之前:把之前的遍历方式改变一下,将来比较方便的去进行删除和添加
-
不是直接使用 attr_vals 而是在js处理数据的时候 转换数组
-
动态参数的值删除
<el-tag @close="delTag(scope.row,i)" v-for="(item,i) in scope.row.attr_vals" :key="i" size="normal" closable>{{item}} +添加tag
具体js操作 依赖了计算属性:
// 计算属性:函数的名字就是一个数据的字段名称 使用和data中申明的数据一样
computed: {
id: function () {
// 为了严谨 程序更加健壮
if (this.categoryValues.length === 3) {
return this.categoryValues[2]
} else {
return null
}
}
},
// tag关闭事件
async delTag (row, i) {
// 删除tag的效果 并没有真正的去修改后台的数据
row.attr_vals.splice(i, 1)
// 根据现在的arr去修改后台的参数的值
const {data: {meta}} = await this.$http.put(`categories/${this.id}/attributes/${row.attr_id}`, {
attr_name: row.attr_name,
attr_sel: this.activeName,
attr_vals: row.attr_vals.join(',')
})
if (meta.status !== 200) return this.$message.error('更新参数值失败')
this.$message.success('更新参数值成功')
},
- 动态参数的值添加
-
实现 点击添加tag 去显示一个输入框 且 隐藏添加tag
-
input去获取焦点的时候 需要等input显示后去获取 $nextTick
-
需要给每一行的input加ref属性 需要唯一 input+attr_id
-
失去焦点 enter键 隐藏输入框 显示tag
- @blur
- @keyup.native.enter 注意会触发两次 当前的事件 失去焦点事件
- native的意思:在组件上绑定的事件是组件的自定义事件,如果想触发原生的事件需要使用native
-
发送数据 如果 输入的内容是空的 不让提交 (在提交数据后 清空当前输入框的内容)
<el-tag v-show="!scope.row.inputShow" @click="showInput(scope.row)" :disable-transitions="true" class="w100" size="normal"> +添加tag <el-input v-model="scope.row.inputValue" @blur="hideInput(scope.row)" @keyup.native.enter="hideInput(scope.row)" :ref="'input'+scope.row.attr_id" v-show="scope.row.inputShow" class="w100 newInput">
// 隐藏input事件 hideInput (row) { row.inputShow = false // 如果输入的内容为空 不能提交
if (row.inputValue) { // 当前input输入的内容 追加到 attr_vals 中 row.attr_vals.push(row.inputValue) // 把修改好的数据给后台 this.editAttr(row) row.inputValue = '' } }, // 显示input的事件 showInput (row) { row.inputShow = true // dom.focus() 获取焦点 dom 当前行的input console.log(this.nextTick(() => { this.
http.put(
categories/${this.id}/attributes/${row.attr_id}, { attr_name: row.attr_name, attr_sel: this.activeName, attr_vals: row.attr_vals.join(',') }) if (meta.status !== 200) return this.message.success('更新参数值成功') },
-
12-分类参数-修改静态参数值
- 功能点相同 当作练习
13-商品列表-路由级组件骨架
路由
{path: '/goods', name: 'goods', component: Goods}
组件骨架
<template>
<div class="goods_container">
</div>
</template>
<script>
import mixin from './Goods-Mixin'
export default {
mixins: [mixin]
}
</script>
<style scoped>
</style>
14-商品列表-组件基础布局
15-商品列表-列表展示与分页
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>商品管理</el-breadcrumb-item>
<el-breadcrumb-item>商品列表</el-breadcrumb-item>
</el-breadcrumb>
<el-card>
<el-row :gutter="20">
<el-col :span="6">
<el-input v-model="reqParams.query" placeholder="请输入内容">
<el-button @click="search()" slot="append" icon="el-icon-search"></el-button>
</el-input>
</el-col>
<el-col :span="18">
<el-button type="primary" plain>添加商品</el-button>
</el-col>
</el-row>
<el-table :data="goodsList">
<el-table-column type="index"></el-table-column>
<el-table-column label="商品名称" width="300px" prop="goods_name"></el-table-column>
<el-table-column label="价格" prop="goods_price"></el-table-column>
<el-table-column label="重量" prop="goods_weight"></el-table-column>
<el-table-column label="创建时间">
<template slot-scope="scope">
{{scope.row.add_time|ft}}
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button icon="el-icon-edit" circle></el-button>
<el-button icon="el-icon-delete" @click="delGoods(scope.row.goods_id)" circle></el-button>
</template>
</el-table-column>
</el-table>
<div class="pager_container">
<el-pagination
@current-change="changePager"
:page-size="reqParams.pagesize"
:current-page="reqParams.pagenum"
background
layout="prev, pager, next"
:total="total">
</el-pagination>
</div>
</el-card>
data () {
return {
goodsList: [],
reqParams: {
query: '',
pagenum: 1,
pagesize: 5
},
total: 0
}
},
mounted () {
this.getData()
},
methods: {
async getData () {
const {data: {data, meta}} = await this.$http.get('goods', {params: this.reqParams})
if (meta.status !== 200) return this.$message.error('获取商品信息失败')
this.goodsList = data.goods
this.total = data.total
},
changePager (newPage) {
this.reqParams.pagenum = newPage
this.getData()
},
16-商品列表-搜索商品
<el-input v-model="reqParams.query" placeholder="请输入内容">
<el-button @click="search()" slot="append" icon="el-icon-search"></el-button>
</el-input>
search () {
this.reqParams.pagenum = 1
this.getData()
},
17-商品列表-删除商品
<el-button icon="el-icon-delete" @click="delGoods(scope.row.goods_id)" circle></el-button>
delGoods (id) {
this.$confirm('是否删除该商品?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
// 发请求去删除
const {data: {meta}} = await this.$http.delete(`goods/${id}`)
if (meta.status !== 200) return this.$message.error('删除商品失败')
this.$message.success('删除商品成功')
this.getData()
}).catch(() => {})
}