|
@@ -1,24 +1,24 @@
|
|
|
<template>
|
|
|
<div class="fullBox white pa-3 relative" ref="boxRef">
|
|
|
<e-charts ref="eCharts" class="fullBox"></e-charts>
|
|
|
- <div class="btnBox pa-1">
|
|
|
- <m-button type="orange" icon="el-icon-download" size="small" :loading="exportLoading" @click="onExport">导出</m-button>
|
|
|
- <m-button type="orange" icon="el-icon-plus" size="small" @click="onAdd">新增机构</m-button>
|
|
|
- </div>
|
|
|
- <div ref="contextMenuRefs" class="contextMenu">
|
|
|
- <el-card shadow="always" :body-style="{padding: 0}">
|
|
|
- <div
|
|
|
- v-for="menu in menus"
|
|
|
- :key="menu.prop"
|
|
|
- class="contextMenuItem pa-3"
|
|
|
- @click="onMenuClick(menu.prop)"
|
|
|
- >
|
|
|
- {{ menu.label }}
|
|
|
- </div>
|
|
|
- </el-card>
|
|
|
- </div>
|
|
|
- <OrganizationEdit ref="organizationEditRefs" @refresh="onRefresh"></OrganizationEdit>
|
|
|
- <OrganizationAdd ref="organizationAddRefs" @refresh="onRefresh"></OrganizationAdd>
|
|
|
+ <div class="btnBox pa-1">
|
|
|
+ <m-button type="orange" icon="el-icon-download" size="small" :loading="exportLoading" @click="onExport">导出</m-button>
|
|
|
+ <m-button type="orange" icon="el-icon-plus" size="small" @click="onAdd">新增机构</m-button>
|
|
|
+ </div>
|
|
|
+ <div ref="contextMenuRefs" class="contextMenu" v-show="contextMenuShow">
|
|
|
+ <el-card shadow="always" :body-style="{padding: 0}">
|
|
|
+ <div
|
|
|
+ v-for="menu in menus"
|
|
|
+ :key="menu.prop"
|
|
|
+ class="contextMenuItem pa-3"
|
|
|
+ @click="onMenuClick(menu.prop)"
|
|
|
+ >
|
|
|
+ {{ menu.label }}
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+ <OrganizationEdit ref="organizationEditRefs" @refresh="onRefresh"></OrganizationEdit>
|
|
|
+ <OrganizationAdd ref="organizationAddRefs" @refresh="onRefresh"></OrganizationAdd>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
@@ -27,7 +27,7 @@ import OrganizationEdit from './organizationEdit.vue'
|
|
|
import OrganizationAdd from './organizationAdd.vue'
|
|
|
|
|
|
import {
|
|
|
- getOrganizationAtlas,
|
|
|
+ getOrganizationAndEmployeeTree,
|
|
|
// getOrganizationAtlasEmployee,
|
|
|
importOrganization,
|
|
|
exportOrganization,
|
|
@@ -39,7 +39,6 @@ import {
|
|
|
upload,
|
|
|
download
|
|
|
} from '@/utils/elementUploadAndDownload'
|
|
|
-
|
|
|
export default {
|
|
|
name: 'organization-structure',
|
|
|
components: {
|
|
@@ -48,6 +47,7 @@ export default {
|
|
|
},
|
|
|
data () {
|
|
|
return {
|
|
|
+ contextMenuShow: false,
|
|
|
menus: [
|
|
|
{ label: '编辑', prop: 'edit' },
|
|
|
{ label: '删除', prop: 'delete' }
|
|
@@ -76,9 +76,12 @@ export default {
|
|
|
symbolSize: 15,
|
|
|
label: {
|
|
|
position: 'left',
|
|
|
- verticalAlign: 'middle',
|
|
|
+ borderColor: '#000',
|
|
|
+ // backgroundColor: '#ff650e',
|
|
|
+ // verticalAlign: 'middle',
|
|
|
align: 'right',
|
|
|
- fontSize: 16
|
|
|
+ fontSize: 16,
|
|
|
+ silent: false
|
|
|
},
|
|
|
leaves: {
|
|
|
label: {
|
|
@@ -87,12 +90,9 @@ export default {
|
|
|
align: 'left'
|
|
|
}
|
|
|
},
|
|
|
- emphasis: {
|
|
|
- focus: 'descendant'
|
|
|
- },
|
|
|
initialTreeDepth: 1,
|
|
|
roam: true,
|
|
|
- expandAndCollapse: true,
|
|
|
+ expandAndCollapse: false,
|
|
|
animationDuration: 550,
|
|
|
animationDurationUpdate: 750
|
|
|
}
|
|
@@ -103,50 +103,95 @@ export default {
|
|
|
mounted () {
|
|
|
this.$nextTick(async () => {
|
|
|
this.graph = this.$refs.eCharts.onInit()
|
|
|
- console.log(211, this.graph)
|
|
|
this.graph.showLoading()
|
|
|
- const { data } = await this.onInit()
|
|
|
- this.seriesData = data
|
|
|
-
|
|
|
+ this.seriesData = await this.onInit()
|
|
|
this.graph.setOption(this.option)
|
|
|
this.graph.hideLoading()
|
|
|
+ this.graph.on('click', (params) => {
|
|
|
+ const data = getData(params.data.id, this.seriesData)
|
|
|
+ if (params.event.target.type === 'tspan') {
|
|
|
+ this.nodes = data
|
|
|
+ this.onGraphHandles(params.event.event)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.show = false
|
|
|
+ if (!params.data.children || !params.data.children.length) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ data.collapsed = !data.collapsed
|
|
|
+ this.graph.setOption(this.option)
|
|
|
+ })
|
|
|
+ // 关闭
|
|
|
+ this.graph.getZr().on('click', (event) => {
|
|
|
+ if (event.target?.type !== 'tspan') {
|
|
|
+ this.contextMenuShow = false
|
|
|
+ }
|
|
|
+ })
|
|
|
+ this.graph.on('treeroam', (event) => {
|
|
|
+ this.contextMenuShow = false
|
|
|
+ })
|
|
|
})
|
|
|
|
|
|
- // this.$nextTick(() => {
|
|
|
- // this.$refs.boxRef.addEventListener('contextmenu', (e) => {
|
|
|
- // e.preventDefault()
|
|
|
- // })
|
|
|
- // })
|
|
|
+ function getData (id, data) {
|
|
|
+ if (data.id === id) {
|
|
|
+ return data
|
|
|
+ }
|
|
|
+ if (data.children && data.children.length) {
|
|
|
+ for (const item of data.children) {
|
|
|
+ const result = getData(id, item)
|
|
|
+ if (result) {
|
|
|
+ return result
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null
|
|
|
+ }
|
|
|
+ },
|
|
|
+ beforeDestroy () {
|
|
|
+ if (!this.graph) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.graph.off('click')
|
|
|
+ this.graph.off('treeroam')
|
|
|
},
|
|
|
- // beforeDestroy () {
|
|
|
- // this.$refs.boxRef.removeEventListener('contextmenu', (e) => {
|
|
|
- // e.preventDefault()
|
|
|
- // })
|
|
|
- // },
|
|
|
methods: {
|
|
|
async onInit () {
|
|
|
this.loading = true
|
|
|
try {
|
|
|
- const { data } = await getOrganizationAtlas()
|
|
|
- const { nodes, edges } = data
|
|
|
- const graphData = {
|
|
|
- nodes: nodes.map(e => {
|
|
|
- return {
|
|
|
- ...e,
|
|
|
- getChildren: this.getChildren
|
|
|
- }
|
|
|
- }),
|
|
|
- edges
|
|
|
+ const { data } = await getOrganizationAndEmployeeTree({})
|
|
|
+ return changeChildToChildren(data)
|
|
|
+ function changeChildToChildren (obj, currentDepth = 1, maxDepth = 2) {
|
|
|
+ const { child, ..._obj } = obj
|
|
|
+ _obj.collapsed = currentDepth >= maxDepth
|
|
|
+ if (child && child.length) {
|
|
|
+ _obj.children = child.map(e => changeChildToChildren(e, currentDepth + 1, maxDepth))
|
|
|
+ }
|
|
|
+ return _obj
|
|
|
}
|
|
|
- return graphData
|
|
|
} catch (error) {
|
|
|
this.$message.error(error)
|
|
|
- return { nodes: [], edges: [] }
|
|
|
+ return {}
|
|
|
} finally {
|
|
|
this.loading = false
|
|
|
}
|
|
|
},
|
|
|
-
|
|
|
+ onGraphHandles (e) {
|
|
|
+ const contextMenu = this.$refs.contextMenuRefs
|
|
|
+ const { width, height } = this.$refs.boxRef.getBoundingClientRect()
|
|
|
+ const { left, top } = this.$refs.boxRef.getBoundingClientRect()
|
|
|
+ const content = {
|
|
|
+ x: 0,
|
|
|
+ y: 0,
|
|
|
+ width,
|
|
|
+ height
|
|
|
+ }
|
|
|
+ const { x, y } = e
|
|
|
+ content.x = x
|
|
|
+ content.y = y
|
|
|
+ contextMenu.style.left = x - left + 'px'
|
|
|
+ contextMenu.style.top = y - top + 'px'
|
|
|
+ this.contextMenuShow = true
|
|
|
+ },
|
|
|
async onDelete (nodes) {
|
|
|
this.$confirm('是否删除该项', '提示').then(async () => {
|
|
|
try {
|
|
@@ -204,7 +249,6 @@ export default {
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
.contextMenu {
|
|
|
- display: none;
|
|
|
position: absolute;
|
|
|
width: 200px;
|
|
|
}
|