@peng_kai/kit 0.0.14 → 0.0.16

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.
Files changed (91) hide show
  1. package/.vscode/settings.json +41 -0
  2. package/admin/components/filter/index.ts +5 -0
  3. package/admin/{filter → components/filter/src}/FilterDrawer.vue +99 -96
  4. package/admin/{filter → components/filter/src}/FilterParam.vue +76 -76
  5. package/admin/{filter → components/filter/src}/FilterReset.vue +7 -4
  6. package/admin/{filter → components/filter/src}/useFilterParams.ts +9 -9
  7. package/admin/{filter → components/filter/src}/useFilterQuery.ts +11 -11
  8. package/admin/components/scroll-nav/index.ts +1 -1
  9. package/admin/components/scroll-nav/src/ScrollNav.vue +59 -59
  10. package/admin/components/text/index.ts +13 -13
  11. package/admin/components/text/src/Amount.vue +117 -114
  12. package/admin/components/text/src/Datetime.vue +44 -44
  13. package/admin/components/text/src/Duration.vue +26 -26
  14. package/admin/components/text/src/Hash.vue +42 -40
  15. package/admin/components/text/src/createTagGetter.ts +13 -13
  16. package/admin/defines/index.ts +4 -5
  17. package/admin/defines/page/definePage.ts +12 -0
  18. package/admin/defines/page/index.ts +1 -0
  19. package/admin/defines/route/defineRoute.ts +14 -0
  20. package/admin/defines/route/getRoutes.ts +84 -0
  21. package/admin/defines/route/helpers.ts +49 -0
  22. package/admin/defines/route/index.ts +73 -0
  23. package/admin/defines/route-guard/defineRouteGuard.ts +18 -0
  24. package/admin/defines/route-guard/getRouteGuards.ts +40 -0
  25. package/admin/defines/route-guard/index.ts +2 -0
  26. package/admin/defines/startup/defineStartup.ts +11 -0
  27. package/admin/defines/startup/getStartups.ts +30 -0
  28. package/admin/defines/startup/index.ts +2 -0
  29. package/admin/hooks/index.ts +5 -6
  30. package/admin/hooks/useMenu.ts +128 -128
  31. package/admin/hooks/usePage.ts +141 -139
  32. package/admin/hooks/usePageTab.ts +35 -35
  33. package/admin/layout/large/Breadcrumb.vue +69 -70
  34. package/admin/layout/large/Content.vue +24 -24
  35. package/admin/layout/large/Menu.vue +69 -68
  36. package/admin/layout/large/PageTab.vue +71 -71
  37. package/admin/layout/large/index.ts +4 -4
  38. package/admin/permission/index.ts +4 -0
  39. package/admin/permission/routerGuard.ts +43 -0
  40. package/admin/permission/usePermission.ts +52 -0
  41. package/admin/permission/vuePlugin.ts +30 -0
  42. package/admin/route-guards/index.ts +2 -0
  43. package/admin/route-guards/pageProgress.ts +16 -0
  44. package/admin/route-guards/pageTitle.ts +24 -0
  45. package/admin/styles/globalCover.scss +43 -43
  46. package/admin/types/assist.ts +10 -0
  47. package/admin/unocss/index.ts +1 -1
  48. package/antd/components/InputNumberRange.vue +53 -47
  49. package/antd/directives/formLabelAlign.ts +36 -31
  50. package/antd/hooks/createAntdModal.ts +29 -29
  51. package/antd/hooks/useAntdDrawer.ts +73 -73
  52. package/antd/hooks/useAntdForm.helpers.ts +18 -18
  53. package/antd/hooks/useAntdForm.ts +38 -37
  54. package/antd/hooks/useAntdModal.ts +25 -25
  55. package/antd/hooks/useAntdTable.ts +70 -70
  56. package/antd/hooks/useAntdTheme.ts +86 -0
  57. package/antd/index.ts +8 -7
  58. package/eslint.config.js +50 -0
  59. package/kitDependencies.ts +21 -7
  60. package/package.json +46 -40
  61. package/pnpm-lock.yaml +2689 -0
  62. package/request/helpers.ts +49 -32
  63. package/request/index.ts +2 -2
  64. package/request/interceptors/checkCode.ts +8 -8
  65. package/request/interceptors/filterEmptyValue.ts +9 -9
  66. package/request/interceptors/formatPaging.ts +12 -12
  67. package/request/interceptors/index.ts +7 -6
  68. package/request/interceptors/popupMessage.ts +35 -35
  69. package/request/interceptors/returnResultType.ts +19 -19
  70. package/request/interceptors/toLogin.ts +13 -0
  71. package/request/interceptors/unitizeAxiosError.ts +7 -7
  72. package/request/queryClient.ts +42 -0
  73. package/request/request.ts +21 -21
  74. package/request/type.d.ts +89 -89
  75. package/tsconfig.json +47 -18
  76. package/utils/index.ts +67 -29
  77. package/vue/components/index.ts +1 -0
  78. package/{components → vue/components}/infinite-query/index.ts +1 -1
  79. package/{components → vue/components}/infinite-query/src/InfiniteQuery.vue +147 -147
  80. package/{components → vue/components}/infinite-query/src/useCreateTrigger.ts +35 -35
  81. package/vue/hooks/useComponentRef.ts +12 -12
  82. package/vue/hooks/useIsMounted.ts +4 -4
  83. package/vue/hooks/useTeleportTarget.ts +7 -7
  84. package/vue/index.ts +4 -3
  85. package/admin/defines/definePage.ts +0 -14
  86. package/admin/defines/defineRoute.helpers.ts +0 -30
  87. package/admin/defines/defineRoute.ts +0 -161
  88. package/admin/defines/defineRouteGuard.ts +0 -56
  89. package/admin/defines/defineStartup.ts +0 -41
  90. package/admin/filter/index.ts +0 -5
  91. package/admin/hooks/usePermission.ts +0 -5
