From f2587f2104ea44568171de5b3ec844868fb6224b Mon Sep 17 00:00:00 2001
From: loulijun2021 <1694218219@qq.com>
Date: 星期三, 02 八月 2023 11:24:59 +0800
Subject: [PATCH] 1.角色权限完善
---
src/views/basicSettings/roleList.vue | 631 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 631 insertions(+), 0 deletions(-)
diff --git a/src/views/basicSettings/roleList.vue b/src/views/basicSettings/roleList.vue
new file mode 100644
index 0000000..a59c491
--- /dev/null
+++ b/src/views/basicSettings/roleList.vue
@@ -0,0 +1,631 @@
+<template>
+ <div>
+ <div class="body" :style="{height:mainHeight+'px'}">
+
+ <div
+ class="elTableDiv"
+ >
+
+ <div style="width: 300px;background:#fff">
+
+ <div style="margin: 20px 10px 0 10px;display: flex;justify-content: space-between;">
+ <div style="display: flex;">
+ <div
+ style="width: 5px;height: 100%;border-radius: 5px;"
+ :style="{background:$store.state.settings.theme}"
+ />
+ <div style="margin-left: 8px;">瑙掕壊鍚嶇О</div>
+ </div>
+
+ <div style="margin-right:10px">
+ <i class="el-icon-plus" style="cursor: pointer;color: #999" @click="rolePlusClick" />
+ </div>
+
+ </div>
+
+ <el-tree
+ ref="treeLeftRef"
+ style="padding: 10px;overflow: scroll"
+ :style="{height:(tableHeight-20)+'px'}"
+ :data="treeLeft"
+ node-key="code"
+ highlight-current
+ :props="defaultPropsLeft"
+ :default-expand-all="true"
+ :expand-on-click-node="false"
+ @node-click="treeLeftNodeClick"
+ >
+ <span slot-scope="{ node, data }" class="custom-tree-node">
+ <span v-if="!data.isEdit">{{ node.label }}</span>
+ <input
+ v-if="data.isEdit"
+ :ref="data.code"
+ v-model="node.label"
+ type="text"
+ @click.stop
+ @blur="roleSave(data)"
+ @keyup.enter="roleSave(data)"
+ >
+
+ <span v-if="!data.isEdit">
+ <i
+ v-if="data.code!=='000'"
+ class="el-icon-edit"
+ style="margin-right:10px;color: #999"
+ @click.stop="val=>roleEditClick(val,node,data)"
+ />
+ <i
+ v-if="data.code!=='000'"
+ class="el-icon-delete"
+ style="margin-right: 4px;color: #999"
+ @click.stop="val=>roleDeleteClick(val,node,data)"
+ />
+ </span>
+ </span>
+ </el-tree>
+ </div>
+
+ <div
+ style="margin-left: 15px;width:100%;position: relative"
+ >
+
+ <el-button
+ style="position: absolute;right: 15px;z-index:1;top:3px"
+ type="primary"
+ @click="saveClick"
+ >淇� 瀛�</el-button>
+
+ <el-tabs v-model="activeName" type="border-card">
+ <el-tab-pane label="PC绔�" name="PC绔�">
+ <div style="display: flex;">
+
+ <div
+ ref="scrollLeft"
+ style="border-right: 1px solid rgba(0,0,0,0.2);width: 200px;
+ overflow-y: auto;overflow-x:hidden;"
+ :style="{height:(tableHeight-40)+'px'}"
+ @scroll="scrollLeftScroll()"
+ @mouseover="isScroll='left'"
+ >
+ <div style=" ">
+ <i class="el-icon-s-operation" :style="{color:$store.state.settings.theme}" /> 鑿滃崟鏉冮檺
+ </div>
+
+ <el-tree
+ ref="treeCenterRef"
+ style="padding-top: 10px;width: 199px;"
+ :data="treeCenter"
+ highlight-current
+ :props="defaultPropsCenter"
+ show-checkbox
+ node-key="code"
+ :default-expand-all="true"
+ @check-change="handleTreeCenterCheckChange"
+ @check="handleTreeCenterCheck"
+ @node-click="getLeftTreeNode"
+ />
+ </div>
+
+ <div
+ ref="scrollCenter"
+ style="border-right: 1px solid rgba(0,0,0,0.2);width: 600px;padding-left: 10px;overflow-y: auto"
+ :style="{height:(tableHeight-40)+'px'}"
+ @scroll="scrollCenterScroll()"
+ @mouseover="isScroll='center'"
+ >
+ <div style=" ">
+ <i class="el-icon-s-operation" :style="{color:$store.state.settings.theme}" /> 鎸夐挳鏉冮檺
+ </div>
+
+ <el-checkbox
+ v-model="buttonIsChecked"
+ style="height: 26px;display:flex;align-items: center;margin-top:10px;width:200px"
+ @change="val=>handleCheckAllChange(val,'button')"
+ >鍏ㄩ��
+ </el-checkbox>
+
+ <div v-if="treeCenter.length>0">
+ <div v-for="item in treeCenter[0].children" :key="item.code">
+ <div
+ v-if="item.display"
+ style="margin-left: 40px;height:26px;display: flex;"
+ />
+
+ <el-checkbox-group
+ v-for="it in item.children"
+ v-if="item.expanded"
+ :key="it.code"
+ v-model="it.checkedButton"
+ style="margin-left: 40px;height:26px;display: flex"
+ @change="val=>handleCheckedButtonChange(val,it.code)"
+ >
+
+ <el-checkbox
+ v-for="i in it.itemButton"
+ :key="i.code"
+ :label="i.name"
+ style="display:flex;align-items: center"
+ />
+ </el-checkbox-group>
+ </div>
+
+ </div>
+
+ </div>
+
+ <div
+ ref="scrollRight"
+ style="width: 360px;padding-left: 10px;overflow-y: auto"
+ :style="{height:(tableHeight-40)+'px',}"
+ @scroll="scrollRightScroll()"
+ @mouseover="isScroll='right'"
+ >
+ <div style=" ">
+ <i class="el-icon-s-operation" :style="{color:$store.state.settings.theme}" /> 鏁版嵁鏉冮檺
+ </div>
+
+ <el-checkbox
+ v-model="dataIsChecked"
+ style="height: 26px;display:flex;align-items: center;margin-top:10px;width:200px"
+ @change="val=>handleCheckAllChange(val,'data')"
+ >鍏ㄩ��
+ </el-checkbox>
+
+ <div v-if="treeCenter.length>0">
+ <div v-for="item in treeCenter[0].children" :key="item.code">
+ <div
+ v-if="item.display"
+ style="margin-left: 40px;height:26px;display: flex;"
+ />
+
+ <el-radio-group
+ v-for="it in item.children"
+ v-if="item.expanded"
+ :key="it.code"
+ v-model="it.checkedData"
+ style="margin-left: 40px;height:26px;display: flex"
+ @change="val=>handleCheckedDataChange(val,it.code)"
+ >
+ <el-radio
+ v-for="i in it.itemData"
+ :key="i.code"
+ style="display:flex;align-items: center"
+ :label="i.name"
+ />
+ </el-radio-group>
+ </div>
+
+ </div>
+
+ </div>
+
+ </div>
+ </el-tab-pane>
+ <el-tab-pane label="APP绔�" name="APP绔�">澶уぇ</el-tab-pane>
+ <el-tab-pane label="宸ユ帶绔�" name="宸ユ帶绔�">宸ユ帶绔�</el-tab-pane>
+ </el-tabs>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ </div>
+</template>
+
+<script>
+import waves from '@/directive/waves'
+import {
+ RolePermissionSava,
+ RolePermissionSearchRole,
+ RolePermissionSearchRoleMenu,
+ RolePermissionSearchRoleMenuButton
+} from '@/api/basicSettings'
+import arrayToTree from 'array-to-tree'
+import { throttle } from '@/utils/debounceAndThrottle'
+
+export default {
+ name: 'RoleList',
+ directives: { waves },
+ data() {
+ return {
+ mainHeight: 0,
+ tableHeight: 0,
+
+ treeLeft: [], // 宸︿晶鏍�
+ treeCenter: [], // 涓棿鏍�
+ defaultPropsLeft: {
+ children: 'roles',
+ label: 'name'
+ },
+ defaultPropsCenter: {
+ children: 'children',
+ label: 'name'
+ },
+ activeName: 'PC绔�',
+
+ buttonIsChecked: false,
+ dataIsChecked: false,
+
+ menuCheckedCodeArr: [], // 鑿滃崟鏉冮檺鏁扮粍閫変腑鐨�
+
+ allButtonData: [], // 鎵�鏈夌殑鎸夐挳鍔犳潈闄�
+
+ isScroll: 'left'
+
+ }
+ },
+ watch: {
+ treeLeft: {
+ handler(newValue, oldValue) {
+ newValue[0].roles.forEach(i => {
+ if (i.isEdit) {
+ this.$nextTick(() => {
+ this.$refs[i.code].focus()
+ })
+ }
+ })
+ },
+ deep: true
+ }
+ },
+
+ created() {
+ this.getRolePermissionSearchRole()
+ },
+ mounted() {
+ window.addEventListener('resize', this.getHeight)
+ this.getHeight()
+ },
+ methods: {
+
+ // 鑾峰彇瑙掕壊鏉冮檺鏌ヨ瑙掕壊
+ async getRolePermissionSearchRole() {
+ const { data: res } = await RolePermissionSearchRole()
+ res[0].roles.forEach(i => {
+ i.isEdit = false
+ })
+
+ this.treeLeft = res
+
+ if (res.length > 0) {
+ this.$nextTick(() => { // 榛樿閫変腑绗竴涓�
+ this.$refs.treeLeftRef.setCurrentKey(res[0].roles[0].code) // 榛樿閫変腑鑺傜偣绗竴涓�
+ })
+ await this.getRolePermissionSearchRoleMenuButton(res[0].roles[0].code)
+ await this.getRolePermissionSearchRoleMenu(res[0].roles[0].code)
+ } else {
+ this.$notify.error('璇峰厛寤虹浉瀵瑰簲鐨勮鑹诧紒')
+ }
+ },
+ // 鑾峰彇鑿滃崟鏉冮檺瀵瑰簲鐨勬寜閽�
+ async getRolePermissionSearchRoleMenuButton(rolecode) {
+ const { data: res } = await RolePermissionSearchRoleMenuButton({ rolecode })
+ this.allButtonData = res
+ },
+ // 鑾峰彇鑿滃崟鏉冮檺
+ async getRolePermissionSearchRoleMenu(rolecode) {
+ const { data: res } = await RolePermissionSearchRoleMenu({ rolecode, type: 'PC' })
+
+ // 鎷垮埌鏁扮粍list杞崲鎴愭爲褰ree
+ const result = arrayToTree(res, {
+ parentProperty: 'parentid',
+ customID: 'code',
+ childrenProperty: 'children'
+ })
+
+ this.menuCheckedCodeArr = []
+
+ result.forEach(item => {
+ if (item.children && item.children.length) {
+ item.children.forEach(it => {
+ // 鎸夐挳鏉冮檺鍥炴樉
+ const buttonAll = this.allButtonData.tButton.filter(j => j.menucode === it.code)
+ const buttonChecked = this.allButtonData.tButton.filter(j =>
+ j.menucode === it.code && j.flag === 'Y'
+ ).map(j => j.name)
+ it.itemButton = buttonAll
+ it.checkedButton = buttonChecked
+
+ // 鏁版嵁鏉冮檺鍥炴樉
+ const dataAll = this.allButtonData.tData.filter(j => j.menucode === it.code)
+ const dataChecked = this.allButtonData.tData.filter(j => j.menucode === it.code && j.flag === 'Y')
+
+ it.itemData = dataAll
+ it.checkedData = dataChecked.length > 0 ? dataChecked[0].name : []
+
+ // 鐢ㄤ綔鑿滃崟鍕鹃�夊洖鏄�
+ if (it.flag === 'Y') {
+ this.menuCheckedCodeArr.push(it.code)
+ }
+ })
+ item.display = true
+ item.expanded = true
+ }
+ })
+
+ // console.log(JSON.parse(JSON.stringify(result)), 8)
+
+ this.treeCenter = [
+ { code: '-1', name: '鍏ㄩ儴', flag: result.every(i => i.flag === 'Y') ? 'Y' : 'N', children: result }
+ ]
+
+ this.handleCheckedButtonChange('', '', true)
+ this.handleCheckedDataChange('', '', true)
+
+ this.$nextTick(() => {
+ this.$refs.treeCenterRef.setCheckedKeys(this.menuCheckedCodeArr)
+ })
+
+ this.$forceUpdate()
+ },
+
+ // 宸﹁竟婊氬姩鏉℃粦鍔ㄦ椂
+ scrollLeftScroll() {
+ if (this.isScroll === 'left') {
+ this.$refs.scrollCenter.scrollTop = this.$refs.scrollLeft.scrollTop
+ this.$refs.scrollRight.scrollTop = this.$refs.scrollLeft.scrollTop
+ }
+ },
+ // 涓棿杈规粴鍔ㄦ潯婊戝姩鏃�
+ scrollCenterScroll() {
+ if (this.isScroll === 'center') {
+ this.$refs.scrollLeft.scrollTop = this.$refs.scrollCenter.scrollTop
+ this.$refs.scrollRight.scrollTop = this.$refs.scrollCenter.scrollTop
+ }
+ },
+ // 鍙充晶婊氬姩鏉℃粦鍔ㄦ椂
+ scrollRightScroll() {
+ if (this.isScroll === 'right') {
+ this.$refs.scrollLeft.scrollTop = this.$refs.scrollRight.scrollTop
+ this.$refs.scrollCenter.scrollTop = this.$refs.scrollRight.scrollTop
+ }
+ },
+ // 鍏ㄩ�夋敼鍙�
+ handleCheckAllChange(val, belong) {
+ const checkedKeys = this.$refs.treeCenterRef.getCheckedKeys()
+
+ if (val) {
+ this.treeCenter[0].children.forEach(item => {
+ if (item.children && item.children.length) {
+ item.children.forEach(it => {
+ if (checkedKeys.includes(it.code)) {
+ if (belong === 'button') {
+ it.checkedButton = it.itemButton.map(i => i.name)
+ }
+ if (belong === 'data') {
+ it.checkedData = '鍏ㄩ儴'
+ }
+ }
+ })
+ }
+ })
+ } else {
+ this.treeCenter[0].children.forEach(item => {
+ if (item.children && item.children.length) {
+ item.children.forEach(it => {
+ if (checkedKeys.includes(it.code)) {
+ if (belong === 'button') {
+ it.checkedButton = []
+ }
+ if (belong === 'data') {
+ it.checkedData = undefined
+ }
+ }
+ })
+ }
+ })
+ }
+ },
+ // 鍗曚釜鎸夐挳鏀瑰彉
+ handleCheckedButtonChange(value, code, flag) {
+ // 鍒ゆ柇鏄惁鍖呭惈鍦ㄥ唴
+ if (!flag) {
+ if (!this.menuCheckedCodeArr.includes(code) && value.length === 1) { // 鍚�
+ this.menuCheckedCodeArr.push(code)
+ } else if (this.menuCheckedCodeArr.includes(code) && value.length === 0) { // 鏄�
+ this.menuCheckedCodeArr = this.menuCheckedCodeArr.filter(i => i !== code)
+ }
+ this.$refs.treeCenterRef.setCheckedKeys(this.menuCheckedCodeArr)
+ }
+
+ // 杩欓噷鏄垽鏂叏閫塩heckbox 鏄惁閫変腑
+ let count = 0
+ let childrenLength = 0
+ this.treeCenter[0].children.forEach(item => {
+ if (item.children && item.children.length) {
+ item.children.forEach(it => {
+ if (it.checkedButton.length === it.itemButton.length) {
+ count++
+ }
+ childrenLength++
+ })
+ }
+ })
+ this.buttonIsChecked = count === childrenLength
+ this.$forceUpdate()
+ },
+ // 鑾峰彇鏍戝舰鑺傜偣node
+ getLeftTreeNode(data, Node, VueComponent) {
+ // console.log(data, Node, VueComponent, 2221)
+ // console.log(Node.expanded)
+ this.treeCenter[0].children.forEach(item => {
+ if (item.name === data.name) {
+ item.expanded = Node.expanded
+ }
+ })
+ if (data.code === '-1') {
+ Node.expanded = true // 鏆傛椂鍏堝啓鎴愯繖涓�
+ // this.treeCenter[0].children.forEach(item => {
+ // item.expanded = Node.expanded
+ // })
+ }
+ this.$forceUpdate()
+ },
+ // 澶勭悊涓棿鏍戝舰鍕鹃��
+ handleTreeCenterCheck(obj, { checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys }) {
+ // console.log(obj, checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys, '鍔犲瀹�')
+
+ if (checkedKeys.length === 0) { // 鏍戝舰鑿滃崟鍏ㄤ笉閫夌殑鎯呭喌涓�
+ this.buttonIsChecked = false
+ this.dataIsChecked = false
+ this.menuCheckedCodeArr = []
+ } else {
+ if (checkedKeys.includes(obj.code)) { // 鍒ゆ柇鏄惁鍖呭惈鍦ㄥ唴 //鏄�
+ this.menuCheckedCodeArr.push(obj.code)
+ } else { // 鍚�
+ this.menuCheckedCodeArr = this.menuCheckedCodeArr.filter(i => i !== obj.code)
+ }
+ }
+ },
+ // 澶勭悊涓棿鏍戝舰閫変腑鍊兼敼鍙�
+ handleTreeCenterCheckChange(obj, selfChecked, selfChildrenTreeCheck) {
+ // console.log(obj, selfChecked, selfChildrenTreeCheck, '鐜嬭�佸悏')
+ obj.flag = selfChecked ? 'Y' : 'N'
+ if (!selfChildrenTreeCheck) {
+ if (!selfChecked) {
+ this.treeCenter[0].children.forEach(item => {
+ if (item.children && item.children.length) {
+ item.children.forEach(it => {
+ if (it.code === obj.code) {
+ it.checkedButton = []
+ it.checkedData = undefined
+ }
+ })
+ }
+ })
+ this.$forceUpdate()
+ }
+ }
+ },
+ // 鍗曢�夋鎸夐挳鏀瑰彉
+ handleCheckedDataChange(value, code, flag) {
+ // console.log(value, code)
+ if (!flag) {
+ this.menuCheckedCodeArr.push(code)
+ this.menuCheckedCodeArr = [...new Set(this.menuCheckedCodeArr)]
+
+ this.$refs.treeCenterRef.setCheckedKeys(this.menuCheckedCodeArr)
+ }
+ // 杩欓噷鏄垽鏂叏閫塺adio 鏄惁閫変腑
+ let count = 0
+ let childrenLength = 0
+ this.treeCenter[0].children.forEach(item => {
+ if (item.children && item.children.length) {
+ item.children.forEach(it => {
+ if (it.checkedData.length > 0) {
+ count++
+ }
+ if (it.itemData.length > 0) {
+ childrenLength++
+ }
+ })
+ }
+ })
+ // console.log(count, childrenLength, 9)
+ this.dataIsChecked = count === childrenLength
+ this.$forceUpdate()
+ },
+ // 瑙掕壊鍒囨崲
+ async treeLeftNodeClick(obj, Node, VueComponent) {
+ if (obj.code !== '000') {
+ await this.getRolePermissionSearchRoleMenuButton(obj.code)
+ await this.getRolePermissionSearchRoleMenu(obj.code)
+ }
+ },
+ // 瑙掕壊鍚嶇О鏂板
+ rolePlusClick() {
+ this.treeLeft[0].roles.push({ code: 1234, name: '', isEdit: true })
+ },
+ // 瑙掕壊鍚嶇О淇敼
+ roleEditClick(self, node, data) {
+ // console.log(self, node, data)
+ this.treeLeft[0].roles.forEach(i => {
+ i.isEdit = false
+ })
+ data.isEdit = !data.isEdit
+ },
+ // 瑙掕壊鍚嶇О鍒犻櫎
+ roleDeleteClick(self, node, data) {
+ // console.log(self, node, data)
+ // this.treeLeft[0].roles.forEach((item, index) => {
+ // if (item.code === data.code) {
+ // this.treeLeft[0].roles.splice(index, 1) // 鏆傛椂鍏堝啓鎴愬墠绔垹闄わ紝鍚庢湡璋冪敤鎺ュ彛鍒犻櫎
+ // }
+ // })
+ },
+ // 瑙掕壊鍚嶇О淇濆瓨 閲囩敤闃叉姈褰㈠紡
+ roleSave: throttle(function(data) {
+ data.isEdit = false
+ console.log('鎵ц浜嗭紒')
+ }, 1000, true),
+
+ // 椤甸潰鍕鹃�夊ソ淇濆瓨浜嬩欢
+ saveClick() {
+ // console.log(this.treeCenter)
+
+ const rolecode = this.$refs.treeLeftRef.getCurrentKey()
+
+ const roleMenu = []
+ const roleButton = []
+ const roleData = []
+
+ this.treeCenter[0].children.forEach((item, index) => {
+ if (item.children && item.children.length) {
+ item.children.forEach((it, ind) => {
+ if (it.flag === 'Y') {
+ roleMenu.push({ rolecode, menucode: it.code })
+
+ if (it.itemButton && it.itemButton.length && it.checkedButton.length > 0) {
+ it.itemButton.forEach(i => {
+ if (it.checkedButton.includes(i.name)) {
+ roleButton.push({ rolecode, buttoncode: i.code })
+ }
+ })
+ }
+ if (it.checkedData && it.checkedData.length) {
+ roleData.push({ rolecode, datacode: it.itemData.find(i => i.name === it.checkedData).code })
+ }
+ }
+ })
+ }
+ })
+ // console.log(roleMenu)
+ // console.log(roleButton)
+ // console.log(roleData)
+ const data = {
+ roleMenu, roleButton, roleData
+ }
+
+ RolePermissionSava(data).then(res => {
+ if (res.code === '200') {
+ const rolename = this.treeLeft[0].roles.find(i => i.code === rolecode).name
+ this.$notify.success(rolename + '鐨勮鑹叉潈闄愭彁浜ゆ垚鍔燂紒')
+ this.getRolePermissionSearchRoleMenuButton(rolecode)
+ this.getRolePermissionSearchRoleMenu(rolecode)
+ }
+ this.$forceUpdate()
+ })
+ },
+ // 鑾峰彇椤甸潰楂樺害
+ getHeight() {
+ this.$nextTick(() => {
+ this.mainHeight = window.innerHeight - 85
+ this.tableHeight = this.mainHeight - 50
+ })
+ }
+ }
+}
+</script>
+
+<style scoped lang="scss">
+.custom-tree-node {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ font-size: 14px;
+ padding-right: 8px;
+}
+</style>
--
Gitblit v1.9.3