@peng_kai/kit 0.1.16 → 0.2.0-beta.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/admin/adminPlugin.ts +47 -0
- package/admin/components/filter/src/FilterParam.vue +76 -78
- package/admin/components/filter/src/FilterReset.vue +2 -2
- package/admin/components/filter/src/useFilterParams.ts +75 -25
- package/admin/components/filter/src/useFilterQuery.ts +32 -16
- package/admin/components/rich-text/index.ts +2 -0
- package/admin/components/rich-text/src/RichText.vue +342 -0
- package/admin/components/rich-text/src/imageUploader.ts +34 -0
- package/admin/components/rich-text/src/type.d.ts +7 -0
- package/admin/components/text/src/Datetime.vue +47 -48
- package/admin/components/upload/index.ts +2 -0
- package/admin/components/upload/src/PictureCardUpload.vue +143 -0
- package/admin/components/upload/src/customRequests.ts +31 -0
- package/admin/defines/index.ts +1 -1
- package/admin/defines/route/helpers.ts +0 -1
- package/admin/defines/startup/defineStartup.ts +8 -1
- package/admin/defines/startup/index.ts +1 -1
- package/admin/defines/startup/{getStartups.ts → runStartup.ts} +16 -7
- package/admin/layout/large/Breadcrumb.vue +68 -69
- package/admin/layout/large/Content.vue +23 -24
- package/admin/layout/large/Menu.vue +68 -69
- package/admin/layout/large/PageTab.vue +70 -71
- package/admin/permission/index.ts +2 -4
- package/admin/permission/routerGuard.ts +41 -43
- package/admin/permission/vuePlugin.ts +46 -30
- package/admin/route-guards/collapseMenu.ts +3 -3
- package/admin/route-guards/pageTitle.ts +18 -19
- package/admin/scripts/deploy.ts +67 -0
- package/admin/{hooks/useMenu.ts → stores/createUseMenuStore.ts} +133 -128
- package/admin/{hooks/usePage.ts → stores/createUsePageStore.ts} +145 -141
- package/admin/stores/createUsePageTabStore.ts +43 -0
- package/admin/{permission/usePermission.ts → stores/createUsePermissionStore.ts} +57 -52
- package/admin/stores/index.ts +8 -0
- package/admin/styles/classCover.scss +8 -0
- package/antd/hooks/useAntdForm.helpers.ts +92 -8
- package/antd/hooks/useAntdForm.ts +55 -63
- package/antd/hooks/useAntdTable.ts +12 -0
- package/antd/index.ts +1 -1
- package/libs/a-calc.ts +1 -0
- package/libs/axios.ts +2 -0
- package/libs/bignumber.ts +2 -0
- package/libs/dayjs.ts +5 -0
- package/libs/echarts.ts +5 -0
- package/libs/localstorage-slim.ts +2 -0
- package/libs/lodash-es.ts +1 -0
- package/libs/pinia.ts +1 -0
- package/libs/vue-query.ts +1 -0
- package/libs/vueuse.ts +3 -0
- package/package.json +97 -53
- package/request/helpers.ts +20 -1
- package/request/interceptors/checkCode.ts +3 -3
- package/request/interceptors/returnResultType.ts +2 -2
- package/request/queryClient.ts +34 -21
- package/utils/upload/AwsS3.ts +76 -0
- package/utils/upload/fileHandlers.ts +27 -0
- package/utils/upload/index.ts +2 -0
- package/vite/index.d.ts +1 -0
- package/vite/index.mjs +27 -0
- package/vue/components/echarts/index.ts +1 -0
- package/vue/components/echarts/src/ECharts.vue +48 -0
- package/vue/components/index.ts +1 -0
- package/vue/components/infinite-query/src/InfiniteQuery.vue +2 -8
- package/vue/components/test/KitTest.vue +9 -0
- package/vue/components/test/testStore.ts +11 -0
- package/admin/hooks/index.ts +0 -5
- package/admin/hooks/usePageTab.ts +0 -35
- package/kitDependencies.ts +0 -43
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { defineStartup } from './defineStartup';
|
|
2
|
-
export {
|
|
2
|
+
export { runStartup } from './runStartup';
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
import type { App } from 'vue';
|
|
1
2
|
import { ENV } from '../../../utils';
|
|
2
3
|
import { StartupSymbol } from './defineStartup';
|
|
3
4
|
import type { StartupFn } from './defineStartup';
|
|
4
5
|
|
|
5
|
-
export async function
|
|
6
|
-
const moduleLoaders =
|
|
6
|
+
export async function runStartup(app: App) {
|
|
7
|
+
const moduleLoaders = runStartup.modules as Record<string, Function>;
|
|
7
8
|
const startupPaths: string[] = [];
|
|
8
|
-
const
|
|
9
|
+
const onMountCallbacks: Function[] = [];
|
|
10
|
+
(app as any).deps = {};
|
|
9
11
|
|
|
10
12
|
for (const [path, moduleLoader] of Object.entries(moduleLoaders)) {
|
|
11
13
|
const module: any = await moduleLoader();
|
|
@@ -15,16 +17,23 @@ export async function getStartups() {
|
|
|
15
17
|
continue;
|
|
16
18
|
|
|
17
19
|
startupPaths.push(path);
|
|
18
|
-
|
|
20
|
+
|
|
21
|
+
/* create 钩子 */
|
|
22
|
+
await plugin(app, {
|
|
23
|
+
onMount(cb) {
|
|
24
|
+
cb && onMountCallbacks.push(cb);
|
|
25
|
+
},
|
|
26
|
+
});
|
|
19
27
|
}
|
|
20
28
|
|
|
29
|
+
/* mount 钩子 */
|
|
30
|
+
onMountCallbacks.forEach(cb => cb());
|
|
31
|
+
|
|
21
32
|
// 输出 App 插件
|
|
22
33
|
if (!ENV.isProd) {
|
|
23
34
|
console.groupCollapsed('启动时');
|
|
24
35
|
console.table(startupPaths.map(path => ({ path })), ['path']);
|
|
25
36
|
console.groupEnd();
|
|
26
37
|
}
|
|
27
|
-
|
|
28
|
-
return startups;
|
|
29
38
|
}
|
|
30
|
-
|
|
39
|
+
runStartup.modules = {} as any;
|
|
@@ -1,69 +1,68 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { computed } from 'vue';
|
|
3
|
-
import type { VNode } from 'vue';
|
|
4
|
-
import { Breadcrumb as ABreadcrumb } from 'ant-design-vue';
|
|
5
|
-
import type { Route as AntdBreadcrumbRoute } from 'ant-design-vue/es/breadcrumb/Breadcrumb';
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
interface IBreadcrumbRoute extends AntdBreadcrumbRoute {
|
|
10
|
-
icon?: VNode | null
|
|
11
|
-
trigger?: () => void
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function _buildRoute(breadcrumb: IBreadcrumb): IBreadcrumbRoute {
|
|
15
|
-
return {
|
|
16
|
-
breadcrumbName: breadcrumb.title,
|
|
17
|
-
path: breadcrumb.title,
|
|
18
|
-
icon: breadcrumb.icon,
|
|
19
|
-
children: breadcrumb.children?.map(child => _buildRoute(child)),
|
|
20
|
-
trigger: breadcrumb.trigger,
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
</script>
|
|
24
|
-
|
|
25
|
-
<script setup lang="ts">
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
</style>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { computed } from 'vue';
|
|
3
|
+
import type { VNode } from 'vue';
|
|
4
|
+
import { Breadcrumb as ABreadcrumb } from 'ant-design-vue';
|
|
5
|
+
import type { Route as AntdBreadcrumbRoute } from 'ant-design-vue/es/breadcrumb/Breadcrumb';
|
|
6
|
+
import { adminPlugin } from '../../adminPlugin';
|
|
7
|
+
import type { IBreadcrumb } from '../../stores/createUsePageStore';
|
|
8
|
+
|
|
9
|
+
interface IBreadcrumbRoute extends AntdBreadcrumbRoute {
|
|
10
|
+
icon?: VNode | null
|
|
11
|
+
trigger?: () => void
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function _buildRoute(breadcrumb: IBreadcrumb): IBreadcrumbRoute {
|
|
15
|
+
return {
|
|
16
|
+
breadcrumbName: breadcrumb.title,
|
|
17
|
+
path: breadcrumb.title,
|
|
18
|
+
icon: breadcrumb.icon,
|
|
19
|
+
children: breadcrumb.children?.map(child => _buildRoute(child)),
|
|
20
|
+
trigger: breadcrumb.trigger,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<script setup lang="ts">
|
|
26
|
+
const pageStore = adminPlugin.deps.usePageStore();
|
|
27
|
+
const routes = computed(() => {
|
|
28
|
+
let breadcrumbs: IBreadcrumbRoute[] = [];
|
|
29
|
+
|
|
30
|
+
if (!pageStore.currentPageState)
|
|
31
|
+
return breadcrumbs;
|
|
32
|
+
|
|
33
|
+
breadcrumbs = pageStore.currentPageState.breadcrumbs.map(breadcrumb => _buildRoute(breadcrumb));
|
|
34
|
+
|
|
35
|
+
breadcrumbs.push({
|
|
36
|
+
path: pageStore.currentPageState.title,
|
|
37
|
+
breadcrumbName: pageStore.currentPageState.title,
|
|
38
|
+
icon: pageStore.currentPageState.icon,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
return breadcrumbs;
|
|
42
|
+
});
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<template>
|
|
46
|
+
<ABreadcrumb class="breadcrumb" :routes="routes">
|
|
47
|
+
<template #itemRender="{ route }: {route: IBreadcrumbRoute}">
|
|
48
|
+
<div @click="route.trigger?.()">
|
|
49
|
+
<component :is="route.icon" v-if="route.icon" class="mb-0.2em mr-0.2em" />
|
|
50
|
+
<span>{{ route.breadcrumbName }}</span>
|
|
51
|
+
</div>
|
|
52
|
+
</template>
|
|
53
|
+
</ABreadcrumb>
|
|
54
|
+
</template>
|
|
55
|
+
|
|
56
|
+
<style lang="scss" scoped>
|
|
57
|
+
.breadcrumb {
|
|
58
|
+
font-size: 1rem;
|
|
59
|
+
|
|
60
|
+
:deep(.ant-dropdown-trigger) {
|
|
61
|
+
height: 1.6em;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
:deep(.anticon-down) {
|
|
65
|
+
display: none;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
</style>
|
|
@@ -1,24 +1,23 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
<
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
</template>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { adminPlugin } from '../../adminPlugin';
|
|
3
|
+
|
|
4
|
+
const pageStore = adminPlugin.deps.usePageStore();
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<template>
|
|
8
|
+
<RouterView #default="{ Component, route }">
|
|
9
|
+
<KeepAlive :include="pageStore.pageCacheList">
|
|
10
|
+
<Suspense>
|
|
11
|
+
<component :is="pageStore.setPage(Component, route)" :key="(Component.type as any).name" />
|
|
12
|
+
<template #fallback>
|
|
13
|
+
<div class="flex justify-center items-center h-70">
|
|
14
|
+
<div class="flex items-center">
|
|
15
|
+
<i class="i-svg-spinners:180-ring-with-bg block color-primary scale-125 mr-2" />
|
|
16
|
+
<span class="text-gray">正在加载...</span>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
</template>
|
|
20
|
+
</Suspense>
|
|
21
|
+
</KeepAlive>
|
|
22
|
+
</RouterView>
|
|
23
|
+
</template>
|
|
@@ -1,69 +1,68 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { computed, ref, watch } from 'vue';
|
|
3
|
-
import { Menu as AMenu } from 'ant-design-vue';
|
|
4
|
-
import type { ItemType } from 'ant-design-vue';
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
function formatMenu(menu: TMenu): ItemType {
|
|
9
|
-
return {
|
|
10
|
-
key: menu.key,
|
|
11
|
-
title: menu.label,
|
|
12
|
-
label: menu.label,
|
|
13
|
-
icon: menu.icon ?? undefined,
|
|
14
|
-
onClick: (e) => {
|
|
15
|
-
(e as any).stopPropagation();
|
|
16
|
-
menu.trigger();
|
|
17
|
-
},
|
|
18
|
-
children: menu.children?.map(formatMenu),
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
</script>
|
|
22
|
-
|
|
23
|
-
<script setup lang="ts">
|
|
24
|
-
const {
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
() =>
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
},
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
:
|
|
49
|
-
:
|
|
50
|
-
:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
</style>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { computed, ref, watch } from 'vue';
|
|
3
|
+
import { Menu as AMenu } from 'ant-design-vue';
|
|
4
|
+
import type { ItemType } from 'ant-design-vue';
|
|
5
|
+
import { adminPlugin } from '../../adminPlugin';
|
|
6
|
+
import type { TMenu } from '../../stores/createUseMenuStore';
|
|
7
|
+
|
|
8
|
+
function formatMenu(menu: TMenu): ItemType {
|
|
9
|
+
return {
|
|
10
|
+
key: menu.key,
|
|
11
|
+
title: menu.label,
|
|
12
|
+
label: menu.label,
|
|
13
|
+
icon: menu.icon ?? undefined,
|
|
14
|
+
onClick: (e) => {
|
|
15
|
+
(e as any).stopPropagation();
|
|
16
|
+
menu.trigger();
|
|
17
|
+
},
|
|
18
|
+
children: menu.children?.map(formatMenu),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<script setup lang="ts">
|
|
24
|
+
const { router, useMenuStore } = adminPlugin.deps;
|
|
25
|
+
const menuStore = useMenuStore();
|
|
26
|
+
const items = computed(() => menuStore.menus.map(formatMenu));
|
|
27
|
+
const openKeys = ref<string[]>([]);
|
|
28
|
+
const selectedKeys = ref<string[]>([]);
|
|
29
|
+
|
|
30
|
+
watch(
|
|
31
|
+
() => router?.currentRoute.value,
|
|
32
|
+
(route) => {
|
|
33
|
+
if (!route)
|
|
34
|
+
return;
|
|
35
|
+
|
|
36
|
+
const menuPath = menuStore.getMenuPath(route.name as string);
|
|
37
|
+
openKeys.value = menuPath.map(menu => menu.key);
|
|
38
|
+
selectedKeys.value = [openKeys.value.pop()!];
|
|
39
|
+
},
|
|
40
|
+
{ immediate: true },
|
|
41
|
+
);
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<template>
|
|
45
|
+
<AMenu
|
|
46
|
+
class="menu"
|
|
47
|
+
:items="items"
|
|
48
|
+
:openKeys="openKeys"
|
|
49
|
+
:selectedKeys="selectedKeys"
|
|
50
|
+
:inlineIndent="16"
|
|
51
|
+
mode="inline"
|
|
52
|
+
/>
|
|
53
|
+
</template>
|
|
54
|
+
|
|
55
|
+
<style lang="scss" scoped>
|
|
56
|
+
.menu {
|
|
57
|
+
border-inline-end: none !important;
|
|
58
|
+
|
|
59
|
+
&.ant-menu-inline-collapsed {
|
|
60
|
+
width: var(--app-siderbar-width);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
&,
|
|
64
|
+
.ant-menu {
|
|
65
|
+
background-color: transparent;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
</style>
|
|
@@ -1,71 +1,70 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { TabPane as ATabPane, Tabs as ATabs } from 'ant-design-vue';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
<
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
:
|
|
16
|
-
:
|
|
17
|
-
|
|
18
|
-
@
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
:deep(.ant-tabs-tab
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
:deep(.ant-tabs-tab
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
</style>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { TabPane as ATabPane, Tabs as ATabs } from 'ant-design-vue';
|
|
3
|
+
import { adminPlugin } from '../../adminPlugin';
|
|
4
|
+
|
|
5
|
+
const pageTabStore = adminPlugin.deps.usePageTabStore();
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<template>
|
|
9
|
+
<ATabs
|
|
10
|
+
class="app-page-tabs"
|
|
11
|
+
:activeKey="pageTabStore.activeTab"
|
|
12
|
+
type="editable-card"
|
|
13
|
+
size="small"
|
|
14
|
+
:animated="false"
|
|
15
|
+
:hideAdd="true"
|
|
16
|
+
:tabBarGutter="4"
|
|
17
|
+
@tabClick="(pageTabStore.openTab as any)"
|
|
18
|
+
@edit="(pageTabStore.closeTab as any)"
|
|
19
|
+
>
|
|
20
|
+
<ATabPane v-for="tab of pageTabStore.tabList" :key="tab.key" :tab="tab.title">
|
|
21
|
+
<template #closeIcon>
|
|
22
|
+
<i class="i-icon-park-outline:close" />
|
|
23
|
+
</template>
|
|
24
|
+
</ATabPane>
|
|
25
|
+
</ATabs>
|
|
26
|
+
</template>
|
|
27
|
+
|
|
28
|
+
<style scoped lang="scss">
|
|
29
|
+
.app-page-tabs {
|
|
30
|
+
:deep(.ant-tabs-nav) {
|
|
31
|
+
margin: 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
:deep(.ant-tabs-nav::before) {
|
|
35
|
+
display: none;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
:deep(.ant-tabs-tab) {
|
|
39
|
+
--uno: 'border-rd-3px! text-14px p-[3px_1px_3px_8px]! select-none';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
:deep(.ant-tabs-tab .ant-tabs-tab-btn) {
|
|
43
|
+
transform: translateX(8px);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
:deep(.ant-tabs-tab-active) {
|
|
47
|
+
--uno: 'border-[currentColor]!';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
:deep(.ant-tabs-tab-remove) {
|
|
51
|
+
display: flex;
|
|
52
|
+
height: 100%;
|
|
53
|
+
align-items: center;
|
|
54
|
+
margin: 0;
|
|
55
|
+
opacity: 0;
|
|
56
|
+
transition: all 150ms;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
:deep(.ant-tabs-tab:hover .ant-tabs-tab-btn),
|
|
60
|
+
:deep(.ant-tabs-tab-active .ant-tabs-tab-btn) {
|
|
61
|
+
transform: translateX(0);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
:deep(.ant-tabs-tab:hover .ant-tabs-tab-remove),
|
|
65
|
+
:deep(.ant-tabs-tab-active .ant-tabs-tab-remove) {
|
|
66
|
+
margin-left: 0;
|
|
67
|
+
opacity: 1;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
</style>
|
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
export { setupPermissionRouterGuard } from './routerGuard';
|
|
2
|
-
export { setupPermissionPlugin } from './vuePlugin';
|
|
3
|
-
export { usePermission } from './usePermission';
|
|
4
|
-
export type { THasPermissionsFn } from './vuePlugin';
|
|
1
|
+
export { setupPermissionRouterGuard } from './routerGuard';
|
|
2
|
+
export { setupPermissionPlugin } from './vuePlugin';
|
|
@@ -1,43 +1,41 @@
|
|
|
1
|
-
import type { Router } from 'vue-router';
|
|
2
|
-
import {
|
|
3
|
-
import { hasToken } from '../../utils';
|
|
4
|
-
|
|
5
|
-
export function setupPermissionRouterGuard(router: Router, rouneNames: { index: string, login: string, 403: string }) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
});
|
|
43
|
-
}
|
|
1
|
+
import type { Router } from 'vue-router';
|
|
2
|
+
import { adminPlugin } from '../adminPlugin';
|
|
3
|
+
import { hasToken } from '../../utils';
|
|
4
|
+
|
|
5
|
+
export function setupPermissionRouterGuard(router: Router, rouneNames: { index: string, login: string, 403: string }) {
|
|
6
|
+
router.beforeEach(async (to, _, next) => {
|
|
7
|
+
const permissionStore = adminPlugin.deps.usePermissionStore();
|
|
8
|
+
const isLogin = hasToken();
|
|
9
|
+
const needLogin = Boolean(to.meta?.requireAuth);
|
|
10
|
+
let hasPermission = false;
|
|
11
|
+
|
|
12
|
+
if (isLogin) {
|
|
13
|
+
await permissionStore.refreshPermission();
|
|
14
|
+
|
|
15
|
+
const permissionCode = to.meta?.permissionCode;
|
|
16
|
+
hasPermission = permissionCode ? permissionStore.hasPermission(permissionCode) : true;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// 已登录状态跳转登录页,跳转至首页
|
|
20
|
+
if (isLogin && to.name === rouneNames.login)
|
|
21
|
+
return next({ name: rouneNames.index, replace: true });
|
|
22
|
+
|
|
23
|
+
// 不需要登录权限的页面直接通行
|
|
24
|
+
else if (!needLogin)
|
|
25
|
+
return next(true);
|
|
26
|
+
|
|
27
|
+
// 未登录状态进入需要登录权限的页面
|
|
28
|
+
else if (!isLogin && needLogin)
|
|
29
|
+
return next({ name: rouneNames.login, replace: true });
|
|
30
|
+
|
|
31
|
+
// 登录状态进入需要登录权限的页面,有权限直接通行
|
|
32
|
+
else if (isLogin && needLogin && hasPermission)
|
|
33
|
+
return next(true);
|
|
34
|
+
|
|
35
|
+
// 登录状态进入需要登录权限的页面,无权限,重定向到无权限页面
|
|
36
|
+
else if (isLogin && needLogin && !hasPermission)
|
|
37
|
+
return next({ name: rouneNames[403], replace: true });
|
|
38
|
+
|
|
39
|
+
return next(false);
|
|
40
|
+
});
|
|
41
|
+
}
|