@pubinfo/core 2.0.14 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{AppSetting-Bfabd02_.js → AppSetting-Dzj6YBgW.js} +17 -17
- package/dist/{HCheckList.vue_vue_type_script_setup_true_lang-LHEWLVoX.js → HCheckList.vue_vue_type_script_setup_true_lang-OWv01eXk.js} +1 -1
- package/dist/{HToggle-B3C623BZ.js → HToggle-BnESuuPG.js} +1 -1
- package/dist/HeaderThinMenu-Co2S6vIB.js +4 -0
- package/dist/{PreferencesContent-B42MPjzA.js → PreferencesContent-DBKQJ8Ob.js} +6 -6
- package/dist/{SettingBreadcrumb-D3GS-3MN.js → SettingBreadcrumb-DmP1nJLZ.js} +3 -3
- package/dist/{SettingCopyright-KDpCggiE.js → SettingCopyright-C8_F7BB2.js} +2 -2
- package/dist/{SettingEnableTransition-BF27WYg0.js → SettingEnableTransition-BeJMq6ny.js} +2 -2
- package/dist/{SettingHome-DWyDzFcn.js → SettingHome-yGmbxzJm.js} +3 -3
- package/dist/{SettingMenu-Dz0fbIa3.js → SettingMenu-yWnqZqmz.js} +4 -4
- package/dist/{SettingMode-AD_S9ZkO.js → SettingMode-B8fgUhvi.js} +1 -1
- package/dist/{SettingNavSearch-oWIPjQFc.js → SettingNavSearch--yQEXqEL.js} +3 -3
- package/dist/{SettingOther-ZlPSoHz3.js → SettingOther-CSs1_D9L.js} +3 -3
- package/dist/{SettingPage-BnwAMror.js → SettingPage-Pm7KblGG.js} +2 -2
- package/dist/{SettingTabbar-Vvz-1zTa.js → SettingTabbar-DM5hdlQf.js} +6 -6
- package/dist/{SettingThemes-CLhV2OOt.js → SettingThemes-DqygGgDK.js} +5 -5
- package/dist/{SettingToolbar-nCkGwG2H.js → SettingToolbar-BP-yWiKo.js} +3 -3
- package/dist/{SettingTopbar-DMujCz4n.js → SettingTopbar-Dd_SXy2e.js} +4 -4
- package/dist/{SettingWidthMode-7qsluuMR.js → SettingWidthMode-DOtJg5uB.js} +2 -2
- package/dist/built-in/devtools/index.d.ts +13 -0
- package/dist/built-in/index.d.ts +1 -0
- package/dist/built-in/layout-component/Layout.vue.d.ts +7 -1
- package/dist/built-in/layout-component/components/Topbar/index.vue.d.ts +1 -1
- package/dist/built-in/layout-component/composables/useLayoutVisible.d.ts +8 -0
- package/dist/built-in/layout-component/interface.d.ts +22 -0
- package/dist/features/stores/modules/settings.d.ts +6 -6
- package/dist/features/stores/modules/user.d.ts +14 -2
- package/dist/{index-D210UZpV.js → index--xVOZLmn.js} +1 -1
- package/dist/{index-DSNuCtw6.js → index-BSTB6EhQ.js} +1 -1
- package/dist/{index-BN5BYOEh.js → index-C88VclMA.js} +15618 -15440
- package/dist/{index-2Zh2rSjN.js → index-CnbD4YWA.js} +3 -3
- package/dist/{index-BaRQkDKe.js → index-D8kKHmiD.js} +1 -1
- package/dist/index-GSKGoyv_.js +4 -0
- package/dist/{index-DQnnCCLU.js → index-igxVB1m3.js} +4 -5
- package/dist/{index-XjjX4TvH.js → index-npW0xuOi.js} +1 -1
- package/dist/index.js +1 -1
- package/dist/{pick-BZcCK3Xe.js → pick-l2RrF3SE.js} +1 -1
- package/dist/{question-line-CfkciTFq.js → question-line-DCMVyZ3e.js} +2 -2
- package/dist/{right-Bfe2p1o0.js → right-aIVrXLnr.js} +4 -4
- package/dist/style.css +1 -1
- package/package.json +8 -8
- package/src/built-in/devtools/index.ts +292 -0
- package/src/built-in/index.ts +1 -0
- package/src/built-in/layout-component/Layout.vue +93 -9
- package/src/built-in/layout-component/components/Header/HeaderFullMenu/index.vue +8 -4
- package/src/built-in/layout-component/components/Header/index.vue +4 -11
- package/src/built-in/layout-component/components/Sidebar/MainSidebar.vue +3 -1
- package/src/built-in/layout-component/components/Sidebar/SubSidebar.vue +4 -21
- package/src/built-in/layout-component/components/Topbar/index.vue +4 -105
- package/src/built-in/layout-component/composables/useLayoutVisible.ts +87 -0
- package/src/built-in/layout-component/interface.ts +25 -0
- package/src/core/create.ts +1 -3
- package/src/core/request.ts +0 -1
- package/src/features/assets/styles/globals.css +2 -1
- package/src/features/composables/log.ts +3 -5
- package/src/features/stores/modules/keepAlive.ts +10 -14
- package/src/features/stores/modules/menu.ts +20 -13
- package/src/features/stores/modules/route.ts +3 -3
- package/src/features/stores/modules/settings.ts +2 -7
- package/src/features/stores/modules/user.ts +57 -2
- package/src/index.ts +3 -0
- package/types/vue-router.d.ts +9 -2
- package/dist/HeaderThinMenu-B6cpu5jx.js +0 -4
- package/dist/index-iASxH_cj.js +0 -4
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
import { useContext } from '../../composables/useContext';
|
|
2
|
+
import { useLayoutVisible } from '../../composables/useLayoutVisible';
|
|
4
3
|
import Tabbar from './Tabbar/index.vue';
|
|
5
4
|
import Toolbar from './Toolbar/index.vue';
|
|
6
5
|
|
|
@@ -8,110 +7,10 @@ defineOptions({
|
|
|
8
7
|
name: 'Topbar',
|
|
9
8
|
});
|
|
10
9
|
|
|
11
|
-
const {
|
|
12
|
-
const route = useRoute();
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* 计算属性:是否开启工具栏
|
|
16
|
-
*
|
|
17
|
-
* @return {boolean}
|
|
18
|
-
*/
|
|
19
|
-
const enableToolbar = computed(() => {
|
|
20
|
-
return !(
|
|
21
|
-
(
|
|
22
|
-
settingsStore.settings.menu.menuMode === 'head'
|
|
23
|
-
&& !settingsStore.settings.menu.enableSubMenuCollapseButton
|
|
24
|
-
&& !settingsStore.settings.favorites.enable
|
|
25
|
-
&& !settingsStore.settings.breadcrumb.enable
|
|
26
|
-
) || (
|
|
27
|
-
settingsStore.settings.menu.menuMode === 'only-head'
|
|
28
|
-
&& !settingsStore.settings.favorites.enable
|
|
29
|
-
&& !settingsStore.settings.breadcrumb.enable
|
|
30
|
-
)
|
|
31
|
-
);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
// 统一在 Topbar 内控制是否渲染 Tabbar/Toolbar(结合全局设置与路由 meta)
|
|
35
|
-
const showTabbar = computed(() => {
|
|
36
|
-
// 路由可通过 meta.layout.tabs 显隐,默认显示
|
|
37
|
-
const routeAllow = (routeStore.getRemoteAppRouteById(route)?.meta as any)?.layout?.tabs ?? true;
|
|
38
|
-
return settingsStore.settings.tabbar.enable && routeAllow;
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
const showToolbar = computed(() => {
|
|
42
|
-
// 路由可通过 meta.layout.toolbar 显隐,默认显示
|
|
43
|
-
const routeAllow = (routeStore.getRemoteAppRouteById(route)?.meta as any)?.layout?.toolbar ?? true;
|
|
44
|
-
return enableToolbar.value && routeAllow;
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
const scrollTop = ref(0);
|
|
48
|
-
const scrollOnHide = ref(false);
|
|
49
|
-
const globalTabbarHeight = useCssVar('--g-tabbar-height', document.documentElement || document.body);
|
|
50
|
-
const globalToolBarHeight = useCssVar('--g-toolbar-height', document.documentElement || document.body);
|
|
51
|
-
|
|
52
|
-
const topbarHeight = computed(() => {
|
|
53
|
-
const tabbarHeight = showTabbar.value
|
|
54
|
-
? Number.parseInt(globalTabbarHeight.value!)
|
|
55
|
-
: 0;
|
|
56
|
-
const toolbarHeight = showToolbar.value
|
|
57
|
-
? Number.parseInt(globalToolBarHeight.value!)
|
|
58
|
-
: 0;
|
|
59
|
-
return tabbarHeight + toolbarHeight;
|
|
60
|
-
});
|
|
61
|
-
onMounted(() => {
|
|
62
|
-
window.addEventListener('scroll', onScroll);
|
|
63
|
-
});
|
|
64
|
-
onUnmounted(() => {
|
|
65
|
-
window.removeEventListener('scroll', onScroll);
|
|
66
|
-
});
|
|
67
|
-
function onScroll() {
|
|
68
|
-
scrollTop.value = (document.documentElement || document.body).scrollTop;
|
|
69
|
-
}
|
|
70
|
-
watch(scrollTop, (val, oldVal) => {
|
|
71
|
-
scrollOnHide.value = settingsStore.settings.topbar.mode === 'sticky' && val > oldVal && val > topbarHeight.value;
|
|
72
|
-
});
|
|
10
|
+
const { show } = useLayoutVisible();
|
|
73
11
|
</script>
|
|
74
12
|
|
|
75
13
|
<template>
|
|
76
|
-
<
|
|
77
|
-
|
|
78
|
-
:class="{
|
|
79
|
-
'has-tabbar': showTabbar,
|
|
80
|
-
'has-toolbar': showToolbar,
|
|
81
|
-
[`topbar-${settingsStore.settings.topbar.mode}`]: true,
|
|
82
|
-
'shadow': !settingsStore.settings.topbar.switchTabbarAndToolbar && scrollTop,
|
|
83
|
-
'hide': scrollOnHide,
|
|
84
|
-
'switch-tabbar-toolbar': settingsStore.settings.topbar.switchTabbarAndToolbar,
|
|
85
|
-
}"
|
|
86
|
-
data-fixed-calc-width
|
|
87
|
-
>
|
|
88
|
-
<Tabbar v-if="showTabbar" />
|
|
89
|
-
<Toolbar v-if="showToolbar" />
|
|
90
|
-
</div>
|
|
14
|
+
<Tabbar v-if="show.tabbar" />
|
|
15
|
+
<Toolbar v-if="show.toolbar" />
|
|
91
16
|
</template>
|
|
92
|
-
|
|
93
|
-
<style scoped>
|
|
94
|
-
.topbar-container {
|
|
95
|
-
--at-apply: absolute top-0 z-100 flex flex-col;
|
|
96
|
-
box-shadow: 0 1px 0 0 var(--g-border-color);
|
|
97
|
-
transition: width 0.3s, top 0.3s, transform 0.3s, box-shadow 0.3s;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
.topbar-container.topbar-fixed,
|
|
101
|
-
.topbar-container.topbar-sticky {
|
|
102
|
-
--at-apply: fixed;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
.topbar-container.topbar-fixed.shadow,
|
|
106
|
-
.topbar-container.topbar-sticky.shadow {
|
|
107
|
-
box-shadow: 0 10px 10px -10px var(--g-box-shadow-color);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
.topbar-container.topbar-sticky.hide {
|
|
111
|
-
top: calc((var(--g-tabbar-height) + var(--g-toolbar-height)) * -1) !important;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
.topbar-container.switch-tabbar-toolbar {
|
|
115
|
-
flex-direction: column-reverse;
|
|
116
|
-
}
|
|
117
|
-
</style>
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { RouterMetaRawBaseOptions } from '#/vue-router';
|
|
2
|
+
import type { RequiredDeep } from 'type-fest';
|
|
3
|
+
import type { LayoutProps } from '../interface';
|
|
4
|
+
import { useContext } from './useContext';
|
|
5
|
+
|
|
6
|
+
const visibleInjectionKey = Symbol.for('pubinfo.layout.visible') as InjectionKey<LayoutProps>;
|
|
7
|
+
|
|
8
|
+
export function createLayoutVisible(props: LayoutProps) {
|
|
9
|
+
provide(visibleInjectionKey, props);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 判断布局组件内各个部分的展示
|
|
14
|
+
*/
|
|
15
|
+
export function useLayoutVisible(_props?: LayoutProps) {
|
|
16
|
+
const { routeStore, settingsStore, menuStore } = useContext();
|
|
17
|
+
const props = inject(visibleInjectionKey, _props);
|
|
18
|
+
|
|
19
|
+
const route = useRoute();
|
|
20
|
+
|
|
21
|
+
const show = computed(() => {
|
|
22
|
+
// 应用级 meta.layout 配置
|
|
23
|
+
const appMetaData: RequiredDeep<RouterMetaRawBaseOptions['layout']> = {
|
|
24
|
+
header: true,
|
|
25
|
+
sidebar: true,
|
|
26
|
+
tabs: true,
|
|
27
|
+
toolbar: true,
|
|
28
|
+
...routeStore.getRemoteAppRouteById(route)?.meta?.layout,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// 侧边栏菜单的菜单数据
|
|
32
|
+
const sidebarMenus = menuStore.sidebarMenus;
|
|
33
|
+
|
|
34
|
+
// 菜单模式
|
|
35
|
+
const { menuMode, subMenuOnlyOneHide, enableSubMenuCollapseButton } = settingsStore.settings.menu;
|
|
36
|
+
|
|
37
|
+
const mode = settingsStore.mode;
|
|
38
|
+
const tabbarEnable = settingsStore.settings.tabbar.enable;
|
|
39
|
+
const favoritesEnable = settingsStore.settings.favorites.enable;
|
|
40
|
+
const breadcrumbEnable = settingsStore.settings.breadcrumb.enable;
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
/** 顶部栏 */
|
|
44
|
+
header: mode === 'pc' && ['head', 'only-head'].includes(menuMode) && appMetaData.header && props?.showHeader,
|
|
45
|
+
|
|
46
|
+
/** 主侧边栏 */
|
|
47
|
+
mainSidebar: ((mode === 'mobile' && menuMode !== 'single') || ['side', 'only-side'].includes(menuMode)) && props?.showSidebar,
|
|
48
|
+
|
|
49
|
+
/** 副侧边栏 */
|
|
50
|
+
subSidebar: (
|
|
51
|
+
mode === 'mobile' || (
|
|
52
|
+
['side', 'head', 'single'].includes(menuMode)
|
|
53
|
+
&& sidebarMenus.length > 0
|
|
54
|
+
&& !(
|
|
55
|
+
subMenuOnlyOneHide
|
|
56
|
+
&& sidebarMenus.length === 1
|
|
57
|
+
&& (
|
|
58
|
+
!sidebarMenus[0].children
|
|
59
|
+
|| sidebarMenus[0]?.children.every(item => item.meta?.sidebar === false)
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
)
|
|
63
|
+
) && appMetaData.sidebar && props?.showSidebar,
|
|
64
|
+
|
|
65
|
+
/** 标签栏 */
|
|
66
|
+
tabbar: tabbarEnable && appMetaData.tabs && props?.showTabbar,
|
|
67
|
+
|
|
68
|
+
/** 工具栏 */
|
|
69
|
+
toolbar: !(
|
|
70
|
+
(
|
|
71
|
+
menuMode === 'head'
|
|
72
|
+
&& !enableSubMenuCollapseButton
|
|
73
|
+
&& !favoritesEnable
|
|
74
|
+
&& !breadcrumbEnable
|
|
75
|
+
) || (
|
|
76
|
+
menuMode === 'only-head'
|
|
77
|
+
&& !favoritesEnable
|
|
78
|
+
&& !breadcrumbEnable
|
|
79
|
+
)
|
|
80
|
+
) && appMetaData.toolbar && props?.showToolbar,
|
|
81
|
+
};
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
show,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface LayoutProps {
|
|
2
|
+
/**
|
|
3
|
+
* 是否展示头部
|
|
4
|
+
* @default true
|
|
5
|
+
*/
|
|
6
|
+
showHeader?: boolean
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 是否展示侧边栏
|
|
10
|
+
* @default true
|
|
11
|
+
*/
|
|
12
|
+
showSidebar?: boolean
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 是否展示标签栏
|
|
16
|
+
* @default true
|
|
17
|
+
*/
|
|
18
|
+
showTabbar?: boolean
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 是否展示工具栏
|
|
22
|
+
* @default true
|
|
23
|
+
*/
|
|
24
|
+
showToolbar?: boolean
|
|
25
|
+
}
|
package/src/core/create.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Context, Options } from './interface';
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import { createPinia } from 'pinia';
|
|
4
4
|
import { createApp as createVueApp } from 'vue';
|
|
5
5
|
import { createRouter, createWebHashHistory } from 'vue-router';
|
|
@@ -25,8 +25,6 @@ export function createApp(options: Options) {
|
|
|
25
25
|
const store = createPinia();
|
|
26
26
|
app.use(store);
|
|
27
27
|
|
|
28
|
-
setupDevtoolsPanel();
|
|
29
|
-
|
|
30
28
|
const { base, ...restRouterOptions } = routerOptions;
|
|
31
29
|
const router = createRouter({
|
|
32
30
|
history: createWebHashHistory(base),
|
package/src/core/request.ts
CHANGED
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
|
|
34
34
|
/* 明暗模式 CSS 变量 */
|
|
35
35
|
:root {
|
|
36
|
-
color-scheme: light
|
|
36
|
+
color-scheme: light;
|
|
37
37
|
--g-box-shadow-color: rgba(0, 0, 0, 0.12);
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
:root.dark {
|
|
55
|
+
color-scheme: dark;
|
|
55
56
|
--g-box-shadow-color: rgba(0, 0, 0, 0.72);
|
|
56
57
|
}
|
|
57
58
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { logger } from '@pubinfo/shared';
|
|
2
2
|
|
|
3
3
|
enum LOG_TYPE {
|
|
4
4
|
ERROR = 'error',
|
|
@@ -17,8 +17,6 @@ enum EMOJI {
|
|
|
17
17
|
BOX = '🟧',
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
const createConsoleLog = consola.withTag('腾龙开发底座');
|
|
21
|
-
|
|
22
20
|
function createLog(type: LOG_TYPE, emoji: EMOJI) {
|
|
23
21
|
return (message: string | Error) => {
|
|
24
22
|
if (!import.meta.env.DEV) {
|
|
@@ -27,11 +25,11 @@ function createLog(type: LOG_TYPE, emoji: EMOJI) {
|
|
|
27
25
|
|
|
28
26
|
if (typeof message === 'string') {
|
|
29
27
|
const msg = message.length > 0 ? `${emoji} ${message}` : '';
|
|
30
|
-
|
|
28
|
+
logger[type](msg);
|
|
31
29
|
}
|
|
32
30
|
else {
|
|
33
31
|
const msg = message instanceof Error ? message : new Error(message);
|
|
34
|
-
|
|
32
|
+
logger[type](msg);
|
|
35
33
|
}
|
|
36
34
|
};
|
|
37
35
|
}
|
|
@@ -22,14 +22,13 @@ const useKeepAliveStore = defineStore(
|
|
|
22
22
|
if (isString(name)) {
|
|
23
23
|
return !list.value.includes(name) && list.value.push(name);
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
useWarn(`KeepAlive 需要接受一个字符串或者字符串数组作为参数, 但是接受到了 ${typeof name} 类型`);
|
|
25
|
+
|
|
26
|
+
if (isArray(name)) {
|
|
27
|
+
name.forEach(_name => add(_name));
|
|
28
|
+
return;
|
|
32
29
|
}
|
|
30
|
+
|
|
31
|
+
useWarn(`KeepAlive 需要接受一个字符串或者字符串数组作为参数, 但是接受到了 ${typeof name} 类型`);
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
/**
|
|
@@ -39,14 +38,11 @@ const useKeepAliveStore = defineStore(
|
|
|
39
38
|
*/
|
|
40
39
|
function remove(name: string | string[]) {
|
|
41
40
|
if (isString(name)) {
|
|
42
|
-
list.value = list.value.filter(
|
|
43
|
-
return v !== name;
|
|
44
|
-
});
|
|
41
|
+
list.value = list.value.filter(v => v !== name);
|
|
45
42
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
});
|
|
43
|
+
|
|
44
|
+
if (isArray(name)) {
|
|
45
|
+
list.value = list.value.filter(v => !name.includes(v));
|
|
50
46
|
}
|
|
51
47
|
}
|
|
52
48
|
|
|
@@ -97,25 +97,32 @@ const useMenuStore = defineStore(
|
|
|
97
97
|
* @returns {MenuData['children']} 当前活动菜单的子菜单,如果没有菜单则返回空数组。
|
|
98
98
|
*/
|
|
99
99
|
const sidebarMenus = computed<MenuData['children']>(() => {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
100
|
+
// 过滤 meta.isDev 为 true 的应用
|
|
101
|
+
const filteredAllMenus = allMenus.value.filter(item => !get(item, 'meta.isDev', false));
|
|
102
|
+
|
|
103
|
+
if (filteredAllMenus.length === 0) {
|
|
104
|
+
return [];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
while (true) {
|
|
108
|
+
const menu = allMenus.value[actived.value];
|
|
109
|
+
|
|
110
|
+
if (actived.value >= allMenus.value.length - 1) {
|
|
111
|
+
break;
|
|
107
112
|
}
|
|
108
|
-
|
|
109
|
-
|
|
113
|
+
|
|
114
|
+
// 有子菜单且不为开发中的应用
|
|
115
|
+
if (menu.children.length > 0 && !get(menu, 'meta.isDev', false)) {
|
|
116
|
+
break;
|
|
110
117
|
}
|
|
118
|
+
|
|
119
|
+
actived.value++;
|
|
111
120
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
121
|
+
|
|
122
|
+
return allMenus.value[actived.value].children ?? [];
|
|
115
123
|
});
|
|
116
124
|
|
|
117
125
|
/**
|
|
118
|
-
* TODO V1: 如果第一个菜单是一个isDev为true的菜单,那么这个计算属性可能会出现问题
|
|
119
126
|
* 返回第一个侧边栏菜单的最深路径的计算属性。
|
|
120
127
|
*
|
|
121
128
|
* @returns {string} 第一个侧边栏菜单的最深路径,如果没有侧边栏菜单则返回'/'。
|
|
@@ -283,15 +283,15 @@ const useRouteStore = defineStore(
|
|
|
283
283
|
*/
|
|
284
284
|
const routes = computed<RouteData[]>(() => {
|
|
285
285
|
return needFilterRoutes.value
|
|
286
|
-
? filterAsyncRoutes(routesRaw.value, userStore
|
|
286
|
+
? filterAsyncRoutes(routesRaw.value, userStore?.user?.permissions ?? [])
|
|
287
287
|
: cloneDeep(routesRaw.value);
|
|
288
288
|
});
|
|
289
289
|
|
|
290
290
|
// 将设置 meta.singleMenu 的一级路由转换成二级路由
|
|
291
291
|
function convertSingleRoutes<T extends RouteData[]>(routes: T) {
|
|
292
292
|
routes.map((route) => {
|
|
293
|
-
// 在应用级配置 meta.
|
|
294
|
-
const Layout = setupDefaultLayout(route?.meta?.
|
|
293
|
+
// 在应用级配置 meta.layoutComponent
|
|
294
|
+
const Layout = setupDefaultLayout(route?.meta?.layoutComponent);
|
|
295
295
|
|
|
296
296
|
if (route.children && route.children.length > 0) {
|
|
297
297
|
route.children.forEach((item, index, arr) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { RouteLocationNormalized, RouteMeta } from 'vue-router';
|
|
2
2
|
import { FrownOutlined } from '@ant-design/icons-vue';
|
|
3
|
-
import { usePreferredDark } from '@vueuse/core';
|
|
3
|
+
import { usePreferredDark, useToggle } from '@vueuse/core';
|
|
4
4
|
import { Modal } from 'ant-design-vue';
|
|
5
5
|
import { cloneDeep, defaultsDeep, get, isArray, isEmpty, isObject, reduce, set } from 'lodash-es';
|
|
6
6
|
import { defineStore } from 'pinia';
|
|
@@ -243,13 +243,8 @@ const useSettingsStore = defineStore(
|
|
|
243
243
|
settings.value.app.colorScheme = color;
|
|
244
244
|
}
|
|
245
245
|
|
|
246
|
-
// 主页面是否最大化
|
|
247
|
-
const mainPageMaximizeStatus = ref(false);
|
|
248
|
-
|
|
249
246
|
// 切换当前主页面最大化
|
|
250
|
-
|
|
251
|
-
mainPageMaximizeStatus.value = value ?? !mainPageMaximizeStatus.value;
|
|
252
|
-
}
|
|
247
|
+
const [mainPageMaximizeStatus, setMainPageMaximize] = useToggle(false);
|
|
253
248
|
|
|
254
249
|
/**
|
|
255
250
|
* 更新配置
|
|
@@ -2,7 +2,7 @@ import type { AxiosRequestHeaders } from 'axios';
|
|
|
2
2
|
import type { ComputedRef } from 'vue';
|
|
3
3
|
import { find } from 'lodash-es';
|
|
4
4
|
import { defineStore } from 'pinia';
|
|
5
|
-
import { postAuthChangeLoginOrg, postAuthLogin } from '@/features/api/modules/auth';
|
|
5
|
+
import { postAuthChangeLoginOrg, postAuthLogin, postAuthLoginNew } from '@/features/api/modules/auth';
|
|
6
6
|
import { getRbacResourceGrantedResources, getRbacUserUserEntireInfo, putRbacUserChangePassword } from '@/features/api/modules/rbac';
|
|
7
7
|
import { usePubinfoContext } from '@/features/context';
|
|
8
8
|
import { publicKeyEncryption } from '@/utils';
|
|
@@ -24,7 +24,10 @@ export interface UserStore {
|
|
|
24
24
|
/** 获取用户权限码 */
|
|
25
25
|
getPermissions: () => Promise<string[]>
|
|
26
26
|
|
|
27
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* 登录
|
|
29
|
+
* @deprecated 请使用 `signIn` 方法替代
|
|
30
|
+
*/
|
|
28
31
|
login: (data: {
|
|
29
32
|
account: string
|
|
30
33
|
password: string
|
|
@@ -33,6 +36,16 @@ export interface UserStore {
|
|
|
33
36
|
loginType?: 'password' | string
|
|
34
37
|
}) => Promise<API.ResponseDataLoginTokenVo>
|
|
35
38
|
|
|
39
|
+
/** 登录 */
|
|
40
|
+
signIn: (data: {
|
|
41
|
+
account: string
|
|
42
|
+
password: string
|
|
43
|
+
captchas: string
|
|
44
|
+
captchaHash: string
|
|
45
|
+
loginType?: 'password' | string
|
|
46
|
+
captchaType?: string
|
|
47
|
+
}) => Promise<API.ResponseDataLoginTokenVo>
|
|
48
|
+
|
|
36
49
|
/** 登出 */
|
|
37
50
|
logout: () => void
|
|
38
51
|
|
|
@@ -96,6 +109,7 @@ const useUserStore = defineStore<STORE_NAME.USER, UserStore>(
|
|
|
96
109
|
|
|
97
110
|
/**
|
|
98
111
|
* 用户登录函数
|
|
112
|
+
* @deprecated 请使用 `signIn` 方法替代
|
|
99
113
|
* @param data 登录所需的数据
|
|
100
114
|
* @param data.account 账号
|
|
101
115
|
* @param data.password 密码
|
|
@@ -130,6 +144,46 @@ const useUserStore = defineStore<STORE_NAME.USER, UserStore>(
|
|
|
130
144
|
return result;
|
|
131
145
|
}
|
|
132
146
|
|
|
147
|
+
/**
|
|
148
|
+
* 用户登录函数
|
|
149
|
+
* @param data 登录所需的数据
|
|
150
|
+
* @param data.account 账号
|
|
151
|
+
* @param data.password 密码
|
|
152
|
+
* @param data.captchas 验证码
|
|
153
|
+
* @param data.captchaHash 验证码哈希值
|
|
154
|
+
* @param data.loginType 登录类型,默认为 'password'
|
|
155
|
+
* @param data.captchaType 验证类型
|
|
156
|
+
*/
|
|
157
|
+
async function signIn(data: {
|
|
158
|
+
account: string
|
|
159
|
+
password: string
|
|
160
|
+
captchas: string
|
|
161
|
+
captchaHash: string
|
|
162
|
+
loginType?: 'password' | string
|
|
163
|
+
captchaType?: string
|
|
164
|
+
}) {
|
|
165
|
+
const {
|
|
166
|
+
account: loginName,
|
|
167
|
+
password,
|
|
168
|
+
captchaHash: codeHash,
|
|
169
|
+
captchas: code,
|
|
170
|
+
loginType = 'password',
|
|
171
|
+
captchaType,
|
|
172
|
+
} = data;
|
|
173
|
+
const loginPwd = await publicKeyEncryption(password);
|
|
174
|
+
const result = await postAuthLoginNew({
|
|
175
|
+
loginType,
|
|
176
|
+
loginName,
|
|
177
|
+
loginPwd,
|
|
178
|
+
codeHash,
|
|
179
|
+
code,
|
|
180
|
+
captchaType,
|
|
181
|
+
});
|
|
182
|
+
const { accessToken, refreshToken } = result.data as Required<API.LoginTokenVo>;
|
|
183
|
+
setToken(accessToken, refreshToken);
|
|
184
|
+
return result;
|
|
185
|
+
}
|
|
186
|
+
|
|
133
187
|
/**
|
|
134
188
|
* 执行用户注销操作,并跳转到登录页面。
|
|
135
189
|
*/
|
|
@@ -231,6 +285,7 @@ const useUserStore = defineStore<STORE_NAME.USER, UserStore>(
|
|
|
231
285
|
getUserInfo,
|
|
232
286
|
getPermissions,
|
|
233
287
|
login,
|
|
288
|
+
signIn,
|
|
234
289
|
logout,
|
|
235
290
|
changePassword,
|
|
236
291
|
changeOrg,
|
package/src/index.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { Options, RequestInstance } from './core';
|
|
|
2
2
|
import {
|
|
3
3
|
Authentication,
|
|
4
4
|
Authorization,
|
|
5
|
+
Devtools,
|
|
5
6
|
LayoutComponent,
|
|
6
7
|
NProgress,
|
|
7
8
|
PiniaPlugin,
|
|
@@ -57,6 +58,7 @@ export function createPubinfo(options: PubinfoOptions) {
|
|
|
57
58
|
modules: [
|
|
58
59
|
{
|
|
59
60
|
name: 'built-in:context',
|
|
61
|
+
enforce: 'pre',
|
|
60
62
|
setup(ctx) {
|
|
61
63
|
createPubinfoContext({
|
|
62
64
|
router: ctx.router,
|
|
@@ -74,6 +76,7 @@ export function createPubinfo(options: PubinfoOptions) {
|
|
|
74
76
|
NProgress(),
|
|
75
77
|
SystemInfo(),
|
|
76
78
|
...(options.modules ?? []),
|
|
79
|
+
Devtools(),
|
|
77
80
|
],
|
|
78
81
|
});
|
|
79
82
|
}
|
package/types/vue-router.d.ts
CHANGED
|
@@ -29,7 +29,14 @@ export interface RouterMetaRawBaseOptions {
|
|
|
29
29
|
pin?: boolean
|
|
30
30
|
routeName?: string
|
|
31
31
|
id?: string | number
|
|
32
|
+
layout?: {
|
|
33
|
+
header?: boolean
|
|
34
|
+
sidebar?: boolean
|
|
35
|
+
tabs?: boolean
|
|
36
|
+
toolbar?: boolean
|
|
37
|
+
}
|
|
32
38
|
partyLogin?: PartyLoginStepConfig[]
|
|
39
|
+
custom?: any
|
|
33
40
|
}
|
|
34
41
|
|
|
35
42
|
type RouterMetaRaw = RequireExactlyOne<Partial<RouterMetaRawBaseOptions>, 'title'>;
|
|
@@ -48,12 +55,12 @@ export declare namespace Route {
|
|
|
48
55
|
type recordMainRawBasicMeta = Partial<Pick<RouterMetaRawBaseOptions, mainMeta>>;
|
|
49
56
|
|
|
50
57
|
interface recordMainRawNotDev {
|
|
51
|
-
meta: Merge<recordMainRawBasicMeta, { isDev?: false,
|
|
58
|
+
meta: Merge<recordMainRawBasicMeta, { isDev?: false, layoutComponent?: string }>
|
|
52
59
|
children: RouteRecordRaw[]
|
|
53
60
|
}
|
|
54
61
|
|
|
55
62
|
interface recordMainRawDev {
|
|
56
|
-
meta: Merge<recordMainRawBasicMeta, { isDev: true,
|
|
63
|
+
meta: Merge<recordMainRawBasicMeta, { isDev: true, layoutComponent?: string }>
|
|
57
64
|
children?: RouteRecordRaw[]
|
|
58
65
|
}
|
|
59
66
|
|
package/dist/index-iASxH_cj.js
DELETED