1.axios模块注意事项

  1. // 查询工号是否重复
  2. export function getEmployeeCheckUserCode(data) {
  3. return request({
  4. url: 'employee-user/v1/emp-user/code',
  5. method: 'get',
  6. params: data
  7. })
  8. }
  9. getEmployeeCheckUserCode({ code: value, userId: this.userId }).then(res => {
  10. if (res.data.msg === '工号可用') {
  11. callback()
  12. } else {
  13. callback('工号已存在')
  14. }
  15. })

2.0 数组CRUD

1.业务场景删除指定内容,

  1. <el-tag
  2. v-for="(tag, index) in deptData"
  3. :key="index"
  4. closable
  5. @close="handleCloseDept(tag)">
  6. {{ tag.deptName }}
  7. </el-tag>
  8. // 删除部门tag
  9. handleCloseDept(tag) {
  10. // 通过key值的变动强制刷新组件
  11. this.deptData.splice(this.deptData.indexOf(tag), 1)
  12. },

2.0 el-tags和el-tree树形结构的综合运用情况

3 el-table设置表格高度自适应

  1. <el-table ref="table" :data="tableData" :height="tableHeight"></el-table>
  1. export default {
  2. data(){
  3. return {
  4. tableHeight: 50,
  5. tableData: []
  6. }
  7. },
  8. mounted:function(){
  9. this.$nextTick(function () {
  10. this.tableHeight = window.innerHeight - this.$refs.table.$el.offsetTop - 50;
  11. // 监听窗口大小变化
  12. let self = this;
  13. window.onresize = function() {
  14. self.tableHeight = window.innerHeight - self.$refs.table.$el.offsetTop - 50
  15. }
  16. })
  17. //this.$refs.table.$el.offsetTop:表格距离浏览器的高度
  18.      //50表示你想要调整的表格距离底部的高度(你可以自己随意调整),因为我们一般都有放分页组件的,所以需要给它留一个高度 
  19. }
  20. }

4.vue路由跳转打开新一页

  1. outsideLink () {
  2. let {href}= this.$router.resolve({
  3. path: "/newLinkPage",
  4. });
  5. window.open(href, '_blank');
  6. }

5.0 el-table全选和取消全选2种方式

5.1 自定义的表格模式

  • 自定义封装列表的选项框勾选,使用自定义方式完成全选或者取消,选择个别状态为isIndeterminate 等待状态。
  1. <el-table-column width="55">
  2. <template slot-scope="scope">
  3. <el-checkbox v-model="scope.row.isCheck" @change="handleCheck($event, scope.row)"/>
  4. </template>
  5. </el-table-column>
  1. table点击点击选择
    • 第一步先判断点击的数组和当前传进来的数据是否存在,存在返回下标没有则-1
    • 如果不存在空的则把选择的内容添加到中间数组 this.checkList 则表示当前是选择点击勾选状态
    • 存在数据并且返回当前数据下标则 haveAny !== -1进行下标的删除等于 取消勾选状态取消选择
    • this.isIndeterminate通过当前点击的长度和输入的中间数组长度判断若不相等则为等待状态表示false(indeterminate 属性用以表示 checkbox 的不确定状态,一般用于实现全选的效果)
    • checkAll全部选择状态,table表格全部选择表示当前状态
  1. handleCheck(val, item) {
  2. const haveAny = this.checkList.findIndex((citem) => {
  3. return citem.orderId === item.orderId
  4. })
  5. if (val) {
  6. if (haveAny === -1) {
  7. this.checkList.push(item)
  8. }
  9. } else {
  10. if (haveAny !== -1) {
  11. this.checkList.splice(haveAny, 1)
  12. }
  13. }
  14. this.isIndeterminate = this.checkList.length > 0 && this.checkList.length < this.tableData.length
  15. this.checkAll = this.checkList.length > 0 && this.checkList.length === this.tableData.length
  16. console.log(this.checkList)
  17. },
  1. 自定义checkbox点击实现table自定义的 checkbox全部选择
  • 先让 this.isIndeterminate状态隐藏
  • 判断 this.tableData 内容使用 forEach遍历完成 开关状态
  • 并且完成赋值修改最后的选择状态
  1. handleCheckAllChange(val) {
  2. this.isIndeterminate = false
  3. if (val) {
  4. this.tableData.forEach(item => {
  5. item.isCheck = true
  6. })
  7. this.checkList = JSON.parse(JSON.stringify(this.tableData))
  8. } else {
  9. this.tableData.forEach(item => {
  10. item.isCheck = false
  11. })
  12. this.checkList = []
  13. }
  14. },

