减少冗余代码
This commit is contained in:
		| @@ -1,282 +1,282 @@ | ||||
| <template> | ||||
|   <div class="AiGrid" ref="container"> | ||||
|     <div | ||||
|       class="AiGrid-wrapper" | ||||
|       ref="tree" | ||||
|       id="tree" | ||||
|       :style="{left: x, top: y, transform: `scale(${scale}) translate(-50%, -50%) `, 'transform-origin': `${0} ${0}`}"> | ||||
|         class="AiGrid-wrapper" | ||||
|         ref="tree" | ||||
|         id="tree" | ||||
|         :style="{left: x, top: y, transform: `scale(${scale}) translate(-50%, -50%) `, 'transform-origin': `${0} ${0}`}"> | ||||
|       <VueOkrTree | ||||
|         :props="props" | ||||
|         node-key="id" | ||||
|         show-collapsable | ||||
|         show-node-num | ||||
|         current-lable-class-name="aigrid-active" | ||||
|         :default-expanded-keys="defaultExpandedKeys" | ||||
|         ref="VueOkrTree" | ||||
|         @node-click="onNodeClick" | ||||
|         :data="treeData"> | ||||
|           :props="props" | ||||
|           node-key="id" | ||||
|           show-collapsable | ||||
|           show-node-num | ||||
|           current-lable-class-name="aigrid-active" | ||||
|           :default-expanded-keys="defaultExpandedKeys" | ||||
|           ref="VueOkrTree" | ||||
|           @node-click="onNodeClick" | ||||
|           :data="treeData"> | ||||
|       </VueOkrTree> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import OkrTree from './vue-okr-tree/OkrTree' | ||||
| import AiOkrTree from "dvcp-dv-ui/components/AiOkrTree/AiOkrTree" | ||||
|  | ||||
|   export default { | ||||
|     name: 'AiGrid', | ||||
| export default { | ||||
|   name: 'AiGrid', | ||||
|  | ||||
|     props: ['instance'], | ||||
|   props: ['instance'], | ||||
|  | ||||
|     components: { | ||||
|       VueOkrTree: OkrTree | ||||
|     }, | ||||
|   components: { | ||||
|     VueOkrTree: AiOkrTree | ||||
|   }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         scale: 1, | ||||
|         x: '50%', | ||||
|         y: '50%', | ||||
|         defaultExpandedKeys: [], | ||||
|         treeData: [], | ||||
|         props: { | ||||
|           label: 'girdName', | ||||
|           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%' | ||||
|   data() { | ||||
|     return { | ||||
|       scale: 1, | ||||
|       x: '50%', | ||||
|       y: '50%', | ||||
|       defaultExpandedKeys: [], | ||||
|       treeData: [], | ||||
|       props: { | ||||
|         label: 'girdName', | ||||
|         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%' | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|   .AiGrid { | ||||
|     position: relative; | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
| .AiGrid { | ||||
|   position: relative; | ||||
|   width: 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; | ||||
|     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; | ||||
|       position: absolute; | ||||
|       align-items: center; | ||||
|       left: 50%; | ||||
|       top: 50%; | ||||
|       padding: 20px; | ||||
|       overflow: hidden; | ||||
|       width: max-content; | ||||
|       height: 300%; | ||||
|       justify-content: center; | ||||
|       float: initial !important; | ||||
|     } | ||||
|  | ||||
|     .aigrid-active { | ||||
|       background: linear-gradient(180deg, #42C6CE 0%, #307598 100%); | ||||
|     } | ||||
|  | ||||
|     ::v-deep .org-chart-container { | ||||
|       color: #FFFFFF; | ||||
|     .org-chart-node-btn { | ||||
|       border: 1px solid #23A0AC !important; | ||||
|       font-size: 16px; | ||||
|       font-weight: bold; | ||||
|       background: #071030; | ||||
|       color: #FF9A02; | ||||
|  | ||||
|       .org-chart-node-children { | ||||
|         display: flex; | ||||
|         justify-content: center; | ||||
|         float: initial!important; | ||||
|       &:after, &::before { | ||||
|         display: none; | ||||
|       } | ||||
|  | ||||
|       .org-chart-node-btn { | ||||
|         border: 1px solid #23A0AC!important; | ||||
|         font-size: 16px; | ||||
|         font-weight: bold; | ||||
|         background: #071030; | ||||
|       &.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; | ||||
|  | ||||
|         &: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 { | ||||
|         // overflow: hidden; | ||||
|     .org-chart-node { | ||||
|       // overflow: hidden; | ||||
|  | ||||
|         .org-chart-node-label { | ||||
|           width: 40px; | ||||
|           height: 254px; | ||||
|           margin-right: 15px; | ||||
|           padding: 0 0; | ||||
|       .org-chart-node-label { | ||||
|         width: 40px; | ||||
|         height: 254px; | ||||
|         margin-right: 15px; | ||||
|         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 { | ||||
|             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; | ||||
|             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; | ||||
|             font-size: 18px; | ||||
|             color: rgba(255, 255, 255, 0.8); | ||||
|             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; | ||||
|               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, | ||||
|       .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; | ||||
|       &:last-child { | ||||
|         .org-chart-node-label { | ||||
|           margin-right: 0; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .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> | ||||
|   | ||||
| @@ -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; | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user