- 添加 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>
|