@@ -1,68 +1,69 @@
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 type { TMenu } from '../../hooks'
6
- import { getDependencies } from "../../../kitDependencies";
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{ useRouter, useMenu } = getDependencies()
25
- const router = useRouter()
26
- const { menus, getMenuPath } = useMenu()
27
- const items = computed(() => menus.map(formatMenu))
28
- const openKeys = ref<string[]>([])
29
- const selectedKeys = ref<string[]>([])
30
-
31
- watch(
32
- () => router?.currentRoute.value,
33
- (route) => {
34
- if (!route) return;
35
-
36
- const menuPath = 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
- mode="inline"
51
- :inlineIndent="14"
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
+ <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 type { TMenu } from '../../hooks';
6
+ import { getDependencies } from '../../../kitDependencies';
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 { useRouter, useMenu } = getDependencies();
25
+ const router = useRouter();
26
+ const { menus, getMenuPath } = useMenu();
27
+ const items = computed(() => menus.map(formatMenu));
28
+ const openKeys = ref<string[]>([]);
29
+ const selectedKeys = ref<string[]>([]);
30
+
31
+ watch(
32
+ () => router?.currentRoute.value,
33
+ (route) => {
34
+ if (!route)
35
+ return;
36
+
37
+ const menuPath = getMenuPath(route.name as string);
38
+ openKeys.value = menuPath.map(menu => menu.key);
39
+ selectedKeys.value = [openKeys.value.pop()!];
40
+ },
41
+ { immediate: true },
42
+ );
43
+ </script>
44
+
45
+ <template>
46
+ <AMenu
47
+ class="menu"
48
+ :items="items"
49
+ :openKeys="openKeys"
50
+ :selectedKeys="selectedKeys"
51
+ mode="inline"
52
+ :inlineIndent="14"
53
+ />
54
+ </template>
55
+
56
+ <style lang="scss" scoped>
57
+ .menu {
58
+ border-inline-end: none !important;
59
+
60
+ &.ant-menu-inline-collapsed {
61
+ width: var(--app-siderbar-width);
62
+ }
63
+
64
+ &,
65
+ .ant-menu {
66
+ background-color: transparent;
67
+ }
68
+ }
69
+ </style>
@@ -1,71 +1,71 @@
1
- <script setup lang="ts">
2
- import { Tabs as ATabs, TabPane as ATabPane } from "ant-design-vue";
3
- import { getDependencies } from "../../../kitDependencies";
4
-
5
- const { usePageTab } = getDependencies()
6
- const { activeTab, tabList, openTab, closeTab } = usePageTab()
7
- </script>
8
-
9
- <template>
10
- <ATabs
11
- class="app-page-tabs"
12
- :activeKey="activeTab"
13
- type="editable-card"
14
- size="small"
15
- :animated="false"
16
- :hideAdd="true"
17
- :tabBarGutter="4"
18
- @tabClick="(openTab as any)"
19
- @edit="(closeTab as any)"
20
- >
21
- <ATabPane v-for="tab of tabList" :key="tab.key" :tab="tab.title">
22
- <template #closeIcon>
23
- <i class="i-icon-park-outline:close" />
24
- </template>
25
- </ATabPane>
26
- </ATabs>
27
- </template>
28
-
29
- <style scoped lang="scss">
30
- .app-page-tabs {
31
- :deep(.ant-tabs-nav) {
32
- margin: 0;
33
- }
34
-
35
- :deep(.ant-tabs-nav::before) {
36
- display: none;
37
- }
38
-
39
- :deep(.ant-tabs-tab) {
40
- --uno: 'border-rd-3px! text-14px p-[3px_1px_3px_8px]! select-none';
41
- }
42
-
43
- :deep(.ant-tabs-tab .ant-tabs-tab-btn) {
44
- transform: translateX(8px);
45
- }
46
-
47
- :deep(.ant-tabs-tab-active) {
48
- --uno: 'border-[currentColor]!';
49
- }
50
-
51
- :deep(.ant-tabs-tab-remove) {
52
- display: flex;
53
- height: 100%;
54
- align-items: center;
55
- margin: 0;
56
- opacity: 0;
57
- transition: all 150ms;
58
- }
59
-
60
- :deep(.ant-tabs-tab:hover .ant-tabs-tab-btn),
61
- :deep(.ant-tabs-tab-active .ant-tabs-tab-btn) {
62
- transform: translateX(0);
63
- }
64
-
65
- :deep(.ant-tabs-tab:hover .ant-tabs-tab-remove),
66
- :deep(.ant-tabs-tab-active .ant-tabs-tab-remove) {
67
- margin-left: 0;
68
- opacity: 1;
69
- }
70
- }
71
- </style>
1
+ <script setup lang="ts">
2
+ import { TabPane as ATabPane, Tabs as ATabs } from 'ant-design-vue';
3
+ import { getDependencies } from '../../../kitDependencies';
4
+
5
+ const { usePageTab } = getDependencies();
6
+ const { activeTab, tabList, openTab, closeTab } = usePageTab();
7
+ </script>
8
+
9
+ <template>
10
+ <ATabs
11
+ class="app-page-tabs"
12
+ :activeKey="activeTab"
13
+ type="editable-card"
14
+ size="small"
15
+ :animated="false"
16
+ :hideAdd="true"
17
+ :tabBarGutter="4"
18
+ @tabClick="(openTab as any)"
19
+ @edit="(closeTab as any)"
20
+ >
21
+ <ATabPane v-for="tab of tabList" :key="tab.key" :tab="tab.title">
22
+ <template #closeIcon>
23
+ <i class="i-icon-park-outline:close" />
24
+ </template>
25
+ </ATabPane>
26
+ </ATabs>
27
+ </template>
28
+
29
+ <style scoped lang="scss">
30
+ .app-page-tabs {
31
+ :deep(.ant-tabs-nav) {
32
+ margin: 0;
33
+ }
34
+
35
+ :deep(.ant-tabs-nav::before) {
36
+ display: none;
37
+ }
38
+
39
+ :deep(.ant-tabs-tab) {
40
+ --uno: 'border-rd-3px! text-14px p-[3px_1px_3px_8px]! select-none';
41
+ }
42
+
43
+ :deep(.ant-tabs-tab .ant-tabs-tab-btn) {
44
+ transform: translateX(8px);
45
+ }
46
+
47
+ :deep(.ant-tabs-tab-active) {
48
+ --uno: 'border-[currentColor]!';
49
+ }
50
+
51
+ :deep(.ant-tabs-tab-remove) {
52
+ display: flex;
53
+ height: 100%;
54
+ align-items: center;
55
+ margin: 0;
56
+ opacity: 0;
57
+ transition: all 150ms;
58
+ }
59
+
60
+ :deep(.ant-tabs-tab:hover .ant-tabs-tab-btn),
61
+ :deep(.ant-tabs-tab-active .ant-tabs-tab-btn) {
62
+ transform: translateX(0);
63
+ }
64
+
65
+ :deep(.ant-tabs-tab:hover .ant-tabs-tab-remove),
66
+ :deep(.ant-tabs-tab-active .ant-tabs-tab-remove) {
67
+ margin-left: 0;
68
+ opacity: 1;
69
+ }
70
+ }
71
+ </style>
@@ -1,4 +1,4 @@
1
- export { default as Breadcrumb } from './Breadcrumb.vue'
2
- export { default as Content } from './Content.vue'
3
- export { default as Menu } from './Menu.vue'
4
- export { default as PageTab } from './PageTab.vue'
1
+ export { default as Breadcrumb } from './Breadcrumb.vue';
2
+ export { default as Content } from './Content.vue';
3
+ export { default as Menu } from './Menu.vue';
4
+ export { default as PageTab } from './PageTab.vue';
@@ -0,0 +1,4 @@
1
+ export { setupPermissionRouterGuard } from './routerGuard';
2
+ export { setupPermissionPlugin } from './vuePlugin';
3
+ export { usePermission } from './usePermission';
4
+ export type { THasPermissionsFn } from './vuePlugin';
@@ -0,0 +1,43 @@
1
+ import type { Router } from 'vue-router';
2
+ import { getDependencies } from '../../kitDependencies';
3
+ import { hasToken } from '../../utils';
4
+
5
+ export function setupPermissionRouterGuard(router: Router, rouneNames: { index: string, login: string, 403: string }) {
6
+ const { usePermission } = getDependencies();
7
+ const { refreshPermission, hasPermissions } = usePermission();
8
+
9
+ router.beforeEach(async (to, _, next) => {
10
+ const isLogin = hasToken();
11
+ const needLogin = Boolean(to.meta?.requireAuth);
12
+ let hasPermission = false;
13
+
14
+ if (isLogin) {
15
+ await refreshPermission();
16
+
17
+ const permissionCode = to.meta?.permissionCode;
18
+ hasPermission = permissionCode ? hasPermissions(permissionCode) : true;
19
+ }
20
+
21
+ // 已登录状态跳转登录页,跳转至首页
22
+ if (isLogin && to.name === rouneNames.login)
23
+ return next({ name: rouneNames.index, replace: true });
24
+
25
+ // 不需要登录权限的页面直接通行
26
+ else if (!needLogin)
27
+ return next(true);
28
+
29
+ // 未登录状态进入需要登录权限的页面
30
+ else if (!isLogin && needLogin)
31
+ return next({ name: rouneNames.login, replace: true });
32
+
33
+ // 登录状态进入需要登录权限的页面,有权限直接通行
34
+ else if (isLogin && needLogin && hasPermission)
35
+ return next(true);
36
+
37
+ // 登录状态进入需要登录权限的页面,无权限,重定向到无权限页面
38
+ else if (isLogin && needLogin && !hasPermission)
39
+ return next({ name: rouneNames[403], replace: true });
40
+
41
+ return next(false);
42
+ });
43
+ }
@@ -0,0 +1,52 @@
1
+ import { createGlobalState } from '@vueuse/core';
2
+ import type { AsyncReturnType } from 'type-fest';
3
+ import { computed, readonly, ref, watch } from 'vue';
4
+ import { getDependencies } from '../../kitDependencies';
5
+
6
+ export { usePermission };
7
+ export type { TRole };
8
+
9
+ type TRole = () => Promise<Record<string, boolean> | null | undefined>;
10
+
11
+ const usePermission = createGlobalState(() => {
12
+ const { roles } = getDependencies();
13
+ const role = ref('main');
14
+ const permissionCodes = ref<AsyncReturnType<TRole>>();
15
+ const permissionCodesStr = computed(() => Object.keys(permissionCodes.value ?? {}).sort().join(','));
16
+
17
+ /**
18
+ * 刷新权限
19
+ */
20
+ const refreshPermission = async () => {
21
+ permissionCodes.value = await roles[role.value]?.();
22
+
23
+ return permissionCodes.value;
24
+ };
25
+
26
+ /**
27
+ * 是否满足权限要求
28
+ * @param codes 权限 code
29
+ */
30
+ const hasPermissions = (codes: string | string[]) => {
31
+ const _codes = Array.isArray(codes) ? codes : [codes];
32
+ const _permissionCodes = permissionCodes.value;
33
+
34
+ if (_permissionCodes === null)
35
+ return false;
36
+ else if (_permissionCodes === undefined)
37
+ // undefined 则表示没有权限要求,返回 true
38
+ return true;
39
+ else
40
+ return _codes.every(code => !!_permissionCodes[code]);
41
+ };
42
+
43
+ watch(role, refreshPermission, { immediate: true });
44
+
45
+ return {
46
+ permissionCodes: readonly(permissionCodes),
47
+ permissionCodesStr,
48
+ role,
49
+ hasPermissions,
50
+ refreshPermission,
51
+ };
52
+ });
@@ -0,0 +1,30 @@
1
+ import type { App } from 'vue';
2
+ import { getDependencies } from '../../kitDependencies';
3
+
4
+ export type THasPermissionsFn = ReturnType<ReturnType<typeof getDependencies>['usePermission']>['hasPermissions'];
5
+
6
+ export function setupPermissionPlugin(app: App) {
7
+ const { usePermission } = getDependencies();
8
+ const { hasPermissions } = usePermission();
9
+
10
+ app.directive('has-permissions', {
11
+ mounted(el, binding) {
12
+ const codes = binding.value;
13
+
14
+ if (!hasPermissions(codes))
15
+ el.remove();
16
+ },
17
+ updated(el, binding) {
18
+ const codes = binding.value;
19
+
20
+ if (!hasPermissions(codes))
21
+ el.remove();
22
+ },
23
+ });
24
+
25
+ app.use({
26
+ install(app) {
27
+ app.config.globalProperties.$hasPermission = hasPermissions;
28
+ },
29
+ });
30
+ }
@@ -0,0 +1,2 @@
1
+ export { setupPageProgress } from './pageProgress';
2
+ export { setupPageTitle } from './pageTitle';
@@ -0,0 +1,16 @@
1
+ import type { Router } from 'vue-router';
2
+ import { getDependencies } from '../../kitDependencies';
3
+
4
+ export function setupPageProgress(router: Router) {
5
+ const deps = getDependencies();
6
+
7
+ router.afterEach((to, _, err) => {
8
+ const title = to.meta.title;
9
+
10
+ if (!err) {
11
+ document.title = typeof title === 'function'
12
+ ? title()
13
+ : title ?? deps.appName;
14
+ }
15
+ });
16
+ }
@@ -0,0 +1,24 @@
1
+ import type { Router } from 'vue-router';
2
+ import { useStyleTag } from '@vueuse/core';
3
+ import NProgress from 'nprogress';
4
+ import 'nprogress/nprogress.css';
5
+
6
+ export function setupPageTitle(router: Router) {
7
+ NProgress.configure({ showSpinner: false });
8
+ useStyleTag(`
9
+ #nprogress .bar {
10
+ height: 3px;
11
+ background: var(--antd-colorPrimary);
12
+ }
13
+ #nprogress .peg {
14
+ box-shadow: 0 0 10px var(--antd-colorPrimary), 0 0 5px var(--antd-colorPrimary);
15
+ }
16
+ `);
17
+
18
+ router.beforeEach(() => {
19
+ NProgress.start();
20
+ });
21
+ router.afterEach(() => {
22
+ setTimeout(() => NProgress.done(), 200);
23
+ });
24
+ }
@@ -1,43 +1,43 @@
1
- :root {
2
- // table 组件头部圆角设为 0
3
- .ant-table-wrapper {
4
- .ant-table .ant-table-header,
5
- table,
6
- .ant-table-container table > thead > tr:first-child > *:first-child,
7
- .ant-table-container table > thead > tr:first-child > *:last-child {
8
- border-radius: 0;
9
- }
10
-
11
- .ant-pagination {
12
- margin-bottom: 0;
13
- }
14
- }
15
-
16
-
17
- // 隐藏在 sticky 模式下的滚动条
18
- .ant-table-sticky-scroll {
19
- display: none;
20
- }
21
-
22
- // 卡片
23
- .ant-card .ant-card-actions > li > span {
24
- cursor: inherit;
25
- }
26
-
27
- // Tab 溢出出现下列框时
28
- .ant-tabs-dropdown-menu-title-content {
29
- display: flex;
30
- align-items: center;
31
- justify-content: space-between;
32
- }
33
-
34
- // 表格
35
- .ant-table-wrapper {
36
- .ant-table-row-expand-icon-collapsed::before {
37
- height: 1.5px;
38
- }
39
- .ant-table-row-expand-icon-collapsed::after {
40
- width: 1.5px;
41
- }
42
- }
43
- }
1
+ :root {
2
+ // table 组件头部圆角设为 0
3
+ .ant-table-wrapper {
4
+ .ant-table .ant-table-header,
5
+ table,
6
+ .ant-table-container table > thead > tr:first-child > *:first-child,
7
+ .ant-table-container table > thead > tr:first-child > *:last-child {
8
+ border-radius: 0;
9
+ }
10
+
11
+ .ant-pagination {
12
+ margin-bottom: 0;
13
+ }
14
+ }
15
+
16
+
17
+ // 隐藏在 sticky 模式下的滚动条
18
+ .ant-table-sticky-scroll {
19
+ display: none;
20
+ }
21
+
22
+ // 卡片
23
+ .ant-card .ant-card-actions > li > span {
24
+ cursor: inherit;
25
+ }
26
+
27
+ // Tab 溢出出现下列框时
28
+ .ant-tabs-dropdown-menu-title-content {
29
+ display: flex;
30
+ align-items: center;
31
+ justify-content: space-between;
32
+ }
33
+
34
+ // 表格
35
+ .ant-table-wrapper {
36
+ .ant-table-row-expand-icon-collapsed::before {
37
+ height: 1.5px;
38
+ }
39
+ .ant-table-row-expand-icon-collapsed::after {
40
+ width: 1.5px;
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,10 @@
1
+ import { createSelfKeyProxy } from '../../utils';
2
+
3
+ export declare interface AppPermissionCodes {}
4
+ export declare interface AppRouteNames {}
5
+
6
+ /** 权限 code 类型辅助(permission code) */
7
+ export const pc_ = createSelfKeyProxy<{ [K in keyof AppPermissionCodes]: K }>();
8
+
9
+ /** 路由 name 类型辅助(route name) */
10
+ export const rn_ = createSelfKeyProxy<{ [K in keyof AppRouteNames]: K }>();
@@ -3,4 +3,4 @@ export const shortcuts = [
3
3
  ['page-section', 'p-4 bg-$antd-colorBgContainer'],
4
4
  // 用于 FormItem 在 flex布局下的自适应
5
5
  [/^fiw-(.*?)_(.*?)_(.*?)$/, ([, w1, w2, w3]) => `min-w-${w1} w-${w2} max-w-${w3} flex-auto`],
6
- ]
6
+ ];