feat(xumu): 新增应用角色权限管理功能
- 添加 AppRoleRightsManager 组件,实现角色管理、权限分配等功能 - 新增 rightsAdd 组件,用于添加和编辑应用角色 - 新增 rightsGraph 组件,用于展示权限关系图 - 集成 ECharts 实现复杂的权限关系可视化
This commit is contained in:
		
							
								
								
									
										192
									
								
								project/xumu/AppRoleRightsManager/rightsGraph.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								project/xumu/AppRoleRightsManager/rightsGraph.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,192 @@ | ||||
| <template> | ||||
|   <section class="rightsGraph"> | ||||
|     <div id="RightGraph"/> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| ; | ||||
|  | ||||
| export default { | ||||
|   name: "rightsGraph", | ||||
|   inject: ['top'], | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     app: Object | ||||
|   }, | ||||
|   computed: { | ||||
|     graphData() { | ||||
|       let data = [...this.users, ...this.nodes].map(e => { | ||||
|         if (e.x) { | ||||
|           return e | ||||
|         } else return {...e, ...this.renderPosition(e)} | ||||
|       }) | ||||
|       return [ | ||||
|         { | ||||
|           data, | ||||
|           links: this.links, | ||||
|           categories: data.map(e => e.category).flat().map(name => ({name})) | ||||
|         } | ||||
|       ] | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       graph: null, | ||||
|       nodes: [], | ||||
|       links: [], | ||||
|       users: [] | ||||
|     } | ||||
|   }, | ||||
|   watch: { | ||||
|     graphData: { | ||||
|       deep: true, handler() { | ||||
|         this.refreshGraph() | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     initGraph() { | ||||
|       let dom = document.querySelector("#RightGraph") | ||||
|       if (dom) { | ||||
|         this.graph = echarts.init(dom) | ||||
|         this.graph.setOption({ | ||||
|           tooltip: {}, | ||||
|           series: [ | ||||
|             { | ||||
|               type: 'graph', | ||||
|               layout: 'none', | ||||
|               roam: true, | ||||
|               label: { | ||||
|                 show: true, | ||||
|                 position: 'right', | ||||
|                 formatter: '{b}' | ||||
|               }, | ||||
|               labelLayout: { | ||||
|                 hideOverlap: true, | ||||
|               }, | ||||
|               scaleLimit: { | ||||
|                 min: 0.4, | ||||
|                 max: 4 | ||||
|               }, | ||||
|               lineStyle: { | ||||
|                 color: 'target', | ||||
|                 curveness: 0.1 | ||||
|               }, | ||||
|               emphasis: { | ||||
|                 focus: 'adjacency', | ||||
|                 lineStyle: { | ||||
|                   width: 5 | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           ] | ||||
|         }) | ||||
|         this.graph.on('click', this.handleNodeClick) | ||||
|       } | ||||
|     }, | ||||
|     refreshGraph() { | ||||
|       this.graph?.setOption({ | ||||
|         series: this.graphData | ||||
|       }) | ||||
|     }, | ||||
|     getAppRoles(role) { | ||||
|       if (role) { | ||||
|         this.nodes.push({...role, category: '应用角色', value: "应用角色", symbolSize: 15}) | ||||
|       } else this.instance.post(this.top.actions.list, null, { | ||||
|         params: {pageSize: 999} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           res.data.records.map(e => { | ||||
|             this.getUsers(e.users, e.id) | ||||
|             this.nodes.push({...e, category: '应用角色', value: "应用角色"}) | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     getUsers(pending, source) { | ||||
|       pending?.map(e => { | ||||
|         if (!this.users.some(u => u.id == e.phone)) { | ||||
|           this.users.push({id: e.phone, name: e.name, symbolSize: 5, category: '用户', value: "用户"}) | ||||
|         } | ||||
|         this.links.push({source, target: e.phone}) | ||||
|       }) | ||||
|     }, | ||||
|     getPermissions({id: roleId, name: category, dataIndex}) { | ||||
|       const addNodes = (list, source, category, pos) => { | ||||
|         list?.map(e => { | ||||
|           let node = { | ||||
|             ...e, | ||||
|             symbolSize: 5, | ||||
|             category, | ||||
|             value: e.list?.length > 0 ? "应用" : "权限", | ||||
|           } | ||||
|           node = {...node, ...this.renderPosition(pos || node)} | ||||
|           this.nodes.splice(dataIndex, 0, node) | ||||
|           if (e.checked == 1) { | ||||
|             this.links.push({source, target: e.id}) | ||||
|           } | ||||
|           addNodes(e.list, e.id, e.label, node) | ||||
|         }) | ||||
|       } | ||||
|       roleId && this.instance.post(this.top.actions.detail, null, { | ||||
|         params: {roleId} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           addNodes(res.data, roleId, category) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleNodeClick(v) { | ||||
|       let {data: role, dataIndex} = v | ||||
|       if (!this.nodes.some(e => e.category == role?.name)) { | ||||
|         role && this.getPermissions({...role, dataIndex}) | ||||
|       } | ||||
|     }, | ||||
|     renderPosition(node) { | ||||
|       node = JSON.parse(JSON.stringify(node)) | ||||
|       let pos = {x: 0, y: 0} | ||||
|       if (node?.x) { | ||||
|         pos.x = Math.max(this.graph?.getWidth() / 3 * 2, node.x) + 100 + Math.random() * 50 | ||||
|         pos.y = node.y + Math.random() * 100 - 50 | ||||
|       } else if (node.value == '应用角色') { | ||||
|         pos.x = this.graph?.getWidth() / 3 - 200 + Math.random() * 200 | ||||
|         pos.y = this.graph?.getHeight() / 2 - 100 + Math.random() * 200 | ||||
|       } else if (node.value == '应用') { | ||||
|         pos.x = this.graph?.getWidth() / 3 * 2 - 100 + Math.random() * 100 | ||||
|         pos.y = Math.random() * this.graph?.getHeight() | ||||
|       } else if (node.value == '用户') { | ||||
|         pos.x = Math.random() * 50 | ||||
|         pos.y = Math.random() * this.graph?.getHeight() | ||||
|       } else { | ||||
|         pos.x = this.graph?.getWidth() - 100 + Math.random() * 100 | ||||
|         pos.y = Math.random() * this.graph?.getHeight() | ||||
|       } | ||||
|       return pos | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getAppRoles(this.app) | ||||
|     this.getUsers(this.app.users, this.app.id) | ||||
|     this.getPermissions(this.app) | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.$nextTick(() => { | ||||
|       this.initGraph() | ||||
|     }) | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .rightsGraph { | ||||
|   height: 100%; | ||||
|  | ||||
|   :deep( #RightGraph ){ | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|     min-height: 500px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
		Reference in New Issue
	
	Block a user