Merge branch 'dev' into build
# Conflicts: # components/AiOkrTree/AiOkrTree.vue # project/dv/apps/AppGridDV.vue
This commit is contained in:
@@ -610,6 +610,14 @@
|
|||||||
.dept-name{
|
.dept-name{
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 200px;
|
width: 200px;
|
||||||
|
height: 22px;
|
||||||
|
overflow:hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
.el-icon-arrow-down{
|
||||||
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.active{
|
.active{
|
||||||
|
|||||||
@@ -1,282 +1,282 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="AiGrid" ref="container">
|
<div class="AiGrid" ref="container">
|
||||||
<div
|
<div
|
||||||
class="AiGrid-wrapper"
|
class="AiGrid-wrapper"
|
||||||
ref="tree"
|
ref="tree"
|
||||||
id="tree"
|
id="tree"
|
||||||
:style="{left: x, top: y, transform: `scale(${scale}) translate(-50%, -50%) `, 'transform-origin': `${0} ${0}`}">
|
:style="{left: x, top: y, transform: `scale(${scale}) translate(-50%, -50%) `, 'transform-origin': `${0} ${0}`}">
|
||||||
<VueOkrTree
|
<VueOkrTree
|
||||||
:props="props"
|
:props="props"
|
||||||
node-key="id"
|
node-key="id"
|
||||||
show-collapsable
|
show-collapsable
|
||||||
show-node-num
|
show-node-num
|
||||||
current-lable-class-name="aigrid-active"
|
current-lable-class-name="aigrid-active"
|
||||||
:default-expanded-keys="defaultExpandedKeys"
|
:default-expanded-keys="defaultExpandedKeys"
|
||||||
ref="VueOkrTree"
|
ref="VueOkrTree"
|
||||||
@node-click="onNodeClick"
|
@node-click="onNodeClick"
|
||||||
:data="treeData">
|
:data="treeData">
|
||||||
</VueOkrTree>
|
</VueOkrTree>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import OkrTree from './vue-okr-tree/OkrTree'
|
import AiOkrTree from "dvcp-dv-ui/components/AiOkrTree/AiOkrTree"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AiGrid',
|
name: 'AiGrid',
|
||||||
|
|
||||||
props: ['instance'],
|
props: ['instance'],
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
VueOkrTree: OkrTree
|
VueOkrTree: AiOkrTree
|
||||||
},
|
},
|
||||||
|
|
||||||
data () {
|
data() {
|
||||||
return {
|
return {
|
||||||
scale: 1,
|
scale: 1,
|
||||||
x: '50%',
|
x: '50%',
|
||||||
y: '50%',
|
y: '50%',
|
||||||
defaultExpandedKeys: [],
|
defaultExpandedKeys: [],
|
||||||
treeData: [],
|
treeData: [],
|
||||||
props: {
|
props: {
|
||||||
label: 'girdName',
|
label: 'girdName',
|
||||||
children: 'children'
|
children: 'children'
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted () {
|
|
||||||
this.bindEvent()
|
|
||||||
this.getPartyOrg()
|
|
||||||
},
|
|
||||||
|
|
||||||
destroyed () {
|
|
||||||
document.querySelector('body').removeEventListener('mousewheel', this.onMousewheel)
|
|
||||||
document.querySelector('body').removeEventListener('mouseup', this.onMouseUp)
|
|
||||||
document.querySelector('body').removeEventListener('mousedown', this.onMousedown)
|
|
||||||
document.querySelector('body').removeEventListener('mousemove', this.onMouseMove)
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
bindEvent () {
|
|
||||||
document.querySelector('body').addEventListener('mousewheel', this.onMousewheel, true)
|
|
||||||
document.querySelector('body').addEventListener('mouseup', this.onMouseUp, true)
|
|
||||||
document.querySelector('body').addEventListener('mousedown', this.onMousedown, true)
|
|
||||||
document.querySelector('body').addEventListener('mousemove', this.onMouseMove, true)
|
|
||||||
},
|
|
||||||
|
|
||||||
onMousewheel (event) {
|
|
||||||
if (!event) return false
|
|
||||||
const elClass = event.target.className
|
|
||||||
if (elClass === 'tree' || elClass === 'middle' || (elClass && (elClass.indexOf('chart') > -1 || elClass.indexOf('user') > -1))) {
|
|
||||||
var dir = event.deltaY > 0 ? 'Up' : 'Down'
|
|
||||||
if (dir === 'Up') {
|
|
||||||
this.scale = this.scale - 0.12 <= 0.1 ? 0.1 : this.scale - 0.12
|
|
||||||
} else {
|
|
||||||
this.scale = this.scale + 0.12
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
},
|
|
||||||
|
|
||||||
onMousedown (e) {
|
|
||||||
const elClass = e.target.className
|
|
||||||
if ((elClass && (elClass.indexOf('chart') > -1 || elClass.indexOf('user') > -1))) {
|
|
||||||
const left = document.querySelector('#tree').offsetLeft
|
|
||||||
const top = document.querySelector('#tree').offsetTop
|
|
||||||
this.isMove = true
|
|
||||||
this.offsetX = e.clientX - left
|
|
||||||
this.offsetY = e.clientY - top
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onMouseMove (e) {
|
|
||||||
if (!this.isMove) return
|
|
||||||
|
|
||||||
this.x = (e.clientX - this.offsetX) + 'px'
|
|
||||||
this.y = (e.clientY - this.offsetY) + 'px'
|
|
||||||
},
|
|
||||||
|
|
||||||
onMouseUp () {
|
|
||||||
this.isMove = false
|
|
||||||
},
|
|
||||||
|
|
||||||
onNodeClick (e) {
|
|
||||||
this.$emit('nodeClick', e)
|
|
||||||
},
|
|
||||||
|
|
||||||
getPartyOrg () {
|
|
||||||
this.instance.post('/app/appgirdinfo/listAll3').then(res => {
|
|
||||||
if (res.code === 0) {
|
|
||||||
this.treeData = res.data.filter(e => !e.parentGirdId)
|
|
||||||
const parentGirdId = this.treeData[0].id
|
|
||||||
|
|
||||||
this.treeData.map(p => this.addChild(p, res.data.map(v => {
|
|
||||||
if (v.id === parentGirdId) {
|
|
||||||
this.defaultExpandedKeys.push(v.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...v,
|
|
||||||
girdName: v.girdName.substr(0, 11)
|
|
||||||
}
|
|
||||||
}), {
|
|
||||||
parent: 'parentGirdId'
|
|
||||||
}))
|
|
||||||
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.autoScale()
|
|
||||||
this.$refs.VueOkrTree.setCurrentKey(parentGirdId)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
autoScale () {
|
|
||||||
const treeWidth = this.$refs.tree.offsetWidth
|
|
||||||
const containerWidth = this.$refs.container.offsetWidth - 100
|
|
||||||
this.scale = treeWidth < containerWidth ? 1 : containerWidth / treeWidth
|
|
||||||
this.x = '50%'
|
|
||||||
this.y = '50%'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.bindEvent()
|
||||||
|
this.getPartyOrg()
|
||||||
|
},
|
||||||
|
|
||||||
|
destroyed() {
|
||||||
|
document.querySelector('body').removeEventListener('mousewheel', this.onMousewheel)
|
||||||
|
document.querySelector('body').removeEventListener('mouseup', this.onMouseUp)
|
||||||
|
document.querySelector('body').removeEventListener('mousedown', this.onMousedown)
|
||||||
|
document.querySelector('body').removeEventListener('mousemove', this.onMouseMove)
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
bindEvent() {
|
||||||
|
document.querySelector('body').addEventListener('mousewheel', this.onMousewheel, true)
|
||||||
|
document.querySelector('body').addEventListener('mouseup', this.onMouseUp, true)
|
||||||
|
document.querySelector('body').addEventListener('mousedown', this.onMousedown, true)
|
||||||
|
document.querySelector('body').addEventListener('mousemove', this.onMouseMove, true)
|
||||||
|
},
|
||||||
|
|
||||||
|
onMousewheel(event) {
|
||||||
|
if (!event) return false
|
||||||
|
const elClass = event.target.className
|
||||||
|
if (elClass === 'tree' || elClass === 'middle' || (elClass && (elClass.indexOf('chart') > -1 || elClass.indexOf('user') > -1))) {
|
||||||
|
var dir = event.deltaY > 0 ? 'Up' : 'Down'
|
||||||
|
if (dir === 'Up') {
|
||||||
|
this.scale = this.scale - 0.12 <= 0.1 ? 0.1 : this.scale - 0.12
|
||||||
|
} else {
|
||||||
|
this.scale = this.scale + 0.12
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
|
||||||
|
onMousedown(e) {
|
||||||
|
const elClass = e.target.className
|
||||||
|
if ((elClass && (elClass.indexOf('chart') > -1 || elClass.indexOf('user') > -1))) {
|
||||||
|
const left = document.querySelector('#tree').offsetLeft
|
||||||
|
const top = document.querySelector('#tree').offsetTop
|
||||||
|
this.isMove = true
|
||||||
|
this.offsetX = e.clientX - left
|
||||||
|
this.offsetY = e.clientY - top
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onMouseMove(e) {
|
||||||
|
if (!this.isMove) return
|
||||||
|
|
||||||
|
this.x = (e.clientX - this.offsetX) + 'px'
|
||||||
|
this.y = (e.clientY - this.offsetY) + 'px'
|
||||||
|
},
|
||||||
|
|
||||||
|
onMouseUp() {
|
||||||
|
this.isMove = false
|
||||||
|
},
|
||||||
|
|
||||||
|
onNodeClick(e) {
|
||||||
|
this.$emit('nodeClick', e)
|
||||||
|
},
|
||||||
|
|
||||||
|
getPartyOrg() {
|
||||||
|
this.instance.post('/app/appgirdinfo/listAll3').then(res => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.treeData = res.data.filter(e => !e.parentGirdId)
|
||||||
|
const parentGirdId = this.treeData[0].id
|
||||||
|
|
||||||
|
this.treeData.map(p => this.addChild(p, res.data.map(v => {
|
||||||
|
if (v.id === parentGirdId) {
|
||||||
|
this.defaultExpandedKeys.push(v.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...v,
|
||||||
|
girdName: v.girdName.substr(0, 11)
|
||||||
|
}
|
||||||
|
}), {
|
||||||
|
parent: 'parentGirdId'
|
||||||
|
}))
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.autoScale()
|
||||||
|
this.$refs.VueOkrTree.setCurrentKey(parentGirdId)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
autoScale() {
|
||||||
|
const treeWidth = this.$refs.tree.offsetWidth
|
||||||
|
const containerWidth = this.$refs.container.offsetWidth - 100
|
||||||
|
this.scale = treeWidth < containerWidth ? 1 : containerWidth / treeWidth
|
||||||
|
this.x = '50%'
|
||||||
|
this.y = '50%'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.AiGrid {
|
.AiGrid {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.AiGrid-wrapper {
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
align-items: center;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
padding: 20px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-sizing: border-box;
|
width: max-content;
|
||||||
|
height: 300%;
|
||||||
|
}
|
||||||
|
|
||||||
.AiGrid-wrapper {
|
.aigrid-active {
|
||||||
|
background: linear-gradient(180deg, #42C6CE 0%, #307598 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .org-chart-container {
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-size: 16px;
|
||||||
|
|
||||||
|
.org-chart-node-children {
|
||||||
display: flex;
|
display: flex;
|
||||||
position: absolute;
|
justify-content: center;
|
||||||
align-items: center;
|
float: initial !important;
|
||||||
left: 50%;
|
|
||||||
top: 50%;
|
|
||||||
padding: 20px;
|
|
||||||
overflow: hidden;
|
|
||||||
width: max-content;
|
|
||||||
height: 300%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.aigrid-active {
|
.org-chart-node-btn {
|
||||||
background: linear-gradient(180deg, #42C6CE 0%, #307598 100%);
|
border: 1px solid #23A0AC !important;
|
||||||
}
|
|
||||||
|
|
||||||
::v-deep .org-chart-container {
|
|
||||||
color: #FFFFFF;
|
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
background: #071030;
|
||||||
|
color: #FF9A02;
|
||||||
|
|
||||||
.org-chart-node-children {
|
&:after, &::before {
|
||||||
display: flex;
|
display: none;
|
||||||
justify-content: center;
|
|
||||||
float: initial!important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.org-chart-node-btn {
|
&.expanded::before {
|
||||||
border: 1px solid #23A0AC!important;
|
display: block;
|
||||||
font-size: 16px;
|
position: absolute;
|
||||||
font-weight: bold;
|
top: 50%;
|
||||||
background: #071030;
|
left: 4px;
|
||||||
|
right: 4px;
|
||||||
|
height: 0;
|
||||||
|
border-top: 1px solid #FF9A02;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
.org-chart-node-btn-text {
|
||||||
|
background: transparent;
|
||||||
color: #FF9A02;
|
color: #FF9A02;
|
||||||
|
|
||||||
&:after, &::before {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.expanded::before {
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 4px;
|
|
||||||
right: 4px;
|
|
||||||
height: 0;
|
|
||||||
border-top: 1px solid #FF9A02;
|
|
||||||
content: "";
|
|
||||||
}
|
|
||||||
|
|
||||||
.org-chart-node-btn-text {
|
|
||||||
background: transparent;
|
|
||||||
color: #FF9A02;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.org-chart-node {
|
.org-chart-node {
|
||||||
// overflow: hidden;
|
// overflow: hidden;
|
||||||
|
|
||||||
.org-chart-node-label {
|
.org-chart-node-label {
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 254px;
|
height: 254px;
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
padding: 0 0;
|
padding: 0 0;
|
||||||
|
|
||||||
|
.org-chart-node-label-inner {
|
||||||
|
width: 40px !important;
|
||||||
|
height: 254px !important;
|
||||||
|
border: 1px solid;
|
||||||
|
background: linear-gradient(180deg, rgba(69, 210, 218, 0.2500) 0%, rgba(69, 210, 218, 0.1000) 100%) !important;
|
||||||
|
border-image: linear-gradient(180deg, rgba(5, 185, 203, 1), rgba(73, 214, 207, 1)) 1 1 !important;
|
||||||
|
line-height: 1.3;
|
||||||
|
padding: 10px 8px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 18px;
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
|
||||||
|
&.aigrid-active {
|
||||||
|
background: linear-gradient(180deg, #42C6CE 0%, #307598 100%) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-root-label {
|
||||||
|
width: auto !important;
|
||||||
|
min-width: 240px;
|
||||||
|
height: 40px !important;
|
||||||
|
line-height: 40px !important;
|
||||||
|
min-height: 40px !important;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
.org-chart-node-label-inner {
|
.org-chart-node-label-inner {
|
||||||
width: 40px!important;
|
padding: 0 30px !important;
|
||||||
height: 254px!important;
|
color: #fff !important;
|
||||||
border: 1px solid;
|
width: auto !important;
|
||||||
background: linear-gradient(180deg, rgba(69,210,218,0.2500) 0%, rgba(69,210,218,0.1000) 100%)!important;
|
min-width: 240px;
|
||||||
border-image: linear-gradient(180deg, rgba(5, 185, 203, 1), rgba(73, 214, 207, 1)) 1 1!important;
|
height: 40px !important;
|
||||||
line-height: 1.3;
|
line-height: 40px !important;
|
||||||
padding: 10px 8px;
|
min-height: 40px !important;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 18px;
|
background: linear-gradient(180deg, rgba(69, 210, 218, 0.2500) 0%, rgba(69, 210, 218, 0.1000) 100%) !important;
|
||||||
color: rgba(255, 255, 255, 0.8);
|
border-image: linear-gradient(180deg, rgba(5, 185, 203, 1), rgba(73, 214, 207, 1)) 1 1 !important;
|
||||||
|
|
||||||
&.aigrid-active {
|
&.aigrid-active {
|
||||||
background: linear-gradient(180deg, #42C6CE 0%, #307598 100%)!important;
|
background: linear-gradient(180deg, #42C6CE 0%, #307598 100%) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-root-label {
|
|
||||||
width: auto!important;
|
|
||||||
min-width: 240px;
|
|
||||||
height: 40px!important;
|
|
||||||
line-height: 40px!important;
|
|
||||||
min-height: 40px!important;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
.org-chart-node-label-inner {
|
|
||||||
padding: 0 30px!important;
|
|
||||||
color: #fff!important;
|
|
||||||
width: auto!important;
|
|
||||||
min-width: 240px;
|
|
||||||
height: 40px!important;
|
|
||||||
line-height: 40px!important;
|
|
||||||
min-height: 40px!important;
|
|
||||||
text-align: center;
|
|
||||||
background: linear-gradient(180deg, rgba(69,210,218,0.2500) 0%, rgba(69,210,218,0.1000) 100%)!important;
|
|
||||||
border-image: linear-gradient(180deg, rgba(5, 185, 203, 1), rgba(73, 214, 207, 1)) 1 1!important;
|
|
||||||
|
|
||||||
&.aigrid-active {
|
|
||||||
background: linear-gradient(180deg, #42C6CE 0%, #307598 100%)!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
.org-chart-node-label {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.org-chart-node-children:before, .org-chart-node:after, .org-chart-node:last-child:before,
|
&:last-child {
|
||||||
.org-chart-node.is-leaf:before {
|
.org-chart-node-label {
|
||||||
border-radius: 0;
|
margin-right: 0;
|
||||||
border-color: #23A0AC!important;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.vertical .org-chart-node:after, .vertical .org-chart-node:before {
|
|
||||||
border-radius: 0;
|
|
||||||
border-color: #23A0AC!important;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.org-chart-node-children:before, .org-chart-node:after, .org-chart-node:last-child:before,
|
||||||
|
.org-chart-node.is-leaf:before {
|
||||||
|
border-radius: 0;
|
||||||
|
border-color: #23A0AC !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vertical .org-chart-node:after, .vertical .org-chart-node:before {
|
||||||
|
border-radius: 0;
|
||||||
|
border-color: #23A0AC !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,682 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="org-chart-container">
|
|
||||||
<div
|
|
||||||
ref="orgChartRoot"
|
|
||||||
class="org-chart-node-children"
|
|
||||||
:class="{
|
|
||||||
vertical: direction === 'vertical',
|
|
||||||
horizontal: direction === 'horizontal',
|
|
||||||
'show-collapsable': showCollapsable,
|
|
||||||
'one-branch': data.length === 1
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<OkrTreeNode
|
|
||||||
v-for="child in root.childNodes"
|
|
||||||
:node="child"
|
|
||||||
:root="root"
|
|
||||||
orkstyle
|
|
||||||
:show-collapsable="showCollapsable"
|
|
||||||
:label-width="labelWidth"
|
|
||||||
:label-height="labelHeight"
|
|
||||||
:renderContent="renderContent"
|
|
||||||
:nodeBtnContent="nodeBtnContent"
|
|
||||||
:selected-key="selectedKey"
|
|
||||||
:default-expand-all="defaultExpandAll"
|
|
||||||
:node-key="nodeKey"
|
|
||||||
:show-node-num="showNodeNum"
|
|
||||||
:key="getNodeKey(child)"
|
|
||||||
:props="props"
|
|
||||||
></OkrTreeNode>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import Vue from "vue";
|
|
||||||
import OkrTreeNode from "./OkrTreeNode.vue";
|
|
||||||
import TreeStore from "./model/tree-store.js";
|
|
||||||
import { getNodeKey } from "./model/util";
|
|
||||||
export default {
|
|
||||||
name: "OkrTree",
|
|
||||||
components: {
|
|
||||||
OkrTreeNode
|
|
||||||
},
|
|
||||||
provide() {
|
|
||||||
return {
|
|
||||||
okrEventBus: this.okrEventBus
|
|
||||||
};
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
data: {
|
|
||||||
// 源数据
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
leftData: {
|
|
||||||
// 源数据
|
|
||||||
type: Array
|
|
||||||
},
|
|
||||||
// 方向
|
|
||||||
direction: {
|
|
||||||
type: String,
|
|
||||||
default: "vertical"
|
|
||||||
},
|
|
||||||
// 子节点是否可折叠
|
|
||||||
showCollapsable: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
// 飞书 OKR 模式
|
|
||||||
onlyBothTree: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
orkstyle: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
// 树节点的内容区的渲染 Function
|
|
||||||
renderContent: Function,
|
|
||||||
// 展开节点的内容渲染 Function
|
|
||||||
nodeBtnContent: Function,
|
|
||||||
// 显示节点数
|
|
||||||
showNodeNum: Boolean,
|
|
||||||
// 树节点区域的宽度
|
|
||||||
labelWidth: [String, Number],
|
|
||||||
// 树节点区域的高度
|
|
||||||
labelHeight: [String, Number],
|
|
||||||
// 树节点的样式
|
|
||||||
labelClassName: [Function, String],
|
|
||||||
// 当前选中节点样式
|
|
||||||
currentLableClassName: [Function, String],
|
|
||||||
// 用来控制选择节点的字段名
|
|
||||||
selectedKey: String,
|
|
||||||
// 是否默认展开所有节点
|
|
||||||
defaultExpandAll: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
// 当前选中的节点
|
|
||||||
currentNodeKey: [String, Number],
|
|
||||||
// 每个树节点用来作为唯一标识的属性,整棵树应该是唯一的
|
|
||||||
nodeKey: String,
|
|
||||||
defaultExpandedKeys: {
|
|
||||||
type: Array
|
|
||||||
},
|
|
||||||
filterNodeMethod: Function,
|
|
||||||
props: {
|
|
||||||
default() {
|
|
||||||
return {
|
|
||||||
leftChildren: "leftChildren",
|
|
||||||
children: "children",
|
|
||||||
label: "label",
|
|
||||||
disabled: "disabled"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 动画
|
|
||||||
animate: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
animateName: {
|
|
||||||
type: String,
|
|
||||||
default: "okr-zoom-in-center"
|
|
||||||
},
|
|
||||||
animateDuration: {
|
|
||||||
type: Number,
|
|
||||||
default: 200
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
ondeClass() {
|
|
||||||
return {
|
|
||||||
findNode: null
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
okrEventBus: new Vue(),
|
|
||||||
store: null,
|
|
||||||
root: null
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.isTree = true;
|
|
||||||
this.store = new TreeStore({
|
|
||||||
key: this.nodeKey,
|
|
||||||
data: Object.freeze(this.data),
|
|
||||||
leftData: this.leftData,
|
|
||||||
props: this.props,
|
|
||||||
defaultExpandedKeys: this.defaultExpandedKeys,
|
|
||||||
showCollapsable: this.showCollapsable,
|
|
||||||
currentNodeKey: this.currentNodeKey,
|
|
||||||
defaultExpandAll: this.defaultExpandAll,
|
|
||||||
filterNodeMethod: this.filterNodeMethod,
|
|
||||||
labelClassName: this.labelClassName,
|
|
||||||
currentLableClassName: this.currentLableClassName,
|
|
||||||
onlyBothTree: this.onlyBothTree,
|
|
||||||
direction: this.direction,
|
|
||||||
animate: this.animate,
|
|
||||||
animateName: this.animateName
|
|
||||||
});
|
|
||||||
this.root = this.store.root;
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
data(newVal) {
|
|
||||||
this.store.setData(newVal);
|
|
||||||
},
|
|
||||||
defaultExpandedKeys(newVal) {
|
|
||||||
this.store.defaultExpandedKeys = newVal;
|
|
||||||
this.store.setDefaultExpandedKeys(newVal);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
filter(value) {
|
|
||||||
if (!this.filterNodeMethod)
|
|
||||||
throw new Error("[Tree] filterNodeMethod is required when filter");
|
|
||||||
this.store.filter(value);
|
|
||||||
if (this.onlyBothTree) {
|
|
||||||
this.store.filter(value, "leftChildNodes");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getNodeKey(node) {
|
|
||||||
return getNodeKey(this.nodeKey, node.data);
|
|
||||||
},
|
|
||||||
// 通过 node 设置某个节点的当前选中状态
|
|
||||||
setCurrentNode(node) {
|
|
||||||
if (!this.nodeKey)
|
|
||||||
throw new Error("[Tree] nodeKey is required in setCurrentNode");
|
|
||||||
this.store.setUserCurrentNode(node);
|
|
||||||
},
|
|
||||||
// 根据 data 或者 key 拿到 Tree 组件中的 node
|
|
||||||
getNode(data) {
|
|
||||||
return this.store.getNode(data);
|
|
||||||
},
|
|
||||||
// 通过 key 设置某个节点的当前选中状态
|
|
||||||
setCurrentKey(key) {
|
|
||||||
if (!this.nodeKey)
|
|
||||||
throw new Error("[Tree] nodeKey is required in setCurrentKey");
|
|
||||||
this.store.setCurrentNodeKey(key);
|
|
||||||
},
|
|
||||||
remove(data) {
|
|
||||||
this.store.remove(data);
|
|
||||||
},
|
|
||||||
// 获取当前被选中节点的 data
|
|
||||||
getCurrentNode() {
|
|
||||||
const currentNode = this.store.getCurrentNode();
|
|
||||||
return currentNode ? currentNode.data : null;
|
|
||||||
},
|
|
||||||
getCurrentKey() {
|
|
||||||
if (!this.nodeKey)
|
|
||||||
throw new Error("[Tree] nodeKey is required in getCurrentKey");
|
|
||||||
const currentNode = this.getCurrentNode();
|
|
||||||
return currentNode ? currentNode[this.nodeKey] : null;
|
|
||||||
},
|
|
||||||
append(data, parentNode) {
|
|
||||||
this.store.append(data, parentNode);
|
|
||||||
},
|
|
||||||
insertBefore(data, refNode) {
|
|
||||||
this.store.insertBefore(data, refNode);
|
|
||||||
},
|
|
||||||
insertAfter(data, refNode) {
|
|
||||||
this.store.insertAfter(data, refNode);
|
|
||||||
},
|
|
||||||
updateKeyChildren(key, data) {
|
|
||||||
if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in updateKeyChild');
|
|
||||||
this.store.updateChildren(key, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
@import "./model/transition.css";
|
|
||||||
* {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
.org-chart-container {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vertical .org-chart-node-children {
|
|
||||||
position: relative;
|
|
||||||
padding-top: 20px;
|
|
||||||
transition: all 0.5s;
|
|
||||||
}
|
|
||||||
.vertical .org-chart-node {
|
|
||||||
float: left;
|
|
||||||
text-align: center;
|
|
||||||
list-style-type: none;
|
|
||||||
position: relative;
|
|
||||||
padding: 20px 5px 0 5px;
|
|
||||||
transition: all 0.5s;
|
|
||||||
}
|
|
||||||
/*使用 ::before 和 ::after 绘制连接器*/
|
|
||||||
.vertical .org-chart-node::before,
|
|
||||||
.vertical .org-chart-node::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 50%;
|
|
||||||
width: 50%;
|
|
||||||
border-top: 1px solid #ccc;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
.vertical .org-chart-node::after {
|
|
||||||
right: auto;
|
|
||||||
left: 50%;
|
|
||||||
border-left: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
/*我们需要从没有任何兄弟元素的元素中删除左右连接器*/
|
|
||||||
.vertical.one-branch > .org-chart-node::after,
|
|
||||||
.vertical.one-branch > .org-chart-node::before {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
/*从单个子节点的顶部移除空格*/
|
|
||||||
.vertical.one-branch > .org-chart-node {
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
/*从第一个子节点移除左连接器,从最后一个子节点移除右连接器*/
|
|
||||||
.vertical .org-chart-node:first-child::before,
|
|
||||||
.vertical .org-chart-node:last-child::after {
|
|
||||||
border: 0 none;
|
|
||||||
}
|
|
||||||
/*将垂直连接器添加回最后的节点*/
|
|
||||||
.vertical .org-chart-node:last-child::before {
|
|
||||||
border-right: 1px solid #ccc;
|
|
||||||
border-radius: 0 5px 0 0;
|
|
||||||
}
|
|
||||||
.vertical .org-chart-node:only-child:before {
|
|
||||||
border-radius: 0 0px 0 0;
|
|
||||||
margin-right: -1px;
|
|
||||||
}
|
|
||||||
.vertical .org-chart-node:first-child::after {
|
|
||||||
border-radius: 5px 0 0 0;
|
|
||||||
}
|
|
||||||
.vertical .org-chart-node.is-leaf {
|
|
||||||
padding-top: 20px;
|
|
||||||
padding-bottom: 20px;
|
|
||||||
}
|
|
||||||
.vertical .org-chart-node.is-leaf::before {
|
|
||||||
content: "";
|
|
||||||
display: block;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
.vertical .org-chart-node.is-leaf .org-chart-node-label::after {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*从父节点添加向下的连接器了*/
|
|
||||||
.vertical .org-chart-node-children::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 50%;
|
|
||||||
border-left: 1px solid #ccc;
|
|
||||||
width: 0;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
.vertical .org-chart-node-label {
|
|
||||||
position: relative;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
.vertical .org-chart-node-label .org-chart-node-label-inner {
|
|
||||||
box-shadow: 0 1px 10px rgba(31, 35, 41, 0.08);
|
|
||||||
display: inline-block;
|
|
||||||
padding: 10px;
|
|
||||||
margin: 0px;
|
|
||||||
font-size: 16px;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
.vertical .org-chart-node-label .org-chart-node-label-inner:hover {
|
|
||||||
box-shadow: 0 1px 14px rgba(31, 35, 41, 0.12);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.vertical .org-chart-node-label .org-chart-node-btn {
|
|
||||||
position: absolute;
|
|
||||||
top: 100%;
|
|
||||||
left: 50%;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
z-index: 10;
|
|
||||||
margin-left: -11px;
|
|
||||||
margin-top: 9px;
|
|
||||||
background-color: #fff;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 50%;
|
|
||||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.15);
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.35s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vertical .org-chart-node-label .org-chart-node-btn:hover {
|
|
||||||
transform: scale(1.15);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.vertical .org-chart-node-label .org-chart-node-btn::before,
|
|
||||||
.vertical .org-chart-node-label .org-chart-node-btn::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
.vertical .org-chart-node-label .org-chart-node-btn::before {
|
|
||||||
top: 50%;
|
|
||||||
left: 4px;
|
|
||||||
right: 4px;
|
|
||||||
height: 0;
|
|
||||||
border-top: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
.vertical .org-chart-node-label .org-chart-node-btn::after {
|
|
||||||
top: 4px;
|
|
||||||
left: 50%;
|
|
||||||
bottom: 4px;
|
|
||||||
width: 0;
|
|
||||||
border-left: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
.vertical .org-chart-node-label .expanded.org-chart-node-btn::after {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vertical .org-chart-node.collapsed .org-chart-node-label {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.vertical .org-chart-node.collapsed .org-chart-node-label::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
top: 100%;
|
|
||||||
left: 0;
|
|
||||||
width: 50%;
|
|
||||||
height: 20px;
|
|
||||||
border-right: 1px solid #ddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizontal .org-chart-node-children,
|
|
||||||
.horizontal .org-chart-node-left-children {
|
|
||||||
position: relative;
|
|
||||||
padding-left: 20px;
|
|
||||||
transition: all 0.5s;
|
|
||||||
}
|
|
||||||
.horizontal .org-chart-node-left-children {
|
|
||||||
padding-right: 20px;
|
|
||||||
}
|
|
||||||
.horizontal .org-chart-node:not(.is-left-child-node) {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
position: relative;
|
|
||||||
padding: 0px 5px 0 20px;
|
|
||||||
transition: all 0.5s;
|
|
||||||
}
|
|
||||||
.horizontal .is-left-child-node {
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
justify-content: flex-end;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.horizontal .is-left-child-node {
|
|
||||||
padding: 0px 20px 0 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*使用 ::before 和 ::after 绘制连接器*/
|
|
||||||
.horizontal .org-chart-node:not(.is-left-child-node):before,
|
|
||||||
.horizontal .org-chart-node:not(.is-left-child-node)::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
border-left: 1px solid #ccc;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 20px;
|
|
||||||
height: 50%;
|
|
||||||
}
|
|
||||||
.horizontal .is-left-child-node:before,
|
|
||||||
.horizontal .is-left-child-node::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
border-right: 1px solid #ccc;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
width: 20px;
|
|
||||||
height: 50%;
|
|
||||||
}
|
|
||||||
.horizontal .org-chart-node:not(.is-left-child-node):after {
|
|
||||||
top: 50%;
|
|
||||||
border-top: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
.horizontal .is-left-child-node:after {
|
|
||||||
top: 50%;
|
|
||||||
border-top: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*我们需要从没有任何兄弟元素的元素中删除左右连接器*/
|
|
||||||
.horizontal.one-branch > .org-chart-node::after,
|
|
||||||
.horizontal.one-branch > .org-chart-node::before {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
/*从单个子节点的顶部移除空格*/
|
|
||||||
.horizontal.one-branch > .org-chart-node {
|
|
||||||
padding-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*从第一个子节点移除左连接器,从最后一个子节点移除右连接器*/
|
|
||||||
.horizontal .org-chart-node:first-child::before,
|
|
||||||
.horizontal .org-chart-node:last-child::after {
|
|
||||||
border: 0 none;
|
|
||||||
}
|
|
||||||
/*将垂直连接器添加回最后的节点*/
|
|
||||||
.horizontal .org-chart-node:not(.is-left-child-node):not(.is-not-child):last-child::before {
|
|
||||||
border-bottom: 1px solid #ccc;
|
|
||||||
border-radius: 0 0px 0 5px;
|
|
||||||
}
|
|
||||||
.horizontal .is-left-child-node:last-child::before {
|
|
||||||
border-bottom: 1px solid #ccc;
|
|
||||||
border-radius: 0 0px 5px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizontal .org-chart-node:only-child::before {
|
|
||||||
border-radius: 0 0px 0 0px !important;
|
|
||||||
border-color: #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizontal .org-chart-node:not(.is-left-child-node):first-child::after {
|
|
||||||
border-radius: 5px 0px 0 0;
|
|
||||||
}
|
|
||||||
.horizontal .is-left-child-node:first-child::after {
|
|
||||||
border-radius: 0 5px 0px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizontal .org-chart-node.is-leaf {
|
|
||||||
position: relative;
|
|
||||||
padding-left: 20px;
|
|
||||||
padding-right: 20px;
|
|
||||||
}
|
|
||||||
.horizontal .org-chart-node.is-leaf::before {
|
|
||||||
content: "";
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.horizontal .org-chart-node.is-leaf .org-chart-node-label::after,
|
|
||||||
.horizontal .is-left-child-node.is-leaf .org-chart-node-label::before {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizontal .is-left-child-node:last-child::after {
|
|
||||||
/* border-bottom: 1px solid green; */
|
|
||||||
border-radius: 0 0px 5px 0px;
|
|
||||||
}
|
|
||||||
.horizontal .is-left-child-node:only-child::after {
|
|
||||||
border-radius: 0 0px 0 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizontal .is-left-child-node.is-leaf {
|
|
||||||
position: relative;
|
|
||||||
padding-left: 20px;
|
|
||||||
padding-right: 20px;
|
|
||||||
}
|
|
||||||
.horizontal .is-left-child-node.is-leaf::before {
|
|
||||||
content: "";
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.horizontal .is-left-child-node .org-chart-node-label::after {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*从父节点添加向下的连接器了*/
|
|
||||||
.horizontal .org-chart-node-children::before,
|
|
||||||
.horizontal .org-chart-node-left-children::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 50%;
|
|
||||||
border-top: 1px solid #ccc;
|
|
||||||
width: 12px;
|
|
||||||
height: 10px;
|
|
||||||
}
|
|
||||||
.horizontal .org-chart-node-children::before {
|
|
||||||
width: 20px;
|
|
||||||
}
|
|
||||||
.horizontal .org-chart-node-left-children::before {
|
|
||||||
left: calc(100% - 11px);
|
|
||||||
}
|
|
||||||
.horizontal > .only-both-tree-node > .org-chart-node-left-children::before {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizontal .org-chart-node-label {
|
|
||||||
position: relative;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizontal .org-chart-node-label .org-chart-node-label-inner {
|
|
||||||
box-shadow: 0 1px 10px rgba(31, 35, 41, 0.08);
|
|
||||||
display: inline-block;
|
|
||||||
padding: 10px;
|
|
||||||
margin: 10px 0;
|
|
||||||
font-size: 16px;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizontal .org-chart-node-label .org-chart-node-label-inner:hover {
|
|
||||||
box-shadow: 0 1px 14px rgba(31, 35, 41, 0.12);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.horizontal .org-chart-node-label .org-chart-node-btn {
|
|
||||||
position: absolute;
|
|
||||||
left: 100%;
|
|
||||||
top: 50%;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
z-index: 10;
|
|
||||||
margin-top: -11px;
|
|
||||||
margin-left: 9px;
|
|
||||||
background-color: #fff;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 50%;
|
|
||||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.15);
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.35s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizontal .org-chart-node-label .org-chart-node-btn:hover,
|
|
||||||
.horizontal .org-chart-node-label .org-chart-node-left-btn:hover {
|
|
||||||
transform: scale(1.15);
|
|
||||||
}
|
|
||||||
.horizontal .org-chart-node-label .org-chart-node-btn::before,
|
|
||||||
.horizontal .org-chart-node-label .org-chart-node-btn::after,
|
|
||||||
.horizontal .org-chart-node-label .org-chart-node-left-btn::before,
|
|
||||||
.horizontal .org-chart-node-label .org-chart-node-left-btn::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizontal .org-chart-node-label .org-chart-node-btn::before,
|
|
||||||
.horizontal .org-chart-node-label .org-chart-node-left-btn::before {
|
|
||||||
top: 50%;
|
|
||||||
left: 4px;
|
|
||||||
right: 3px;
|
|
||||||
border-top: 1px solid #ccc;
|
|
||||||
height: 0;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
}
|
|
||||||
.horizontal .org-chart-node-label .org-chart-node-btn::after,
|
|
||||||
.horizontal .org-chart-node-label .org-chart-node-left-btn::after {
|
|
||||||
top: 4px;
|
|
||||||
left: 50%;
|
|
||||||
bottom: 4px;
|
|
||||||
width: 0;
|
|
||||||
border-left: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
.horizontal .org-chart-node-label .expanded.org-chart-node-btn::after,
|
|
||||||
.horizontal .org-chart-node-label .expanded.org-chart-node-left-btn::after {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizontal .org-chart-node-label .org-chart-node-left-btn {
|
|
||||||
position: absolute;
|
|
||||||
right: 100%;
|
|
||||||
top: 50%;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
z-index: 10;
|
|
||||||
margin-top: -11px;
|
|
||||||
margin-right: 9px;
|
|
||||||
background-color: #fff;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 50%;
|
|
||||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.15);
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.35s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizontal .org-chart-node.collapsed .org-chart-node-label,
|
|
||||||
.horizontal .is-left-child-node.collapsed .org-chart-node-label {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.horizontal .org-chart-node.collapsed .org-chart-node-label::after,
|
|
||||||
.horizontal .is-left-child-node.collapsed .org-chart-node-label::before {
|
|
||||||
content: "";
|
|
||||||
border-bottom: 1px solid #ccc;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 100%;
|
|
||||||
height: 50%;
|
|
||||||
width: 10px;
|
|
||||||
}
|
|
||||||
.horizontal .org-chart-node .is-root-label.is-not-right-child::after,
|
|
||||||
.horizontal .org-chart-node .is-root-label.is-not-left-child::before {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
/* .horizontal .org-chart-node.collapsed .is-root-label.is-right-child::after,
|
|
||||||
.horizontal .org-chart-node.collapsed .is-root-label.is-left-child::before {
|
|
||||||
display: block;
|
|
||||||
} */
|
|
||||||
|
|
||||||
.horizontal .is-left-child-node.collapsed .org-chart-node-label::before {
|
|
||||||
left: -10px;
|
|
||||||
}
|
|
||||||
.horizontal .only-both-tree-node > .org-chart-node-label::before {
|
|
||||||
content: "";
|
|
||||||
border-bottom: 1px solid #ccc;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 100%;
|
|
||||||
height: 50%;
|
|
||||||
width: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.org-chart-node-children .org-chart-node-btn-text {
|
|
||||||
position: absolute;
|
|
||||||
top:0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background: #fff;
|
|
||||||
border-radius: 50%;
|
|
||||||
font-size: 12px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: #909090;
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,386 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div
|
|
||||||
class="org-chart-node"
|
|
||||||
@contextmenu="$event => this.handleContextMenu($event)"
|
|
||||||
v-if="node.visible"
|
|
||||||
:class="{
|
|
||||||
collapsed: !node.leftExpanded || !node.expanded,
|
|
||||||
'is-leaf': isLeaf,
|
|
||||||
'is-current': node.isCurrent,
|
|
||||||
'is-left-child-node': isLeftChildNode,
|
|
||||||
'is-not-child': node.level === 1 && node.childNodes.length <= 0 && leftChildNodes.length <= 0,
|
|
||||||
'only-both-tree-node': node.level === 1 && tree.store.onlyBothTree
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<transition :duration="animateDuration" :name="animateName">
|
|
||||||
<div
|
|
||||||
class="org-chart-node-left-children"
|
|
||||||
v-if="showLeftChildNode"
|
|
||||||
v-show="node.leftExpanded"
|
|
||||||
>
|
|
||||||
<OkrTreeNode
|
|
||||||
v-for="child in leftChildNodes"
|
|
||||||
:show-collapsable="showCollapsable"
|
|
||||||
:node="child"
|
|
||||||
:label-width="labelWidth"
|
|
||||||
:label-height="labelHeight"
|
|
||||||
:renderContent="renderContent"
|
|
||||||
:nodeBtnContent="nodeBtnContent"
|
|
||||||
:selected-key="selectedKey"
|
|
||||||
:node-key="nodeKey"
|
|
||||||
:key="getNodeKey(child)"
|
|
||||||
:props="props"
|
|
||||||
:show-node-num="showNodeNum"
|
|
||||||
is-left-child-node
|
|
||||||
></OkrTreeNode>
|
|
||||||
</div>
|
|
||||||
</transition>
|
|
||||||
<div class="org-chart-node-label"
|
|
||||||
:class="{
|
|
||||||
'is-root-label': node.level === 1,
|
|
||||||
'is-not-right-child': node.level === 1 && node.childNodes.length <= 0,
|
|
||||||
'is-not-left-child': node.level === 1 && leftChildNodes.length <= 0
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
v-if="showNodeLeftBtn && leftChildNodes.length > 0"
|
|
||||||
class="org-chart-node-left-btn"
|
|
||||||
:class="{ expanded: node.leftExpanded }"
|
|
||||||
@click="handleBtnClick('left')">
|
|
||||||
<template v-if="showNodeNum" >
|
|
||||||
<span v-if="!node.leftExpanded" class="org-chart-node-btn-text">
|
|
||||||
{{ (node.level === 1 && leftChildNodes.length > 0) ? leftChildNodes.length : node.childNodes.length }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<node-btn-content v-else :node="node">
|
|
||||||
<slot>
|
|
||||||
</slot>
|
|
||||||
</node-btn-content>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="org-chart-node-label-inner"
|
|
||||||
@click="handleNodeClick"
|
|
||||||
:class="computeLabelClass"
|
|
||||||
:style="computeLabelStyle"
|
|
||||||
>
|
|
||||||
<node-content :node="node">
|
|
||||||
<slot>
|
|
||||||
{{ node.label }}
|
|
||||||
</slot>
|
|
||||||
</node-content>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="showNodeBtn && !isLeftChildNode"
|
|
||||||
class="org-chart-node-btn"
|
|
||||||
:class="{ expanded: node.expanded }"
|
|
||||||
@click="handleBtnClick('right')">
|
|
||||||
<template v-if="showNodeNum">
|
|
||||||
<span v-if="!node.expanded " class="org-chart-node-btn-text">
|
|
||||||
{{ node.childNodes.length }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<node-btn-content v-else :node="node">
|
|
||||||
<slot>
|
|
||||||
<!-- <div class="org-chart-node-btn-text">10</div> -->
|
|
||||||
</slot>
|
|
||||||
</node-btn-content>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<transition :duration="animateDuration" :name="animateName">
|
|
||||||
<div
|
|
||||||
class="org-chart-node-children"
|
|
||||||
v-if="!isLeftChildNode && node.childNodes && node.childNodes.length > 0"
|
|
||||||
v-show="node.expanded"
|
|
||||||
>
|
|
||||||
<OkrTreeNode
|
|
||||||
v-for="child in node.childNodes"
|
|
||||||
:show-collapsable="showCollapsable"
|
|
||||||
:node="child"
|
|
||||||
:label-width="labelWidth"
|
|
||||||
:label-height="labelHeight"
|
|
||||||
:renderContent="renderContent"
|
|
||||||
:nodeBtnContent="nodeBtnContent"
|
|
||||||
:selected-key="selectedKey"
|
|
||||||
:node-key="nodeKey"
|
|
||||||
:key="getNodeKey(child)"
|
|
||||||
:show-node-num='showNodeNum'
|
|
||||||
:props="props"
|
|
||||||
></OkrTreeNode>
|
|
||||||
</div>
|
|
||||||
</transition>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import { getNodeKey } from "./model/util";
|
|
||||||
export default {
|
|
||||||
name: "OkrTreeNode",
|
|
||||||
inject: ["okrEventBus"],
|
|
||||||
props: {
|
|
||||||
props: {},
|
|
||||||
node: {
|
|
||||||
default() {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
root: {
|
|
||||||
default() {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 子节点是否可折叠
|
|
||||||
showCollapsable: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
// 判断是否是左子树的节点,样式需要改
|
|
||||||
isLeftChildNode: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
// 树节点的内容区的渲染 Function
|
|
||||||
renderContent: Function,
|
|
||||||
// 展开节点的内容渲染 Function
|
|
||||||
nodeBtnContent: Function,
|
|
||||||
// 显示节点数
|
|
||||||
showNodeNum: Boolean,
|
|
||||||
// 树节点区域的宽度
|
|
||||||
labelWidth: [String, Number],
|
|
||||||
// 树节点区域的高度
|
|
||||||
labelHeight: [String, Number],
|
|
||||||
// 用来控制选择节点的字段名
|
|
||||||
selectedKey: String,
|
|
||||||
// 每个树节点用来作为唯一标识的属性,整棵树应该是唯一的
|
|
||||||
nodeKey: String
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
NodeContent: {
|
|
||||||
props: {
|
|
||||||
node: {
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
render(h) {
|
|
||||||
const parent = this.$parent;
|
|
||||||
if (parent._props.renderContent) {
|
|
||||||
return parent._props.renderContent(h, this.node);
|
|
||||||
} else {
|
|
||||||
return this.$scopedSlots.default(this.node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 渲染展开节点的样式
|
|
||||||
NodeBtnContent: {
|
|
||||||
props: {
|
|
||||||
node: {
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
render(h) {
|
|
||||||
const parent = this.$parent;
|
|
||||||
if (parent._props.nodeBtnContent) {
|
|
||||||
return parent._props.nodeBtnContent(h, this.node);
|
|
||||||
} else {
|
|
||||||
if (this.$scopedSlots.default) {
|
|
||||||
return this.$scopedSlots.default(this.node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
isLeaf () {
|
|
||||||
if (this.node.level === 1) {
|
|
||||||
if (this.leftChildNodes.length == 0 && this.node.childNodes.length == 0) {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return this.node.isLeaf
|
|
||||||
}
|
|
||||||
},
|
|
||||||
leftChildNodes() {
|
|
||||||
if (this.tree.store.onlyBothTree) {
|
|
||||||
if (this.isLeftChildNode) {
|
|
||||||
return this.node.childNodes;
|
|
||||||
} else {
|
|
||||||
return this.node.leftChildNodes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
},
|
|
||||||
animateName() {
|
|
||||||
if (this.tree.store.animate) {
|
|
||||||
return this.tree.store.animateName;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
},
|
|
||||||
animateDuration() {
|
|
||||||
if (this.tree.store.animate) {
|
|
||||||
return this.tree.store.animateDuration;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
},
|
|
||||||
// 是否显示展开按钮
|
|
||||||
showNodeBtn() {
|
|
||||||
if (this.isLeftChildNode) {
|
|
||||||
return (
|
|
||||||
(this.tree.store.direction === "horizontal" &&
|
|
||||||
this.showCollapsable &&
|
|
||||||
this.leftChildNodes.length > 0) || this.level === 1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
this.showCollapsable &&
|
|
||||||
this.node.childNodes &&
|
|
||||||
this.node.childNodes.length > 0
|
|
||||||
)
|
|
||||||
},
|
|
||||||
showNodeLeftBtn() {
|
|
||||||
return (
|
|
||||||
(this.tree.store.direction === "horizontal" &&
|
|
||||||
this.showCollapsable &&
|
|
||||||
this.leftChildNodes.length > 0)
|
|
||||||
)
|
|
||||||
},
|
|
||||||
// 节点的宽度
|
|
||||||
computeLabelStyle() {
|
|
||||||
let { labelWidth = "auto", labelHeight = "auto" } = this;
|
|
||||||
if (typeof labelWidth === "number") {
|
|
||||||
labelWidth = `${labelWidth}px`;
|
|
||||||
}
|
|
||||||
if (typeof labelHeight === "number") {
|
|
||||||
labelHeight = `${labelHeight}px`;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
width: labelWidth,
|
|
||||||
height: labelHeight
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computeLabelClass() {
|
|
||||||
let clsArr = [];
|
|
||||||
const store = this.tree.store;
|
|
||||||
if (store.labelClassName) {
|
|
||||||
if (typeof store.labelClassName === "function") {
|
|
||||||
clsArr.push(store.labelClassName(this.node));
|
|
||||||
} else {
|
|
||||||
clsArr.push(store.labelClassName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (store.currentLableClassName && this.node.isCurrent) {
|
|
||||||
if (typeof store.currentLableClassName === "function") {
|
|
||||||
clsArr.push(store.currentLableClassName(this.node));
|
|
||||||
} else {
|
|
||||||
clsArr.push(store.currentLableClassName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.node.isCurrent) {
|
|
||||||
clsArr.push("is-current");
|
|
||||||
}
|
|
||||||
return clsArr;
|
|
||||||
},
|
|
||||||
computNodeStyle() {
|
|
||||||
return {
|
|
||||||
display: this.node.expanded ? "" : "none"
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computLeftNodeStyle() {
|
|
||||||
return {
|
|
||||||
display: this.node.leftExpanded ? "" : "none"
|
|
||||||
};
|
|
||||||
},
|
|
||||||
// 是否显示左子数
|
|
||||||
showLeftChildNode() {
|
|
||||||
return (
|
|
||||||
this.tree.onlyBothTree &&
|
|
||||||
this.tree.store.direction === "horizontal" &&
|
|
||||||
this.leftChildNodes &&
|
|
||||||
this.leftChildNodes.length > 0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
"node.expanded"(val) {
|
|
||||||
// this.$nextTick(() => this.expanded = val);
|
|
||||||
},
|
|
||||||
"node.leftExpanded"(val) {
|
|
||||||
// this.$nextTick(() => this.expanded = val);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
// node 的展开状态
|
|
||||||
expanded: false,
|
|
||||||
tree: null
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
const parent = this.$parent;
|
|
||||||
if (parent.isTree) {
|
|
||||||
this.tree = parent;
|
|
||||||
} else {
|
|
||||||
this.tree = parent.tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
const tree = this.tree;
|
|
||||||
if (!tree) {
|
|
||||||
console.warn("Can not find node's tree.");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getNodeKey(node) {
|
|
||||||
return getNodeKey(this.nodeKey, node.data);
|
|
||||||
},
|
|
||||||
handleNodeClick() {
|
|
||||||
const store = this.tree.store;
|
|
||||||
store.setCurrentNode(this.node);
|
|
||||||
this.tree.$emit("node-click", this.node.data, this.node, this);
|
|
||||||
},
|
|
||||||
handleBtnClick(isLeft) {
|
|
||||||
isLeft = isLeft === "left";
|
|
||||||
const store = this.tree.store;
|
|
||||||
// 表示是OKR飞书模式
|
|
||||||
if (store.onlyBothTree) {
|
|
||||||
if (isLeft) {
|
|
||||||
if (this.node.leftExpanded) {
|
|
||||||
this.node.leftExpanded = false;
|
|
||||||
this.tree.$emit("node-collapse", this.node.data, this.node, this);
|
|
||||||
} else {
|
|
||||||
this.node.leftExpanded = true;
|
|
||||||
this.tree.$emit("node-expand", this.node.data, this.node, this);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.node.expanded) {
|
|
||||||
this.node.collapse();
|
|
||||||
this.tree.$emit("node-collapse", this.node.data, this.node, this);
|
|
||||||
} else {
|
|
||||||
if (this.node.parent.childNodes && this.node.parent.childNodes.length) {
|
|
||||||
this.node.parent.childNodes.forEach(e => {
|
|
||||||
e.collapse()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.node.expand();
|
|
||||||
this.tree.$emit("node-expand", this.node.data, this.node, this);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleContextMenu(event) {
|
|
||||||
if (
|
|
||||||
this.tree._events["node-contextmenu"] &&
|
|
||||||
this.tree._events["node-contextmenu"].length > 0
|
|
||||||
) {
|
|
||||||
event.stopPropagation();
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
this.tree.$emit(
|
|
||||||
"node-contextmenu",
|
|
||||||
event,
|
|
||||||
this.node.data,
|
|
||||||
this.node,
|
|
||||||
this
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
export default function(target) {
|
|
||||||
for (let i = 1, j = arguments.length; i < j; i++) {
|
|
||||||
let source = arguments[i] || {};
|
|
||||||
for (let prop in source) {
|
|
||||||
if (source.hasOwnProperty(prop)) {
|
|
||||||
let value = source[prop];
|
|
||||||
if (value !== undefined) {
|
|
||||||
target[prop] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
@@ -1,254 +0,0 @@
|
|||||||
import { markNodeData, NODE_KEY } from './util';
|
|
||||||
import objectAssign from './merge';
|
|
||||||
|
|
||||||
const getPropertyFromData = function (node, prop) {
|
|
||||||
const props = node.store.props;
|
|
||||||
const data = node.data || {};
|
|
||||||
const config = props[prop];
|
|
||||||
|
|
||||||
if (typeof config === 'function') {
|
|
||||||
return config(data, node);
|
|
||||||
} else if (typeof config === 'string') {
|
|
||||||
return data[config];
|
|
||||||
} else if (typeof config === 'undefined') {
|
|
||||||
const dataProp = data[prop];
|
|
||||||
return dataProp === undefined ? '' : dataProp;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let nodeIdSeed = 0;
|
|
||||||
|
|
||||||
export default class Node {
|
|
||||||
constructor(options, isLeftChild = false) {
|
|
||||||
this.isLeftChild = isLeftChild;
|
|
||||||
this.id = nodeIdSeed++;
|
|
||||||
this.data = null;
|
|
||||||
this.expanded = false;
|
|
||||||
this.leftExpanded = false;
|
|
||||||
this.isCurrent = false;
|
|
||||||
this.visible = true;
|
|
||||||
this.parent = null;
|
|
||||||
for (let name in options) {
|
|
||||||
if (options.hasOwnProperty(name)) {
|
|
||||||
this[name] = options[name];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.level = 0;
|
|
||||||
this.childNodes = [];
|
|
||||||
this.leftChildNodes = [];
|
|
||||||
|
|
||||||
if (this.parent) {
|
|
||||||
this.level = this.parent.level + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const store = this.store;
|
|
||||||
if (!store) {
|
|
||||||
throw new Error('[Node]store is required!');
|
|
||||||
}
|
|
||||||
store.registerNode(this);
|
|
||||||
if (this.data) {
|
|
||||||
this.setData(this.data, isLeftChild);
|
|
||||||
if (store.defaultExpandAll || !store.showCollapsable) {
|
|
||||||
this.expanded = true;
|
|
||||||
this.leftExpanded = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Array.isArray(this.data)) {
|
|
||||||
markNodeData(this, this.data);
|
|
||||||
}
|
|
||||||
if (!this.data) return;
|
|
||||||
const defaultExpandedKeys = store.defaultExpandedKeys;
|
|
||||||
const key = store.key;
|
|
||||||
if (
|
|
||||||
key &&
|
|
||||||
defaultExpandedKeys &&
|
|
||||||
defaultExpandedKeys.indexOf(this.key) !== -1
|
|
||||||
) {
|
|
||||||
this.expand(null, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
key &&
|
|
||||||
store.currentNodeKey !== undefined &&
|
|
||||||
this.key === store.currentNodeKey
|
|
||||||
) {
|
|
||||||
store.currentNode = this;
|
|
||||||
store.currentNode.isCurrent = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.updateLeafState();
|
|
||||||
}
|
|
||||||
|
|
||||||
setData(data, isLeftChild) {
|
|
||||||
if (!Array.isArray(data)) {
|
|
||||||
markNodeData(this, data);
|
|
||||||
}
|
|
||||||
const store = this.store;
|
|
||||||
this.data = data;
|
|
||||||
this.childNodes = [];
|
|
||||||
let children;
|
|
||||||
if (this.level === 0 && this.data instanceof Array) {
|
|
||||||
children = this.data;
|
|
||||||
} else {
|
|
||||||
children = getPropertyFromData(this, 'children') || [];
|
|
||||||
}
|
|
||||||
for (let i = 0, j = children.length; i < j; i++) {
|
|
||||||
this.insertChild({ data: children[i] }, null, null, isLeftChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
get key() {
|
|
||||||
const nodeKey = this.store.key;
|
|
||||||
if (this.data) return this.data[nodeKey];
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
get label() {
|
|
||||||
return getPropertyFromData(this, 'label');
|
|
||||||
}
|
|
||||||
// 是否是 OKR 飞书模式
|
|
||||||
hasLeftChild() {
|
|
||||||
const store = this.store;
|
|
||||||
return store.onlyBothTree && store.direction === 'horizontal';
|
|
||||||
}
|
|
||||||
insertChild(child, index, batch, isLeftChild) {
|
|
||||||
if (!child) throw new Error('insertChild error: child is required.');
|
|
||||||
if (!(child instanceof Node)) {
|
|
||||||
if (!batch) {
|
|
||||||
const children = this.getChildren(true);
|
|
||||||
if (children.indexOf(child.data) === -1) {
|
|
||||||
if (index === undefined || index === null || index < 0) {
|
|
||||||
children.push(child.data);
|
|
||||||
} else {
|
|
||||||
children.splice(index, 0, child.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
objectAssign(child, {
|
|
||||||
parent: this,
|
|
||||||
store: this.store,
|
|
||||||
});
|
|
||||||
child = new Node(child, isLeftChild);
|
|
||||||
}
|
|
||||||
child.level = this.level + 1;
|
|
||||||
if (index === undefined || index === null || index < 0) {
|
|
||||||
this.childNodes.push(child);
|
|
||||||
} else {
|
|
||||||
this.childNodes.splice(index, 0, child);
|
|
||||||
}
|
|
||||||
this.updateLeafState();
|
|
||||||
}
|
|
||||||
getChildren(forceInit = false) {
|
|
||||||
// this is data
|
|
||||||
if (this.level === 0) return this.data;
|
|
||||||
const data = this.data;
|
|
||||||
if (!data) return null;
|
|
||||||
|
|
||||||
const props = this.store.props;
|
|
||||||
let children = 'children';
|
|
||||||
if (props) {
|
|
||||||
children = props.children || 'children';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data[children] === undefined) {
|
|
||||||
data[children] = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (forceInit && !data[children]) {
|
|
||||||
data[children] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return data[children];
|
|
||||||
}
|
|
||||||
updateLeafState() {
|
|
||||||
if (
|
|
||||||
this.store.lazy === true &&
|
|
||||||
this.loaded !== true &&
|
|
||||||
typeof this.isLeafByUser !== 'undefined'
|
|
||||||
) {
|
|
||||||
this.isLeaf = this.isLeafByUser;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const childNodes = this.childNodes;
|
|
||||||
if (
|
|
||||||
!this.store.lazy ||
|
|
||||||
(this.store.lazy === true && this.loaded === true)
|
|
||||||
) {
|
|
||||||
this.isLeaf = !childNodes || childNodes.length === 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.isLeaf = false;
|
|
||||||
}
|
|
||||||
updateLeftLeafState() {
|
|
||||||
if (
|
|
||||||
this.store.lazy === true &&
|
|
||||||
this.loaded !== true &&
|
|
||||||
typeof this.isLeafByUser !== 'undefined'
|
|
||||||
) {
|
|
||||||
this.isLeaf = this.isLeafByUser;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const childNodes = this.leftChildNodes;
|
|
||||||
if (
|
|
||||||
!this.store.lazy ||
|
|
||||||
(this.store.lazy === true && this.loaded === true)
|
|
||||||
) {
|
|
||||||
this.isLeaf = !childNodes || childNodes.length === 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.isLeaf = false;
|
|
||||||
}
|
|
||||||
// 节点的收起
|
|
||||||
collapse() {
|
|
||||||
this.expanded = false;
|
|
||||||
}
|
|
||||||
// 节点的展开
|
|
||||||
expand(callback, expandParent) {
|
|
||||||
const done = () => {
|
|
||||||
if (expandParent) {
|
|
||||||
let parent = this.parent;
|
|
||||||
while (parent.level > 0) {
|
|
||||||
parent.isLeftChild
|
|
||||||
? (parent.leftExpanded = true)
|
|
||||||
: (parent.expanded = true);
|
|
||||||
parent = parent.parent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.isLeftChild ? (this.leftExpanded = true) : (this.expanded = true);
|
|
||||||
if (callback) callback();
|
|
||||||
};
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
|
|
||||||
removeChild(child) {
|
|
||||||
const children = this.getChildren() || [];
|
|
||||||
const dataIndex = children.indexOf(child.data);
|
|
||||||
if (dataIndex > -1) {
|
|
||||||
children.splice(dataIndex, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const index = this.childNodes.indexOf(child);
|
|
||||||
|
|
||||||
if (index > -1) {
|
|
||||||
this.store && this.store.deregisterNode(child);
|
|
||||||
child.parent = null;
|
|
||||||
this.childNodes.splice(index, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.updateLeafState();
|
|
||||||
}
|
|
||||||
insertBefore(child, ref) {
|
|
||||||
let index;
|
|
||||||
if (ref) {
|
|
||||||
index = this.childNodes.indexOf(ref);
|
|
||||||
}
|
|
||||||
this.insertChild(child, index);
|
|
||||||
}
|
|
||||||
insertAfter(child, ref) {
|
|
||||||
let index;
|
|
||||||
if (ref) {
|
|
||||||
index = this.childNodes.indexOf(ref);
|
|
||||||
if (index !== -1) index += 1;
|
|
||||||
}
|
|
||||||
this.insertChild(child, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
.okr-fade-in-enter,.okr-fade-in-leave-active,.okr-fade-in-linear-enter,.okr-fade-in-linear-leave,.okr-fade-in-linear-leave-active,.fade-in-linear-enter,.fade-in-linear-leave,.fade-in-linear-leave-active{opacity:0}.fade-in-linear-enter-active,.fade-in-linear-leave-active{-webkit-transition:opacity .2s linear;transition:opacity .2s linear}.okr-fade-in-linear-enter-active,.okr-fade-in-linear-leave-active{-webkit-transition:opacity .2s linear;transition:opacity .2s linear}.okr-fade-in-enter-active,.okr-fade-in-leave-active{-webkit-transition:all .3s cubic-bezier(.55,0,.1,1);transition:all .3s cubic-bezier(.55,0,.1,1)}.okr-zoom-in-center-enter-active,.okr-zoom-in-center-leave-active{-webkit-transition:all .3s cubic-bezier(.55,0,.1,1);transition:all .3s cubic-bezier(.55,0,.1,1)}.okr-zoom-in-center-enter,.okr-zoom-in-center-leave-active{opacity:0;-webkit-transform:scaleX(0);transform:scaleX(0)}.okr-zoom-in-top-enter-active,.okr-zoom-in-top-leave-active{opacity:1;-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);-webkit-transform-origin:center top;transform-origin:center top}.okr-zoom-in-top-enter,.okr-zoom-in-top-leave-active{opacity:0;-webkit-transform:scaleY(0);transform:scaleY(0)}.okr-zoom-in-bottom-enter-active,.okr-zoom-in-bottom-leave-active{opacity:1;-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);-webkit-transform-origin:center bottom;transform-origin:center bottom}.okr-zoom-in-bottom-enter,.okr-zoom-in-bottom-leave-active{opacity:0;-webkit-transform:scaleY(0);transform:scaleY(0)}.okr-zoom-in-left-enter-active,.okr-zoom-in-left-leave-active{opacity:1;-webkit-transform:scale(1,1);transform:scale(1,1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);-webkit-transform-origin:top left;transform-origin:top left}.okr-zoom-in-left-enter,.okr-zoom-in-left-leave-active{opacity:0;-webkit-transform:scale(.45,.45);transform:scale(.45,.45)}.collapse-transition{-webkit-transition:.3s height ease-in-out,.3s padding-top ease-in-out,.3s padding-bottom ease-in-out;transition:.3s height ease-in-out,.3s padding-top ease-in-out,.3s padding-bottom ease-in-out}.horizontal-collapse-transition{-webkit-transition:.3s width ease-in-out,.3s padding-left ease-in-out,.3s padding-right ease-in-out;transition:.3s width ease-in-out,.3s padding-left ease-in-out,.3s padding-right ease-in-out}.okr-list-enter-active,.okr-list-leave-active{-webkit-transition:all 1s;transition:all 1s}.okr-list-enter,.okr-list-leave-active{opacity:0;-webkit-transform:translateY(-30px);transform:translateY(-30px)}.okr-opacity-transition{-webkit-transition:opacity .3s cubic-bezier(.55,0,.1,1);transition:opacity .3s cubic-bezier(.55,0,.1,1)}
|
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
import Node from "./node";
|
|
||||||
import { getNodeKey } from "./util";
|
|
||||||
export default class TreeStore {
|
|
||||||
constructor(options) {
|
|
||||||
this.currentNode = null;
|
|
||||||
this.currentNodeKey = null;
|
|
||||||
|
|
||||||
for (let option in options) {
|
|
||||||
if (options.hasOwnProperty(option)) {
|
|
||||||
this[option] = options[option];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.nodesMap = {};
|
|
||||||
this.root = new Node(
|
|
||||||
{
|
|
||||||
data: this.data,
|
|
||||||
store: this
|
|
||||||
},
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.root.store.onlyBothTree) {
|
|
||||||
if (!this.leftData)
|
|
||||||
throw new Error("[Tree] leftData is required in onlyBothTree");
|
|
||||||
if (this.leftData) {
|
|
||||||
this.isLeftChilds = new Node(
|
|
||||||
{
|
|
||||||
data: this.leftData,
|
|
||||||
store: this
|
|
||||||
},
|
|
||||||
true
|
|
||||||
);
|
|
||||||
if (this.isLeftChilds) {
|
|
||||||
this.root.childNodes[0].leftChildNodes = this.isLeftChilds.childNodes[0].childNodes;
|
|
||||||
this.root.childNodes[0].leftExpanded = this.isLeftChilds.childNodes[0].leftExpanded;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
filter(value, childName = "childNodes") {
|
|
||||||
this.filterRight(value, childName);
|
|
||||||
}
|
|
||||||
// 过滤默认节点
|
|
||||||
filterRight(value, childName) {
|
|
||||||
const filterNodeMethod = this.filterNodeMethod;
|
|
||||||
const traverse = function(node, childName) {
|
|
||||||
let childNodes;
|
|
||||||
if (node.root) {
|
|
||||||
childNodes = node.root.childNodes[0][childName];
|
|
||||||
} else {
|
|
||||||
childNodes = node.childNodes;
|
|
||||||
}
|
|
||||||
childNodes.forEach(child => {
|
|
||||||
child.visible = filterNodeMethod.call(child, value, child.data, child);
|
|
||||||
traverse(child, childName);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!node.visible && childNodes.length) {
|
|
||||||
let allHidden = true;
|
|
||||||
allHidden = !childNodes.some(child => child.visible);
|
|
||||||
|
|
||||||
if (node.root) {
|
|
||||||
node.root.visible = allHidden === false;
|
|
||||||
} else {
|
|
||||||
node.visible = allHidden === false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!value) return;
|
|
||||||
|
|
||||||
if (node.visible) node.expand();
|
|
||||||
};
|
|
||||||
|
|
||||||
traverse(this, childName);
|
|
||||||
}
|
|
||||||
|
|
||||||
registerNode(node) {
|
|
||||||
const key = this.key;
|
|
||||||
if (!key || !node || !node.data) return;
|
|
||||||
|
|
||||||
const nodeKey = node.key;
|
|
||||||
if (nodeKey !== undefined) this.nodesMap[node.key] = node;
|
|
||||||
}
|
|
||||||
deregisterNode(node) {
|
|
||||||
const key = this.key;
|
|
||||||
if (!key || !node || !node.data) return;
|
|
||||||
node.childNodes.forEach(child => {
|
|
||||||
this.deregisterNode(child);
|
|
||||||
});
|
|
||||||
delete this.nodesMap[node.key];
|
|
||||||
}
|
|
||||||
setData(newVal) {
|
|
||||||
const instanceChanged = newVal !== this.root.data;
|
|
||||||
if (instanceChanged) {
|
|
||||||
this.root.setData(newVal);
|
|
||||||
} else {
|
|
||||||
this.root.updateChildren();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateChildren(key, data) {
|
|
||||||
const node = this.nodesMap[key];
|
|
||||||
if (!node) return;
|
|
||||||
const childNodes = node.childNodes;
|
|
||||||
for (let i = childNodes.length - 1; i >= 0; i--) {
|
|
||||||
const child = childNodes[i];
|
|
||||||
this.remove(child.data);
|
|
||||||
}
|
|
||||||
for (let i = 0, j = data.length; i < j; i++) {
|
|
||||||
const child = data[i];
|
|
||||||
this.append(child, node.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getNode(data) {
|
|
||||||
if (data instanceof Node) return data;
|
|
||||||
const key = typeof data !== "object" ? data : getNodeKey(this.key, data);
|
|
||||||
return this.nodesMap[key] || null;
|
|
||||||
}
|
|
||||||
setDefaultExpandedKeys(keys) {
|
|
||||||
keys = keys || [];
|
|
||||||
this.defaultExpandedKeys = keys;
|
|
||||||
keys.forEach(key => {
|
|
||||||
const node = this.getNode(key);
|
|
||||||
if (node) node.expand(null, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setCurrentNode(currentNode) {
|
|
||||||
const prevCurrentNode = this.currentNode;
|
|
||||||
if (prevCurrentNode) {
|
|
||||||
prevCurrentNode.isCurrent = false;
|
|
||||||
}
|
|
||||||
this.currentNode = currentNode;
|
|
||||||
this.currentNode.isCurrent = true;
|
|
||||||
}
|
|
||||||
setUserCurrentNode(node) {
|
|
||||||
const key = node.key;
|
|
||||||
const currNode = this.nodesMap[key];
|
|
||||||
this.setCurrentNode(currNode);
|
|
||||||
}
|
|
||||||
setCurrentNodeKey(key) {
|
|
||||||
if (key === null || key === undefined) {
|
|
||||||
this.currentNode && (this.currentNode.isCurrent = false);
|
|
||||||
this.currentNode = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const node = this.getNode(key);
|
|
||||||
if (node) {
|
|
||||||
this.setCurrentNode(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getCurrentNode() {
|
|
||||||
return this.currentNode;
|
|
||||||
}
|
|
||||||
remove(data) {
|
|
||||||
const node = this.getNode(data);
|
|
||||||
if (node && node.parent) {
|
|
||||||
if (node === this.currentNode) {
|
|
||||||
this.currentNode = null;
|
|
||||||
}
|
|
||||||
node.parent.removeChild(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
append(data, parentData) {
|
|
||||||
const parentNode = parentData ? this.getNode(parentData) : this.root;
|
|
||||||
|
|
||||||
if (parentNode) {
|
|
||||||
parentNode.insertChild({ data });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
insertBefore(data, refData) {
|
|
||||||
const refNode = this.getNode(refData);
|
|
||||||
refNode.parent.insertBefore({ data }, refNode);
|
|
||||||
}
|
|
||||||
insertAfter(data, refData) {
|
|
||||||
const refNode = this.getNode(refData);
|
|
||||||
refNode.parent.insertAfter({ data }, refNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
export const NODE_KEY = "$treeNodeId";
|
|
||||||
|
|
||||||
export const markNodeData = function(node, data) {
|
|
||||||
if (!data || data[NODE_KEY]) return;
|
|
||||||
Object.defineProperty(data, NODE_KEY, {
|
|
||||||
value: node.id,
|
|
||||||
enumerable: false,
|
|
||||||
configurable: false,
|
|
||||||
writable: false
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getNodeKey = function(key, data) {
|
|
||||||
if (!key) return data[NODE_KEY];
|
|
||||||
return data[key];
|
|
||||||
};
|
|
||||||
|
|
||||||
export const findNearestComponent = (element, componentName) => {
|
|
||||||
let target = element;
|
|
||||||
while (target && target.tagName !== "BODY") {
|
|
||||||
if (target.__vue__ && target.__vue__.$options.name === componentName) {
|
|
||||||
return target.__vue__;
|
|
||||||
}
|
|
||||||
target = target.parentNode;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
@@ -617,6 +617,14 @@
|
|||||||
.dept-name{
|
.dept-name{
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 200px;
|
width: 200px;
|
||||||
|
height: 22px;
|
||||||
|
overflow:hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
.el-icon-arrow-down{
|
||||||
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.active{
|
.active{
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ export default {
|
|||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res?.data) {
|
if (res?.data) {
|
||||||
this.tableData = res.data?.records.map(e => {
|
this.tableData = res.data?.records.map(e => {
|
||||||
let guaranteeModeLabel = e.guaranteeMode.split(",").map(g => this.dict.getLabel("productGuaranteeMode", g))?.toString()
|
let guaranteeModeLabel = e.guaranteeMode?.split(",").map(g => this.dict.getLabel("productGuaranteeMode", g))?.toString()
|
||||||
return {...e, guaranteeModeLabel}
|
return {...e, guaranteeModeLabel}
|
||||||
})
|
})
|
||||||
this.page.total = res.data.total
|
this.page.total = res.data.total
|
||||||
|
|||||||
Reference in New Issue
Block a user