Tree 优化
This commit is contained in:
parent
4ac50f3bd7
commit
a4d07a5aec
|
@ -54,6 +54,15 @@
|
|||
}
|
||||
}
|
||||
|
||||
&-rootItem {
|
||||
line-height: $Tree-itemHeight;
|
||||
}
|
||||
|
||||
&-item>div:hover>.#{$ns}Tree-item-icons,
|
||||
&-rootItem>div:hover>.#{$ns}Tree-item-icons {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
&-itemLabel {
|
||||
&:hover {
|
||||
background: $Tree-item-onHover-bg;
|
||||
|
@ -200,7 +209,6 @@
|
|||
|
||||
&-itemLabel {
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
|
||||
&.is-checked,
|
||||
&.is-children-checked {
|
||||
|
@ -212,6 +220,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
&-itemText {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&-placeholder {
|
||||
color: $text--muted-color;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,14 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {eachTree, isVisible, autobind, findTreeIndex} from '../utils/helper';
|
||||
import {
|
||||
eachTree,
|
||||
isVisible,
|
||||
autobind,
|
||||
findTreeIndex,
|
||||
hasAbility,
|
||||
createObject
|
||||
} from '../utils/helper';
|
||||
import {Option, Options, value2array} from './Checkboxes';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
import {highlight} from '../renderers/Form/Options';
|
||||
|
@ -35,10 +42,10 @@ interface TreeSelectorProps {
|
|||
// 名称、取值等字段名映射
|
||||
labelField: string;
|
||||
valueField: string;
|
||||
iconField?: string;
|
||||
unfoldedField?: string;
|
||||
foldedField?: string;
|
||||
disabledField?: string;
|
||||
iconField: string;
|
||||
unfoldedField: string;
|
||||
foldedField: string;
|
||||
disabledField: string;
|
||||
|
||||
className?: string;
|
||||
itemClassName?: string;
|
||||
|
@ -59,6 +66,7 @@ interface TreeSelectorProps {
|
|||
|
||||
// 是否为内建 增、改、删。当有复杂表单的时候直接抛出去让外层能统一处理
|
||||
bultinCUD?: boolean;
|
||||
rootCreatable?: boolean;
|
||||
creatable?: boolean;
|
||||
onAdd?: (
|
||||
idx?: number | Array<number>,
|
||||
|
@ -444,16 +452,16 @@ export class TreeSelector extends React.Component<
|
|||
showRadio,
|
||||
multiple,
|
||||
disabled,
|
||||
labelField: nameField = '',
|
||||
valueField = '',
|
||||
iconField = '',
|
||||
disabledField = '',
|
||||
labelField,
|
||||
valueField,
|
||||
iconField,
|
||||
disabledField,
|
||||
cascade,
|
||||
selfDisabledAffectChildren,
|
||||
onlyChildren,
|
||||
classnames: cx,
|
||||
highlightTxt,
|
||||
options: data,
|
||||
options,
|
||||
maxLength,
|
||||
minLength,
|
||||
creatable,
|
||||
|
@ -471,7 +479,7 @@ export class TreeSelector extends React.Component<
|
|||
|
||||
let childrenChecked = 0;
|
||||
let ret = list.map((item, key) => {
|
||||
if (!isVisible(item as any, data)) {
|
||||
if (!isVisible(item as any, options)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -584,12 +592,13 @@ export class TreeSelector extends React.Component<
|
|||
) : null}
|
||||
|
||||
{highlightTxt
|
||||
? highlight(item[nameField], highlightTxt)
|
||||
: item[nameField]}
|
||||
? highlight(item[labelField], highlightTxt)
|
||||
: item[labelField]}
|
||||
</span>
|
||||
|
||||
{!nodeDisabled && !isAdding && !isEditing ? (
|
||||
<div className={cx('Tree-item-icons')}>
|
||||
{creatable ? (
|
||||
{creatable && hasAbility(item, 'creatable') ? (
|
||||
<a
|
||||
onClick={this.handleAdd.bind(this, item)}
|
||||
data-tooltip="添加孩子节点"
|
||||
|
@ -597,7 +606,8 @@ export class TreeSelector extends React.Component<
|
|||
<Icon icon="plus" className="icon" />
|
||||
</a>
|
||||
) : null}
|
||||
{removable ? (
|
||||
|
||||
{removable && hasAbility(item, 'removable') ? (
|
||||
<a
|
||||
onClick={this.handleRemove.bind(this, item)}
|
||||
data-tooltip="移除该节点"
|
||||
|
@ -605,7 +615,8 @@ export class TreeSelector extends React.Component<
|
|||
<Icon icon="minus" className="icon" />
|
||||
</a>
|
||||
) : null}
|
||||
{editable ? (
|
||||
|
||||
{editable && hasAbility(item, 'editable') ? (
|
||||
<a
|
||||
onClick={this.handleEdit.bind(this, item)}
|
||||
data-tooltip="编辑该节点"
|
||||
|
@ -654,32 +665,32 @@ export class TreeSelector extends React.Component<
|
|||
rootLabel,
|
||||
showIcon,
|
||||
classnames: cx,
|
||||
creatable
|
||||
creatable,
|
||||
rootCreatable,
|
||||
disabled
|
||||
} = this.props;
|
||||
let data = this.props.options;
|
||||
let options = this.props.options;
|
||||
const {value, isAdding, addingParent, isEditing, inputValue} = this.state;
|
||||
|
||||
let addBtn = null;
|
||||
|
||||
if (creatable) {
|
||||
if (creatable && hideRoot) {
|
||||
addBtn = (
|
||||
<li>
|
||||
<a
|
||||
className={cx('Tree-addTopBtn', {
|
||||
'is-disabled': isAdding || isEditing
|
||||
})}
|
||||
onClick={this.handleAdd.bind(this, null)}
|
||||
>
|
||||
<Icon icon="plus" className="icon" />
|
||||
<span>添加一级节点</span>
|
||||
</a>
|
||||
</li>
|
||||
<a
|
||||
className={cx('Tree-addTopBtn', {
|
||||
'is-disabled': isAdding || isEditing
|
||||
})}
|
||||
onClick={this.handleAdd.bind(this, null)}
|
||||
>
|
||||
<Icon icon="plus" className="icon" />
|
||||
<span>添加一级节点</span>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cx(`Tree ${className || ''}`)}>
|
||||
{data && data.length ? (
|
||||
{options && options.length ? (
|
||||
<ul className={cx('Tree-list')}>
|
||||
{hideRoot ? (
|
||||
<>
|
||||
|
@ -687,34 +698,43 @@ export class TreeSelector extends React.Component<
|
|||
{isAdding && !addingParent ? (
|
||||
<li className={cx('Tree-item')}>{this.renderInput()}</li>
|
||||
) : null}
|
||||
{this.renderList(data, value, false).dom}
|
||||
{this.renderList(options, value, false).dom}
|
||||
</>
|
||||
) : (
|
||||
<li
|
||||
className={cx('Tree-item Tree-rootItem', {
|
||||
className={cx('Tree-rootItem', {
|
||||
'is-checked': !value || !value.length
|
||||
})}
|
||||
>
|
||||
<a>
|
||||
{showIcon ? (
|
||||
<i className={cx('Tree-itemIcon Tree-rootIcon')} />
|
||||
<div className={cx('Tree-itemLabel')}>
|
||||
<span className={cx('Tree-itemText')}>
|
||||
{showIcon ? (
|
||||
<i className={cx('Tree-itemIcon Tree-rootIcon')} />
|
||||
) : null}
|
||||
{rootLabel}
|
||||
</span>
|
||||
{!disabled &&
|
||||
creatable &&
|
||||
rootCreatable !== false &&
|
||||
!isAdding &&
|
||||
!isEditing ? (
|
||||
<div className={cx('Tree-item-icons')}>
|
||||
{creatable ? (
|
||||
<a
|
||||
onClick={this.handleAdd.bind(this, null)}
|
||||
data-tooltip="添加一级节点"
|
||||
>
|
||||
<Icon icon="plus" className="icon" />
|
||||
</a>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<label className={cx('Tree-itemLabel')}>
|
||||
<span
|
||||
className={cx('Tree-itemText')}
|
||||
onClick={this.clearSelect}
|
||||
>
|
||||
{rootLabel}
|
||||
</span>
|
||||
</label>
|
||||
</a>
|
||||
{addBtn}
|
||||
</div>
|
||||
<ul className={cx('Tree-sublist')}>
|
||||
{isAdding && !addingParent ? (
|
||||
<li className={cx('Tree-item')}>{this.renderInput()}</li>
|
||||
) : null}
|
||||
{this.renderList(data, value, false).dom}
|
||||
{this.renderList(options, value, false).dom}
|
||||
</ul>
|
||||
</li>
|
||||
)}
|
||||
|
|
|
@ -67,6 +67,7 @@ export interface OptionsProps extends FormControlProps, OptionProps {
|
|||
editControls?: Array<any>;
|
||||
deleteApi?: Api;
|
||||
deleteConfirmText?: string;
|
||||
optionLabel?: string;
|
||||
}
|
||||
|
||||
export function registerOptionsControl(config: OptionsConfig) {
|
||||
|
@ -478,6 +479,7 @@ export function registerOptionsControl(config: OptionsConfig) {
|
|||
disabled,
|
||||
labelField,
|
||||
onOpenDialog,
|
||||
optionLabel,
|
||||
addApi,
|
||||
source,
|
||||
data,
|
||||
|
@ -509,7 +511,7 @@ export function registerOptionsControl(config: OptionsConfig) {
|
|||
: await onOpenDialog(
|
||||
{
|
||||
type: 'dialog',
|
||||
title: createBtnLabel || '新增选项',
|
||||
title: createBtnLabel || `新增${optionLabel || '选项'}`,
|
||||
body: {
|
||||
type: 'form',
|
||||
api: addApi,
|
||||
|
@ -580,7 +582,8 @@ export function registerOptionsControl(config: OptionsConfig) {
|
|||
editApi,
|
||||
source,
|
||||
data,
|
||||
formItem: model
|
||||
formItem: model,
|
||||
optionLabel
|
||||
} = this.props;
|
||||
|
||||
if (disabled || !model) {
|
||||
|
@ -603,7 +606,7 @@ export function registerOptionsControl(config: OptionsConfig) {
|
|||
: await onOpenDialog(
|
||||
{
|
||||
type: 'dialog',
|
||||
title: '编辑选项',
|
||||
title: `编辑${optionLabel || '选项'}`,
|
||||
body: {
|
||||
type: 'form',
|
||||
api: editApi,
|
||||
|
|
|
@ -15,6 +15,7 @@ export interface TreeProps extends OptionsControlProps {
|
|||
onlyChildren?: boolean; // 选父级的时候,是否只把子节点的值包含在内
|
||||
addControls?: Array<any>;
|
||||
updateControls?: Array<any>;
|
||||
rootCreatable?: boolean;
|
||||
}
|
||||
|
||||
export default class TreeControl extends React.Component<TreeProps> {
|
||||
|
@ -63,7 +64,8 @@ export default class TreeControl extends React.Component<TreeProps> {
|
|||
editable,
|
||||
editControls,
|
||||
removable,
|
||||
onDelete
|
||||
onDelete,
|
||||
rootCreatable
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
|
@ -97,6 +99,7 @@ export default class TreeControl extends React.Component<TreeProps> {
|
|||
selfDisabledAffectChildren={false}
|
||||
onAdd={onAdd}
|
||||
creatable={creatable}
|
||||
rootCreatable={rootCreatable}
|
||||
onEdit={onEdit}
|
||||
editable={editable}
|
||||
removable={removable}
|
||||
|
|
|
@ -6,6 +6,7 @@ import PopOver from '../../components/PopOver';
|
|||
import {OptionsControl, OptionsControlProps, Option} from './Options';
|
||||
import {Icon} from '../../components/icons';
|
||||
import TreeSelector from '../../components/Tree';
|
||||
// @ts-ignore
|
||||
import matchSorter from 'match-sorter';
|
||||
import debouce = require('lodash/debounce');
|
||||
import find = require('lodash/find');
|
||||
|
|
|
@ -373,6 +373,19 @@ export function isDisabled(
|
|||
);
|
||||
}
|
||||
|
||||
export function hasAbility(
|
||||
schema: any,
|
||||
ability: string,
|
||||
data?: object,
|
||||
defaultValue: boolean = true
|
||||
): boolean {
|
||||
return schema.hasOwnProperty(ability)
|
||||
? schema[ability]
|
||||
: schema.hasOwnProperty(`${ability}On`)
|
||||
? evalExpression(schema[`${ability}On`], data || schema)
|
||||
: defaultValue;
|
||||
}
|
||||
|
||||
export function makeHorizontalDeeper(
|
||||
horizontal: {
|
||||
left: string;
|
||||
|
|
Loading…
Reference in New Issue