From e58b99ceb829b24f349231f27092d2fb5cecff6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=8D=8E=E6=98=A5?= Date: Wed, 6 Sep 2023 16:17:51 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=20Mask?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dev/public/mock/menus.json | 19 +++- dev/src/views/ui/mask.vue | 18 +-- dev/src/views/ui/pages/index.vue | 23 ++-- dev/src/views/ui/pages/subpage.vue | 16 ++- packages/boot/vite.config.ts | 4 +- packages/ui/src/components/mask/Mask.vue | 105 +++++++++--------- .../components/mask/components/Content.vue | 26 ++--- .../src/components/mask/components/Tabs.vue | 39 +++---- .../components/mask/components/Toolbar.vue | 2 +- packages/ui/src/components/mask/types.ts | 30 +++-- packages/ui/src/components/mask/use/index.ts | 1 + .../ui/src/components/mask/use/useMenus.ts | 61 +++++----- .../ui/src/components/mask/use/useTabs.ts | 96 +++++++++------- .../src/components/mask/use/useViewCache.ts | 33 ++++++ 14 files changed, 277 insertions(+), 196 deletions(-) create mode 100644 packages/ui/src/components/mask/use/useViewCache.ts diff --git a/dev/public/mock/menus.json b/dev/public/mock/menus.json index c45374c9e..c89fd3d6f 100644 --- a/dev/public/mock/menus.json +++ b/dev/public/mock/menus.json @@ -53,16 +53,29 @@ } ] }, + { + "id": "home", + "title": "首页工作台", + "type": "dialog", + "url": "/ui/mask" + }, { "id": "test", - "title": "测试无图标", + "title": "测试", "children": [ { "id": "test_1", - "title": "测试无图标", + "title": "测试弹窗打开", "disabled": false, - "type": "route", + "type": "dialog", "url": "/ui/mask/page?id=test_1" + }, + { + "id": "test_2", + "title": "测试新开窗口", + "disabled": false, + "type": "window", + "url": "https://www.baidu.com/" } ] }, diff --git a/dev/src/views/ui/mask.vue b/dev/src/views/ui/mask.vue index 98cccc236..dcea006ef 100644 --- a/dev/src/views/ui/mask.vue +++ b/dev/src/views/ui/mask.vue @@ -2,10 +2,9 @@ res.data); }; - const onMenuSelect = (menu: MenuDataItem) => { - router.push({ - path: '/ui/mask/page', - query: { id: menu.id } - }); + const menuAdapter = (menu: MenuDataItem) => { + return { + ...menu, + url: + !menu.type || menu.type === 'route' + ? `/ui/mask/page?id=${menu.id}` + : menu.url + }; }; const defaultActiveMenu = ( diff --git a/dev/src/views/ui/pages/index.vue b/dev/src/views/ui/pages/index.vue index 1d002a890..2bc00d6f8 100644 --- a/dev/src/views/ui/pages/index.vue +++ b/dev/src/views/ui/pages/index.vue @@ -11,25 +11,26 @@ import { ref } from 'vue'; import { ElInput, ElButton } from 'element-plus'; import { useRoute, useRouter } from 'vue-router'; - import { useMask } from '@vtj/ui'; + import { useMask, MaskTab } from '@vtj/ui'; const route = useRoute(); const router = useRouter(); const inputValue = ref(''); const mask = useMask(); const onClick = () => { router.push('/ui/mask/subpage'); - mask.exposed?.addTab({ - menu: { - id: 'aaaaa', - title: '测试' - }, - closable: true - }); }; defineOptions({ - tabAdapter() { - console.log('component tabAdapter'); - } + name: 'InnerPage' + }); + + const defineTab = async () => { + return { + // title: '自定义标签' + }; + }; + + defineExpose({ + defineTab }); diff --git a/dev/src/views/ui/pages/subpage.vue b/dev/src/views/ui/pages/subpage.vue index 69d6581ef..d82acf281 100644 --- a/dev/src/views/ui/pages/subpage.vue +++ b/dev/src/views/ui/pages/subpage.vue @@ -2,10 +2,16 @@
Subpage
- diff --git a/packages/boot/vite.config.ts b/packages/boot/vite.config.ts index 85cf16f87..6c2552291 100644 --- a/packages/boot/vite.config.ts +++ b/packages/boot/vite.config.ts @@ -10,13 +10,13 @@ const packagesPath = resolve('../../packages'); const alias = { // '@vtj/utils': join(packagesPath, 'utils/src/index.ts'), - // '@vtj/ui/lib/style.css': join(packagesPath, 'ui/src/style/index.scss'), + '@vtj/ui/lib/style.css': join(packagesPath, 'ui/src/style/index.scss'), // '@vtj/engine/lib/style.css': join( // packagesPath, // 'engine/src/style/index.scss' // ), // '@vtj/icons/lib/style.css': join(packagesPath, 'icons/src/style.scss'), - // '@vtj/ui': join(packagesPath, 'ui/src'), + '@vtj/ui': join(packagesPath, 'ui/src') // '@vtj/icons': join(packagesPath, 'icons/src'), // '@vtj/engine': join(packagesPath, 'engine/src'), // '@vtj/runtime': join(packagesPath, 'runtime/src') diff --git a/packages/ui/src/components/mask/Mask.vue b/packages/ui/src/components/mask/Mask.vue index a1d404fc8..d4745d65d 100644 --- a/packages/ui/src/components/mask/Mask.vue +++ b/packages/ui/src/components/mask/Mask.vue @@ -6,7 +6,7 @@ + @select="select"> + @toggleFavorite="toggleFavorite" + @dialog="onTabDialog"> { - select(menu); - const { type = 'route' } = menu; - if (type === 'route') { + const init = async (menus?: MenuDataItem[]) => { + if (!menus || !menus.length) return; + const fullPath = route.fullPath; + const menu = getMenuByUrl(fullPath); + if (isHomeTab(fullPath)) { + currentTabValue.value = fullPath; + } else { await nextTick(); - addTab({ - menu, - closable: false - }); + const { url = fullPath, icon, title = '新建标签页' } = menu || {}; + const view = contentRef.value.getCacheComponent(fullPath); + const defineTab = view?.exposed?.defineTab as MaskDefineTab; + const tab: MaskTab = Object.assign( + { url, icon, title, menu }, + defineTab ? await defineTab() : {} + ); + addTab(tab); + } + if (menu) { + await nextTick(); + active.value = menu; } }; - const defaultActiveMenu = - props.defaultActiveMenu ?? - ((to: RouteLocationNormalizedLoaded) => { - return flatMenus.value.find((n) => n.url === to.fullPath); - }); - - watch( - flatMenus, - () => { - if (!flatMenus.value.length) return; - const current = defaultActiveMenu(route, flatMenus.value); - if (current) { - selectMenu(current); - } else { - active.value = null; - } - }, - { immediate: true } - ); - + watch(flatMenus, init, { immediate: true }); watch( () => route.fullPath, - () => { - console.log('route change', route.fullPath); - }, - { - immediate: true - } + () => init(flatMenus.value) ); + const onTabClick = (tab: MaskTab) => { + router.push(tab.url).catch((e) => e); + }; + const onActionClick = (action: ActionProps) => { emit('actionClick', action); }; @@ -190,6 +183,10 @@ contentRef.value.refresh(); }; + const onTabDialog = (tab: MaskTab) => { + console.log('open dialog', tab); + }; + provide(MASK_INSTANCE_KEY, instance as ComponentInternalInstance); defineExpose({ @@ -198,7 +195,7 @@ flatMenus, favorites, active, - selectMenu, + select, addTab }); diff --git a/packages/ui/src/components/mask/components/Content.vue b/packages/ui/src/components/mask/components/Content.vue index e32688edf..fa8326b45 100644 --- a/packages/ui/src/components/mask/components/Content.vue +++ b/packages/ui/src/components/mask/components/Content.vue @@ -1,28 +1,24 @@ diff --git a/packages/ui/src/components/mask/components/Tabs.vue b/packages/ui/src/components/mask/components/Tabs.vue index a52e1392f..b7fa7af70 100644 --- a/packages/ui/src/components/mask/components/Tabs.vue +++ b/packages/ui/src/components/mask/components/Tabs.vue @@ -12,23 +12,21 @@ :model-value="props.value" @tab-remove="onTabRemove" @tab-click="onTabClick"> - +