5.2 自定义的表格模式

  1. <el-table @selection-change="handleSelectionChange"
  2. <el-table-column type="selection" width="55"/>
  3. <el-table/>
  1. 自定义全选模式
    • 完成中间数组的赋值插入,根据插入的数据的长度和 this.tableData.length 判断实现对自定义checkbox的状态切换修改
  1. handleSelectionChange(val) {
  2. this.checkList = val
  3. this.checkList.length === this.tableData.length ? this.checkAll = true : this.checkAll = false
  4. console.log(this.checkList)
  5. },
  1. 点击选项
  • 第一步先判断点击的数组和当前传进来的数据是否存在,存在返回下标没有则-1
  • 如果不存在空的则把选择的内容添加到中间数组 this.checkList 则表示当前是选择点击勾选状态
  • 存在数据并且返回当前数据下标则 haveAny !== -1进行下标的删除等于 取消勾选状态取消选择
  • this.isIndeterminate通过当前点击的长度和输入的中间数组长度判断若不相等则为等待状态表示false(indeterminate 属性用以表示 checkbox 的不确定状态,一般用于实现全选的效果)
  • checkAll全部选择状态,table表格全部选择表示当前状态
  1. // 点击选项
  2. handleCheck(val, item) {
  3. const haveAny = this.checkList.findIndex((citem) => {
  4. return citem.userId === item.userId
  5. })
  6. if (val) {
  7. if (haveAny === -1) {
  8. this.checkList.push(item)
  9. }
  10. } else {
  11. if (haveAny !== -1) {
  12. this.checkList.splice(haveAny, 1)
  13. }
  14. }
  15. this.isIndeterminate = this.checkList.length > 0 && this.checkList.length < this.tableData.length
  16. this.checkAll = this.checkList.length > 0 && this.checkList.length === this.tableData.length
  17. },
  1. 当页全选模式
  1. // 当页全选
  2. handleCheckAllChange(val) {
  3. console.log(val)
  4. this.isIndeterminate = false
  5. if (val) {
  6. this.tableData.forEach(item => {
  7. const isCheck = item.isCheck = true
  8. this.$refs.table.toggleRowSelection(item, isCheck)
  9. })
  10. } else {
  11. this.tableData.forEach(item => {
  12. item.isCheck = false
  13. this.$refs.table.clearSelection()
  14. })
  15. this.checkList = []
  16. }
  17. },

6.0 树形结构权限树形(难点)

  1. <!-- 树形结构 -->
  2. <el-tree
  3. ref="tree"
  4. :data="treeData"
  5. :expand-on-click-node="false"
  6. :props="defaultProps"
  7. :default-expanded-keys="treeNnfoldArray"
  8. :highlight-current="isHighlight"
  9. node-key="deptId"
  10. @node-click="setUserData"
  11. @node-expand="nodeExpand"
  12. @node-collapse="nodeCollapse"
  13. >
  14. <span slot-scope="{ node, data }" class="custom-tree-node">
  15. <span style="margin-right: 6px">
  16. <img src="./img/Process.png" >
  17. </span>
  18. <span style="margin-right: 6px">{{ node.label }}</span>
  19. </span>
  20. </el-tree>

