1.axios模块注意事项
// 查询工号是否重复
export function getEmployeeCheckUserCode(data) {
return request({
url: 'employee-user/v1/emp-user/code',
method: 'get',
params: data
})
}
getEmployeeCheckUserCode({ code: value, userId: this.userId }).then(res => {
if (res.data.msg === '工号可用') {
callback()
} else {
callback('工号已存在')
}
})
2.0 数组CRUD
1.业务场景删除指定内容,
<el-tag
v-for="(tag, index) in deptData"
:key="index"
closable
@close="handleCloseDept(tag)">
{{ tag.deptName }}
</el-tag>
// 删除部门tag
handleCloseDept(tag) {
// 通过key值的变动强制刷新组件
this.deptData.splice(this.deptData.indexOf(tag), 1)
},
2.0 el-tags和el-tree树形结构的综合运用情况
3 el-table设置表格高度自适应
<el-table ref="table" :data="tableData" :height="tableHeight"></el-table>
export default {
data(){
return {
tableHeight: 50,
tableData: []
}
},
mounted:function(){
this.$nextTick(function () {
this.tableHeight = window.innerHeight - this.$refs.table.$el.offsetTop - 50;
// 监听窗口大小变化
let self = this;
window.onresize = function() {
self.tableHeight = window.innerHeight - self.$refs.table.$el.offsetTop - 50
}
})
//this.$refs.table.$el.offsetTop:表格距离浏览器的高度
//50表示你想要调整的表格距离底部的高度(你可以自己随意调整),因为我们一般都有放分页组件的,所以需要给它留一个高度
}
}
4.vue路由跳转打开新一页
outsideLink () {
let {href}= this.$router.resolve({
path: "/newLinkPage",
});
window.open(href, '_blank');
}
5.0 el-table全选和取消全选2种方式
5.1 自定义的表格模式
- 自定义封装列表的选项框勾选,使用自定义方式完成全选或者取消,选择个别状态为isIndeterminate 等待状态。
<el-table-column width="55">
<template slot-scope="scope">
<el-checkbox v-model="scope.row.isCheck" @change="handleCheck($event, scope.row)"/>
</template>
</el-table-column>
- table点击点击选择
- 第一步先判断点击的数组和当前传进来的数据是否存在,存在返回下标没有则-1
- 如果不存在空的则把选择的内容添加到中间数组
this.checkList
则表示当前是选择点击勾选状态 - 存在数据并且返回当前数据下标则
haveAny !== -1
进行下标的删除等于 取消勾选状态取消选择 this.isIndeterminate
通过当前点击的长度和输入的中间数组长度判断若不相等则为等待状态表示false(indeterminate
属性用以表示 checkbox 的不确定状态,一般用于实现全选的效果)checkAll
全部选择状态,table表格全部选择表示当前状态
handleCheck(val, item) {
const haveAny = this.checkList.findIndex((citem) => {
return citem.orderId === item.orderId
})
if (val) {
if (haveAny === -1) {
this.checkList.push(item)
}
} else {
if (haveAny !== -1) {
this.checkList.splice(haveAny, 1)
}
}
this.isIndeterminate = this.checkList.length > 0 && this.checkList.length < this.tableData.length
this.checkAll = this.checkList.length > 0 && this.checkList.length === this.tableData.length
console.log(this.checkList)
},
- 自定义checkbox点击实现table自定义的 checkbox全部选择
- 先让
this.isIndeterminate
状态隐藏 - 判断
this.tableData
内容使用forEach
遍历完成 开关状态 - 并且完成赋值修改最后的选择状态
handleCheckAllChange(val) {
this.isIndeterminate = false
if (val) {
this.tableData.forEach(item => {
item.isCheck = true
})
this.checkList = JSON.parse(JSON.stringify(this.tableData))
} else {
this.tableData.forEach(item => {
item.isCheck = false
})
this.checkList = []
}
},
5.2 自定义的表格模式
<el-table @selection-change="handleSelectionChange"
<el-table-column type="selection" width="55"/>
<el-table/>
- 自定义全选模式
- 完成中间数组的赋值插入,根据插入的数据的长度和
this.tableData.length
判断实现对自定义checkbox的状态切换修改
- 完成中间数组的赋值插入,根据插入的数据的长度和
handleSelectionChange(val) {
this.checkList = val
this.checkList.length === this.tableData.length ? this.checkAll = true : this.checkAll = false
console.log(this.checkList)
},
- 点击选项
- 第一步先判断点击的数组和当前传进来的数据是否存在,存在返回下标没有则-1
- 如果不存在空的则把选择的内容添加到中间数组
this.checkList
则表示当前是选择点击勾选状态 - 存在数据并且返回当前数据下标则
haveAny !== -1
进行下标的删除等于 取消勾选状态取消选择 this.isIndeterminate
通过当前点击的长度和输入的中间数组长度判断若不相等则为等待状态表示false(indeterminate
属性用以表示 checkbox 的不确定状态,一般用于实现全选的效果)checkAll
全部选择状态,table表格全部选择表示当前状态
// 点击选项
handleCheck(val, item) {
const haveAny = this.checkList.findIndex((citem) => {
return citem.userId === item.userId
})
if (val) {
if (haveAny === -1) {
this.checkList.push(item)
}
} else {
if (haveAny !== -1) {
this.checkList.splice(haveAny, 1)
}
}
this.isIndeterminate = this.checkList.length > 0 && this.checkList.length < this.tableData.length
this.checkAll = this.checkList.length > 0 && this.checkList.length === this.tableData.length
},
- 当页全选模式
// 当页全选
handleCheckAllChange(val) {
console.log(val)
this.isIndeterminate = false
if (val) {
this.tableData.forEach(item => {
const isCheck = item.isCheck = true
this.$refs.table.toggleRowSelection(item, isCheck)
})
} else {
this.tableData.forEach(item => {
item.isCheck = false
this.$refs.table.clearSelection()
})
this.checkList = []
}
},
6.0 树形结构权限树形(难点)
<!-- 树形结构 -->
<el-tree
ref="tree"
:data="treeData"
:expand-on-click-node="false"
:props="defaultProps"
:default-expanded-keys="treeNnfoldArray"
:highlight-current="isHighlight"
node-key="deptId"
@node-click="setUserData"
@node-expand="nodeExpand"
@node-collapse="nodeCollapse"
>
<span slot-scope="{ node, data }" class="custom-tree-node">
<span style="margin-right: 6px">
<img src="./img/Process.png" >
</span>
<span style="margin-right: 6px">{{ node.label }}</span>
</span>
</el-tree>
7.0 Popover 弹出框嵌套只显示一个处理方案
<template>
<div class="position-dept-class">
<div class="classify-main">
<div class="tree-class">
<div class="tree-box">
<!-- <el-button>添加分类</el-button> -->
<el-tree
ref="tree"
:data="treeList"
:props="getData"
:highlight-current="true"
:expand-on-click-node="false"
:check-on-click-node="true"
:indent="8"
node-key="deptId"
default-expand-all
draggable
@node-click="selectDep"
@node-drop="handleDrop"
@node-drag-start="startDrop">
<!-- @mouseover="toggleShow(data)" @mouseout="togglenoShow(data)" -->
<span slot-scope="{ node, data }" class="custom-tree-node" >
<span style="margin-right: 5px">
<img src="./img/Process.png">
</span>
<span style="margin-left:10px;"> {{ data.deptName }}</span>
<!-- <img v-show="overIndex === data.deptId" src="./img/treePoint.png" @click="tools(data)"> -->
<span>
<!-- v-model="data.visible" -->
<el-popover
v-model="data.visible"
:width="isModify ? '300': '160'"
placement="bottom"
trigger="click"
popper-class="position-dept-popper-class"
@show="tools(data)"
@hide="cancelDepartmen(data)">
<div v-if="!isModify">
<div @click="openToModify(data)">
<el-dropdown-item><span>修改名称</span></el-dropdown-item>
</div>
<div @click.stop="addPosition('child', node, data)">
<el-dropdown-item><span>新建子部门</span></el-dropdown-item>
</div>
<div @click.stop="addPosition('peer', node, data)">
<el-dropdown-item><span>添加同级部门</span></el-dropdown-item>
</div>
<template v-if="!(node.level === 1 && treeList.length === 1)">
<div @click.stop="isDeleteDept(node,data)">
<el-dropdown-item style="border-top: 1px solid #EEEEEE;margin-top: 12px;padding-top: 6px;color: #FF6000;"><span>删除</span></el-dropdown-item>
</div>
</template>
</div>
<div v-if="isModify" class="modifyName" style="padding: 14px 10px;">
<el-input v-model="companyName" maxlength="16" style="margin-bottom:19px;" />
<el-button class="cancel" style="padding: 8px 20px; border: 1px solid #D7B759;color: #D7B759;margin-left: 120px;margin-bottom: 7px;" @click="cancelDepartmen(data)">取消</el-button>
<el-button type="primary" style="padding: 8px 20px;" @click="modifyName(data)">保存</el-button>
</div>
<!-- v-show="overIndex === data.deptId" -->
<!-- @click="tools(data)" -->
<img slot="reference" :style=" data.visible ? {display: 'inline-block'} : {}" class="cc-img" src="./img/treePoint.png" style="margin-left:12px; width:16px;position: absolute; right: 6px;top: 16px" @click.stop="" >
<!-- <img slot="reference" type="text" src="../../../assets/treePoint.png" @click="tools(data)"> -->
</el-popover>
</span>
</span>
</el-tree>
</div>
</div>
</div>
<el-dialog :visible.sync="dialogVisible" title="新增部门" width="580px" class="addDept">
<div class="add_content">
<span class="content_text">
<span style="color:#FF6000">*</span> 部门名
</span>
<el-input v-model="addDeptName" />
</div>
<span slot="footer" class="dialog-footer">
<el-button class="cancel" @click.stop="addCancel">取 消</el-button>
<el-button type="primary" @click.stop="addSave">保 存</el-button>
</span>
</el-dialog>
<el-dialog :visible.sync="isDelete" :show-close="false" width="580px">
<div class="delete_content">
<img src="./img/tip.png" style="width: 24px;">
<span class="delete_text">删除部门将会将部门所关联的权限一并删除,此操作不可逆</span>
</div>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click.stop="deleteDept">确定删除</el-button>
<el-button class="cancel" style=" border: 1px solid #D7B759;color:#D7B759;" @click.stop="isDelete = false">取 消</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import {
getDeptTree,
sortDeptTree,
addDept,
deleteDept,
modifyDeptName
} from '@/api/manager-user'
export default {
data() {
return {
treeList: [],
// treeData: [],
// visible: false,
// isOpen: false,
overIndex: -1,
cacheDataItem: {},
isModify: false,
companyName: '',
dialogVisible: false,
isDelete: false,
addDeptName: '',
parentId: 0,
getData: {
children: 'deptItems'
},
parentNode: [],
childrenNode: []
}
},
mounted() {
this.getTreeData()
},
methods: {
getTreeData() {
getDeptTree().then(async res => {
if (res.data.code === 200) {
const treeList = res.data.data
if (treeList && treeList.length > 0) {
this.treeList = treeList
this.$emit('selectDept', this.treeList[0], [this.treeList[0].deptId])
this.$nextTick(() => {
if (this.$refs.tree) {
this.$refs.tree.setCurrentKey(this.treeList[0].deptId)
}
})
}
}
})
},
selectDep(val) {
const checkedKeys = this.$refs.tree.getHalfCheckedKeys()
const newKeys = [...checkedKeys, val.deptId]
this.$emit('selectDept', val, newKeys)
this.$refs.tree.setCheckedKeys([])
},
// 递归查找所有父id
searchParent(dropNode) {
if (!dropNode.parent || dropNode.parent.id === 0 || !dropNode.parent.data.deptId) {
return true
}
console.log(dropNode.parent.data.deptId)
this.parentNode.push(dropNode.parent.data.deptId)
this.searchParent(dropNode.parent)
},
// 递归查找所有子id
searchChild(draggingNode) {
if (draggingNode.childNodes.length === 0) {
return true
}
draggingNode.childNodes.forEach((item, index) => {
this.searchChild(item)
this.childrenNode.push(item.data.deptId)
})
},
startDrop(draggingNode, ev) {
console.log(draggingNode)
},
handleDrop(draggingNode, dropNode, dropType, ev) {
this.parentNode = []
this.childrenNode = []
if (dropType === 'inner' && dropNode.data.deptId) {
this.parentNode.push(dropNode.data.deptId)
}
if (dropType === 'inner' || (draggingNode.data.deptParentId !== dropNode.data.deptParentId)) {
this.searchParent(dropNode)
this.childrenNode.push(draggingNode.data.deptId)
this.searchChild(draggingNode)
}
const updateData = {
id: draggingNode.data.deptId,
parent: '',
sort: '',
dropData: {
sortDeptIds: [],
roleDeptIds: [],
deptItems: []
}
}
const data = dropType !== 'inner' ? dropNode.parent.data : dropNode.data
var nodeData = dropNode.level === 1 && dropType !== 'inner' ? data : data.deptItems
let list = []
const findIndex = nodeData.findIndex(x => x.deptId === draggingNode.data.deptId)
if (findIndex !== -1) {
let sort
if (findIndex === 0) {
sort = 0
} else {
const prve = findIndex - 1
sort = nodeData[prve].sort + 1
}
// draggingNode.data.sort = sort
updateData.sort = sort
let parentId = dropType !== 'inner' ? dropNode.parent.data.deptId : dropNode.data.deptId
if (!parentId) {
parentId = 0
}
const start = findIndex + 1
list = nodeData.slice(start)
updateData.parent = parentId
// draggingNode.data.paterId = parentId
list.forEach(item => {
// sort++
// item.sort = sort
updateData.dropData.sortDeptIds.push(item.deptId)
})
updateData.dropData.roleDeptIds = this.parentNode
updateData.dropData.deptItems = this.childrenNode
}
sortDeptTree(updateData.id, updateData.parent, updateData.sort, updateData.dropData).then(res => {
if (res.data.code === 200) {
let sort = updateData.sort
draggingNode.data.sort = sort
draggingNode.data.deptParentId = updateData.parent
list.forEach(item => {
sort++
item.sort = sort
})
} else {
this.$notify({
title: '失败',
message: '排序失败,请重试',
type: 'error',
duration: 2000
})
this.getTreeData()
}
})
},
// toggleShow(item) {
// this.overIndex = item.deptId
// },
// // 左侧鼠标离开
// togglenoShow(data) {
// this.overIndex = -1
// },
tools(item) {
if (this.cacheDataItem && item.deptId !== this.cacheDataItem.deptId) {
this.cacheDataItem.visible = false
}
this.cacheDataItem = item
},
cancelDepartmen(data) {
// data.visible = false
setTimeout(() => {
this.isModify = false
}, 200)
},
openToModify(data) {
this.companyName = data.deptName
this.isModify = true
},
addPosition(type, node, data) {
data.visible = false
let parentId
this.dialogVisible = true
if (type === 'peer') {
parentId = node.data.deptParentId
} else if (type === 'child') {
parentId = data.deptId
}
this.parentId = parentId
},
addCancel() {
this.dialogVisible = false
this.addDeptName = ''
},
addSave() {
if (!this.addDeptName) {
this.$notify({
title: '添加失败',
message: '部门名不能为空!',
type: 'error',
duration: 2000
})
return
}
const addData = {
deptName: this.addDeptName,
deptParentId: this.parentId
}
addDept(addData).then(res => {
if (res.data.code === 200) {
this.$notify({
title: '成功',
message: '添加部门成功',
type: 'success',
duration: 2000
})
this.getTreeData()
this.dialogVisible = false
this.addDeptName = ''
}
})
},
isDeleteDept(node, data) {
data.visible = false
if (node.childNodes.length) {
this.$notify({
title: '失败',
message: '存在子部门,不能删除',
type: 'error',
duration: 2000
})
return
}
this.isDelete = true
this.deleteId = data.deptId
},
deleteDept() {
deleteDept(this.deleteId).then(res => {
if (res.data.code === 200) {
if (res.data.type === 1) {
this.$notify({
title: '成功',
message: '删除部门成功',
type: 'success',
duration: 2000
})
this.getTreeData()
} else if (res.data.type === 3) {
this.$notify({
title: '失败',
message: res.data.msg,
type: 'error',
duration: 2000
})
}
}
this.isDelete = false
})
},
modifyName(data) {
if (!this.companyName) {
this.$notify({
title: '失败',
message: '部门名不能为空',
type: 'error',
duration: 2000
})
return
}
const deptData = {
deptId: data.deptId,
deptName: this.companyName
}
modifyDeptName(deptData).then(res => {
if (res.data.code === 200) {
this.$notify({
title: '成功',
message: '修改部门名成功',
type: 'success',
duration: 2000
})
data.deptName = this.companyName
data.visible = false
this.$emit('selectDept', data)
}
})
}
}
}
</script>
8.0 绝对定位布局
<el-drawer
title="配置权限"
:visible.sync="drawer"
direction="rtl"
:before-close="handleClose"
size="40%">
<div style="position: absolute;top:52px;left: 0;right: 0;bottom: 0;">
<div style="position: absolute;top: 0;left: 0;right: 0;bottom: 60px;overflow-y: auto;">
<el-tree
:data="ruleList"
show-checkbox
node-key="id"
default-expand-all
:default-checked-keys="checkedKeys"
:props="defaultProps"
:check-strictly="true"
@check="check">
</el-tree>
</div>
<div style="height: 60px;position: absolute;bottom: 0;right: 0;left: 0;" class="border d-flex align-items-center px-3 bg-white">
<el-button @click="drawer = false">取消</el-button>
<el-button type="primary" @click="submitRules">确定</el-button>
</div>
</div>
</el-drawer>
9.0 element-ui promise自定义校验
validator: async (rule, value)=>{
// 请求判断用户是否存在
let res = await that.certificate(value);
if(res.status === 1)
return Promise.reject('用户名已存在');
else return Promise.resolve('用户名可用');
},
10.0 反复点击清除背景颜色问题
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
11.0 防抖函数处理请求
this.debounce(this.getEmployeeQueryDepartmentUser, 600)
debounce(fn, wait) {
if (this.timer !== null) {
clearTimeout(this.timer)
}
this.timer = setTimeout(fn, wait)
}
debounce(fn, wait) {
if (this.timer) {
clearTimeout(this.timer)
}
this.timer = setTimeout(() => {
if (this.form.fileKey && this.appId && this.formId && this.printId) {
console.log('执行代码')
this.submitForm2()
}
}, 500)
}