Commit cd8e924d4641fc46cacd4a934478d8861e8c3c04
1 parent
9a1ba749
perf(tree): strengthen BasicTree function
Showing
20 changed files
with
394 additions
and
138 deletions
CHANGELOG.zh_CN.md
@@ -11,8 +11,9 @@ | @@ -11,8 +11,9 @@ | ||
11 | - 新增修改密码界面 | 11 | - 新增修改密码界面 |
12 | - 新增部门管理示例界面 | 12 | - 新增部门管理示例界面 |
13 | - 新增 WebSocket 示例和服务脚本 | 13 | - 新增 WebSocket 示例和服务脚本 |
14 | -- BasicTree 组件新增 `renderIcon` 属性用于控制层级图标显示 | ||
15 | -- BasicTree->actionItem 新增 show 属性,用于动态控制按钮显示 | 14 | +- Tree 组件新增 `renderIcon` 属性用于控制层级图标显示 |
15 | +- Tree->actionItem 新增 show 属性,用于动态控制按钮显示 | ||
16 | +- Tree 新增工具栏/title/搜索功能 | ||
16 | 17 | ||
17 | ### ⚡ Performance Improvements | 18 | ### ⚡ Performance Improvements |
18 | 19 |
package.json
@@ -29,7 +29,7 @@ | @@ -29,7 +29,7 @@ | ||
29 | "dependencies": { | 29 | "dependencies": { |
30 | "@iconify/iconify": "^2.0.0-rc.6", | 30 | "@iconify/iconify": "^2.0.0-rc.6", |
31 | "@vueuse/core": "^4.3.1", | 31 | "@vueuse/core": "^4.3.1", |
32 | - "@zxcvbn-ts/core": "^0.2.0", | 32 | + "@zxcvbn-ts/core": "^0.3.0", |
33 | "ant-design-vue": "2.0.1", | 33 | "ant-design-vue": "2.0.1", |
34 | "apexcharts": "^3.25.0", | 34 | "apexcharts": "^3.25.0", |
35 | "axios": "^0.21.1", | 35 | "axios": "^0.21.1", |
src/components/StrengthMeter/src/index.vue
@@ -23,7 +23,8 @@ | @@ -23,7 +23,8 @@ | ||
23 | 23 | ||
24 | import { Input } from 'ant-design-vue'; | 24 | import { Input } from 'ant-design-vue'; |
25 | 25 | ||
26 | - import zxcvbn from '@zxcvbn-ts/core'; | 26 | + // @ts-ignore |
27 | + import { zxcvbn } from '@zxcvbn-ts/core'; | ||
27 | import { useDesign } from '/@/hooks/web/useDesign'; | 28 | import { useDesign } from '/@/hooks/web/useDesign'; |
28 | import { propTypes } from '/@/utils/propTypes'; | 29 | import { propTypes } from '/@/utils/propTypes'; |
29 | 30 |
src/components/Tree/src/TreeHeader.vue
0 → 100644
1 | +<template> | ||
2 | + <div class="flex px-2 py-1.5 items-center border-b-1"> | ||
3 | + <BasicTitle :helpMessage="helpMessage" v-if="title">{{ title }}</BasicTitle> | ||
4 | + | ||
5 | + <div class="flex flex-1 justify-end items-center cursor-pointer" v-if="search || toolbar"> | ||
6 | + <div class="mr-1 w-2/3" v-if="search"> | ||
7 | + <InputSearch :placeholder="t('common.searchText')" size="small" @change="handleSearch" /> | ||
8 | + </div> | ||
9 | + <Dropdown @click.prevent v-if="toolbar"> | ||
10 | + <Icon icon="ion:ellipsis-vertical" /> | ||
11 | + <template #overlay> | ||
12 | + <Menu @click="handleMenuClick"> | ||
13 | + <MenuItem v-for="item in toolbarList" :key="item.value"> | ||
14 | + {{ item.label }} | ||
15 | + </MenuItem> | ||
16 | + </Menu> | ||
17 | + </template> | ||
18 | + </Dropdown> | ||
19 | + </div> | ||
20 | + </div> | ||
21 | +</template> | ||
22 | +<script lang="ts"> | ||
23 | + import type { PropType } from 'vue'; | ||
24 | + import { defineComponent, ref } from 'vue'; | ||
25 | + | ||
26 | + import { Dropdown, Menu, Checkbox, Input } from 'ant-design-vue'; | ||
27 | + import { Icon } from '/@/components/Icon'; | ||
28 | + import { BasicTitle } from '/@/components/Basic'; | ||
29 | + | ||
30 | + import { propTypes } from '/@/utils/propTypes'; | ||
31 | + | ||
32 | + import { useI18n } from '/@/hooks/web/useI18n'; | ||
33 | + import { useDebounce } from '/@/hooks/core/useDebounce'; | ||
34 | + | ||
35 | + import { ToolbarEnum } from './enum'; | ||
36 | + | ||
37 | + interface MenuInfo { | ||
38 | + key: ToolbarEnum; | ||
39 | + } | ||
40 | + export default defineComponent({ | ||
41 | + name: 'BasicTreeHeader', | ||
42 | + components: { | ||
43 | + BasicTitle, | ||
44 | + Icon, | ||
45 | + Checkbox, | ||
46 | + Dropdown, | ||
47 | + Menu, | ||
48 | + MenuItem: Menu.Item, | ||
49 | + InputSearch: Input.Search, | ||
50 | + }, | ||
51 | + props: { | ||
52 | + helpMessage: { | ||
53 | + type: [String, Array] as PropType<string | string[]>, | ||
54 | + default: '', | ||
55 | + }, | ||
56 | + title: propTypes.string, | ||
57 | + toolbar: propTypes.bool, | ||
58 | + search: propTypes.bool, | ||
59 | + checkAll: propTypes.func, | ||
60 | + expandAll: propTypes.func, | ||
61 | + }, | ||
62 | + emits: ['strictly-change', 'search'], | ||
63 | + setup(props, { emit }) { | ||
64 | + const { t } = useI18n(); | ||
65 | + const toolbarList = ref([ | ||
66 | + { label: t('component.tree.selectAll'), value: ToolbarEnum.SELECT_ALL }, | ||
67 | + { label: t('component.tree.unSelectAll'), value: ToolbarEnum.UN_SELECT_ALL }, | ||
68 | + { label: t('component.tree.expandAll'), value: ToolbarEnum.EXPAND_ALL }, | ||
69 | + { label: t('component.tree.unExpandAll'), value: ToolbarEnum.UN_EXPAND_ALL }, | ||
70 | + { label: t('component.tree.checkStrictly'), value: ToolbarEnum.CHECK_STRICTLY }, | ||
71 | + { label: t('component.tree.checkUnStrictly'), value: ToolbarEnum.CHECK_UN_STRICTLY }, | ||
72 | + ]); | ||
73 | + | ||
74 | + function handleMenuClick(e: MenuInfo) { | ||
75 | + const { key } = e; | ||
76 | + switch (key) { | ||
77 | + case ToolbarEnum.SELECT_ALL: | ||
78 | + props.checkAll?.(true); | ||
79 | + break; | ||
80 | + case ToolbarEnum.UN_SELECT_ALL: | ||
81 | + props.checkAll?.(false); | ||
82 | + break; | ||
83 | + case ToolbarEnum.EXPAND_ALL: | ||
84 | + props.expandAll?.(true); | ||
85 | + break; | ||
86 | + case ToolbarEnum.UN_EXPAND_ALL: | ||
87 | + props.expandAll?.(false); | ||
88 | + break; | ||
89 | + case ToolbarEnum.CHECK_STRICTLY: | ||
90 | + emit('strictly-change', false); | ||
91 | + break; | ||
92 | + case ToolbarEnum.CHECK_UN_STRICTLY: | ||
93 | + emit('strictly-change', true); | ||
94 | + break; | ||
95 | + } | ||
96 | + } | ||
97 | + | ||
98 | + function emitChange(value?: string): void { | ||
99 | + emit('search', value); | ||
100 | + } | ||
101 | + const [debounceEmitChange] = useDebounce(emitChange, 200); | ||
102 | + | ||
103 | + function handleSearch(e: ChangeEvent): void { | ||
104 | + debounceEmitChange(e.target.value); | ||
105 | + } | ||
106 | + | ||
107 | + return { t, toolbarList, handleMenuClick, handleSearch }; | ||
108 | + }, | ||
109 | + }); | ||
110 | +</script> |
src/components/Tree/src/enum.ts
0 → 100644
src/components/Tree/src/index.vue
1 | <script lang="tsx"> | 1 | <script lang="tsx"> |
2 | import type { ReplaceFields, Keys, CheckKeys, TreeActionType, TreeItem } from './types'; | 2 | import type { ReplaceFields, Keys, CheckKeys, TreeActionType, TreeItem } from './types'; |
3 | 3 | ||
4 | - import { | ||
5 | - defineComponent, | ||
6 | - reactive, | ||
7 | - computed, | ||
8 | - unref, | ||
9 | - ref, | ||
10 | - watchEffect, | ||
11 | - onMounted, | ||
12 | - toRaw, | ||
13 | - } from 'vue'; | 4 | + import { defineComponent, reactive, computed, unref, ref, watchEffect, toRaw } from 'vue'; |
14 | import { Tree } from 'ant-design-vue'; | 5 | import { Tree } from 'ant-design-vue'; |
15 | import { TreeIcon } from './TreeIcon'; | 6 | import { TreeIcon } from './TreeIcon'; |
7 | + import TreeHeader from './TreeHeader.vue'; | ||
16 | // import { DownOutlined } from '@ant-design/icons-vue'; | 8 | // import { DownOutlined } from '@ant-design/icons-vue'; |
17 | 9 | ||
18 | import { omit, get } from 'lodash-es'; | 10 | import { omit, get } from 'lodash-es'; |
19 | import { isBoolean, isFunction } from '/@/utils/is'; | 11 | import { isBoolean, isFunction } from '/@/utils/is'; |
20 | import { extendSlots } from '/@/utils/helper/tsxHelper'; | 12 | import { extendSlots } from '/@/utils/helper/tsxHelper'; |
13 | + import { filter } from '/@/utils/helper/treeHelper'; | ||
21 | 14 | ||
22 | import { useTree } from './useTree'; | 15 | import { useTree } from './useTree'; |
23 | import { useContextMenu, ContextMenuItem } from '/@/hooks/web/useContextMenu'; | 16 | import { useContextMenu, ContextMenuItem } from '/@/hooks/web/useContextMenu'; |
@@ -30,18 +23,25 @@ | @@ -30,18 +23,25 @@ | ||
30 | expandedKeys: Keys; | 23 | expandedKeys: Keys; |
31 | selectedKeys: Keys; | 24 | selectedKeys: Keys; |
32 | checkedKeys: CheckKeys; | 25 | checkedKeys: CheckKeys; |
26 | + checkStrictly: boolean; | ||
33 | } | 27 | } |
34 | export default defineComponent({ | 28 | export default defineComponent({ |
35 | name: 'BasicTree', | 29 | name: 'BasicTree', |
36 | props: basicProps, | 30 | props: basicProps, |
37 | - emits: ['update:expandedKeys', 'update:selectedKeys', 'update:value', 'get'], | 31 | + emits: ['update:expandedKeys', 'update:selectedKeys', 'update:value', 'change'], |
38 | setup(props, { attrs, slots, emit }) { | 32 | setup(props, { attrs, slots, emit }) { |
39 | const state = reactive<State>({ | 33 | const state = reactive<State>({ |
34 | + checkStrictly: props.checkStrictly, | ||
40 | expandedKeys: props.expandedKeys || [], | 35 | expandedKeys: props.expandedKeys || [], |
41 | selectedKeys: props.selectedKeys || [], | 36 | selectedKeys: props.selectedKeys || [], |
42 | checkedKeys: props.checkedKeys || [], | 37 | checkedKeys: props.checkedKeys || [], |
43 | }); | 38 | }); |
44 | 39 | ||
40 | + const searchState = reactive({ | ||
41 | + startSearch: false, | ||
42 | + searchData: [] as TreeItem[], | ||
43 | + }); | ||
44 | + | ||
45 | const treeDataRef = ref<TreeItem[]>([]); | 45 | const treeDataRef = ref<TreeItem[]>([]); |
46 | 46 | ||
47 | const [createContextMenu] = useContextMenu(); | 47 | const [createContextMenu] = useContextMenu(); |
@@ -77,6 +77,7 @@ | @@ -77,6 +77,7 @@ | ||
77 | expandedKeys: state.expandedKeys, | 77 | expandedKeys: state.expandedKeys, |
78 | selectedKeys: state.selectedKeys, | 78 | selectedKeys: state.selectedKeys, |
79 | checkedKeys: state.checkedKeys, | 79 | checkedKeys: state.checkedKeys, |
80 | + checkStrictly: state.checkStrictly, | ||
80 | replaceFields: unref(getReplaceFields), | 81 | replaceFields: unref(getReplaceFields), |
81 | 'onUpdate:expandedKeys': (v: Keys) => { | 82 | 'onUpdate:expandedKeys': (v: Keys) => { |
82 | state.expandedKeys = v; | 83 | state.expandedKeys = v; |
@@ -88,21 +89,27 @@ | @@ -88,21 +89,27 @@ | ||
88 | }, | 89 | }, |
89 | onCheck: (v: CheckKeys) => { | 90 | onCheck: (v: CheckKeys) => { |
90 | state.checkedKeys = v; | 91 | state.checkedKeys = v; |
92 | + emit('change', v); | ||
91 | emit('update:value', v); | 93 | emit('update:value', v); |
92 | }, | 94 | }, |
93 | onRightClick: handleRightClick, | 95 | onRightClick: handleRightClick, |
94 | }; | 96 | }; |
95 | - propsData = omit(propsData, 'treeData'); | 97 | + propsData = omit(propsData, 'treeData', 'class'); |
96 | return propsData; | 98 | return propsData; |
97 | }); | 99 | }); |
98 | 100 | ||
99 | - const getTreeData = computed((): TreeItem[] => unref(treeDataRef)); | ||
100 | - | ||
101 | - const { deleteNodeByKey, insertNodeByKey, filterByLevel, updateNodeByKey } = useTree( | ||
102 | - treeDataRef, | ||
103 | - getReplaceFields | 101 | + const getTreeData = computed((): TreeItem[] => |
102 | + searchState.startSearch ? searchState.searchData : unref(treeDataRef) | ||
104 | ); | 103 | ); |
105 | 104 | ||
105 | + const { | ||
106 | + deleteNodeByKey, | ||
107 | + insertNodeByKey, | ||
108 | + filterByLevel, | ||
109 | + updateNodeByKey, | ||
110 | + getAllKeys, | ||
111 | + } = useTree(treeDataRef, getReplaceFields); | ||
112 | + | ||
106 | function getIcon(params: Recordable, icon?: string) { | 113 | function getIcon(params: Recordable, icon?: string) { |
107 | if (!icon) { | 114 | if (!icon) { |
108 | if (props.renderIcon && isFunction(props.renderIcon)) { | 115 | if (props.renderIcon && isFunction(props.renderIcon)) { |
@@ -112,60 +119,6 @@ | @@ -112,60 +119,6 @@ | ||
112 | return icon; | 119 | return icon; |
113 | } | 120 | } |
114 | 121 | ||
115 | - function renderAction(node: TreeItem) { | ||
116 | - const { actionList } = props; | ||
117 | - if (!actionList || actionList.length === 0) return; | ||
118 | - return actionList.map((item, index) => { | ||
119 | - if (isFunction(item.show)) { | ||
120 | - return item.show?.(node); | ||
121 | - } | ||
122 | - | ||
123 | - if (isBoolean(item.show)) { | ||
124 | - return item.show; | ||
125 | - } | ||
126 | - | ||
127 | - return ( | ||
128 | - <span key={index} class={`${prefixCls}__action`}> | ||
129 | - {item.render(node)} | ||
130 | - </span> | ||
131 | - ); | ||
132 | - }); | ||
133 | - } | ||
134 | - | ||
135 | - function renderTreeNode({ data, level }: { data: TreeItem[] | undefined; level: number }) { | ||
136 | - if (!data) { | ||
137 | - return null; | ||
138 | - } | ||
139 | - return data.map((item) => { | ||
140 | - const { title: titleField, key: keyField, children: childrenField } = unref( | ||
141 | - getReplaceFields | ||
142 | - ); | ||
143 | - | ||
144 | - const propsData = omit(item, 'title'); | ||
145 | - const icon = getIcon({ ...item, level }, item.icon); | ||
146 | - return ( | ||
147 | - <Tree.TreeNode {...propsData} node={toRaw(item)} key={get(item, keyField)}> | ||
148 | - {{ | ||
149 | - title: () => ( | ||
150 | - <span class={`${prefixCls}-title`}> | ||
151 | - {icon && <TreeIcon icon={icon} />} | ||
152 | - <span | ||
153 | - class={`${prefixCls}__content`} | ||
154 | - // style={unref(getContentStyle)} | ||
155 | - > | ||
156 | - {get(item, titleField)} | ||
157 | - </span> | ||
158 | - <span class={`${prefixCls}__actions`}> {renderAction({ ...item, level })}</span> | ||
159 | - </span> | ||
160 | - ), | ||
161 | - default: () => | ||
162 | - renderTreeNode({ data: get(item, childrenField) || [], level: level + 1 }), | ||
163 | - }} | ||
164 | - </Tree.TreeNode> | ||
165 | - ); | ||
166 | - }); | ||
167 | - } | ||
168 | - | ||
169 | async function handleRightClick({ event, node }: any) { | 122 | async function handleRightClick({ event, node }: any) { |
170 | const { rightMenuList: menuList = [], beforeRightClick } = props; | 123 | const { rightMenuList: menuList = [], beforeRightClick } = props; |
171 | let rightMenuList: ContextMenuItem[] = []; | 124 | let rightMenuList: ContextMenuItem[] = []; |
@@ -205,6 +158,32 @@ | @@ -205,6 +158,32 @@ | ||
205 | return state.checkedKeys; | 158 | return state.checkedKeys; |
206 | } | 159 | } |
207 | 160 | ||
161 | + function checkAll(checkAll: boolean) { | ||
162 | + state.checkedKeys = checkAll ? getAllKeys() : ([] as Keys); | ||
163 | + } | ||
164 | + | ||
165 | + function expandAll(expandAll: boolean) { | ||
166 | + state.expandedKeys = expandAll ? getAllKeys() : ([] as Keys); | ||
167 | + } | ||
168 | + | ||
169 | + function onStrictlyChange(strictly: boolean) { | ||
170 | + state.checkStrictly = strictly; | ||
171 | + } | ||
172 | + | ||
173 | + function handleSearch(searchValue: string) { | ||
174 | + if (!searchValue) { | ||
175 | + searchState.startSearch = false; | ||
176 | + return; | ||
177 | + } | ||
178 | + searchState.startSearch = true; | ||
179 | + | ||
180 | + searchState.searchData = filter(unref(treeDataRef), (node) => { | ||
181 | + const { title } = node; | ||
182 | + return title?.includes(searchValue) ?? false; | ||
183 | + // || key?.includes(searchValue); | ||
184 | + }); | ||
185 | + } | ||
186 | + | ||
208 | watchEffect(() => { | 187 | watchEffect(() => { |
209 | treeDataRef.value = props.treeData as TreeItem[]; | 188 | treeDataRef.value = props.treeData as TreeItem[]; |
210 | state.expandedKeys = props.expandedKeys; | 189 | state.expandedKeys = props.expandedKeys; |
@@ -212,6 +191,16 @@ | @@ -212,6 +191,16 @@ | ||
212 | state.checkedKeys = props.checkedKeys; | 191 | state.checkedKeys = props.checkedKeys; |
213 | }); | 192 | }); |
214 | 193 | ||
194 | + watchEffect(() => { | ||
195 | + if (props.value) { | ||
196 | + state.checkedKeys = props.value; | ||
197 | + } | ||
198 | + }); | ||
199 | + | ||
200 | + watchEffect(() => { | ||
201 | + state.checkStrictly = props.checkStrictly; | ||
202 | + }); | ||
203 | + | ||
215 | const instance: TreeActionType = { | 204 | const instance: TreeActionType = { |
216 | setExpandedKeys, | 205 | setExpandedKeys, |
217 | getExpandedKeys, | 206 | getExpandedKeys, |
@@ -222,6 +211,8 @@ | @@ -222,6 +211,8 @@ | ||
222 | insertNodeByKey, | 211 | insertNodeByKey, |
223 | deleteNodeByKey, | 212 | deleteNodeByKey, |
224 | updateNodeByKey, | 213 | updateNodeByKey, |
214 | + checkAll, | ||
215 | + expandAll, | ||
225 | filterByLevel: (level: number) => { | 216 | filterByLevel: (level: number) => { |
226 | state.expandedKeys = filterByLevel(level); | 217 | state.expandedKeys = filterByLevel(level); |
227 | }, | 218 | }, |
@@ -229,19 +220,83 @@ | @@ -229,19 +220,83 @@ | ||
229 | 220 | ||
230 | useExpose<TreeActionType>(instance); | 221 | useExpose<TreeActionType>(instance); |
231 | 222 | ||
232 | - onMounted(() => { | ||
233 | - emit('get', instance); | ||
234 | - }); | 223 | + function renderAction(node: TreeItem) { |
224 | + const { actionList } = props; | ||
225 | + if (!actionList || actionList.length === 0) return; | ||
226 | + return actionList.map((item, index) => { | ||
227 | + if (isFunction(item.show)) { | ||
228 | + return item.show?.(node); | ||
229 | + } | ||
230 | + | ||
231 | + if (isBoolean(item.show)) { | ||
232 | + return item.show; | ||
233 | + } | ||
234 | + | ||
235 | + return ( | ||
236 | + <span key={index} class={`${prefixCls}__action`}> | ||
237 | + {item.render(node)} | ||
238 | + </span> | ||
239 | + ); | ||
240 | + }); | ||
241 | + } | ||
242 | + | ||
243 | + function renderTreeNode({ data, level }: { data: TreeItem[] | undefined; level: number }) { | ||
244 | + if (!data) { | ||
245 | + return null; | ||
246 | + } | ||
247 | + return data.map((item) => { | ||
248 | + const { title: titleField, key: keyField, children: childrenField } = unref( | ||
249 | + getReplaceFields | ||
250 | + ); | ||
235 | 251 | ||
252 | + const propsData = omit(item, 'title'); | ||
253 | + const icon = getIcon({ ...item, level }, item.icon); | ||
254 | + return ( | ||
255 | + <Tree.TreeNode {...propsData} node={toRaw(item)} key={get(item, keyField)}> | ||
256 | + {{ | ||
257 | + title: () => ( | ||
258 | + <span class={`${prefixCls}-title pl-2`}> | ||
259 | + {icon && <TreeIcon icon={icon} />} | ||
260 | + <span | ||
261 | + class={`${prefixCls}__content`} | ||
262 | + // style={unref(getContentStyle)} | ||
263 | + > | ||
264 | + {get(item, titleField)} | ||
265 | + </span> | ||
266 | + <span class={`${prefixCls}__actions`}> {renderAction({ ...item, level })}</span> | ||
267 | + </span> | ||
268 | + ), | ||
269 | + default: () => | ||
270 | + renderTreeNode({ data: get(item, childrenField) || [], level: level + 1 }), | ||
271 | + }} | ||
272 | + </Tree.TreeNode> | ||
273 | + ); | ||
274 | + }); | ||
275 | + } | ||
236 | return () => { | 276 | return () => { |
277 | + const { title, helpMessage, toolbar, search } = props; | ||
237 | return ( | 278 | return ( |
238 | - <Tree {...unref(getBindValues)} showIcon={false} class={[prefixCls]}> | ||
239 | - {{ | ||
240 | - // switcherIcon: () => <DownOutlined />, | ||
241 | - default: () => renderTreeNode({ data: unref(getTreeData), level: 1 }), | ||
242 | - ...extendSlots(slots), | ||
243 | - }} | ||
244 | - </Tree> | 279 | + <div class={[prefixCls, 'h-full bg-white']}> |
280 | + {(title || toolbar || search) && ( | ||
281 | + <TreeHeader | ||
282 | + checkAll={checkAll} | ||
283 | + expandAll={expandAll} | ||
284 | + title={title} | ||
285 | + search={search} | ||
286 | + toolbar={toolbar} | ||
287 | + helpMessage={helpMessage} | ||
288 | + onStrictlyChange={onStrictlyChange} | ||
289 | + onSearch={handleSearch} | ||
290 | + /> | ||
291 | + )} | ||
292 | + <Tree {...unref(getBindValues)} showIcon={false}> | ||
293 | + {{ | ||
294 | + // switcherIcon: () => <DownOutlined />, | ||
295 | + default: () => renderTreeNode({ data: unref(getTreeData), level: 1 }), | ||
296 | + ...extendSlots(slots), | ||
297 | + }} | ||
298 | + </Tree> | ||
299 | + </div> | ||
245 | ); | 300 | ); |
246 | }; | 301 | }; |
247 | }, | 302 | }, |
@@ -251,8 +306,6 @@ | @@ -251,8 +306,6 @@ | ||
251 | @prefix-cls: ~'@{namespace}-basic-tree'; | 306 | @prefix-cls: ~'@{namespace}-basic-tree'; |
252 | 307 | ||
253 | .@{prefix-cls} { | 308 | .@{prefix-cls} { |
254 | - position: relative; | ||
255 | - | ||
256 | .ant-tree-node-content-wrapper { | 309 | .ant-tree-node-content-wrapper { |
257 | position: relative; | 310 | position: relative; |
258 | 311 | ||
@@ -278,14 +331,14 @@ | @@ -278,14 +331,14 @@ | ||
278 | } | 331 | } |
279 | 332 | ||
280 | &__content { | 333 | &__content { |
281 | - display: inline-block; | 334 | + // display: inline-block; |
282 | overflow: hidden; | 335 | overflow: hidden; |
283 | } | 336 | } |
284 | 337 | ||
285 | &__actions { | 338 | &__actions { |
286 | position: absolute; | 339 | position: absolute; |
287 | top: 2px; | 340 | top: 2px; |
288 | - right: 2px; | 341 | + right: 3px; |
289 | display: flex; | 342 | display: flex; |
290 | } | 343 | } |
291 | 344 |
src/components/Tree/src/props.ts
@@ -2,11 +2,26 @@ import type { PropType } from 'vue'; | @@ -2,11 +2,26 @@ import type { PropType } from 'vue'; | ||
2 | import type { ReplaceFields, ActionItem, Keys, CheckKeys } from './types'; | 2 | import type { ReplaceFields, ActionItem, Keys, CheckKeys } from './types'; |
3 | import type { ContextMenuItem } from '/@/hooks/web/useContextMenu'; | 3 | import type { ContextMenuItem } from '/@/hooks/web/useContextMenu'; |
4 | import type { TreeDataItem } from 'ant-design-vue/es/tree/Tree'; | 4 | import type { TreeDataItem } from 'ant-design-vue/es/tree/Tree'; |
5 | +import { propTypes } from '/@/utils/propTypes'; | ||
5 | 6 | ||
6 | export const basicProps = { | 7 | export const basicProps = { |
8 | + value: { | ||
9 | + type: Array as PropType<Keys>, | ||
10 | + }, | ||
7 | renderIcon: { | 11 | renderIcon: { |
8 | type: Function as PropType<(params: Recordable) => string>, | 12 | type: Function as PropType<(params: Recordable) => string>, |
9 | }, | 13 | }, |
14 | + | ||
15 | + helpMessage: { | ||
16 | + type: [String, Array] as PropType<string | string[]>, | ||
17 | + default: '', | ||
18 | + }, | ||
19 | + | ||
20 | + title: propTypes.string, | ||
21 | + toolbar: propTypes.bool, | ||
22 | + search: propTypes.bool, | ||
23 | + checkStrictly: propTypes.bool, | ||
24 | + | ||
10 | replaceFields: { | 25 | replaceFields: { |
11 | type: Object as PropType<ReplaceFields>, | 26 | type: Object as PropType<ReplaceFields>, |
12 | }, | 27 | }, |
src/components/Tree/src/types.ts
@@ -21,6 +21,8 @@ export type CheckKeys = | @@ -21,6 +21,8 @@ export type CheckKeys = | ||
21 | | { checked: string[] | number[]; halfChecked: string[] | number[] }; | 21 | | { checked: string[] | number[]; halfChecked: string[] | number[] }; |
22 | 22 | ||
23 | export interface TreeActionType { | 23 | export interface TreeActionType { |
24 | + checkAll: (checkAll: boolean) => void; | ||
25 | + expandAll: (expandAll: boolean) => void; | ||
24 | setExpandedKeys: (keys: Keys) => void; | 26 | setExpandedKeys: (keys: Keys) => void; |
25 | getExpandedKeys: () => Keys; | 27 | getExpandedKeys: () => Keys; |
26 | setSelectedKeys: (keys: Keys) => void; | 28 | setSelectedKeys: (keys: Keys) => void; |
src/components/Tree/src/useTree.ts
1 | -import type { InsertNodeParams, ReplaceFields } from './types'; | 1 | +import type { InsertNodeParams, Keys, ReplaceFields } from './types'; |
2 | import type { Ref, ComputedRef } from 'vue'; | 2 | import type { Ref, ComputedRef } from 'vue'; |
3 | import type { TreeDataItem } from 'ant-design-vue/es/tree/Tree'; | 3 | import type { TreeDataItem } from 'ant-design-vue/es/tree/Tree'; |
4 | 4 | ||
@@ -10,6 +10,23 @@ export function useTree( | @@ -10,6 +10,23 @@ export function useTree( | ||
10 | treeDataRef: Ref<TreeDataItem[]>, | 10 | treeDataRef: Ref<TreeDataItem[]>, |
11 | getReplaceFields: ComputedRef<ReplaceFields> | 11 | getReplaceFields: ComputedRef<ReplaceFields> |
12 | ) { | 12 | ) { |
13 | + function getAllKeys(list?: TreeDataItem[]) { | ||
14 | + const keys: string[] = []; | ||
15 | + const treeData = list || unref(treeDataRef); | ||
16 | + const { key: keyField, children: childrenField } = unref(getReplaceFields); | ||
17 | + if (!childrenField || !keyField) return keys; | ||
18 | + | ||
19 | + for (let index = 0; index < treeData.length; index++) { | ||
20 | + const node = treeData[index]; | ||
21 | + keys.push(node[keyField]!); | ||
22 | + const children = node[childrenField]; | ||
23 | + if (children && children.length) { | ||
24 | + keys.push(...(getAllKeys(children) as string[])); | ||
25 | + } | ||
26 | + } | ||
27 | + return keys as Keys; | ||
28 | + } | ||
29 | + | ||
13 | // Update node | 30 | // Update node |
14 | function updateNodeByKey(key: string, node: TreeDataItem, list?: TreeDataItem[]) { | 31 | function updateNodeByKey(key: string, node: TreeDataItem, list?: TreeDataItem[]) { |
15 | if (!key) return; | 32 | if (!key) return; |
@@ -94,5 +111,5 @@ export function useTree( | @@ -94,5 +111,5 @@ export function useTree( | ||
94 | } | 111 | } |
95 | } | 112 | } |
96 | } | 113 | } |
97 | - return { deleteNodeByKey, insertNodeByKey, filterByLevel, updateNodeByKey }; | 114 | + return { deleteNodeByKey, insertNodeByKey, filterByLevel, updateNodeByKey, getAllKeys }; |
98 | } | 115 | } |
src/locales/lang/en/component/tree.ts
0 → 100644
src/locales/lang/en/routes/demo/comp.ts
@@ -12,7 +12,7 @@ export default { | @@ -12,7 +12,7 @@ export default { | ||
12 | tree: 'Tree', | 12 | tree: 'Tree', |
13 | 13 | ||
14 | treeBasic: 'Basic', | 14 | treeBasic: 'Basic', |
15 | - editTree: 'Right-click', | 15 | + editTree: 'Searchable/toolbar', |
16 | actionTree: 'Function operation', | 16 | actionTree: 'Function operation', |
17 | 17 | ||
18 | modal: 'Modal', | 18 | modal: 'Modal', |
src/locales/lang/zh_CN/component/tree.ts
0 → 100644
src/locales/lang/zh_CN/routes/demo/comp.ts
src/router/menus/modules/demo/comp.ts
@@ -6,7 +6,10 @@ const menu: MenuModule = { | @@ -6,7 +6,10 @@ const menu: MenuModule = { | ||
6 | menu: { | 6 | menu: { |
7 | name: t('routes.demo.comp.comp'), | 7 | name: t('routes.demo.comp.comp'), |
8 | path: '/comp', | 8 | path: '/comp', |
9 | - | 9 | + tag: { |
10 | + dot: true, | ||
11 | + type: 'warn', | ||
12 | + }, | ||
10 | children: [ | 13 | children: [ |
11 | { | 14 | { |
12 | path: 'basic', | 15 | path: 'basic', |
@@ -154,6 +157,10 @@ const menu: MenuModule = { | @@ -154,6 +157,10 @@ const menu: MenuModule = { | ||
154 | { | 157 | { |
155 | path: 'tree', | 158 | path: 'tree', |
156 | name: t('routes.demo.comp.tree'), | 159 | name: t('routes.demo.comp.tree'), |
160 | + tag: { | ||
161 | + dot: true, | ||
162 | + type: 'warn', | ||
163 | + }, | ||
157 | children: [ | 164 | children: [ |
158 | { | 165 | { |
159 | path: 'basic', | 166 | path: 'basic', |
@@ -162,6 +169,10 @@ const menu: MenuModule = { | @@ -162,6 +169,10 @@ const menu: MenuModule = { | ||
162 | { | 169 | { |
163 | path: 'editTree', | 170 | path: 'editTree', |
164 | name: t('routes.demo.comp.editTree'), | 171 | name: t('routes.demo.comp.editTree'), |
172 | + tag: { | ||
173 | + dot: true, | ||
174 | + type: 'warn', | ||
175 | + }, | ||
165 | }, | 176 | }, |
166 | { | 177 | { |
167 | path: 'actionTree', | 178 | path: 'actionTree', |
@@ -172,9 +183,6 @@ const menu: MenuModule = { | @@ -172,9 +183,6 @@ const menu: MenuModule = { | ||
172 | { | 183 | { |
173 | name: t('routes.demo.editor.editor'), | 184 | name: t('routes.demo.editor.editor'), |
174 | path: 'editor', | 185 | path: 'editor', |
175 | - tag: { | ||
176 | - content: 'new', | ||
177 | - }, | ||
178 | children: [ | 186 | children: [ |
179 | { | 187 | { |
180 | path: 'markdown', | 188 | path: 'markdown', |
src/router/menus/modules/demo/system.ts
@@ -22,21 +22,21 @@ const menu: MenuModule = { | @@ -22,21 +22,21 @@ const menu: MenuModule = { | ||
22 | path: 'role', | 22 | path: 'role', |
23 | name: t('routes.demo.system.role'), | 23 | name: t('routes.demo.system.role'), |
24 | tag: { | 24 | tag: { |
25 | - content: 'new', | 25 | + dot: true, |
26 | }, | 26 | }, |
27 | }, | 27 | }, |
28 | { | 28 | { |
29 | path: 'menu', | 29 | path: 'menu', |
30 | name: t('routes.demo.system.menu'), | 30 | name: t('routes.demo.system.menu'), |
31 | tag: { | 31 | tag: { |
32 | - content: 'new', | 32 | + dot: true, |
33 | }, | 33 | }, |
34 | }, | 34 | }, |
35 | { | 35 | { |
36 | path: 'dept', | 36 | path: 'dept', |
37 | name: t('routes.demo.system.dept'), | 37 | name: t('routes.demo.system.dept'), |
38 | tag: { | 38 | tag: { |
39 | - content: 'new', | 39 | + dot: true, |
40 | }, | 40 | }, |
41 | }, | 41 | }, |
42 | 42 | ||
@@ -44,7 +44,7 @@ const menu: MenuModule = { | @@ -44,7 +44,7 @@ const menu: MenuModule = { | ||
44 | path: 'changePassword', | 44 | path: 'changePassword', |
45 | name: t('routes.demo.system.password'), | 45 | name: t('routes.demo.system.password'), |
46 | tag: { | 46 | tag: { |
47 | - content: 'new', | 47 | + dot: true, |
48 | }, | 48 | }, |
49 | }, | 49 | }, |
50 | ], | 50 | ], |
src/store/modules/permission.ts
@@ -18,7 +18,7 @@ import { transformObjToRoute } from '/@/router/helper/routeHelper'; | @@ -18,7 +18,7 @@ import { transformObjToRoute } from '/@/router/helper/routeHelper'; | ||
18 | import { transformRouteToMenu } from '/@/router/helper/menuHelper'; | 18 | import { transformRouteToMenu } from '/@/router/helper/menuHelper'; |
19 | 19 | ||
20 | import { useMessage } from '/@/hooks/web/useMessage'; | 20 | import { useMessage } from '/@/hooks/web/useMessage'; |
21 | -import { useI18n } from '/@/hooks/web/useI18n'; | 21 | +// import { useI18n } from '/@/hooks/web/useI18n'; |
22 | import { ERROR_LOG_ROUTE, PAGE_NOT_FOUND_ROUTE } from '/@/router/constant'; | 22 | import { ERROR_LOG_ROUTE, PAGE_NOT_FOUND_ROUTE } from '/@/router/constant'; |
23 | 23 | ||
24 | const { createMessage } = useMessage(); | 24 | const { createMessage } = useMessage(); |
@@ -84,7 +84,7 @@ class Permission extends VuexModule { | @@ -84,7 +84,7 @@ class Permission extends VuexModule { | ||
84 | 84 | ||
85 | @Action | 85 | @Action |
86 | async buildRoutesAction(id?: number | string): Promise<AppRouteRecordRaw[]> { | 86 | async buildRoutesAction(id?: number | string): Promise<AppRouteRecordRaw[]> { |
87 | - const { t } = useI18n(); | 87 | + // const { t } = useI18n(); |
88 | let routes: AppRouteRecordRaw[] = []; | 88 | let routes: AppRouteRecordRaw[] = []; |
89 | const roleList = toRaw(userStore.getRoleListState); | 89 | const roleList = toRaw(userStore.getRoleListState); |
90 | 90 | ||
@@ -101,7 +101,8 @@ class Permission extends VuexModule { | @@ -101,7 +101,8 @@ class Permission extends VuexModule { | ||
101 | // If you are sure that you do not need to do background dynamic permissions, please comment the entire judgment below | 101 | // If you are sure that you do not need to do background dynamic permissions, please comment the entire judgment below |
102 | } else if (permissionMode === PermissionModeEnum.BACK) { | 102 | } else if (permissionMode === PermissionModeEnum.BACK) { |
103 | createMessage.loading({ | 103 | createMessage.loading({ |
104 | - content: t('sys.app.menuLoading'), | 104 | + content: 'Loading menu...', |
105 | + // content: 't('sys.app.menuLoading')', | ||
105 | duration: 1, | 106 | duration: 1, |
106 | }); | 107 | }); |
107 | // Here to get the background routing menu logic to modify by yourself | 108 | // Here to get the background routing menu logic to modify by yourself |
src/views/demo/tree/ActionTree.vue
1 | <template> | 1 | <template> |
2 | <PageWrapper title="Tree函数操作示例" contentBackground contentClass="p-4"> | 2 | <PageWrapper title="Tree函数操作示例" contentBackground contentClass="p-4"> |
3 | <div class="mb-4"> | 3 | <div class="mb-4"> |
4 | + <a-button @click="expandAll(true)" class="mr-2"> 展开全部 </a-button> | ||
5 | + <a-button @click="expandAll(false)" class="mr-2"> 折叠全部 </a-button> | ||
6 | + <a-button @click="checkAll(true)" class="mr-2"> 全选 </a-button> | ||
7 | + <a-button @click="checkAll(false)" class="mr-2"> 全不选 </a-button> | ||
4 | <a-button @click="handleLevel(2)" class="mr-2"> 显示到第2级 </a-button> | 8 | <a-button @click="handleLevel(2)" class="mr-2"> 显示到第2级 </a-button> |
5 | <a-button @click="handleLevel(1)" class="mr-2"> 显示到第1级 </a-button> | 9 | <a-button @click="handleLevel(1)" class="mr-2"> 显示到第1级 </a-button> |
10 | + </div> | ||
11 | + <div class="mb-4"> | ||
6 | <a-button @click="handleSetCheckData" class="mr-2"> 设置勾选数据 </a-button> | 12 | <a-button @click="handleSetCheckData" class="mr-2"> 设置勾选数据 </a-button> |
7 | <a-button @click="handleGetCheckData" class="mr-2"> 获取勾选数据 </a-button> | 13 | <a-button @click="handleGetCheckData" class="mr-2"> 获取勾选数据 </a-button> |
8 | <a-button @click="handleSetSelectData" class="mr-2"> 设置选中数据 </a-button> | 14 | <a-button @click="handleSetSelectData" class="mr-2"> 设置选中数据 </a-button> |
@@ -17,21 +23,18 @@ | @@ -17,21 +23,18 @@ | ||
17 | <a-button @click="deleteNodeByKey('2-2')" class="mr-2"> 删除parent3节点 </a-button> | 23 | <a-button @click="deleteNodeByKey('2-2')" class="mr-2"> 删除parent3节点 </a-button> |
18 | <a-button @click="updateNodeByKey('1-1')" class="mr-2"> 更新parent2节点 </a-button> | 24 | <a-button @click="updateNodeByKey('1-1')" class="mr-2"> 更新parent2节点 </a-button> |
19 | </div> | 25 | </div> |
20 | - <CollapseContainer title="函数操作" class="mr-4" :canExpan="false" :style="{ width: '33%' }"> | ||
21 | - <BasicTree :treeData="treeData" ref="treeRef" :checkable="true" /> | ||
22 | - </CollapseContainer> | 26 | + <BasicTree :treeData="treeData" title="函数操作" ref="treeRef" :checkable="true" /> |
23 | </PageWrapper> | 27 | </PageWrapper> |
24 | </template> | 28 | </template> |
25 | <script lang="ts"> | 29 | <script lang="ts"> |
26 | import { defineComponent, ref, unref } from 'vue'; | 30 | import { defineComponent, ref, unref } from 'vue'; |
27 | import { BasicTree, TreeActionType } from '/@/components/Tree/index'; | 31 | import { BasicTree, TreeActionType } from '/@/components/Tree/index'; |
28 | import { treeData } from './data'; | 32 | import { treeData } from './data'; |
29 | - import { CollapseContainer } from '/@/components/Container/index'; | ||
30 | import { useMessage } from '/@/hooks/web/useMessage'; | 33 | import { useMessage } from '/@/hooks/web/useMessage'; |
31 | import { PageWrapper } from '/@/components/Page'; | 34 | import { PageWrapper } from '/@/components/Page'; |
32 | 35 | ||
33 | export default defineComponent({ | 36 | export default defineComponent({ |
34 | - components: { BasicTree, CollapseContainer, PageWrapper }, | 37 | + components: { BasicTree, PageWrapper }, |
35 | setup() { | 38 | setup() { |
36 | const treeRef = ref<Nullable<TreeActionType>>(null); | 39 | const treeRef = ref<Nullable<TreeActionType>>(null); |
37 | const { createMessage } = useMessage(); | 40 | const { createMessage } = useMessage(); |
@@ -75,6 +78,14 @@ | @@ -75,6 +78,14 @@ | ||
75 | createMessage.success(JSON.stringify(keys)); | 78 | createMessage.success(JSON.stringify(keys)); |
76 | } | 79 | } |
77 | 80 | ||
81 | + function checkAll(checkAll: boolean) { | ||
82 | + getTree().checkAll(checkAll); | ||
83 | + } | ||
84 | + | ||
85 | + function expandAll(checkAll: boolean) { | ||
86 | + getTree().expandAll(checkAll); | ||
87 | + } | ||
88 | + | ||
78 | function appendNodeByKey(parentKey: string | null = null) { | 89 | function appendNodeByKey(parentKey: string | null = null) { |
79 | getTree().insertNodeByKey({ | 90 | getTree().insertNodeByKey({ |
80 | parentKey: parentKey, | 91 | parentKey: parentKey, |
@@ -112,6 +123,8 @@ | @@ -112,6 +123,8 @@ | ||
112 | appendNodeByKey, | 123 | appendNodeByKey, |
113 | deleteNodeByKey, | 124 | deleteNodeByKey, |
114 | updateNodeByKey, | 125 | updateNodeByKey, |
126 | + checkAll, | ||
127 | + expandAll, | ||
115 | }; | 128 | }; |
116 | }, | 129 | }, |
117 | }); | 130 | }); |
src/views/demo/tree/EditTree.vue
1 | <template> | 1 | <template> |
2 | <PageWrapper title="Tree函数操作示例"> | 2 | <PageWrapper title="Tree函数操作示例"> |
3 | <div class="flex"> | 3 | <div class="flex"> |
4 | - <CollapseContainer title="右侧操作按钮/自定义图标" class="mr-4" :style="{ width: '33%' }"> | ||
5 | - <BasicTree :treeData="treeData" :actionList="actionList" :renderIcon="createIcon" /> | ||
6 | - </CollapseContainer> | ||
7 | - | ||
8 | - <CollapseContainer title="右键菜单" class="mr-4" :style="{ width: '33%' }"> | ||
9 | - <BasicTree :treeData="treeData" :beforeRightClick="getRightMenuList" /> | ||
10 | - </CollapseContainer> | 4 | + <BasicTree |
5 | + class="w-1/3" | ||
6 | + title="右侧操作按钮/自定义图标" | ||
7 | + helpMessage="帮助信息" | ||
8 | + :treeData="treeData" | ||
9 | + :actionList="actionList" | ||
10 | + :renderIcon="createIcon" | ||
11 | + /> | ||
12 | + <BasicTree | ||
13 | + class="w-1/3 mx-4" | ||
14 | + title="右键菜单" | ||
15 | + :treeData="treeData" | ||
16 | + :beforeRightClick="getRightMenuList" | ||
17 | + /> | ||
18 | + <BasicTree | ||
19 | + class="w-1/3" | ||
20 | + title="工具栏使用" | ||
21 | + toolbar | ||
22 | + checkable | ||
23 | + search | ||
24 | + :treeData="treeData" | ||
25 | + :beforeRightClick="getRightMenuList" | ||
26 | + /> | ||
11 | </div> | 27 | </div> |
12 | </PageWrapper> | 28 | </PageWrapper> |
13 | </template> | 29 | </template> |
@@ -15,12 +31,11 @@ | @@ -15,12 +31,11 @@ | ||
15 | import { defineComponent, h } from 'vue'; | 31 | import { defineComponent, h } from 'vue'; |
16 | import { BasicTree, ActionItem, ContextMenuItem } from '/@/components/Tree/index'; | 32 | import { BasicTree, ActionItem, ContextMenuItem } from '/@/components/Tree/index'; |
17 | import { treeData } from './data'; | 33 | import { treeData } from './data'; |
18 | - import { CollapseContainer } from '/@/components/Container/index'; | ||
19 | import { PlusOutlined, DeleteOutlined } from '@ant-design/icons-vue'; | 34 | import { PlusOutlined, DeleteOutlined } from '@ant-design/icons-vue'; |
20 | import { PageWrapper } from '/@/components/Page'; | 35 | import { PageWrapper } from '/@/components/Page'; |
21 | 36 | ||
22 | export default defineComponent({ | 37 | export default defineComponent({ |
23 | - components: { BasicTree, CollapseContainer, PageWrapper }, | 38 | + components: { BasicTree, PageWrapper }, |
24 | setup() { | 39 | setup() { |
25 | function handlePlus(node: any) { | 40 | function handlePlus(node: any) { |
26 | console.log(node); | 41 | console.log(node); |
src/views/demo/tree/index.vue
1 | <template> | 1 | <template> |
2 | <PageWrapper title="Tree基础示例"> | 2 | <PageWrapper title="Tree基础示例"> |
3 | <div class="flex"> | 3 | <div class="flex"> |
4 | - <CollapseContainer title="基础示例" :style="{ width: '33%' }" class="mr-4"> | ||
5 | - <BasicTree :treeData="treeData" /> | ||
6 | - </CollapseContainer> | 4 | + <BasicTree :treeData="treeData" title="基础示例" class="w-1/3" /> |
7 | 5 | ||
8 | - <CollapseContainer title="可勾选" class="mr-4" :style="{ width: '33%' }"> | ||
9 | - <BasicTree :treeData="treeData" :checkable="true" /> | ||
10 | - </CollapseContainer> | 6 | + <BasicTree :treeData="treeData" title="可勾选" :checkable="true" class="w-1/3 mx-4" /> |
11 | 7 | ||
12 | - <CollapseContainer title="默认展开/勾选示例" :style="{ width: '33%' }"> | ||
13 | - <BasicTree | ||
14 | - :treeData="treeData" | ||
15 | - :checkable="true" | ||
16 | - :expandedKeys="['0-0']" | ||
17 | - :checkedKeys="['0-0']" | ||
18 | - /> | ||
19 | - </CollapseContainer> | 8 | + <BasicTree |
9 | + title="默认展开/勾选示例" | ||
10 | + :treeData="treeData" | ||
11 | + :checkable="true" | ||
12 | + :expandedKeys="['0-0']" | ||
13 | + :checkedKeys="['0-0']" | ||
14 | + class="w-1/3" | ||
15 | + /> | ||
20 | </div> | 16 | </div> |
21 | </PageWrapper> | 17 | </PageWrapper> |
22 | </template> | 18 | </template> |
@@ -24,11 +20,10 @@ | @@ -24,11 +20,10 @@ | ||
24 | import { defineComponent } from 'vue'; | 20 | import { defineComponent } from 'vue'; |
25 | import { BasicTree } from '/@/components/Tree/index'; | 21 | import { BasicTree } from '/@/components/Tree/index'; |
26 | import { treeData } from './data'; | 22 | import { treeData } from './data'; |
27 | - import { CollapseContainer } from '/@/components/Container/index'; | ||
28 | import { PageWrapper } from '/@/components/Page'; | 23 | import { PageWrapper } from '/@/components/Page'; |
29 | 24 | ||
30 | export default defineComponent({ | 25 | export default defineComponent({ |
31 | - components: { BasicTree, CollapseContainer, PageWrapper }, | 26 | + components: { BasicTree, PageWrapper }, |
32 | setup() { | 27 | setup() { |
33 | return { treeData }; | 28 | return { treeData }; |
34 | }, | 29 | }, |
yarn.lock
@@ -1791,10 +1791,10 @@ | @@ -1791,10 +1791,10 @@ | ||
1791 | micromatch "^4.0.2" | 1791 | micromatch "^4.0.2" |
1792 | windicss "^2.2.3" | 1792 | windicss "^2.2.3" |
1793 | 1793 | ||
1794 | -"@zxcvbn-ts/core@^0.2.0": | ||
1795 | - version "0.2.0" | ||
1796 | - resolved "https://registry.npmjs.org/@zxcvbn-ts/core/-/core-0.2.0.tgz#ba3af1fed2213464ae12c0ab565798590afe8ef7" | ||
1797 | - integrity sha512-1NVKw2Tz3Iv3NE4RFTTcF2EQlmHfkNi48U0H80ZR/KLt3ANOFsCDp/mxGawdzCnBrf64E121xI49mpZDAACYZw== | 1794 | +"@zxcvbn-ts/core@^0.3.0": |
1795 | + version "0.3.0" | ||
1796 | + resolved "https://registry.npmjs.org/@zxcvbn-ts/core/-/core-0.3.0.tgz#1a021afef29b97a5f8f72458de005fa149628e32" | ||
1797 | + integrity sha512-H1SOAoC7MbccN/CU9ENZHXwvwTwh6aRt88SOkGROAN9nT88o/qDPJ5B5bElRSbjKLfmmO1LqK2K4u2lUxjbQKQ== | ||
1798 | 1798 | ||
1799 | JSONStream@^1.0.4: | 1799 | JSONStream@^1.0.4: |
1800 | version "1.3.5" | 1800 | version "1.3.5" |