7.0 Popover 弹出框嵌套只显示一个处理方案

  1. <template>
  2. <div class="position-dept-class">
  3. <div class="classify-main">
  4. <div class="tree-class">
  5. <div class="tree-box">
  6. <!-- <el-button>添加分类</el-button> -->
  7. <el-tree
  8. ref="tree"
  9. :data="treeList"
  10. :props="getData"
  11. :highlight-current="true"
  12. :expand-on-click-node="false"
  13. :check-on-click-node="true"
  14. :indent="8"
  15. node-key="deptId"
  16. default-expand-all
  17. draggable
  18. @node-click="selectDep"
  19. @node-drop="handleDrop"
  20. @node-drag-start="startDrop">
  21. <!-- @mouseover="toggleShow(data)" @mouseout="togglenoShow(data)" -->
  22. <span slot-scope="{ node, data }" class="custom-tree-node" >
  23. <span style="margin-right: 5px">
  24. <img src="./img/Process.png">
  25. </span>
  26. <span style="margin-left:10px;"> {{ data.deptName }}</span>
  27. <!-- <img v-show="overIndex === data.deptId" src="./img/treePoint.png" @click="tools(data)"> -->
  28. <span>
  29. <!-- v-model="data.visible" -->
  30. <el-popover
  31. v-model="data.visible"
  32. :width="isModify ? '300': '160'"
  33. placement="bottom"
  34. trigger="click"
  35. popper-class="position-dept-popper-class"
  36. @show="tools(data)"
  37. @hide="cancelDepartmen(data)">
  38. <div v-if="!isModify">
  39. <div @click="openToModify(data)">
  40. <el-dropdown-item><span>修改名称</span></el-dropdown-item>
  41. </div>
  42. <div @click.stop="addPosition('child', node, data)">
  43. <el-dropdown-item><span>新建子部门</span></el-dropdown-item>
  44. </div>
  45. <div @click.stop="addPosition('peer', node, data)">
  46. <el-dropdown-item><span>添加同级部门</span></el-dropdown-item>
  47. </div>
  48. <template v-if="!(node.level === 1 && treeList.length === 1)">
  49. <div @click.stop="isDeleteDept(node,data)">
  50. <el-dropdown-item style="border-top: 1px solid #EEEEEE;margin-top: 12px;padding-top: 6px;color: #FF6000;"><span>删除</span></el-dropdown-item>
  51. </div>
  52. </template>
  53. </div>
  54. <div v-if="isModify" class="modifyName" style="padding: 14px 10px;">
  55. <el-input v-model="companyName" maxlength="16" style="margin-bottom:19px;" />
  56. <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>
  57. <el-button type="primary" style="padding: 8px 20px;" @click="modifyName(data)">保存</el-button>
  58. </div>
  59. <!-- v-show="overIndex === data.deptId" -->
  60. <!-- @click="tools(data)" -->
  61. <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="" >
  62. <!-- <img slot="reference" type="text" src="../../../assets/treePoint.png" @click="tools(data)"> -->
  63. </el-popover>
  64. </span>
  65. </span>
  66. </el-tree>
  67. </div>
  68. </div>
  69. </div>
  70. <el-dialog :visible.sync="dialogVisible" title="新增部门" width="580px" class="addDept">
  71. <div class="add_content">
  72. <span class="content_text">
  73. <span style="color:#FF6000">*</span> 部门名
  74. </span>
  75. <el-input v-model="addDeptName" />
  76. </div>
  77. <span slot="footer" class="dialog-footer">
  78. <el-button class="cancel" @click.stop="addCancel">取 消</el-button>
  79. <el-button type="primary" @click.stop="addSave">保 存</el-button>
  80. </span>
  81. </el-dialog>
  82. <el-dialog :visible.sync="isDelete" :show-close="false" width="580px">
  83. <div class="delete_content">
  84. <img src="./img/tip.png" style="width: 24px;">
  85. <span class="delete_text">删除部门将会将部门所关联的权限一并删除,此操作不可逆</span>
  86. </div>
  87. <span slot="footer" class="dialog-footer">
  88. <el-button type="primary" @click.stop="deleteDept">确定删除</el-button>
  89. <el-button class="cancel" style=" border: 1px solid #D7B759;color:#D7B759;" @click.stop="isDelete = false">取 消</el-button>
  90. </span>
  91. </el-dialog>
  92. </div>
  93. </template>
  94. <script>
  95. import {
  96. getDeptTree,
  97. sortDeptTree,
  98. addDept,
  99. deleteDept,
  100. modifyDeptName
  101. } from '@/api/manager-user'
  102. export default {
  103. data() {
  104. return {
  105. treeList: [],
  106. // treeData: [],
  107. // visible: false,
  108. // isOpen: false,
  109. overIndex: -1,
  110. cacheDataItem: {},
  111. isModify: false,
  112. companyName: '',
  113. dialogVisible: false,
  114. isDelete: false,
  115. addDeptName: '',
  116. parentId: 0,
  117. getData: {
  118. children: 'deptItems'
  119. },
  120. parentNode: [],
  121. childrenNode: []
  122. }
  123. },
  124. mounted() {
  125. this.getTreeData()
  126. },
  127. methods: {
  128. getTreeData() {
  129. getDeptTree().then(async res => {
  130. if (res.data.code === 200) {
  131. const treeList = res.data.data
  132. if (treeList && treeList.length > 0) {
  133. this.treeList = treeList
  134. this.$emit('selectDept', this.treeList[0], [this.treeList[0].deptId])
  135. this.$nextTick(() => {
  136. if (this.$refs.tree) {
  137. this.$refs.tree.setCurrentKey(this.treeList[0].deptId)
  138. }
  139. })
  140. }
  141. }
  142. })
  143. },
  144. selectDep(val) {
  145. const checkedKeys = this.$refs.tree.getHalfCheckedKeys()
  146. const newKeys = [...checkedKeys, val.deptId]
  147. this.$emit('selectDept', val, newKeys)
  148. this.$refs.tree.setCheckedKeys([])
  149. },
  150. // 递归查找所有父id
  151. searchParent(dropNode) {
  152. if (!dropNode.parent || dropNode.parent.id === 0 || !dropNode.parent.data.deptId) {
  153. return true
  154. }
  155. console.log(dropNode.parent.data.deptId)
  156. this.parentNode.push(dropNode.parent.data.deptId)
  157. this.searchParent(dropNode.parent)
  158. },
  159. // 递归查找所有子id
  160. searchChild(draggingNode) {
  161. if (draggingNode.childNodes.length === 0) {
  162. return true
  163. }
  164. draggingNode.childNodes.forEach((item, index) => {
  165. this.searchChild(item)
  166. this.childrenNode.push(item.data.deptId)
  167. })
  168. },
  169. startDrop(draggingNode, ev) {
  170. console.log(draggingNode)
  171. },
  172. handleDrop(draggingNode, dropNode, dropType, ev) {
  173. this.parentNode = []
  174. this.childrenNode = []
  175. if (dropType === 'inner' && dropNode.data.deptId) {
  176. this.parentNode.push(dropNode.data.deptId)
  177. }
  178. if (dropType === 'inner' || (draggingNode.data.deptParentId !== dropNode.data.deptParentId)) {
  179. this.searchParent(dropNode)
  180. this.childrenNode.push(draggingNode.data.deptId)
  181. this.searchChild(draggingNode)
  182. }
  183. const updateData = {
  184. id: draggingNode.data.deptId,
  185. parent: '',
  186. sort: '',
  187. dropData: {
  188. sortDeptIds: [],
  189. roleDeptIds: [],
  190. deptItems: []
  191. }
  192. }
  193. const data = dropType !== 'inner' ? dropNode.parent.data : dropNode.data
  194. var nodeData = dropNode.level === 1 && dropType !== 'inner' ? data : data.deptItems
  195. let list = []
  196. const findIndex = nodeData.findIndex(x => x.deptId === draggingNode.data.deptId)
  197. if (findIndex !== -1) {
  198. let sort
  199. if (findIndex === 0) {
  200. sort = 0
  201. } else {
  202. const prve = findIndex - 1
  203. sort = nodeData[prve].sort + 1
  204. }
  205. // draggingNode.data.sort = sort
  206. updateData.sort = sort
  207. let parentId = dropType !== 'inner' ? dropNode.parent.data.deptId : dropNode.data.deptId
  208. if (!parentId) {
  209. parentId = 0
  210. }
  211. const start = findIndex + 1
  212. list = nodeData.slice(start)
  213. updateData.parent = parentId
  214. // draggingNode.data.paterId = parentId
  215. list.forEach(item => {
  216. // sort++
  217. // item.sort = sort
  218. updateData.dropData.sortDeptIds.push(item.deptId)
  219. })
  220. updateData.dropData.roleDeptIds = this.parentNode
  221. updateData.dropData.deptItems = this.childrenNode
  222. }
  223. sortDeptTree(updateData.id, updateData.parent, updateData.sort, updateData.dropData).then(res => {
  224. if (res.data.code === 200) {
  225. let sort = updateData.sort
  226. draggingNode.data.sort = sort
  227. draggingNode.data.deptParentId = updateData.parent
  228. list.forEach(item => {
  229. sort++
  230. item.sort = sort
  231. })
  232. } else {
  233. this.$notify({
  234. title: '失败',
  235. message: '排序失败,请重试',
  236. type: 'error',
  237. duration: 2000
  238. })
  239. this.getTreeData()
  240. }
  241. })
  242. },
  243. // toggleShow(item) {
  244. // this.overIndex = item.deptId
  245. // },
  246. // // 左侧鼠标离开
  247. // togglenoShow(data) {
  248. // this.overIndex = -1
  249. // },
  250. tools(item) {
  251. if (this.cacheDataItem && item.deptId !== this.cacheDataItem.deptId) {
  252. this.cacheDataItem.visible = false
  253. }
  254. this.cacheDataItem = item
  255. },
  256. cancelDepartmen(data) {
  257. // data.visible = false
  258. setTimeout(() => {
  259. this.isModify = false
  260. }, 200)
  261. },
  262. openToModify(data) {
  263. this.companyName = data.deptName
  264. this.isModify = true
  265. },
  266. addPosition(type, node, data) {
  267. data.visible = false
  268. let parentId
  269. this.dialogVisible = true
  270. if (type === 'peer') {
  271. parentId = node.data.deptParentId
  272. } else if (type === 'child') {
  273. parentId = data.deptId
  274. }
  275. this.parentId = parentId
  276. },
  277. addCancel() {
  278. this.dialogVisible = false
  279. this.addDeptName = ''
  280. },
  281. addSave() {
  282. if (!this.addDeptName) {
  283. this.$notify({
  284. title: '添加失败',
  285. message: '部门名不能为空!',
  286. type: 'error',
  287. duration: 2000
  288. })
  289. return
  290. }
  291. const addData = {
  292. deptName: this.addDeptName,
  293. deptParentId: this.parentId
  294. }
  295. addDept(addData).then(res => {
  296. if (res.data.code === 200) {
  297. this.$notify({
  298. title: '成功',
  299. message: '添加部门成功',
  300. type: 'success',
  301. duration: 2000
  302. })
  303. this.getTreeData()
  304. this.dialogVisible = false
  305. this.addDeptName = ''
  306. }
  307. })
  308. },
  309. isDeleteDept(node, data) {
  310. data.visible = false
  311. if (node.childNodes.length) {
  312. this.$notify({
  313. title: '失败',
  314. message: '存在子部门,不能删除',
  315. type: 'error',
  316. duration: 2000
  317. })
  318. return
  319. }
  320. this.isDelete = true
  321. this.deleteId = data.deptId
  322. },
  323. deleteDept() {
  324. deleteDept(this.deleteId).then(res => {
  325. if (res.data.code === 200) {
  326. if (res.data.type === 1) {
  327. this.$notify({
  328. title: '成功',
  329. message: '删除部门成功',
  330. type: 'success',
  331. duration: 2000
  332. })
  333. this.getTreeData()
  334. } else if (res.data.type === 3) {
  335. this.$notify({
  336. title: '失败',
  337. message: res.data.msg,
  338. type: 'error',
  339. duration: 2000
  340. })
  341. }
  342. }
  343. this.isDelete = false
  344. })
  345. },
  346. modifyName(data) {
  347. if (!this.companyName) {
  348. this.$notify({
  349. title: '失败',
  350. message: '部门名不能为空',
  351. type: 'error',
  352. duration: 2000
  353. })
  354. return
  355. }
  356. const deptData = {
  357. deptId: data.deptId,
  358. deptName: this.companyName
  359. }
  360. modifyDeptName(deptData).then(res => {
  361. if (res.data.code === 200) {
  362. this.$notify({
  363. title: '成功',
  364. message: '修改部门名成功',
  365. type: 'success',
  366. duration: 2000
  367. })
  368. data.deptName = this.companyName
  369. data.visible = false
  370. this.$emit('selectDept', data)
  371. }
  372. })
  373. }
  374. }
  375. }
  376. </script>

8.0 绝对定位布局

  1. <el-drawer
  2. title="配置权限"
  3. :visible.sync="drawer"
  4. direction="rtl"
  5. :before-close="handleClose"
  6. size="40%">
  7. <div style="position: absolute;top:52px;left: 0;right: 0;bottom: 0;">
  8. <div style="position: absolute;top: 0;left: 0;right: 0;bottom: 60px;overflow-y: auto;">
  9. <el-tree
  10. :data="ruleList"
  11. show-checkbox
  12. node-key="id"
  13. default-expand-all
  14. :default-checked-keys="checkedKeys"
  15. :props="defaultProps"
  16. :check-strictly="true"
  17. @check="check">
  18. </el-tree>
  19. </div>
  20. <div style="height: 60px;position: absolute;bottom: 0;right: 0;left: 0;" class="border d-flex align-items-center px-3 bg-white">
  21. <el-button @click="drawer = false">取消</el-button>
  22. <el-button type="primary" @click="submitRules">确定</el-button>
  23. </div>
  24. </div>
  25. </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)
    }