Commit 215d8bab380728164d7fe2958c2d2d1151fce892

Authored by Vben
1 parent 700306bb

refactor: refactor store

Showing 80 changed files with 1546 additions and 1497 deletions
build/generate/generateModifyVars.ts
... ... @@ -28,6 +28,7 @@ export function generateModifyVars(dark = false) {
28 28 'success-color': '#55D187', // Success color
29 29 'error-color': '#ED6F6F', // False color
30 30 'warning-color': '#EFBD47', // Warning color
  31 + 'border-color-base': '#EEEEEE',
31 32 'font-size-base': '14px', // Main font size
32 33 'border-radius-base': '2px', // Component/float fillet
33 34 'link-color': primary, // Link color
... ...
index.html
... ... @@ -16,9 +16,11 @@
16 16 <script>
17 17 (() => {
18 18 var htmlRoot = document.getElementById('htmlRoot');
19   - const theme = window.localStorage.getItem('__APP__DARK__MODE__');
20   - if (!htmlRoot || !theme) return;
21   - htmlRoot.setAttribute('data-theme', theme);
  19 + var theme = window.localStorage.getItem('__APP__DARK__MODE__');
  20 + if (htmlRoot && theme) {
  21 + htmlRoot.setAttribute('data-theme', theme);
  22 + theme = htmlRoot = null;
  23 + }
22 24 })();
23 25 </script>
24 26 <div id="app">
... ...
package.json
... ... @@ -32,7 +32,7 @@
32 32 },
33 33 "dependencies": {
34 34 "@iconify/iconify": "^2.0.0-rc.6",
35   - "@vueuse/core": "^4.8.0",
  35 + "@vueuse/core": "^4.8.1",
36 36 "@zxcvbn-ts/core": "^0.3.0",
37 37 "ant-design-vue": "^2.1.2",
38 38 "axios": "^0.21.1",
... ... @@ -43,6 +43,7 @@
43 43 "mockjs": "^1.1.0",
44 44 "nprogress": "^0.2.0",
45 45 "path-to-regexp": "^6.2.0",
  46 + "pinia": "^2.0.0-alpha.12",
46 47 "print-js": "^1.6.0",
47 48 "qrcode": "^1.4.4",
48 49 "sortablejs": "^1.13.0",
... ... @@ -52,8 +53,6 @@
52 53 "vue-i18n": "9.0.0",
53 54 "vue-router": "^4.0.6",
54 55 "vue-types": "^3.0.2",
55   - "vuex": "^4.0.0",
56   - "vuex-module-decorators": "^1.0.1",
57 56 "xlsx": "^0.16.9"
58 57 },
59 58 "devDependencies": {
... ... @@ -81,7 +80,7 @@
81 80 "conventional-changelog-cli": "^2.1.1",
82 81 "cross-env": "^7.0.3",
83 82 "dotenv": "^8.2.0",
84   - "eslint": "^7.23.0",
  83 + "eslint": "^7.24.0",
85 84 "eslint-config-prettier": "^8.1.0",
86 85 "eslint-define-config": "^1.0.7",
87 86 "eslint-plugin-prettier": "^3.3.1",
... ... @@ -115,13 +114,14 @@
115 114 "vite-plugin-style-import": "^0.9.2",
116 115 "vite-plugin-svg-icons": "^0.4.1",
117 116 "vite-plugin-theme": "^0.6.3",
118   - "vite-plugin-windicss": "0.12.5",
  117 + "vite-plugin-windicss": "0.13.1",
119 118 "vue-eslint-parser": "^7.6.0"
120 119 },
121 120 "resolutions": {
122 121 "//": "Used to install imagemin dependencies, because imagemin may not be installed in China.If it is abroad, you can delete it",
123 122 "bin-wrapper": "npm:bin-wrapper-china",
124   - "rollup": "^2.44.0"
  123 + "rollup": "^2.45.1",
  124 + "esbuild": "^0.11.6"
125 125 },
126 126 "repository": {
127 127 "type": "git",
... ...
src/components/Application/src/AppProvider.vue
... ... @@ -3,22 +3,24 @@
3 3  
4 4 import { createAppProviderContext } from './useAppContext';
5 5  
6   - import designSetting from '/@/settings/designSetting';
  6 + import { prefixCls } from '/@/settings/designSetting';
7 7 import { createBreakpointListen } from '/@/hooks/event/useBreakpoint';
8 8 import { propTypes } from '/@/utils/propTypes';
9   - import { appStore } from '/@/store/modules/app';
  9 + import { useAppStore } from '/@/store/modules/app';
10 10 import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
11 11  
12 12 export default defineComponent({
13 13 name: 'AppProvider',
14 14 inheritAttrs: false,
15 15 props: {
16   - prefixCls: propTypes.string.def(designSetting.prefixCls),
  16 + prefixCls: propTypes.string.def(prefixCls),
17 17 },
18 18 setup(props, { slots }) {
19 19 const isMobile = ref(false);
20 20 const isSetState = ref(false);
21 21  
  22 + const appStore = useAppStore();
  23 +
22 24 createBreakpointListen(({ screenMap, sizeEnum, width }) => {
23 25 const lgWidth = screenMap.get(sizeEnum.LG);
24 26 if (lgWidth) {
... ... @@ -42,20 +44,20 @@
42 44 split: menuSplit,
43 45 },
44 46 } = appStore.getProjectConfig;
45   - appStore.commitProjectConfigState({
  47 + appStore.setProjectConfig({
46 48 menuSetting: {
47 49 type: MenuTypeEnum.SIDEBAR,
48 50 mode: MenuModeEnum.INLINE,
49 51 split: false,
50 52 },
51 53 });
52   - appStore.commitBeforeMiniState({ menuMode, menuCollapsed, menuType, menuSplit });
  54 + appStore.setBeforeMiniInfo({ menuMode, menuCollapsed, menuType, menuSplit });
53 55 }
54 56 } else {
55 57 if (unref(isSetState)) {
56 58 isSetState.value = false;
57   - const { menuMode, menuCollapsed, menuType, menuSplit } = appStore.getBeforeMiniState;
58   - appStore.commitProjectConfigState({
  59 + const { menuMode, menuCollapsed, menuType, menuSplit } = appStore.getBeforeMiniInfo;
  60 + appStore.setProjectConfig({
59 61 menuSetting: {
60 62 type: menuType,
61 63 mode: menuMode,
... ...
src/components/Application/src/search/AppSearchKeyItem.vue
1 1 <template>
2 2 <span :class="$attrs.class">
3   - <Icon :icon="icon" />
  3 + <g-icon :icon="icon" />
4 4 </span>
5 5 </template>
6 6 <script lang="ts">
7 7 import { defineComponent } from 'vue';
8   - import { Icon } from '/@/components/Icon';
9   - import { propTypes } from '/@/utils/propTypes';
10   -
11 8 export default defineComponent({
12   - components: { Icon },
13 9 props: {
14   - icon: propTypes.string,
  10 + icon: String,
15 11 },
16 12 });
17 13 </script>
... ...
src/components/SimpleMenu/src/SimpleMenu.vue
... ... @@ -6,7 +6,6 @@
6 6 :class="prefixCls"
7 7 :activeSubMenuNames="activeSubMenuNames"
8 8 @select="handleSelect"
9   - @open-change="handleOpenChange"
10 9 >
11 10 <template v-for="item in items" :key="item.path">
12 11 <SimpleSubMenu
... ... @@ -140,17 +139,11 @@
140 139 menuState.activeName = key;
141 140 }
142 141  
143   - function handleOpenChange(v) {
144   - console.log('======================');
145   - console.log(v);
146   - console.log('======================');
147   - }
148 142 return {
149 143 prefixCls,
150 144 getBindValues,
151 145 handleSelect,
152 146 getOpenKeys,
153   - handleOpenChange,
154 147 ...toRefs(menuState),
155 148 };
156 149 },
... ...
src/hooks/setting/useHeaderSetting.ts
... ... @@ -2,94 +2,89 @@ import type { HeaderSetting } from &#39;/#/config&#39;;
2 2  
3 3 import { computed, unref } from 'vue';
4 4  
5   -import { appStore } from '/@/store/modules/app';
  5 +import { useAppStore } from '/@/store/modules/app';
6 6  
7 7 import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
8 8 import { useRootSetting } from '/@/hooks/setting/useRootSetting';
9 9 import { useFullContent } from '/@/hooks/web/useFullContent';
10   -
11 10 import { MenuModeEnum } from '/@/enums/menuEnum';
12 11  
13   -const { getFullContent } = useFullContent();
14   -const {
15   - getMenuMode,
16   - getSplit,
17   - getShowHeaderTrigger,
18   - getIsSidebarType,
19   - getIsMixSidebar,
20   - getIsTopMenu,
21   -} = useMenuSetting();
22   -const { getShowBreadCrumb, getShowLogo } = useRootSetting();
23   -
24   -const getShowMixHeaderRef = computed(() => !unref(getIsSidebarType) && unref(getShowHeader));
  12 +export function useHeaderSetting() {
  13 + const { getFullContent } = useFullContent();
  14 + const appStore = useAppStore();
25 15  
26   -const getShowFullHeaderRef = computed(() => {
27   - return (
28   - !unref(getFullContent) &&
29   - unref(getShowMixHeaderRef) &&
30   - unref(getShowHeader) &&
31   - !unref(getIsTopMenu) &&
32   - !unref(getIsMixSidebar)
33   - );
34   -});
  16 + const getShowFullHeaderRef = computed(() => {
  17 + return (
  18 + !unref(getFullContent) &&
  19 + unref(getShowMixHeaderRef) &&
  20 + unref(getShowHeader) &&
  21 + !unref(getIsTopMenu) &&
  22 + !unref(getIsMixSidebar)
  23 + );
  24 + });
35 25  
36   -const getShowInsetHeaderRef = computed(() => {
37   - const need = !unref(getFullContent) && unref(getShowHeader);
38   - return (
39   - (need && !unref(getShowMixHeaderRef)) ||
40   - (need && unref(getIsTopMenu)) ||
41   - (need && unref(getIsMixSidebar))
42   - );
43   -});
  26 + const getUnFixedAndFull = computed(() => !unref(getFixed) && !unref(getShowFullHeaderRef));
44 27  
45   -// Get header configuration
46   -const getHeaderSetting = computed(() => appStore.getProjectConfig.headerSetting);
  28 + const getShowInsetHeaderRef = computed(() => {
  29 + const need = !unref(getFullContent) && unref(getShowHeader);
  30 + return (
  31 + (need && !unref(getShowMixHeaderRef)) ||
  32 + (need && unref(getIsTopMenu)) ||
  33 + (need && unref(getIsMixSidebar))
  34 + );
  35 + });
47 36  
48   -const getShowDoc = computed(() => unref(getHeaderSetting).showDoc);
  37 + const {
  38 + getMenuMode,
  39 + getSplit,
  40 + getShowHeaderTrigger,
  41 + getIsSidebarType,
  42 + getIsMixSidebar,
  43 + getIsTopMenu,
  44 + } = useMenuSetting();
  45 + const { getShowBreadCrumb, getShowLogo } = useRootSetting();
49 46  
50   -const getHeaderTheme = computed(() => unref(getHeaderSetting).theme);
  47 + const getShowMixHeaderRef = computed(() => !unref(getIsSidebarType) && unref(getShowHeader));
51 48  
52   -const getShowHeader = computed(() => unref(getHeaderSetting).show);
  49 + const getShowDoc = computed(() => appStore.getHeaderSetting.showDoc);
53 50  
54   -const getFixed = computed(() => unref(getHeaderSetting).fixed);
  51 + const getHeaderTheme = computed(() => appStore.getHeaderSetting.theme);
55 52  
56   -const getHeaderBgColor = computed(() => unref(getHeaderSetting).bgColor);
  53 + const getShowHeader = computed(() => appStore.getHeaderSetting.show);
57 54  
58   -const getShowSearch = computed(() => unref(getHeaderSetting).showSearch);
  55 + const getFixed = computed(() => appStore.getHeaderSetting.fixed);
59 56  
60   -const getUseLockPage = computed(() => unref(getHeaderSetting).useLockPage);
  57 + const getHeaderBgColor = computed(() => appStore.getHeaderSetting.bgColor);
61 58  
62   -const getShowFullScreen = computed(() => unref(getHeaderSetting).showFullScreen);
  59 + const getShowSearch = computed(() => appStore.getHeaderSetting.showSearch);
63 60  
64   -const getShowNotice = computed(() => unref(getHeaderSetting).showNotice);
  61 + const getUseLockPage = computed(() => appStore.getHeaderSetting.useLockPage);
65 62  
66   -const getUnFixedAndFull = computed(() => !unref(getFixed) && !unref(getShowFullHeaderRef));
  63 + const getShowFullScreen = computed(() => appStore.getHeaderSetting.showFullScreen);
67 64  
68   -const getShowBread = computed(() => {
69   - return (
70   - unref(getMenuMode) !== MenuModeEnum.HORIZONTAL && unref(getShowBreadCrumb) && !unref(getSplit)
71   - );
72   -});
  65 + const getShowNotice = computed(() => appStore.getHeaderSetting.showNotice);
73 66  
74   -const getShowHeaderLogo = computed(() => {
75   - return unref(getShowLogo) && !unref(getIsSidebarType) && !unref(getIsMixSidebar);
76   -});
  67 + const getShowBread = computed(() => {
  68 + return (
  69 + unref(getMenuMode) !== MenuModeEnum.HORIZONTAL && unref(getShowBreadCrumb) && !unref(getSplit)
  70 + );
  71 + });
77 72  
78   -const getShowContent = computed(() => {
79   - return unref(getShowBread) || unref(getShowHeaderTrigger);
80   -});
  73 + const getShowHeaderLogo = computed(() => {
  74 + return unref(getShowLogo) && !unref(getIsSidebarType) && !unref(getIsMixSidebar);
  75 + });
81 76  
82   -// Set header configuration
83   -function setHeaderSetting(headerSetting: Partial<HeaderSetting>): void {
84   - appStore.commitProjectConfigState({ headerSetting });
85   -}
  77 + const getShowContent = computed(() => {
  78 + return unref(getShowBread) || unref(getShowHeaderTrigger);
  79 + });
86 80  
87   -export function useHeaderSetting() {
  81 + // Set header configuration
  82 + function setHeaderSetting(headerSetting: Partial<HeaderSetting>) {
  83 + appStore.setProjectConfig({ headerSetting });
  84 + }
88 85 return {
89 86 setHeaderSetting,
90 87  
91   - getHeaderSetting,
92   -
93 88 getShowDoc,
94 89 getShowSearch,
95 90 getHeaderTheme,
... ...
src/hooks/setting/useMenuSetting.ts
... ... @@ -2,7 +2,7 @@ import type { MenuSetting } from &#39;/#/config&#39;;
2 2  
3 3 import { computed, unref, ref } from 'vue';
4 4  
5   -import { appStore } from '/@/store/modules/app';
  5 +import { useAppStore } from '/@/store/modules/app';
6 6  
7 7 import { SIDE_BAR_MINI_WIDTH, SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '/@/enums/appEnum';
8 8 import { MenuModeEnum, MenuTypeEnum, TriggerEnum } from '/@/enums/menuEnum';
... ... @@ -10,127 +10,129 @@ import { useFullContent } from &#39;/@/hooks/web/useFullContent&#39;;
10 10  
11 11 const mixSideHasChildren = ref(false);
12 12  
13   -// Get menu configuration
14   -const getMenuSetting = computed(() => appStore.getProjectConfig.menuSetting);
  13 +export function useMenuSetting() {
  14 + const { getFullContent: fullContent } = useFullContent();
  15 + const appStore = useAppStore();
  16 +
  17 + const getShowSidebar = computed(() => {
  18 + return (
  19 + unref(getSplit) ||
  20 + (unref(getShowMenu) && unref(getMenuMode) !== MenuModeEnum.HORIZONTAL && !unref(fullContent))
  21 + );
  22 + });
15 23  
16   -const getCollapsed = computed(() => unref(getMenuSetting).collapsed);
  24 + const getCollapsed = computed(() => appStore.getMenuSetting.collapsed);
17 25  
18   -const getMenuType = computed(() => unref(getMenuSetting).type);
  26 + const getMenuType = computed(() => appStore.getMenuSetting.type);
19 27  
20   -const getMenuMode = computed(() => unref(getMenuSetting).mode);
  28 + const getMenuMode = computed(() => appStore.getMenuSetting.mode);
21 29  
22   -const getMenuFixed = computed(() => unref(getMenuSetting).fixed);
  30 + const getMenuFixed = computed(() => appStore.getMenuSetting.fixed);
23 31  
24   -const getShowMenu = computed(() => unref(getMenuSetting).show);
  32 + const getShowMenu = computed(() => appStore.getMenuSetting.show);
25 33  
26   -const getMenuHidden = computed(() => unref(getMenuSetting).hidden);
  34 + const getMenuHidden = computed(() => appStore.getMenuSetting.hidden);
27 35  
28   -const getMenuWidth = computed(() => unref(getMenuSetting).menuWidth);
  36 + const getMenuWidth = computed(() => appStore.getMenuSetting.menuWidth);
29 37  
30   -const getTrigger = computed(() => unref(getMenuSetting).trigger);
  38 + const getTrigger = computed(() => appStore.getMenuSetting.trigger);
31 39  
32   -const getMenuTheme = computed(() => unref(getMenuSetting).theme);
  40 + const getMenuTheme = computed(() => appStore.getMenuSetting.theme);
33 41  
34   -const getSplit = computed(() => unref(getMenuSetting).split);
  42 + const getSplit = computed(() => appStore.getMenuSetting.split);
35 43  
36   -const getMenuBgColor = computed(() => unref(getMenuSetting).bgColor);
  44 + const getMenuBgColor = computed(() => appStore.getMenuSetting.bgColor);
37 45  
38   -const getMixSideTrigger = computed(() => unref(getMenuSetting).mixSideTrigger);
  46 + const getMixSideTrigger = computed(() => appStore.getMenuSetting.mixSideTrigger);
39 47  
40   -const getCanDrag = computed(() => unref(getMenuSetting).canDrag);
  48 + const getCanDrag = computed(() => appStore.getMenuSetting.canDrag);
41 49  
42   -const getAccordion = computed(() => unref(getMenuSetting).accordion);
  50 + const getAccordion = computed(() => appStore.getMenuSetting.accordion);
43 51  
44   -const getMixSideFixed = computed(() => unref(getMenuSetting).mixSideFixed);
  52 + const getMixSideFixed = computed(() => appStore.getMenuSetting.mixSideFixed);
45 53  
46   -const getTopMenuAlign = computed(() => unref(getMenuSetting).topMenuAlign);
  54 + const getTopMenuAlign = computed(() => appStore.getMenuSetting.topMenuAlign);
47 55  
48   -const getCloseMixSidebarOnChange = computed(() => unref(getMenuSetting).closeMixSidebarOnChange);
  56 + const getCloseMixSidebarOnChange = computed(
  57 + () => appStore.getMenuSetting.closeMixSidebarOnChange
  58 + );
49 59  
50   -const getIsSidebarType = computed(() => unref(getMenuType) === MenuTypeEnum.SIDEBAR);
  60 + const getIsSidebarType = computed(() => unref(getMenuType) === MenuTypeEnum.SIDEBAR);
51 61  
52   -const getIsTopMenu = computed(() => unref(getMenuType) === MenuTypeEnum.TOP_MENU);
  62 + const getIsTopMenu = computed(() => unref(getMenuType) === MenuTypeEnum.TOP_MENU);
53 63  
54   -const getCollapsedShowTitle = computed(() => unref(getMenuSetting).collapsedShowTitle);
  64 + const getCollapsedShowTitle = computed(() => appStore.getMenuSetting.collapsedShowTitle);
55 65  
56   -const getShowTopMenu = computed(() => {
57   - return unref(getMenuMode) === MenuModeEnum.HORIZONTAL || unref(getSplit);
58   -});
  66 + const getShowTopMenu = computed(() => {
  67 + return unref(getMenuMode) === MenuModeEnum.HORIZONTAL || unref(getSplit);
  68 + });
59 69  
60   -const getShowHeaderTrigger = computed(() => {
61   - if (unref(getMenuType) === MenuTypeEnum.TOP_MENU || !unref(getShowMenu) || unref(getMenuHidden)) {
62   - return false;
63   - }
  70 + const getShowHeaderTrigger = computed(() => {
  71 + if (
  72 + unref(getMenuType) === MenuTypeEnum.TOP_MENU ||
  73 + !unref(getShowMenu) ||
  74 + unref(getMenuHidden)
  75 + ) {
  76 + return false;
  77 + }
64 78  
65   - return unref(getTrigger) === TriggerEnum.HEADER;
66   -});
  79 + return unref(getTrigger) === TriggerEnum.HEADER;
  80 + });
67 81  
68   -const getIsHorizontal = computed(() => {
69   - return unref(getMenuMode) === MenuModeEnum.HORIZONTAL;
70   -});
  82 + const getIsHorizontal = computed(() => {
  83 + return unref(getMenuMode) === MenuModeEnum.HORIZONTAL;
  84 + });
71 85  
72   -const getIsMixSidebar = computed(() => {
73   - return unref(getMenuType) === MenuTypeEnum.MIX_SIDEBAR;
74   -});
  86 + const getIsMixSidebar = computed(() => {
  87 + return unref(getMenuType) === MenuTypeEnum.MIX_SIDEBAR;
  88 + });
75 89  
76   -const getIsMixMode = computed(() => {
77   - return unref(getMenuMode) === MenuModeEnum.INLINE && unref(getMenuType) === MenuTypeEnum.MIX;
78   -});
  90 + const getIsMixMode = computed(() => {
  91 + return unref(getMenuMode) === MenuModeEnum.INLINE && unref(getMenuType) === MenuTypeEnum.MIX;
  92 + });
79 93  
80   -const getRealWidth = computed(() => {
81   - if (unref(getIsMixSidebar)) {
82   - return unref(getCollapsed) && !unref(getMixSideFixed)
83   - ? unref(getMiniWidthNumber)
84   - : unref(getMenuWidth);
85   - }
86   - return unref(getCollapsed) ? unref(getMiniWidthNumber) : unref(getMenuWidth);
87   -});
88   -
89   -const getMiniWidthNumber = computed(() => {
90   - const { collapsedShowTitle } = unref(getMenuSetting);
91   - return collapsedShowTitle ? SIDE_BAR_SHOW_TIT_MINI_WIDTH : SIDE_BAR_MINI_WIDTH;
92   -});
93   -
94   -const getCalcContentWidth = computed(() => {
95   - const width =
96   - unref(getIsTopMenu) || !unref(getShowMenu) || (unref(getSplit) && unref(getMenuHidden))
97   - ? 0
98   - : unref(getIsMixSidebar)
99   - ? (unref(getCollapsed) ? SIDE_BAR_MINI_WIDTH : SIDE_BAR_SHOW_TIT_MINI_WIDTH) +
100   - (unref(getMixSideFixed) && unref(mixSideHasChildren) ? unref(getRealWidth) : 0)
101   - : unref(getRealWidth);
102   -
103   - return `calc(100% - ${unref(width)}px)`;
104   -});
105   -
106   -const { getFullContent: fullContent } = useFullContent();
107   -
108   -const getShowSidebar = computed(() => {
109   - return (
110   - unref(getSplit) ||
111   - (unref(getShowMenu) && unref(getMenuMode) !== MenuModeEnum.HORIZONTAL && !unref(fullContent))
112   - );
113   -});
  94 + const getRealWidth = computed(() => {
  95 + if (unref(getIsMixSidebar)) {
  96 + return unref(getCollapsed) && !unref(getMixSideFixed)
  97 + ? unref(getMiniWidthNumber)
  98 + : unref(getMenuWidth);
  99 + }
  100 + return unref(getCollapsed) ? unref(getMiniWidthNumber) : unref(getMenuWidth);
  101 + });
114 102  
115   -// Set menu configuration
116   -function setMenuSetting(menuSetting: Partial<MenuSetting>): void {
117   - appStore.commitProjectConfigState({ menuSetting });
118   -}
  103 + const getMiniWidthNumber = computed(() => {
  104 + const { collapsedShowTitle } = appStore.getMenuSetting;
  105 + return collapsedShowTitle ? SIDE_BAR_SHOW_TIT_MINI_WIDTH : SIDE_BAR_MINI_WIDTH;
  106 + });
  107 +
  108 + const getCalcContentWidth = computed(() => {
  109 + const width =
  110 + unref(getIsTopMenu) || !unref(getShowMenu) || (unref(getSplit) && unref(getMenuHidden))
  111 + ? 0
  112 + : unref(getIsMixSidebar)
  113 + ? (unref(getCollapsed) ? SIDE_BAR_MINI_WIDTH : SIDE_BAR_SHOW_TIT_MINI_WIDTH) +
  114 + (unref(getMixSideFixed) && unref(mixSideHasChildren) ? unref(getRealWidth) : 0)
  115 + : unref(getRealWidth);
119 116  
120   -function toggleCollapsed() {
121   - setMenuSetting({
122   - collapsed: !unref(getCollapsed),
  117 + return `calc(100% - ${unref(width)}px)`;
123 118 });
124   -}
125 119  
126   -export function useMenuSetting() {
  120 + // Set menu configuration
  121 + function setMenuSetting(menuSetting: Partial<MenuSetting>): void {
  122 + appStore.setProjectConfig({ menuSetting });
  123 + }
  124 +
  125 + function toggleCollapsed() {
  126 + setMenuSetting({
  127 + collapsed: !unref(getCollapsed),
  128 + });
  129 + }
127 130 return {
128 131 setMenuSetting,
129 132  
130 133 toggleCollapsed,
131 134  
132 135 getMenuFixed,
133   - getMenuSetting,
134 136 getRealWidth,
135 137 getMenuType,
136 138 getMenuMode,
... ...
src/hooks/setting/useMultipleTabSetting.ts
1 1 import type { MultiTabsSetting } from '/#/config';
2 2  
3   -import { computed, unref } from 'vue';
  3 +import { computed } from 'vue';
4 4  
5   -import { appStore } from '/@/store/modules/app';
  5 +import { useAppStore } from '/@/store/modules/app';
6 6  
7   -const getMultipleTabSetting = computed(() => appStore.getProjectConfig.multiTabsSetting);
8   -
9   -const getShowMultipleTab = computed(() => unref(getMultipleTabSetting).show);
  7 +export function useMultipleTabSetting() {
  8 + const appStore = useAppStore();
10 9  
11   -const getShowQuick = computed(() => unref(getMultipleTabSetting).showQuick);
  10 + const getShowMultipleTab = computed(() => appStore.getMultiTabsSetting.show);
12 11  
13   -const getShowRedo = computed(() => unref(getMultipleTabSetting).showRedo);
  12 + const getShowQuick = computed(() => appStore.getMultiTabsSetting.showQuick);
14 13  
15   -const getShowFold = computed(() => unref(getMultipleTabSetting).showFold);
  14 + const getShowRedo = computed(() => appStore.getMultiTabsSetting.showRedo);
16 15  
17   -function setMultipleTabSetting(multiTabsSetting: Partial<MultiTabsSetting>) {
18   - appStore.commitProjectConfigState({ multiTabsSetting });
19   -}
  16 + const getShowFold = computed(() => appStore.getMultiTabsSetting.showFold);
20 17  
21   -export function useMultipleTabSetting() {
  18 + function setMultipleTabSetting(multiTabsSetting: Partial<MultiTabsSetting>) {
  19 + appStore.setProjectConfig({ multiTabsSetting });
  20 + }
22 21 return {
23 22 setMultipleTabSetting,
24   -
25   - getMultipleTabSetting,
26 23 getShowMultipleTab,
27 24 getShowQuick,
28 25 getShowRedo,
... ...
src/hooks/setting/useRootSetting.ts
1 1 import type { ProjectConfig } from '/#/config';
2 2  
3   -import { computed, unref } from 'vue';
  3 +import { computed } from 'vue';
4 4  
5   -import { appStore } from '/@/store/modules/app';
6   -import { ContentEnum } from '/@/enums/appEnum';
7   -import { ThemeEnum } from '../../enums/appEnum';
  5 +import { useAppStore } from '/@/store/modules/app';
  6 +import { ContentEnum, ThemeEnum } from '/@/enums/appEnum';
8 7  
9 8 type RootSetting = Omit<
10 9 ProjectConfig,
11 10 'locale' | 'headerSetting' | 'menuSetting' | 'multiTabsSetting'
12 11 >;
13 12  
14   -const getRootSetting = computed((): RootSetting => appStore.getProjectConfig);
  13 +export function useRootSetting() {
  14 + const appStore = useAppStore();
15 15  
16   -const getPageLoading = computed(() => appStore.getPageLoading);
  16 + const getPageLoading = computed(() => appStore.getPageLoading);
17 17  
18   -const getOpenKeepAlive = computed(() => unref(getRootSetting).openKeepAlive);
  18 + const getOpenKeepAlive = computed(() => appStore.getProjectConfig.openKeepAlive);
19 19  
20   -const getSettingButtonPosition = computed(() => unref(getRootSetting).settingButtonPosition);
  20 + const getSettingButtonPosition = computed(() => appStore.getProjectConfig.settingButtonPosition);
21 21  
22   -const getCanEmbedIFramePage = computed(() => unref(getRootSetting).canEmbedIFramePage);
  22 + const getCanEmbedIFramePage = computed(() => appStore.getProjectConfig.canEmbedIFramePage);
23 23  
24   -const getPermissionMode = computed(() => unref(getRootSetting).permissionMode);
  24 + const getPermissionMode = computed(() => appStore.getProjectConfig.permissionMode);
25 25  
26   -const getShowLogo = computed(() => unref(getRootSetting).showLogo);
  26 + const getShowLogo = computed(() => appStore.getProjectConfig.showLogo);
27 27  
28   -const getContentMode = computed(() => unref(getRootSetting).contentMode);
  28 + const getContentMode = computed(() => appStore.getProjectConfig.contentMode);
29 29  
30   -const getUseOpenBackTop = computed(() => unref(getRootSetting).useOpenBackTop);
  30 + const getUseOpenBackTop = computed(() => appStore.getProjectConfig.useOpenBackTop);
31 31  
32   -const getShowSettingButton = computed(() => unref(getRootSetting).showSettingButton);
  32 + const getShowSettingButton = computed(() => appStore.getProjectConfig.showSettingButton);
33 33  
34   -const getUseErrorHandle = computed(() => unref(getRootSetting).useErrorHandle);
  34 + const getUseErrorHandle = computed(() => appStore.getProjectConfig.useErrorHandle);
35 35  
36   -const getShowFooter = computed(() => unref(getRootSetting).showFooter);
  36 + const getShowFooter = computed(() => appStore.getProjectConfig.showFooter);
37 37  
38   -const getShowBreadCrumb = computed(() => unref(getRootSetting).showBreadCrumb);
  38 + const getShowBreadCrumb = computed(() => appStore.getProjectConfig.showBreadCrumb);
39 39  
40   -const getThemeColor = computed(() => unref(getRootSetting).themeColor);
  40 + const getThemeColor = computed(() => appStore.getProjectConfig.themeColor);
41 41  
42   -const getShowBreadCrumbIcon = computed(() => unref(getRootSetting).showBreadCrumbIcon);
  42 + const getShowBreadCrumbIcon = computed(() => appStore.getProjectConfig.showBreadCrumbIcon);
43 43  
44   -const getFullContent = computed(() => unref(getRootSetting).fullContent);
  44 + const getFullContent = computed(() => appStore.getProjectConfig.fullContent);
45 45  
46   -const getColorWeak = computed(() => unref(getRootSetting).colorWeak);
  46 + const getColorWeak = computed(() => appStore.getProjectConfig.colorWeak);
47 47  
48   -const getGrayMode = computed(() => unref(getRootSetting).grayMode);
  48 + const getGrayMode = computed(() => appStore.getProjectConfig.grayMode);
49 49  
50   -const getLockTime = computed(() => unref(getRootSetting).lockTime);
  50 + const getLockTime = computed(() => appStore.getProjectConfig.lockTime);
51 51  
52   -const getShowDarkModeToggle = computed(() => unref(getRootSetting).showDarkModeToggle);
  52 + const getShowDarkModeToggle = computed(() => appStore.getProjectConfig.showDarkModeToggle);
53 53  
54   -const getDarkMode = computed(() => appStore.getDarkMode);
  54 + const getDarkMode = computed(() => appStore.getDarkMode);
55 55  
56   -const getLayoutContentMode = computed(() =>
57   - unref(getRootSetting).contentMode === ContentEnum.FULL ? ContentEnum.FULL : ContentEnum.FIXED
58   -);
  56 + const getLayoutContentMode = computed(() =>
  57 + appStore.getProjectConfig.contentMode === ContentEnum.FULL
  58 + ? ContentEnum.FULL
  59 + : ContentEnum.FIXED
  60 + );
59 61  
60   -function setRootSetting(setting: Partial<RootSetting>) {
61   - appStore.commitProjectConfigState(setting);
62   -}
  62 + function setRootSetting(setting: Partial<RootSetting>) {
  63 + appStore.setProjectConfig(setting);
  64 + }
63 65  
64   -function setDarkMode(mode: ThemeEnum) {
65   - appStore.commitDarkMode(mode);
66   -}
67   -
68   -export function useRootSetting() {
  66 + function setDarkMode(mode: ThemeEnum) {
  67 + appStore.setDarkMode(mode);
  68 + }
69 69 return {
70 70 setRootSetting,
71 71  
... ... @@ -73,7 +73,6 @@ export function useRootSetting() {
73 73 getFullContent,
74 74 getColorWeak,
75 75 getGrayMode,
76   - getRootSetting,
77 76 getLayoutContentMode,
78 77 getPageLoading,
79 78 getOpenKeepAlive,
... ...
src/hooks/setting/useTransitionSetting.ts
1 1 import type { TransitionSetting } from '/#/config';
2 2  
3   -import { computed, unref } from 'vue';
  3 +import { computed } from 'vue';
4 4  
5   -import { appStore } from '/@/store/modules/app';
  5 +import { useAppStore } from '/@/store/modules/app';
6 6  
7   -const getTransitionSetting = computed(() => appStore.getProjectConfig.transitionSetting);
8   -
9   -const getEnableTransition = computed(() => unref(getTransitionSetting)?.enable);
  7 +export function useTransitionSetting() {
  8 + const appStore = useAppStore();
10 9  
11   -const getOpenNProgress = computed(() => unref(getTransitionSetting)?.openNProgress);
  10 + const getEnableTransition = computed(() => appStore.getTransitionSetting?.enable);
12 11  
13   -const getOpenPageLoading = computed((): boolean => {
14   - return !!unref(getTransitionSetting)?.openPageLoading;
15   -});
  12 + const getOpenNProgress = computed(() => appStore.getTransitionSetting?.openNProgress);
16 13  
17   -const getBasicTransition = computed(() => unref(getTransitionSetting)?.basicTransition);
  14 + const getOpenPageLoading = computed((): boolean => {
  15 + return !!appStore.getTransitionSetting?.openPageLoading;
  16 + });
18 17  
19   -function setTransitionSetting(transitionSetting: Partial<TransitionSetting>) {
20   - appStore.commitProjectConfigState({ transitionSetting });
21   -}
  18 + const getBasicTransition = computed(() => appStore.getTransitionSetting?.basicTransition);
22 19  
23   -export function useTransitionSetting() {
  20 + function setTransitionSetting(transitionSetting: Partial<TransitionSetting>) {
  21 + appStore.setProjectConfig({ transitionSetting });
  22 + }
24 23 return {
25 24 setTransitionSetting,
26 25  
27   - getTransitionSetting,
28 26 getEnableTransition,
29 27 getOpenNProgress,
30 28 getOpenPageLoading,
... ...
src/plugins/echarts/index.ts renamed to src/hooks/web/useEcharts/echarts.ts
src/hooks/web/useECharts.ts renamed to src/hooks/web/useEcharts/index.ts
  1 +import type { EChartsOption } from 'echarts';
  2 +import type { Ref } from 'vue';
  3 +
1 4 import { useTimeoutFn } from '/@/hooks/core/useTimeout';
2 5 import { tryOnUnmounted } from '@vueuse/core';
3   -import { unref, Ref, nextTick, watch, computed, ref } from 'vue';
4   -import type { EChartsOption } from 'echarts';
  6 +import { unref, nextTick, watch, computed, ref } from 'vue';
5 7 import { useDebounce } from '/@/hooks/core/useDebounce';
6 8 import { useEventListener } from '/@/hooks/event/useEventListener';
7 9 import { useBreakpoint } from '/@/hooks/event/useBreakpoint';
8 10  
9   -import echarts from '/@/plugins/echarts';
10   -import { useRootSetting } from '../setting/useRootSetting';
  11 +import echarts from './echarts';
  12 +import { useRootSetting } from '/@/hooks/setting/useRootSetting';
11 13  
12 14 export function useECharts(
13 15 elRef: Ref<HTMLDivElement>,
... ...
src/hooks/web/useFullContent.ts
1 1 import { computed, unref } from 'vue';
2 2  
3   -import { appStore } from '/@/store/modules/app';
  3 +import { useAppStore } from '/@/store/modules/app';
4 4  
5 5 import router from '/@/router';
6 6  
... ... @@ -8,6 +8,7 @@ import router from &#39;/@/router&#39;;
8 8 * @description: Full screen display content
9 9 */
10 10 export const useFullContent = () => {
  11 + const appStore = useAppStore();
11 12 const { currentRoute } = router;
12 13  
13 14 // Whether to display the content in full screen without displaying the menu
... ...
src/hooks/web/useLockPage.ts
1 1 import { computed, onUnmounted, unref, watchEffect } from 'vue';
2 2 import { useThrottle } from '/@/hooks/core/useThrottle';
3 3  
4   -import { appStore } from '/@/store/modules/app';
5   -import { lockStore } from '/@/store/modules/lock';
6   -import { userStore } from '/@/store/modules/user';
  4 +import { useAppStore } from '/@/store/modules/app';
  5 +import { useLockStore } from '/@/store/modules/lock';
  6 +
  7 +import { useUserStore } from '/@/store/modules/user';
7 8 import { useRootSetting } from '../setting/useRootSetting';
8 9  
9 10 export function useLockPage() {
10 11 const { getLockTime } = useRootSetting();
  12 + const lockStore = useLockStore();
  13 + const userStore = useUserStore();
  14 + const appStore = useAppStore();
  15 +
11 16 let timeId: TimeoutHandle;
12 17  
13 18 function clear(): void {
... ... @@ -16,7 +21,7 @@ export function useLockPage() {
16 21  
17 22 function resetCalcLockTimeout(): void {
18 23 // not login
19   - if (!userStore.getTokenState) {
  24 + if (!userStore.getToken) {
20 25 clear();
21 26 return;
22 27 }
... ... @@ -33,14 +38,14 @@ export function useLockPage() {
33 38 }
34 39  
35 40 function lockPage(): void {
36   - lockStore.commitLockInfoState({
  41 + lockStore.setLockInfo({
37 42 isLock: true,
38 43 pwd: undefined,
39 44 });
40 45 }
41 46  
42 47 watchEffect((onClean) => {
43   - if (userStore.getTokenState) {
  48 + if (userStore.getToken) {
44 49 resetCalcLockTimeout();
45 50 } else {
46 51 clear();
... ...
src/hooks/web/usePage.ts
1   -import type { RouteLocationRaw } from 'vue-router';
  1 +import type { RouteLocationRaw, Router } from 'vue-router';
2 2  
3 3 import { PageEnum } from '/@/enums/pageEnum';
4 4 import { isString } from '/@/utils/is';
5 5 import { unref } from 'vue';
6 6  
7   -import router from '/@/router';
  7 +import { useRouter } from 'vue-router';
8 8  
9 9 export type RouteLocationRawEx = Omit<RouteLocationRaw, 'path'> & { path: PageEnum };
10 10  
... ... @@ -13,10 +13,16 @@ function handleError(e: Error) {
13 13 }
14 14  
15 15 // page switch
16   -export function useGo() {
17   - const { push, replace } = router;
  16 +export function useGo(_router?: Router) {
  17 + let router;
  18 + if (!_router) {
  19 + router = useRouter();
  20 + }
  21 + const { push, replace } = _router || router;
18 22 function go(opt: PageEnum | RouteLocationRawEx | string = PageEnum.BASE_HOME, isReplace = false) {
19   - if (!opt) return;
  23 + if (!opt) {
  24 + return;
  25 + }
20 26 if (isString(opt)) {
21 27 isReplace ? replace(opt).catch(handleError) : push(opt).catch(handleError);
22 28 } else {
... ... @@ -30,8 +36,12 @@ export function useGo() {
30 36 /**
31 37 * @description: redo current page
32 38 */
33   -export const useRedo = () => {
34   - const { push, currentRoute } = router;
  39 +export const useRedo = (_router?: Router) => {
  40 + let router;
  41 + if (!_router) {
  42 + router = useRouter();
  43 + }
  44 + const { push, currentRoute } = _router || router;
35 45 const { query, params } = currentRoute.value;
36 46 function redo(): Promise<boolean> {
37 47 return new Promise((resolve) => {
... ...
src/hooks/web/usePermission.ts
1 1 import type { RouteRecordRaw } from 'vue-router';
2 2  
3   -import { appStore } from '/@/store/modules/app';
4   -import { permissionStore } from '/@/store/modules/permission';
5   -import { userStore } from '/@/store/modules/user';
  3 +import { useAppStore } from '/@/store/modules/app';
  4 +import { usePermissionStore } from '/@/store/modules/permission';
  5 +import { useUserStore } from '/@/store/modules/user';
6 6  
7 7 import { useTabs } from './useTabs';
8 8  
... ... @@ -15,15 +15,20 @@ import { RoleEnum } from &#39;/@/enums/roleEnum&#39;;
15 15  
16 16 import { intersection } from 'lodash-es';
17 17 import { isArray } from '/@/utils/is';
18   -import { tabStore } from '/@/store/modules/tab';
  18 +import { useMultipleTabStore } from '/@/store/modules/multipleTab';
19 19  
20 20 // User permissions related operations
21 21 export function usePermission() {
  22 + const userStore = useUserStore();
  23 + const appStore = useAppStore();
  24 + const permissionStore = usePermissionStore();
  25 + const { closeAll } = useTabs(router);
  26 +
22 27 /**
23 28 * Change permission mode
24 29 */
25 30 async function togglePermissionMode() {
26   - appStore.commitProjectConfigState({
  31 + appStore.setProjectConfig({
27 32 permissionMode:
28 33 projectSetting.permissionMode === PermissionModeEnum.BACK
29 34 ? PermissionModeEnum.ROLE
... ... @@ -37,14 +42,14 @@ export function usePermission() {
37 42 * @param id
38 43 */
39 44 async function resume(id?: string | number) {
40   - tabStore.commitClearCache();
  45 + const tabStore = useMultipleTabStore();
  46 + tabStore.clearCacheTabs();
41 47 resetRouter();
42 48 const routes = await permissionStore.buildRoutesAction(id);
43 49 routes.forEach((route) => {
44 50 router.addRoute((route as unknown) as RouteRecordRaw);
45 51 });
46   - permissionStore.commitLastBuildMenuTimeState();
47   - const { closeAll } = useTabs();
  52 + permissionStore.setLastBuildMenuTime();
48 53 closeAll();
49 54 }
50 55  
... ... @@ -53,22 +58,24 @@ export function usePermission() {
53 58 */
54 59 function hasPermission(value?: RoleEnum | RoleEnum[] | string | string[], def = true): boolean {
55 60 const permMode = projectSetting.permissionMode;
  61 +
56 62 if (PermissionModeEnum.ROLE === permMode) {
57 63 // Visible by default
58 64 if (!value) {
59 65 return def;
60 66 }
61 67 if (!isArray(value)) {
62   - return userStore.getRoleListState?.includes(value as RoleEnum);
  68 + return userStore.getRoleList?.includes(value as RoleEnum);
63 69 }
64   - return (intersection(value, userStore.getRoleListState) as RoleEnum[]).length > 0;
  70 + return (intersection(value, userStore.getRoleList) as RoleEnum[]).length > 0;
65 71 }
  72 +
66 73 if (PermissionModeEnum.BACK === permMode) {
67 74 // Visible by default
68 75 if (!value) {
69 76 return def;
70 77 }
71   - const allCodeList = permissionStore.getPermCodeListState;
  78 + const allCodeList = permissionStore.getPermCodeList;
72 79 if (!isArray(value)) {
73 80 return allCodeList.includes(value as string);
74 81 }
... ... @@ -90,7 +97,7 @@ export function usePermission() {
90 97 if (!isArray(roles)) {
91 98 roles = [roles];
92 99 }
93   - userStore.commitRoleListState(roles);
  100 + userStore.setRoleList(roles);
94 101 await resume();
95 102 }
96 103  
... ...
src/hooks/web/useTabs.ts
1   -import { tabStore } from '/@/store/modules/tab';
2   -import { appStore } from '/@/store/modules/app';
3   -import type { RouteLocationNormalized } from 'vue-router';
  1 +import type { RouteLocationNormalized, Router } from 'vue-router';
4 2  
5   -export function useTabs() {
6   - function canIUseFn(): boolean {
7   - const { multiTabsSetting: { show } = {} } = appStore.getProjectConfig;
  3 +import { useRouter } from 'vue-router';
  4 +import { unref } from 'vue';
  5 +
  6 +import { useMultipleTabStore } from '/@/store/modules/multipleTab';
  7 +import { useAppStore } from '/@/store/modules/app';
  8 +
  9 +enum TableActionEnum {
  10 + REFRESH,
  11 + CLOSE_ALL,
  12 + CLOSE_LEFT,
  13 + CLOSE_RIGHT,
  14 + CLOSE_OTHER,
  15 + CLOSE_CURRENT,
  16 + CLOSE,
  17 +}
  18 +
  19 +export function useTabs(_router: Router) {
  20 + const appStore = useAppStore();
  21 +
  22 + function canIUseTabs(): boolean {
  23 + const { show } = appStore.getMultiTabsSetting;
8 24 if (!show) {
9 25 throw new Error('The multi-tab page is currently not open, please open it in the settings๏ผ');
10 26 }
11 27 return !!show;
12 28 }
13 29  
  30 + const tabStore = useMultipleTabStore();
  31 + const router = _router || useRouter();
  32 +
  33 + const { currentRoute } = router;
  34 +
  35 + function getCurrentTab() {
  36 + const route = unref(currentRoute);
  37 + return tabStore.getTabList.find((item) => item.path === route.path)!;
  38 + }
  39 +
  40 + async function handleTabAction(action: TableActionEnum, tab?: RouteLocationNormalized) {
  41 + const canIUse = canIUseTabs;
  42 + if (!canIUse) {
  43 + return;
  44 + }
  45 + const currentTab = getCurrentTab();
  46 + switch (action) {
  47 + case TableActionEnum.REFRESH:
  48 + await tabStore.refreshPage(router);
  49 + break;
  50 +
  51 + case TableActionEnum.CLOSE_ALL:
  52 + await tabStore.closeAllTab(router);
  53 + break;
  54 +
  55 + case TableActionEnum.CLOSE_LEFT:
  56 + await tabStore.closeLeftTabs(currentTab, router);
  57 + break;
  58 +
  59 + case TableActionEnum.CLOSE_RIGHT:
  60 + await tabStore.closeRightTabs(currentTab, router);
  61 + break;
  62 +
  63 + case TableActionEnum.CLOSE_OTHER:
  64 + await tabStore.closeOtherTabs(currentTab, router);
  65 + break;
  66 +
  67 + case TableActionEnum.CLOSE_CURRENT:
  68 + case TableActionEnum.CLOSE:
  69 + await tabStore.closeTab(tab || currentTab, router);
  70 + break;
  71 + }
  72 + }
  73 +
14 74 return {
15   - refreshPage: async () => {
16   - if (canIUseFn()) {
17   - await tabStore.commitRedoPage();
18   - }
  75 + refreshPage: () => handleTabAction(TableActionEnum.REFRESH),
  76 + closeAll: () => handleTabAction(TableActionEnum.CLOSE_ALL),
  77 + closeLeft: () => handleTabAction(TableActionEnum.CLOSE_LEFT),
  78 + closeRight: () => handleTabAction(TableActionEnum.CLOSE_RIGHT),
  79 + closeOther: () => handleTabAction(TableActionEnum.CLOSE_OTHER),
  80 + closeCurrent: () => handleTabAction(TableActionEnum.CLOSE_CURRENT),
  81 + close: (tab?: RouteLocationNormalized) => {
  82 + handleTabAction(TableActionEnum.CLOSE, tab);
19 83 },
20   - closeAll: () => canIUseFn() && tabStore.closeAllTabAction(),
21   - closeLeft: () => canIUseFn() && tabStore.closeLeftTabAction(tabStore.getCurrentTab),
22   - closeRight: () => canIUseFn() && tabStore.closeRightTabAction(tabStore.getCurrentTab),
23   - closeOther: () => canIUseFn() && tabStore.closeOtherTabAction(tabStore.getCurrentTab),
24   - closeCurrent: () => canIUseFn() && tabStore.closeTabAction(tabStore.getCurrentTab),
25   - close: (tab?: RouteLocationNormalized) =>
26   - canIUseFn() && tabStore.closeTabAction(tab || tabStore.getCurrentTab),
27 84 };
28 85 }
... ...
src/layouts/default/header/components/ErrorAction.vue
... ... @@ -5,7 +5,7 @@
5 5 :mouseEnterDelay="0.5"
6 6 @click="handleToErrorList"
7 7 >
8   - <Badge :count="getCount" :offset="[0, 10]" dot :overflowCount="99">
  8 + <Badge :count="getCount" :offset="[0, 10]" :overflowCount="99">
9 9 <Icon icon="ion:bug-outline" />
10 10 </Badge>
11 11 </Tooltip>
... ... @@ -16,7 +16,7 @@
16 16 import Icon from '/@/components/Icon';
17 17  
18 18 import { useI18n } from '/@/hooks/web/useI18n';
19   - import { errorStore } from '/@/store/modules/error';
  19 + import { useErrorLogStore } from '/@/store/modules/errorLog';
20 20 import { PageEnum } from '/@/enums/pageEnum';
21 21  
22 22 import { useRouter } from 'vue-router';
... ... @@ -28,14 +28,13 @@
28 28 setup() {
29 29 const { t } = useI18n();
30 30 const { push } = useRouter();
  31 + const errorLogStore = useErrorLogStore();
31 32  
32   - const getCount = computed(() => {
33   - return errorStore.getErrorListCountState;
34   - });
  33 + const getCount = computed(() => errorLogStore.getErrorLogListCount);
35 34  
36 35 function handleToErrorList() {
37 36 push(PageEnum.ERROR_LOG_PAGE).then(() => {
38   - errorStore.commitErrorListCountState(0);
  37 + errorLogStore.setErrorLogListCount(0);
39 38 });
40 39 }
41 40  
... ...
src/layouts/default/header/components/lock/LockModal.vue
... ... @@ -31,8 +31,8 @@
31 31 import { BasicModal, useModalInner } from '/@/components/Modal/index';
32 32 import { BasicForm, useForm } from '/@/components/Form/index';
33 33  
34   - import { userStore } from '/@/store/modules/user';
35   - import { lockStore } from '/@/store/modules/lock';
  34 + import { useUserStore } from '/@/store/modules/user';
  35 + import { useLockStore } from '/@/store/modules/lock';
36 36 import headerImg from '/@/assets/images/header.jpg';
37 37 export default defineComponent({
38 38 name: 'LockModal',
... ... @@ -41,10 +41,10 @@
41 41 setup() {
42 42 const { t } = useI18n();
43 43 const { prefixCls } = useDesign('header-lock-modal');
  44 + const userStore = useUserStore();
  45 + const lockStore = useLockStore();
44 46  
45   - const getRealName = computed(() => {
46   - return userStore.getUserInfoState?.realName;
47   - });
  47 + const getRealName = computed(() => userStore.getUserInfo?.realName);
48 48 const [register, { closeModal }] = useModalInner();
49 49  
50 50 const [registerForm, { validateFields, resetFields }] = useForm({
... ... @@ -64,7 +64,7 @@
64 64 const password: string | undefined = values.password;
65 65 closeModal();
66 66  
67   - lockStore.commitLockInfoState({
  67 + lockStore.setLockInfo({
68 68 isLock: true,
69 69 pwd: password,
70 70 });
... ...
src/layouts/default/header/components/user-dropdown/index.vue
... ... @@ -41,7 +41,7 @@
41 41  
42 42 import { DOC_URL } from '/@/settings/siteSetting';
43 43  
44   - import { userStore } from '/@/store/modules/user';
  44 + import { useUserStore } from '/@/store/modules/user';
45 45 import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
46 46 import { useI18n } from '/@/hooks/web/useI18n';
47 47 import { useDesign } from '/@/hooks/web/useDesign';
... ... @@ -71,9 +71,10 @@
71 71 const { prefixCls } = useDesign('header-user-dropdown');
72 72 const { t } = useI18n();
73 73 const { getShowDoc } = useHeaderSetting();
  74 + const userStore = useUserStore();
74 75  
75 76 const getUserInfo = computed(() => {
76   - const { realName = '', desc } = userStore.getUserInfoState || {};
  77 + const { realName = '', desc } = userStore.getUserInfo || {};
77 78 return { realName, desc };
78 79 });
79 80  
... ...
src/layouts/default/index.vue
... ... @@ -42,13 +42,9 @@
42 42 },
43 43 setup() {
44 44 const { prefixCls } = useDesign('default-layout');
45   -
46 45 const { getIsMobile } = useAppInject();
47   -
48 46 const { getShowFullHeaderRef } = useHeaderSetting();
49   -
50 47 const { getShowSidebar, getIsMixSidebar } = useMenuSetting();
51   -
52 48 const layoutClass = computed(() => ({ 'ant-layout-has-sider': unref(getIsMixSidebar) }));
53 49  
54 50 return {
... ...
src/layouts/default/menu/useLayoutMenu.ts
... ... @@ -9,7 +9,7 @@ import { useThrottle } from &#39;/@/hooks/core/useThrottle&#39;;
9 9 import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
10 10  
11 11 import { getChildrenMenus, getCurrentParentPath, getMenus, getShallowMenus } from '/@/router/menus';
12   -import { permissionStore } from '/@/store/modules/permission';
  12 +import { usePermissionStore } from '/@/store/modules/permission';
13 13 import { useAppInject } from '/@/hooks/web/useAppInject';
14 14  
15 15 export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
... ... @@ -17,6 +17,7 @@ export function useSplitMenu(splitType: Ref&lt;MenuSplitTyeEnum&gt;) {
17 17 const menusRef = ref<Menu[]>([]);
18 18 const { currentRoute } = useRouter();
19 19 const { getIsMobile } = useAppInject();
  20 + const permissionStore = usePermissionStore();
20 21 const { setMenuSetting, getIsHorizontal, getSplit } = useMenuSetting();
21 22  
22 23 const [throttleHandleSplitLeftMenu] = useThrottle(handleSplitLeftMenu, 50);
... ... @@ -55,7 +56,7 @@ export function useSplitMenu(splitType: Ref&lt;MenuSplitTyeEnum&gt;) {
55 56  
56 57 // Menu changes
57 58 watch(
58   - [() => permissionStore.getLastBuildMenuTimeState, () => permissionStore.getBackMenuListState],
  59 + [() => permissionStore.getLastBuildMenuTime, () => permissionStore.getBackMenuList],
59 60 () => {
60 61 genMenus();
61 62 },
... ...
src/layouts/default/setting/components/SettingFooter.vue
... ... @@ -21,32 +21,36 @@
21 21  
22 22 import { CopyOutlined, RedoOutlined } from '@ant-design/icons-vue';
23 23  
24   - import { appStore } from '/@/store/modules/app';
25   - import { permissionStore } from '/@/store/modules/permission';
26   - import { tabStore } from '/@/store/modules/tab';
27   - import { userStore } from '/@/store/modules/user';
  24 + import { useAppStore } from '/@/store/modules/app';
  25 + import { usePermissionStore } from '/@/store/modules/permission';
  26 + import { useMultipleTabStore } from '/@/store/modules/multipleTab';
  27 + import { useUserStore } from '/@/store/modules/user';
28 28  
29 29 import { useDesign } from '/@/hooks/web/useDesign';
30 30 import { useI18n } from '/@/hooks/web/useI18n';
31 31 import { useMessage } from '/@/hooks/web/useMessage';
32 32 import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
33   - import { useRootSetting } from '/@/hooks/setting/useRootSetting';
34 33  
35 34 import { updateColorWeak } from '/@/logics/theme/updateColorWeak';
36 35 import { updateGrayMode } from '/@/logics/theme/updateGrayMode';
37   -
38 36 import defaultSetting from '/@/settings/projectSetting';
  37 +
39 38 export default defineComponent({
40 39 name: 'SettingFooter',
41 40 components: { CopyOutlined, RedoOutlined },
42 41 setup() {
43   - const { getRootSetting } = useRootSetting();
  42 + const permissionStore = usePermissionStore();
44 43 const { prefixCls } = useDesign('setting-footer');
45 44 const { t } = useI18n();
46 45 const { createSuccessModal, createMessage } = useMessage();
  46 + const tabStore = useMultipleTabStore();
  47 + const userStore = useUserStore();
  48 + const appStore = useAppStore();
47 49  
48 50 function handleCopy() {
49   - const { isSuccessRef } = useCopyToClipboard(JSON.stringify(unref(getRootSetting), null, 2));
  51 + const { isSuccessRef } = useCopyToClipboard(
  52 + JSON.stringify(unref(appStore.getProjectConfig), null, 2)
  53 + );
50 54 unref(isSuccessRef) &&
51 55 createSuccessModal({
52 56 title: t('layout.setting.operatingTitle'),
... ... @@ -55,7 +59,7 @@
55 59 }
56 60 function handleResetSetting() {
57 61 try {
58   - appStore.commitProjectConfigState(defaultSetting);
  62 + appStore.setProjectConfig(defaultSetting);
59 63 const { colorWeak, grayMode } = defaultSetting;
60 64 // updateTheme(themeColor);
61 65 updateColorWeak(colorWeak);
... ... @@ -68,10 +72,10 @@
68 72  
69 73 function handleClearAndRedo() {
70 74 localStorage.clear();
71   - appStore.resumeAllState();
72   - permissionStore.commitResetState();
73   - tabStore.commitResetState();
74   - userStore.commitResetState();
  75 + appStore.resetAllState();
  76 + permissionStore.resetState();
  77 + tabStore.resetState();
  78 + userStore.resetState();
75 79 location.reload();
76 80 }
77 81 return {
... ...
src/layouts/default/setting/handler.ts
... ... @@ -3,15 +3,16 @@ import { updateHeaderBgColor, updateSidebarBgColor } from &#39;/@/logics/theme/updat
3 3 import { updateColorWeak } from '/@/logics/theme/updateColorWeak';
4 4 import { updateGrayMode } from '/@/logics/theme/updateGrayMode';
5 5  
6   -import { appStore } from '/@/store/modules/app';
  6 +import { useAppStore } from '/@/store/modules/app';
7 7 import { ProjectConfig } from '/#/config';
8 8 import { changeTheme } from '/@/logics/theme';
9 9 import { updateDarkTheme } from '/@/logics/theme/dark';
10 10 import { useRootSetting } from '/@/hooks/setting/useRootSetting';
11 11  
12 12 export function baseHandler(event: HandlerEnum, value: any) {
  13 + const appStore = useAppStore();
13 14 const config = handler(event, value);
14   - appStore.commitProjectConfigState(config);
  15 + appStore.setProjectConfig(config);
15 16 if (event === HandlerEnum.CHANGE_THEME) {
16 17 updateHeaderBgColor();
17 18 updateSidebarBgColor();
... ... @@ -19,6 +20,8 @@ export function baseHandler(event: HandlerEnum, value: any) {
19 20 }
20 21  
21 22 export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConfig> {
  23 + const appStore = useAppStore();
  24 +
22 25 const { getThemeColor, getDarkMode } = useRootSetting();
23 26 switch (event) {
24 27 case HandlerEnum.CHANGE_LAYOUT:
... ... @@ -50,7 +53,7 @@ export function handler(event: HandlerEnum, value: any): DeepPartial&lt;ProjectConf
50 53 }
51 54 updateDarkTheme(value);
52 55  
53   - return { darkMode: value };
  56 + return {};
54 57  
55 58 case HandlerEnum.MENU_HAS_DRAG:
56 59 return { menuSetting: { canDrag: value } };
... ... @@ -97,7 +100,7 @@ export function handler(event: HandlerEnum, value: any): DeepPartial&lt;ProjectConf
97 100  
98 101 // ============transition==================
99 102 case HandlerEnum.OPEN_PAGE_LOADING:
100   - appStore.commitPageLoadingState(false);
  103 + appStore.setPageLoading(false);
101 104 return { transitionSetting: { openPageLoading: value } };
102 105  
103 106 case HandlerEnum.ROUTER_TRANSITION:
... ...
src/layouts/default/tabs/components/FoldButton.vue
... ... @@ -5,38 +5,33 @@
5 5 </template>
6 6 <script lang="ts">
7 7 import { defineComponent, unref, computed } from 'vue';
  8 + import { Icon } from '/@/components/Icon';
  9 +
8 10 import { useDesign } from '/@/hooks/web/useDesign';
9 11 import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
10 12 import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
11 13  
12   - import Icon from '/@/components/Icon';
13   -
14 14 export default defineComponent({
15 15 name: 'FoldButton',
16 16 components: { Icon },
17   -
18 17 setup() {
19 18 const { prefixCls } = useDesign('multiple-tabs-content');
20 19 const { getShowMenu, setMenuSetting } = useMenuSetting();
21 20 const { getShowHeader, setHeaderSetting } = useHeaderSetting();
22 21  
23   - const getIsUnFold = computed(() => {
24   - return !unref(getShowMenu) && !unref(getShowHeader);
25   - });
  22 + const getIsUnFold = computed(() => !unref(getShowMenu) && !unref(getShowHeader));
26 23  
27   - const getIcon = computed(() => {
28   - return unref(getIsUnFold) ? 'codicon:screen-normal' : 'codicon:screen-full';
29   - });
  24 + const getIcon = computed(() =>
  25 + unref(getIsUnFold) ? 'codicon:screen-normal' : 'codicon:screen-full'
  26 + );
30 27  
31 28 function handleFold() {
32   - const isScale = !unref(getShowMenu) && !unref(getShowHeader);
  29 + const isUnFold = unref(getIsUnFold);
33 30 setMenuSetting({
34   - show: isScale,
35   - hidden: !isScale,
36   - });
37   - setHeaderSetting({
38   - show: isScale,
  31 + show: isUnFold,
  32 + hidden: !isUnFold,
39 33 });
  34 + setHeaderSetting({ show: isUnFold });
40 35 }
41 36  
42 37 return { prefixCls, getIcon, handleFold };
... ...
src/layouts/default/tabs/components/QuickButton.vue deleted 100644 โ†’ 0
1   -<template>
2   - <TabContent :type="TabContentEnum.EXTRA_TYPE" :tabItem="$route" />
3   -</template>
4   -<script lang="ts">
5   - import { defineComponent } from 'vue';
6   -
7   - import { TabContentEnum } from '../types';
8   -
9   - import TabContent from './TabContent.vue';
10   - export default defineComponent({
11   - name: 'QuickButton',
12   - components: {
13   - TabContent,
14   - },
15   - setup() {
16   - return {
17   - TabContentEnum,
18   - };
19   - },
20   - });
21   -</script>
src/layouts/default/tabs/components/TabContent.vue
1 1 <template>
2 2 <Dropdown :dropMenuList="getDropMenuList" :trigger="getTrigger" @menuEvent="handleMenuEvent">
3   - <div :class="`${prefixCls}__info`" @contextmenu="handleContext" v-if="isTabs">
  3 + <div :class="`${prefixCls}__info`" @contextmenu="handleContext" v-if="getIsTabs">
4 4 <span class="ml-1">{{ getTitle }}</span>
5 5 </div>
6   -
7 6 <span :class="`${prefixCls}__extra-quick`" v-else @click="handleContext">
8 7 <Icon icon="ion:chevron-down" />
9 8 </span>
... ... @@ -11,18 +10,18 @@
11 10 </template>
12 11 <script lang="ts">
13 12 import type { PropType } from 'vue';
  13 + import type { RouteLocationNormalized } from 'vue-router';
14 14  
15   - import { defineComponent, computed } from 'vue';
  15 + import { defineComponent, computed, unref } from 'vue';
16 16 import { Dropdown } from '/@/components/Dropdown/index';
17   - import Icon from '/@/components/Icon';
  17 + import { Icon } from '/@/components/Icon';
18 18  
19   - import { TabContentProps, TabContentEnum } from '../types';
  19 + import { TabContentProps } from '../types';
20 20  
21 21 import { useDesign } from '/@/hooks/web/useDesign';
22   - import { useTabDropdown } from '../useTabDropdown';
23 22 import { useI18n } from '/@/hooks/web/useI18n';
  23 + import { useTabDropdown } from '../useTabDropdown';
24 24  
25   - import { RouteLocationNormalized } from 'vue-router';
26 25 export default defineComponent({
27 26 name: 'TabContent',
28 27 components: { Dropdown, Icon },
... ... @@ -31,11 +30,7 @@
31 30 type: Object as PropType<RouteLocationNormalized>,
32 31 default: null,
33 32 },
34   -
35   - type: {
36   - type: Number as PropType<TabContentEnum>,
37   - default: TabContentEnum.TAB_TYPE,
38   - },
  33 + isExtra: Boolean,
39 34 },
40 35 setup(props) {
41 36 const { prefixCls } = useDesign('multiple-tabs-content');
... ... @@ -43,27 +38,29 @@
43 38  
44 39 const getTitle = computed(() => {
45 40 const { tabItem: { meta } = {} } = props;
46   - return meta && t(meta.title);
  41 + return meta && t(meta.title as string);
47 42 });
48 43  
49   - const {
50   - getDropMenuList,
51   - handleMenuEvent,
52   - handleContextMenu,
53   - getTrigger,
54   - isTabs,
55   - } = useTabDropdown(props as TabContentProps);
  44 + const getIsTabs = computed(() => !props.isExtra);
  45 +
  46 + const getTrigger = computed(() => (unref(getIsTabs) ? ['contextmenu'] : ['click']));
56 47  
57   - function handleContext(e: ChangeEvent) {
  48 + const { getDropMenuList, handleMenuEvent, handleContextMenu } = useTabDropdown(
  49 + props as TabContentProps,
  50 + getIsTabs
  51 + );
  52 +
  53 + function handleContext(e) {
58 54 props.tabItem && handleContextMenu(props.tabItem)(e);
59 55 }
  56 +
60 57 return {
61 58 prefixCls,
62 59 getDropMenuList,
63 60 handleMenuEvent,
64 61 handleContext,
65 62 getTrigger,
66   - isTabs,
  63 + getIsTabs,
67 64 getTitle,
68 65 };
69 66 },
... ...
src/layouts/default/tabs/components/TabRedo.vue
1 1 <template>
2   - <Tooltip :title="t('common.redo')" placement="bottom" :mouseEnterDelay="0.5">
3   - <span :class="`${prefixCls}__extra-redo`" @click="handleRedo">
4   - <RedoOutlined :spin="loading" />
5   - </span>
6   - </Tooltip>
  2 + <span :class="`${prefixCls}__extra-redo`" @click="handleRedo">
  3 + <RedoOutlined :spin="loading" />
  4 + </span>
7 5 </template>
8 6 <script lang="ts">
9 7 import { defineComponent, ref } from 'vue';
10 8 import { RedoOutlined } from '@ant-design/icons-vue';
11 9 import { useDesign } from '/@/hooks/web/useDesign';
12   - import { Tooltip } from 'ant-design-vue';
13   - import { useI18n } from '/@/hooks/web/useI18n';
14 10 import { useTabs } from '/@/hooks/web/useTabs';
15 11  
16 12 export default defineComponent({
17 13 name: 'TabRedo',
18   - components: { RedoOutlined, Tooltip },
  14 + components: { RedoOutlined },
19 15  
20 16 setup() {
21 17 const loading = ref(false);
  18 +
22 19 const { prefixCls } = useDesign('multiple-tabs-content');
23   - const { t } = useI18n();
24 20 const { refreshPage } = useTabs();
25 21  
26 22 async function handleRedo() {
... ... @@ -29,9 +25,9 @@
29 25 setTimeout(() => {
30 26 loading.value = false;
31 27 // Animation execution time
32   - }, 1000);
  28 + }, 1200);
33 29 }
34   - return { prefixCls, t, handleRedo, loading };
  30 + return { prefixCls, handleRedo, loading };
35 31 },
36 32 });
37 33 </script>
... ...
src/layouts/default/tabs/index.less
... ... @@ -8,13 +8,20 @@ html[data-theme=&#39;dark&#39;] {
8 8 }
9 9 }
10 10  
  11 +html[data-theme='light'] {
  12 + .@{prefix-cls} {
  13 + .ant-tabs-tab:not(.ant-tabs-tab-active) {
  14 + border: 1px solid #d9d9d9 !important;
  15 + }
  16 + }
  17 +}
  18 +
11 19 .@{prefix-cls} {
12 20 z-index: 10;
13 21 height: @multiple-height + 2;
14 22 line-height: @multiple-height + 2;
15 23 background: @component-background;
16 24 border-bottom: 1px solid @border-color-base;
17   - box-shadow: 0 1px 2px 0 rgba(29, 35, 41, 0.05);
18 25  
19 26 .ant-tabs-small {
20 27 height: @multiple-height;
... ...
src/layouts/default/tabs/index.vue
... ... @@ -20,26 +20,26 @@
20 20  
21 21 <template #tabBarExtraContent v-if="getShowRedo || getShowQuick">
22 22 <TabRedo v-if="getShowRedo" />
23   - <QuickButton v-if="getShowQuick" />
  23 + <TabContent isExtra :tabItem="$route" v-if="getShowQuick" />
24 24 <FoldButton v-if="getShowFold" />
25 25 </template>
26 26 </Tabs>
27 27 </div>
28 28 </template>
29 29 <script lang="ts">
  30 + import type { RouteLocationNormalized } from 'vue-router';
  31 +
30 32 import { defineComponent, computed, unref, ref } from 'vue';
31 33  
32 34 import { Tabs } from 'ant-design-vue';
33 35 import TabContent from './components/TabContent.vue';
34   - import QuickButton from './components/QuickButton.vue';
35 36 import FoldButton from './components/FoldButton.vue';
36 37 import TabRedo from './components/TabRedo.vue';
37   - import type { RouteLocationNormalized } from 'vue-router';
38 38  
39 39 import { useGo } from '/@/hooks/web/usePage';
40 40  
41   - import { tabStore } from '/@/store/modules/tab';
42   - import { userStore } from '/@/store/modules/user';
  41 + import { useMultipleTabStore } from '/@/store/modules/multipleTab';
  42 + import { useUserStore } from '/@/store/modules/user';
43 43  
44 44 import { initAffixTabs, useTabsDrag } from './useMultipleTabs';
45 45 import { useDesign } from '/@/hooks/web/useDesign';
... ... @@ -48,13 +48,12 @@
48 48 import { REDIRECT_NAME } from '/@/router/constant';
49 49 import { listenerRouteChange } from '/@/logics/mitt/routeChange';
50 50  
51   - import router from '/@/router';
  51 + import { useRouter } from 'vue-router';
52 52  
53 53 export default defineComponent({
54 54 name: 'MultipleTabs',
55 55 components: {
56   - QuickButton,
57   - TabRedo: TabRedo,
  56 + TabRedo,
58 57 FoldButton,
59 58 Tabs,
60 59 TabPane: Tabs.TabPane,
... ... @@ -65,12 +64,16 @@
65 64 const activeKeyRef = ref('');
66 65  
67 66 useTabsDrag(affixTextList);
  67 + const tabStore = useMultipleTabStore();
  68 + const userStore = useUserStore();
  69 + const router = useRouter();
  70 +
68 71 const { prefixCls } = useDesign('multiple-tabs');
69 72 const go = useGo();
70 73 const { getShowQuick, getShowRedo, getShowFold } = useMultipleTabSetting();
71 74  
72 75 const getTabsState = computed(() => {
73   - return tabStore.getTabsState.filter((item) => !item.meta?.hideTab);
  76 + return tabStore.getTabList.filter((item) => !item.meta?.hideTab);
74 77 });
75 78  
76 79 const unClose = computed(() => unref(getTabsState).length === 1);
... ... @@ -86,10 +89,11 @@
86 89  
87 90 listenerRouteChange((route) => {
88 91 const { name } = route;
89   - if (name === REDIRECT_NAME || !route || !userStore.getTokenState) return;
  92 + if (name === REDIRECT_NAME || !route || !userStore.getToken) {
  93 + return;
  94 + }
90 95  
91 96 const { path, fullPath, meta = {} } = route;
92   -
93 97 const { currentActiveMenu, hideTab } = meta;
94 98 const isHide = !hideTab ? null : currentActiveMenu;
95 99 const p = isHide || fullPath || path;
... ... @@ -101,10 +105,11 @@
101 105 const findParentRoute = router
102 106 .getRoutes()
103 107 .find((item) => item.path === currentActiveMenu);
  108 +
104 109 findParentRoute &&
105   - tabStore.addTabAction((findParentRoute as unknown) as RouteLocationNormalized);
  110 + tabStore.addTab((findParentRoute as unknown) as RouteLocationNormalized);
106 111 } else {
107   - tabStore.addTabAction(unref(route));
  112 + tabStore.addTab(unref(route));
108 113 }
109 114 });
110 115  
... ... @@ -116,9 +121,11 @@
116 121 // Close the current tab
117 122 function handleEdit(targetKey: string) {
118 123 // Added operation to hide, currently only use delete operation
119   - if (unref(unClose)) return;
  124 + if (unref(unClose)) {
  125 + return;
  126 + }
120 127  
121   - tabStore.closeTabByKeyAction(targetKey);
  128 + tabStore.closeTabByKey(targetKey, router);
122 129 }
123 130 return {
124 131 prefixCls,
... ...
src/layouts/default/tabs/types.ts
... ... @@ -14,22 +14,12 @@ export interface TabContentProps {
14 14 trigger?: ('click' | 'hover' | 'contextmenu')[];
15 15 }
16 16  
17   -/**
18   - * @description: ๅณ้”ฎ๏ผšไธ‹ๆ‹‰่œๅ•ๆ–‡ๅญ—
19   - */
20 17 export enum MenuEventEnum {
21   - // ๅˆทๆ–ฐ
22 18 REFRESH_PAGE,
23   - // ๅ…ณ้—ญๅฝ“ๅ‰
24 19 CLOSE_CURRENT,
25   - // ๅ…ณ้—ญๅทฆไพง
26 20 CLOSE_LEFT,
27   - // ๅ…ณ้—ญๅณไพง
28 21 CLOSE_RIGHT,
29   - // ๅ…ณ้—ญๅ…ถไป–
30 22 CLOSE_OTHER,
31   - // ๅ…ณ้—ญๆ‰€ๆœ‰
32 23 CLOSE_ALL,
33   - // ๆ”พๅคง
34 24 SCALE,
35 25 }
... ...
src/layouts/default/tabs/useMultipleTabs.ts
1 1 import { toRaw, ref, nextTick } from 'vue';
2   -import { RouteLocationNormalized } from 'vue-router';
  2 +import type { RouteLocationNormalized } from 'vue-router';
3 3 import { useDesign } from '/@/hooks/web/useDesign';
4 4 import { useSortable } from '/@/hooks/web/useSortable';
5   -import router from '/@/router';
6   -import { tabStore } from '/@/store/modules/tab';
  5 +import { useMultipleTabStore } from '/@/store/modules/multipleTab';
7 6 import { isNullAndUnDef } from '/@/utils/is';
8 7 import projectSetting from '/@/settings/projectSetting';
  8 +import { useRouter } from 'vue-router';
9 9  
10 10 export function initAffixTabs(): string[] {
11 11 const affixList = ref<RouteLocationNormalized[]>([]);
  12 +
  13 + const tabStore = useMultipleTabStore();
  14 + const router = useRouter();
12 15 /**
13 16 * @description: Filter all fixed routes
14 17 */
... ... @@ -30,7 +33,7 @@ export function initAffixTabs(): string[] {
30 33 const affixTabs = filterAffixTabs((router.getRoutes() as unknown) as RouteLocationNormalized[]);
31 34 affixList.value = affixTabs;
32 35 for (const tab of affixTabs) {
33   - tabStore.addTabAction(({
  36 + tabStore.addTab(({
34 37 meta: tab.meta,
35 38 name: tab.name,
36 39 path: tab.path,
... ... @@ -39,6 +42,7 @@ export function initAffixTabs(): string[] {
39 42 }
40 43  
41 44 let isAddAffix = false;
  45 +
42 46 if (!isAddAffix) {
43 47 addAffixTabs();
44 48 isAddAffix = true;
... ... @@ -47,8 +51,8 @@ export function initAffixTabs(): string[] {
47 51 }
48 52  
49 53 export function useTabsDrag(affixTextList: string[]) {
  54 + const tabStore = useMultipleTabStore();
50 55 const { multiTabsSetting } = projectSetting;
51   -
52 56 const { prefixCls } = useDesign('multiple-tabs');
53 57 nextTick(() => {
54 58 if (!multiTabsSetting.canDrag) return;
... ... @@ -66,7 +70,7 @@ export function useTabsDrag(affixTextList: string[]) {
66 70 return;
67 71 }
68 72  
69   - tabStore.commitSortTabs({ oldIndex, newIndex });
  73 + tabStore.sortTabs(oldIndex, newIndex);
70 74 },
71 75 });
72 76 initSortable();
... ...
src/layouts/default/tabs/useTabDropdown.ts
1 1 import type { TabContentProps } from './types';
2 2 import type { DropMenu } from '/@/components/Dropdown';
  3 +import type { ComputedRef } from 'vue';
3 4  
4 5 import { computed, unref, reactive } from 'vue';
5   -import { TabContentEnum, MenuEventEnum } from './types';
6   -import { tabStore } from '/@/store/modules/tab';
7   -import router from '/@/router';
8   -import { RouteLocationNormalized } from 'vue-router';
  6 +import { MenuEventEnum } from './types';
  7 +import { useMultipleTabStore } from '/@/store/modules/multipleTab';
  8 +import { RouteLocationNormalized, useRouter } from 'vue-router';
9 9 import { useTabs } from '/@/hooks/web/useTabs';
10 10 import { useI18n } from '/@/hooks/web/useI18n';
11 11  
12   -const { t } = useI18n();
13   -
14   -export function useTabDropdown(tabContentProps: TabContentProps) {
  12 +export function useTabDropdown(tabContentProps: TabContentProps, getIsTabs: ComputedRef<boolean>) {
15 13 const state = reactive({
16 14 current: null as Nullable<RouteLocationNormalized>,
17 15 currentIndex: 0,
18 16 });
19 17  
20   - const { currentRoute } = router;
21   -
22   - const isTabs = computed(() => tabContentProps.type === TabContentEnum.TAB_TYPE);
  18 + const { t } = useI18n();
  19 + const tabStore = useMultipleTabStore();
  20 + const { currentRoute } = useRouter();
  21 + const { refreshPage, closeAll, close, closeLeft, closeOther, closeRight } = useTabs();
23 22  
24   - const getCurrentTab = computed(
  23 + const getTargetTab = computed(
25 24 (): RouteLocationNormalized => {
26   - return unref(isTabs) ? tabContentProps.tabItem : unref(currentRoute);
  25 + return unref(getIsTabs) ? tabContentProps.tabItem : unref(currentRoute);
27 26 }
28 27 );
29 28  
... ... @@ -31,8 +30,10 @@ export function useTabDropdown(tabContentProps: TabContentProps) {
31 30 * @description: drop-down list
32 31 */
33 32 const getDropMenuList = computed(() => {
34   - if (!unref(getCurrentTab)) return;
35   - const { meta } = unref(getCurrentTab);
  33 + if (!unref(getTargetTab)) {
  34 + return;
  35 + }
  36 + const { meta } = unref(getTargetTab);
36 37 const { path } = unref(currentRoute);
37 38  
38 39 // Refresh button
... ... @@ -42,11 +43,11 @@ export function useTabDropdown(tabContentProps: TabContentProps) {
42 43 // Close left
43 44 const closeLeftDisabled = index === 0;
44 45  
45   - const disabled = tabStore.getTabsState.length === 1;
  46 + const disabled = tabStore.getTabList.length === 1;
46 47  
47 48 // Close right
48 49 const closeRightDisabled =
49   - index === tabStore.getTabsState.length - 1 && tabStore.getLastDragEndIndexState >= 0;
  50 + index === tabStore.getTabList.length - 1 && tabStore.getLastDragEndIndex >= 0;
50 51 const dropMenuList: DropMenu[] = [
51 52 {
52 53 icon: 'ion:reload-sharp',
... ... @@ -58,7 +59,7 @@ export function useTabDropdown(tabContentProps: TabContentProps) {
58 59 icon: 'clarity:close-line',
59 60 event: MenuEventEnum.CLOSE_CURRENT,
60 61 text: t('layout.multipleTab.close'),
61   - disabled: meta?.affix || disabled,
  62 + disabled: !!meta?.affix || disabled,
62 63 divider: true,
63 64 },
64 65 {
... ... @@ -92,15 +93,13 @@ export function useTabDropdown(tabContentProps: TabContentProps) {
92 93 return dropMenuList;
93 94 });
94 95  
95   - const getTrigger = computed(() => {
96   - return unref(isTabs) ? ['contextmenu'] : ['click'];
97   - });
98   -
99 96 function handleContextMenu(tabItem: RouteLocationNormalized) {
100 97 return (e: Event) => {
101   - if (!tabItem) return;
  98 + if (!tabItem) {
  99 + return;
  100 + }
102 101 e?.preventDefault();
103   - const index = tabStore.getTabsState.findIndex((tab) => tab.path === tabItem.path);
  102 + const index = tabStore.getTabList.findIndex((tab) => tab.path === tabItem.path);
104 103 state.current = tabItem;
105 104 state.currentIndex = index;
106 105 };
... ... @@ -108,12 +107,8 @@ export function useTabDropdown(tabContentProps: TabContentProps) {
108 107  
109 108 // Handle right click event
110 109 function handleMenuEvent(menu: DropMenu): void {
111   - const { refreshPage, closeAll, close, closeLeft, closeOther, closeRight } = useTabs();
112 110 const { event } = menu;
113 111 switch (event) {
114   - case MenuEventEnum.SCALE:
115   - scaleScreen();
116   - break;
117 112 case MenuEventEnum.REFRESH_PAGE:
118 113 // refresh page
119 114 refreshPage();
... ... @@ -140,5 +135,5 @@ export function useTabDropdown(tabContentProps: TabContentProps) {
140 135 break;
141 136 }
142 137 }
143   - return { getDropMenuList, handleMenuEvent, handleContextMenu, getTrigger, isTabs };
  138 + return { getDropMenuList, handleMenuEvent, handleContextMenu };
144 139 }
... ...
src/layouts/iframe/useFrameKeepAlive.ts
... ... @@ -2,18 +2,19 @@ import type { AppRouteRecordRaw } from &#39;/@/router/types&#39;;
2 2  
3 3 import { computed, toRaw, unref } from 'vue';
4 4  
5   -import { tabStore } from '/@/store/modules/tab';
  5 +import { useMultipleTabStore } from '/@/store/modules/multipleTab';
6 6  
7 7 import { uniqBy } from 'lodash-es';
8 8  
9 9 import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
10 10  
11   -import router from '/@/router';
  11 +import { useRouter } from 'vue-router';
12 12  
13 13 export function useFrameKeepAlive() {
  14 + const router = useRouter();
14 15 const { currentRoute } = router;
15 16 const { getShowMultipleTab } = useMultipleTabSetting();
16   -
  17 + const tabStore = useMultipleTabStore();
17 18 const getFramePages = computed(() => {
18 19 const ret =
19 20 getAllFramePages((toRaw(router.getRoutes()) as unknown) as AppRouteRecordRaw[]) || [];
... ... @@ -21,7 +22,7 @@ export function useFrameKeepAlive() {
21 22 });
22 23  
23 24 const getOpenTabList = computed((): string[] => {
24   - return tabStore.getTabsState.reduce((prev: string[], next) => {
  25 + return tabStore.getTabList.reduce((prev: string[], next) => {
25 26 if (next.meta && Reflect.has(next.meta, 'frameSrc')) {
26 27 prev.push(next.name as string);
27 28 }
... ...
src/layouts/page/index.vue
... ... @@ -35,13 +35,14 @@
35 35 import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
36 36 import { getTransitionName } from './transition';
37 37  
38   - import { useStore } from 'vuex';
  38 + import { useMultipleTabStore } from '/@/store/modules/multipleTab';
39 39  
40 40 export default defineComponent({
41 41 name: 'PageLayout',
42 42 components: { FrameLayout },
43 43 setup() {
44 44 const { getShowMultipleTab } = useMultipleTabSetting();
  45 + const tabStore = useMultipleTabStore();
45 46  
46 47 const { getOpenKeepAlive, getCanEmbedIFramePage } = useRootSetting();
47 48  
... ... @@ -49,15 +50,11 @@
49 50  
50 51 const openCache = computed(() => unref(getOpenKeepAlive) && unref(getShowMultipleTab));
51 52  
52   - const { getters } = useStore();
53   -
54 53 const getCaches = computed((): string[] => {
55 54 if (!unref(getOpenKeepAlive)) {
56 55 return [];
57 56 }
58   - // TODO The useStore is used here mainly to solve the problem of circular dependency hot update
59   - const cacheTabs = getters['app-tab/getCachedTabsState'];
60   - return cacheTabs;
  57 + return tabStore.getCachedTabList;
61 58 });
62 59  
63 60 return {
... ...
src/locales/setupI18n.ts
... ... @@ -3,14 +3,15 @@ import type { I18n, I18nOptions } from &#39;vue-i18n&#39;;
3 3  
4 4 import { createI18n } from 'vue-i18n';
5 5  
6   -import { localeStore } from '/@/store/modules/locale';
7 6 import { localeSetting } from '/@/settings/localeSetting';
  7 +import { useLocaleStoreWithOut } from '/@/store/modules/locale';
8 8  
9 9 const { fallback, availableLocales } = localeSetting;
10 10  
11 11 export let i18n: ReturnType<typeof createI18n>;
12 12  
13 13 async function createI18nOptions(): Promise<I18nOptions> {
  14 + const localeStore = useLocaleStoreWithOut();
14 15 const locale = localeStore.getLocale;
15 16 const defaultLocal = await import(`./lang/${locale}.ts`);
16 17 const message = defaultLocal.default?.message ?? {};
... ...
src/locales/useLocale.ts
... ... @@ -6,7 +6,7 @@ import type { LocaleType } from &#39;/#/config&#39;;
6 6 import moment from 'moment';
7 7  
8 8 import { i18n } from './setupI18n';
9   -import { localeStore } from '/@/store/modules/locale';
  9 +import { useLocaleStoreWithOut } from '/@/store/modules/locale';
10 10 import { unref, computed } from 'vue';
11 11  
12 12 interface LangModule {
... ... @@ -18,6 +18,8 @@ interface LangModule {
18 18 const loadLocalePool: LocaleType[] = [];
19 19  
20 20 function setI18nLanguage(locale: LocaleType) {
  21 + const localeStore = useLocaleStoreWithOut();
  22 +
21 23 if (i18n.mode === 'legacy') {
22 24 i18n.global.locale = locale;
23 25 } else {
... ... @@ -28,6 +30,7 @@ function setI18nLanguage(locale: LocaleType) {
28 30 }
29 31  
30 32 export function useLocale() {
  33 + const localeStore = useLocaleStoreWithOut();
31 34 const getLocale = computed(() => localeStore.getLocale);
32 35 const getShowLocalePicker = computed(() => localeStore.getShowPicker);
33 36  
... ... @@ -40,7 +43,9 @@ export function useLocale() {
40 43 async function changeLocale(locale: LocaleType) {
41 44 const globalI18n = i18n.global;
42 45 const currentLocale = unref(globalI18n.locale);
43   - if (currentLocale === locale) return locale;
  46 + if (currentLocale === locale) {
  47 + return locale;
  48 + }
44 49  
45 50 if (loadLocalePool.includes(locale)) {
46 51 setI18nLanguage(locale);
... ...
src/logics/error-handle/index.ts
... ... @@ -2,7 +2,10 @@
2 2 * Used to configure the global error handling function, which can monitor vue errors, script errors, static resource errors and Promise errors
3 3 */
4 4  
5   -import { errorStore, ErrorInfo } from '/@/store/modules/error';
  5 +import type { ErrorLogInfo } from '/#/store';
  6 +
  7 +import { useErrorLogStoreWithOut } from '/@/store/modules/errorLog';
  8 +
6 9 import { ErrorTypeEnum } from '/@/enums/exceptionEnum';
7 10 import { App } from 'vue';
8 11 import projectSetting from '/@/settings/projectSetting';
... ... @@ -61,8 +64,9 @@ function formatComponentName(vm: any) {
61 64 */
62 65  
63 66 function vueErrorHandler(err: Error, vm: any, info: string) {
  67 + const errorLogStore = useErrorLogStoreWithOut();
64 68 const { name, path } = formatComponentName(vm);
65   - errorStore.commitErrorInfoState({
  69 + errorLogStore.addErrorLogInfo({
66 70 type: ErrorTypeEnum.VUE,
67 71 name,
68 72 file: path,
... ... @@ -86,7 +90,7 @@ export function scriptErrorHandler(
86 90 if (event === 'Script error.' && !source) {
87 91 return false;
88 92 }
89   - const errorInfo: Partial<ErrorInfo> = {};
  93 + const errorInfo: Partial<ErrorLogInfo> = {};
90 94 colno = colno || (window.event && (window.event as any).errorCharacter) || 0;
91 95 errorInfo.message = event as string;
92 96 if (error?.stack) {
... ... @@ -95,13 +99,14 @@ export function scriptErrorHandler(
95 99 errorInfo.stack = '';
96 100 }
97 101 const name = source ? source.substr(source.lastIndexOf('/') + 1) : 'script';
98   - errorStore.commitErrorInfoState({
  102 + const errorLogStore = useErrorLogStoreWithOut();
  103 + errorLogStore.addErrorLogInfo({
99 104 type: ErrorTypeEnum.SCRIPT,
100 105 name: name,
101 106 file: source as string,
102 107 detail: 'lineno' + lineno,
103 108 url: window.location.href,
104   - ...(errorInfo as Pick<ErrorInfo, 'message' | 'stack'>),
  109 + ...(errorInfo as Pick<ErrorLogInfo, 'message' | 'stack'>),
105 110 });
106 111 return true;
107 112 }
... ... @@ -112,8 +117,9 @@ export function scriptErrorHandler(
112 117 function registerPromiseErrorHandler() {
113 118 window.addEventListener(
114 119 'unhandledrejection',
115   - function (event: any) {
116   - errorStore.commitErrorInfoState({
  120 + function (event) {
  121 + const errorLogStore = useErrorLogStoreWithOut();
  122 + errorLogStore.addErrorLogInfo({
117 123 type: ErrorTypeEnum.PROMISE,
118 124 name: 'Promise Error!',
119 125 file: 'none',
... ... @@ -136,10 +142,10 @@ function registerResourceErrorHandler() {
136 142 'error',
137 143 function (e: Event) {
138 144 const target = e.target ? e.target : (e.srcElement as any);
139   -
140   - errorStore.commitErrorInfoState({
  145 + const errorLogStore = useErrorLogStoreWithOut();
  146 + errorLogStore.addErrorLogInfo({
141 147 type: ErrorTypeEnum.RESOURCE,
142   - name: 'Resouce Error!',
  148 + name: 'Resource Error!',
143 149 file: (e.target || ({} as any)).currentSrc,
144 150 detail: JSON.stringify({
145 151 tagName: target.localName,
... ... @@ -147,7 +153,7 @@ function registerResourceErrorHandler() {
147 153 type: e.type,
148 154 }),
149 155 url: window.location.href,
150   - stack: 'resouce is not found',
  156 + stack: 'resource is not found',
151 157 message: (e.target || ({} as any)).localName + ' is load error',
152 158 });
153 159 },
... ... @@ -161,7 +167,9 @@ function registerResourceErrorHandler() {
161 167 */
162 168 export function setupErrorHandle(app: App) {
163 169 const { useErrorHandle } = projectSetting;
164   - if (!useErrorHandle) return;
  170 + if (!useErrorHandle) {
  171 + return;
  172 + }
165 173 // Vue exception monitoring;
166 174 app.config.errorHandler = vueErrorHandler;
167 175  
... ...
src/logics/initAppConfig.ts
... ... @@ -12,18 +12,20 @@ import { updateGrayMode } from &#39;/@/logics/theme/updateGrayMode&#39;;
12 12 import { updateDarkTheme } from '/@/logics/theme/dark';
13 13 import { changeTheme } from '/@/logics/theme';
14 14  
15   -import { appStore } from '/@/store/modules/app';
16   -import { localeStore } from '/@/store/modules/locale';
  15 +import { useAppStore } from '/@/store/modules/app';
  16 +import { useLocaleStore } from '/@/store/modules/locale';
17 17  
18 18 import { getCommonStoragePrefix, getStorageShortName } from '/@/utils/env';
19 19  
20 20 import { primaryColor } from '../../build/config/themeConfig';
21 21 import { Persistent } from '/@/utils/cache/persistent';
22 22 import { deepMerge } from '/@/utils';
23   -import { ThemeEnum } from '../enums/appEnum';
  23 +import { ThemeEnum } from '/@/enums/appEnum';
24 24  
25 25 // Initial project configuration
26 26 export function initAppConfigStore() {
  27 + const localeStore = useLocaleStore();
  28 + const appStore = useAppStore();
27 29 let projCfg: ProjectConfig = Persistent.getLocal(PROJ_CFG_KEY) as ProjectConfig;
28 30 projCfg = deepMerge(projectSetting, projCfg || {});
29 31 const darkMode = appStore.getDarkMode;
... ... @@ -45,7 +47,7 @@ export function initAppConfigStore() {
45 47 } catch (error) {
46 48 console.log(error);
47 49 }
48   - appStore.commitProjectConfigState(projCfg);
  50 + appStore.setProjectConfig(projCfg);
49 51  
50 52 // init dark mode
51 53 updateDarkTheme(darkMode);
... ...
src/logics/theme/updateBackground.ts
1 1 import { colorIsDark, lighten, darken } from '/@/utils/color';
2   -import { appStore } from '/@/store/modules/app';
  2 +import { useAppStore } from '/@/store/modules/app';
3 3 import { ThemeEnum } from '/@/enums/appEnum';
4 4 import { setCssVar } from './util';
5 5  
... ... @@ -16,12 +16,13 @@ const SIDER_LIGHTEN_BG_COLOR = &#39;--sider-dark-lighten-bg-color&#39;;
16 16 * @param color
17 17 */
18 18 export function updateHeaderBgColor(color?: string) {
  19 + const appStore = useAppStore();
19 20 const darkMode = appStore.getDarkMode === ThemeEnum.DARK;
20 21 if (!color) {
21 22 if (darkMode) {
22 23 color = '#151515';
23 24 } else {
24   - color = appStore.getProjectConfig.headerSetting.bgColor;
  25 + color = appStore.getHeaderSetting.bgColor;
25 26 }
26 27 }
27 28 // bg color
... ... @@ -35,7 +36,7 @@ export function updateHeaderBgColor(color?: string) {
35 36 // Determine the depth of the color value and automatically switch the theme
36 37 const isDark = colorIsDark(color!);
37 38  
38   - appStore.commitProjectConfigState({
  39 + appStore.setProjectConfig({
39 40 headerSetting: {
40 41 theme: isDark || darkMode ? ThemeEnum.DARK : ThemeEnum.LIGHT,
41 42 },
... ... @@ -47,13 +48,15 @@ export function updateHeaderBgColor(color?: string) {
47 48 * @param color bg color
48 49 */
49 50 export function updateSidebarBgColor(color?: string) {
  51 + const appStore = useAppStore();
  52 +
50 53 // if (!isHexColor(color)) return;
51 54 const darkMode = appStore.getDarkMode === ThemeEnum.DARK;
52 55 if (!color) {
53 56 if (darkMode) {
54 57 color = '#212121';
55 58 } else {
56   - color = appStore.getProjectConfig.menuSetting.bgColor;
  59 + color = appStore.getMenuSetting.bgColor;
57 60 }
58 61 }
59 62 setCssVar(SIDER_DARK_BG_COLOR, color);
... ... @@ -64,7 +67,7 @@ export function updateSidebarBgColor(color?: string) {
64 67 // Only when the background color is #fff, the theme of the menu will be changed to light
65 68 const isLight = ['#fff', '#ffffff'].includes(color!.toLowerCase());
66 69  
67   - appStore.commitProjectConfigState({
  70 + appStore.setProjectConfig({
68 71 menuSetting: {
69 72 theme: isLight && !darkMode ? ThemeEnum.LIGHT : ThemeEnum.DARK,
70 73 },
... ...
src/main.ts
... ... @@ -5,15 +5,13 @@ import { createApp } from &#39;vue&#39;;
5 5 import App from './App.vue';
6 6  
7 7 import router, { setupRouter } from '/@/router';
  8 +import { setupRouterGuard } from '/@/router/guard';
8 9 import { setupStore } from '/@/store';
9 10 import { setupErrorHandle } from '/@/logics/error-handle';
10 11 import { setupGlobDirectives } from '/@/directives';
11 12 import { setupI18n } from '/@/locales/setupI18n';
12 13 import { registerGlobComp } from '/@/components/registerGlobComp';
13 14  
14   -// router-guard
15   -import '/@/router/guard';
16   -
17 15 // Register icon Sprite
18 16 import 'vite-plugin-svg-icons/register';
19 17  
... ... @@ -27,6 +25,10 @@ if (import.meta.env.DEV) {
27 25  
28 26 (async () => {
29 27 const app = createApp(App);
  28 +
  29 + // Configure vuex store
  30 + setupStore(app);
  31 +
30 32 // Register global components
31 33 registerGlobComp(app);
32 34  
... ... @@ -36,8 +38,8 @@ if (import.meta.env.DEV) {
36 38 // Configure routing
37 39 setupRouter(app);
38 40  
39   - // Configure vuex store
40   - setupStore(app);
  41 + // router-guard
  42 + setupRouterGuard();
41 43  
42 44 // Register global directive
43 45 setupGlobDirectives(app);
... ...
src/router/constant.ts
... ... @@ -20,13 +20,3 @@ export const getParentLayout = (_name?: string) =&gt; {
20 20 });
21 21 });
22 22 };
23   -
24   -// export const getParentLayout = (name: string) => {
25   -// return () =>
26   -// new Promise((resolve) => {
27   -// resolve({
28   -// ...ParentLayout,
29   -// name,
30   -// });
31   -// });
32   -// };
... ...
src/router/guard/index.ts
... ... @@ -9,11 +9,13 @@ import { createHttpGuard } from &#39;./httpGuard&#39;;
9 9 import { createPageGuard } from './pageGuard';
10 10 import { createStateGuard } from './stateGuard';
11 11  
12   -createPageGuard(router);
13   -createPageLoadingGuard(router);
14   -createHttpGuard(router);
15   -createScrollGuard(router);
16   -createMessageGuard(router);
17   -createProgressGuard(router);
18   -createPermissionGuard(router);
19   -createStateGuard(router);
  12 +export function setupRouterGuard() {
  13 + createPageGuard(router);
  14 + createPageLoadingGuard(router);
  15 + createHttpGuard(router);
  16 + createScrollGuard(router);
  17 + createMessageGuard(router);
  18 + createProgressGuard(router);
  19 + createPermissionGuard(router);
  20 + createStateGuard(router);
  21 +}
... ...
src/router/guard/pageLoadingGuard.ts
1 1 import type { Router } from 'vue-router';
2   -import { appStore } from '/@/store/modules/app';
3   -import { userStore } from '/@/store/modules/user';
  2 +import { useAppStoreWidthOut } from '/@/store/modules/app';
  3 +import { useUserStoreWidthOut } from '/@/store/modules/user';
4 4 import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
5 5 import { unref } from 'vue';
6 6  
7   -const { getOpenPageLoading } = useTransitionSetting();
8 7 export function createPageLoadingGuard(router: Router) {
  8 + const userStore = useUserStoreWidthOut();
  9 + const appStore = useAppStoreWidthOut();
  10 + const { getOpenPageLoading } = useTransitionSetting();
9 11 router.beforeEach(async (to) => {
10   - if (!userStore.getTokenState) {
  12 + if (!userStore.getToken) {
11 13 return true;
12 14 }
13 15 if (to.meta.loaded) {
... ... @@ -24,7 +26,7 @@ export function createPageLoadingGuard(router: Router) {
24 26 router.afterEach(async () => {
25 27 if (unref(getOpenPageLoading)) {
26 28 setTimeout(() => {
27   - appStore.commitPageLoadingState(false);
  29 + appStore.setPageLoading(false);
28 30 }, 220);
29 31 }
30 32 return true;
... ...
src/router/guard/permissionGuard.ts
1 1 import type { Router, RouteRecordRaw } from 'vue-router';
2 2  
3   -import { permissionStore } from '/@/store/modules/permission';
  3 +import { usePermissionStoreWidthOut } from '/@/store/modules/permission';
4 4  
5 5 import { PageEnum } from '/@/enums/pageEnum';
6   -import { userStore } from '/@/store/modules/user';
  6 +import { useUserStoreWidthOut } from '/@/store/modules/user';
7 7  
8 8 import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic';
9 9  
... ... @@ -12,6 +12,8 @@ const LOGIN_PATH = PageEnum.BASE_LOGIN;
12 12 const whitePathList: PageEnum[] = [LOGIN_PATH];
13 13  
14 14 export function createPermissionGuard(router: Router) {
  15 + const userStore = useUserStoreWidthOut();
  16 + const permissionStore = usePermissionStoreWidthOut();
15 17 router.beforeEach(async (to, from, next) => {
16 18 // Jump to the 404 page after processing the login
17 19 if (from.path === LOGIN_PATH && to.name === PAGE_NOT_FOUND_ROUTE.name) {
... ... @@ -25,7 +27,7 @@ export function createPermissionGuard(router: Router) {
25 27 return;
26 28 }
27 29  
28   - const token = userStore.getTokenState;
  30 + const token = userStore.getToken;
29 31  
30 32 // token does not exist
31 33 if (!token) {
... ... @@ -51,7 +53,7 @@ export function createPermissionGuard(router: Router) {
51 53 next(redirectData);
52 54 return;
53 55 }
54   - if (permissionStore.getIsDynamicAddedRouteState) {
  56 + if (permissionStore.getIsDynamicAddedRoute) {
55 57 next();
56 58 return;
57 59 }
... ... @@ -64,7 +66,7 @@ export function createPermissionGuard(router: Router) {
64 66 const redirectPath = (from.query.redirect || to.path) as string;
65 67 const redirect = decodeURIComponent(redirectPath);
66 68 const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect };
67   - permissionStore.commitDynamicAddedRouteState(true);
  69 + permissionStore.setDynamicAddedRoute(true);
68 70 next(nextData);
69 71 });
70 72 }
... ...
src/router/guard/progressGuard.ts
... ... @@ -6,9 +6,8 @@ import nProgress from &#39;nprogress&#39;;
6 6  
7 7 import { unref } from 'vue';
8 8  
9   -const { getOpenNProgress } = useTransitionSetting();
10   -
11 9 export function createProgressGuard(router: Router) {
  10 + const { getOpenNProgress } = useTransitionSetting();
12 11 router.beforeEach(async (to) => {
13 12 if (to.meta.loaded) return true;
14 13 unref(getOpenNProgress) && nProgress.start();
... ...
src/router/guard/stateGuard.ts
1 1 import type { Router } from 'vue-router';
2   -import { appStore } from '/@/store/modules/app';
3   -import { tabStore } from '/@/store/modules/tab';
4   -import { userStore } from '/@/store/modules/user';
5   -import { permissionStore } from '/@/store/modules/permission';
  2 +import { useAppStore } from '/@/store/modules/app';
  3 +import { useMultipleTabStore } from '/@/store/modules/multipleTab';
  4 +import { useUserStore } from '/@/store/modules/user';
  5 +import { usePermissionStore } from '/@/store/modules/permission';
6 6 import { PageEnum } from '/@/enums/pageEnum';
7 7 import { removeTabChangeListener } from '/@/logics/mitt/routeChange';
8 8  
9 9 export function createStateGuard(router: Router) {
10 10 router.afterEach((to) => {
  11 + const tabStore = useMultipleTabStore();
  12 + const userStore = useUserStore();
  13 + const appStore = useAppStore();
  14 + const permissionStore = usePermissionStore();
11 15 // Just enter the login page and clear the authentication information
12 16 if (to.path === PageEnum.BASE_LOGIN) {
13   - appStore.resumeAllState();
14   - permissionStore.commitResetState();
15   - tabStore.commitResetState();
16   - userStore.commitResetState();
  17 + appStore.resetAllState();
  18 + permissionStore.resetState();
  19 + tabStore.resetState();
  20 + userStore.resetState();
17 21 removeTabChangeListener();
18 22 }
19 23 });
... ...
src/router/menus/index.ts
1 1 import type { Menu, MenuModule } from '/@/router/types';
2 2 import type { RouteRecordNormalized } from 'vue-router';
3 3  
4   -import { appStore } from '/@/store/modules/app';
5   -import { permissionStore } from '/@/store/modules/permission';
  4 +import { useAppStoreWidthOut } from '/@/store/modules/app';
  5 +import { usePermissionStore } from '/@/store/modules/permission';
6 6 import { transformMenuModule, getAllParentPath } from '/@/router/helper/menuHelper';
7 7 import { filter } from '/@/utils/helper/treeHelper';
8 8 import { isUrl } from '/@/utils/is';
... ... @@ -24,6 +24,7 @@ Object.keys(modules).forEach((key) =&gt; {
24 24 // ==========Helper===========
25 25 // ===========================
26 26 const isBackMode = () => {
  27 + const appStore = useAppStoreWidthOut();
27 28 return appStore.getProjectConfig.permissionMode === PermissionModeEnum.BACK;
28 29 };
29 30  
... ... @@ -39,7 +40,8 @@ const staticMenus: Menu[] = [];
39 40 })();
40 41  
41 42 async function getAsyncMenus() {
42   - return !isBackMode() ? staticMenus : permissionStore.getBackMenuListState;
  43 + const permissionStore = usePermissionStore();
  44 + return !isBackMode() ? staticMenus : permissionStore.getBackMenuList;
43 45 }
44 46  
45 47 export const getMenus = async (): Promise<Menu[]> => {
... ...
src/settings/designSetting.ts
1 1 import { ThemeEnum } from '../enums/appEnum';
2   -export default {
3   - prefixCls: 'vben',
4   -};
  2 +
  3 +export const prefixCls = 'vben';
5 4  
6 5 export const darkMode = ThemeEnum.LIGHT;
7 6  
... ...
src/settings/projectSetting.ts
... ... @@ -61,7 +61,6 @@ const setting: ProjectConfig = {
61 61 theme: ThemeEnum.LIGHT,
62 62 // Whether to enable the lock screen function
63 63 useLockPage: true,
64   -
65 64 // Whether to show the full screen button
66 65 showFullScreen: true,
67 66 // Whether to show the document button
... ...
src/settings/siteSetting.ts
1 1 // github repo url
2 2 export const GITHUB_URL = 'https://github.com/anncwb/vue-vben-admin';
  3 +
3 4 // vue-vben-admin-next-doc
4 5 export const DOC_URL = 'https://vvbin.cn/doc-next/';
  6 +
5 7 // site url
6 8 export const SITE_URL = 'https://vvbin.cn/next/';
... ...
src/store/index.ts
1 1 import type { App } from 'vue';
2   -import { createStore } from 'vuex';
3   -import { config } from 'vuex-module-decorators';
4   -import { isDevMode } from '/@/utils/env';
5   -
6   -config.rawError = true;
7   -
8   -const store = createStore({
9   - strict: isDevMode(),
10   -});
  2 +import { createPinia } from 'pinia';
  3 +const store = createPinia();
11 4  
12 5 export function setupStore(app: App<Element>) {
13 6 app.use(store);
14 7 }
15 8  
16   -export default store;
  9 +export { store };
... ...
src/store/modules/app.ts
1 1 import type { ProjectConfig } from '/#/config';
2   -import type { BeforeMiniState } from '../types';
  2 +import type { BeforeMiniState } from '/#/store';
3 3  
4   -import { VuexModule, getModule, Module, Mutation, Action } from 'vuex-module-decorators';
5   -import store from '/@/store';
  4 +import { defineStore } from 'pinia';
  5 +import { store } from '/@/store';
6 6  
7   -import { PROJ_CFG_KEY, APP_DARK_MODE_KEY_ } from '/@/enums/cacheEnum';
8   -
9   -import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper';
  7 +import { ThemeEnum } from '/@/enums/appEnum';
  8 +import { APP_DARK_MODE_KEY_, PROJ_CFG_KEY } from '/@/enums/cacheEnum';
10 9 import { Persistent } from '/@/utils/cache/persistent';
11   -import { deepMerge } from '/@/utils';
12   -
13   -import { resetRouter } from '/@/router';
14   -import { ThemeEnum } from '../../enums/appEnum';
15   -
16 10 import { darkMode } from '/@/settings/designSetting';
  11 +import { resetRouter } from '/@/router';
  12 +import { deepMerge } from '/@/utils';
17 13  
18   -export interface LockInfo {
19   - pwd: string | undefined;
20   - isLock: boolean;
21   -}
22   -
23   -let timeId: TimeoutHandle;
24   -const NAME = 'app';
25   -hotModuleUnregisterModule(NAME);
26   -@Module({ dynamic: true, namespaced: true, store, name: NAME })
27   -export default class App extends VuexModule {
28   - private darkMode;
29   -
  14 +interface AppState {
  15 + darkMode: ThemeEnum;
30 16 // Page loading status
31   - private pageLoadingState = false;
32   -
  17 + pageLoading: boolean;
33 18 // project config
34   - private projectConfigState: ProjectConfig | null = Persistent.getLocal(PROJ_CFG_KEY);
35   -
36   - // set main overflow hidden
37   - private lockMainScrollState = false;
38   -
  19 + projectConfig: ProjectConfig | null;
39 20 // When the window shrinks, remember some states, and restore these states when the window is restored
40   - private beforeMiniState: BeforeMiniState = {};
41   -
42   - get getPageLoading() {
43   - return this.pageLoadingState;
44   - }
45   -
46   - get getDarkMode() {
47   - return this.darkMode || localStorage.getItem(APP_DARK_MODE_KEY_) || darkMode;
48   - }
49   -
50   - get getBeforeMiniState() {
51   - return this.beforeMiniState;
52   - }
53   -
54   - get getLockMainScrollState() {
55   - return this.lockMainScrollState;
56   - }
57   -
58   - get getProjectConfig(): ProjectConfig {
59   - return this.projectConfigState || ({} as ProjectConfig);
60   - }
61   -
62   - @Mutation
63   - commitPageLoadingState(loading: boolean): void {
64   - this.pageLoadingState = loading;
65   - }
66   -
67   - @Mutation
68   - commitDarkMode(mode: ThemeEnum): void {
69   - this.darkMode = mode;
70   - localStorage.setItem(APP_DARK_MODE_KEY_, mode);
71   - }
72   -
73   - @Mutation
74   - commitBeforeMiniState(state: BeforeMiniState): void {
75   - this.beforeMiniState = state;
76   - }
77   -
78   - @Mutation
79   - commitLockMainScrollState(lock: boolean): void {
80   - this.lockMainScrollState = lock;
81   - }
82   -
83   - @Mutation
84   - commitProjectConfigState(proCfg: DeepPartial<ProjectConfig>): void {
85   - this.projectConfigState = deepMerge(this.projectConfigState || {}, proCfg);
86   - Persistent.setLocal(PROJ_CFG_KEY, this.projectConfigState);
87   - }
88   -
89   - @Action
90   - async resumeAllState() {
91   - resetRouter();
92   - Persistent.clearAll();
93   - }
94   -
95   - @Action
96   - public async setPageLoadingAction(loading: boolean): Promise<void> {
97   - if (loading) {
98   - clearTimeout(timeId);
99   - // Prevent flicker
100   - timeId = setTimeout(() => {
101   - this.commitPageLoadingState(loading);
102   - }, 50);
103   - } else {
104   - this.commitPageLoadingState(loading);
105   - clearTimeout(timeId);
106   - }
107   - }
  21 + beforeMiniInfo: BeforeMiniState;
  22 +}
  23 +let timeId: TimeoutHandle;
  24 +export const useAppStore = defineStore({
  25 + id: 'app',
  26 + state: (): AppState => ({
  27 + darkMode: ThemeEnum.LIGHT,
  28 + pageLoading: false,
  29 + projectConfig: Persistent.getLocal(PROJ_CFG_KEY),
  30 + beforeMiniInfo: {},
  31 + }),
  32 + getters: {
  33 + getPageLoading() {
  34 + return this.pageLoading;
  35 + },
  36 + getDarkMode() {
  37 + return this.darkMode || localStorage.getItem(APP_DARK_MODE_KEY_) || darkMode;
  38 + },
  39 +
  40 + getBeforeMiniInfo() {
  41 + return this.beforeMiniInfo;
  42 + },
  43 +
  44 + getProjectConfig(): ProjectConfig {
  45 + return this.projectConfig || ({} as ProjectConfig);
  46 + },
  47 +
  48 + getHeaderSetting() {
  49 + return this.getProjectConfig.headerSetting;
  50 + },
  51 + getMenuSetting() {
  52 + return this.getProjectConfig.menuSetting;
  53 + },
  54 + getTransitionSetting() {
  55 + return this.getProjectConfig.transitionSetting;
  56 + },
  57 + getMultiTabsSetting() {
  58 + return this.getProjectConfig.multiTabsSetting;
  59 + },
  60 + },
  61 + actions: {
  62 + setPageLoading(loading: boolean): void {
  63 + this.pageLoading = loading;
  64 + },
  65 +
  66 + setDarkMode(mode: ThemeEnum): void {
  67 + this.darkMode = mode;
  68 + localStorage.setItem(APP_DARK_MODE_KEY_, mode);
  69 + },
  70 +
  71 + setBeforeMiniInfo(state: BeforeMiniState): void {
  72 + this.beforeMiniInfo = state;
  73 + },
  74 +
  75 + setProjectConfig(config: DeepPartial<ProjectConfig>): void {
  76 + this.projectConfig = deepMerge(this.projectConfig || {}, config);
  77 + Persistent.setLocal(PROJ_CFG_KEY, this.projectConfig);
  78 + },
  79 +
  80 + async resetAllState() {
  81 + resetRouter();
  82 + Persistent.clearAll();
  83 + },
  84 + async setPageLoadingAction(loading: boolean): Promise<void> {
  85 + if (loading) {
  86 + clearTimeout(timeId);
  87 + // Prevent flicker
  88 + timeId = setTimeout(() => {
  89 + this.setPageLoading(loading);
  90 + }, 50);
  91 + } else {
  92 + this.setPageLoading(loading);
  93 + clearTimeout(timeId);
  94 + }
  95 + },
  96 + },
  97 +});
  98 +
  99 +// Need to be used outside the setup
  100 +export function useAppStoreWidthOut() {
  101 + return useAppStore(store);
108 102 }
109   -export const appStore = getModule<App>(App);
... ...
src/store/modules/error.ts deleted 100644 โ†’ 0
1   -import store from '/@/store';
2   -import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper';
3   -import { VuexModule, getModule, Module, Mutation, Action } from 'vuex-module-decorators';
4   -
5   -import { formatToDateTime } from '/@/utils/dateUtil';
6   -import { ErrorTypeEnum } from '/@/enums/exceptionEnum';
7   -import projectSetting from '/@/settings/projectSetting';
8   -
9   -export interface ErrorInfo {
10   - type: ErrorTypeEnum;
11   - file: string;
12   - name?: string;
13   - message: string;
14   - stack?: string;
15   - detail: string;
16   - url: string;
17   - time?: string;
18   -}
19   -
20   -export interface ErrorState {
21   - errorInfoState: ErrorInfo[] | null;
22   - errorListCountState: number;
23   -}
24   -
25   -const NAME = 'app-error';
26   -hotModuleUnregisterModule(NAME);
27   -@Module({ dynamic: true, namespaced: true, store, name: NAME })
28   -class Error extends VuexModule implements ErrorState {
29   - // error log list
30   - errorInfoState: ErrorInfo[] = [];
31   -
32   - // error log count
33   - errorListCountState = 0;
34   -
35   - get getErrorInfoState() {
36   - return this.errorInfoState;
37   - }
38   -
39   - get getErrorListCountState() {
40   - return this.errorListCountState;
41   - }
42   -
43   - @Mutation
44   - commitErrorInfoState(info: ErrorInfo): void {
45   - const item = {
46   - ...info,
47   - time: formatToDateTime(new Date()),
48   - };
49   - this.errorInfoState = [item, ...this.errorInfoState];
50   - this.errorListCountState += 1;
51   - }
52   -
53   - @Mutation
54   - commitErrorListCountState(count: number): void {
55   - this.errorListCountState = count;
56   - }
57   -
58   - @Action
59   - setupErrorHandle(error: any) {
60   - const { useErrorHandle } = projectSetting;
61   - if (!useErrorHandle) return;
62   -
63   - const errInfo: Partial<ErrorInfo> = {
64   - message: error.message,
65   - type: ErrorTypeEnum.AJAX,
66   - };
67   - if (error.response) {
68   - const {
69   - config: { url = '', data: params = '', method = 'get', headers = {} } = {},
70   - data = {},
71   - } = error.response;
72   - errInfo.url = url;
73   - errInfo.name = 'Ajax Error!';
74   - errInfo.file = '-';
75   - errInfo.stack = JSON.stringify(data);
76   - errInfo.detail = JSON.stringify({ params, method, headers });
77   - }
78   - this.commitErrorInfoState(errInfo as ErrorInfo);
79   - }
80   -}
81   -export const errorStore = getModule<Error>(Error);
src/store/modules/errorLog.ts 0 โ†’ 100644
  1 +import type { ErrorLogInfo } from '/#/store';
  2 +
  3 +import { defineStore } from 'pinia';
  4 +import { store } from '/@/store';
  5 +
  6 +import { formatToDateTime } from '/@/utils/dateUtil';
  7 +import projectSetting from '/@/settings/projectSetting';
  8 +
  9 +import { ErrorTypeEnum } from '/@/enums/exceptionEnum';
  10 +
  11 +export interface ErrorLogState {
  12 + errorLogInfoList: Nullable<ErrorLogInfo[]>;
  13 + errorLogListCount: number;
  14 +}
  15 +
  16 +export const useErrorLogStore = defineStore({
  17 + id: 'app-error-log',
  18 + state: (): ErrorLogState => ({
  19 + errorLogInfoList: null,
  20 + errorLogListCount: 0,
  21 + }),
  22 + getters: {
  23 + getErrorLogInfoList() {
  24 + return this.errorLogInfoList || [];
  25 + },
  26 + getErrorLogListCount() {
  27 + return this.errorLogListCount;
  28 + },
  29 + },
  30 + actions: {
  31 + addErrorLogInfo(info: ErrorLogInfo) {
  32 + const item = {
  33 + ...info,
  34 + time: formatToDateTime(new Date()),
  35 + };
  36 + this.errorLogInfoList = [item, ...(this.errorLogInfoList || [])];
  37 + this.errorLogListCount += 1;
  38 + },
  39 +
  40 + setErrorLogListCount(count: number): void {
  41 + this.errorLogListCount = count;
  42 + },
  43 +
  44 + /**
  45 + * Triggered after ajax request error
  46 + * @param error
  47 + * @returns
  48 + */
  49 + addAjaxErrorInfo(error) {
  50 + const { useErrorHandle } = projectSetting;
  51 + if (!useErrorHandle) {
  52 + return;
  53 + }
  54 + const errInfo: Partial<ErrorLogInfo> = {
  55 + message: error.message,
  56 + type: ErrorTypeEnum.AJAX,
  57 + };
  58 + if (error.response) {
  59 + const {
  60 + config: { url = '', data: params = '', method = 'get', headers = {} } = {},
  61 + data = {},
  62 + } = error.response;
  63 + errInfo.url = url;
  64 + errInfo.name = 'Ajax Error!';
  65 + errInfo.file = '-';
  66 + errInfo.stack = JSON.stringify(data);
  67 + errInfo.detail = JSON.stringify({ params, method, headers });
  68 + }
  69 + this.addErrorLogInfo(errInfo as ErrorLogInfo);
  70 + },
  71 + },
  72 +});
  73 +
  74 +// Need to be used outside the setup
  75 +export function useErrorLogStoreWithOut() {
  76 + return useErrorLogStore(store);
  77 +}
... ...
src/store/modules/locale.ts
1   -import store from '/@/store';
  1 +import type { LocaleSetting, LocaleType } from '/#/config';
2 2  
3   -import { VuexModule, getModule, Module, Mutation, Action } from 'vuex-module-decorators';
  3 +import { defineStore } from 'pinia';
  4 +import { store } from '/@/store';
4 5  
5 6 import { LOCALE_KEY } from '/@/enums/cacheEnum';
6   -
7   -import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper';
8   -import { LocaleSetting, LocaleType } from '/#/config';
9 7 import { createLocalStorage } from '/@/utils/cache';
10 8 import { localeSetting } from '/@/settings/localeSetting';
11 9  
12 10 const ls = createLocalStorage();
13 11  
14   -const lsSetting = (ls.get(LOCALE_KEY) || localeSetting) as LocaleSetting;
15   -
16   -const NAME = 'app-locale';
17   -hotModuleUnregisterModule(NAME);
18   -@Module({ dynamic: true, namespaced: true, store, name: NAME })
19   -class Locale extends VuexModule {
20   - private info: LocaleSetting = lsSetting;
21   -
22   - get getShowPicker(): boolean {
23   - return !!this.info?.showPicker;
24   - }
  12 +const lsLocaleSetting = (ls.get(LOCALE_KEY) || localeSetting) as LocaleSetting;
25 13  
26   - get getLocale(): LocaleType {
27   - return this.info?.locale;
28   - }
29   -
30   - @Mutation
31   - setLocaleInfo(info: Partial<LocaleSetting>): void {
32   - this.info = { ...this.info, ...info };
33   - ls.set(LOCALE_KEY, this.info);
34   - }
  14 +interface LocaleState {
  15 + localInfo: LocaleSetting;
  16 +}
35 17  
36   - @Action
37   - initLocale(): void {
38   - this.setLocaleInfo({
39   - ...localeSetting,
40   - ...this.info,
41   - });
42   - }
  18 +export const useLocaleStore = defineStore({
  19 + id: 'app-locale',
  20 + state: (): LocaleState => ({
  21 + localInfo: lsLocaleSetting,
  22 + }),
  23 + getters: {
  24 + getShowPicker() {
  25 + return !!this.localInfo?.showPicker;
  26 + },
  27 + getLocale(): LocaleType {
  28 + return this.localInfo?.locale ?? 'zh_CN';
  29 + },
  30 + },
  31 + actions: {
  32 + /**
  33 + * Set up multilingual information and cache
  34 + * @param info multilingual info
  35 + */
  36 + setLocaleInfo(info: Partial<LocaleSetting>) {
  37 + this.localInfo = { ...this.localInfo, ...info };
  38 + ls.set(LOCALE_KEY, this.localInfo);
  39 + },
  40 + /**
  41 + * Initialize multilingual information and load the existing configuration from the local cache
  42 + */
  43 + initLocale() {
  44 + this.setLocaleInfo({
  45 + ...localeSetting,
  46 + ...this.localInfo,
  47 + });
  48 + },
  49 + },
  50 +});
  51 +
  52 +// Need to be used outside the setup
  53 +export function useLocaleStoreWithOut() {
  54 + return useLocaleStore(store);
43 55 }
44   -export const localeStore = getModule<Locale>(Locale);
... ...
src/store/modules/lock.ts
1   -import type { LockInfo } from '/@/store/types';
  1 +import type { LockInfo } from '/#/store';
2 2  
3   -import { VuexModule, getModule, Module, Mutation, Action } from 'vuex-module-decorators';
4   -import store from '/@/store';
  3 +import { defineStore } from 'pinia';
5 4  
6 5 import { LOCK_INFO_KEY } from '/@/enums/cacheEnum';
7   -
8   -import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper';
9 6 import { Persistent } from '/@/utils/cache/persistent';
  7 +import { useUserStore } from './user';
10 8  
11   -import { userStore } from './user';
12   -
13   -const NAME = 'app-lock';
14   -hotModuleUnregisterModule(NAME);
15   -@Module({ dynamic: true, namespaced: true, store, name: NAME })
16   -class Lock extends VuexModule {
17   - // lock info
18   - private lockInfoState: LockInfo | null = Persistent.getLocal(LOCK_INFO_KEY);
19   -
20   - get getLockInfo(): LockInfo {
21   - return this.lockInfoState || ({} as LockInfo);
22   - }
23   -
24   - @Mutation
25   - commitLockInfoState(info: LockInfo): void {
26   - this.lockInfoState = Object.assign({}, this.lockInfoState, info);
27   - Persistent.setLocal(LOCK_INFO_KEY, this.lockInfoState);
28   - }
29   -
30   - @Mutation
31   - resetLockInfo(): void {
32   - Persistent.removeLocal(LOCK_INFO_KEY);
33   - this.lockInfoState = null;
34   - }
  9 +interface LockState {
  10 + lockInfo: Nullable<LockInfo>;
  11 +}
35 12  
36   - /**
37   - * @description: unlock page
38   - */
39   - @Action
40   - public async unLockAction({ password }: { password: string }) {
41   - const tryLogin = async () => {
42   - try {
43   - const username = userStore.getUserInfoState.username;
44   - const res = await userStore.login({ username, password, goHome: false, mode: 'none' });
45   - if (res) {
46   - this.resetLockInfo();
47   - }
48   - return res;
49   - } catch (error) {
50   - return false;
  13 +export const useLockStore = defineStore({
  14 + id: 'app-lock',
  15 + state: (): LockState => ({
  16 + lockInfo: Persistent.getLocal(LOCK_INFO_KEY),
  17 + }),
  18 + getters: {
  19 + getLockInfo() {
  20 + return this.lockInfo;
  21 + },
  22 + },
  23 + actions: {
  24 + setLockInfo(info: LockInfo) {
  25 + this.lockInfo = Object.assign({}, this.lockInfo, info);
  26 + Persistent.setLocal(LOCK_INFO_KEY, this.lockInfo);
  27 + },
  28 + resetLockInfo() {
  29 + Persistent.removeLocal(LOCK_INFO_KEY);
  30 + this.lockInfo = null;
  31 + },
  32 + // Unlock
  33 + async unLock(password?: string) {
  34 + const userStore = useUserStore();
  35 + if (this.lockInfo?.pwd === password) {
  36 + this.resetLockInfo();
  37 + return true;
51 38 }
52   - };
53   -
54   - if (this.getLockInfo?.pwd === password) {
55   - this.resetLockInfo();
56   - return true;
57   - }
58   - return await tryLogin();
59   - }
60   -}
61   -export const lockStore = getModule<Lock>(Lock);
  39 + const tryLogin = async () => {
  40 + try {
  41 + const username = userStore.getUserInfo?.username;
  42 + const res = await userStore.login({
  43 + username,
  44 + password: password!,
  45 + goHome: false,
  46 + mode: 'none',
  47 + });
  48 + if (res) {
  49 + this.resetLockInfo();
  50 + }
  51 + return res;
  52 + } catch (error) {
  53 + return false;
  54 + }
  55 + };
  56 + return await tryLogin();
  57 + },
  58 + },
  59 +});
... ...
src/store/modules/multipleTab.ts 0 โ†’ 100644
  1 +import type { RouteLocationNormalized, RouteLocationRaw, Router } from 'vue-router';
  2 +
  3 +import { toRaw, unref } from 'vue';
  4 +import { defineStore } from 'pinia';
  5 +import { store } from '/@/store';
  6 +
  7 +import { useGo, useRedo } from '/@/hooks/web/usePage';
  8 +
  9 +import { PageEnum } from '/@/enums/pageEnum';
  10 +import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '/@/router/routes/basic';
  11 +import { getRawRoute } from '/@/utils';
  12 +
  13 +export interface MultipleTabState {
  14 + cacheTabList: Set<string>;
  15 + tabList: RouteLocationNormalized[];
  16 + lastDragEndIndex: number;
  17 +}
  18 +
  19 +function handleGotoPage(router: Router) {
  20 + const go = useGo(router);
  21 + go(unref(router.currentRoute).path, true);
  22 +}
  23 +
  24 +export const useMultipleTabStore = defineStore({
  25 + id: 'app-multiple-tab',
  26 + state: (): MultipleTabState => ({
  27 + // Tabs that need to be cached
  28 + cacheTabList: new Set(),
  29 + // multiple tab list
  30 + tabList: [],
  31 + // Index of the last moved tab
  32 + lastDragEndIndex: 0,
  33 + }),
  34 + getters: {
  35 + getTabList() {
  36 + return this.tabList;
  37 + },
  38 + getCachedTabList(): string[] {
  39 + return Array.from(this.cacheTabList);
  40 + },
  41 + getLastDragEndIndex(): number {
  42 + return this.lastDragEndIndex;
  43 + },
  44 + },
  45 + actions: {
  46 + /**
  47 + * Update the cache according to the currently opened tabs
  48 + */
  49 + async updateCacheTab() {
  50 + const cacheMap: Set<string> = new Set();
  51 +
  52 + for (const tab of this.tabList) {
  53 + const item = getRawRoute(tab);
  54 + // Ignore the cache
  55 + const needCache = !item.meta?.ignoreKeepAlive;
  56 + if (!needCache) {
  57 + return;
  58 + }
  59 + const name = item.name as string;
  60 + cacheMap.add(name);
  61 + }
  62 + this.cacheTabList = cacheMap;
  63 + },
  64 +
  65 + /**
  66 + * Refresh tabs
  67 + */
  68 + async refreshPage(router: Router) {
  69 + const { currentRoute } = router;
  70 + const route = unref(currentRoute);
  71 + const name = route.name;
  72 +
  73 + const findTab = this.getCachedTabList.find((item) => item === name);
  74 + if (findTab) {
  75 + this.cacheTabList.delete(findTab);
  76 + }
  77 + const redo = useRedo(router);
  78 + await redo();
  79 + },
  80 + clearCacheTabs(): void {
  81 + this.cacheTabList = new Set();
  82 + },
  83 + resetState(): void {
  84 + this.tabList = [];
  85 + this.clearCacheTabs();
  86 + },
  87 + goToPage(router: Router) {
  88 + const go = useGo(router);
  89 + const len = this.tabList.length;
  90 + const { path } = unref(router.currentRoute);
  91 +
  92 + let toPath: PageEnum | string = PageEnum.BASE_HOME;
  93 +
  94 + if (len > 0) {
  95 + const page = this.tabList[len - 1];
  96 + const p = page.fullPath || page.path;
  97 + if (p) {
  98 + toPath = p;
  99 + }
  100 + }
  101 + // Jump to the current page and report an error
  102 + path !== toPath && go(toPath as PageEnum, true);
  103 + },
  104 +
  105 + async addTab(route: RouteLocationNormalized) {
  106 + const { path, name, fullPath, params, query } = getRawRoute(route);
  107 + // 404 The page does not need to add a tab
  108 + if (
  109 + path === PageEnum.ERROR_PAGE ||
  110 + !name ||
  111 + [REDIRECT_ROUTE.name, PAGE_NOT_FOUND_ROUTE.name].includes(name as string)
  112 + ) {
  113 + return;
  114 + }
  115 +
  116 + let updateIndex = -1;
  117 + // Existing pages, do not add tabs repeatedly
  118 + const tabHasExits = this.tabList.some((tab, index) => {
  119 + updateIndex = index;
  120 + return (tab.fullPath || tab.path) === (fullPath || path);
  121 + });
  122 +
  123 + // If the tab already exists, perform the update operation
  124 + if (tabHasExits) {
  125 + const curTab = toRaw(this.tabList)[updateIndex];
  126 + if (!curTab) {
  127 + return;
  128 + }
  129 + curTab.params = params || curTab.params;
  130 + curTab.query = query || curTab.query;
  131 + curTab.fullPath = fullPath || curTab.fullPath;
  132 + this.tabList.splice(updateIndex, 1, curTab);
  133 + return;
  134 + }
  135 + // Add tab
  136 + this.tabList.push(route);
  137 + this.updateCacheTab();
  138 + },
  139 +
  140 + async closeTab(tab: RouteLocationNormalized, router: Router) {
  141 + const getToTarget = (tabItem: RouteLocationNormalized) => {
  142 + const { params, path, query } = tabItem;
  143 + return {
  144 + params: params || {},
  145 + path,
  146 + query: query || {},
  147 + };
  148 + };
  149 +
  150 + const close = (route: RouteLocationNormalized) => {
  151 + const { fullPath, meta: { affix } = {} } = route;
  152 + if (affix) {
  153 + return;
  154 + }
  155 + const index = this.tabList.findIndex((item) => item.fullPath === fullPath);
  156 + index !== -1 && this.tabList.splice(index, 1);
  157 + };
  158 +
  159 + const { currentRoute, replace } = router;
  160 +
  161 + const { path } = unref(currentRoute);
  162 + if (path !== tab.path) {
  163 + // Closed is not the activation tab
  164 + close(tab);
  165 + return;
  166 + }
  167 +
  168 + // Closed is activated atb
  169 + let toTarget: RouteLocationRaw = {};
  170 +
  171 + const index = this.tabList.findIndex((item) => item.path === path);
  172 +
  173 + // If the current is the leftmost tab
  174 + if (index === 0) {
  175 + // There is only one tab, then jump to the homepage, otherwise jump to the right tab
  176 + if (this.tabList.length === 1) {
  177 + toTarget = PageEnum.BASE_HOME;
  178 + } else {
  179 + // Jump to the right tab
  180 + const page = this.tabList[index + 1];
  181 + toTarget = getToTarget(page);
  182 + }
  183 + } else {
  184 + // Close the current tab
  185 + const page = this.tabList[index - 1];
  186 + toTarget = getToTarget(page);
  187 + }
  188 + close(currentRoute.value);
  189 + replace(toTarget);
  190 + },
  191 +
  192 + // Close according to key
  193 + async closeTabByKey(key: string, router: Router) {
  194 + const index = this.tabList.findIndex((item) => (item.fullPath || item.path) === key);
  195 + index !== -1 && this.closeTab(this.tabList[index], router);
  196 + },
  197 +
  198 + // Sort the tabs
  199 + async sortTabs(oldIndex: number, newIndex: number) {
  200 + const currentTab = this.tabList[oldIndex];
  201 + this.tabList.splice(oldIndex, 1);
  202 + this.tabList.splice(newIndex, 0, currentTab);
  203 + this.lastDragEndIndex = this.lastDragEndIndex + 1;
  204 + },
  205 +
  206 + // Close the tab on the right and jump
  207 + async closeLeftTabs(route: RouteLocationNormalized, router: Router) {
  208 + const index = this.tabList.findIndex((item) => item.path === route.path);
  209 +
  210 + if (index > 0) {
  211 + const leftTabs = this.tabList.slice(0, index);
  212 + const pathList: string[] = [];
  213 + for (const item of leftTabs) {
  214 + const affix = item?.meta?.affix ?? false;
  215 + if (!affix) {
  216 + pathList.push(item.fullPath);
  217 + }
  218 + }
  219 + this.bulkCloseTabs(pathList);
  220 + }
  221 + this.updateCacheTab();
  222 + handleGotoPage(router);
  223 + },
  224 +
  225 + // Close the tab on the left and jump
  226 + async closeRightTabs(route: RouteLocationNormalized, router: Router) {
  227 + const index = this.tabList.findIndex((item) => item.fullPath === route.fullPath);
  228 +
  229 + if (index >= 0 && index < this.tabList.length - 1) {
  230 + const rightTabs = this.tabList.slice(index + 1, this.tabList.length);
  231 +
  232 + const pathList: string[] = [];
  233 + for (const item of rightTabs) {
  234 + const affix = item?.meta?.affix ?? false;
  235 + if (!affix) {
  236 + pathList.push(item.fullPath);
  237 + }
  238 + }
  239 + this.bulkCloseTabs(pathList);
  240 + }
  241 + this.updateCacheTab();
  242 + handleGotoPage(router);
  243 + },
  244 +
  245 + async closeAllTab(router: Router) {
  246 + this.tabList = this.tabList.filter((item) => item?.meta?.affix ?? false);
  247 + this.clearCacheTabs();
  248 + this.goToPage(router);
  249 + },
  250 +
  251 + /**
  252 + * Close other tabs
  253 + */
  254 + async closeOtherTabs(route: RouteLocationNormalized, router: Router) {
  255 + const closePathList = this.tabList.map((item) => item.fullPath);
  256 +
  257 + const pathList: string[] = [];
  258 +
  259 + for (const path of closePathList) {
  260 + if (path !== route.fullPath) {
  261 + const closeItem = this.tabList.find((item) => item.path === path);
  262 + if (!closeItem) {
  263 + return;
  264 + }
  265 + const affix = closeItem?.meta?.affix ?? false;
  266 + if (!affix) {
  267 + pathList.push(closeItem.fullPath);
  268 + }
  269 + }
  270 + }
  271 + this.bulkCloseTabs(pathList);
  272 + this.updateCacheTab();
  273 + handleGotoPage(router);
  274 + },
  275 +
  276 + /**
  277 + * Close tabs in bulk
  278 + */
  279 + async bulkCloseTabs(pathList: string[]) {
  280 + this.tabList = this.tabList.filter((item) => !pathList.includes(item.fullPath));
  281 + },
  282 + },
  283 +});
  284 +
  285 +// Need to be used outside the setup
  286 +export function useMultipleTabWithOutStore() {
  287 + return useMultipleTabStore(store);
  288 +}
... ...
src/store/modules/permission.ts
1 1 import type { AppRouteRecordRaw, Menu } from '/@/router/types';
2 2  
3   -import store from '/@/store';
  3 +import { defineStore } from 'pinia';
  4 +import { store } from '/@/store';
  5 +import { useI18n } from '/@/hooks/web/useI18n';
  6 +import { useUserStore } from './user';
  7 +import { useAppStoreWidthOut } from './app';
4 8 import { toRaw } from 'vue';
5   -import { VuexModule, Mutation, Module, getModule, Action } from 'vuex-module-decorators';
  9 +import { transformObjToRoute, flatMultiLevelRoutes } from '/@/router/helper/routeHelper';
  10 +import { transformRouteToMenu } from '/@/router/helper/menuHelper';
6 11  
7   -import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper';
  12 +import projectSetting from '/@/settings/projectSetting';
8 13  
9 14 import { PermissionModeEnum } from '/@/enums/appEnum';
10 15  
11   -import { appStore } from '/@/store/modules/app';
12   -import { userStore } from '/@/store/modules/user';
13   -import projectSetting from '/@/settings/projectSetting';
14   -
15 16 import { asyncRoutes } from '/@/router/routes';
16 17 import { ERROR_LOG_ROUTE, PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic';
17   -import { transformObjToRoute, flatMultiLevelRoutes } from '/@/router/helper/routeHelper';
18   -import { transformRouteToMenu } from '/@/router/helper/menuHelper';
19 18  
20 19 import { filter } from '/@/utils/helper/treeHelper';
21 20  
... ... @@ -23,125 +22,127 @@ import { getMenuListById } from &#39;/@/api/sys/menu&#39;;
23 22 import { getPermCodeByUserId } from '/@/api/sys/user';
24 23  
25 24 import { useMessage } from '/@/hooks/web/useMessage';
26   -import { useI18n } from '/@/hooks/web/useI18n';
27 25  
28   -const NAME = 'app-permission';
29   -hotModuleUnregisterModule(NAME);
30   -@Module({ dynamic: true, namespaced: true, store, name: NAME })
31   -class Permission extends VuexModule {
  26 +interface PermissionState {
32 27 // Permission code list
33   - private permCodeListState: string[] = [];
34   -
  28 + permCodeList: string[];
35 29 // Whether the route has been dynamically added
36   - private isDynamicAddedRouteState = false;
37   -
  30 + isDynamicAddedRoute: boolean;
38 31 // To trigger a menu update
39   - private lastBuildMenuTimeState = 0;
40   -
  32 + lastBuildMenuTime: number;
41 33 // Backstage menu list
42   - private backMenuListState: Menu[] = [];
43   -
44   - get getPermCodeListState() {
45   - return this.permCodeListState;
46   - }
47   -
48   - get getBackMenuListState() {
49   - return this.backMenuListState;
50   - }
51   -
52   - get getLastBuildMenuTimeState() {
53   - return this.lastBuildMenuTimeState;
54   - }
55   -
56   - get getIsDynamicAddedRouteState() {
57   - return this.isDynamicAddedRouteState;
58   - }
59   -
60   - @Mutation
61   - commitPermCodeListState(codeList: string[]): void {
62   - this.permCodeListState = codeList;
63   - }
64   -
65   - @Mutation
66   - commitBackMenuListState(list: Menu[]): void {
67   - this.backMenuListState = list;
68   - }
69   -
70   - @Mutation
71   - commitLastBuildMenuTimeState(): void {
72   - this.lastBuildMenuTimeState = new Date().getTime();
73   - }
74   -
75   - @Mutation
76   - commitDynamicAddedRouteState(added: boolean): void {
77   - this.isDynamicAddedRouteState = added;
78   - }
79   -
80   - @Mutation
81   - commitResetState(): void {
82   - this.isDynamicAddedRouteState = false;
83   - this.permCodeListState = [];
84   - this.backMenuListState = [];
85   - this.lastBuildMenuTimeState = 0;
86   - }
87   -
88   - @Action
89   - async changePermissionCode(userId: string) {
90   - const codeList = await getPermCodeByUserId({ userId });
91   - this.commitPermCodeListState(codeList);
92   - }
93   -
94   - @Action
95   - async buildRoutesAction(id?: number | string): Promise<AppRouteRecordRaw[]> {
96   - const { t } = useI18n();
97   - let routes: AppRouteRecordRaw[] = [];
98   - const roleList = toRaw(userStore.getRoleListState);
99   - const { permissionMode = projectSetting.permissionMode } = appStore.getProjectConfig;
100   - // role permissions
101   - if (permissionMode === PermissionModeEnum.ROLE) {
102   - const routeFilter = (route: AppRouteRecordRaw) => {
103   - const { meta } = route;
104   - const { roles } = meta || {};
105   - if (!roles) return true;
106   - return roleList.some((role) => roles.includes(role));
107   - };
108   - routes = filter(asyncRoutes, routeFilter);
109   - routes = routes.filter(routeFilter);
110   - // Convert multi-level routing to level 2 routing
111   - routes = flatMultiLevelRoutes(routes);
112   - // If you are sure that you do not need to do background dynamic permissions, please comment the entire judgment below
113   - } else if (permissionMode === PermissionModeEnum.BACK) {
114   - const { createMessage } = useMessage();
115   -
116   - createMessage.loading({
117   - content: t('sys.app.menuLoading'),
118   - duration: 1,
119   - });
120   - // Here to get the background routing menu logic to modify by yourself
121   - const paramId = id || userStore.getUserInfoState.userId;
122   -
123   - // !Simulate to obtain permission codes from the background,
124   - // this function may only need to be executed once, and the actual project can be put at the right time by itself
125   - try {
126   - this.changePermissionCode('1');
127   - } catch (error) {}
128   - if (!paramId) {
129   - throw new Error('paramId is undefined!');
  34 + backMenuList: Menu[];
  35 +}
  36 +export const usePermissionStore = defineStore({
  37 + id: 'app-permission',
  38 + state: (): PermissionState => ({
  39 + permCodeList: [],
  40 + // Whether the route has been dynamically added
  41 + isDynamicAddedRoute: false,
  42 + // To trigger a menu update
  43 + lastBuildMenuTime: 0,
  44 + // Backstage menu list
  45 + backMenuList: [],
  46 + }),
  47 + getters: {
  48 + getPermCodeList() {
  49 + return this.permCodeList;
  50 + },
  51 + getBackMenuList() {
  52 + return this.backMenuList;
  53 + },
  54 + getLastBuildMenuTime() {
  55 + return this.lastBuildMenuTime;
  56 + },
  57 + getIsDynamicAddedRoute() {
  58 + return this.isDynamicAddedRoute;
  59 + },
  60 + },
  61 + actions: {
  62 + setPermCodeList(codeList: string[]) {
  63 + this.permCodeList = codeList;
  64 + },
  65 +
  66 + setBackMenuList(list: Menu[]) {
  67 + this.backMenuList = list;
  68 + },
  69 +
  70 + setLastBuildMenuTime() {
  71 + this.lastBuildMenuTime = new Date().getTime();
  72 + },
  73 +
  74 + setDynamicAddedRoute(added: boolean) {
  75 + this.isDynamicAddedRoute = added;
  76 + },
  77 + resetState(): void {
  78 + this.isDynamicAddedRoute = false;
  79 + this.permCodeList = [];
  80 + this.backMenuList = [];
  81 + this.lastBuildMenuTime = 0;
  82 + },
  83 + async changePermissionCode(userId: string) {
  84 + const codeList = await getPermCodeByUserId({ userId });
  85 + this.setPermCodeList(codeList);
  86 + },
  87 + async buildRoutesAction(id?: number | string): Promise<AppRouteRecordRaw[]> {
  88 + const { t } = useI18n();
  89 + const userStore = useUserStore();
  90 + const appStore = useAppStoreWidthOut();
  91 +
  92 + let routes: AppRouteRecordRaw[] = [];
  93 + const roleList = toRaw(userStore.getRoleList);
  94 + const { permissionMode = projectSetting.permissionMode } = appStore.getProjectConfig;
  95 + // role permissions
  96 + if (permissionMode === PermissionModeEnum.ROLE) {
  97 + const routeFilter = (route: AppRouteRecordRaw) => {
  98 + const { meta } = route;
  99 + const { roles } = meta || {};
  100 + if (!roles) return true;
  101 + return roleList.some((role) => roles.includes(role));
  102 + };
  103 + routes = filter(asyncRoutes, routeFilter);
  104 + routes = routes.filter(routeFilter);
  105 + // Convert multi-level routing to level 2 routing
  106 + routes = flatMultiLevelRoutes(routes);
  107 + // If you are sure that you do not need to do background dynamic permissions, please comment the entire judgment below
  108 + } else if (permissionMode === PermissionModeEnum.BACK) {
  109 + const { createMessage } = useMessage();
  110 +
  111 + createMessage.loading({
  112 + content: t('sys.app.menuLoading'),
  113 + duration: 1,
  114 + });
  115 + // Here to get the background routing menu logic to modify by yourself
  116 + const paramId = id || userStore.getUserInfo?.userId;
  117 +
  118 + // !Simulate to obtain permission codes from the background,
  119 + // this function may only need to be executed once, and the actual project can be put at the right time by itself
  120 + try {
  121 + this.changePermissionCode('1');
  122 + } catch (error) {}
  123 +
  124 + if (!paramId) {
  125 + throw new Error('paramId is undefined!');
  126 + }
  127 + let routeList = (await getMenuListById({ id: paramId })) as AppRouteRecordRaw[];
  128 +
  129 + // Dynamically introduce components
  130 + routeList = transformObjToRoute(routeList);
  131 +
  132 + // Background routing to menu structure
  133 + const backMenuList = transformRouteToMenu(routeList);
  134 + this.setBackMenuList(backMenuList);
  135 +
  136 + routeList = flatMultiLevelRoutes(routeList);
  137 + routes = [PAGE_NOT_FOUND_ROUTE, ...routeList];
130 138 }
131   - let routeList = (await getMenuListById({ id: paramId })) as AppRouteRecordRaw[];
132   -
133   - // Dynamically introduce components
134   - routeList = transformObjToRoute(routeList);
135   -
136   - // Background routing to menu structure
137   - const backMenuList = transformRouteToMenu(routeList);
138   - this.commitBackMenuListState(backMenuList);
139   -
140   - routeList = flatMultiLevelRoutes(routeList);
141   - routes = [PAGE_NOT_FOUND_ROUTE, ...routeList];
142   - }
143   - routes.push(ERROR_LOG_ROUTE);
144   - return routes;
145   - }
  139 + routes.push(ERROR_LOG_ROUTE);
  140 + return routes;
  141 + },
  142 + },
  143 +});
  144 +
  145 +// Need to be used outside the setup
  146 +export function usePermissionStoreWidthOut() {
  147 + return usePermissionStore(store);
146 148 }
147   -export const permissionStore = getModule<Permission>(Permission);
... ...
src/store/modules/tab.ts deleted 100644 โ†’ 0
1   -import type { RouteLocationNormalized, RouteLocationRaw } from 'vue-router';
2   -
3   -import { toRaw, unref } from 'vue';
4   -import { Action, Module, Mutation, VuexModule, getModule } from 'vuex-module-decorators';
5   -import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper';
6   -
7   -import { PageEnum } from '/@/enums/pageEnum';
8   -
9   -import store from '/@/store';
10   -import router from '/@/router';
11   -import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '/@/router/routes/basic';
12   -import { getRawRoute } from '/@/utils';
13   -
14   -import { useGo, useRedo } from '/@/hooks/web/usePage';
15   -import { cloneDeep } from 'lodash-es';
16   -
17   -const NAME = 'app-tab';
18   -
19   -hotModuleUnregisterModule(NAME);
20   -
21   -function isGotoPage() {
22   - const go = useGo();
23   - go(unref(router.currentRoute).path, true);
24   -}
25   -
26   -@Module({ namespaced: true, name: NAME, dynamic: true, store })
27   -class Tab extends VuexModule {
28   - cachedTabsState: Set<string> = new Set();
29   -
30   - // tab list
31   - tabsState: RouteLocationNormalized[] = [];
32   -
33   - lastDragEndIndexState = 0;
34   -
35   - get getTabsState() {
36   - return this.tabsState;
37   - }
38   -
39   - get getCurrentTab(): RouteLocationNormalized {
40   - const route = unref(router.currentRoute);
41   - return this.tabsState.find((item) => item.path === route.path)!;
42   - }
43   -
44   - get getCachedTabsState(): string[] {
45   - return Array.from(this.cachedTabsState);
46   - }
47   -
48   - get getLastDragEndIndexState(): number {
49   - return this.lastDragEndIndexState;
50   - }
51   -
52   - @Mutation
53   - commitClearCache(): void {
54   - this.cachedTabsState = new Set();
55   - }
56   -
57   - @Mutation
58   - goToPage() {
59   - const go = useGo();
60   - const len = this.tabsState.length;
61   - const { path } = unref(router.currentRoute);
62   -
63   - let toPath: PageEnum | string = PageEnum.BASE_HOME;
64   -
65   - if (len > 0) {
66   - const page = this.tabsState[len - 1];
67   - const p = page.fullPath || page.path;
68   - if (p) {
69   - toPath = p;
70   - }
71   - }
72   - // Jump to the current page and report an error
73   - path !== toPath && go(toPath as PageEnum, true);
74   - }
75   -
76   - @Mutation
77   - commitCachedMapState(): void {
78   - const cacheMap: Set<string> = new Set();
79   -
80   - this.tabsState.forEach((tab) => {
81   - const item = getRawRoute(tab);
82   - const needCache = !item.meta?.ignoreKeepAlive;
83   - if (!needCache) return;
84   - const name = item.name as string;
85   - cacheMap.add(name);
86   - });
87   - this.cachedTabsState = cacheMap;
88   - }
89   -
90   - @Mutation
91   - commitTabRoutesState(route: RouteLocationNormalized) {
92   - const { path, fullPath, params, query } = route;
93   -
94   - let updateIndex = -1;
95   - // Existing pages, do not add tabs repeatedly
96   - const hasTab = this.tabsState.some((tab, index) => {
97   - updateIndex = index;
98   - return (tab.fullPath || tab.path) === (fullPath || path);
99   - });
100   - if (hasTab) {
101   - const curTab = toRaw(this.tabsState)[updateIndex];
102   - if (!curTab) return;
103   - curTab.params = params || curTab.params;
104   - curTab.query = query || curTab.query;
105   - curTab.fullPath = fullPath || curTab.fullPath;
106   - this.tabsState.splice(updateIndex, 1, curTab);
107   - return;
108   - }
109   - this.tabsState = cloneDeep([...this.tabsState, route]);
110   - }
111   -
112   - /**
113   - * @description: close tab
114   - */
115   - @Mutation
116   - commitCloseTab(route: RouteLocationNormalized): void {
117   - const { fullPath, meta: { affix } = {} } = route;
118   - if (affix) return;
119   - const index = this.tabsState.findIndex((item) => item.fullPath === fullPath);
120   - index !== -1 && this.tabsState.splice(index, 1);
121   - }
122   -
123   - @Mutation
124   - commitCloseAllTab(): void {
125   - this.tabsState = this.tabsState.filter((item) => {
126   - return item.meta && item.meta.affix;
127   - });
128   - }
129   -
130   - @Mutation
131   - commitResetState(): void {
132   - this.tabsState = [];
133   - this.cachedTabsState = new Set();
134   - }
135   -
136   - @Mutation
137   - commitSortTabs({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }): void {
138   - const currentTab = this.tabsState[oldIndex];
139   -
140   - this.tabsState.splice(oldIndex, 1);
141   - this.tabsState.splice(newIndex, 0, currentTab);
142   - this.lastDragEndIndexState = this.lastDragEndIndexState + 1;
143   - }
144   -
145   - @Mutation
146   - closeMultipleTab({ pathList }: { pathList: string[] }): void {
147   - this.tabsState = toRaw(this.tabsState).filter((item) => !pathList.includes(item.fullPath));
148   - }
149   -
150   - @Action
151   - addTabAction(route: RouteLocationNormalized) {
152   - const { path, name } = route;
153   - // 404 The page does not need to add a tab
154   - if (
155   - path === PageEnum.ERROR_PAGE ||
156   - !name ||
157   - [REDIRECT_ROUTE.name, PAGE_NOT_FOUND_ROUTE.name].includes(name as string)
158   - ) {
159   - return;
160   - }
161   - this.commitTabRoutesState(getRawRoute(route));
162   -
163   - this.commitCachedMapState();
164   - }
165   -
166   - @Mutation
167   - async commitRedoPage() {
168   - const route = router.currentRoute.value;
169   - const name = route.name;
170   -
171   - const findVal = Array.from(this.cachedTabsState).find((item) => item === name);
172   - if (findVal) {
173   - this.cachedTabsState.delete(findVal);
174   - // this.cachedTabsState.splice(index, 1);
175   - }
176   - const redo = useRedo();
177   - await redo();
178   - }
179   -
180   - @Action
181   - closeAllTabAction() {
182   - this.commitCloseAllTab();
183   - this.commitClearCache();
184   - this.goToPage();
185   - }
186   -
187   - @Action
188   - closeTabAction(tab: RouteLocationNormalized) {
189   - function getObj(tabItem: RouteLocationNormalized) {
190   - const { params, path, query } = tabItem;
191   - return {
192   - params: params || {},
193   - path,
194   - query: query || {},
195   - };
196   - }
197   - const { currentRoute, replace } = router;
198   -
199   - const { path } = unref(currentRoute);
200   - if (path !== tab.path) {
201   - // Closed is not the activation tab
202   - this.commitCloseTab(tab);
203   - return;
204   - }
205   -
206   - // Closed is activated atb
207   - let toObj: RouteLocationRaw = {};
208   -
209   - const index = this.getTabsState.findIndex((item) => item.path === path);
210   -
211   - // If the current is the leftmost tab
212   - if (index === 0) {
213   - // There is only one tab, then jump to the homepage, otherwise jump to the right tab
214   - if (this.getTabsState.length === 1) {
215   - toObj = PageEnum.BASE_HOME;
216   - } else {
217   - // Jump to the right tab
218   - const page = this.getTabsState[index + 1];
219   - toObj = getObj(page);
220   - }
221   - } else {
222   - // Close the current tab
223   - const page = this.getTabsState[index - 1];
224   - toObj = getObj(page);
225   - }
226   - this.commitCloseTab(currentRoute.value);
227   - replace(toObj);
228   - }
229   -
230   - @Action
231   - closeTabByKeyAction(key: string) {
232   - const index = this.tabsState.findIndex((item) => (item.fullPath || item.path) === key);
233   - index !== -1 && this.closeTabAction(this.tabsState[index]);
234   - }
235   -
236   - @Action
237   - closeLeftTabAction(route: RouteLocationNormalized): void {
238   - const index = this.tabsState.findIndex((item) => item.path === route.path);
239   -
240   - if (index > 0) {
241   - const leftTabs = this.tabsState.slice(0, index);
242   - const pathList: string[] = [];
243   - for (const item of leftTabs) {
244   - const affix = item.meta ? item.meta.affix : false;
245   - if (!affix) {
246   - pathList.push(item.fullPath);
247   - }
248   - }
249   - this.closeMultipleTab({ pathList });
250   - }
251   - this.commitCachedMapState();
252   - isGotoPage();
253   - }
254   -
255   - @Action
256   - closeRightTabAction(route: RouteLocationNormalized): void {
257   - const index = this.tabsState.findIndex((item) => item.fullPath === route.fullPath);
258   -
259   - if (index >= 0 && index < this.tabsState.length - 1) {
260   - const rightTabs = this.tabsState.slice(index + 1, this.tabsState.length);
261   -
262   - const pathList: string[] = [];
263   - for (const item of rightTabs) {
264   - const affix = item.meta ? item.meta.affix : false;
265   - if (!affix) {
266   - pathList.push(item.fullPath);
267   - }
268   - }
269   - this.closeMultipleTab({ pathList });
270   - }
271   - this.commitCachedMapState();
272   - isGotoPage();
273   - }
274   -
275   - @Action
276   - closeOtherTabAction(route: RouteLocationNormalized): void {
277   - const closePathList = this.tabsState.map((item) => item.fullPath);
278   - const pathList: string[] = [];
279   - closePathList.forEach((path) => {
280   - if (path !== route.fullPath) {
281   - const closeItem = this.tabsState.find((item) => item.path === path);
282   - if (!closeItem) return;
283   - const affix = closeItem.meta ? closeItem.meta.affix : false;
284   - if (!affix) {
285   - pathList.push(closeItem.fullPath);
286   - }
287   - }
288   - });
289   - this.closeMultipleTab({ pathList });
290   - this.commitCachedMapState();
291   - isGotoPage();
292   - }
293   -}
294   -export const tabStore = getModule<Tab>(Tab);
src/store/modules/user.ts
1   -import type {
2   - LoginParams,
3   - GetUserInfoByUserIdModel,
4   - GetUserInfoByUserIdParams,
5   -} from '/@/api/sys/model/userModel';
6   -import type { UserInfo } from '/@/store/types';
  1 +import type { UserInfo } from '/#/store';
  2 +import type { ErrorMessageMode } from '/@/utils/http/axios/types';
7 3  
8   -import store from '/@/store/index';
9   -import { VuexModule, Module, getModule, Mutation, Action } from 'vuex-module-decorators';
10   -import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper';
  4 +import { defineStore } from 'pinia';
  5 +import { store } from '/@/store';
11 6  
12   -import { PageEnum } from '/@/enums/pageEnum';
13 7 import { RoleEnum } from '/@/enums/roleEnum';
  8 +import { PageEnum } from '/@/enums/pageEnum';
14 9 import { ROLES_KEY, TOKEN_KEY, USER_INFO_KEY } from '/@/enums/cacheEnum';
15 10  
16   -import { useMessage } from '/@/hooks/web/useMessage';
17   -
18   -import router from '/@/router';
  11 +import { getAuthCache, setAuthCache } from '/@/utils/auth';
  12 +import {
  13 + GetUserInfoByUserIdModel,
  14 + GetUserInfoByUserIdParams,
  15 + LoginParams,
  16 +} from '/@/api/sys/model/userModel';
19 17  
20   -import { loginApi, getUserInfoById } from '/@/api/sys/user';
  18 +import { getUserInfoById, loginApi } from '/@/api/sys/user';
21 19  
22 20 import { useI18n } from '/@/hooks/web/useI18n';
23   -import { ErrorMessageMode } from '/@/utils/http/axios/types';
24   -import { getAuthCache, setAuthCache } from '/@/utils/auth/index';
25   -
26   -const NAME = 'app-user';
27   -hotModuleUnregisterModule(NAME);
28   -
29   -@Module({ namespaced: true, name: NAME, dynamic: true, store })
30   -class User extends VuexModule {
31   - // user info
32   - private userInfoState: UserInfo | null = null;
33   -
34   - // token
35   - private tokenState = '';
36   -
37   - // roleList
38   - private roleListState: RoleEnum[] = [];
39   -
40   - get getUserInfoState(): UserInfo {
41   - return this.userInfoState || getAuthCache<UserInfo>(USER_INFO_KEY) || {};
42   - }
43   -
44   - get getTokenState(): string {
45   - return this.tokenState || getAuthCache<string>(TOKEN_KEY);
46   - }
47   -
48   - get getRoleListState(): RoleEnum[] {
49   - return this.roleListState.length > 0 ? this.roleListState : getAuthCache<RoleEnum[]>(ROLES_KEY);
50   - }
51   -
52   - @Mutation
53   - commitResetState(): void {
54   - this.userInfoState = null;
55   - this.tokenState = '';
56   - this.roleListState = [];
57   - }
58   -
59   - @Mutation
60   - commitUserInfoState(info: UserInfo): void {
61   - this.userInfoState = info;
62   - setAuthCache(USER_INFO_KEY, info);
63   - }
64   -
65   - @Mutation
66   - commitRoleListState(roleList: RoleEnum[]): void {
67   - this.roleListState = roleList;
68   - setAuthCache(ROLES_KEY, roleList);
69   - }
70   -
71   - @Mutation
72   - commitTokenState(info: string): void {
73   - this.tokenState = info;
74   - setAuthCache(TOKEN_KEY, info);
75   - }
76   -
77   - /**
78   - * @description: login
79   - */
80   - @Action
81   - async login(
82   - params: LoginParams & {
83   - goHome?: boolean;
84   - mode?: ErrorMessageMode;
85   - }
86   - ): Promise<GetUserInfoByUserIdModel | null> {
87   - try {
88   - const { goHome = true, mode, ...loginParams } = params;
89   - const data = await loginApi(loginParams, mode);
90   -
91   - const { token, userId } = data;
92   -
93   - // save token
94   - this.commitTokenState(token);
  21 +import { useMessage } from '/@/hooks/web/useMessage';
  22 +import router from '/@/router';
95 23  
96   - // get user info
97   - const userInfo = await this.getUserInfoAction({ userId });
  24 +interface UserState {
  25 + userInfo: Nullable<UserInfo>;
  26 + token?: string;
  27 + roleList: RoleEnum[];
  28 +}
98 29  
99   - goHome && (await router.replace(PageEnum.BASE_HOME));
  30 +export const useUserStore = defineStore({
  31 + id: 'app-user',
  32 + state: (): UserState => ({
  33 + // user info
  34 + userInfo: null,
  35 + // token
  36 + token: undefined,
  37 + // roleList
  38 + roleList: [],
  39 + }),
  40 + getters: {
  41 + getUserInfo(): UserInfo {
  42 + return this.userInfo || getAuthCache<UserInfo>(USER_INFO_KEY) || {};
  43 + },
  44 + getToken(): string {
  45 + return this.token || getAuthCache<string>(TOKEN_KEY);
  46 + },
  47 + getRoleList(): RoleEnum[] {
  48 + return this.roleList.length > 0 ? this.roleList : getAuthCache<RoleEnum[]>(ROLES_KEY);
  49 + },
  50 + },
  51 + actions: {
  52 + setToken(info: string) {
  53 + this.token = info;
  54 + setAuthCache(TOKEN_KEY, info);
  55 + },
  56 + setRoleList(roleList: RoleEnum[]) {
  57 + this.roleList = roleList;
  58 + setAuthCache(ROLES_KEY, roleList);
  59 + },
  60 + setUserInfo(info: UserInfo) {
  61 + this.userInfo = info;
  62 + setAuthCache(USER_INFO_KEY, info);
  63 + },
  64 + resetState() {
  65 + this.userInfo = null;
  66 + this.token = '';
  67 + this.roleList = [];
  68 + },
  69 + /**
  70 + * @description: login
  71 + */
  72 + async login(
  73 + params: LoginParams & {
  74 + goHome?: boolean;
  75 + mode?: ErrorMessageMode;
  76 + }
  77 + ): Promise<GetUserInfoByUserIdModel | null> {
  78 + try {
  79 + const { goHome = true, mode, ...loginParams } = params;
  80 + const data = await loginApi(loginParams, mode);
  81 + const { token, userId } = data;
  82 +
  83 + // save token
  84 + this.setToken(token);
  85 + // get user info
  86 + const userInfo = await this.getUserInfoAction({ userId });
  87 +
  88 + goHome && (await router.replace(PageEnum.BASE_HOME));
  89 + return userInfo;
  90 + } catch (error) {
  91 + return null;
  92 + }
  93 + },
  94 + async getUserInfoAction({ userId }: GetUserInfoByUserIdParams) {
  95 + const userInfo = await getUserInfoById({ userId });
  96 + const { roles } = userInfo;
  97 + const roleList = roles.map((item) => item.value) as RoleEnum[];
  98 + this.setUserInfo(userInfo);
  99 + this.setRoleList(roleList);
100 100 return userInfo;
101   - } catch (error) {
102   - return null;
103   - }
104   - }
105   -
106   - @Action
107   - async getUserInfoAction({ userId }: GetUserInfoByUserIdParams) {
108   - const userInfo = await getUserInfoById({ userId });
109   - const { roles } = userInfo;
110   - const roleList = roles.map((item) => item.value) as RoleEnum[];
111   - this.commitUserInfoState(userInfo);
112   - this.commitRoleListState(roleList);
113   - return userInfo;
114   - }
115   -
116   - /**
117   - * @description: logout
118   - */
119   - @Action
120   - async logout(goLogin = false) {
121   - goLogin && router.push(PageEnum.BASE_LOGIN);
122   - }
123   -
124   - /**
125   - * @description: Confirm before logging out
126   - */
127   - @Action
128   - async confirmLoginOut() {
129   - const { createConfirm } = useMessage();
130   - const { t } = useI18n();
131   - createConfirm({
132   - iconType: 'warning',
133   - title: t('sys.app.logoutTip'),
134   - content: t('sys.app.logoutMessage'),
135   - onOk: async () => {
136   - await this.logout(true);
137   - },
138   - });
139   - }
  101 + },
  102 + /**
  103 + * @description: logout
  104 + */
  105 + logout(goLogin = false) {
  106 + goLogin && router.push(PageEnum.BASE_LOGIN);
  107 + },
  108 +
  109 + /**
  110 + * @description: Confirm before logging out
  111 + */
  112 + confirmLoginOut() {
  113 + const { createConfirm } = useMessage();
  114 + const { t } = useI18n();
  115 + createConfirm({
  116 + iconType: 'warning',
  117 + title: t('sys.app.logoutTip'),
  118 + content: t('sys.app.logoutMessage'),
  119 + onOk: async () => {
  120 + await this.logout(true);
  121 + },
  122 + });
  123 + },
  124 + },
  125 +});
  126 +
  127 +// Need to be used outside the setup
  128 +export function useUserStoreWidthOut() {
  129 + return useUserStore(store);
140 130 }
141   -export const userStore = getModule<User>(User);
... ...
src/store/types.ts deleted 100644 โ†’ 0
1   -import { MenuModeEnum, MenuTypeEnum } from '../enums/menuEnum';
2   -
3   -export interface LockInfo {
4   - pwd: string | undefined;
5   - isLock: boolean;
6   -}
7   -
8   -export interface UserInfo {
9   - // ็”จๆˆทid
10   - userId: string | number;
11   - // ็”จๆˆทๅ
12   - username: string;
13   - // ็œŸๅฎžๅๅญ—
14   - realName: string;
15   - // ไป‹็ป
16   - desc?: string;
17   -}
18   -
19   -export interface BeforeMiniState {
20   - menuCollapsed?: boolean;
21   - menuSplit?: boolean;
22   - menuMode?: MenuModeEnum;
23   - menuType?: MenuTypeEnum;
24   -}
src/utils/cache/persistent.ts
1   -import type { LockInfo, UserInfo } from '/@/store/types';
2   -
3   -import { ProjectConfig } from '/#/config';
  1 +import type { LockInfo, UserInfo } from '/#/store';
  2 +import type { ProjectConfig } from '/#/config';
4 3  
5 4 import { createLocalStorage, createSessionStorage } from '/@/utils/cache';
6 5 import { Memory } from './memory';
... ...
src/utils/env.ts
... ... @@ -35,6 +35,7 @@ export function getAppEnvConfig() {
35 35 `VITE_GLOB_APP_SHORT_NAME Variables can only be characters/underscores, please modify in the environment variables and re-running.`
36 36 );
37 37 }
  38 +
38 39 return {
39 40 VITE_GLOB_APP_TITLE,
40 41 VITE_GLOB_API_URL,
... ...
src/utils/http/axios/index.ts
... ... @@ -16,7 +16,8 @@ import { RequestEnum, ResultEnum, ContentTypeEnum } from &#39;/@/enums/httpEnum&#39;;
16 16 import { isString } from '/@/utils/is';
17 17 import { getToken } from '/@/utils/auth';
18 18 import { setObjToUrlParams, deepMerge } from '/@/utils';
19   -import { errorStore } from '/@/store/modules/error';
  19 +import { useErrorLogStoreWithOut } from '/@/store/modules/errorLog';
  20 +
20 21 import { errorResult } from './const';
21 22 import { useI18n } from '/@/hooks/web/useI18n';
22 23 import { createNow, formatRequestDate } from './helper';
... ... @@ -150,7 +151,8 @@ const transform: AxiosTransform = {
150 151 */
151 152 responseInterceptorsCatch: (error: any) => {
152 153 const { t } = useI18n();
153   - errorStore.setupErrorHandle(error);
  154 + const errorLogStore = useErrorLogStoreWithOut();
  155 + errorLogStore.addAjaxErrorInfo(error);
154 156 const { response, code, message } = error || {};
155 157 const msg: string = response?.data?.error?.message ?? '';
156 158 const err: string = error?.toString?.() ?? '';
... ...
src/views/demo/permission/CurrentPermissionMode.vue
... ... @@ -10,7 +10,7 @@
10 10 </template>
11 11 <script lang="ts">
12 12 import { defineComponent, computed } from 'vue';
13   - import { appStore } from '/@/store/modules/app';
  13 + import { useAppStore } from '/@/store/modules/app';
14 14 import { PermissionModeEnum } from '/@/enums/appEnum';
15 15 import { Divider } from 'ant-design-vue';
16 16 import { usePermission } from '/@/hooks/web/usePermission';
... ... @@ -18,9 +18,8 @@
18 18 name: 'CurrentPermissionMode',
19 19 components: { Divider },
20 20 setup() {
21   - const permissionMode = computed(() => {
22   - return appStore.getProjectConfig.permissionMode;
23   - });
  21 + const appStore = useAppStore();
  22 + const permissionMode = computed(() => appStore.getProjectConfig.permissionMode);
24 23 const { togglePermissionMode } = usePermission();
25 24  
26 25 return {
... ...
src/views/demo/permission/back/Btn.vue
... ... @@ -5,7 +5,7 @@
5 5 <CurrentPermissionMode />
6 6  
7 7 <p>
8   - ๅฝ“ๅ‰ๆ‹ฅๆœ‰็š„codeๅˆ—่กจ: <a> {{ permissionStore.getPermCodeListState }} </a>
  8 + ๅฝ“ๅ‰ๆ‹ฅๆœ‰็š„codeๅˆ—่กจ: <a> {{ permissionStore.getPermCodeList }} </a>
9 9 </p>
10 10 <Divider />
11 11 <Alert class="mt-4" type="info" message="็‚นๅ‡ปๅŽ่ฏทๆŸฅ็œ‹ๆŒ‰้’ฎๅ˜ๅŒ–" show-icon />
... ... @@ -59,7 +59,7 @@
59 59 import CurrentPermissionMode from '../CurrentPermissionMode.vue';
60 60 import { usePermission } from '/@/hooks/web/usePermission';
61 61 import { Authority } from '/@/components/Authority';
62   - import { permissionStore } from '/@/store/modules/permission';
  62 + import { usePermissionStore } from '/@/store/modules/permission';
63 63 import { PermissionModeEnum } from '/@/enums/appEnum';
64 64 import { PageWrapper } from '/@/components/Page';
65 65  
... ... @@ -67,6 +67,7 @@
67 67 components: { Alert, PageWrapper, CurrentPermissionMode, Divider, Authority },
68 68 setup() {
69 69 const { hasPermission } = usePermission();
  70 + const permissionStore = usePermissionStore();
70 71  
71 72 function changePermissionCode(userId: string) {
72 73 permissionStore.changePermissionCode(userId);
... ...
src/views/demo/permission/front/Btn.vue
... ... @@ -8,7 +8,7 @@
8 8 <CurrentPermissionMode />
9 9  
10 10 <p>
11   - ๅฝ“ๅ‰่ง’่‰ฒ: <a> {{ userStore.getRoleListState }} </a>
  11 + ๅฝ“ๅ‰่ง’่‰ฒ: <a> {{ userStore.getRoleList }} </a>
12 12 </p>
13 13 <Alert class="mt-4" type="info" message="็‚นๅ‡ปๅŽ่ฏทๆŸฅ็œ‹ๆŒ‰้’ฎๅ˜ๅŒ–" show-icon />
14 14  
... ... @@ -63,7 +63,7 @@
63 63 import { computed, defineComponent } from 'vue';
64 64 import { Alert, Divider } from 'ant-design-vue';
65 65 import CurrentPermissionMode from '../CurrentPermissionMode.vue';
66   - import { userStore } from '/@/store/modules/user';
  66 + import { useUserStore } from '/@/store/modules/user';
67 67 import { RoleEnum } from '/@/enums/roleEnum';
68 68 import { usePermission } from '/@/hooks/web/usePermission';
69 69 import { Authority } from '/@/components/Authority';
... ... @@ -73,11 +73,13 @@
73 73 components: { Alert, PageWrapper, CurrentPermissionMode, Divider, Authority },
74 74 setup() {
75 75 const { changeRole, hasPermission } = usePermission();
  76 + const userStore = useUserStore();
  77 +
76 78 return {
77 79 userStore,
78 80 RoleEnum,
79   - isSuper: computed(() => userStore.getRoleListState.includes(RoleEnum.SUPER)),
80   - isTest: computed(() => userStore.getRoleListState.includes(RoleEnum.TEST)),
  81 + isSuper: computed(() => userStore.getRoleList.includes(RoleEnum.SUPER)),
  82 + isTest: computed(() => userStore.getRoleList.includes(RoleEnum.TEST)),
81 83 changeRole,
82 84 hasPermission,
83 85 };
... ...
src/views/demo/permission/front/index.vue
... ... @@ -8,7 +8,7 @@
8 8 <CurrentPermissionMode />
9 9  
10 10 <p>
11   - ๅฝ“ๅ‰่ง’่‰ฒ: <a> {{ userStore.getRoleListState }} </a>
  11 + ๅฝ“ๅ‰่ง’่‰ฒ: <a> {{ userStore.getRoleList }} </a>
12 12 </p>
13 13 <Alert class="mt-4" type="info" message="็‚นๅ‡ปๅŽ่ฏทๆŸฅ็œ‹ๅทฆไพง่œๅ•ๅ˜ๅŒ–" show-icon />
14 14  
... ... @@ -29,7 +29,7 @@
29 29 import { computed, defineComponent } from 'vue';
30 30 import { Alert } from 'ant-design-vue';
31 31 import CurrentPermissionMode from '../CurrentPermissionMode.vue';
32   - import { userStore } from '/@/store/modules/user';
  32 + import { useUserStore } from '/@/store/modules/user';
33 33 import { RoleEnum } from '/@/enums/roleEnum';
34 34 import { usePermission } from '/@/hooks/web/usePermission';
35 35 import { PageWrapper } from '/@/components/Page';
... ... @@ -38,11 +38,13 @@
38 38 components: { Alert, CurrentPermissionMode, PageWrapper },
39 39 setup() {
40 40 const { changeRole } = usePermission();
  41 + const userStore = useUserStore();
  42 +
41 43 return {
42 44 userStore,
43 45 RoleEnum,
44   - isSuper: computed(() => userStore.getRoleListState.includes(RoleEnum.SUPER)),
45   - isTest: computed(() => userStore.getRoleListState.includes(RoleEnum.TEST)),
  46 + isSuper: computed(() => userStore.getRoleList.includes(RoleEnum.SUPER)),
  47 + isTest: computed(() => userStore.getRoleList.includes(RoleEnum.TEST)),
46 48 changeRole,
47 49 };
48 50 },
... ...
src/views/sys/error-log/DetailModal.vue
... ... @@ -5,6 +5,7 @@
5 5 </template>
6 6 <script lang="ts">
7 7 import type { PropType } from 'vue';
  8 + import type { ErrorLogInfo } from '/#/store';
8 9  
9 10 import { defineComponent } from 'vue';
10 11 import { BasicModal } from '/@/components/Modal/index';
... ... @@ -12,8 +13,6 @@
12 13  
13 14 import { useI18n } from '/@/hooks/web/useI18n';
14 15  
15   - import { ErrorInfo } from '/@/store/modules/error';
16   -
17 16 import { getDescSchema } from './data';
18 17  
19 18 export default defineComponent({
... ... @@ -21,7 +20,7 @@
21 20 components: { BasicModal, Description },
22 21 props: {
23 22 info: {
24   - type: Object as PropType<ErrorInfo>,
  23 + type: Object as PropType<ErrorLogInfo>,
25 24 default: null,
26 25 },
27 26 },
... ... @@ -30,7 +29,7 @@
30 29  
31 30 const [register] = useDescription({
32 31 column: 2,
33   - schema: getDescSchema(),
  32 + schema: getDescSchema()!,
34 33 });
35 34  
36 35 return {
... ...
src/views/sys/error-log/data.tsx
... ... @@ -57,7 +57,7 @@ export function getColumns(): BasicColumn[] {
57 57 ];
58 58 }
59 59  
60   -export function getDescSchema() {
  60 +export function getDescSchema(): any {
61 61 return getColumns().map((column) => {
62 62 return {
63 63 field: column.dataIndex!,
... ...
src/views/sys/error-log/index.vue
... ... @@ -28,6 +28,8 @@
28 28 </template>
29 29  
30 30 <script lang="ts">
  31 + import type { ErrorLogInfo } from '/#/store';
  32 +
31 33 import { defineComponent, watch, ref, nextTick } from 'vue';
32 34  
33 35 import DetailModal from './DetailModal.vue';
... ... @@ -37,7 +39,7 @@
37 39 import { useMessage } from '/@/hooks/web/useMessage';
38 40 import { useI18n } from '/@/hooks/web/useI18n';
39 41  
40   - import { errorStore, ErrorInfo } from '/@/store/modules/error';
  42 + import { useErrorLogStore } from '/@/store/modules/errorLog';
41 43  
42 44 import { fireErrorApi } from '/@/api/demo/error';
43 45  
... ... @@ -49,11 +51,11 @@
49 51 name: 'ErrorHandler',
50 52 components: { DetailModal, BasicTable, TableAction },
51 53 setup() {
52   - const rowInfo = ref<ErrorInfo>();
  54 + const rowInfo = ref<ErrorLogInfo>();
53 55 const imgList = ref<string[]>([]);
54 56  
55 57 const { t } = useI18n();
56   -
  58 + const errorLogStore = useErrorLogStore();
57 59 const [register, { setTableData }] = useTable({
58 60 title: t('sys.errorLog.tableTitle'),
59 61 columns: getColumns(),
... ... @@ -67,7 +69,7 @@
67 69 const [registerModal, { openModal }] = useModal();
68 70  
69 71 watch(
70   - () => errorStore.getErrorInfoState,
  72 + () => errorLogStore.getErrorLogInfoList,
71 73 (list) => {
72 74 nextTick(() => {
73 75 setTableData(cloneDeep(list));
... ... @@ -82,7 +84,7 @@
82 84 createMessage.info(t('sys.errorLog.enableMessage'));
83 85 }
84 86 // ๆŸฅ็œ‹่ฏฆๆƒ…
85   - function handleDetail(row: ErrorInfo) {
  87 + function handleDetail(row: ErrorLogInfo) {
86 88 rowInfo.value = row;
87 89 openModal(true);
88 90 }
... ...
src/views/sys/lock/LockPage.vue
... ... @@ -38,7 +38,7 @@
38 38 class="enter-x"
39 39 v-model:value="password"
40 40 />
41   - <span :class="`${prefixCls}-entry__err-msg enter-x`" v-if="errMsgRef">
  41 + <span :class="`${prefixCls}-entry__err-msg enter-x`" v-if="errMsg">
42 42 {{ t('sys.lock.alert') }}
43 43 </span>
44 44 <div :class="`${prefixCls}-entry__footer enter-x`">
... ... @@ -46,7 +46,7 @@
46 46 type="link"
47 47 size="small"
48 48 class="mt-2 mr-2 enter-x"
49   - :disabled="loadingRef"
  49 + :disabled="loading"
50 50 @click="handleShowForm(true)"
51 51 >
52 52 {{ t('common.back') }}
... ... @@ -55,12 +55,12 @@
55 55 type="link"
56 56 size="small"
57 57 class="mt-2 mr-2 enter-x"
58   - :disabled="loadingRef"
  58 + :disabled="loading"
59 59 @click="goLogin"
60 60 >
61 61 {{ t('sys.lock.backToLogin') }}
62 62 </a-button>
63   - <a-button class="mt-2" type="link" size="small" @click="unLock()" :loading="loadingRef">
  63 + <a-button class="mt-2" type="link" size="small" @click="unLock()" :loading="loading">
64 64 {{ t('sys.lock.entry') }}
65 65 </a-button>
66 66 </div>
... ... @@ -80,8 +80,8 @@
80 80 import { defineComponent, ref, computed } from 'vue';
81 81 import { Input } from 'ant-design-vue';
82 82  
83   - import { userStore } from '/@/store/modules/user';
84   - import { lockStore } from '/@/store/modules/lock';
  83 + import { useUserStore } from '/@/store/modules/user';
  84 + import { useLockStore } from '/@/store/modules/lock';
85 85 import { useI18n } from '/@/hooks/web/useI18n';
86 86  
87 87 import { useNow } from './useNow';
... ... @@ -95,19 +95,21 @@
95 95 components: { LockOutlined, InputPassword: Input.Password },
96 96  
97 97 setup() {
98   - const passwordRef = ref('');
99   - const loadingRef = ref(false);
100   - const errMsgRef = ref(false);
  98 + const password = ref('');
  99 + const loading = ref(false);
  100 + const errMsg = ref(false);
101 101 const showDate = ref(true);
102 102  
103 103 const { prefixCls } = useDesign('lock-page');
  104 + const lockStore = useLockStore();
  105 + const userStore = useUserStore();
104 106  
105 107 const { ...state } = useNow(true);
106 108  
107 109 const { t } = useI18n();
108 110  
109 111 const realName = computed(() => {
110   - const { realName } = userStore.getUserInfoState || {};
  112 + const { realName } = userStore.getUserInfo || {};
111 113 return realName;
112 114 });
113 115  
... ... @@ -115,16 +117,16 @@
115 117 * @description: unLock
116 118 */
117 119 async function unLock() {
118   - if (!passwordRef.value) {
  120 + if (!password.value) {
119 121 return;
120 122 }
121   - let password = passwordRef.value;
  123 + let pwd = password.value;
122 124 try {
123   - loadingRef.value = true;
124   - const res = await lockStore.unLockAction({ password });
125   - errMsgRef.value = !res;
  125 + loading.value = true;
  126 + const res = await lockStore.unLock(pwd);
  127 + errMsg.value = !res;
126 128 } finally {
127   - loadingRef.value = false;
  129 + loading.value = false;
128 130 }
129 131 }
130 132  
... ... @@ -141,12 +143,12 @@
141 143 goLogin,
142 144 realName,
143 145 unLock,
144   - errMsgRef,
145   - loadingRef,
  146 + errMsg,
  147 + loading,
146 148 t,
147 149 prefixCls,
148 150 showDate,
149   - password: passwordRef,
  151 + password,
150 152 handleShowForm,
151 153 headerImg,
152 154 ...state,
... ...
src/views/sys/lock/index.vue
... ... @@ -7,17 +7,13 @@
7 7 import { defineComponent, computed } from 'vue';
8 8 import LockPage from './LockPage.vue';
9 9  
10   - import { lockStore } from '/@/store/modules/lock';
  10 + import { useLockStore } from '/@/store/modules/lock';
11 11 export default defineComponent({
12 12 name: 'Lock',
13 13 components: { LockPage },
14 14 setup() {
15   - const getIsLock = computed(() => {
16   - const { getLockInfo } = lockStore;
17   - const { isLock } = getLockInfo;
18   - return isLock;
19   - });
20   -
  15 + const lockStore = useLockStore();
  16 + const getIsLock = computed(() => lockStore?.getLockInfo?.isLock ?? false);
21 17 return { getIsLock };
22 18 },
23 19 });
... ...
src/views/sys/lock/useNow.ts
1 1 import { dateUtil } from '/@/utils/dateUtil';
2 2 import { reactive, toRefs } from 'vue';
3   -import { localeStore } from '/@/store/modules/locale';
  3 +import { useLocaleStore } from '/@/store/modules/locale';
4 4 import { tryOnMounted, tryOnUnmounted } from '@vueuse/core';
5 5  
6 6 export function useNow(immediate = true) {
  7 + const localeStore = useLocaleStore();
7 8 const localData = dateUtil.localeData(localeStore.getLocale);
8 9 let timer: IntervalHandle;
9 10  
... ...
src/views/sys/login/Login.vue
... ... @@ -58,7 +58,7 @@
58 58 import { useGlobSetting } from '/@/hooks/setting';
59 59 import { useI18n } from '/@/hooks/web/useI18n';
60 60 import { useDesign } from '/@/hooks/web/useDesign';
61   - import { localeStore } from '/@/store/modules/locale';
  61 + import { useLocaleStore } from '/@/store/modules/locale';
62 62  
63 63 export default defineComponent({
64 64 name: 'Login',
... ... @@ -76,6 +76,7 @@
76 76 const globSetting = useGlobSetting();
77 77 const { prefixCls } = useDesign('login');
78 78 const { t } = useI18n();
  79 + const localeStore = useLocaleStore();
79 80  
80 81 return {
81 82 t,
... ...
src/views/sys/login/LoginForm.vue
... ... @@ -85,7 +85,7 @@
85 85 import { useI18n } from '/@/hooks/web/useI18n';
86 86 import { useMessage } from '/@/hooks/web/useMessage';
87 87  
88   - import { userStore } from '/@/store/modules/user';
  88 + import { useUserStore } from '/@/store/modules/user';
89 89 import { LoginStateEnum, useLoginState, useFormRules, useFormValid } from './useLogin';
90 90 import { useDesign } from '/@/hooks/web/useDesign';
91 91 import { useKeyPress } from '/@/hooks/event/useKeyPress';
... ... @@ -114,6 +114,7 @@
114 114 const { t } = useI18n();
115 115 const { notification } = useMessage();
116 116 const { prefixCls } = useDesign('login');
  117 + const userStore = useUserStore();
117 118  
118 119 const { setLoginState, getLoginState } = useLoginState();
119 120 const { getFormRules } = useFormRules();
... ...
types/store.ts 0 โ†’ 100644
  1 +import { ErrorTypeEnum } from '/@/enums/exceptionEnum';
  2 +import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
  3 +
  4 +// Lock screen information
  5 +export interface LockInfo {
  6 + // Password required
  7 + pwd?: string | undefined;
  8 + // Is it locked?
  9 + isLock?: boolean;
  10 +}
  11 +
  12 +// Error-log information
  13 +export interface ErrorLogInfo {
  14 + // Type of error
  15 + type: ErrorTypeEnum;
  16 + // Error file
  17 + file: string;
  18 + // Error name
  19 + name?: string;
  20 + // Error message
  21 + message: string;
  22 + // Error stack
  23 + stack?: string;
  24 + // Error detail
  25 + detail: string;
  26 + // Error url
  27 + url: string;
  28 + // Error time
  29 + time?: string;
  30 +}
  31 +
  32 +export interface UserInfo {
  33 + userId: string | number;
  34 + username: string;
  35 + realName: string;
  36 + desc?: string;
  37 +}
  38 +
  39 +export interface BeforeMiniState {
  40 + menuCollapsed?: boolean;
  41 + menuSplit?: boolean;
  42 + menuMode?: MenuModeEnum;
  43 + menuType?: MenuTypeEnum;
  44 +}
... ...
yarn.lock
... ... @@ -1762,25 +1762,25 @@
1762 1762 resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.0.11.tgz#20d22dd0da7d358bb21c17f9bde8628152642c77"
1763 1763 integrity sha512-b+zB8A2so8eCE0JsxjL24J7vdGl8rzPQ09hZNhystm+KqSbKcAej1A+Hbva1rCMmTTqA+hFnUSDc5kouEo0JzA==
1764 1764  
1765   -"@vueuse/core@^4.8.0":
1766   - version "4.8.0"
1767   - resolved "https://registry.npmjs.org/@vueuse/core/-/core-4.8.0.tgz#d86e36956521c0f9b6571cb58b27f0e2535259b3"
1768   - integrity sha512-nUH4Hn1DN4kkuF1r5ZcfGnjoAKDD0Kw9oFnt/TUo1aueNijq4KujagtoQN8OC4Pei10TeTDdqhmZAWnaCE1NbA==
  1765 +"@vueuse/core@^4.8.1":
  1766 + version "4.8.1"
  1767 + resolved "https://registry.npmjs.org/@vueuse/core/-/core-4.8.1.tgz#d7a7fb2e72610d1962ecb9244bd93dacb96d921c"
  1768 + integrity sha512-oXFEDaKNU69Rj20/Hd7ZlmTpEtA2M19cRkZaL4A0Nl0w5Wb5In/8aK+0vtdi1VyMUXXbq6h1OGKCJcIhg5cziA==
1769 1769 dependencies:
1770   - "@vueuse/shared" "4.8.0"
  1770 + "@vueuse/shared" "4.8.1"
1771 1771 vue-demi latest
1772 1772  
1773   -"@vueuse/shared@4.8.0":
1774   - version "4.8.0"
1775   - resolved "https://registry.npmjs.org/@vueuse/shared/-/shared-4.8.0.tgz#abf3da96ca81b4be82e885928193fef2c676cdbc"
1776   - integrity sha512-g1lSbHD4ptiS74qBUvffJ98QjRsoCH7ILjxVzJF488EPAmp5z3taLnoggt6NXfonnYve7fEPuqsJqd2BLOxT1A==
  1773 +"@vueuse/shared@4.8.1":
  1774 + version "4.8.1"
  1775 + resolved "https://registry.npmjs.org/@vueuse/shared/-/shared-4.8.1.tgz#45fd5f64bf4e8944db42a5b72fa2705cfc74608a"
  1776 + integrity sha512-ONKJoIvZPrGCA8loK7dX+ZcjgZLikI+vPiz1lWlXs6+jZiQiZSLkmvg1NjV6Cfb6OqbDCfEScTWLbZHB7EwrRw==
1777 1777 dependencies:
1778 1778 vue-demi latest
1779 1779  
1780   -"@windicss/plugin-utils@0.12.5":
1781   - version "0.12.5"
1782   - resolved "https://registry.npmjs.org/@windicss/plugin-utils/-/plugin-utils-0.12.5.tgz#d03517d1ae7a48b5b459e3d670e873d38b63e4a1"
1783   - integrity sha512-4ux2o4s6D/gRTD68os41oxs/0NFk/eSJxHhZL9nN2wy4RGt+pPMQJyOHV56l7zDh9B0ywU5+ZRxDjdw2cl5Yvg==
  1780 +"@windicss/plugin-utils@0.13.1":
  1781 + version "0.13.1"
  1782 + resolved "https://registry.npmjs.org/@windicss/plugin-utils/-/plugin-utils-0.13.1.tgz#e0e172855ebcf0b8a5f0f358befdcaf44bae5cf1"
  1783 + integrity sha512-Vr7f7yWxmB5AWwe+iDPV3JbhTlZHbDvM89IfJ0hyP6PqYmZNTtUfMXMbHXZJHVAbQ54dWBMG23WmeC9X327ETA==
1784 1784 dependencies:
1785 1785 debug "^4.3.2"
1786 1786 fast-glob "^3.2.5"
... ... @@ -1788,7 +1788,7 @@
1788 1788 micromatch "^4.0.2"
1789 1789 pirates "^4.0.1"
1790 1790 sucrase "^3.17.1"
1791   - windicss "^2.5.11"
  1791 + windicss "^2.5.12"
1792 1792  
1793 1793 "@zxcvbn-ts/core@^0.3.0":
1794 1794 version "0.3.0"
... ... @@ -3670,21 +3670,11 @@ esbuild-register@^2.2.0:
3670 3670 esbuild "^0.9.2"
3671 3671 jsonc-parser "^3.0.0"
3672 3672  
3673   -esbuild@^0.11.4:
3674   - version "0.11.5"
3675   - resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.11.5.tgz#25b18a2ff2fb9580683edce26a48f64c08c2f2df"
3676   - integrity sha512-aRs6jAE+bVRp1tyfzUugAw1T/Y0Fwzp4Z2ROikF3h+UifoD5QlEbEYQGc6orNnnSIRhWR5VWBH7LozlAumaLHg==
3677   -
3678   -esbuild@^0.11.6:
  3673 +esbuild@^0.11.4, esbuild@^0.11.6, esbuild@^0.9.2, esbuild@^0.9.3:
3679 3674 version "0.11.6"
3680 3675 resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.11.6.tgz#20961309c4cfed00b71027e18806150358d0cbb0"
3681 3676 integrity sha512-L+nKW9ftVS/N2CVJMR9YmXHbkm+vHzlNYuo09rzipQhF7dYNvRLfWoEPSDRTl10and4owFBV9rJ2CTFNtLIOiw==
3682 3677  
3683   -esbuild@^0.9.2, esbuild@^0.9.3:
3684   - version "0.9.7"
3685   - resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.9.7.tgz#ea0d639cbe4b88ec25fbed4d6ff00c8d788ef70b"
3686   - integrity sha512-VtUf6aQ89VTmMLKrWHYG50uByMF4JQlVysb8dmg6cOgW8JnFCipmz7p+HNBl+RR3LLCuBxFGVauAe2wfnF9bLg==
3687   -
3688 3678 escalade@^3.1.1:
3689 3679 version "3.1.1"
3690 3680 resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
... ... @@ -3752,10 +3742,10 @@ eslint-visitor-keys@^2.0.0:
3752 3742 resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
3753 3743 integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
3754 3744  
3755   -eslint@^7.23.0:
3756   - version "7.23.0"
3757   - resolved "https://registry.npmjs.org/eslint/-/eslint-7.23.0.tgz#8d029d252f6e8cf45894b4bee08f5493f8e94325"
3758   - integrity sha512-kqvNVbdkjzpFy0XOszNwjkKzZ+6TcwCQ/h+ozlcIWwaimBBuhlQ4nN6kbiM2L+OjDcznkTJxzYfRFH92sx4a0Q==
  3745 +eslint@^7.24.0:
  3746 + version "7.24.0"
  3747 + resolved "https://registry.npmjs.org/eslint/-/eslint-7.24.0.tgz#2e44fa62d93892bfdb100521f17345ba54b8513a"
  3748 + integrity sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==
3759 3749 dependencies:
3760 3750 "@babel/code-frame" "7.12.11"
3761 3751 "@eslint/eslintrc" "^0.4.0"
... ... @@ -6942,6 +6932,11 @@ pify@^4.0.1:
6942 6932 resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
6943 6933 integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
6944 6934  
  6935 +pinia@^2.0.0-alpha.12:
  6936 + version "2.0.0-alpha.12"
  6937 + resolved "https://registry.npmjs.org/pinia/-/pinia-2.0.0-alpha.12.tgz#690e9a7b4c176bb9d95fe0dc8ec4ab8847b09493"
  6938 + integrity sha512-qmcDpuoAwxQKAVp7/cOkXFYDaja+vyXMWR6kvdyzeJcGGMvZf1HQ2xFhUSW5lf1eW5IiQP0cBRdF3ZDyVa+JIQ==
  6939 +
6945 6940 pinkie-promise@^2.0.0:
6946 6941 version "2.0.1"
6947 6942 resolved "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
... ... @@ -7691,10 +7686,10 @@ rollup-plugin-visualizer@5.3.0:
7691 7686 source-map "^0.7.3"
7692 7687 yargs "^16.2.0"
7693 7688  
7694   -rollup@^2.25.0, rollup@^2.38.5, rollup@^2.44.0:
7695   - version "2.44.0"
7696   - resolved "https://registry.npmjs.org/rollup/-/rollup-2.44.0.tgz#8da324d1c4fd12beef9ae6e12f4068265b6d95eb"
7697   - integrity sha512-rGSF4pLwvuaH/x4nAS+zP6UNn5YUDWf/TeEU5IoXSZKBbKRNTCI3qMnYXKZgrC0D2KzS2baiOZt1OlqhMu5rnQ==
  7689 +rollup@^2.25.0, rollup@^2.38.5, rollup@^2.44.0, rollup@^2.45.1:
  7690 + version "2.45.1"
  7691 + resolved "https://registry.npmjs.org/rollup/-/rollup-2.45.1.tgz#eae2b94dc2088b4e0a3b7197a5a1ee0bdd589d5c"
  7692 + integrity sha512-vPD+JoDj3CY8k6m1bLcAFttXMe78P4CMxoau0iLVS60+S9kLsv2379xaGy4NgYWu+h2WTlucpoLPAoUoixFBag==
7698 7693 optionalDependencies:
7699 7694 fsevents "~2.3.1"
7700 7695  
... ... @@ -9187,15 +9182,15 @@ vite-plugin-theme@^0.6.3:
9187 9182 esbuild-plugin-alias "^0.1.2"
9188 9183 tinycolor2 "^1.4.2"
9189 9184  
9190   -vite-plugin-windicss@0.12.5:
9191   - version "0.12.5"
9192   - resolved "https://registry.npmjs.org/vite-plugin-windicss/-/vite-plugin-windicss-0.12.5.tgz#74a5043db3615fe432855f6ecff13be36f7a6843"
9193   - integrity sha512-M/eEA+x94kxZNpEEkJLdY7M6Lp3WFhN0Kb/a2zhdPxBviMwaHSA5A7fUqN1xTYMxlQe4xM7D7naxL7EpnSNlmg==
  9185 +vite-plugin-windicss@0.13.1:
  9186 + version "0.13.1"
  9187 + resolved "https://registry.npmjs.org/vite-plugin-windicss/-/vite-plugin-windicss-0.13.1.tgz#82a488f3395be710ae2166b83b0612a5eaec7738"
  9188 + integrity sha512-WmFfTLTMSY5gRC3MWX9o72Yni2HRdrtJ2im+cCyZ2W/p4WE6T702zFCScO8Tnz/E08GDx4OH6oFCZWeZYwgxzg==
9194 9189 dependencies:
9195   - "@windicss/plugin-utils" "0.12.5"
  9190 + "@windicss/plugin-utils" "0.13.1"
9196 9191 chalk "^4.1.0"
9197 9192 debug "^4.3.2"
9198   - windicss "^2.5.11"
  9193 + windicss "^2.5.12"
9199 9194  
9200 9195 vite@2.1.5:
9201 9196 version "2.1.5"
... ... @@ -9265,16 +9260,6 @@ vue@^3.0.0:
9265 9260 "@vue/runtime-dom" "3.0.10"
9266 9261 "@vue/shared" "3.0.10"
9267 9262  
9268   -vuex-module-decorators@^1.0.1:
9269   - version "1.0.1"
9270   - resolved "https://registry.npmjs.org/vuex-module-decorators/-/vuex-module-decorators-1.0.1.tgz#d34dafb5428a3636f1c26d3d014c15fc9659ccd0"
9271   - integrity sha512-FLWZsXV5XAtl/bcKUyQFpnSBtpc3wK/7zSdy9oKbyp71mZd4ut5y2zSd219wWW9OG7WUOlVwac4rXFFDVnq7ug==
9272   -
9273   -vuex@^4.0.0:
9274   - version "4.0.0"
9275   - resolved "https://registry.npmjs.org/vuex/-/vuex-4.0.0.tgz#ac877aa76a9c45368c979471e461b520d38e6cf5"
9276   - integrity sha512-56VPujlHscP5q/e7Jlpqc40sja4vOhC4uJD1llBCWolVI8ND4+VzisDVkUMl+z5y0MpIImW6HjhNc+ZvuizgOw==
9277   -
9278 9263 warning@^4.0.0:
9279 9264 version "4.0.3"
9280 9265 resolved "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
... ... @@ -9326,10 +9311,10 @@ which@^2.0.1:
9326 9311 dependencies:
9327 9312 isexe "^2.0.0"
9328 9313  
9329   -windicss@^2.5.11:
9330   - version "2.5.11"
9331   - resolved "https://registry.npmjs.org/windicss/-/windicss-2.5.11.tgz#dd4027c724c7b12a37746d1474b96a52239157d1"
9332   - integrity sha512-u7b4rOPb8MwO1glkf0gdDygZ+lIzXb/PYLNjqni5Fe2684DCEt6dWTKdk3iMxXgbKoqRNncKu7xt3pFwXHdSAw==
  9314 +windicss@^2.5.12:
  9315 + version "2.5.12"
  9316 + resolved "https://registry.npmjs.org/windicss/-/windicss-2.5.12.tgz#7bc469b05d7a8fa3905d49d6521a1ff9107d0ea4"
  9317 + integrity sha512-BZ0Ps1C0RlCHBVOPcw/DAReeR9o/mKaoFgkBsVphQ23M5nsvVfVXgGlNJZssjAQsXnlDpj97pnIhtDn1ENBjXw==
9333 9318  
9334 9319 wmf@~1.0.1:
9335 9320 version "1.0.2"
... ...