Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
basic-vue-admin
概览
概览
详情
活动
周期分析
版本库
存储库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Basic
basic-vue-admin
Commits
72b42d7b
提交
72b42d7b
authored
3月 02, 2021
作者:
Vben
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat(tree): add renderIcon props close #309
上级
d67bd496
隐藏空白字符变更
内嵌
并排
正在显示
11 个修改的文件
包含
313 行增加
和
332 行删除
+313
-332
CHANGELOG.zh_CN.md
CHANGELOG.zh_CN.md
+1
-0
index.ts
src/components/Tree/index.ts
+2
-3
TreeIcon.ts
src/components/Tree/src/TreeIcon.ts
+17
-0
index.less
src/components/Tree/src/index.less
+0
-35
index.vue
src/components/Tree/src/index.vue
+254
-192
props.ts
src/components/Tree/src/props.ts
+8
-4
types.ts
src/components/Tree/src/types.ts
+5
-83
useTree.ts
src/components/Tree/src/useTree.ts
+9
-8
ActionTree.vue
src/views/demo/tree/ActionTree.vue
+1
-0
EditTree.vue
src/views/demo/tree/EditTree.vue
+15
-3
data.ts
src/views/demo/tree/data.ts
+1
-4
没有找到文件。
CHANGELOG.zh_CN.md
浏览文件 @
72b42d7b
...
@@ -11,6 +11,7 @@
...
@@ -11,6 +11,7 @@
-
新增修改密码界面
-
新增修改密码界面
-
新增部门管理示例界面
-
新增部门管理示例界面
-
新增 WebSocket 示例和服务脚本
-
新增 WebSocket 示例和服务脚本
-
BasicTree 组件新增
`renderIcon`
属性用于控制层级图标显示
### ⚡ Performance Improvements
### ⚡ Performance Improvements
...
...
src/components/Tree/index.ts
浏览文件 @
72b42d7b
import
{
createAsyncComponent
}
from
'/@/utils/factory/createAsyncComponent'
;
import
BasicTree
from
'./src/index.vue'
;
export
const
BasicTree
=
createAsyncComponent
(()
=>
import
(
'./src/BasicTree'
));
export
{
BasicTree
};
export
type
{
ContextMenuItem
}
from
'/@/hooks/web/useContextMenu'
;
export
type
{
ContextMenuItem
}
from
'/@/hooks/web/useContextMenu'
;
export
*
from
'./src/types'
;
export
*
from
'./src/types'
;
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
deleted
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/
BasicTree.tsx
→
src/components/Tree/src/
index.vue
浏览文件 @
72b42d7b
import
'./index.less'
;
<
script
lang=
"tsx"
>
import
type
{
ReplaceFields
,
Keys
,
CheckKeys
,
TreeActionType
,
TreeItem
}
from
'./types'
;
import
type
{
ReplaceFields
,
TreeItem
,
Keys
,
CheckKeys
,
TreeActionType
}
from
'./types'
;
import
{
defineComponent
,
reactive
,
computed
,
unref
,
ref
,
watchEffect
,
onMounted
}
from
'vue'
;
import
{
defineComponent
,
reactive
,
computed
,
unref
,
ref
,
watchEffect
,
CSSProperties
}
from
'vue'
;
import
{
Tree
}
from
'ant-design-vue'
;
import
{
Tree
}
from
'ant-design-vue'
;
import
{
TreeIcon
}
from
'./TreeIcon'
;
import
{
DownOutlined
}
from
'@ant-design/icons-vue'
;
// import { DownOutlined } from '@ant-design/icons-vue';
import
{
useContextMenu
,
ContextMenuItem
}
from
'/@/hooks/web/useContextMenu'
;
import
{
omit
,
get
}
from
'lodash-es'
;
import
{
isFunction
}
from
'/@/utils/is'
;
import
{
isFunction
}
from
'/@/utils/is'
;
import
{
extendSlots
}
from
'/@/utils/helper/tsxHelper'
;
import
{
omit
}
from
'lodash-es'
;
import
{
extendSlots
}
from
'/@/utils/helper/tsxHelper'
;
import
{
useTree
}
from
'./useTree'
;
import
{
useContextMenu
,
ContextMenuItem
}
from
'/@/hooks/web/useContextMenu'
;
import
{
basicProps
}
from
'./props'
;
import
{
useExpose
}
from
'/@/hooks/core/useExpose'
;
import
{
useTree
}
from
'./useTree'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
useExpose
}
from
'/@/hooks/core/useExpose'
;
import
{
onMounted
}
from
'vue'
;
import
{
basicProps
}
from
'./props'
;
interface
State
{
interface
State
{
expandedKeys
:
Keys
;
expandedKeys
:
Keys
;
selectedKeys
:
Keys
;
selectedKeys
:
Keys
;
checkedKeys
:
CheckKeys
;
checkedKeys
:
CheckKeys
;
}
}
const
prefixCls
=
'basic-tree'
;
export
default
defineComponent
({
export
default
defineComponent
({
name
:
'BasicTree'
,
name
:
'BasicTree'
,
props
:
basicProps
,
props
:
basicProps
,
emits
:
[
'update:expandedKeys'
,
'update:selectedKeys'
,
'update:value'
,
'get'
],
emits
:
[
'update:expandedKeys'
,
'update:selectedKeys'
,
'update:value'
,
'get'
],
setup
(
props
,
{
attrs
,
slots
,
emit
})
{
setup
(
props
,
{
attrs
,
slots
,
emit
})
{
const
state
=
reactive
<
State
>
({
const
state
=
reactive
<
State
>
({
expandedKeys
:
props
.
expandedKeys
||
[],
expandedKeys
:
props
.
expandedKeys
||
[],
selectedKeys
:
props
.
selectedKeys
||
[],
selectedKeys
:
props
.
selectedKeys
||
[],
checkedKeys
:
props
.
checkedKeys
||
[],
checkedKeys
:
props
.
checkedKeys
||
[],
});
});
const
treeDataRef
=
ref
<
TreeItem
[]
>
([]);
const
treeDataRef
=
ref
<
TreeItem
[]
>
([]);
const
[
createContextMenu
]
=
useContextMenu
();
const
[
createContextMenu
]
=
useContextMenu
();
const
{
prefixCls
}
=
useDesign
(
'basic-tree'
);
const
getReplaceFields
=
computed
(
const
getReplaceFields
=
computed
(
():
Required
<
ReplaceFields
>
=>
{
():
Required
<
ReplaceFields
>
=>
{
const
{
replaceFields
}
=
props
;
const
{
replaceFields
}
=
props
;
return
{
return
{
children
:
'children'
,
children
:
'children'
,
title
:
'title'
,
title
:
'title'
,
key
:
'key'
,
key
:
'key'
,
...
replaceFields
,
...
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
;
}
}
);
const
getContentStyle
=
computed
(
function
renderAction
(
node
:
TreeItem
)
{
():
CSSProperties
=>
{
const
{
actionList
}
=
props
;
const
{
actionList
}
=
props
;
const
width
=
actionList
.
length
*
18
;
if
(
!
actionList
||
actionList
.
length
===
0
)
return
;
return
{
return
actionList
.
map
((
item
,
index
)
=>
{
width
:
`calc(100% -
${
width
}
px)`
,
return
(
};
<
span
key
=
{
index
}
class
=
{
`
${
prefixCls
}
__action`
}
>
{
item
.
render
(
node
)}
<
/span
>
);
});
}
}
);
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
));
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
{
deleteNodeByKey
,
insertNodeByKey
,
filterByLevel
,
updateNodeByKey
}
=
useTree
(
const
propsData
=
omit
(
item
,
'title'
);
treeDataRef
,
const
icon
=
getIcon
({
...
item
,
level
},
item
.
icon
);
getReplaceFields
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
)
{
function
renderAction
(
node
:
TreeItem
)
{
const
{
rightMenuList
:
menuList
=
[],
beforeRightClick
}
=
props
;
const
{
actionList
}
=
props
;
let
rightMenuList
:
ContextMenuItem
[]
=
[]
;
if
(
!
actionList
||
actionList
.
length
===
0
)
return
;
if
(
beforeRightClick
&&
isFunction
(
beforeRightClick
))
{
rightMenuList
=
await
beforeRightClick
(
node
);
}
else
{
rightMenuList
=
menuList
;
}
if
(
!
rightMenuList
.
length
)
return
;
createContextMenu
({
event
,
items
:
rightMenuList
,
});
}
return
actionList
.
map
((
item
,
index
)
=>
{
function
setExpandedKeys
(
keys
:
string
[])
{
return
(
state
.
expandedKeys
=
keys
;
<
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
(
function
getExpandedKeys
()
{
getReplaceFields
return
state
.
expandedKeys
;
);
}
const
propsData
=
omit
(
item
,
'title'
);
function
setSelectedKeys
(
keys
:
string
[])
{
const
anyItem
=
item
as
any
;
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
(
return
(
<
Tree
.
TreeNode
{
...
propsData
}
key=
{
anyItem
?.[
keyField
]
}
>
<
Tree
{...
unref
(
getBindValues
)}
showIcon
=
{
false
}
class
=
{[
prefixCls
]}
>
{{
{{
title
:
()
=>
(
// switcherIcon: () =>
<
DownOutlined
/>
,
<
span
class=
{
`${prefixCls}-title`
}
>
default
:
()
=>
renderTreeNode
({
data
:
unref
(
getTreeData
),
level
:
1
}),
<
span
class=
{
`${prefixCls}__content`
}
style=
{
unref
(
getContentStyle
)
}
>
...
extendSlots
(
slots
),
{
titleField
&&
anyItem
[
titleField
]
}
</
span
>
<
span
class=
{
`${prefixCls}__actions`
}
>
{
renderAction
(
item
)
}
</
span
>
</
span
>
),
default
:
()
=>
renderTreeNode
({
data
:
childrenField
?
anyItem
[
childrenField
]
:
[]
}),
}}
}}
</
Tree
.
TreeNode
>
<
/Tree
>
);
);
});
};
}
},
});
</
script
>
<
style
lang=
"less"
>
@prefix-cls
:
~
'@{namespace}-basic-tree'
;
.@
{
prefix-cls
}
{
position
:
relative
;
// 处理右键事件
.ant-tree-node-content-wrapper
{
async
function
handleRightClick
({
event
,
node
}:
any
)
{
position
:
relative
;
const
{
rightMenuList
:
menuList
=
[],
beforeRightClick
}
=
props
;
let
rightMenuList
:
ContextMenuItem
[]
=
[];
.ant-tree-title
{
if
(
beforeRightClick
&&
isFunction
(
beforeRightClick
))
{
position
:
absolute
;
rightMenuList
=
await
beforeRightClick
(
node
);
left
:
0
;
}
else
{
width
:
100%
;
rightMenuList
=
menuList
;
}
}
if
(
!
rightMenuList
.
length
)
return
;
createContextMenu
({
event
,
items
:
rightMenuList
,
});
}
}
function
setExpandedKeys
(
keys
:
string
[])
{
&
-title
{
state
.
expandedKeys
=
keys
;
position
:
relative
;
}
display
:
flex
;
align-items
:
center
;
width
:
100%
;
padding-right
:
10px
;
function
getExpandedKeys
()
{
&:hover
{
return
state
.
expandedKeys
;
.@{prefix-cls
}
__action
{
}
visibility
:
visible
;
function
setSelectedKeys
(
keys
:
string
[])
{
}
state
.
selectedKeys
=
keys
;
}
}
}
function
getSelectedKeys
()
{
&
__content
{
return
state
.
selectedKeys
;
display
:
inline-block
;
overflow
:
hidden
;
}
}
function
setCheckedKeys
(
keys
:
CheckKeys
)
{
&
__actions
{
state
.
checkedKeys
=
keys
;
position
:
absolute
;
top
:
2px
;
right
:
2px
;
display
:
flex
;
}
}
function
getCheckedKeys
()
{
&
__action
{
return
state
.
checkedKeys
;
margin-left
:
4px
;
visibility
:
hidden
;
}
}
}
watchEffect
(()
=>
{
</
style
>
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/props.ts
浏览文件 @
72b42d7b
import
{
PropType
}
from
'vue'
;
import
type
{
PropType
}
from
'vue'
;
import
type
{
ReplaceFields
,
TreeItem
,
ActionItem
,
Keys
,
CheckKeys
}
from
'./types'
;
import
type
{
ReplaceFields
,
ActionItem
,
Keys
,
CheckKeys
}
from
'./types'
;
import
type
{
ContextMenuItem
}
from
'/@/hooks/web/useContextMenu'
;
import
type
{
ContextMenuItem
}
from
'/@/hooks/web/useContextMenu'
;
import
type
{
TreeDataItem
}
from
'ant-design-vue/es/tree/Tree'
;
export
const
basicProps
=
{
export
const
basicProps
=
{
renderIcon
:
{
type
:
Function
as
PropType
<
(
params
:
Recordable
)
=>
string
>
,
},
replaceFields
:
{
replaceFields
:
{
type
:
Object
as
PropType
<
ReplaceFields
>
,
type
:
Object
as
PropType
<
ReplaceFields
>
,
},
},
treeData
:
{
treeData
:
{
type
:
Array
as
PropType
<
TreeItem
[]
>
,
type
:
Array
as
PropType
<
Tree
Data
Item
[]
>
,
},
},
actionList
:
{
actionList
:
{
...
@@ -50,7 +54,7 @@ export const treeNodeProps = {
...
@@ -50,7 +54,7 @@ export const treeNodeProps = {
type
:
Object
as
PropType
<
ReplaceFields
>
,
type
:
Object
as
PropType
<
ReplaceFields
>
,
},
},
treeData
:
{
treeData
:
{
type
:
Array
as
PropType
<
TreeItem
[]
>
,
type
:
Array
as
PropType
<
Tree
Data
Item
[]
>
,
default
:
()
=>
[],
default
:
()
=>
[],
},
},
};
};
src/components/Tree/src/types.ts
浏览文件 @
72b42d7b
import
type
{
TreeDataItem
}
from
'ant-design-vue/es/tree/Tree'
;
export
interface
ActionItem
{
export
interface
ActionItem
{
render
:
(
record
:
any
)
=>
any
;
render
:
(
record
:
any
)
=>
any
;
}
}
export
interface
TreeItem
{
export
interface
TreeItem
extends
TreeDataItem
{
/**
* 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)
*/
icon
?:
any
;
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
{
export
interface
ReplaceFields
{
...
@@ -107,12 +29,12 @@ export interface TreeActionType {
...
@@ -107,12 +29,12 @@ export interface TreeActionType {
filterByLevel
:
(
level
:
number
)
=>
void
;
filterByLevel
:
(
level
:
number
)
=>
void
;
insertNodeByKey
:
(
opt
:
InsertNodeParams
)
=>
void
;
insertNodeByKey
:
(
opt
:
InsertNodeParams
)
=>
void
;
deleteNodeByKey
:
(
key
:
string
)
=>
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
{
export
interface
InsertNodeParams
{
parentKey
:
string
|
null
;
parentKey
:
string
|
null
;
node
:
TreeItem
;
node
:
Tree
Data
Item
;
list
?:
TreeItem
[];
list
?:
Tree
Data
Item
[];
push
?:
'push'
|
'unshift'
;
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
{
Ref
,
ComputedRef
}
from
'vue'
;
import
type
{
TreeDataItem
}
from
'ant-design-vue/es/tree/Tree'
;
import
{
cloneDeep
}
from
'lodash-es'
;
import
{
cloneDeep
}
from
'lodash-es'
;
import
{
unref
}
from
'vue'
;
import
{
unref
}
from
'vue'
;
import
{
forEach
}
from
'/@/utils/helper/treeHelper'
;
import
{
forEach
}
from
'/@/utils/helper/treeHelper'
;
export
function
useTree
(
export
function
useTree
(
treeDataRef
:
Ref
<
TreeItem
[]
>
,
treeDataRef
:
Ref
<
Tree
Data
Item
[]
>
,
getReplaceFields
:
ComputedRef
<
ReplaceFields
>
getReplaceFields
:
ComputedRef
<
ReplaceFields
>
)
{
)
{
//
更新节点
//
Update node
function
updateNodeByKey
(
key
:
string
,
node
:
Tree
Item
,
list
?:
Tree
Item
[])
{
function
updateNodeByKey
(
key
:
string
,
node
:
Tree
DataItem
,
list
?:
TreeData
Item
[])
{
if
(
!
key
)
return
;
if
(
!
key
)
return
;
const
treeData
=
list
||
unref
(
treeDataRef
);
const
treeData
=
list
||
unref
(
treeDataRef
);
const
{
key
:
keyField
,
children
:
childrenField
}
=
unref
(
getReplaceFields
);
const
{
key
:
keyField
,
children
:
childrenField
}
=
unref
(
getReplaceFields
);
...
@@ -30,8 +31,8 @@ export function useTree(
...
@@ -30,8 +31,8 @@ export function useTree(
}
}
}
}
//
展开指定级别
//
Expand the specified level
function
filterByLevel
(
level
=
1
,
list
?:
TreeItem
[],
currentLevel
=
1
)
{
function
filterByLevel
(
level
=
1
,
list
?:
Tree
Data
Item
[],
currentLevel
=
1
)
{
if
(
!
level
)
{
if
(
!
level
)
{
return
[];
return
[];
}
}
...
@@ -74,8 +75,8 @@ export function useTree(
...
@@ -74,8 +75,8 @@ export function useTree(
treeDataRef
.
value
=
treeData
;
treeDataRef
.
value
=
treeData
;
}
}
//
删除节点
//
Delete node
function
deleteNodeByKey
(
key
:
string
,
list
?:
TreeItem
[])
{
function
deleteNodeByKey
(
key
:
string
,
list
?:
Tree
Data
Item
[])
{
if
(
!
key
)
return
;
if
(
!
key
)
return
;
const
treeData
=
list
||
unref
(
treeDataRef
);
const
treeData
=
list
||
unref
(
treeDataRef
);
const
{
key
:
keyField
,
children
:
childrenField
}
=
unref
(
getReplaceFields
);
const
{
key
:
keyField
,
children
:
childrenField
}
=
unref
(
getReplaceFields
);
...
...
src/views/demo/tree/ActionTree.vue
浏览文件 @
72b42d7b
...
@@ -35,6 +35,7 @@
...
@@ -35,6 +35,7 @@
setup
()
{
setup
()
{
const
treeRef
=
ref
<
Nullable
<
TreeActionType
>>
(
null
);
const
treeRef
=
ref
<
Nullable
<
TreeActionType
>>
(
null
);
const
{
createMessage
}
=
useMessage
();
const
{
createMessage
}
=
useMessage
();
function
getTree
()
{
function
getTree
()
{
const
tree
=
unref
(
treeRef
);
const
tree
=
unref
(
treeRef
);
if
(
!
tree
)
{
if
(
!
tree
)
{
...
...
src/views/demo/tree/EditTree.vue
浏览文件 @
72b42d7b
<
template
>
<
template
>
<PageWrapper
title=
"Tree函数操作示例"
>
<PageWrapper
title=
"Tree函数操作示例"
>
<div
class=
"flex"
>
<div
class=
"flex"
>
<CollapseContainer
title=
"右侧操作按钮"
class=
"mr-4"
:style=
"
{ width: '33%' }">
<CollapseContainer
title=
"右侧操作按钮
/自定义图标
"
class=
"mr-4"
:style=
"
{ width: '33%' }">
<BasicTree
:treeData=
"treeData"
:actionList=
"actionList"
/>
<BasicTree
:treeData=
"treeData"
:actionList=
"actionList"
:renderIcon=
"createIcon"
/>
</CollapseContainer>
</CollapseContainer>
<CollapseContainer
title=
"右键菜单"
class=
"mr-4"
:style=
"
{ width: '33%' }">
<CollapseContainer
title=
"右键菜单"
class=
"mr-4"
:style=
"
{ width: '33%' }">
...
@@ -61,7 +61,19 @@
...
@@ -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
>
</
script
>
src/views/demo/tree/data.ts
浏览文件 @
72b42d7b
...
@@ -2,9 +2,8 @@ import { TreeItem } from '/@/components/Tree/index';
...
@@ -2,9 +2,8 @@ import { TreeItem } from '/@/components/Tree/index';
export
const
treeData
:
TreeItem
[]
=
[
export
const
treeData
:
TreeItem
[]
=
[
{
{
title
:
'parent
1parent
'
,
title
:
'parent '
,
key
:
'0-0'
,
key
:
'0-0'
,
icon
:
'home|svg'
,
children
:
[
children
:
[
{
title
:
'leaf'
,
key
:
'0-0-0'
},
{
title
:
'leaf'
,
key
:
'0-0-0'
},
{
{
...
@@ -20,7 +19,6 @@ export const treeData: TreeItem[] = [
...
@@ -20,7 +19,6 @@ export const treeData: TreeItem[] = [
{
{
title
:
'parent 2'
,
title
:
'parent 2'
,
key
:
'1-1'
,
key
:
'1-1'
,
icon
:
'home|svg'
,
children
:
[
children
:
[
{
title
:
'leaf'
,
key
:
'1-1-0'
},
{
title
:
'leaf'
,
key
:
'1-1-0'
},
{
title
:
'leaf'
,
key
:
'1-1-1'
},
{
title
:
'leaf'
,
key
:
'1-1-1'
},
...
@@ -29,7 +27,6 @@ export const treeData: TreeItem[] = [
...
@@ -29,7 +27,6 @@ export const treeData: TreeItem[] = [
{
{
title
:
'parent 3'
,
title
:
'parent 3'
,
key
:
'2-2'
,
key
:
'2-2'
,
icon
:
'home|svg'
,
children
:
[
children
:
[
{
title
:
'leaf'
,
key
:
'2-2-0'
},
{
title
:
'leaf'
,
key
:
'2-2-0'
},
{
title
:
'leaf'
,
key
:
'2-2-1'
},
{
title
:
'leaf'
,
key
:
'2-2-1'
},
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论