diff --git a/scss/components/form/_tree.scss b/scss/components/form/_tree.scss index 5dce1891..b1af2271 100644 --- a/scss/components/form/_tree.scss +++ b/scss/components/form/_tree.scss @@ -1,7 +1,9 @@ @mixin tree-input { - > i { + > svg { display: inline-block; cursor: pointer; + position: relative; + top: 2px; margin-left: px2rem(5px); } @@ -65,16 +67,27 @@ line-height: px2rem(30px); position: relative; + .#{$ns}Tree-item-icons { + visibility: hidden; + transition: visibility .1s ease; + } + > a { color: inherit; &:hover { text-decoration: none; + + > span.#{$ns}Tree-item-icons { + visibility: visible; + } } - > span > i { + > span > svg { display: inline-block; cursor: pointer; + position: relative; + top: 2px; margin-left: px2rem(5px); } } @@ -99,8 +112,14 @@ line-height: px2rem(25px); cursor: pointer; padding-left: $Tree-indent; - > p > span { - padding-left: px2rem(5px); + > p { + > svg { + position: relative; + top: 2px; + } + > span { + padding-left: px2rem(5px); + } } &-input { diff --git a/src/components/Tree.tsx b/src/components/Tree.tsx index 2b756d24..da419a6b 100644 --- a/src/components/Tree.tsx +++ b/src/components/Tree.tsx @@ -5,10 +5,11 @@ */ import React from 'react'; -import {eachTree, isVisible, isObject} from '../utils/helper'; +import {eachTree, isVisible, isObject, autobind} from '../utils/helper'; import {Option, Options, value2array} from './Checkboxes'; import {ClassNamesFn, themeable} from '../theme'; import {highlight} from '../renderers/Form/Options'; +import {Icon} from './icons'; interface TreeSelectorProps { classPrefix: string; @@ -53,20 +54,21 @@ interface TreeSelectorProps { selfDisabledAffectChildren?: boolean; minLength?: number; maxLength?: number; - addMode?: string; - addItem?: Function; + addMode?: 'dialog' | 'normal'; + addable?: boolean; + onAdd?: Function; openAddDialog?: Function; - editMode?: string; - editItem?: Function; + editMode?: 'dialog' | 'normal'; + onEdit?: Function; + editable?: boolean; openEditDialog?: Function; deletable?: boolean; - deleteItem?: Function; + onDelete?: Function; } interface TreeSelectorState { value: Array; unfolded: {[propName: string]: string}; - hoverItem: Option | null; editItem: Option | null; addItem: Option | null; addingItem: Option | null; @@ -101,24 +103,6 @@ export class TreeSelector extends React.Component - !nodeDisabled && this.handleMove(e, item) - } - onMouseEnter={() => - !nodeDisabled && this.handleEnter(item) - } - onMouseLeave={() => - !nodeDisabled && this.handleLeave() - } > {!editItem || isObject(editItem) && (editItem as Option)[valueField] !== item[valueField] ? ( @@ -598,24 +556,21 @@ export class TreeSelector extends React.Component {highlightTxt ? highlight(item[nameField], highlightTxt) : item[nameField]} - {/* 非添加时 && 非编辑时 && 鼠标覆盖时是当前item时,显示添加/编辑/删除图标 */} {!addTop && !addItem - && !editItem - && isObject(hoverItem) - && (hoverItem as Option)[valueField as string] === item[valueField] ? ( - - {addMode ? this.addItem(item, !isLeaf)}> : null} - {deletable ? this.deleteItem(item)}> : null} - {editMode ? this.editItem(item)}> : null} + && !editItem ? ( + + {addable ? this.handleAdd(item, !isLeaf)}/> : null} + {deletable ? this.handleDelete(item)}/> : null} + {editable ? this.handleEdit(item)}/> : null} ) : null} ) : (
- this.onChangeEditItem(item, e.currentTarget.value)}/> - - + this.handleChangeOnEdit(item, e.currentTarget.value)}/> + +
)} {/* 有children而且为展开状态 或者 添加child时 */} @@ -625,9 +580,9 @@ export class TreeSelector extends React.Component {addItem && addItem[valueField] === item[valueField] ? (
  • - this.onChangeAddItem(e.currentTarget.value)}/> - - + this.handleChangeOnAdd(e.currentTarget.value)}/> + +
  • ) : null} {childrenItems} @@ -644,7 +599,7 @@ export class TreeSelector extends React.Component - {addMode ? ( + {addable ? (
    {!addTop ? ( -

    this.addItem(null, false)}> - +

    this.handleAdd(null, false)}> + 添加一级

    - ) : null } + ) : null} {addTop ? (
    - this.onChangeAddItem(e.currentTarget.value)}/> - - + this.handleChangeOnAdd(e.currentTarget.value)}/> + +
    ) : null}
    diff --git a/src/components/icons.tsx b/src/components/icons.tsx index 150ae7b4..b4900707 100644 --- a/src/components/icons.tsx +++ b/src/components/icons.tsx @@ -25,6 +25,16 @@ import PauseIcon from '../icons/pause.svg'; import LeftArrowIcon from '../icons/left-arrow.svg'; // @ts-ignore import RightArrowIcon from '../icons/right-arrow.svg'; +// @ts-ignore +import CheckIcon from '../icons/check.svg'; +// @ts-ignore +import PlusIcon from '../icons/plus.svg'; +// @ts-ignore +import MinusIcon from '../icons/minus.svg'; +// @ts-ignore +import PencilIcon from '../icons/pencil.svg'; +// @ts-ignore +import TreeClose from '../icons/tree-close.svg'; // 兼容原来的用法,后续不直接试用。 // @ts-ignore @@ -70,6 +80,11 @@ registerIcon('play', PlayIcon); registerIcon('pause', PauseIcon); registerIcon('left-arrow', LeftArrowIcon); registerIcon('right-arrow', RightArrowIcon); +registerIcon('check', CheckIcon); +registerIcon('plus', PlusIcon); +registerIcon('minus', MinusIcon); +registerIcon('pencil', PencilIcon); +registerIcon('tree-close', TreeClose); export function Icon({ icon, @@ -91,5 +106,9 @@ export { PlayIcon, PauseIcon, LeftArrowIcon, - RightArrowIcon + RightArrowIcon, + CheckIcon, + PlusIcon, + MinusIcon, + PencilIcon }; diff --git a/src/icons/check.svg b/src/icons/check.svg new file mode 100644 index 00000000..0c5a7267 --- /dev/null +++ b/src/icons/check.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/icons/minus.svg b/src/icons/minus.svg new file mode 100644 index 00000000..91005aa6 --- /dev/null +++ b/src/icons/minus.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/icons/pencil.svg b/src/icons/pencil.svg new file mode 100644 index 00000000..fc07da74 --- /dev/null +++ b/src/icons/pencil.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/icons/plus.svg b/src/icons/plus.svg new file mode 100644 index 00000000..d22d6526 --- /dev/null +++ b/src/icons/plus.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/icons/tree-close.svg b/src/icons/tree-close.svg new file mode 100644 index 00000000..c2a1fa4f --- /dev/null +++ b/src/icons/tree-close.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/renderers/Form/Tree.tsx b/src/renderers/Form/Tree.tsx index 57b87353..d70d4bbe 100644 --- a/src/renderers/Form/Tree.tsx +++ b/src/renderers/Form/Tree.tsx @@ -18,10 +18,10 @@ export interface TreeProps extends OptionsControlProps { withChildren?: boolean; // 选父级的时候是否把子节点的值也包含在内。 onlyChildren?: boolean; // 选父级的时候,是否只把子节点的值包含在内 addApi?: Api; - addMode?: string; + addMode?: 'dialog' | 'normal'; addDialog?: Schema; editApi?: Api; - editMode?: string; + editMode?: 'dialog' | 'normal'; editDialog?: Schema; deleteApi?: Api; deleteConfirmText?: string; @@ -57,7 +57,7 @@ export default class TreeControl extends React.Component { } @autobind - addItem(values: PlainObject) { + handleAdd(values: PlainObject) { this.saveRemote(values, 'add'); } @@ -71,7 +71,7 @@ export default class TreeControl extends React.Component { } @autobind - editItem(values: PlainObject) { + handleEdit(values: PlainObject) { this.saveRemote(values, 'add'); } @@ -80,7 +80,7 @@ export default class TreeControl extends React.Component { this.saveRemote({ ...values, prev: this.state.prev - }, 'add'); + }, 'edit'); this.closeEditDialog(); } @@ -109,7 +109,7 @@ export default class TreeControl extends React.Component { } @autobind - async deleteItem(item: any) { + async handleDelete(item: any) { const {deleteConfirmText, deleteApi, data, env} = this.props; const ctx = createObject(data, item); if (isEffectiveApi(deleteApi, ctx)) { @@ -189,8 +189,10 @@ export default class TreeControl extends React.Component { showRadio, render, addMode, + addApi, addDialog, editMode, + editApi, editDialog, deleteApi } = this.props; @@ -228,17 +230,19 @@ export default class TreeControl extends React.Component { nameField="label" selfDisabledAffectChildren={false} addMode={addMode} - addItem={this.addItem} + addable={isEffectiveApi(addApi)} + onAdd={this.handleAdd} openAddDialog={this.openAddDialog} editMode={editMode} - editItem={this.editItem} + editable={isEffectiveApi(editApi)} + onEdit={this.handleEdit} openEditDialog={this.openEditDialog} - deleteItem={this.deleteItem} + onDelete={this.handleDelete} deletable={isEffectiveApi(deleteApi)} /> )} - {render( + {addMode && render( 'modal', { type: 'dialog', @@ -252,7 +256,7 @@ export default class TreeControl extends React.Component { } )} - {render( + {editMode && render( 'modal', { type: 'dialog',