feat(@zhst/biz): 树组件支持tag面板、优化filter传参、优化option传参、废弃之前的定制化方案
This commit is contained in:
parent
e90dcce641
commit
da3c1714c5
@ -1,5 +1,11 @@
|
|||||||
# @zhst/biz
|
# @zhst/biz
|
||||||
|
|
||||||
|
## 0.24.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- 树组件支持 tag 面板、优化 filter 传参、优化 option 传参、废弃之前的定制化方案
|
||||||
|
|
||||||
## 0.23.0
|
## 0.23.0
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@zhst/biz",
|
"name": "@zhst/biz",
|
||||||
"version": "0.23.0",
|
"version": "0.24.0",
|
||||||
"description": "业务库",
|
"description": "业务库",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"business",
|
"business",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { FC, useContext } from 'react';
|
import React, { FC, ReactNode, useContext } from 'react';
|
||||||
import { Tabs, TabsProps } from 'antd'
|
import { Tabs, TabsProps } from 'antd'
|
||||||
import { ConfigProvider } from '@zhst/meta';
|
import { ConfigProvider } from '@zhst/meta';
|
||||||
import BoxPanel from './components/boxPanel';
|
import BoxPanel from './components/boxPanel';
|
||||||
@ -9,31 +9,18 @@ export interface BoxSelectTreeProps extends BoxPanelProps {
|
|||||||
onTabChange?: (e: any) => void
|
onTabChange?: (e: any) => void
|
||||||
tabsProps?: TabsProps
|
tabsProps?: TabsProps
|
||||||
prefixCls?: string;
|
prefixCls?: string;
|
||||||
|
footer?: ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
const { ConfigContext } = ConfigProvider
|
const { ConfigContext } = ConfigProvider
|
||||||
|
|
||||||
const BoxSelectTree: FC<BoxSelectTreeProps> = (props) => {
|
const BoxSelectTree: FC<BoxSelectTreeProps> = (props) => {
|
||||||
const {
|
const {
|
||||||
data,
|
prefixCls: customizePrefixCls,
|
||||||
boxDataSource = [],
|
|
||||||
onTabChange,
|
|
||||||
onSearch,
|
|
||||||
onItemCheck,
|
|
||||||
onItemSelect,
|
|
||||||
onBoxBatchDelete,
|
|
||||||
onBoxDelete,
|
|
||||||
onCreateSubmit,
|
|
||||||
onClockClick,
|
|
||||||
onImport,
|
|
||||||
onCreate,
|
|
||||||
tabsProps,
|
tabsProps,
|
||||||
searchInputProps,
|
onTabChange,
|
||||||
treeProps,
|
footer,
|
||||||
customImport,
|
...rest
|
||||||
showOptions,
|
|
||||||
extraBtns,
|
|
||||||
prefixCls: customizePrefixCls
|
|
||||||
} = props
|
} = props
|
||||||
const { getPrefixCls } = useContext(ConfigContext);
|
const { getPrefixCls } = useContext(ConfigContext);
|
||||||
const componentName = getPrefixCls('biz-box-select-tree', customizePrefixCls);
|
const componentName = getPrefixCls('biz-box-select-tree', customizePrefixCls);
|
||||||
@ -61,23 +48,9 @@ const BoxSelectTree: FC<BoxSelectTreeProps> = (props) => {
|
|||||||
{...tabsProps}
|
{...tabsProps}
|
||||||
/>
|
/>
|
||||||
<BoxPanel
|
<BoxPanel
|
||||||
searchInputProps={searchInputProps}
|
{...rest}
|
||||||
boxDataSource={boxDataSource}
|
|
||||||
treeProps={treeProps}
|
|
||||||
data={data}
|
|
||||||
onCreate={onCreate}
|
|
||||||
onCreateSubmit={onCreateSubmit}
|
|
||||||
onBoxBatchDelete={onBoxBatchDelete}
|
|
||||||
onBoxDelete={onBoxDelete}
|
|
||||||
onSearch={onSearch}
|
|
||||||
onItemCheck={onItemCheck}
|
|
||||||
onItemSelect={onItemSelect}
|
|
||||||
showOptions={showOptions}
|
|
||||||
customImport={customImport}
|
|
||||||
extraBtns={extraBtns}
|
|
||||||
onClockClick={onClockClick}
|
|
||||||
onImport={onImport}
|
|
||||||
/>
|
/>
|
||||||
|
{footer}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
.zhst-biz-box-select-tree-panel {
|
.zhst-biz-box-select-tree-panel {
|
||||||
&-search {
|
&-search {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
|
|
||||||
&-input {
|
&-input {
|
||||||
|
flex: 1;
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,6 +20,7 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
&-common {
|
&-common {
|
||||||
|
flex: 1;
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,6 +33,60 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-tags {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
margin-top: 6px;
|
||||||
|
padding: 12px;
|
||||||
|
font-size: 0;
|
||||||
|
border-top: 1px solid #09f;
|
||||||
|
border-bottom: 1px solid #09f;
|
||||||
|
|
||||||
|
&-tag {
|
||||||
|
margin-right: 6px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
transition:.3s ease all;
|
||||||
|
|
||||||
|
&_common{
|
||||||
|
margin-bottom: 6px;
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 6px;
|
||||||
|
padding: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #f6f6f6;
|
||||||
|
transition: .3s ease all;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-sizing: content-box;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #09f;
|
||||||
|
background-color: rgba(0, 0, 0, 6%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&_checked {
|
||||||
|
color: #09f;
|
||||||
|
background-color: #edf8ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_fz12 {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_option {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_absolute {
|
||||||
|
position: absolute;
|
||||||
|
top: 12px;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&-tree {
|
&-tree {
|
||||||
padding: 6px 0;
|
padding: 6px 0;
|
||||||
}
|
}
|
||||||
|
@ -1,73 +1,160 @@
|
|||||||
import React, { FC, useState, useRef, useContext } from 'react';
|
import React, { FC, useState, useContext, ReactNode } from 'react';
|
||||||
import{ Button, Divider, Input, Space, TreeDataNode } from 'antd'
|
import{ Button, Divider, Dropdown, Input, TreeDataNode } from 'antd'
|
||||||
import { ModalForm, ModalFormProps, ProFormInstance, ProFormText } from '@ant-design/pro-components'
|
import { ModalFormProps } from '@ant-design/pro-components'
|
||||||
import { ConfigProvider } from '@zhst/meta';
|
import { ButtonProps, ConfigProvider, Tooltip } from '@zhst/meta';
|
||||||
|
import { IconFont } from '@zhst/icon';
|
||||||
import { ClockCircleOutlined, CloseCircleOutlined, DiffOutlined, FolderAddOutlined, ImportOutlined, SwitcherOutlined } from '@ant-design/icons'
|
import { ClockCircleOutlined, CloseCircleOutlined, DiffOutlined, FolderAddOutlined, ImportOutlined, SwitcherOutlined } from '@ant-design/icons'
|
||||||
import type { TreeProps, InputProps } from 'antd';
|
import type { TreeProps, InputProps, DropDownProps } from 'antd';
|
||||||
|
import classNames from 'classnames';
|
||||||
import type { BoxTreeProps } from '../../../tree';
|
import type { BoxTreeProps } from '../../../tree';
|
||||||
import TreeTransferModal from '../../../treeTransferModal'
|
|
||||||
import BoxTree from '../../../tree';
|
import BoxTree from '../../../tree';
|
||||||
import './index.less'
|
import './index.less'
|
||||||
import classNames from 'classnames';
|
|
||||||
|
interface IOption {
|
||||||
|
label: string
|
||||||
|
key: string
|
||||||
|
icon?: string | ReactNode
|
||||||
|
type?: ButtonProps['type'] | 'dropdown'
|
||||||
|
disabled?: boolean;
|
||||||
|
showTooltip?: boolean;
|
||||||
|
props?: ButtonProps
|
||||||
|
onClick?: () => void
|
||||||
|
dropdownConfig?: DropDownProps
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ITag {
|
||||||
|
label: string
|
||||||
|
value: string
|
||||||
|
icon?: ReactNode
|
||||||
|
parentNode?: string
|
||||||
|
children?: ITag[]
|
||||||
|
}
|
||||||
|
|
||||||
export interface BoxPanelProps {
|
export interface BoxPanelProps {
|
||||||
searchInputProps?: InputProps
|
searchInputProps?: InputProps
|
||||||
showOptions?: boolean
|
showOptions?: boolean
|
||||||
treeProps?: Partial<BoxTreeProps>
|
treeProps?: Partial<BoxTreeProps>
|
||||||
data: TreeDataNode[]
|
data: TreeDataNode[]
|
||||||
boxDataSource: TreeDataNode[]
|
|
||||||
handleImport?: () => void
|
|
||||||
onSearch?: (e: any) => void
|
onSearch?: (e: any) => void
|
||||||
onItemCheck?: TreeProps['onCheck']
|
onItemCheck?: TreeProps['onCheck']
|
||||||
onItemSelect?: TreeProps['onSelect']
|
onItemSelect?: TreeProps['onSelect']
|
||||||
|
/**
|
||||||
|
* @deprecated 将于下个版本 0.23.0 以后弃用
|
||||||
|
*/
|
||||||
onBoxBatchDelete?: (data?: any) => void
|
onBoxBatchDelete?: (data?: any) => void
|
||||||
|
/**
|
||||||
|
* @deprecated 将于下个版本 0.23.0 以后弃用
|
||||||
|
*/
|
||||||
onBoxDelete?: (data?: any) => void
|
onBoxDelete?: (data?: any) => void
|
||||||
|
/**
|
||||||
|
* @deprecated 将于下个版本 0.23.0 以后弃用
|
||||||
|
*/
|
||||||
onCreateSubmit?: ModalFormProps['onFinish']
|
onCreateSubmit?: ModalFormProps['onFinish']
|
||||||
onClockClick?: () => void
|
/**
|
||||||
|
* @deprecated 将于下个版本 0.23.0 以后弃用
|
||||||
|
*/
|
||||||
|
onClockClick?: () => void //
|
||||||
|
/**
|
||||||
|
* @deprecated 将于下个版本 0.23.0 以后弃用
|
||||||
|
*/
|
||||||
onImport?: () => void
|
onImport?: () => void
|
||||||
|
/**
|
||||||
|
* @deprecated 将于下个版本 0.23.0 以后弃用
|
||||||
|
*/
|
||||||
onBatch?: () => void
|
onBatch?: () => void
|
||||||
|
/**
|
||||||
|
* @deprecated 将于下个版本 0.23.0 以后弃用
|
||||||
|
*/
|
||||||
onCreate?: () => void
|
onCreate?: () => void
|
||||||
customImport?: any
|
customImport?: ReactNode | string // 自定义搜索栏边上的过滤图标
|
||||||
extraBtns?: any
|
extraBtns?: ReactNode | string // 搜索栏下面的插槽
|
||||||
prefixCls?: string;
|
prefixCls?: string
|
||||||
|
showSearchBar?: boolean // 是否显示搜索栏
|
||||||
|
noFilter?: boolean // 是否显示搜索拓展 icon
|
||||||
|
filterList?: IOption[]
|
||||||
|
optionList?: IOption[]
|
||||||
|
showTagPanel?: boolean // 标签插槽
|
||||||
|
tagList?: ITag[] // 标签列表
|
||||||
|
tagExpandAll?: boolean // 展开所有
|
||||||
|
onTagCheck?: (value: string, tag: ITag) => void;
|
||||||
|
checkedTags?: string[]
|
||||||
|
onResetTags?: () => void
|
||||||
|
onTagExpand?: (e: any) => void
|
||||||
|
tagFootRender?: ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
const { ConfigContext } = ConfigProvider
|
const { ConfigContext } = ConfigProvider
|
||||||
|
|
||||||
const BoxPanel: FC<BoxPanelProps> = (props) => {
|
const BoxPanel: FC<BoxPanelProps> = (props) => {
|
||||||
|
const [isTreeCheckable, setIsTreeCheckable] = useState(false)
|
||||||
const {
|
const {
|
||||||
searchInputProps,
|
searchInputProps,
|
||||||
showOptions = true,
|
showOptions = true,
|
||||||
extraBtns,
|
extraBtns,
|
||||||
|
noFilter,
|
||||||
data = [],
|
data = [],
|
||||||
onSearch,
|
onSearch,
|
||||||
treeProps,
|
treeProps,
|
||||||
onItemCheck,
|
onItemCheck,
|
||||||
onItemSelect,
|
onItemSelect,
|
||||||
onCreateSubmit,
|
|
||||||
onBoxBatchDelete,
|
onBoxBatchDelete,
|
||||||
onBoxDelete,
|
onBoxDelete,
|
||||||
onClockClick,
|
onClockClick,
|
||||||
onImport,
|
onImport,
|
||||||
onBatch,
|
onBatch,
|
||||||
onCreate,
|
onCreate,
|
||||||
boxDataSource,
|
showSearchBar = true,
|
||||||
|
optionList = [
|
||||||
|
{
|
||||||
|
label: '导入盒子',
|
||||||
|
key: 'import',
|
||||||
|
icon: <ImportOutlined />,
|
||||||
|
onClick: () => onImport?.()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '新建组',
|
||||||
|
key: 'add',
|
||||||
|
icon: <FolderAddOutlined />,
|
||||||
|
onClick: () => onCreate?.()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '删除',
|
||||||
|
key: 'del',
|
||||||
|
icon: <CloseCircleOutlined />,
|
||||||
|
onClick: () => onBoxBatchDelete?.(),
|
||||||
|
props: {
|
||||||
|
danger: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
filterList = [
|
||||||
|
{
|
||||||
|
label: '多选',
|
||||||
|
key: 'multi',
|
||||||
|
icon: isTreeCheckable ? <SwitcherOutlined /> : <DiffOutlined />,
|
||||||
|
onClick: () => onBatch?.() || handleCheckable()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '时钟',
|
||||||
|
key: 'clock',
|
||||||
|
icon: <ClockCircleOutlined />,
|
||||||
|
onClick: () => onClockClick?.()
|
||||||
|
}
|
||||||
|
],
|
||||||
|
showTagPanel,
|
||||||
|
tagList,
|
||||||
|
tagExpandAll,
|
||||||
|
onTagExpand,
|
||||||
|
checkedTags = [],
|
||||||
|
onTagCheck,
|
||||||
|
onResetTags,
|
||||||
|
tagFootRender,
|
||||||
prefixCls: customizePrefixCls,
|
prefixCls: customizePrefixCls,
|
||||||
customImport
|
customImport: customFilter
|
||||||
} = props
|
} = props
|
||||||
|
|
||||||
const { getPrefixCls } = useContext(ConfigContext);
|
const { getPrefixCls } = useContext(ConfigContext);
|
||||||
const componentName = getPrefixCls('biz-box-select-tree-panel', customizePrefixCls);
|
const componentName = getPrefixCls('biz-box-select-tree-panel', customizePrefixCls);
|
||||||
const [isTreeCheckable, setIsTreeCheckable] = useState(false)
|
|
||||||
const [targetItems, setTargetItems] = useState<TreeDataNode[]>([]);
|
|
||||||
const [boxChoiceOpen, setBoxChoiceOpen] = useState(false)
|
|
||||||
const [checkedKeys, setCheckedKeys] = useState<string[]>([]);
|
|
||||||
const createFormRef = useRef<
|
|
||||||
ProFormInstance<{
|
|
||||||
name: string;
|
|
||||||
boxList?: any[];
|
|
||||||
}>
|
|
||||||
>()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改选择状态
|
* 修改选择状态
|
||||||
@ -77,151 +164,154 @@ const BoxPanel: FC<BoxPanelProps> = (props) => {
|
|||||||
setIsTreeCheckable(pre => !pre)
|
setIsTreeCheckable(pre => !pre)
|
||||||
}
|
}
|
||||||
|
|
||||||
const onTreeCheck: TreeProps['onCheck'] = (keys: any, info) => {
|
/**
|
||||||
let _targetItems: TreeDataNode[] = []
|
* 初始化拓展 filter
|
||||||
setCheckedKeys(keys)
|
* @param _list
|
||||||
info.checkedNodes.forEach(o => {
|
* @returns
|
||||||
o.isLeaf && _targetItems.push(o)
|
*/
|
||||||
})
|
const initFilter = (_list?: BoxPanelProps['filterList']) => {
|
||||||
setTargetItems(_targetItems)
|
const WithDropdown = (dom: ReactNode, _config?: DropDownProps) => {
|
||||||
|
return (
|
||||||
|
<Dropdown placement="bottomLeft" arrow {..._config}>
|
||||||
|
{dom}
|
||||||
|
</Dropdown>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return _list?.map(item => (
|
||||||
|
<Tooltip
|
||||||
|
title={item.label}
|
||||||
|
open={item.showTooltip}
|
||||||
|
>
|
||||||
|
{item.type === 'dropdown' ? (
|
||||||
|
WithDropdown(
|
||||||
|
<Button className={classNames(componentName + '-search-btns-btn')} type="text" onClick={item.onClick} icon={item.icon} />,
|
||||||
|
item.dropdownConfig
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<Button className={classNames(componentName + '-search-btns-btn')} type="text" onClick={item.onClick} icon={item.icon} />
|
||||||
|
)}
|
||||||
|
</Tooltip>
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除
|
* 初始化拓展 filter
|
||||||
* @param key
|
* @param _list
|
||||||
* @param param1
|
* @returns
|
||||||
*/
|
*/
|
||||||
const onItemDelete = (key: any, { keys }: any) => {
|
const initOptions = (_list?: BoxPanelProps['optionList']) => {
|
||||||
setCheckedKeys(pre => {
|
return _list?.map((item, idx) => (
|
||||||
const newKeys = pre.filter(_key => !keys.includes(_key))
|
<>
|
||||||
return newKeys
|
<Tooltip
|
||||||
|
title={item.label}
|
||||||
|
>
|
||||||
|
{/* @ts-ignore */}
|
||||||
|
<Button className={classNames(componentName + '-btns-common')} type={item.type || 'text'} onClick={item.onClick} icon={item.icon} {...item?.props}>{item.label}</Button>
|
||||||
|
</Tooltip>
|
||||||
|
{idx !== _list.length - 1 && <Divider className={classNames(componentName + '-btns-divider')} type="vertical" />}
|
||||||
|
</>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化标签面板
|
||||||
|
* @param _tagList
|
||||||
|
* @param sort 是否分类
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
const initTagPanel = (_tagList: BoxPanelProps['tagList'], sort?: boolean) => {
|
||||||
|
// 正常标签渲染
|
||||||
|
const commonTag = (_tagProps: ITag) => (
|
||||||
|
<span
|
||||||
|
className={classNames(
|
||||||
|
componentName + '-tags-tag_common',
|
||||||
|
{[componentName + '-tags-tag_checked']: checkedTags.includes(_tagProps.value)}
|
||||||
|
)}
|
||||||
|
key={_tagProps.value}
|
||||||
|
onClick={() => onTagCheck?.(_tagProps.value, _tagProps)}
|
||||||
|
>{_tagProps.label}</span>
|
||||||
|
)
|
||||||
|
// 包装父级标签
|
||||||
|
const _withFather = (tag: ITag) => (
|
||||||
|
<div key={tag.value}>
|
||||||
|
<span className={classNames(componentName + '-tags-tag')}>{tag.label}</span>
|
||||||
|
{tag.children?.map?.(_tag => commonTag(_tag))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
return _tagList?.map(tag => {
|
||||||
|
if (tag.children?.length && sort) {
|
||||||
|
return _withFather(tag)
|
||||||
|
} else {
|
||||||
|
return commonTag(tag)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
setTargetItems(pre => pre.filter(o => o.key !== key))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 盒子点击确定
|
|
||||||
const onBoxChoiceOk = async (data: any) => {
|
|
||||||
createFormRef.current?.setFieldValue('boxList', data)
|
|
||||||
createFormRef.current?.setFieldValue('boxName', 123)
|
|
||||||
console.log(createFormRef.current?.getFieldValue('boxList'))
|
|
||||||
setBoxChoiceOpen(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 盒子选择重置
|
|
||||||
const onBoxChoiceReset = () => {
|
|
||||||
setCheckedKeys([])
|
|
||||||
setTargetItems([])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={componentName}>
|
<div className={componentName}>
|
||||||
{/* 盒子选择弹框 */}
|
{/* 搜索栏 */}
|
||||||
<TreeTransferModal
|
{showSearchBar && (
|
||||||
open={boxChoiceOpen}
|
<div className={classNames(componentName + '-search')}>
|
||||||
onCancel={() => setBoxChoiceOpen(false)}
|
<Input
|
||||||
onRadioChange={(e) => console.log('radio', e.target.value)} // 顶部 radio 事件
|
className={classNames(componentName + '-search-input')}
|
||||||
dataSource={boxDataSource} // 数据源
|
size='middle'
|
||||||
targetItems={targetItems} // 右侧选中项
|
onChange={(e) => onSearch?.(e)}
|
||||||
checkedKeys={checkedKeys} // 左侧选中
|
placeholder='请输入盒子名称'
|
||||||
onReset={onBoxChoiceReset} // 重置按钮事件
|
{...searchInputProps}
|
||||||
onOk={onBoxChoiceOk} // 确定按钮事件
|
/>
|
||||||
onTreeCheck={onTreeCheck} // 树check选中事件
|
{customFilter || (!noFilter && (
|
||||||
onItemDelete={onItemDelete} // 右侧点击删除事件
|
<div
|
||||||
/>
|
className={classNames(componentName + '-search-btns')}
|
||||||
<div className={classNames(componentName + '-search')}>
|
>
|
||||||
<Input
|
{/* @ts-ignore */}
|
||||||
className={classNames(componentName + '-search-input')}
|
{initFilter(filterList)}
|
||||||
size='middle'
|
</div>
|
||||||
onChange={(e) => onSearch?.(e)}
|
))}
|
||||||
placeholder='请输入盒子名称'
|
</div>
|
||||||
{...searchInputProps}
|
)}
|
||||||
/>
|
{/* 默认操作按钮 */}
|
||||||
{customImport || (
|
|
||||||
<div
|
|
||||||
className={classNames(componentName + '-search-btns')}
|
|
||||||
>
|
|
||||||
<Button type="text" onClick={() => onBatch?.() || handleCheckable()} icon={isTreeCheckable ? <SwitcherOutlined /> : <DiffOutlined />} />
|
|
||||||
<Button type="text" onClick={() => onClockClick?.()} icon={<ClockCircleOutlined />} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{/* 是否显示操作按钮 */}
|
|
||||||
{showOptions && (
|
{showOptions && (
|
||||||
<>
|
<>
|
||||||
<div className={classNames(componentName + '-btns')}>
|
<div className={classNames(componentName + '-btns')}>
|
||||||
<Button className={classNames(componentName + '-btns-common')} type='text' onClick={() => onImport?.()} icon={<ImportOutlined />} >导入盒子</Button>
|
{initOptions(optionList)}
|
||||||
<Divider className={classNames(componentName + '-btns-divider')} type="vertical" />
|
|
||||||
{onCreate ?
|
|
||||||
(
|
|
||||||
<Button className={classNames(componentName + '-btns-common')} onClick={onCreate} type='text' icon={<FolderAddOutlined />} >新建组</Button>
|
|
||||||
) : (
|
|
||||||
<ModalForm<{
|
|
||||||
name: string
|
|
||||||
boxList?: any[]
|
|
||||||
}>
|
|
||||||
className={classNames(componentName + '-create-modal')}
|
|
||||||
open={onCreate ? false : undefined}
|
|
||||||
formRef={createFormRef}
|
|
||||||
title="新建组"
|
|
||||||
modalProps={{ destroyOnClose: true }}
|
|
||||||
layout='horizontal'
|
|
||||||
labelCol={{ span: 6 }}
|
|
||||||
wrapperCol={{ span: 18 }}
|
|
||||||
trigger={<Button type='text' className={classNames(componentName + '-btns-common')} icon={<FolderAddOutlined />} >新建组</Button>}
|
|
||||||
submitter={{
|
|
||||||
searchConfig: {
|
|
||||||
submitText: '确定',
|
|
||||||
resetText: '取消',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
onFinish={onCreateSubmit}
|
|
||||||
>
|
|
||||||
<ProFormText
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
max: 20,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
pattern: /^[^\s]*$/g,
|
|
||||||
message: '禁止输入空格'
|
|
||||||
}
|
|
||||||
]}
|
|
||||||
fieldProps={{ showCount: true }}
|
|
||||||
width="md"
|
|
||||||
name="name"
|
|
||||||
label="盒子组名称"
|
|
||||||
placeholder="请输入盒子名称"
|
|
||||||
/>
|
|
||||||
<ProFormText
|
|
||||||
width="md"
|
|
||||||
name="boxList"
|
|
||||||
label="盒子选择"
|
|
||||||
fieldProps={{
|
|
||||||
readOnly: true,
|
|
||||||
value: `已选择${createFormRef.current?.getFieldValue('boxList')?.length || 0}个盒子`,
|
|
||||||
suffix: (
|
|
||||||
<Space>
|
|
||||||
<a onClick={() => {
|
|
||||||
createFormRef.current?.setFieldValue('boxList', null)
|
|
||||||
onBoxChoiceReset()
|
|
||||||
}} >恢复默认</a>
|
|
||||||
<a onClick={() => setBoxChoiceOpen(true)}>范围选择</a>
|
|
||||||
</Space>
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ModalForm>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
<Divider className={classNames(componentName + '-btns-divider')} type="vertical" />
|
|
||||||
{/* @ts-ignore */}
|
|
||||||
<Button className={classNames(componentName + '-btns-common')} danger type='text' icon={<CloseCircleOutlined />} disabled={treeProps?.checkedKeys?.length <= 0} onClick={onBoxBatchDelete} >删除</Button>
|
|
||||||
</div>
|
</div>
|
||||||
<Divider style={{ margin: 0 }} />
|
<Divider style={{ margin: 0 }} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{extraBtns}
|
{extraBtns}
|
||||||
|
{showTagPanel && (
|
||||||
|
<div className={classNames(componentName + '-tags')}>
|
||||||
|
<span
|
||||||
|
className={classNames(componentName + '-tags-tag')}
|
||||||
|
style={tagExpandAll ? {
|
||||||
|
marginBottom: '12px',
|
||||||
|
display: tagExpandAll ? 'block' : 'inline-block'
|
||||||
|
} : {}
|
||||||
|
}
|
||||||
|
>标签:</span>
|
||||||
|
{initTagPanel(tagList, tagExpandAll)}
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
componentName + '-tags-tag_option',
|
||||||
|
{ [componentName + '-tags-tag_absolute']: tagExpandAll },
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{tagExpandAll && (
|
||||||
|
<span
|
||||||
|
className={classNames(componentName + '-tags-tag_common', componentName + '-tags-tag_fz12')}
|
||||||
|
onClick={onResetTags}
|
||||||
|
>重置</span>
|
||||||
|
)}
|
||||||
|
<span
|
||||||
|
className={classNames(componentName + '-tags-tag_common', componentName + '-tags-tag_fz12')}
|
||||||
|
onClick={onTagExpand}
|
||||||
|
>{tagExpandAll ? '收起' : '更多'}<IconFont icon={tagExpandAll ? 'icon-shangjiantou' : 'icon-xiajiantou'} /></span>
|
||||||
|
</div>
|
||||||
|
{tagFootRender}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<BoxTree
|
<BoxTree
|
||||||
className={classNames(componentName + '-tree')}
|
className={classNames(componentName + '-tree')}
|
||||||
treeCheckable={isTreeCheckable}
|
treeCheckable={isTreeCheckable}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { BoxSelectTree } from '@zhst/biz';
|
import { BoxSelectTree } from '@zhst/biz';
|
||||||
import { treeData, boxDataSource } from './mock'
|
import { treeData, boxDataSource } from './mock'
|
||||||
import { Select, TreeProps, Modal, Checkbox } from 'antd';
|
import { Select, TreeProps, Modal, Checkbox, Button } from 'antd';
|
||||||
|
|
||||||
const { Option } = Select
|
const { Option } = Select
|
||||||
|
|
||||||
@ -81,6 +81,7 @@ const demo = () => {
|
|||||||
onItemRenameFinish: async (val, data) => console.log('盒子重命名提交(返回boolean,控制弹框显示\隐藏)', val, data),
|
onItemRenameFinish: async (val, data) => console.log('盒子重命名提交(返回boolean,控制弹框显示\隐藏)', val, data),
|
||||||
checkedKeys,
|
checkedKeys,
|
||||||
}}
|
}}
|
||||||
|
footer={<Button block >加载更多</Button>}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
68
packages/biz/src/boxSelectTree/demo/customFilter.tsx
Normal file
68
packages/biz/src/boxSelectTree/demo/customFilter.tsx
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { BoxSelectTree } from '@zhst/biz';
|
||||||
|
import { treeData, boxDataSource } from './mock'
|
||||||
|
import { FilterOutlined } from '@ant-design/icons';
|
||||||
|
import { Badge } from 'antd';
|
||||||
|
|
||||||
|
const demo = () => {
|
||||||
|
const [activeKey] = useState('1')
|
||||||
|
const [checkedKeys] = useState<string[]>([]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ border: '1px solid #ccc', width: '340px', minHeight: '900px' }}>
|
||||||
|
<BoxSelectTree
|
||||||
|
data={activeKey === '1' ? treeData : boxDataSource}
|
||||||
|
boxDataSource={boxDataSource}
|
||||||
|
showOptions={false}
|
||||||
|
tabsProps={{
|
||||||
|
activeKey,
|
||||||
|
}}
|
||||||
|
treeProps={{
|
||||||
|
checkedKeys
|
||||||
|
}}
|
||||||
|
filterList={[
|
||||||
|
{
|
||||||
|
label: '过滤',
|
||||||
|
key: 'multi',
|
||||||
|
icon: <FilterOutlined />,
|
||||||
|
type: 'dropdown',
|
||||||
|
showTooltip: false,
|
||||||
|
dropdownConfig: {
|
||||||
|
menu: {
|
||||||
|
// 自定义返回项
|
||||||
|
_internalRenderMenuItem: (originNode, menuItemProps, stateProps) => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{originNode}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
selectable: true,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: <p style={{ margin: '0', textAlign: 'center' }} >全部</p>,
|
||||||
|
key: 'all',
|
||||||
|
onClick: () => console.log('多选1')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <Badge status="success" />,
|
||||||
|
label: '多选1',
|
||||||
|
key: 'multi1',
|
||||||
|
onClick: () => console.log('多选1')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '多选2',
|
||||||
|
icon: <Badge status='error' />,
|
||||||
|
key: 'multi2',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default demo;
|
33
packages/biz/src/boxSelectTree/demo/customOptions.tsx
Normal file
33
packages/biz/src/boxSelectTree/demo/customOptions.tsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { BoxSelectTree } from '@zhst/biz';
|
||||||
|
import { treeData, boxDataSource } from './mock'
|
||||||
|
import { CloseCircleOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
|
const demo = () => {
|
||||||
|
const [activeKey, setActiveKey] = useState('1')
|
||||||
|
const [checkedKeys, setCheckedKeys] = useState<string[]>([]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ border: '1px solid #ccc', width: '340px', minHeight: '900px' }}>
|
||||||
|
<BoxSelectTree
|
||||||
|
data={activeKey === '1' ? treeData : boxDataSource}
|
||||||
|
boxDataSource={boxDataSource}
|
||||||
|
tabsProps={{
|
||||||
|
activeKey,
|
||||||
|
}}
|
||||||
|
treeProps={{
|
||||||
|
checkedKeys
|
||||||
|
}}
|
||||||
|
optionList={[
|
||||||
|
{
|
||||||
|
label: '删除',
|
||||||
|
key: 'del',
|
||||||
|
icon: <CloseCircleOutlined />,
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default demo;
|
@ -2,10 +2,12 @@ import React, { useState } from 'react';
|
|||||||
import { BoxSelectTree } from '@zhst/biz';
|
import { BoxSelectTree } from '@zhst/biz';
|
||||||
import { treeData, boxDataSource } from './mock'
|
import { treeData, boxDataSource } from './mock'
|
||||||
import { Button } from 'antd';
|
import { Button } from 'antd';
|
||||||
|
import { ClockCircleOutlined, DiffOutlined, SwitcherOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
const demo = () => {
|
const demo = () => {
|
||||||
const [activeKey, setActiveKey] = useState('1')
|
const [activeKey, setActiveKey] = useState('1')
|
||||||
const [checkedKeys, setCheckedKeys] = useState<string[]>([]);
|
const [checkedKeys, setCheckedKeys] = useState<string[]>([]);
|
||||||
|
const [isTreeCheckable, setIsTreeCheckable] = useState(false)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ border: '1px solid #ccc', width: '340px', minHeight: '900px' }}>
|
<div style={{ border: '1px solid #ccc', width: '340px', minHeight: '900px' }}>
|
||||||
@ -13,10 +15,23 @@ const demo = () => {
|
|||||||
data={activeKey === '1' ? treeData : boxDataSource}
|
data={activeKey === '1' ? treeData : boxDataSource}
|
||||||
boxDataSource={boxDataSource}
|
boxDataSource={boxDataSource}
|
||||||
showOptions={false}
|
showOptions={false}
|
||||||
extraBtns={<Button type="dashed" style={{ color: 'green' }}>自定义按钮</Button>}
|
extraBtns={<div><Button type="dashed" style={{ color: 'red' }}>自定义区域</Button> Hello Lambo</div>}
|
||||||
tabsProps={{
|
tabsProps={{
|
||||||
activeKey,
|
activeKey,
|
||||||
}}
|
}}
|
||||||
|
filterList={[
|
||||||
|
{
|
||||||
|
label: '多选',
|
||||||
|
key: 'multi',
|
||||||
|
icon: isTreeCheckable ? <SwitcherOutlined /> : <DiffOutlined />,
|
||||||
|
onClick: () => setIsTreeCheckable(pre => !pre)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '时钟',
|
||||||
|
key: 'clock',
|
||||||
|
icon: <ClockCircleOutlined />,
|
||||||
|
}
|
||||||
|
]}
|
||||||
treeProps={{
|
treeProps={{
|
||||||
checkedKeys
|
checkedKeys
|
||||||
}}
|
}}
|
||||||
|
27
packages/biz/src/boxSelectTree/demo/noFilter.tsx
Normal file
27
packages/biz/src/boxSelectTree/demo/noFilter.tsx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { BoxSelectTree } from '@zhst/biz';
|
||||||
|
import { treeData, boxDataSource } from './mock'
|
||||||
|
|
||||||
|
const demo = () => {
|
||||||
|
const [activeKey, setActiveKey] = useState('1')
|
||||||
|
const [checkedKeys, setCheckedKeys] = useState<string[]>([]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ border: '1px solid #ccc', width: '340px', minHeight: '900px' }}>
|
||||||
|
<BoxSelectTree
|
||||||
|
data={activeKey === '1' ? treeData : boxDataSource}
|
||||||
|
boxDataSource={boxDataSource}
|
||||||
|
showOptions={false}
|
||||||
|
tabsProps={{
|
||||||
|
activeKey,
|
||||||
|
}}
|
||||||
|
treeProps={{
|
||||||
|
checkedKeys
|
||||||
|
}}
|
||||||
|
noFilter
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default demo;
|
@ -30,7 +30,7 @@ const demo = () => {
|
|||||||
tabsProps={{
|
tabsProps={{
|
||||||
activeKey,
|
activeKey,
|
||||||
}}
|
}}
|
||||||
customImport={<Button type="text" icon={<FilterOutlined />} />}
|
customImport={<div style={{ color: 'red' }}>自定义区域</div>}
|
||||||
searchInputProps={{
|
searchInputProps={{
|
||||||
addonBefore: (
|
addonBefore: (
|
||||||
<Select
|
<Select
|
||||||
@ -43,7 +43,6 @@ const demo = () => {
|
|||||||
>
|
>
|
||||||
{[
|
{[
|
||||||
{ value: '1', label: '盒子' },
|
{ value: '1', label: '盒子' },
|
||||||
{ value: '2', label: '盒子组' }
|
|
||||||
].map(item => (
|
].map(item => (
|
||||||
<Option value={item.value}>{item.label}</Option>
|
<Option value={item.value}>{item.label}</Option>
|
||||||
))}
|
))}
|
||||||
|
84
packages/biz/src/boxSelectTree/demo/withTagPanel.tsx
Normal file
84
packages/biz/src/boxSelectTree/demo/withTagPanel.tsx
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { BoxSelectTree } from '@zhst/biz';
|
||||||
|
import { treeData, boxDataSource } from './mock'
|
||||||
|
import { Button, Switch } from 'antd';
|
||||||
|
|
||||||
|
const demo = () => {
|
||||||
|
const [activeKey] = useState('1')
|
||||||
|
const [checkedKeys] = useState<string[]>([]);
|
||||||
|
const [checkedTags, setCheckedTags] = useState<string[]>([]);
|
||||||
|
const [tagExpandAll, setTagExpandAll] = useState(false);
|
||||||
|
const [showTagPanel, setShowTagPanel] = useState(true);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div style={{ marginBottom: '12px' }}>
|
||||||
|
显示标签面板:
|
||||||
|
<Switch value={showTagPanel} onChange={status => setShowTagPanel(status)} />
|
||||||
|
</div>
|
||||||
|
<div style={{ border: '1px solid #ccc', width: '340px', minHeight: '900px' }}>
|
||||||
|
<BoxSelectTree
|
||||||
|
data={activeKey === '1' ? treeData : boxDataSource}
|
||||||
|
boxDataSource={boxDataSource}
|
||||||
|
showOptions={false}
|
||||||
|
tabsProps={{
|
||||||
|
activeKey,
|
||||||
|
}}
|
||||||
|
treeProps={{
|
||||||
|
checkedKeys
|
||||||
|
}}
|
||||||
|
showTagPanel={showTagPanel}
|
||||||
|
tagExpandAll={tagExpandAll}
|
||||||
|
onTagExpand={() => {
|
||||||
|
setTagExpandAll(pre => !pre)
|
||||||
|
setCheckedTags([])
|
||||||
|
}}
|
||||||
|
onTagCheck={(value) => setCheckedTags(pre => {
|
||||||
|
if (pre.includes(value)) {
|
||||||
|
return pre.filter(item => item !== value)
|
||||||
|
} else {
|
||||||
|
return [...pre, value]
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
onResetTags={() => setCheckedTags([])}
|
||||||
|
checkedTags={checkedTags}
|
||||||
|
tagFootRender={<Button danger>自定义dom</Button>}
|
||||||
|
tagList={[
|
||||||
|
{
|
||||||
|
label: '标签组1',
|
||||||
|
value: '1',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
label: '标签1-1',
|
||||||
|
value: '1-1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '标签1-2',
|
||||||
|
value: '1-2',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '标签组2',
|
||||||
|
value: '2',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
label: '标签2-1',
|
||||||
|
value: '2-1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '标签2-2',
|
||||||
|
value: '2-2',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default demo;
|
@ -3,7 +3,7 @@ category: Components
|
|||||||
title: BoxSelectTree 盒子树
|
title: BoxSelectTree 盒子树
|
||||||
toc: content
|
toc: content
|
||||||
demo:
|
demo:
|
||||||
cols: 2
|
cols: 3
|
||||||
group:
|
group:
|
||||||
title: 进阶组件
|
title: 进阶组件
|
||||||
---
|
---
|
||||||
@ -15,6 +15,10 @@ group:
|
|||||||
<code src="./demo/basic.tsx">基本用法</code>
|
<code src="./demo/basic.tsx">基本用法</code>
|
||||||
<code src="./demo/extraBtns.tsx">自定义其它按钮</code>
|
<code src="./demo/extraBtns.tsx">自定义其它按钮</code>
|
||||||
<code src="./demo/noOptions.tsx">不显示其它按钮</code>
|
<code src="./demo/noOptions.tsx">不显示其它按钮</code>
|
||||||
|
<code src="./demo/customOptions.tsx">自定义配置按钮</code>
|
||||||
|
<code src="./demo/noFilter.tsx">不显示过滤按钮</code>
|
||||||
|
<code src="./demo/customFilter.tsx">自定义过滤按钮</code>
|
||||||
|
<code src="./demo/withTagPanel.tsx">标签看板</code>
|
||||||
<code src="./demo/async.tsx">异步加载数据</code>
|
<code src="./demo/async.tsx">异步加载数据</code>
|
||||||
|
|
||||||
## API
|
## API
|
||||||
@ -22,17 +26,35 @@ group:
|
|||||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
| data | 数据源 | Array[] | [] | - |
|
| data | 数据源 | Array[] | [] | - |
|
||||||
|
| tabsProps | Tabs组件的Props | 参考antd的Tabs组件 | - | - |
|
||||||
|
| searchInputProps | 搜索框的 Props | 参考antd的Input组件 | - | - |
|
||||||
|
| showOptions | 展示其它功能按钮 | boolean | true | - |
|
||||||
|
| filterList | 搜索框边上的插槽列表 | boolean | true | - |
|
||||||
|
| customImport | 自定义搜索栏边上的过滤图标 | ReactNode、string | - | - |
|
||||||
|
| extraBtns | 搜索栏下面的插槽 | ReactNode、string | - | - |
|
||||||
|
| prefixCls | class前缀 | string | - | - |
|
||||||
|
| showSearchBar | 是否显示搜索框 | boolean | true | - |
|
||||||
|
| noFilter | 是否显示搜索拓展 icon | boolean | false | - |
|
||||||
|
| filterList | 拓展列表 | IOption[] | [] | - |
|
||||||
|
| optionList | 操作按钮列表 | IOption[] | [] | - |
|
||||||
|
| showTagPanel | 是否显示标签看板 | boolean | false | - |
|
||||||
|
| tagList | 标签列表 | ITag[] | [] | - |
|
||||||
|
| tagExpandAll | 标签是否展开 | boolean | false | - |
|
||||||
|
| checkedTags | 选中的标签值 | string[] | [] | - |
|
||||||
|
| footer | 盒子树底部渲染(需要内容撑开) | ReactNode、string | - | - |
|
||||||
|
| tagFootRender | 标签看板底部自定义 | ReactNode、string | - | - |
|
||||||
|
|
||||||
|
| onResetTags | 标签重置 | () => void | [] | - |
|
||||||
|
| onTagExpand | 标签展开 | (e: any) => void | [] | - |
|
||||||
|
| onTabChange | tab切换监听 | function: (e) => void | - | - |
|
||||||
|
| onTagCheck | 标签选中事件 | (value: string, tag: ITag) => void | false | - |
|
||||||
| onSearch | 搜索监听 | function: (e) => void | - | - |
|
| onSearch | 搜索监听 | function: (e) => void | - | - |
|
||||||
| onItemSelect | 树当前选中(单选) | function: (e) => void | - | - |
|
| onItemSelect | 树当前选中(单选) | function: (e) => void | - | - |
|
||||||
| onItemCheck | 树选择(支持多选) | function: (e) => void | - | - |
|
| onItemCheck | 树选择(支持多选) | function: (e) => void | - | - |
|
||||||
| tabsProps | Tabs组件的Props | antd的Tabs组件 | - | - |
|
| onBoxDelete | 盒子删除事件 | function: (e) => void | - | 0.23.0 以后弃用 |
|
||||||
| searchInputProps | 搜索框的Props | antd的Input组件 | - | - |
|
| onBatch | 多选 | function: (e) => void | - | 0.23.0 以后弃用 |
|
||||||
| onTabChange | tab切换监听 | function: (e) => void | - | - |
|
| onBoxBatchDelete | 盒子批量删除事件 | function: (e) => void | - | 0.23.0 以后弃用 |
|
||||||
| onBoxDelete | 盒子删除事件 | function: (e) => void | - | - |
|
| onCreateSubmit | 新建提交事件 | function: (e) => void | - | 0.23.0 以后弃用 |
|
||||||
| onBoxBatchDelete | 盒子批量删除事件 | function: (e) => void | - | - |
|
| onImport | 监听导入盒子点击事件 | function: () => void | - | 0.23.0 以后弃用 |
|
||||||
| onCreateSubmit | 新建提交事件 | function: (e) => void | - | - |
|
| onClockClick | 监听时钟点击事件 | function: () => void | - | 0.23.0 以后弃用 |
|
||||||
| onImport | 监听导入盒子点击事件 | function: () => void | - | - |
|
| onCreate | 监听创建点击事件 | function: () => void | 如果不传默认用自带的创建事件 | 0.23.0 以后弃用 |
|
||||||
| onClockClick | 监听时钟点击事件 | function: () => void | - | - |
|
|
||||||
| onCreate | 监听创建点击事件 | function: () => void | 如果不传默认用自带的创建事件 | - |
|
|
||||||
| showOptions | 展示其它功能按钮 | boolean | true | - |
|
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { FC, useState } from 'react';
|
import React, { FC, useState } from 'react';
|
||||||
import { Tree, Badge, TreeDataNode, Space, TreeProps, theme } from 'antd';
|
import { Tree, Badge, TreeDataNode, Space, TreeProps, theme, ConfigProvider } from 'antd';
|
||||||
import { CloseOutlined, EditOutlined, SettingOutlined } from '@ant-design/icons'
|
import { CloseOutlined, EditOutlined, SettingOutlined } from '@ant-design/icons'
|
||||||
import { ModalForm, ProFormText } from '@ant-design/pro-components';
|
import classNames from 'classnames';
|
||||||
import './index.less'
|
import './index.less'
|
||||||
|
|
||||||
const componentName = 'zhst-biz-tree'
|
const componentName = 'zhst-biz-tree'
|
||||||
@ -30,7 +30,7 @@ const boxTree: FC<BoxTreeProps> = (props) => {
|
|||||||
showItemOption = true,
|
showItemOption = true,
|
||||||
treeCheckable = false,
|
treeCheckable = false,
|
||||||
onItemRename,
|
onItemRename,
|
||||||
onItemRenameFinish,
|
className: customClassName,
|
||||||
customOptions
|
customOptions
|
||||||
} = props
|
} = props
|
||||||
const { token } = useToken()
|
const { token } = useToken()
|
||||||
@ -45,6 +45,7 @@ const boxTree: FC<BoxTreeProps> = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Tree
|
<Tree
|
||||||
|
className={classNames(componentName, customClassName)}
|
||||||
checkable={treeCheckable}
|
checkable={treeCheckable}
|
||||||
blockNode
|
blockNode
|
||||||
onSelect={(selectedKeys, info) => {
|
onSelect={(selectedKeys, info) => {
|
||||||
@ -70,38 +71,11 @@ const boxTree: FC<BoxTreeProps> = (props) => {
|
|||||||
<Space className={`${componentName}-item-render_right`} style={{ float:'right' }} >
|
<Space className={`${componentName}-item-render_right`} style={{ float:'right' }} >
|
||||||
{customOptions || (
|
{customOptions || (
|
||||||
<>
|
<>
|
||||||
<ModalForm
|
<EditOutlined onClick={(e) => {
|
||||||
title="重命名"
|
e.preventDefault();
|
||||||
width={600}
|
e.stopPropagation();
|
||||||
modalProps={{ destroyOnClose: true }}
|
onItemRename?.(_nodeData)
|
||||||
layout='horizontal'
|
}} />
|
||||||
labelCol={{ span: 6 }}
|
|
||||||
wrapperCol={{ span: 18 }}
|
|
||||||
trigger={<EditOutlined onClick={(e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
onItemRename?.(_nodeData)
|
|
||||||
}} />}
|
|
||||||
submitter={{
|
|
||||||
searchConfig: {
|
|
||||||
submitText: '确定',
|
|
||||||
resetText: '取消',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
onFinish={async (value) => onItemRenameFinish?.(value, _nodeData)}
|
|
||||||
>
|
|
||||||
<ProFormText
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
width="md"
|
|
||||||
name="name"
|
|
||||||
label="盒子名称"
|
|
||||||
placeholder="请输入盒子名称"
|
|
||||||
/>
|
|
||||||
</ModalForm>
|
|
||||||
<SettingOutlined onClick={(e) => {
|
<SettingOutlined onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
.zhst-biz-tree-item-render {
|
.zhst-biz-tree {
|
||||||
&_right {
|
&-item-render {
|
||||||
display: none;
|
&_right {
|
||||||
}
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover &_right {
|
&:hover &_right {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
# @zhst/material
|
# @zhst/material
|
||||||
|
|
||||||
|
## 0.18.4
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies
|
||||||
|
- @zhst/biz@0.24.0
|
||||||
|
|
||||||
## 0.18.3
|
## 0.18.3
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@zhst/material",
|
"name": "@zhst/material",
|
||||||
"version": "0.18.3",
|
"version": "0.18.4",
|
||||||
"description": "物料库",
|
"description": "物料库",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"business",
|
"business",
|
||||||
|
Loading…
Reference in New Issue
Block a user