From ddcc8a66f33612284d3f2768cc16c4b6be269bf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Wed, 1 Apr 2020 16:26:54 +0800 Subject: [PATCH 01/44] =?UTF-8?q?=E6=A0=91=E8=8A=82=E7=82=B9=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E7=9A=84=E6=8B=96=E6=8B=BD=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/tree/pl-tree-node.vue | 12 +++++-- src/components/tree/pl-tree.vue | 48 ++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/components/tree/pl-tree-node.vue b/src/components/tree/pl-tree-node.vue index 757a839ea..af7f1ec13 100644 --- a/src/components/tree/pl-tree-node.vue +++ b/src/components/tree/pl-tree-node.vue @@ -23,13 +23,21 @@ name: 'show', value: this.treeNode.isVisible }] + const nodeOn = { + ...(!!this.plTree.draggable ? { + dragstart: this.plTree.dragState.dragstart, + dragend: this.plTree.dragState.dragend, + dragover: this.plTree.dragState.dragover, + } : {}) + } + const nodeListDirectives = [{ name: 'show', value: this.isExpand && this.show }] return ( -
  • +
  • this.plTree.onClickNodeContent(this.treeNode)}>
    { @@ -74,7 +82,7 @@ ) }, computed: { - level(){ + level() { return this.treeNode.level - 1 }, classes() { diff --git a/src/components/tree/pl-tree.vue b/src/components/tree/pl-tree.vue index a13c7c88f..87143c068 100644 --- a/src/components/tree/pl-tree.vue +++ b/src/components/tree/pl-tree.vue @@ -5,6 +5,7 @@ {{emptyText}}
  • + @@ -122,6 +123,44 @@ const mark: { [key: string]: TreeMark } = {} // 标记映射 const formatCount: number = 0; // 当前格式化数据的时候,数据的版本,用来清理mark中不需要保存的数据 let rootTreeNode: TreeNode = new TreeNode({}, this, 0); // 根节点 treeNode对象 + + const dragState = { + show: false, + indicatorStyles: {}, + /*---------------------------------------drag listener-------------------------------------------*/ + dragstart: (e) => { + e.stopPropagation() + e.dataTransfer.effectAllowed = 'move' + }, + dragend: (e) => { + e.stopPropagation() + console.log('被拖拽的节点', e.currentTarget.__vue__.treeNode.label) + + dragState.show = false + dragState.indicatorStyles = {} + }, + /*---------------------------------------drop listener-------------------------------------------*/ + dragover: (e) => { + e.stopPropagation() + e.preventDefault() + // console.log('over ', e.currentTarget.__vue__.treeNode.label) + const {clientY} = e + + let rect = e.currentTarget.getBoundingClientRect() + if (!!rect) { + const {height, width, left, top} = rect + + dragState.show = true + dragState.indicatorStyles = { + top: `${top}px`, + width: `${width}px`, + left: `${left}px`, + } + } + + console.log(clientY) + }, + } return { p_data, p_loading, @@ -129,6 +168,7 @@ mark, formatCount, rootTreeNode, + dragState, } }, created(): void { @@ -647,6 +687,14 @@ } } + .pl-tree-drag-indicator { + position: fixed; + z-index: 9999; + height: 2px; + background-color: $colorPrimary; + display: inline-block; + } + &.pl-tree-highlight-current { .pl-tree-node.pl-tree-node-current > .pl-tree-node-content { background-color: mix(white, $colorPrimary, 90%); -- Gitee From f7e937e9e1aa7b3e7860592ce7426dceec23887f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Wed, 1 Apr 2020 18:20:56 +0800 Subject: [PATCH 02/44] =?UTF-8?q?=E5=A5=BD=E5=83=8F=E6=88=90=E5=8A=9F?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E4=BA=86=20tree=20=E7=9A=84=E6=8B=96?= =?UTF-8?q?=E6=8B=BD=E6=8E=92=E5=BA=8F=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/tree/pl-tree-node.vue | 3 +- src/components/tree/pl-tree.vue | 180 ++++++++++++++++++++++++--- src/components/tree/tree.ts | 18 +++ 3 files changed, 184 insertions(+), 17 deletions(-) diff --git a/src/components/tree/pl-tree-node.vue b/src/components/tree/pl-tree-node.vue index af7f1ec13..4d4de0933 100644 --- a/src/components/tree/pl-tree-node.vue +++ b/src/components/tree/pl-tree-node.vue @@ -88,7 +88,8 @@ classes() { return [ 'pl-tree-node', - {'pl-tree-node-expand': this.isExpand, 'pl-tree-node-current': this.treeNode.key === this.plTree.p_currentKey} + {'pl-tree-node-expand': this.isExpand, 'pl-tree-node-current': this.treeNode.key === this.plTree.p_currentKey}, + {'pl-tree-node-drop-inner': this.plTree.dragState.dropInnerKey === this.treeNode.key} ] }, /** diff --git a/src/components/tree/pl-tree.vue b/src/components/tree/pl-tree.vue index 87143c068..c337d7624 100644 --- a/src/components/tree/pl-tree.vue +++ b/src/components/tree/pl-tree.vue @@ -5,7 +5,7 @@ {{emptyText}} - + @@ -14,6 +14,18 @@ import PlTreeNode from "./pl-tree-node.vue"; import {TreeMark, TreeNode} from "./tree"; + /** + * 拖拽放置的类型 + * @author 韦胜健 + * @date 2020/4/1 17:15 + */ + enum DropType { + prev = 'prev', + inner = 'inner', + next = 'next', + null = 'null', + } + export default { name: "pl-tree", components: {PlTreeNode}, @@ -124,41 +136,149 @@ const formatCount: number = 0; // 当前格式化数据的时候,数据的版本,用来清理mark中不需要保存的数据 let rootTreeNode: TreeNode = new TreeNode({}, this, 0); // 根节点 treeNode对象 - const dragState = { - show: false, - indicatorStyles: {}, + const dragState: { + show: boolean, + indicatorStyles: { top?: number, width?: number, left?: number }, + dropInnerKey: string, + dropType: DropType, + dropTreeNode: TreeNode, + dragTreeNode: TreeNode, + dragstart: Function, + dragend: Function, + dragover: Function, + } + = { + show: false, // 当前拖拽指示器是否展示 + indicatorStyles: {}, // 当前指示器样式 + dropInnerKey: null, // 当前拖拽,即将放入内部的节点的key + dropType: DropType.null, // 当前拖拽在目标节点的位置 + dropTreeNode: null, // 当前拖拽目标节点的treeNode对象 + dragTreeNode: null, /*---------------------------------------drag listener-------------------------------------------*/ dragstart: (e) => { e.stopPropagation() e.dataTransfer.effectAllowed = 'move' + dragState.dragTreeNode = e.currentTarget.__vue__.treeNode }, dragend: (e) => { e.stopPropagation() console.log('被拖拽的节点', e.currentTarget.__vue__.treeNode.label) dragState.show = false + dragState.dropInnerKey = null dragState.indicatorStyles = {} + + const {dropTreeNode, dragTreeNode, dropType} = dragState + + if (!!dropTreeNode) { + dragTreeNode.removeSelf() + const dropRelativeTreeNodes = dropTreeNode.parent.children + + switch (dropType) { + case DropType.prev: + // console.log(`添加到 ${dropTreeNode.label} 之前`) + dropTreeNode.splice(dropRelativeTreeNodes.indexOf(dropTreeNode), 0, dragTreeNode.data) + break + case DropType.inner: + // console.log(`添加到 ${dropTreeNode.label} 内部`) + dropTreeNode.push(dragTreeNode.data) + break + case DropType.next: + // console.log(`添加到 ${dropTreeNode.label} 之后`) + dropTreeNode.splice(dropRelativeTreeNodes.indexOf(dropTreeNode) + 1, 0, dragTreeNode.data) + break + default: + // console.log(`无任何变化`) + break + } + } }, /*---------------------------------------drop listener-------------------------------------------*/ dragover: (e) => { e.stopPropagation() e.preventDefault() - // console.log('over ', e.currentTarget.__vue__.treeNode.label) - const {clientY} = e + e.dataTransfer.dropEffect = 'move' - let rect = e.currentTarget.getBoundingClientRect() - if (!!rect) { - const {height, width, left, top} = rect + const treeNode = e.currentTarget.__vue__.treeNode + + let doNothing = () => { + e.dataTransfer.dropEffect = 'none' + dragState.show = false + dragState.dropInnerKey = null + dragState.indicatorStyles = {} + dragState.dropType = DropType.null + dragState.dropTreeNode = null + } - dragState.show = true - dragState.indicatorStyles = { - top: `${top}px`, - width: `${width}px`, - left: `${left}px`, + // 如果当前 over 的节点为拖拽节点的子节点,则什么事也不干,清空标记信息并且什么也不做 + if (treeNode === dragState.dragTreeNode) { + doNothing() + return; + } else { + let containsFlag = false + this.iterateAll(dragState.dragTreeNode.children, (child) => { + if (child === treeNode) { + containsFlag = true + } + }) + if (containsFlag) { + doNothing() + return; } } - console.log(clientY) + let label = e.currentTarget.querySelector('.pl-tree-node-content-label') + let rect = label.getBoundingClientRect() + + if (!!rect) { + let {height, width, left, top} = rect + let deltaY = e.clientY - top + + dragState.dropTreeNode = treeNode + + if (deltaY < height / 4) { + // 上 + dragState.dropType = DropType.prev + dragState.show = true + dragState.dropInnerKey = null + dragState.indicatorStyles = {top, width, left} + } else if (deltaY < height * (3 / 4)) { + // 中 + dragState.dropType = DropType.inner + dragState.show = false + dragState.indicatorStyles = {} + dragState.dropInnerKey = treeNode.key + + } else { + // 下 + if (treeNode.isExpand && !!treeNode.children && treeNode.children.length > 0) { + // 节点已经展开,并且有子节点,表示插入到第一个子节点之前 + let firstChildTreeNodeDom = e.currentTarget.querySelector('.pl-tree-node') + label = firstChildTreeNodeDom.querySelector('.pl-tree-node-content-label') + rect = label.getBoundingClientRect() + if (!!rect) { + + dragState.dropTreeNode = firstChildTreeNodeDom.__vue__.treeNode + + width = rect.width + left = rect.left + top = rect.top + + dragState.dropType = DropType.prev + dragState.show = true + dragState.dropInnerKey = null + dragState.indicatorStyles = {top, width, left} + } + + } else { + // 否则这时候应该将节点插入到目标节点之后 + dragState.dropType = DropType.next + dragState.show = true + dragState.dropInnerKey = null + dragState.indicatorStyles = {top: top + height, width, left,} + } + } + } }, } return { @@ -208,6 +328,7 @@ } this.formatCount++ this.rootTreeNode.children = this.p_data.map(item => this.formatNodeData(item, this.formatCount, this.rootTreeNode)) + this.rootTreeNode.data = {[this.childrenField]: this.p_data} return this.rootTreeNode.children }, /** @@ -234,6 +355,25 @@ isLoading() { return this.loading || this.p_loading }, + /** + * 拖拽指示器的样式 + * @author 韦胜健 + * @date 2020/4/1 17:39 + */ + indicatorStyles() { + let styles = {} as any + const indicatorStyles = this.dragState.indicatorStyles + if (!!indicatorStyles.left) { + styles.left = `${indicatorStyles.left + 6}px` + } + if (!!indicatorStyles.width) { + styles.width = `${indicatorStyles.width}px` + } + if (!!indicatorStyles.top) { + styles.top = `${indicatorStyles.top}px` + } + return styles + }, }, methods: { /*---------------------------------------methods-------------------------------------------*/ @@ -633,7 +773,6 @@ font-size: 14px; line-height: 24px; cursor: pointer; - user-select: none; .pl-tree-node-content { padding-right: 12px; @@ -653,12 +792,14 @@ .pl-checkbox-indeterminate { padding-left: 6px; + user-select: none; } .pl-tree-node-content-expand-wrapper { position: relative; display: inline-block; width: 1em; + user-select: none; } } @@ -667,6 +808,13 @@ transform: rotate(90deg); } } + + &.pl-tree-node-drop-inner { + & > .pl-tree-node-content > .pl-tree-node-content-label { + color: $colorPrimary; + font-weight: bold; + } + } } .pl-icon { diff --git a/src/components/tree/tree.ts b/src/components/tree/tree.ts index ec85b96d7..e3175e27b 100644 --- a/src/components/tree/tree.ts +++ b/src/components/tree/tree.ts @@ -75,6 +75,24 @@ export class TreeNode { setChildren(children: TreeNode[]) { this.context.$set(this.data, this.context.childrenField, children) } + + removeSelf() { + const childrenData = this.parent.data[this.context.childrenField] + childrenData.splice(childrenData.indexOf(this.data), 1) + } + + splice(index, count, replace) { + const childrenData = this.parent.data[this.context.childrenField] || [] + let ret = childrenData.splice(index, count, replace) + this.parent.data[this.context.childrenField] = childrenData + return ret + } + + push(data) { + const childrenData = this.data[this.context.childrenField] || [] + childrenData.push(data) + this.data[this.context.childrenField] = childrenData + } } export class TreeMark { -- Gitee From e9b9357cb69cbb82b4060110be53d54166f456a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Wed, 1 Apr 2020 18:39:40 +0800 Subject: [PATCH 03/44] =?UTF-8?q?=E5=AE=8C=E6=88=90=20tree=20=E7=9A=84?= =?UTF-8?q?=E6=8B=96=E6=8B=BD=E6=8E=92=E5=BA=8F=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-doc/page/normal/tree.vue | 6 +++++- src/components/tree/pl-tree.vue | 17 ++++++++++++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src-doc/page/normal/tree.vue b/src-doc/page/normal/tree.vue index 66ab0c78a..fc27e1c91 100644 --- a/src-doc/page/normal/tree.vue +++ b/src-doc/page/normal/tree.vue @@ -214,7 +214,11 @@ labelField="name" childrenField="subs" draggable - /> + > + + diff --git a/src/components/tree/pl-tree.vue b/src/components/tree/pl-tree.vue index c337d7624..126c9401f 100644 --- a/src/components/tree/pl-tree.vue +++ b/src/components/tree/pl-tree.vue @@ -146,14 +146,16 @@ dragstart: Function, dragend: Function, dragover: Function, + reflow: boolean, } = { show: false, // 当前拖拽指示器是否展示 indicatorStyles: {}, // 当前指示器样式 dropInnerKey: null, // 当前拖拽,即将放入内部的节点的key dropType: DropType.null, // 当前拖拽在目标节点的位置 - dropTreeNode: null, // 当前拖拽目标节点的treeNode对象 - dragTreeNode: null, + dropTreeNode: null, // 当前放置目标节点的treeNode对象 + dragTreeNode: null, // 当前拖拽目标节点的treeNode对象 + reflow: false, // 当前是否正在重新渲染,重新渲染的时候不要展开动画 /*---------------------------------------drag listener-------------------------------------------*/ dragstart: (e) => { e.stopPropagation() @@ -174,6 +176,7 @@ dragTreeNode.removeSelf() const dropRelativeTreeNodes = dropTreeNode.parent.children + dragState.reflow = true switch (dropType) { case DropType.prev: // console.log(`添加到 ${dropTreeNode.label} 之前`) @@ -191,6 +194,7 @@ // console.log(`无任何变化`) break } + setTimeout(() => dragState.reflow = false, 100) } }, /*---------------------------------------drop listener-------------------------------------------*/ @@ -309,7 +313,8 @@ 'pl-tree', 'pl-tree-node-list', { - 'pl-tree-highlight-current': this.highlightCurrent + 'pl-tree-highlight-current': this.highlightCurrent, + 'pl-tree-reflow': this.dragState.reflow, } ] }, @@ -848,6 +853,12 @@ background-color: mix(white, $colorPrimary, 90%); } } + + &.pl-tree-reflow { + .pl-tree-node-list { + transition: none !important; + } + } } } \ No newline at end of file -- Gitee From 0e21bfeb86ec02a47132f0a6bcc6faee349eadb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Wed, 1 Apr 2020 18:42:41 +0800 Subject: [PATCH 04/44] tree checkbox --- src-doc/page/normal/tree.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src-doc/page/normal/tree.vue b/src-doc/page/normal/tree.vue index fc27e1c91..385ed67e5 100644 --- a/src-doc/page/normal/tree.vue +++ b/src-doc/page/normal/tree.vue @@ -214,6 +214,7 @@ labelField="name" childrenField="subs" draggable + showCheckbox > @@ -111,14 +111,49 @@ padding: 0; list-style: none; - .pl-virtual-tree-node { - transition: all 300ms $transition; - } - .pl-list-move-right-enter { opacity: 0; transform: translateX(100px); } + + .pl-icon { + color: $icc; + + &.pl-tree-expand-icon { + transition: all $transition 300ms; + } + } + + .pl-virtual-tree-node { + transition: all 300ms $transition; + font-size: 14px; + line-height: 24px; + cursor: pointer; + width: 200px; + + .pl-virtual-tree-node-expander { + height: 24px; + width: 18px; + user-select: none; + display: inline-block; + } + + .pl-virtual-tree-node-content { + display: inline-block; + padding-left: 18px; + transition: background-color 300ms $transition; + + &:hover { + background-color: mix(white, $colorPrimary, 90%); + } + } + + &.pl-virtual-tree-node-expand { + & > .pl-virtual-tree-node-expander > .pl-tree-expand-icon { + transform: rotate(90deg); + } + } + } } } \ No newline at end of file diff --git a/src/components/virtual-tree/pl-virtual-tree-node.tsx b/src/components/virtual-tree/pl-virtual-tree-node.tsx index 9bd041523..d6ba31e57 100644 --- a/src/components/virtual-tree/pl-virtual-tree-node.tsx +++ b/src/components/virtual-tree/pl-virtual-tree-node.tsx @@ -1,15 +1,66 @@ +import PlTreeNode from '../tree/pl-tree-node.vue' + +const OldTreeNode = PlTreeNode as any + export default { props: { treeNode: {type: Object}, }, + inject: { + plTree: {}, + }, data() { return {} }, render(h) { return ( - - {this.treeNode.label} + +
    + { + this.isLoading ? + + : + (!this.treeNode.isLeaf && this.plTree.onClickExpandIcon(e, this.treeNode)} class="pl-tree-expand-icon"/>) + } +
    +
    this.plTree.onClickNodeContent(this.treeNode)}> + {this.treeNode.label} +
    ) }, + computed: { + // @ts-ignore + classes() { + return [ + 'pl-virtual-tree-node', + { + 'pl-virtual-tree-node-expand': this.isExpand, + 'pl-virtual-tree-node-current': this.treeNode.key === this.plTree.p_currentKey + }, + // {'pl-virtual-tree-node-drop-inner': this.plTree.dragState.dropInnerKey === this.treeNode.key} + ] + }, + level() { + return this.treeNode.level - 1 + }, + expanderStyles() { + const paddingLeft: string = this.level * this.plTree.intent + 'px' + return { + paddingLeft + } + }, + contentStyles() { + let paddingLeft = 18 + if (this.plTree.showCheckbox) { + paddingLeft += 18 + } + paddingLeft += this.level * this.plTree.intent + return { + paddingLeft: paddingLeft + 'px' + } + }, + isExpand: OldTreeNode.computed.isExpand, + isLoading: OldTreeNode.computed.isLoading, + }, } \ No newline at end of file diff --git a/src/components/virtual-tree/pl-virtual-tree.tsx b/src/components/virtual-tree/pl-virtual-tree.tsx index 03438f7df..aa398cf19 100644 --- a/src/components/virtual-tree/pl-virtual-tree.tsx +++ b/src/components/virtual-tree/pl-virtual-tree.tsx @@ -7,9 +7,16 @@ const Tree = tree as any export default { name: "pl-virtual-tree", components: {PlVirtualTreeNode}, + mixins: Tree.mixins, + emitters: Tree.emitters, props: { ...Tree.props, }, + provide() { + return { + plTree: this, + } + }, data() { const p_data: any[] = this.data const p_currentKey: string = null @@ -28,7 +35,7 @@ export default { }, render(h) { return ( - + {this.formatDataFlat.map((item) => )} ) @@ -54,16 +61,47 @@ export default { this.iterateAll(formatData, (treeNode: TreeNode) => { formatDataFlat.push(treeNode) }, (treeNode: TreeNode) => { - return treeNode.isExpand + return treeNode.isExpand === true }) return formatDataFlat }, }, methods: { - formatNodeData: Tree.methods.formatNodeData, - checkProps: Tree.methods.checkProps, + + /*---------------------------------------methods-------------------------------------------*/ + /*current*/ + setCurrent: Tree.methods.setCurrent, + getCurrent: Tree.methods.getCurrent, + /*expand*/ + expand: Tree.methods.expand, + collapse: Tree.methods.collapse, + toggleExpand: Tree.methods.toggleExpand, + expandAll: Tree.methods.expandAll, + collapseAll: Tree.methods.collapseAll, + /*check*/ + check: Tree.methods.check, + uncheck: Tree.methods.uncheck, + toggleCheck: Tree.methods.toggleCheck, + checkAll: Tree.methods.checkAll, + uncheckAll: Tree.methods.uncheckAll, + getCheckedData: Tree.methods.getCheckedData, + + /*---------------------------------------utils-------------------------------------------*/ setMark: Tree.methods.setMark, getMark: Tree.methods.getMark, iterateAll: Tree.methods.iterateAll, + checkProps: Tree.methods.checkProps, + formatNodeData: Tree.methods.formatNodeData, + findTreeNodeByKey: Tree.methods.findTreeNodeByKey, + getChildrenAsync: Tree.methods.getChildrenAsync, + handleKeys: Tree.methods.handleKeys, + + /*---------------------------------------helper-------------------------------------------*/ + initLazy: Tree.methods.initLazy, + + /*---------------------------------------handler-------------------------------------------*/ + onClickExpandIcon: Tree.methods.onClickExpandIcon, + onClickNodeContent: Tree.methods.onClickNodeContent, + onClickCheckbox: Tree.methods.onClickCheckbox, }, } \ No newline at end of file -- Gitee From b84b87a8b3ecaba9d22130c8d10c729ebebfc358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Thu, 2 Apr 2020 11:55:38 +0800 Subject: [PATCH 14/44] =?UTF-8?q?=E8=B0=83=E6=95=B4treeNode=E7=9A=84?= =?UTF-8?q?=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/tree/pl-tree-node.vue | 56 +++++++++++++++++++--------- src/components/tree/pl-tree.vue | 53 ++++++++++++++------------ 2 files changed, 68 insertions(+), 41 deletions(-) diff --git a/src/components/tree/pl-tree-node.vue b/src/components/tree/pl-tree-node.vue index 4d4de0933..215cb7634 100644 --- a/src/components/tree/pl-tree-node.vue +++ b/src/components/tree/pl-tree-node.vue @@ -38,30 +38,34 @@ return (
  • -
    this.plTree.onClickNodeContent(this.treeNode)}> -
    - { - this.isLoading ? - - : - (!this.treeNode.isLeaf && this.plTree.onClickExpandIcon(e, this.treeNode)} class="pl-tree-expand-icon"/>) - } +
    +
    + + { + this.isLoading ? + + : + (!this.treeNode.isLeaf && this.plTree.onClickExpandIcon(e, this.treeNode)} class="pl-tree-expand-icon"/>) + } + + {!!this.plTree.showCheckbox && this.plTree.onClickCheckbox(e, this.treeNode)}}} + />}
    - {!!this.plTree.showCheckbox && this.plTree.onClickCheckbox(e, this.treeNode)}}} - />} - @@ -98,8 +102,24 @@ * @date 2020/3/31 9:32 */ contentStyles() { + let paddingLeft = this.plTree.intent * this.level + 6 + paddingLeft += 18 + if (this.plTree.showCheckbox) { + paddingLeft += 24 + } + return { + paddingLeft: `${paddingLeft}px` + } + }, + /** + * expander节点style + * @author 韦胜健 + * @date 2020/4/2 11:46 + */ + expanderStyles() { + let paddingLeft = this.plTree.intent * this.level + 6 return { - paddingLeft: `${this.plTree.intent * this.level + 6}px` + paddingLeft: `${paddingLeft}px` } }, /** diff --git a/src/components/tree/pl-tree.vue b/src/components/tree/pl-tree.vue index 0e4a5121b..89b17317b 100644 --- a/src/components/tree/pl-tree.vue +++ b/src/components/tree/pl-tree.vue @@ -778,44 +778,51 @@ font-size: 14px; line-height: 24px; cursor: pointer; + display: block; - .pl-tree-node-content { - padding-right: 12px; - display: flex; - align-items: center; - flex-wrap: nowrap; + .pl-tree-node-wrapper { + position: relative; + width: 100%; transition: all $transition 300ms; - &:hover { - background-color: mix(white, $colorPrimary, 90%); - } + .pl-tree-node-operator { + position: absolute; + top: 0; + left: 0; + user-select: none; - .pl-tree-node-content-label { - padding: 0 6px; - flex: 1; + .pl-tree-node-expander { + height: 24px; + content: ''; + display: inline-block; + } + + .pl-checkbox-indeterminate { + user-select: none; + } } - .pl-checkbox-indeterminate { - padding-left: 6px; - user-select: none; + .pl-tree-node-content { + width: 100%; + + .pl-tree-node-content-label { + padding: 0 6px; + } } - .pl-tree-node-content-expand-wrapper { - position: relative; - display: inline-block; - width: 1em; - user-select: none; + &:hover { + background-color: mix(white, $colorPrimary, 90%); } } &.pl-tree-node-expand { - & > .pl-tree-node-content > .pl-tree-node-content-expand-wrapper > .pl-tree-expand-icon { + & > .pl-tree-node-wrapper > .pl-tree-node-operator > .pl-tree-expand-icon { transform: rotate(90deg); } } &.pl-tree-node-drop-inner { - & > .pl-tree-node-content > .pl-tree-node-content-label { + & > .pl-tree-node-wrapper > .pl-tree-node-content { color: $colorPrimary; font-weight: bold; } @@ -824,7 +831,7 @@ .pl-icon { color: $icc; - + margin-right: 6px; &.pl-tree-expand-icon { transition: all $transition 300ms; } @@ -849,7 +856,7 @@ } &.pl-tree-highlight-current { - .pl-tree-node.pl-tree-node-current > .pl-tree-node-content { + .pl-tree-node.pl-tree-node-current > .pl-tree-node-wrapper { background-color: mix(white, $colorPrimary, 90%); } } -- Gitee From 6c4f0ce0a652311d3ea4718306f3259f475d90b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Thu, 2 Apr 2020 12:03:26 +0800 Subject: [PATCH 15/44] adjust tree style --- src/components/tree/pl-tree.vue | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/tree/pl-tree.vue b/src/components/tree/pl-tree.vue index 89b17317b..2fe526a9e 100644 --- a/src/components/tree/pl-tree.vue +++ b/src/components/tree/pl-tree.vue @@ -790,11 +790,11 @@ top: 0; left: 0; user-select: none; - .pl-tree-node-expander { height: 24px; - content: ''; + width: 18px; display: inline-block; + vertical-align: middle; } .pl-checkbox-indeterminate { @@ -832,6 +832,7 @@ .pl-icon { color: $icc; margin-right: 6px; + &.pl-tree-expand-icon { transition: all $transition 300ms; } -- Gitee From 059eae2cffbbfb80357adb97adefb5e163222c28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Thu, 2 Apr 2020 12:07:07 +0800 Subject: [PATCH 16/44] adjust tree style --- src/components/tree/pl-tree.vue | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/tree/pl-tree.vue b/src/components/tree/pl-tree.vue index 2fe526a9e..29f18fa99 100644 --- a/src/components/tree/pl-tree.vue +++ b/src/components/tree/pl-tree.vue @@ -231,7 +231,7 @@ } } - let label = e.currentTarget.querySelector('.pl-tree-node-content-label') + let label = e.currentTarget.querySelector('.pl-tree-node-content') let rect = label.getBoundingClientRect() if (!!rect) { @@ -258,7 +258,7 @@ if (treeNode.isExpand && !!treeNode.children && treeNode.children.length > 0) { // 节点已经展开,并且有子节点,表示插入到第一个子节点之前 let firstChildTreeNodeDom = e.currentTarget.querySelector('.pl-tree-node') - label = firstChildTreeNodeDom.querySelector('.pl-tree-node-content-label') + label = firstChildTreeNodeDom.querySelector('.pl-tree-node-content') rect = label.getBoundingClientRect() if (!!rect) { @@ -790,6 +790,7 @@ top: 0; left: 0; user-select: none; + .pl-tree-node-expander { height: 24px; width: 18px; -- Gitee From 542469c4da4b0a73ed8a9dfcbc857bfe2a6b1621 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Thu, 2 Apr 2020 14:15:36 +0800 Subject: [PATCH 17/44] =?UTF-8?q?=E5=BD=93=E5=89=8D=E6=98=AF=E5=90=A6?= =?UTF-8?q?=E5=B7=B2=E7=BB=8F=E5=88=9D=E5=A7=8B=E5=8C=96=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E8=8A=82=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/tree/pl-tree-node.vue | 21 +++++++-------------- src/components/tree/pl-tree.vue | 19 +++++++++++++------ src/components/tree/tree.ts | 14 +++++++++++++- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/components/tree/pl-tree-node.vue b/src/components/tree/pl-tree-node.vue index 215cb7634..27d0893a7 100644 --- a/src/components/tree/pl-tree-node.vue +++ b/src/components/tree/pl-tree-node.vue @@ -1,6 +1,4 @@ diff --git a/src/components/tree/pl-tree.vue b/src/components/tree/pl-tree.vue index 29f18fa99..f0f5e2688 100644 --- a/src/components/tree/pl-tree.vue +++ b/src/components/tree/pl-tree.vue @@ -231,14 +231,18 @@ } } - let label = e.currentTarget.querySelector('.pl-tree-node-content') - let rect = label.getBoundingClientRect() + let content = e.currentTarget.querySelector('.pl-tree-node-content') + let rect = content.getBoundingClientRect() if (!!rect) { + dragState.dropTreeNode = treeNode + let {height, width, left, top} = rect + width -= dragState.dropTreeNode.indicatorLeft + left += dragState.dropTreeNode.indicatorLeft + let deltaY = e.clientY - top - dragState.dropTreeNode = treeNode if (deltaY < height / 4) { // 上 @@ -258,8 +262,8 @@ if (treeNode.isExpand && !!treeNode.children && treeNode.children.length > 0) { // 节点已经展开,并且有子节点,表示插入到第一个子节点之前 let firstChildTreeNodeDom = e.currentTarget.querySelector('.pl-tree-node') - label = firstChildTreeNodeDom.querySelector('.pl-tree-node-content') - rect = label.getBoundingClientRect() + content = firstChildTreeNodeDom.querySelector('.pl-tree-node-content') + rect = content.getBoundingClientRect() if (!!rect) { dragState.dropTreeNode = firstChildTreeNodeDom.__vue__.treeNode @@ -268,6 +272,9 @@ left = rect.left top = rect.top + width -= dragState.dropTreeNode.indicatorLeft + left += dragState.dropTreeNode.indicatorLeft + dragState.dropType = DropType.prev dragState.show = true dragState.dropInnerKey = null @@ -817,7 +824,7 @@ } &.pl-tree-node-expand { - & > .pl-tree-node-wrapper > .pl-tree-node-operator > .pl-tree-expand-icon { + & > .pl-tree-node-wrapper > .pl-tree-node-operator > .pl-tree-node-expander > .pl-tree-expand-icon { transform: rotate(90deg); } } diff --git a/src/components/tree/tree.ts b/src/components/tree/tree.ts index 91eec54d0..35006d846 100644 --- a/src/components/tree/tree.ts +++ b/src/components/tree/tree.ts @@ -72,10 +72,22 @@ export class TreeNode { } } - get childrenData(){ + get isLoading(): boolean { + return this.context.getMark(this.key, TreeMark.loading) + } + + get childrenData() { return this.data[this.context.childrenField] || [] } + get indicatorLeft() { + let left = this.context.intent * (this.level - 1) + if (this.isLeaf && !this.isLoading) { + left += 18 + } + return left + } + setChildren(children: TreeNode[]) { this.context.$set(this.data, this.context.childrenField, children) } -- Gitee From 3cace1f4587b25a8afad2d1b9eebd2776baeed52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Thu, 2 Apr 2020 14:25:55 +0800 Subject: [PATCH 18/44] remove useless code --- src/components/tree/pl-tree-node.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/tree/pl-tree-node.vue b/src/components/tree/pl-tree-node.vue index 27d0893a7..a4dad7525 100644 --- a/src/components/tree/pl-tree-node.vue +++ b/src/components/tree/pl-tree-node.vue @@ -35,7 +35,7 @@ }] return ( -
  • +
  • @@ -71,7 +71,7 @@ {!this.treeNode.isLeaf && this.init &&
      {!!this.treeNode.children && this.treeNode.children.length > 0 ? - this.treeNode.children.map((item, index) => ) + this.treeNode.children.map((item, index) => ) :
    • -- Gitee From b4b81e176953c4eb05dfcbd20b56e16cba73ad94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Thu, 2 Apr 2020 14:26:18 +0800 Subject: [PATCH 19/44] =?UTF-8?q?virtual-tree=20=E5=A4=8D=E7=94=A8=20tree?= =?UTF-8?q?=20=E7=9A=84=E7=BB=93=E6=9E=84=E4=BB=A5=E5=8F=8A=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-doc/page/normal/virtual-tree.vue | 60 ++------------- .../virtual-tree/pl-virtual-tree-node.tsx | 73 ++++++++----------- .../virtual-tree/pl-virtual-tree.tsx | 10 ++- 3 files changed, 44 insertions(+), 99 deletions(-) diff --git a/src-doc/page/normal/virtual-tree.vue b/src-doc/page/normal/virtual-tree.vue index 80c5a5bcb..059e04bf9 100644 --- a/src-doc/page/normal/virtual-tree.vue +++ b/src-doc/page/normal/virtual-tree.vue @@ -13,12 +13,12 @@ - +
    @@ -106,54 +106,6 @@ \ No newline at end of file diff --git a/src/components/virtual-tree/pl-virtual-tree-node.tsx b/src/components/virtual-tree/pl-virtual-tree-node.tsx index d6ba31e57..91d16542a 100644 --- a/src/components/virtual-tree/pl-virtual-tree-node.tsx +++ b/src/components/virtual-tree/pl-virtual-tree-node.tsx @@ -14,53 +14,42 @@ export default { }, render(h) { return ( - -
    - { - this.isLoading ? - + +
    +
    + + { + this.treeNode.isLoading ? + + : + (!this.treeNode.isLeaf && this.plTree.onClickExpandIcon(e, this.treeNode)} class="pl-tree-expand-icon"/>) + } + + {!!this.plTree.showCheckbox && this.plTree.onClickCheckbox(e, this.treeNode)}}} + />} +
    +
    this.plTree.onClickNodeContent(this.treeNode)} style={this.contentStyles}> + {!!this.plTree.$scopedSlots.default ? + this.plTree.$scopedSlots.default(this.treeNode) : - (!this.treeNode.isLeaf && this.plTree.onClickExpandIcon(e, this.treeNode)} class="pl-tree-expand-icon"/>) - } -
    -
    this.plTree.onClickNodeContent(this.treeNode)}> - {this.treeNode.label} + (!!this.plTree.renderContent ? + this.plTree.renderContent(h, this.treeNode) + : + [ + !this.plTree.nodeIcon ? null : , + {this.treeNode.label} + ]) + } +
    ) }, computed: { - // @ts-ignore - classes() { - return [ - 'pl-virtual-tree-node', - { - 'pl-virtual-tree-node-expand': this.isExpand, - 'pl-virtual-tree-node-current': this.treeNode.key === this.plTree.p_currentKey - }, - // {'pl-virtual-tree-node-drop-inner': this.plTree.dragState.dropInnerKey === this.treeNode.key} - ] - }, - level() { - return this.treeNode.level - 1 - }, - expanderStyles() { - const paddingLeft: string = this.level * this.plTree.intent + 'px' - return { - paddingLeft - } - }, - contentStyles() { - let paddingLeft = 18 - if (this.plTree.showCheckbox) { - paddingLeft += 18 - } - paddingLeft += this.level * this.plTree.intent - return { - paddingLeft: paddingLeft + 'px' - } - }, - isExpand: OldTreeNode.computed.isExpand, - isLoading: OldTreeNode.computed.isLoading, + ...OldTreeNode.computed, }, } \ No newline at end of file diff --git a/src/components/virtual-tree/pl-virtual-tree.tsx b/src/components/virtual-tree/pl-virtual-tree.tsx index aa398cf19..f78b44766 100644 --- a/src/components/virtual-tree/pl-virtual-tree.tsx +++ b/src/components/virtual-tree/pl-virtual-tree.tsx @@ -5,7 +5,7 @@ import PlVirtualTreeNode from './pl-virtual-tree-node' const Tree = tree as any export default { - name: "pl-virtual-tree", + name: "pl-tree", components: {PlVirtualTreeNode}, mixins: Tree.mixins, emitters: Tree.emitters, @@ -24,6 +24,8 @@ export default { const mark: { [key: string]: TreeMark } = {} const formatCount: number = 0 const rootTreeNode: TreeNode = new TreeNode({}, this, 0) + + const dragState = {} return { p_data, p_loading, @@ -31,6 +33,8 @@ export default { mark, formatCount, rootTreeNode, + + dragState, } }, render(h) { @@ -41,12 +45,12 @@ export default { ) }, created() { - console.log(this.formatDataFlat) }, computed: { classes() { return [ - 'pl-virtual-tree', + 'pl-tree', + 'pl-tree-node-list', ] }, formatData: Tree.computed.formatData, -- Gitee From fe0669942f15d4ea1800d67df1723dc92760f60e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Thu, 2 Apr 2020 14:55:15 +0800 Subject: [PATCH 20/44] format code --- src/components/tree/pl-tree-node.vue | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/tree/pl-tree-node.vue b/src/components/tree/pl-tree-node.vue index a4dad7525..d2e3794b5 100644 --- a/src/components/tree/pl-tree-node.vue +++ b/src/components/tree/pl-tree-node.vue @@ -90,8 +90,11 @@ classes() { return [ 'pl-tree-node', - {'pl-tree-node-expand': this.isExpand, 'pl-tree-node-current': this.treeNode.key === this.plTree.p_currentKey}, - {'pl-tree-node-drop-inner': this.plTree.dragState.dropInnerKey === this.treeNode.key} + { + 'pl-tree-node-expand': this.isExpand, + 'pl-tree-node-current': this.treeNode.key === this.plTree.p_currentKey, + 'pl-tree-node-drop-inner': this.plTree.dragState.dropInnerKey === this.treeNode.key + }, ] }, /** -- Gitee From c33a407b26acca2fba0a9900578643b93e52a5ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Thu, 2 Apr 2020 14:55:33 +0800 Subject: [PATCH 21/44] =?UTF-8?q?virtual=20tree=20=E6=A0=B9=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E6=B2=A1=E6=9C=89=E6=95=B0=E6=8D=AE=E7=9A=84=E6=97=B6?= =?UTF-8?q?=E5=80=99=EF=BC=8C=E6=98=BE=E7=A4=BA=E6=97=A0=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=96=87=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-doc/page/normal/virtual-tree.vue | 195 ++++++++++++++++-- .../virtual-tree/pl-virtual-tree.tsx | 71 +++---- 2 files changed, 201 insertions(+), 65 deletions(-) diff --git a/src-doc/page/normal/virtual-tree.vue b/src-doc/page/normal/virtual-tree.vue index 059e04bf9..1d090ab98 100644 --- a/src-doc/page/normal/virtual-tree.vue +++ b/src-doc/page/normal/virtual-tree.vue @@ -3,23 +3,33 @@ - - - + - + + + + + +
    @@ -83,21 +93,161 @@ }] }] }] - const count = treeData.length return { + filterText: null, treeData, - count, + lazyDemo: { + isLeaf: (treeNode) => { + return treeNode.level >= 3 + }, + getChildren: (treeNode, resolve) => { + switch (treeNode.level) { + case 0: + // 加载一级数据 + this.lazyDemo.getCitiesByParentId(null).then(resolve) + break + case 1: + // 加载二级数据 + this.lazyDemo.getCitiesByParentId(treeNode.data.id).then(resolve) + break + case 2: + // 加载三级数据 + this.lazyDemo.getCitiesByParentId(treeNode.data.id).then(resolve) + break + default: + return null + } + }, + getCitiesByParentId(parentId) { + return new Promise((resolve) => { + // 这个是模拟在数据库表中的数据 + const data = [ + {id: '1', name: '广东省', parentId: null, subs: []}, + {id: '2', name: '佛山市', parentId: '1', subs: []}, + {id: '3', name: '深圳市', parentId: '1', subs: []}, + {id: '4', name: '禅城区', parentId: '2', subs: []}, + {id: '5', name: '南山区', parentId: '3', subs: []}, + + {id: '6', name: '湖南省', parentId: null, subs: []}, + {id: '7', name: '长沙市', parentId: '6', subs: []}, + {id: '8', name: '邵阳市', parentId: '6', subs: []}, + {id: '9', name: '天心区', parentId: '7', subs: []}, + + {id: '11', name: '陕西省', parentId: null, subs: []}, + ] + + // 模拟请求,请求时间大概在1s-2s之间 + setTimeout(() => { + resolve(data.filter(item => item.parentId === parentId)) + }, Math.random() * 1000 + 1000) + }) + }, + }, + scopedSlotDemo: { + treeData: this.$plain.utils.deepcopy(treeData), + renderContent: (h, data) => { + return ( +
    + {data.data.name}} + + { + e.stopPropagation(); + this.scopedSlotDemo.addItem(data) + }} size="mini"/> + { + e.stopPropagation(); + this.scopedSlotDemo.deleteItem(data) + }} size="mini" status="error"/> + +
    + ) + }, + addItem: (e, treeNode) => { + e.stopPropagation() + const {data} = treeNode + const subs = data.subs || [] + + const name = `n-${data.id}-${subs.length + 1}` + const id = name + Date.now().toString() + subs.push({ + id, + name: `new item ${name}`, + }) + this.$set(data, 'subs', subs) + this.$nextTick(() => this.$refs.scopedSlotDemo.expand(id)) + }, + deleteItem: (e, treeNode) => { + e.stopPropagation() + let {data, parent} = treeNode + const subs = !!parent ? parent.data.subs : this.treeData + subs.splice(subs.indexOf(data), 1) + }, + }, + renderDemo: { + treeData: this.$plain.utils.deepcopy(treeData), + renderContent: (h, data) => { + return ( +
    + {data.data.name} + + this.renderDemo.addItem(e, data)} size="mini"/> + this.renderDemo.deleteItem(e, data)} size="mini" status="error"/> + +
    + ) + }, + addItem: (e, treeNode) => { + e.stopPropagation() + const {data} = treeNode + const subs = data.subs || [] + + const name = `n-${data.id}-${subs.length + 1}` + const id = name + Date.now().toString() + subs.push({ + id, + name: `new item ${name}`, + }) + this.$set(data, 'subs', subs) + this.$nextTick(() => this.$refs.renderDemo.expand(id)) + }, + deleteItem: (e, treeNode) => { + e.stopPropagation() + let {data, parent} = treeNode + const subs = !!parent ? parent.data.subs : this.treeData + subs.splice(subs.indexOf(data), 1) + }, + }, + currentKey: null, } }, methods: { - add() { - this.treeData.push({ - id: ++this.count, - name: `一级 ${this.count}`, - }) + onNodeClick(treeNode) { + console.log(treeNode.data.name) }, - remove() { - this.treeData.pop() + showCurrent() { + let current = this.$refs.tree1.getCurrent() + this.$message(!!current ? current.data.name : '未选中任何节点!') + }, + expandAndSelect() { + this.$refs.tree1.expand('2-2-2') + this.$refs.tree1.setCurrent('2-2-2') + }, + async expandSome() { + // console.log('start') + await this.$refs.tree1.expand(['2-2-2', '3-1-2']) + // console.log('end') + console.log(Array.from(this.$el.querySelectorAll('.pl-tree-node')).length) + }, + filterNodeMethod(treeNode) { + const data = treeNode.data + if (!this.filterText) return true; + return data.name.indexOf(this.filterText) !== -1; + }, + isCheckable(treeNode) { + return treeNode.label.endsWith('1') + }, + nodeIcon(treeNode) { + return treeNode.isLeaf ? 'el-icon-document' : 'el-icon-folder-opened' }, }, } @@ -106,6 +256,11 @@ \ No newline at end of file diff --git a/src/components/virtual-tree/pl-virtual-tree.tsx b/src/components/virtual-tree/pl-virtual-tree.tsx index f78b44766..ad9712a65 100644 --- a/src/components/virtual-tree/pl-virtual-tree.tsx +++ b/src/components/virtual-tree/pl-virtual-tree.tsx @@ -5,18 +5,18 @@ import PlVirtualTreeNode from './pl-virtual-tree-node' const Tree = tree as any export default { - name: "pl-tree", + name: "pl-virtual-tree", components: {PlVirtualTreeNode}, mixins: Tree.mixins, - emitters: Tree.emitters, - props: { - ...Tree.props, - }, provide() { return { plTree: this, } }, + props: { + ...Tree.props, + }, + emitters: Tree.emitters, data() { const p_data: any[] = this.data const p_currentKey: string = null @@ -37,23 +37,39 @@ export default { dragState, } }, + watch: Tree.watch, + created: Tree.created, + mounted() { + }, render(h) { + const directives = [{name: 'loading', value: this.isLoading}] + return ( - + {this.formatDataFlat.map((item) => )} + {(!this.formatDataFlat || this.formatDataFlat.length === 0) && ( +
  • + + {this.emptyText} +
  • + )} + {!!this.draggable && }
    ) }, - created() { - }, computed: { + ...Tree.computed, classes() { return [ 'pl-tree', 'pl-tree-node-list', + 'pl-virtual-tree', + { + 'pl-tree-highlight-current': this.highlightCurrent, + 'pl-tree-reflow': this.dragState.reflow, + } ] }, - formatData: Tree.computed.formatData, /** * formatData偏平格式化 * @author 韦胜健 @@ -71,41 +87,6 @@ export default { }, }, methods: { - - /*---------------------------------------methods-------------------------------------------*/ - /*current*/ - setCurrent: Tree.methods.setCurrent, - getCurrent: Tree.methods.getCurrent, - /*expand*/ - expand: Tree.methods.expand, - collapse: Tree.methods.collapse, - toggleExpand: Tree.methods.toggleExpand, - expandAll: Tree.methods.expandAll, - collapseAll: Tree.methods.collapseAll, - /*check*/ - check: Tree.methods.check, - uncheck: Tree.methods.uncheck, - toggleCheck: Tree.methods.toggleCheck, - checkAll: Tree.methods.checkAll, - uncheckAll: Tree.methods.uncheckAll, - getCheckedData: Tree.methods.getCheckedData, - - /*---------------------------------------utils-------------------------------------------*/ - setMark: Tree.methods.setMark, - getMark: Tree.methods.getMark, - iterateAll: Tree.methods.iterateAll, - checkProps: Tree.methods.checkProps, - formatNodeData: Tree.methods.formatNodeData, - findTreeNodeByKey: Tree.methods.findTreeNodeByKey, - getChildrenAsync: Tree.methods.getChildrenAsync, - handleKeys: Tree.methods.handleKeys, - - /*---------------------------------------helper-------------------------------------------*/ - initLazy: Tree.methods.initLazy, - - /*---------------------------------------handler-------------------------------------------*/ - onClickExpandIcon: Tree.methods.onClickExpandIcon, - onClickNodeContent: Tree.methods.onClickNodeContent, - onClickCheckbox: Tree.methods.onClickCheckbox, + ...Tree.methods, }, } \ No newline at end of file -- Gitee From ab85d89372fb834b17c39e78add75cc65204ab3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Thu, 2 Apr 2020 14:58:35 +0800 Subject: [PATCH 22/44] adjust tree style --- src/components/tree/pl-tree.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/tree/pl-tree.vue b/src/components/tree/pl-tree.vue index f0f5e2688..99af5728f 100644 --- a/src/components/tree/pl-tree.vue +++ b/src/components/tree/pl-tree.vue @@ -802,7 +802,7 @@ height: 24px; width: 18px; display: inline-block; - vertical-align: middle; + vertical-align: top; } .pl-checkbox-indeterminate { -- Gitee From 4d6d019a9c1d0732b481849fc1cdc0c62d3a9dbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Thu, 2 Apr 2020 15:01:58 +0800 Subject: [PATCH 23/44] =?UTF-8?q?=E5=8F=B6=E5=AD=90=E8=8A=82=E7=82=B9?= =?UTF-8?q?=E4=B8=8D=E8=83=BD=E5=B1=95=E5=BC=80=E6=94=B6=E8=B5=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/tree/pl-tree.vue | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/tree/pl-tree.vue b/src/components/tree/pl-tree.vue index 99af5728f..951e4e8ca 100644 --- a/src/components/tree/pl-tree.vue +++ b/src/components/tree/pl-tree.vue @@ -421,6 +421,7 @@ await this.handleKeys(keys, async (key: string) => { const treeNode = this.findTreeNodeByKey(key) if (!treeNode) return + if (treeNode.isLeaf) return if (!treeNode.isExpand) { if ( @@ -460,6 +461,7 @@ await this.handleKeys(keys, async (key: string) => { const treeNode = this.findTreeNodeByKey(key) if (!treeNode) return + if (treeNode.isLeaf) return if (treeNode.isExpand) { this.setMark(treeNode.key, TreeMark.expanded, false) await this.$plain.nextTick() -- Gitee From bac6e2523601a64bd2c145ed63064d6624e03ab0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Thu, 2 Apr 2020 15:08:03 +0800 Subject: [PATCH 24/44] remove useless code --- src/components/tree/pl-tree.vue | 4 +--- src/components/tree/tree.ts | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/components/tree/pl-tree.vue b/src/components/tree/pl-tree.vue index 951e4e8ca..81c6b9a2c 100644 --- a/src/components/tree/pl-tree.vue +++ b/src/components/tree/pl-tree.vue @@ -673,9 +673,7 @@ const treeNode = new TreeNode(data, this, level, parent) this.setMark(treeNode.key, TreeMark.treeNode, treeNode) this.setMark(treeNode.key, TreeMark.formatCount, formatCount) - if (!!treeNode.children) { - treeNode.children = treeNode.children.map(child => this.formatNodeData(child, formatCount, treeNode, level + 1)) - } + treeNode.children = treeNode.childrenData.map(child => this.formatNodeData(child, formatCount, treeNode, level + 1)) return treeNode }, /** diff --git a/src/components/tree/tree.ts b/src/components/tree/tree.ts index 35006d846..03b36b93a 100644 --- a/src/components/tree/tree.ts +++ b/src/components/tree/tree.ts @@ -13,10 +13,9 @@ export class TreeNode { droppable: boolean; // 是否可放置*/ constructor(public data: object, public context: any, public level: number, public parent?: TreeNode | null) { - const {keyField, labelField, childrenField} = context + const {keyField, labelField} = context this.key = !!keyField ? data[keyField] : undefined this.label = !!labelField ? data[labelField] : undefined - this.children = !!childrenField ? data[childrenField] : undefined } get isExpand(): boolean { -- Gitee From 561121347520e86c556a434da8ce3964e6d6f518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Thu, 2 Apr 2020 15:20:39 +0800 Subject: [PATCH 25/44] =?UTF-8?q?=E4=B8=8D=E5=A5=BD=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E8=8A=82=E7=82=B9=E6=98=AF=E4=B8=8D=E6=98=AF?= =?UTF-8?q?=E5=8F=B6=E5=AD=90=E8=8A=82=E7=82=B9=EF=BC=8C=E8=99=BD=E7=84=B6?= =?UTF-8?q?=E5=A6=82=E6=9E=9C=E6=98=AF=E5=8F=B6=E5=AD=90=E8=8A=82=E7=82=B9?= =?UTF-8?q?=E5=B0=B1=E4=B8=8D=E5=B1=95=E5=BC=80=E6=88=96=E8=80=85=E6=94=B6?= =?UTF-8?q?=E8=B5=B7=EF=BC=8C=E4=BD=86=E6=98=AF=E8=BF=99=E6=A0=B7=E4=BC=9A?= =?UTF-8?q?=E5=BD=B1=E5=93=8D=E7=94=A8=E6=B3=95=EF=BC=8C=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=8A=82=E7=82=B9=E4=B9=8B=E5=90=8E=EF=BC=8C?= =?UTF-8?q?=E9=83=A8=E5=88=86=E8=8A=82=E7=82=B9=E4=BC=9A=E5=8F=98=E6=88=90?= =?UTF-8?q?=E9=9D=9E=E5=8F=B6=E5=AD=90=E8=8A=82=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/tree/pl-tree.vue | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/tree/pl-tree.vue b/src/components/tree/pl-tree.vue index 81c6b9a2c..ea9fd4018 100644 --- a/src/components/tree/pl-tree.vue +++ b/src/components/tree/pl-tree.vue @@ -421,7 +421,6 @@ await this.handleKeys(keys, async (key: string) => { const treeNode = this.findTreeNodeByKey(key) if (!treeNode) return - if (treeNode.isLeaf) return if (!treeNode.isExpand) { if ( @@ -461,7 +460,6 @@ await this.handleKeys(keys, async (key: string) => { const treeNode = this.findTreeNodeByKey(key) if (!treeNode) return - if (treeNode.isLeaf) return if (treeNode.isExpand) { this.setMark(treeNode.key, TreeMark.expanded, false) await this.$plain.nextTick() -- Gitee From e1201737d7329841ea3e0eb930755ca7269fca16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Thu, 2 Apr 2020 15:43:41 +0800 Subject: [PATCH 26/44] =?UTF-8?q?virtual=20tree=20=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E5=9F=BA=E6=9C=AC=E5=8A=9F=E8=83=BD=E5=AE=8C=E6=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-doc/page/normal/virtual-tree.vue | 188 +++++++++++++++++- src/components/tree/pl-tree.vue | 26 ++- .../virtual-tree/pl-virtual-tree-node.tsx | 9 +- .../virtual-tree/pl-virtual-tree.tsx | 25 +-- 4 files changed, 218 insertions(+), 30 deletions(-) diff --git a/src-doc/page/normal/virtual-tree.vue b/src-doc/page/normal/virtual-tree.vue index 1d090ab98..3c441308e 100644 --- a/src-doc/page/normal/virtual-tree.vue +++ b/src-doc/page/normal/virtual-tree.vue @@ -12,7 +12,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{currentKey}} + + + + + + + + + + + + + + + + + diff --git a/src/components/tree/pl-tree.vue b/src/components/tree/pl-tree.vue index ea9fd4018..42e434775 100644 --- a/src/components/tree/pl-tree.vue +++ b/src/components/tree/pl-tree.vue @@ -160,11 +160,10 @@ dragstart: (e) => { e.stopPropagation() e.dataTransfer.effectAllowed = 'move' - dragState.dragTreeNode = e.currentTarget.__vue__.treeNode + dragState.dragTreeNode = this.getTreeNodeFromEl(e.currentTarget) }, dragend: (e) => { e.stopPropagation() - console.log('被拖拽的节点', e.currentTarget.__vue__.treeNode.label) dragState.show = false dragState.dropInnerKey = null @@ -203,7 +202,7 @@ e.preventDefault() e.dataTransfer.dropEffect = 'move' - const treeNode = e.currentTarget.__vue__.treeNode + const treeNode = this.getTreeNodeFromEl(e.currentTarget) let doNothing = () => { e.dataTransfer.dropEffect = 'none' @@ -261,12 +260,21 @@ // 下 if (treeNode.isExpand && !!treeNode.children && treeNode.children.length > 0) { // 节点已经展开,并且有子节点,表示插入到第一个子节点之前 - let firstChildTreeNodeDom = e.currentTarget.querySelector('.pl-tree-node') + let firstChildTreeNodeDom = undefined + + if (this.$options.name === 'pl-tree') { + firstChildTreeNodeDom = e.currentTarget.querySelector('.pl-tree-node') + } else if (this.$options.name === 'pl-virtual-tree') { + firstChildTreeNodeDom = e.currentTarget.nextSibling + } else { + console.warn(`can't recognise ${this.$options.name}`) + return doNothing + } + content = firstChildTreeNodeDom.querySelector('.pl-tree-node-content') rect = content.getBoundingClientRect() if (!!rect) { - - dragState.dropTreeNode = firstChildTreeNodeDom.__vue__.treeNode + dragState.dropTreeNode = this.getTreeNodeFromEl(firstChildTreeNodeDom) width = rect.width left = rect.left @@ -718,6 +726,12 @@ keys = Array.isArray(keys) ? keys : [keys] return await Promise.all(keys.map(handler)) }, + getTreeNodeFromEl(el: any) { + const instance = el.__vue__ + if (!!instance.treeNode) return instance.treeNode + if (!!instance.$parent && !!instance.$parent.treeNode) return instance.$parent.treeNode + return null + }, /*---------------------------------------helper-------------------------------------------*/ async initLazy() { diff --git a/src/components/virtual-tree/pl-virtual-tree-node.tsx b/src/components/virtual-tree/pl-virtual-tree-node.tsx index 91d16542a..85fd4423f 100644 --- a/src/components/virtual-tree/pl-virtual-tree-node.tsx +++ b/src/components/virtual-tree/pl-virtual-tree-node.tsx @@ -13,8 +13,15 @@ export default { return {} }, render(h) { + const nodeOn = { + ...(!!this.plTree.draggable ? { + dragstart: this.plTree.dragState.dragstart, + dragend: this.plTree.dragState.dragend, + dragover: this.plTree.dragState.dragover, + } : {}) + } return ( - +
    diff --git a/src/components/virtual-tree/pl-virtual-tree.tsx b/src/components/virtual-tree/pl-virtual-tree.tsx index ad9712a65..e1a33f676 100644 --- a/src/components/virtual-tree/pl-virtual-tree.tsx +++ b/src/components/virtual-tree/pl-virtual-tree.tsx @@ -1,5 +1,5 @@ import tree from '../tree/pl-tree.vue' -import {TreeMark, TreeNode} from "../tree/tree"; +import {TreeNode} from "../tree/tree"; import PlVirtualTreeNode from './pl-virtual-tree-node' const Tree = tree as any @@ -17,26 +17,7 @@ export default { ...Tree.props, }, emitters: Tree.emitters, - data() { - const p_data: any[] = this.data - const p_currentKey: string = null - const p_loading: boolean = false - const mark: { [key: string]: TreeMark } = {} - const formatCount: number = 0 - const rootTreeNode: TreeNode = new TreeNode({}, this, 0) - - const dragState = {} - return { - p_data, - p_loading, - p_currentKey, - mark, - formatCount, - rootTreeNode, - - dragState, - } - }, + data: Tree.data, watch: Tree.watch, created: Tree.created, mounted() { @@ -83,7 +64,7 @@ export default { }, (treeNode: TreeNode) => { return treeNode.isExpand === true }) - return formatDataFlat + return formatDataFlat.filter((treeNode: TreeNode) => !!treeNode.isVisible) }, }, methods: { -- Gitee From aaa3429512a6ce701942faba5b70b450470f6095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Thu, 2 Apr 2020 16:18:37 +0800 Subject: [PATCH 27/44] =?UTF-8?q?virtual=20tree=20=E5=A5=97=E7=94=A8=20vir?= =?UTF-8?q?tual=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../virtual-list/pl-virtual-list.vue | 26 ++++++------ src/components/virtual-tree/index.js | 5 ++- .../virtual-tree/pl-virtual-tree-node.tsx | 1 + .../virtual-tree/pl-virtual-tree.tsx | 40 +++++++++---------- 4 files changed, 37 insertions(+), 35 deletions(-) diff --git a/src/components/virtual-list/pl-virtual-list.vue b/src/components/virtual-list/pl-virtual-list.vue index dfea8a92e..80637a9ce 100644 --- a/src/components/virtual-list/pl-virtual-list.vue +++ b/src/components/virtual-list/pl-virtual-list.vue @@ -1,15 +1,3 @@ - - + + \ No newline at end of file diff --git a/src-doc/page/normal/virtual-tree.vue b/src-doc/page/normal/virtual-tree.vue index 3c441308e..8eef04c2b 100644 --- a/src-doc/page/normal/virtual-tree.vue +++ b/src-doc/page/normal/virtual-tree.vue @@ -41,13 +41,13 @@ + showCheckbox + checkOnClickNode + :expandOnClickNode="false" + :data="treeData" + keyField="id" + labelField="name" + childrenField="subs"/> @@ -61,14 +61,14 @@ + showCheckbox + checkOnClickNode + :expandOnClickNode="false" + checkStrictly + :data="treeData" + keyField="id" + labelField="name" + childrenField="subs"/> @@ -82,15 +82,15 @@ + showCheckbox + checkOnClickNode + :expandOnClickNode="false" + :data="treeData" + checkStrictly + keyField="id" + labelField="name" + childrenField="subs" + :isCheckable="isCheckable"/> @@ -105,12 +105,12 @@ + :data="scopedSlotDemo.treeData" + keyField="id" + labelField="name" + childrenField="subs" + style="width: 500px" + showCheckbox> diff --git a/src/components/virtual-tree/pl-virtual-tree-node.tsx b/src/components/virtual-tree/pl-virtual-tree-node.tsx index b90d68329..7998e4f26 100644 --- a/src/components/virtual-tree/pl-virtual-tree-node.tsx +++ b/src/components/virtual-tree/pl-virtual-tree-node.tsx @@ -1,18 +1,8 @@ import PlTreeNode from '../tree/pl-tree-node.vue' -const OldTreeNode = PlTreeNode as any - export default { name: 'pl-virtual-tree-node', - props: { - treeNode: {type: Object}, - }, - inject: { - plTree: {}, - }, - data() { - return {} - }, + mixins: [PlTreeNode], render(h) { const nodeOn = { ...(!!this.plTree.draggable ? { @@ -23,41 +13,8 @@ export default { } return ( -
    -
    - - { - this.treeNode.isLoading ? - - : - (!this.treeNode.isLeaf && this.plTree.onClickExpandIcon(e, this.treeNode)} class="pl-tree-expand-icon"/>) - } - - {!!this.plTree.showCheckbox && this.plTree.onClickCheckbox(e, this.treeNode)}}} - />} -
    -
    this.plTree.onClickNodeContent(this.treeNode)} style={this.contentStyles}> - {!!this.plTree.$scopedSlots.default ? - this.plTree.$scopedSlots.default(this.treeNode) - : - (!!this.plTree.renderContent ? - this.plTree.renderContent(h, this.treeNode) - : - [ - !this.plTree.nodeIcon ? null : , - {this.treeNode.label} - ]) - } -
    -
    + {this.getTreeNodeWrapper(h)}
    ) }, - computed: { - ...OldTreeNode.computed, - }, } \ No newline at end of file -- Gitee From eb98dbcb9e88535e36d829a7f094aa6e42ec0097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Thu, 2 Apr 2020 19:58:56 +0800 Subject: [PATCH 39/44] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=8B=96=E6=8B=BD?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/tree/pl-tree.vue | 4 ++-- src/components/tree/tree.ts | 24 +++++++++++++++--------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/components/tree/pl-tree.vue b/src/components/tree/pl-tree.vue index d412ff0cb..8a7d09097 100644 --- a/src/components/tree/pl-tree.vue +++ b/src/components/tree/pl-tree.vue @@ -173,7 +173,7 @@ if (!!dropTreeNode) { dragTreeNode.removeSelf() - const dropRelativeData = dropTreeNode.parent.childrenData || [] + const dropRelativeData = dropTreeNode.parent.childrenData dragState.reflow = true switch (dropType) { @@ -681,7 +681,7 @@ const treeNode = new TreeNode(data, this, level, parent) this.setMark(treeNode.key, TreeMark.treeNode, treeNode) this.setMark(treeNode.key, TreeMark.formatCount, formatCount) - treeNode.children = treeNode.childrenData.map(child => this.formatNodeData(child, formatCount, treeNode, level + 1)) + treeNode.children = (treeNode.childrenData || []).map(child => this.formatNodeData(child, formatCount, treeNode, level + 1)) return treeNode }, /** diff --git a/src/components/tree/tree.ts b/src/components/tree/tree.ts index 03b36b93a..41b9236ab 100644 --- a/src/components/tree/tree.ts +++ b/src/components/tree/tree.ts @@ -76,7 +76,7 @@ export class TreeNode { } get childrenData() { - return this.data[this.context.childrenField] || [] + return this.data[this.context.childrenField] } get indicatorLeft() { @@ -92,21 +92,27 @@ export class TreeNode { } removeSelf() { - const childrenData = this.parent.data[this.context.childrenField] - childrenData.splice(childrenData.indexOf(this.data), 1) + const parentChildrenData = this.parent.childrenData + parentChildrenData.splice(parentChildrenData.indexOf(this.data), 1) } splice(index, count, replace) { - const childrenData = this.parent.childrenData || [] - let ret = childrenData.splice(index, count, replace) - this.parent.data[this.context.childrenField] = childrenData - return ret + let parentChildrenData = this.parent.childrenData + + if (!parentChildrenData) { + parentChildrenData = [] + this.parent.setChildren(parentChildrenData) + } + return parentChildrenData.splice(index, count, replace) } push(data) { - const childrenData = this.childrenData || [] + let childrenData = this.childrenData + if (!childrenData) { + childrenData = [] + this.setChildren(childrenData) + } childrenData.push(data) - this.data[this.context.childrenField] = childrenData } } -- Gitee From 7cd1b0ff80c33d1e90e839a0df3370e05c5ffa59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Thu, 2 Apr 2020 20:03:23 +0800 Subject: [PATCH 40/44] add step --- src-doc/menus.js | 2 +- src-doc/page/normal/step.vue | 23 +++++++++++++++++++++++ src/components/index.js | 3 ++- src/components/step/index.js | 4 ++++ src/components/step/pl-step.vue | 19 +++++++++++++++++++ 5 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 src-doc/page/normal/step.vue create mode 100644 src/components/step/index.js create mode 100644 src/components/step/pl-step.vue diff --git a/src-doc/menus.js b/src-doc/menus.js index cb41732a0..51c2ab5be 100644 --- a/src-doc/menus.js +++ b/src-doc/menus.js @@ -50,7 +50,7 @@ export default [ {name: 'Pagination', title: '分页', icon: 'pl-book2', page: '/normal/pagination', complete: true}, {name: 'Badge', title: '标记', icon: 'pl-badge', page: '/normal/badge', complete: true}, {name: 'ScrollOption', title: '滚动选择', icon: 'icon-scroll', page: '/normal/scroll-option', complete: false}, - {name: 'Step', title: '步骤条', icon: 'pl-step', page: '/normal/step', complete: false}, + {name: 'Step', title: '步骤条', icon: 'pl-step', page: '/normal/step', complete: true}, {name: 'Transform', title: '穿梭框', icon: 'pl-exchange', page: '/normal/transform', complete: false}, ] }, diff --git a/src-doc/page/normal/step.vue b/src-doc/page/normal/step.vue new file mode 100644 index 000000000..cd44a3054 --- /dev/null +++ b/src-doc/page/normal/step.vue @@ -0,0 +1,23 @@ + + + + + \ No newline at end of file diff --git a/src/components/index.js b/src/components/index.js index 4f75e851d..115a1403b 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -31,13 +31,14 @@ import badge from './badge' import pagination from './pagination' import tree from './tree' import virtualTree from './virtual-tree' +import step from './step' const plugins = [ button, icon, input, checkbox, radio, select, form, toggle, number, slider, tag, rate, loading, popper, popover, tooltip, dropdown, message, dialog, notice, - list, scroll, dom, collapse, card, carousel, grid, progress, badge, pagination, tree, virtualTree, + list, scroll, dom, collapse, card, carousel, grid, progress, badge, pagination, tree, virtualTree, step, virtualList, ] diff --git a/src/components/step/index.js b/src/components/step/index.js new file mode 100644 index 000000000..9201a6fcf --- /dev/null +++ b/src/components/step/index.js @@ -0,0 +1,4 @@ +import component from './pl-step.vue' +import {plugin} from "../../utils"; + +export default plugin(component) \ No newline at end of file diff --git a/src/components/step/pl-step.vue b/src/components/step/pl-step.vue new file mode 100644 index 000000000..ce2380d1c --- /dev/null +++ b/src/components/step/pl-step.vue @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file -- Gitee From eff7494b07ad2e53e9f45a732fcb25ae8d8ff0d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Thu, 2 Apr 2020 20:21:53 +0800 Subject: [PATCH 41/44] is not support startsWidth --- src-doc/page/normal/tree.vue | 2 +- src-doc/page/normal/virtual-tree.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src-doc/page/normal/tree.vue b/src-doc/page/normal/tree.vue index 385ed67e5..bf41e2973 100644 --- a/src-doc/page/normal/tree.vue +++ b/src-doc/page/normal/tree.vue @@ -217,7 +217,7 @@ showCheckbox >
    diff --git a/src-doc/page/normal/virtual-tree.vue b/src-doc/page/normal/virtual-tree.vue index 5fca4c244..a8b3fb3e2 100644 --- a/src-doc/page/normal/virtual-tree.vue +++ b/src-doc/page/normal/virtual-tree.vue @@ -211,7 +211,7 @@ showCheckbox >
    -- Gitee From 336187f9789cfcc1a01f4330dd8f87210e99dcc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Thu, 2 Apr 2020 20:45:35 +0800 Subject: [PATCH 42/44] add test canvas --- src-doc/menus.js | 2 ++ src-doc/page/test/test-canvas.vue | 21 +++++++++++++++ src-doc/page/test/test-svg.vue | 44 +++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 src-doc/page/test/test-canvas.vue create mode 100644 src-doc/page/test/test-svg.vue diff --git a/src-doc/menus.js b/src-doc/menus.js index 51c2ab5be..8280e0b47 100644 --- a/src-doc/menus.js +++ b/src-doc/menus.js @@ -107,6 +107,8 @@ export default [ name: '其他', children: [ {name: 'Test', title: '测试手动渲染实例', icon: 'pl-table-solid', page: '/normal/test', complete: true}, {name: 'Drag', title: '测试拖拽节点', icon: 'pl-table-solid', page: '/test/test-drag', complete: true}, + {name: 'Svg', title: '测试svg', icon: 'pl-table-solid', page: '/test/test-svg', complete: true}, + {name: 'Canvas', title: '测试canvas', icon: 'pl-table-solid', page: '/test/test-canvas', complete: true}, ] }, ] \ No newline at end of file diff --git a/src-doc/page/test/test-canvas.vue b/src-doc/page/test/test-canvas.vue new file mode 100644 index 000000000..7f94dfa1b --- /dev/null +++ b/src-doc/page/test/test-canvas.vue @@ -0,0 +1,21 @@ + + + + + \ No newline at end of file diff --git a/src-doc/page/test/test-svg.vue b/src-doc/page/test/test-svg.vue new file mode 100644 index 000000000..c6a2f00e5 --- /dev/null +++ b/src-doc/page/test/test-svg.vue @@ -0,0 +1,44 @@ + + + + + \ No newline at end of file -- Gitee From 7a12c3a3412cbf029bb6be541a0728663b8219c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=83=9C=E5=81=A5?= Date: Thu, 2 Apr 2020 21:26:22 +0800 Subject: [PATCH 43/44] add test canvas --- src-doc/page/test/test-canvas.vue | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src-doc/page/test/test-canvas.vue b/src-doc/page/test/test-canvas.vue index 7f94dfa1b..d80913e2b 100644 --- a/src-doc/page/test/test-canvas.vue +++ b/src-doc/page/test/test-canvas.vue @@ -1,7 +1,7 @@ @@ -14,8 +14,28 @@ return {} }, methods: {}, + mounted() { + const canvas = this.$refs.canvas + const ctx = canvas.getContext('2d'); + + ctx.beginPath(); + ctx.moveTo(0, 0); + ctx.lineTo(200,0); + ctx.lineTo(300, 100); + ctx.lineTo(200, 200); + ctx.lineTo(0, 200); + ctx.lineTo(100, 100); + ctx.fill(); + } } \ No newline at end of file -- Gitee From 02069cf3b9dae271e7da5d657d13131c3b9115ca Mon Sep 17 00:00:00 2001 From: martsforever Date: Fri, 3 Apr 2020 00:21:16 +0800 Subject: [PATCH 44/44] =?UTF-8?q?=E6=A0=91=E8=8A=82=E7=82=B9=E6=98=AF?= =?UTF-8?q?=E5=90=A6=E5=8F=AF=E6=8B=96=E6=8B=BD=E4=BB=A5=E5=8F=8A=E6=98=AF?= =?UTF-8?q?=E5=90=A6=E5=8F=AF=E6=94=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-doc/page/normal/tree.vue | 48 +++++ src-doc/page/normal/virtual-tree.vue | 257 +++++---------------------- src/components/tree/pl-tree.vue | 103 +++++++++-- src/components/tree/tree.ts | 32 ++++ 4 files changed, 211 insertions(+), 229 deletions(-) diff --git a/src-doc/page/normal/tree.vue b/src-doc/page/normal/tree.vue index bf41e2973..b546770ac 100644 --- a/src-doc/page/normal/tree.vue +++ b/src-doc/page/normal/tree.vue @@ -222,6 +222,46 @@ + + + + + + +
      +
    1. 父子关联模式下,拖拽节点可能会引起 选中/取消选中 事件
    2. +
    3. 拖拽节点会刷新节点的状态,每个节点会先判断子节点是否全都选中,全部选中并且自身未选中的情况下,会选中自身
    4. +
    5. 自身选中,但是存在子节点未选中的情况下,会取消选中自身
    6. +
    7. 非父子关联模式下,拖拽节点不会导致节点选中状态变化
    8. +
    + +
    + + +
      +
    1. 2-2开头的id不能被拖拽
    2. +
    3. 3开头的id不能放置任何节点
    4. +
    + +
    @@ -441,6 +481,14 @@ nodeIcon(treeNode) { return treeNode.isLeaf ? 'el-icon-document' : 'el-icon-folder-opened' }, + allowDrag(dragTreeNode, event) { + // 2-2开头的id不能被拖拽 + return !dragTreeNode.data.id.startsWith('2-2') + }, + allowDrop(dragTreeNode, dropTreeNode, dragType, event) { + // 3-开头的id不能放置任何节点 + return !dropTreeNode.data.id.startsWith('3') + }, }, } diff --git a/src-doc/page/normal/virtual-tree.vue b/src-doc/page/normal/virtual-tree.vue index a8b3fb3e2..f9bd4c3dc 100644 --- a/src-doc/page/normal/virtual-tree.vue +++ b/src-doc/page/normal/virtual-tree.vue @@ -216,6 +216,47 @@ + + + + + + +
      +
    1. 父子关联模式下,拖拽节点可能会引起 选中/取消选中 事件
    2. +
    3. 拖拽节点会刷新节点的状态,每个节点会先判断子节点是否全都选中,全部选中并且自身未选中的情况下,会选中自身
    4. +
    5. 自身选中,但是存在子节点未选中的情况下,会取消选中自身
    6. +
    7. 非父子关联模式下,拖拽节点不会导致节点选中状态变化
    8. +
    + +
    + + +
      +
    1. 2-2开头的id不能被拖拽
    2. +
    3. 3开头的id不能放置任何节点
    4. +
    + +
    + @@ -224,224 +265,12 @@ diff --git a/src/components/tree/pl-tree.vue b/src/components/tree/pl-tree.vue index 8a7d09097..97cd9a88c 100644 --- a/src/components/tree/pl-tree.vue +++ b/src/components/tree/pl-tree.vue @@ -76,8 +76,8 @@ // 拖拽属性 draggable: {type: Boolean}, // 是否可拖拽 - isDraggable: {type: Function}, // 判断节点是否可以拖拽 - isDroppable: {type: Function}, // 判断目标节点能够被放置 + allowDrag: {type: Function}, // 判断节点是否可以拖拽 + allowDrop: {type: Function}, // 判断目标节点能够被放置 }, emitters: { emitNodeClick: Function, @@ -160,7 +160,15 @@ dragstart: (e) => { e.stopPropagation() e.dataTransfer.effectAllowed = 'move' - dragState.dragTreeNode = this.getTreeNodeFromEl(e.currentTarget) + + const dragTreeNode = this.getTreeNodeFromEl(e.currentTarget) + + if (!this.isAllowDrag(dragTreeNode, e)) { + e.preventDefault() + return + } + + dragState.dragTreeNode = dragTreeNode }, dragend: (e) => { e.stopPropagation() @@ -193,6 +201,7 @@ // console.log(`无任何变化`) break } + this.refreshCheckStatus() setTimeout(() => dragState.reflow = false, 100) } }, @@ -204,7 +213,7 @@ const treeNode = this.getTreeNodeFromEl(e.currentTarget) - let doNothing = () => { + let nothing = () => { e.dataTransfer.dropEffect = 'none' dragState.show = false dragState.dropInnerKey = null @@ -215,7 +224,7 @@ // 如果当前 over 的节点为拖拽节点的子节点,则什么事也不干,清空标记信息并且什么也不做 if (treeNode === dragState.dragTreeNode) { - doNothing() + nothing() return; } else { let containsFlag = false @@ -225,7 +234,7 @@ } }) if (containsFlag) { - doNothing() + nothing() return; } } @@ -241,16 +250,23 @@ left += dragState.dropTreeNode.indicatorLeft let deltaY = e.clientY - top + let allowDrop; if (deltaY < height / 4) { // 上 + allowDrop = this.isAllowDrop(dragState.dragTreeNode, dragState.dropTreeNode, DropType.prev, e) + if (!allowDrop) return nothing() + dragState.dropType = DropType.prev dragState.show = true dragState.dropInnerKey = null dragState.indicatorStyles = {top, width, left} } else if (deltaY < height * (3 / 4)) { // 中 + allowDrop = this.isAllowDrop(dragState.dragTreeNode, dragState.dropTreeNode, DropType.inner, e) + if (!allowDrop) return nothing() + dragState.dropType = DropType.inner dragState.show = false dragState.indicatorStyles = {} @@ -258,6 +274,9 @@ } else { // 下 + allowDrop = this.isAllowDrop(dragState.dragTreeNode, dragState.dropTreeNode, DropType.next, e) + if (!allowDrop) return nothing() + if (treeNode.isExpand && !!treeNode.children && treeNode.children.length > 0) { // 节点已经展开,并且有子节点,表示插入到第一个子节点之前 let firstChildTreeNodeDom = undefined @@ -268,7 +287,7 @@ firstChildTreeNodeDom = e.currentTarget.nextSibling } else { console.warn(`can't recognise ${this.$options.name}`) - return doNothing + return nothing } content = firstChildTreeNodeDom.querySelector('.pl-tree-node-content') @@ -511,17 +530,17 @@ const treeNode = this.findTreeNodeByKey(key) if (!treeNode) return if (!treeNode.isCheck) { - this.setMark(treeNode.key, TreeMark.checked, true) + treeNode.check(true) // 父子关联模式下,改变子节点以及父节点状态 if (!this.checkStrictly) { // 选中所有子节点 - this.iterateAll(treeNode.children, (child) => this.setMark(child.key, TreeMark.checked, true)) + this.iterateAll(treeNode.children, (child) => child.check(true)) // 更新父节点状态,如果父节点所有的子节点都处于选中状态,则更新父节点为选中状态 let parent = treeNode.parent while (!!parent && !!parent.key) { if (parent.children.every(child => child.isCheck)) { - this.setMark(parent.key, TreeMark.checked, true) + parent.check(true) parent = parent.parent } else { break @@ -545,17 +564,17 @@ const treeNode = this.findTreeNodeByKey(key) if (!treeNode) return if (treeNode.isCheck) { - this.setMark(treeNode.key, TreeMark.checked, false) + treeNode.check(false) // 父子关联模式下,改变子节点以及父节点状态 if (!this.checkStrictly) { // 取消选中所有子节点 - this.iterateAll(treeNode.children, (child) => this.setMark(child.key, TreeMark.checked, false)) + this.iterateAll(treeNode.children, (child) => child.check(false)) // 更新父节点状态,如果父节点所有的子节点都处于非选中状态,则更新父节点为非选中状态 let parent = treeNode.parent while (!!parent && !!parent.key) { if (parent.isCheck) { - this.setMark(parent.key, TreeMark.checked, false) + parent.check(false) parent = parent.parent } else { break @@ -590,7 +609,7 @@ * @date 2020/3/31 17:33 */ checkAll() { - this.iterateAll(this.formatData, (treeNode: TreeNode) => this.setMark(treeNode.key, TreeMark.checked, true)) + this.iterateAll(this.formatData, (treeNode: TreeNode) => treeNode.check(true)) }, /** * 取消选中所有节点 @@ -598,7 +617,7 @@ * @date 2020/3/31 17:33 */ uncheckAll() { - this.iterateAll(this.formatData, (treeNode: TreeNode) => this.setMark(treeNode.key, TreeMark.checked, false)) + this.iterateAll(this.formatData, (treeNode: TreeNode) => treeNode.check(false)) }, /** * 获取选中的数据 @@ -734,6 +753,60 @@ if (!!instance.$parent && !!instance.$parent.treeNode) return instance.$parent.treeNode return null }, + /** + * 刷新节点选中状态 + * @author 韦胜健 + * @date 2020/4/1 22:17 + */ + refreshCheckStatus() { + if (!this.showCheckbox) return + if (this.checkStrictly) return; + + const next = (treeNode: TreeNode) => { + let hasCheck = false + let hasUncheck = false + + if (!!treeNode.children && treeNode.children) { + treeNode.children.forEach(child => { + next(child) + if (child.isCheck) { + hasCheck = true + } else { + hasUncheck = true + } + }) + } + if (hasCheck && !hasUncheck) { + // 所有子节点选中 + if (!treeNode.isCheck) { + treeNode.check(true) + } + } else if (hasUncheck) { + // 有子节点未选中 + if (treeNode.isCheck) { + treeNode.check(false) + } + } + } + + this.formatData.forEach(next) + }, + /** + * 判断是否可以拖拽 + * @author 韦胜健 + * @date 2020/4/1 23:12 + */ + isAllowDrag(dragTreeNode: TreeNode, event: DragEvent) { + return !this.allowDrag || this.allowDrag(dragTreeNode, event) + }, + /** + * 判断是否可以放置 + * @author 韦胜健 + * @date 2020/4/1 23:12 + */ + isAllowDrop(dragTreeNode: TreeNode, dropTreeNode: TreeNode, dropType: DropType, event) { + return !this.allowDrop || this.allowDrop(dragTreeNode, dropTreeNode, dropType, event) + }, /*---------------------------------------helper-------------------------------------------*/ async initLazy() { diff --git a/src/components/tree/tree.ts b/src/components/tree/tree.ts index 41b9236ab..0a47ec2b8 100644 --- a/src/components/tree/tree.ts +++ b/src/components/tree/tree.ts @@ -18,19 +18,23 @@ export class TreeNode { this.label = !!labelField ? data[labelField] : undefined } + /*当前是否展开*/ get isExpand(): boolean { return this.context.getMark(this.key, TreeMark.expanded) === true } + /*当前是否已经选中*/ get isCheck(): boolean { return this.context.getMark(this.key, TreeMark.checked) === true } + /*当前是否可以被选中*/ get isCheckable(): boolean { const {isCheckable} = this.context return !isCheckable || (isCheckable(this)) } + /*当前选中状态:选中、未选中、半选中*/ get checkStatus(): CheckStatus { if (this.isLeaf || this.context.checkStrictly) { @@ -49,6 +53,7 @@ export class TreeNode { } } + /*是否为叶子节点*/ get isLeaf(): boolean { const {lazy, isLeaf} = this.context if (!!lazy && !!isLeaf) { @@ -58,6 +63,7 @@ export class TreeNode { } } + /*节点是否可见*/ get isVisible(): boolean { const {filterNodeMethod} = this.context if (!filterNodeMethod) { @@ -71,14 +77,21 @@ export class TreeNode { } } + /*当前是否处于加载状态*/ get isLoading(): boolean { return this.context.getMark(this.key, TreeMark.loading) } + /*当前节点的子节点的数据*/ get childrenData() { return this.data[this.context.childrenField] } + /** + * 拖拽指示器的左偏移距离 + * @author 韦胜健 + * @date 2020/4/3 0:09 + */ get indicatorLeft() { let left = this.context.intent * (this.level - 1) if (this.isLeaf && !this.isLoading) { @@ -87,15 +100,33 @@ export class TreeNode { return left } + /*---------------------------------------methods-------------------------------------------*/ + /** + * 选中/取消选中 当前节点 + * @author 韦胜健 + * @date 2020/4/1 22:37 + */ + check(val: boolean) { + if (!this.isCheckable) return + this.context.setMark(this.key, TreeMark.checked, val) + } + + /** + * 设置子节点数据 + * @author 韦胜健 + * @date 2020/4/3 0:09 + */ setChildren(children: TreeNode[]) { this.context.$set(this.data, this.context.childrenField, children) } + /*将当前节点从当前节点的父节点移除*/ removeSelf() { const parentChildrenData = this.parent.childrenData parentChildrenData.splice(parentChildrenData.indexOf(this.data), 1) } + /*在当前节点所有的数组中插入一个节点*/ splice(index, count, replace) { let parentChildrenData = this.parent.childrenData @@ -106,6 +137,7 @@ export class TreeNode { return parentChildrenData.splice(index, count, replace) } + /*在当前节点所在的数组中添加一个节点*/ push(data) { let childrenData = this.childrenData if (!childrenData) { -- Gitee