Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Dr.Disrespect
vue-vben-admin
提交
72b42d7b
V
vue-vben-admin
项目概览
Dr.Disrespect
/
vue-vben-admin
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vue-vben-admin
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
72b42d7b
编写于
3月 02, 2021
作者:
V
Vben
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat(tree): add renderIcon props close #309
上级
d67bd496
变更
12
隐藏空白更改
内联
并排
Showing
12 changed file
with
340 addition
and
359 deletion
+340
-359
CHANGELOG.zh_CN.md
CHANGELOG.zh_CN.md
+1
-0
src/components/Tree/index.ts
src/components/Tree/index.ts
+2
-3
src/components/Tree/src/BasicTree.tsx
src/components/Tree/src/BasicTree.tsx
+0
-219
src/components/Tree/src/TreeIcon.ts
src/components/Tree/src/TreeIcon.ts
+17
-0
src/components/Tree/src/index.less
src/components/Tree/src/index.less
+0
-35
src/components/Tree/src/index.vue
src/components/Tree/src/index.vue
+281
-0
src/components/Tree/src/props.ts
src/components/Tree/src/props.ts
+8
-4
src/components/Tree/src/types.ts
src/components/Tree/src/types.ts
+5
-83
src/components/Tree/src/useTree.ts
src/components/Tree/src/useTree.ts
+9
-8
src/views/demo/tree/ActionTree.vue
src/views/demo/tree/ActionTree.vue
+1
-0
src/views/demo/tree/EditTree.vue
src/views/demo/tree/EditTree.vue
+15
-3
src/views/demo/tree/data.ts
src/views/demo/tree/data.ts
+1
-4
未找到文件。
CHANGELOG.zh_CN.md
浏览文件 @
72b42d7b
...
...
@@ -11,6 +11,7 @@
-
新增修改密码界面
-
新增部门管理示例界面
-
新增 WebSocket 示例和服务脚本
-
BasicTree 组件新增
`renderIcon`
属性用于控制层级图标显示
### ⚡ Performance Improvements
...
...
src/components/Tree/index.ts
浏览文件 @
72b42d7b
import
{
createAsyncComponent
}
from
'
/@/utils/factory/createAsyncComponent
'
;
export
const
BasicTree
=
createAsyncComponent
(()
=>
import
(
'
./src/BasicTree
'
));
import
BasicTree
from
'
./src/index.vue
'
;
export
{
BasicTree
};
export
type
{
ContextMenuItem
}
from
'
/@/hooks/web/useContextMenu
'
;
export
*
from
'
./src/types
'
;
src/components/Tree/src/BasicTree.tsx
已删除
100644 → 0
浏览文件 @
d67bd496
import
'
./index.less
'
;
import
type
{
ReplaceFields
,
TreeItem
,
Keys
,
CheckKeys
,
TreeActionType
}
from
'
./types
'
;
import
{
defineComponent
,
reactive
,
computed
,
unref
,
ref
,
watchEffect
,
CSSProperties
}
from
'
vue
'
;
import
{
Tree
}
from
'
ant-design-vue
'
;
import
{
DownOutlined
}
from
'
@ant-design/icons-vue
'
;
import
{
useContextMenu
,
ContextMenuItem
}
from
'
/@/hooks/web/useContextMenu
'
;
import
{
isFunction
}
from
'
/@/utils/is
'
;
import
{
omit
}
from
'
lodash-es
'
;
import
{
extendSlots
}
from
'
/@/utils/helper/tsxHelper
'
;
import
{
basicProps
}
from
'
./props
'
;
import
{
useTree
}
from
'
./useTree
'
;
import
{
useExpose
}
from
'
/@/hooks/core/useExpose
'
;
import
{
onMounted
}
from
'
vue
'
;
interface
State
{
expandedKeys
:
Keys
;
selectedKeys
:
Keys
;
checkedKeys
:
CheckKeys
;
}
const
prefixCls
=
'
basic-tree
'
;
export
default
defineComponent
({
name
:
'
BasicTree
'
,
props
:
basicProps
,
emits
:
[
'
update:expandedKeys
'
,
'
update:selectedKeys
'
,
'
update:value
'
,
'
get
'
],
setup
(
props
,
{
attrs
,
slots
,
emit
})
{
const
state
=
reactive
<
State
>
({
expandedKeys
:
props
.
expandedKeys
||
[],
selectedKeys
:
props
.
selectedKeys
||
[],
checkedKeys
:
props
.
checkedKeys
||
[],
});
const
treeDataRef
=
ref
<
TreeItem
[]
>
([]);
const
[
createContextMenu
]
=
useContextMenu
();
const
getReplaceFields
=
computed
(
():
Required
<
ReplaceFields
>
=>
{
const
{
replaceFields
}
=
props
;
return
{
children
:
'
children
'
,
title
:
'
title
'
,
key
:
'
key
'
,
...
replaceFields
,
};
}
);
const
getContentStyle
=
computed
(
():
CSSProperties
=>
{
const
{
actionList
}
=
props
;
const
width
=
actionList
.
length
*
18
;
return
{
width
:
`calc(100% -
${
width
}
px)`
,
};
}
);
const
getBindValues
=
computed
(()
=>
{
let
propsData
=
{
blockNode
:
true
,
...
attrs
,
...
props
,
expandedKeys
:
state
.
expandedKeys
,
selectedKeys
:
state
.
selectedKeys
,
checkedKeys
:
state
.
checkedKeys
,
replaceFields
:
unref
(
getReplaceFields
),
'
onUpdate:expandedKeys
'
:
(
v
:
Keys
)
=>
{
state
.
expandedKeys
=
v
;
emit
(
'
update:expandedKeys
'
,
v
);
},
'
onUpdate:selectedKeys
'
:
(
v
:
Keys
)
=>
{
state
.
selectedKeys
=
v
;
emit
(
'
update:selectedKeys
'
,
v
);
},
onCheck
:
(
v
:
CheckKeys
)
=>
{
state
.
checkedKeys
=
v
;
emit
(
'
update:value
'
,
v
);
},
onRightClick
:
handleRightClick
,
};
propsData
=
omit
(
propsData
,
'
treeData
'
);
return
propsData
;
});
const
getTreeData
=
computed
(():
TreeItem
[]
=>
unref
(
treeDataRef
));
const
{
deleteNodeByKey
,
insertNodeByKey
,
filterByLevel
,
updateNodeByKey
}
=
useTree
(
treeDataRef
,
getReplaceFields
);
// 渲染操作按钮
function
renderAction
(
node
:
TreeItem
)
{
const
{
actionList
}
=
props
;
if
(
!
actionList
||
actionList
.
length
===
0
)
return
;
return
actionList
.
map
((
item
,
index
)
=>
{
return
(
<
span
key
=
{
index
}
class
=
{
`
${
prefixCls
}
__action`
}
>
{
item
.
render
(
node
)
}
</
span
>
);
});
}
// 渲染树节点
function
renderTreeNode
({
data
}:
{
data
:
TreeItem
[]
|
undefined
})
{
if
(
!
data
)
{
return
null
;
}
return
data
.
map
((
item
)
=>
{
const
{
title
:
titleField
,
key
:
keyField
,
children
:
childrenField
}
=
unref
(
getReplaceFields
);
const
propsData
=
omit
(
item
,
'
title
'
);
const
anyItem
=
item
as
any
;
return
(
<
Tree
.
TreeNode
{
...
propsData
}
key
=
{
anyItem
?.[
keyField
]
}
>
{
{
title
:
()
=>
(
<
span
class
=
{
`
${
prefixCls
}
-title`
}
>
<
span
class
=
{
`
${
prefixCls
}
__content`
}
style
=
{
unref
(
getContentStyle
)
}
>
{
titleField
&&
anyItem
[
titleField
]
}
</
span
>
<
span
class
=
{
`
${
prefixCls
}
__actions`
}
>
{
renderAction
(
item
)
}
</
span
>
</
span
>
),
default
:
()
=>
renderTreeNode
({
data
:
childrenField
?
anyItem
[
childrenField
]
:
[]
}),
}
}
</
Tree
.
TreeNode
>
);
});
}
// 处理右键事件
async
function
handleRightClick
({
event
,
node
}:
any
)
{
const
{
rightMenuList
:
menuList
=
[],
beforeRightClick
}
=
props
;
let
rightMenuList
:
ContextMenuItem
[]
=
[];
if
(
beforeRightClick
&&
isFunction
(
beforeRightClick
))
{
rightMenuList
=
await
beforeRightClick
(
node
);
}
else
{
rightMenuList
=
menuList
;
}
if
(
!
rightMenuList
.
length
)
return
;
createContextMenu
({
event
,
items
:
rightMenuList
,
});
}
function
setExpandedKeys
(
keys
:
string
[])
{
state
.
expandedKeys
=
keys
;
}
function
getExpandedKeys
()
{
return
state
.
expandedKeys
;
}
function
setSelectedKeys
(
keys
:
string
[])
{
state
.
selectedKeys
=
keys
;
}
function
getSelectedKeys
()
{
return
state
.
selectedKeys
;
}
function
setCheckedKeys
(
keys
:
CheckKeys
)
{
state
.
checkedKeys
=
keys
;
}
function
getCheckedKeys
()
{
return
state
.
checkedKeys
;
}
watchEffect
(()
=>
{
treeDataRef
.
value
=
props
.
treeData
as
TreeItem
[];
state
.
expandedKeys
=
props
.
expandedKeys
;
state
.
selectedKeys
=
props
.
selectedKeys
;
state
.
checkedKeys
=
props
.
checkedKeys
;
});
const
instance
:
TreeActionType
=
{
setExpandedKeys
,
getExpandedKeys
,
setSelectedKeys
,
getSelectedKeys
,
setCheckedKeys
,
getCheckedKeys
,
insertNodeByKey
,
deleteNodeByKey
,
updateNodeByKey
,
filterByLevel
:
(
level
:
number
)
=>
{
state
.
expandedKeys
=
filterByLevel
(
level
);
},
};
useExpose
<
TreeActionType
>
(
instance
);
onMounted
(()
=>
{
emit
(
'
get
'
,
instance
);
});
return
()
=>
{
return
(
<
Tree
{
...(
unref
(
getBindValues
)
as
any
)
}
class
=
{
prefixCls
}
>
{
{
switcherIcon
:
()
=>
<
DownOutlined
/>,
default
:
()
=>
renderTreeNode
({
data
:
unref
(
getTreeData
)
}),
...
extendSlots
(
slots
),
}
}
</
Tree
>
);
};
},
});
src/components/Tree/src/TreeIcon.ts
0 → 100644
浏览文件 @
72b42d7b
import
type
{
VNode
,
FunctionalComponent
}
from
'
vue
'
;
import
{
h
}
from
'
vue
'
;
import
{
isString
}
from
'
/@/utils/is
'
;
import
{
Icon
}
from
'
/@/components/Icon
'
;
export
interface
ComponentProps
{
icon
:
VNode
|
string
;
}
export
const
TreeIcon
:
FunctionalComponent
=
({
icon
}:
ComponentProps
)
=>
{
if
(
!
icon
)
return
null
;
if
(
isString
(
icon
))
{
return
h
(
Icon
,
{
icon
,
class
:
'
mr-1
'
});
}
return
Icon
;
};
src/components/Tree/src/index.less
已删除
100644 → 0
浏览文件 @
d67bd496
.basic-tree {
position: relative;
&-title {
position: relative;
display: inline-block;
width: 100%;
padding-right: 10px;
&:hover {
.basic-tree__action {
visibility: visible;
}
}
}
&__content {
display: inline-block;
overflow: hidden;
}
&__actions {
position: absolute;
top: 0;
right: 0;
display: flex;
}
&__action {
margin-left: 4px;
// float: right;
// display: none;
visibility: hidden;
}
}
src/components/Tree/src/index.vue
0 → 100644
浏览文件 @
72b42d7b
<
script
lang=
"tsx"
>
import
type
{
ReplaceFields
,
Keys
,
CheckKeys
,
TreeActionType
,
TreeItem
}
from
'
./types
'
;
import
{
defineComponent
,
reactive
,
computed
,
unref
,
ref
,
watchEffect
,
onMounted
}
from
'
vue
'
;
import
{
Tree
}
from
'
ant-design-vue
'
;
import
{
TreeIcon
}
from
'
./TreeIcon
'
;
// import { DownOutlined } from '@ant-design/icons-vue';
import
{
omit
,
get
}
from
'
lodash-es
'
;
import
{
isFunction
}
from
'
/@/utils/is
'
;
import
{
extendSlots
}
from
'
/@/utils/helper/tsxHelper
'
;
import
{
useTree
}
from
'
./useTree
'
;
import
{
useContextMenu
,
ContextMenuItem
}
from
'
/@/hooks/web/useContextMenu
'
;
import
{
useExpose
}
from
'
/@/hooks/core/useExpose
'
;
import
{
useDesign
}
from
'
/@/hooks/web/useDesign
'
;
import
{
basicProps
}
from
'
./props
'
;
interface
State
{
expandedKeys
:
Keys
;
selectedKeys
:
Keys
;
checkedKeys
:
CheckKeys
;
}
export
default
defineComponent
({
name
:
'
BasicTree
'
,
props
:
basicProps
,
emits
:
[
'
update:expandedKeys
'
,
'
update:selectedKeys
'
,
'
update:value
'
,
'
get
'
],
setup
(
props
,
{
attrs
,
slots
,
emit
})
{
const
state
=
reactive
<
State
>
({
expandedKeys
:
props
.
expandedKeys
||
[],
selectedKeys
:
props
.
selectedKeys
||
[],
checkedKeys
:
props
.
checkedKeys
||
[],
});
const
treeDataRef
=
ref
<
TreeItem
[]
>
([]);
const
[
createContextMenu
]
=
useContextMenu
();
const
{
prefixCls
}
=
useDesign
(
'
basic-tree
'
);
const
getReplaceFields
=
computed
(
():
Required
<
ReplaceFields
>
=>
{
const
{
replaceFields
}
=
props
;
return
{
children
:
'
children
'
,
title
:
'
title
'
,
key
:
'
key
'
,
...
replaceFields
,
};
}
);
// const getContentStyle = computed(
// (): CSSProperties => {
// const { actionList } = props;
// const width = actionList.length * 18;
// return {
// width: `calc(100% - ${width}px)`,
// };
// }
// );
const
getBindValues
=
computed
(()
=>
{
let
propsData
=
{
blockNode
:
true
,
...
attrs
,
...
props
,
expandedKeys
:
state
.
expandedKeys
,
selectedKeys
:
state
.
selectedKeys
,
checkedKeys
:
state
.
checkedKeys
,
replaceFields
:
unref
(
getReplaceFields
),
'
onUpdate:expandedKeys
'
:
(
v
:
Keys
)
=>
{
state
.
expandedKeys
=
v
;
emit
(
'
update:expandedKeys
'
,
v
);
},
'
onUpdate:selectedKeys
'
:
(
v
:
Keys
)
=>
{
state
.
selectedKeys
=
v
;
emit
(
'
update:selectedKeys
'
,
v
);
},
onCheck
:
(
v
:
CheckKeys
,
e
)
=>
{
state
.
checkedKeys
=
v
;
console
.
log
(
e
);
emit
(
'
update:value
'
,
v
);
},
onRightClick
:
handleRightClick
,
};
propsData
=
omit
(
propsData
,
'
treeData
'
);
return
propsData
;
});
const
getTreeData
=
computed
(():
TreeItem
[]
=>
unref
(
treeDataRef
));
const
{
deleteNodeByKey
,
insertNodeByKey
,
filterByLevel
,
updateNodeByKey
}
=
useTree
(
treeDataRef
,
getReplaceFields
);
function
getIcon
(
params
:
Recordable
,
icon
?:
string
)
{
if
(
!
icon
)
{
if
(
props
.
renderIcon
&&
isFunction
(
props
.
renderIcon
))
{
return
props
.
renderIcon
(
params
);
}
}
return
icon
;
}
function
renderAction
(
node
:
TreeItem
)
{
const
{
actionList
}
=
props
;
if
(
!
actionList
||
actionList
.
length
===
0
)
return
;
return
actionList
.
map
((
item
,
index
)
=>
{
return
(
<
span
key
=
{
index
}
class
=
{
`
${
prefixCls
}
__action`
}
>
{
item
.
render
(
node
)}
<
/span
>
);
});
}
function
renderTreeNode
({
data
,
level
}:
{
data
:
TreeItem
[]
|
undefined
;
level
:
number
})
{
if
(
!
data
)
{
return
null
;
}
return
data
.
map
((
item
)
=>
{
const
{
title
:
titleField
,
key
:
keyField
,
children
:
childrenField
}
=
unref
(
getReplaceFields
);
const
propsData
=
omit
(
item
,
'
title
'
);
const
icon
=
getIcon
({
...
item
,
level
},
item
.
icon
);
return
(
<
Tree
.
TreeNode
{...
propsData
}
key
=
{
get
(
item
,
keyField
)}
>
{{
title
:
()
=>
(
<
span
class
=
{
`
${
prefixCls
}
-title`
}
>
{
icon
&&
<
TreeIcon
icon
=
{
icon
}
/>
}
<
span
class
=
{
`
${
prefixCls
}
__content`
}
// style={unref(getContentStyle)}
>
{
get
(
item
,
titleField
)}
<
/span
>
<
span
class
=
{
`
${
prefixCls
}
__actions`
}
>
{
renderAction
(
item
)}
<
/span
>
<
/span
>
),
default
:
()
=>
renderTreeNode
({
data
:
get
(
item
,
childrenField
)
||
[],
level
:
level
+
1
}),
}}
<
/Tree.TreeNode
>
);
});
}
async
function
handleRightClick
({
event
,
node
}:
any
)
{
const
{
rightMenuList
:
menuList
=
[],
beforeRightClick
}
=
props
;
let
rightMenuList
:
ContextMenuItem
[]
=
[];
if
(
beforeRightClick
&&
isFunction
(
beforeRightClick
))
{
rightMenuList
=
await
beforeRightClick
(
node
);
}
else
{
rightMenuList
=
menuList
;
}
if
(
!
rightMenuList
.
length
)
return
;
createContextMenu
({
event
,
items
:
rightMenuList
,
});
}
function
setExpandedKeys
(
keys
:
string
[])
{
state
.
expandedKeys
=
keys
;
}
function
getExpandedKeys
()
{
return
state
.
expandedKeys
;
}
function
setSelectedKeys
(
keys
:
string
[])
{
state
.
selectedKeys
=
keys
;
}
function
getSelectedKeys
()
{
return
state
.
selectedKeys
;
}
function
setCheckedKeys
(
keys
:
CheckKeys
)
{
state
.
checkedKeys
=
keys
;
}
function
getCheckedKeys
()
{
return
state
.
checkedKeys
;
}
watchEffect
(()
=>
{
treeDataRef
.
value
=
props
.
treeData
as
TreeItem
[];
state
.
expandedKeys
=
props
.
expandedKeys
;
state
.
selectedKeys
=
props
.
selectedKeys
;
state
.
checkedKeys
=
props
.
checkedKeys
;
});
const
instance
:
TreeActionType
=
{
setExpandedKeys
,
getExpandedKeys
,
setSelectedKeys
,
getSelectedKeys
,
setCheckedKeys
,
getCheckedKeys
,
insertNodeByKey
,
deleteNodeByKey
,
updateNodeByKey
,
filterByLevel
:
(
level
:
number
)
=>
{
state
.
expandedKeys
=
filterByLevel
(
level
);
},
};
useExpose
<
TreeActionType
>
(
instance
);
onMounted
(()
=>
{
emit
(
'
get
'
,
instance
);
});
return
()
=>
{
return
(
<
Tree
{...
unref
(
getBindValues
)}
showIcon
=
{
false
}
class
=
{[
prefixCls
]}
>
{{
// switcherIcon: () =>
<
DownOutlined
/>
,
default
:
()
=>
renderTreeNode
({
data
:
unref
(
getTreeData
),
level
:
1
}),
...
extendSlots
(
slots
),
}}
<
/Tree
>
);
};
},
});
</
script
>
<
style
lang=
"less"
>
@prefix-cls: ~'@{namespace}-basic-tree';
.@{prefix-cls} {
position: relative;
.ant-tree-node-content-wrapper {
position: relative;
.ant-tree-title {
position: absolute;
left: 0;
width: 100%;
}
}
&-title {
position: relative;
display: flex;
align-items: center;
width: 100%;
padding-right: 10px;
&:hover {
.@{prefix-cls}__action {
visibility: visible;
}
}
}
&__content {
display: inline-block;
overflow: hidden;
}
&__actions {
position: absolute;
top: 2px;
right: 2px;
display: flex;
}
&__action {
margin-left: 4px;
visibility: hidden;
}
}
</
style
>
src/components/Tree/src/props.ts
浏览文件 @
72b42d7b
import
{
PropType
}
from
'
vue
'
;
import
type
{
ReplaceFields
,
TreeItem
,
ActionItem
,
Keys
,
CheckKeys
}
from
'
./types
'
;
import
type
{
PropType
}
from
'
vue
'
;
import
type
{
ReplaceFields
,
ActionItem
,
Keys
,
CheckKeys
}
from
'
./types
'
;
import
type
{
ContextMenuItem
}
from
'
/@/hooks/web/useContextMenu
'
;
import
type
{
TreeDataItem
}
from
'
ant-design-vue/es/tree/Tree
'
;
export
const
basicProps
=
{
renderIcon
:
{
type
:
Function
as
PropType
<
(
params
:
Recordable
)
=>
string
>
,
},
replaceFields
:
{
type
:
Object
as
PropType
<
ReplaceFields
>
,
},
treeData
:
{
type
:
Array
as
PropType
<
TreeItem
[]
>
,
type
:
Array
as
PropType
<
Tree
Data
Item
[]
>
,
},
actionList
:
{
...
...
@@ -50,7 +54,7 @@ export const treeNodeProps = {
type
:
Object
as
PropType
<
ReplaceFields
>
,
},
treeData
:
{
type
:
Array
as
PropType
<
TreeItem
[]
>
,
type
:
Array
as
PropType
<
Tree
Data
Item
[]
>
,
default
:
()
=>
[],
},
};
src/components/Tree/src/types.ts
浏览文件 @
72b42d7b
import
type
{
TreeDataItem
}
from
'
ant-design-vue/es/tree/Tree
'
;
export
interface
ActionItem
{
render
:
(
record
:
any
)
=>
any
;
}
export
interface
TreeItem
{
/**
* Class
* @description className
* @type string
*/
class
?:
string
;
/**
* Style
* @description style of tree node
* @type string | object
*/
style
?:
string
|
object
;
/**
* Disable Checkbox
* @description Disables the checkbox of the treeNode
* @default false
* @type boolean
*/
disableCheckbox
?:
boolean
;
/**
* Disabled
* @description Disabled or not
* @default false
* @type boolean
*/
disabled
?:
boolean
;
/**
* Icon
* @description customize icon. When you pass component, whose render will receive full TreeNode props as component props
* @type any (slot | slot-scope)
*/
export
interface
TreeItem
extends
TreeDataItem
{
icon
?:
any
;
/**
* Is Leaf?
* @description Leaf node or not
* @default false
* @type boolean
*/
isLeaf
?:
boolean
;
/**
* Key
* @description Required property, should be unique in the tree
* (In tree: Used with (default)ExpandedKeys / (default)CheckedKeys / (default)SelectedKeys)
* @default internal calculated position of treeNode or undefined
* @type string | number
*/
key
:
string
|
number
;
/**
* Selectable
* @description Set whether the treeNode can be selected
* @default true
* @type boolean
*/
selectable
?:
boolean
;
/**
* Title
* @description Content showed on the treeNodes
* @default '---'
* @type any (string | slot)
*/
title
:
any
;
/**
* Value
* @description Will be treated as treeNodeFilterProp by default, should be unique in the tree
* @default undefined
* @type string
*/
value
?:
string
;
children
?:
TreeItem
[];
slots
?:
any
;
scopedSlots
?:
any
;
}
export
interface
ReplaceFields
{
...
...
@@ -107,12 +29,12 @@ export interface TreeActionType {
filterByLevel
:
(
level
:
number
)
=>
void
;
insertNodeByKey
:
(
opt
:
InsertNodeParams
)
=>
void
;
deleteNodeByKey
:
(
key
:
string
)
=>
void
;
updateNodeByKey
:
(
key
:
string
,
node
:
Omit
<
TreeItem
,
'
key
'
>
)
=>
void
;
updateNodeByKey
:
(
key
:
string
,
node
:
Omit
<
Tree
Data
Item
,
'
key
'
>
)
=>
void
;
}
export
interface
InsertNodeParams
{
parentKey
:
string
|
null
;
node
:
TreeItem
;
list
?:
TreeItem
[];
node
:
Tree
Data
Item
;
list
?:
Tree
Data
Item
[];
push
?:
'
push
'
|
'
unshift
'
;
}
src/components/Tree/src/useTree.ts
浏览文件 @
72b42d7b
import
type
{
InsertNodeParams
,
ReplaceFields
,
TreeItem
}
from
'
./types
'
;
import
type
{
InsertNodeParams
,
ReplaceFields
}
from
'
./types
'
;
import
type
{
Ref
,
ComputedRef
}
from
'
vue
'
;
import
type
{
TreeDataItem
}
from
'
ant-design-vue/es/tree/Tree
'
;
import
{
cloneDeep
}
from
'
lodash-es
'
;
import
{
unref
}
from
'
vue
'
;
import
{
forEach
}
from
'
/@/utils/helper/treeHelper
'
;
export
function
useTree
(
treeDataRef
:
Ref
<
TreeItem
[]
>
,
treeDataRef
:
Ref
<
Tree
Data
Item
[]
>
,
getReplaceFields
:
ComputedRef
<
ReplaceFields
>
)
{
//
更新节点
function
updateNodeByKey
(
key
:
string
,
node
:
Tree
Item
,
list
?:
Tree
Item
[])
{
//
Update node
function
updateNodeByKey
(
key
:
string
,
node
:
Tree
DataItem
,
list
?:
TreeData
Item
[])
{
if
(
!
key
)
return
;
const
treeData
=
list
||
unref
(
treeDataRef
);
const
{
key
:
keyField
,
children
:
childrenField
}
=
unref
(
getReplaceFields
);
...
...
@@ -30,8 +31,8 @@ export function useTree(
}
}
//
展开指定级别
function
filterByLevel
(
level
=
1
,
list
?:
TreeItem
[],
currentLevel
=
1
)
{
//
Expand the specified level
function
filterByLevel
(
level
=
1
,
list
?:
Tree
Data
Item
[],
currentLevel
=
1
)
{
if
(
!
level
)
{
return
[];
}
...
...
@@ -74,8 +75,8 @@ export function useTree(
treeDataRef
.
value
=
treeData
;
}
//
删除节点
function
deleteNodeByKey
(
key
:
string
,
list
?:
TreeItem
[])
{
//
Delete node
function
deleteNodeByKey
(
key
:
string
,
list
?:
Tree
Data
Item
[])
{
if
(
!
key
)
return
;
const
treeData
=
list
||
unref
(
treeDataRef
);
const
{
key
:
keyField
,
children
:
childrenField
}
=
unref
(
getReplaceFields
);
...
...
src/views/demo/tree/ActionTree.vue
浏览文件 @
72b42d7b
...
...
@@ -35,6 +35,7 @@
setup
()
{
const
treeRef
=
ref
<
Nullable
<
TreeActionType
>>
(
null
);
const
{
createMessage
}
=
useMessage
();
function
getTree
()
{
const
tree
=
unref
(
treeRef
);
if
(
!
tree
)
{
...
...
src/views/demo/tree/EditTree.vue
浏览文件 @
72b42d7b
<
template
>
<PageWrapper
title=
"Tree函数操作示例"
>
<div
class=
"flex"
>
<CollapseContainer
title=
"右侧操作按钮"
class=
"mr-4"
:style=
"
{ width: '33%' }">
<BasicTree
:treeData=
"treeData"
:actionList=
"actionList"
/>
<CollapseContainer
title=
"右侧操作按钮
/自定义图标
"
class=
"mr-4"
:style=
"
{ width: '33%' }">
<BasicTree
:treeData=
"treeData"
:actionList=
"actionList"
:renderIcon=
"createIcon"
/>
</CollapseContainer>
<CollapseContainer
title=
"右键菜单"
class=
"mr-4"
:style=
"
{ width: '33%' }">
...
...
@@ -61,7 +61,19 @@
},
},
];
return
{
treeData
,
actionList
,
getRightMenuList
};
function
createIcon
({
level
})
{
if
(
level
===
1
)
{
return
'
ion:git-compare-outline
'
;
}
if
(
level
===
2
)
{
return
'
ion:home
'
;
}
if
(
level
===
3
)
{
return
'
ion:airplane
'
;
}
}
return
{
treeData
,
actionList
,
getRightMenuList
,
createIcon
};
},
});
</
script
>
src/views/demo/tree/data.ts
浏览文件 @
72b42d7b
...
...
@@ -2,9 +2,8 @@ import { TreeItem } from '/@/components/Tree/index';
export
const
treeData
:
TreeItem
[]
=
[
{
title
:
'
parent
1parent
'
,
title
:
'
parent
'
,
key
:
'
0-0
'
,
icon
:
'
home|svg
'
,
children
:
[
{
title
:
'
leaf
'
,
key
:
'
0-0-0
'
},
{
...
...
@@ -20,7 +19,6 @@ export const treeData: TreeItem[] = [
{
title
:
'
parent 2
'
,
key
:
'
1-1
'
,
icon
:
'
home|svg
'
,
children
:
[
{
title
:
'
leaf
'
,
key
:
'
1-1-0
'
},
{
title
:
'
leaf
'
,
key
:
'
1-1-1
'
},
...
...
@@ -29,7 +27,6 @@ export const treeData: TreeItem[] = [
{
title
:
'
parent 3
'
,
key
:
'
2-2
'
,
icon
:
'
home|svg
'
,
children
:
[
{
title
:
'
leaf
'
,
key
:
'
2-2-0
'
},
{
title
:
'
leaf
'
,
key
:
'
2-2-1
'
},
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录