- 添加 AppRoleRightsManager 组件,实现角色管理、权限分配等功能 - 新增 rightsAdd 组件,用于添加和编辑应用角色 - 新增 rightsGraph 组件,用于展示权限关系图 - 集成 ECharts 实现复杂的权限关系可视化
		
			
				
	
	
		
			193 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			193 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <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>
 |