mirror of
https://github.com/vbenjs/gf-vben-admin.git
synced 2025-01-23 11:50:20 +08:00
refactor: refactor store
This commit is contained in:
parent
700306bb45
commit
215d8bab38
@ -28,6 +28,7 @@ export function generateModifyVars(dark = false) {
|
||||
'success-color': '#55D187', // Success color
|
||||
'error-color': '#ED6F6F', // False color
|
||||
'warning-color': '#EFBD47', // Warning color
|
||||
'border-color-base': '#EEEEEE',
|
||||
'font-size-base': '14px', // Main font size
|
||||
'border-radius-base': '2px', // Component/float fillet
|
||||
'link-color': primary, // Link color
|
||||
|
@ -16,9 +16,11 @@
|
||||
<script>
|
||||
(() => {
|
||||
var htmlRoot = document.getElementById('htmlRoot');
|
||||
const theme = window.localStorage.getItem('__APP__DARK__MODE__');
|
||||
if (!htmlRoot || !theme) return;
|
||||
var theme = window.localStorage.getItem('__APP__DARK__MODE__');
|
||||
if (htmlRoot && theme) {
|
||||
htmlRoot.setAttribute('data-theme', theme);
|
||||
theme = htmlRoot = null;
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<div id="app">
|
||||
|
12
package.json
12
package.json
@ -32,7 +32,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@iconify/iconify": "^2.0.0-rc.6",
|
||||
"@vueuse/core": "^4.8.0",
|
||||
"@vueuse/core": "^4.8.1",
|
||||
"@zxcvbn-ts/core": "^0.3.0",
|
||||
"ant-design-vue": "^2.1.2",
|
||||
"axios": "^0.21.1",
|
||||
@ -43,6 +43,7 @@
|
||||
"mockjs": "^1.1.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"path-to-regexp": "^6.2.0",
|
||||
"pinia": "^2.0.0-alpha.12",
|
||||
"print-js": "^1.6.0",
|
||||
"qrcode": "^1.4.4",
|
||||
"sortablejs": "^1.13.0",
|
||||
@ -52,8 +53,6 @@
|
||||
"vue-i18n": "9.0.0",
|
||||
"vue-router": "^4.0.6",
|
||||
"vue-types": "^3.0.2",
|
||||
"vuex": "^4.0.0",
|
||||
"vuex-module-decorators": "^1.0.1",
|
||||
"xlsx": "^0.16.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -81,7 +80,7 @@
|
||||
"conventional-changelog-cli": "^2.1.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"dotenv": "^8.2.0",
|
||||
"eslint": "^7.23.0",
|
||||
"eslint": "^7.24.0",
|
||||
"eslint-config-prettier": "^8.1.0",
|
||||
"eslint-define-config": "^1.0.7",
|
||||
"eslint-plugin-prettier": "^3.3.1",
|
||||
@ -115,13 +114,14 @@
|
||||
"vite-plugin-style-import": "^0.9.2",
|
||||
"vite-plugin-svg-icons": "^0.4.1",
|
||||
"vite-plugin-theme": "^0.6.3",
|
||||
"vite-plugin-windicss": "0.12.5",
|
||||
"vite-plugin-windicss": "0.13.1",
|
||||
"vue-eslint-parser": "^7.6.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"//": "Used to install imagemin dependencies, because imagemin may not be installed in China.If it is abroad, you can delete it",
|
||||
"bin-wrapper": "npm:bin-wrapper-china",
|
||||
"rollup": "^2.44.0"
|
||||
"rollup": "^2.45.1",
|
||||
"esbuild": "^0.11.6"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -3,22 +3,24 @@
|
||||
|
||||
import { createAppProviderContext } from './useAppContext';
|
||||
|
||||
import designSetting from '/@/settings/designSetting';
|
||||
import { prefixCls } from '/@/settings/designSetting';
|
||||
import { createBreakpointListen } from '/@/hooks/event/useBreakpoint';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { useAppStore } from '/@/store/modules/app';
|
||||
import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'AppProvider',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
prefixCls: propTypes.string.def(designSetting.prefixCls),
|
||||
prefixCls: propTypes.string.def(prefixCls),
|
||||
},
|
||||
setup(props, { slots }) {
|
||||
const isMobile = ref(false);
|
||||
const isSetState = ref(false);
|
||||
|
||||
const appStore = useAppStore();
|
||||
|
||||
createBreakpointListen(({ screenMap, sizeEnum, width }) => {
|
||||
const lgWidth = screenMap.get(sizeEnum.LG);
|
||||
if (lgWidth) {
|
||||
@ -42,20 +44,20 @@
|
||||
split: menuSplit,
|
||||
},
|
||||
} = appStore.getProjectConfig;
|
||||
appStore.commitProjectConfigState({
|
||||
appStore.setProjectConfig({
|
||||
menuSetting: {
|
||||
type: MenuTypeEnum.SIDEBAR,
|
||||
mode: MenuModeEnum.INLINE,
|
||||
split: false,
|
||||
},
|
||||
});
|
||||
appStore.commitBeforeMiniState({ menuMode, menuCollapsed, menuType, menuSplit });
|
||||
appStore.setBeforeMiniInfo({ menuMode, menuCollapsed, menuType, menuSplit });
|
||||
}
|
||||
} else {
|
||||
if (unref(isSetState)) {
|
||||
isSetState.value = false;
|
||||
const { menuMode, menuCollapsed, menuType, menuSplit } = appStore.getBeforeMiniState;
|
||||
appStore.commitProjectConfigState({
|
||||
const { menuMode, menuCollapsed, menuType, menuSplit } = appStore.getBeforeMiniInfo;
|
||||
appStore.setProjectConfig({
|
||||
menuSetting: {
|
||||
type: menuType,
|
||||
mode: menuMode,
|
||||
|
@ -1,17 +1,13 @@
|
||||
<template>
|
||||
<span :class="$attrs.class">
|
||||
<Icon :icon="icon" />
|
||||
<g-icon :icon="icon" />
|
||||
</span>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { Icon } from '/@/components/Icon';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
|
||||
export default defineComponent({
|
||||
components: { Icon },
|
||||
props: {
|
||||
icon: propTypes.string,
|
||||
icon: String,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -6,7 +6,6 @@
|
||||
:class="prefixCls"
|
||||
:activeSubMenuNames="activeSubMenuNames"
|
||||
@select="handleSelect"
|
||||
@open-change="handleOpenChange"
|
||||
>
|
||||
<template v-for="item in items" :key="item.path">
|
||||
<SimpleSubMenu
|
||||
@ -140,17 +139,11 @@
|
||||
menuState.activeName = key;
|
||||
}
|
||||
|
||||
function handleOpenChange(v) {
|
||||
console.log('======================');
|
||||
console.log(v);
|
||||
console.log('======================');
|
||||
}
|
||||
return {
|
||||
prefixCls,
|
||||
getBindValues,
|
||||
handleSelect,
|
||||
getOpenKeys,
|
||||
handleOpenChange,
|
||||
...toRefs(menuState),
|
||||
};
|
||||
},
|
||||
|
@ -2,28 +2,18 @@ import type { HeaderSetting } from '/#/config';
|
||||
|
||||
import { computed, unref } from 'vue';
|
||||
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { useAppStore } from '/@/store/modules/app';
|
||||
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
||||
import { useFullContent } from '/@/hooks/web/useFullContent';
|
||||
|
||||
import { MenuModeEnum } from '/@/enums/menuEnum';
|
||||
|
||||
const { getFullContent } = useFullContent();
|
||||
const {
|
||||
getMenuMode,
|
||||
getSplit,
|
||||
getShowHeaderTrigger,
|
||||
getIsSidebarType,
|
||||
getIsMixSidebar,
|
||||
getIsTopMenu,
|
||||
} = useMenuSetting();
|
||||
const { getShowBreadCrumb, getShowLogo } = useRootSetting();
|
||||
export function useHeaderSetting() {
|
||||
const { getFullContent } = useFullContent();
|
||||
const appStore = useAppStore();
|
||||
|
||||
const getShowMixHeaderRef = computed(() => !unref(getIsSidebarType) && unref(getShowHeader));
|
||||
|
||||
const getShowFullHeaderRef = computed(() => {
|
||||
const getShowFullHeaderRef = computed(() => {
|
||||
return (
|
||||
!unref(getFullContent) &&
|
||||
unref(getShowMixHeaderRef) &&
|
||||
@ -31,65 +21,70 @@ const getShowFullHeaderRef = computed(() => {
|
||||
!unref(getIsTopMenu) &&
|
||||
!unref(getIsMixSidebar)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
const getShowInsetHeaderRef = computed(() => {
|
||||
const getUnFixedAndFull = computed(() => !unref(getFixed) && !unref(getShowFullHeaderRef));
|
||||
|
||||
const getShowInsetHeaderRef = computed(() => {
|
||||
const need = !unref(getFullContent) && unref(getShowHeader);
|
||||
return (
|
||||
(need && !unref(getShowMixHeaderRef)) ||
|
||||
(need && unref(getIsTopMenu)) ||
|
||||
(need && unref(getIsMixSidebar))
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// Get header configuration
|
||||
const getHeaderSetting = computed(() => appStore.getProjectConfig.headerSetting);
|
||||
const {
|
||||
getMenuMode,
|
||||
getSplit,
|
||||
getShowHeaderTrigger,
|
||||
getIsSidebarType,
|
||||
getIsMixSidebar,
|
||||
getIsTopMenu,
|
||||
} = useMenuSetting();
|
||||
const { getShowBreadCrumb, getShowLogo } = useRootSetting();
|
||||
|
||||
const getShowDoc = computed(() => unref(getHeaderSetting).showDoc);
|
||||
const getShowMixHeaderRef = computed(() => !unref(getIsSidebarType) && unref(getShowHeader));
|
||||
|
||||
const getHeaderTheme = computed(() => unref(getHeaderSetting).theme);
|
||||
const getShowDoc = computed(() => appStore.getHeaderSetting.showDoc);
|
||||
|
||||
const getShowHeader = computed(() => unref(getHeaderSetting).show);
|
||||
const getHeaderTheme = computed(() => appStore.getHeaderSetting.theme);
|
||||
|
||||
const getFixed = computed(() => unref(getHeaderSetting).fixed);
|
||||
const getShowHeader = computed(() => appStore.getHeaderSetting.show);
|
||||
|
||||
const getHeaderBgColor = computed(() => unref(getHeaderSetting).bgColor);
|
||||
const getFixed = computed(() => appStore.getHeaderSetting.fixed);
|
||||
|
||||
const getShowSearch = computed(() => unref(getHeaderSetting).showSearch);
|
||||
const getHeaderBgColor = computed(() => appStore.getHeaderSetting.bgColor);
|
||||
|
||||
const getUseLockPage = computed(() => unref(getHeaderSetting).useLockPage);
|
||||
const getShowSearch = computed(() => appStore.getHeaderSetting.showSearch);
|
||||
|
||||
const getShowFullScreen = computed(() => unref(getHeaderSetting).showFullScreen);
|
||||
const getUseLockPage = computed(() => appStore.getHeaderSetting.useLockPage);
|
||||
|
||||
const getShowNotice = computed(() => unref(getHeaderSetting).showNotice);
|
||||
const getShowFullScreen = computed(() => appStore.getHeaderSetting.showFullScreen);
|
||||
|
||||
const getUnFixedAndFull = computed(() => !unref(getFixed) && !unref(getShowFullHeaderRef));
|
||||
const getShowNotice = computed(() => appStore.getHeaderSetting.showNotice);
|
||||
|
||||
const getShowBread = computed(() => {
|
||||
const getShowBread = computed(() => {
|
||||
return (
|
||||
unref(getMenuMode) !== MenuModeEnum.HORIZONTAL && unref(getShowBreadCrumb) && !unref(getSplit)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
const getShowHeaderLogo = computed(() => {
|
||||
const getShowHeaderLogo = computed(() => {
|
||||
return unref(getShowLogo) && !unref(getIsSidebarType) && !unref(getIsMixSidebar);
|
||||
});
|
||||
});
|
||||
|
||||
const getShowContent = computed(() => {
|
||||
const getShowContent = computed(() => {
|
||||
return unref(getShowBread) || unref(getShowHeaderTrigger);
|
||||
});
|
||||
});
|
||||
|
||||
// Set header configuration
|
||||
function setHeaderSetting(headerSetting: Partial<HeaderSetting>): void {
|
||||
appStore.commitProjectConfigState({ headerSetting });
|
||||
}
|
||||
|
||||
export function useHeaderSetting() {
|
||||
// Set header configuration
|
||||
function setHeaderSetting(headerSetting: Partial<HeaderSetting>) {
|
||||
appStore.setProjectConfig({ headerSetting });
|
||||
}
|
||||
return {
|
||||
setHeaderSetting,
|
||||
|
||||
getHeaderSetting,
|
||||
|
||||
getShowDoc,
|
||||
getShowSearch,
|
||||
getHeaderTheme,
|
||||
|
@ -2,7 +2,7 @@ import type { MenuSetting } from '/#/config';
|
||||
|
||||
import { computed, unref, ref } from 'vue';
|
||||
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { useAppStore } from '/@/store/modules/app';
|
||||
|
||||
import { SIDE_BAR_MINI_WIDTH, SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '/@/enums/appEnum';
|
||||
import { MenuModeEnum, MenuTypeEnum, TriggerEnum } from '/@/enums/menuEnum';
|
||||
@ -10,88 +10,102 @@ import { useFullContent } from '/@/hooks/web/useFullContent';
|
||||
|
||||
const mixSideHasChildren = ref(false);
|
||||
|
||||
// Get menu configuration
|
||||
const getMenuSetting = computed(() => appStore.getProjectConfig.menuSetting);
|
||||
export function useMenuSetting() {
|
||||
const { getFullContent: fullContent } = useFullContent();
|
||||
const appStore = useAppStore();
|
||||
|
||||
const getCollapsed = computed(() => unref(getMenuSetting).collapsed);
|
||||
const getShowSidebar = computed(() => {
|
||||
return (
|
||||
unref(getSplit) ||
|
||||
(unref(getShowMenu) && unref(getMenuMode) !== MenuModeEnum.HORIZONTAL && !unref(fullContent))
|
||||
);
|
||||
});
|
||||
|
||||
const getMenuType = computed(() => unref(getMenuSetting).type);
|
||||
const getCollapsed = computed(() => appStore.getMenuSetting.collapsed);
|
||||
|
||||
const getMenuMode = computed(() => unref(getMenuSetting).mode);
|
||||
const getMenuType = computed(() => appStore.getMenuSetting.type);
|
||||
|
||||
const getMenuFixed = computed(() => unref(getMenuSetting).fixed);
|
||||
const getMenuMode = computed(() => appStore.getMenuSetting.mode);
|
||||
|
||||
const getShowMenu = computed(() => unref(getMenuSetting).show);
|
||||
const getMenuFixed = computed(() => appStore.getMenuSetting.fixed);
|
||||
|
||||
const getMenuHidden = computed(() => unref(getMenuSetting).hidden);
|
||||
const getShowMenu = computed(() => appStore.getMenuSetting.show);
|
||||
|
||||
const getMenuWidth = computed(() => unref(getMenuSetting).menuWidth);
|
||||
const getMenuHidden = computed(() => appStore.getMenuSetting.hidden);
|
||||
|
||||
const getTrigger = computed(() => unref(getMenuSetting).trigger);
|
||||
const getMenuWidth = computed(() => appStore.getMenuSetting.menuWidth);
|
||||
|
||||
const getMenuTheme = computed(() => unref(getMenuSetting).theme);
|
||||
const getTrigger = computed(() => appStore.getMenuSetting.trigger);
|
||||
|
||||
const getSplit = computed(() => unref(getMenuSetting).split);
|
||||
const getMenuTheme = computed(() => appStore.getMenuSetting.theme);
|
||||
|
||||
const getMenuBgColor = computed(() => unref(getMenuSetting).bgColor);
|
||||
const getSplit = computed(() => appStore.getMenuSetting.split);
|
||||
|
||||
const getMixSideTrigger = computed(() => unref(getMenuSetting).mixSideTrigger);
|
||||
const getMenuBgColor = computed(() => appStore.getMenuSetting.bgColor);
|
||||
|
||||
const getCanDrag = computed(() => unref(getMenuSetting).canDrag);
|
||||
const getMixSideTrigger = computed(() => appStore.getMenuSetting.mixSideTrigger);
|
||||
|
||||
const getAccordion = computed(() => unref(getMenuSetting).accordion);
|
||||
const getCanDrag = computed(() => appStore.getMenuSetting.canDrag);
|
||||
|
||||
const getMixSideFixed = computed(() => unref(getMenuSetting).mixSideFixed);
|
||||
const getAccordion = computed(() => appStore.getMenuSetting.accordion);
|
||||
|
||||
const getTopMenuAlign = computed(() => unref(getMenuSetting).topMenuAlign);
|
||||
const getMixSideFixed = computed(() => appStore.getMenuSetting.mixSideFixed);
|
||||
|
||||
const getCloseMixSidebarOnChange = computed(() => unref(getMenuSetting).closeMixSidebarOnChange);
|
||||
const getTopMenuAlign = computed(() => appStore.getMenuSetting.topMenuAlign);
|
||||
|
||||
const getIsSidebarType = computed(() => unref(getMenuType) === MenuTypeEnum.SIDEBAR);
|
||||
const getCloseMixSidebarOnChange = computed(
|
||||
() => appStore.getMenuSetting.closeMixSidebarOnChange
|
||||
);
|
||||
|
||||
const getIsTopMenu = computed(() => unref(getMenuType) === MenuTypeEnum.TOP_MENU);
|
||||
const getIsSidebarType = computed(() => unref(getMenuType) === MenuTypeEnum.SIDEBAR);
|
||||
|
||||
const getCollapsedShowTitle = computed(() => unref(getMenuSetting).collapsedShowTitle);
|
||||
const getIsTopMenu = computed(() => unref(getMenuType) === MenuTypeEnum.TOP_MENU);
|
||||
|
||||
const getShowTopMenu = computed(() => {
|
||||
const getCollapsedShowTitle = computed(() => appStore.getMenuSetting.collapsedShowTitle);
|
||||
|
||||
const getShowTopMenu = computed(() => {
|
||||
return unref(getMenuMode) === MenuModeEnum.HORIZONTAL || unref(getSplit);
|
||||
});
|
||||
});
|
||||
|
||||
const getShowHeaderTrigger = computed(() => {
|
||||
if (unref(getMenuType) === MenuTypeEnum.TOP_MENU || !unref(getShowMenu) || unref(getMenuHidden)) {
|
||||
const getShowHeaderTrigger = computed(() => {
|
||||
if (
|
||||
unref(getMenuType) === MenuTypeEnum.TOP_MENU ||
|
||||
!unref(getShowMenu) ||
|
||||
unref(getMenuHidden)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return unref(getTrigger) === TriggerEnum.HEADER;
|
||||
});
|
||||
});
|
||||
|
||||
const getIsHorizontal = computed(() => {
|
||||
const getIsHorizontal = computed(() => {
|
||||
return unref(getMenuMode) === MenuModeEnum.HORIZONTAL;
|
||||
});
|
||||
});
|
||||
|
||||
const getIsMixSidebar = computed(() => {
|
||||
const getIsMixSidebar = computed(() => {
|
||||
return unref(getMenuType) === MenuTypeEnum.MIX_SIDEBAR;
|
||||
});
|
||||
});
|
||||
|
||||
const getIsMixMode = computed(() => {
|
||||
const getIsMixMode = computed(() => {
|
||||
return unref(getMenuMode) === MenuModeEnum.INLINE && unref(getMenuType) === MenuTypeEnum.MIX;
|
||||
});
|
||||
});
|
||||
|
||||
const getRealWidth = computed(() => {
|
||||
const getRealWidth = computed(() => {
|
||||
if (unref(getIsMixSidebar)) {
|
||||
return unref(getCollapsed) && !unref(getMixSideFixed)
|
||||
? unref(getMiniWidthNumber)
|
||||
: unref(getMenuWidth);
|
||||
}
|
||||
return unref(getCollapsed) ? unref(getMiniWidthNumber) : unref(getMenuWidth);
|
||||
});
|
||||
});
|
||||
|
||||
const getMiniWidthNumber = computed(() => {
|
||||
const { collapsedShowTitle } = unref(getMenuSetting);
|
||||
const getMiniWidthNumber = computed(() => {
|
||||
const { collapsedShowTitle } = appStore.getMenuSetting;
|
||||
return collapsedShowTitle ? SIDE_BAR_SHOW_TIT_MINI_WIDTH : SIDE_BAR_MINI_WIDTH;
|
||||
});
|
||||
});
|
||||
|
||||
const getCalcContentWidth = computed(() => {
|
||||
const getCalcContentWidth = computed(() => {
|
||||
const width =
|
||||
unref(getIsTopMenu) || !unref(getShowMenu) || (unref(getSplit) && unref(getMenuHidden))
|
||||
? 0
|
||||
@ -101,36 +115,24 @@ const getCalcContentWidth = computed(() => {
|
||||
: unref(getRealWidth);
|
||||
|
||||
return `calc(100% - ${unref(width)}px)`;
|
||||
});
|
||||
});
|
||||
|
||||
const { getFullContent: fullContent } = useFullContent();
|
||||
// Set menu configuration
|
||||
function setMenuSetting(menuSetting: Partial<MenuSetting>): void {
|
||||
appStore.setProjectConfig({ menuSetting });
|
||||
}
|
||||
|
||||
const getShowSidebar = computed(() => {
|
||||
return (
|
||||
unref(getSplit) ||
|
||||
(unref(getShowMenu) && unref(getMenuMode) !== MenuModeEnum.HORIZONTAL && !unref(fullContent))
|
||||
);
|
||||
});
|
||||
|
||||
// Set menu configuration
|
||||
function setMenuSetting(menuSetting: Partial<MenuSetting>): void {
|
||||
appStore.commitProjectConfigState({ menuSetting });
|
||||
}
|
||||
|
||||
function toggleCollapsed() {
|
||||
function toggleCollapsed() {
|
||||
setMenuSetting({
|
||||
collapsed: !unref(getCollapsed),
|
||||
});
|
||||
}
|
||||
|
||||
export function useMenuSetting() {
|
||||
}
|
||||
return {
|
||||
setMenuSetting,
|
||||
|
||||
toggleCollapsed,
|
||||
|
||||
getMenuFixed,
|
||||
getMenuSetting,
|
||||
getRealWidth,
|
||||
getMenuType,
|
||||
getMenuMode,
|
||||
|
@ -1,28 +1,25 @@
|
||||
import type { MultiTabsSetting } from '/#/config';
|
||||
|
||||
import { computed, unref } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
|
||||
const getMultipleTabSetting = computed(() => appStore.getProjectConfig.multiTabsSetting);
|
||||
|
||||
const getShowMultipleTab = computed(() => unref(getMultipleTabSetting).show);
|
||||
|
||||
const getShowQuick = computed(() => unref(getMultipleTabSetting).showQuick);
|
||||
|
||||
const getShowRedo = computed(() => unref(getMultipleTabSetting).showRedo);
|
||||
|
||||
const getShowFold = computed(() => unref(getMultipleTabSetting).showFold);
|
||||
|
||||
function setMultipleTabSetting(multiTabsSetting: Partial<MultiTabsSetting>) {
|
||||
appStore.commitProjectConfigState({ multiTabsSetting });
|
||||
}
|
||||
import { useAppStore } from '/@/store/modules/app';
|
||||
|
||||
export function useMultipleTabSetting() {
|
||||
const appStore = useAppStore();
|
||||
|
||||
const getShowMultipleTab = computed(() => appStore.getMultiTabsSetting.show);
|
||||
|
||||
const getShowQuick = computed(() => appStore.getMultiTabsSetting.showQuick);
|
||||
|
||||
const getShowRedo = computed(() => appStore.getMultiTabsSetting.showRedo);
|
||||
|
||||
const getShowFold = computed(() => appStore.getMultiTabsSetting.showFold);
|
||||
|
||||
function setMultipleTabSetting(multiTabsSetting: Partial<MultiTabsSetting>) {
|
||||
appStore.setProjectConfig({ multiTabsSetting });
|
||||
}
|
||||
return {
|
||||
setMultipleTabSetting,
|
||||
|
||||
getMultipleTabSetting,
|
||||
getShowMultipleTab,
|
||||
getShowQuick,
|
||||
getShowRedo,
|
||||
|
@ -1,71 +1,71 @@
|
||||
import type { ProjectConfig } from '/#/config';
|
||||
|
||||
import { computed, unref } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { ContentEnum } from '/@/enums/appEnum';
|
||||
import { ThemeEnum } from '../../enums/appEnum';
|
||||
import { useAppStore } from '/@/store/modules/app';
|
||||
import { ContentEnum, ThemeEnum } from '/@/enums/appEnum';
|
||||
|
||||
type RootSetting = Omit<
|
||||
ProjectConfig,
|
||||
'locale' | 'headerSetting' | 'menuSetting' | 'multiTabsSetting'
|
||||
>;
|
||||
|
||||
const getRootSetting = computed((): RootSetting => appStore.getProjectConfig);
|
||||
|
||||
const getPageLoading = computed(() => appStore.getPageLoading);
|
||||
|
||||
const getOpenKeepAlive = computed(() => unref(getRootSetting).openKeepAlive);
|
||||
|
||||
const getSettingButtonPosition = computed(() => unref(getRootSetting).settingButtonPosition);
|
||||
|
||||
const getCanEmbedIFramePage = computed(() => unref(getRootSetting).canEmbedIFramePage);
|
||||
|
||||
const getPermissionMode = computed(() => unref(getRootSetting).permissionMode);
|
||||
|
||||
const getShowLogo = computed(() => unref(getRootSetting).showLogo);
|
||||
|
||||
const getContentMode = computed(() => unref(getRootSetting).contentMode);
|
||||
|
||||
const getUseOpenBackTop = computed(() => unref(getRootSetting).useOpenBackTop);
|
||||
|
||||
const getShowSettingButton = computed(() => unref(getRootSetting).showSettingButton);
|
||||
|
||||
const getUseErrorHandle = computed(() => unref(getRootSetting).useErrorHandle);
|
||||
|
||||
const getShowFooter = computed(() => unref(getRootSetting).showFooter);
|
||||
|
||||
const getShowBreadCrumb = computed(() => unref(getRootSetting).showBreadCrumb);
|
||||
|
||||
const getThemeColor = computed(() => unref(getRootSetting).themeColor);
|
||||
|
||||
const getShowBreadCrumbIcon = computed(() => unref(getRootSetting).showBreadCrumbIcon);
|
||||
|
||||
const getFullContent = computed(() => unref(getRootSetting).fullContent);
|
||||
|
||||
const getColorWeak = computed(() => unref(getRootSetting).colorWeak);
|
||||
|
||||
const getGrayMode = computed(() => unref(getRootSetting).grayMode);
|
||||
|
||||
const getLockTime = computed(() => unref(getRootSetting).lockTime);
|
||||
|
||||
const getShowDarkModeToggle = computed(() => unref(getRootSetting).showDarkModeToggle);
|
||||
|
||||
const getDarkMode = computed(() => appStore.getDarkMode);
|
||||
|
||||
const getLayoutContentMode = computed(() =>
|
||||
unref(getRootSetting).contentMode === ContentEnum.FULL ? ContentEnum.FULL : ContentEnum.FIXED
|
||||
);
|
||||
|
||||
function setRootSetting(setting: Partial<RootSetting>) {
|
||||
appStore.commitProjectConfigState(setting);
|
||||
}
|
||||
|
||||
function setDarkMode(mode: ThemeEnum) {
|
||||
appStore.commitDarkMode(mode);
|
||||
}
|
||||
|
||||
export function useRootSetting() {
|
||||
const appStore = useAppStore();
|
||||
|
||||
const getPageLoading = computed(() => appStore.getPageLoading);
|
||||
|
||||
const getOpenKeepAlive = computed(() => appStore.getProjectConfig.openKeepAlive);
|
||||
|
||||
const getSettingButtonPosition = computed(() => appStore.getProjectConfig.settingButtonPosition);
|
||||
|
||||
const getCanEmbedIFramePage = computed(() => appStore.getProjectConfig.canEmbedIFramePage);
|
||||
|
||||
const getPermissionMode = computed(() => appStore.getProjectConfig.permissionMode);
|
||||
|
||||
const getShowLogo = computed(() => appStore.getProjectConfig.showLogo);
|
||||
|
||||
const getContentMode = computed(() => appStore.getProjectConfig.contentMode);
|
||||
|
||||
const getUseOpenBackTop = computed(() => appStore.getProjectConfig.useOpenBackTop);
|
||||
|
||||
const getShowSettingButton = computed(() => appStore.getProjectConfig.showSettingButton);
|
||||
|
||||
const getUseErrorHandle = computed(() => appStore.getProjectConfig.useErrorHandle);
|
||||
|
||||
const getShowFooter = computed(() => appStore.getProjectConfig.showFooter);
|
||||
|
||||
const getShowBreadCrumb = computed(() => appStore.getProjectConfig.showBreadCrumb);
|
||||
|
||||
const getThemeColor = computed(() => appStore.getProjectConfig.themeColor);
|
||||
|
||||
const getShowBreadCrumbIcon = computed(() => appStore.getProjectConfig.showBreadCrumbIcon);
|
||||
|
||||
const getFullContent = computed(() => appStore.getProjectConfig.fullContent);
|
||||
|
||||
const getColorWeak = computed(() => appStore.getProjectConfig.colorWeak);
|
||||
|
||||
const getGrayMode = computed(() => appStore.getProjectConfig.grayMode);
|
||||
|
||||
const getLockTime = computed(() => appStore.getProjectConfig.lockTime);
|
||||
|
||||
const getShowDarkModeToggle = computed(() => appStore.getProjectConfig.showDarkModeToggle);
|
||||
|
||||
const getDarkMode = computed(() => appStore.getDarkMode);
|
||||
|
||||
const getLayoutContentMode = computed(() =>
|
||||
appStore.getProjectConfig.contentMode === ContentEnum.FULL
|
||||
? ContentEnum.FULL
|
||||
: ContentEnum.FIXED
|
||||
);
|
||||
|
||||
function setRootSetting(setting: Partial<RootSetting>) {
|
||||
appStore.setProjectConfig(setting);
|
||||
}
|
||||
|
||||
function setDarkMode(mode: ThemeEnum) {
|
||||
appStore.setDarkMode(mode);
|
||||
}
|
||||
return {
|
||||
setRootSetting,
|
||||
|
||||
@ -73,7 +73,6 @@ export function useRootSetting() {
|
||||
getFullContent,
|
||||
getColorWeak,
|
||||
getGrayMode,
|
||||
getRootSetting,
|
||||
getLayoutContentMode,
|
||||
getPageLoading,
|
||||
getOpenKeepAlive,
|
||||
|
@ -1,30 +1,28 @@
|
||||
import type { TransitionSetting } from '/#/config';
|
||||
|
||||
import { computed, unref } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
|
||||
const getTransitionSetting = computed(() => appStore.getProjectConfig.transitionSetting);
|
||||
|
||||
const getEnableTransition = computed(() => unref(getTransitionSetting)?.enable);
|
||||
|
||||
const getOpenNProgress = computed(() => unref(getTransitionSetting)?.openNProgress);
|
||||
|
||||
const getOpenPageLoading = computed((): boolean => {
|
||||
return !!unref(getTransitionSetting)?.openPageLoading;
|
||||
});
|
||||
|
||||
const getBasicTransition = computed(() => unref(getTransitionSetting)?.basicTransition);
|
||||
|
||||
function setTransitionSetting(transitionSetting: Partial<TransitionSetting>) {
|
||||
appStore.commitProjectConfigState({ transitionSetting });
|
||||
}
|
||||
import { useAppStore } from '/@/store/modules/app';
|
||||
|
||||
export function useTransitionSetting() {
|
||||
const appStore = useAppStore();
|
||||
|
||||
const getEnableTransition = computed(() => appStore.getTransitionSetting?.enable);
|
||||
|
||||
const getOpenNProgress = computed(() => appStore.getTransitionSetting?.openNProgress);
|
||||
|
||||
const getOpenPageLoading = computed((): boolean => {
|
||||
return !!appStore.getTransitionSetting?.openPageLoading;
|
||||
});
|
||||
|
||||
const getBasicTransition = computed(() => appStore.getTransitionSetting?.basicTransition);
|
||||
|
||||
function setTransitionSetting(transitionSetting: Partial<TransitionSetting>) {
|
||||
appStore.setProjectConfig({ transitionSetting });
|
||||
}
|
||||
return {
|
||||
setTransitionSetting,
|
||||
|
||||
getTransitionSetting,
|
||||
getEnableTransition,
|
||||
getOpenNProgress,
|
||||
getOpenPageLoading,
|
||||
|
@ -1,13 +1,15 @@
|
||||
import type { EChartsOption } from 'echarts';
|
||||
import type { Ref } from 'vue';
|
||||
|
||||
import { useTimeoutFn } from '/@/hooks/core/useTimeout';
|
||||
import { tryOnUnmounted } from '@vueuse/core';
|
||||
import { unref, Ref, nextTick, watch, computed, ref } from 'vue';
|
||||
import type { EChartsOption } from 'echarts';
|
||||
import { unref, nextTick, watch, computed, ref } from 'vue';
|
||||
import { useDebounce } from '/@/hooks/core/useDebounce';
|
||||
import { useEventListener } from '/@/hooks/event/useEventListener';
|
||||
import { useBreakpoint } from '/@/hooks/event/useBreakpoint';
|
||||
|
||||
import echarts from '/@/plugins/echarts';
|
||||
import { useRootSetting } from '../setting/useRootSetting';
|
||||
import echarts from './echarts';
|
||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
||||
|
||||
export function useECharts(
|
||||
elRef: Ref<HTMLDivElement>,
|
@ -1,6 +1,6 @@
|
||||
import { computed, unref } from 'vue';
|
||||
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { useAppStore } from '/@/store/modules/app';
|
||||
|
||||
import router from '/@/router';
|
||||
|
||||
@ -8,6 +8,7 @@ import router from '/@/router';
|
||||
* @description: Full screen display content
|
||||
*/
|
||||
export const useFullContent = () => {
|
||||
const appStore = useAppStore();
|
||||
const { currentRoute } = router;
|
||||
|
||||
// Whether to display the content in full screen without displaying the menu
|
||||
|
@ -1,13 +1,18 @@
|
||||
import { computed, onUnmounted, unref, watchEffect } from 'vue';
|
||||
import { useThrottle } from '/@/hooks/core/useThrottle';
|
||||
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { lockStore } from '/@/store/modules/lock';
|
||||
import { userStore } from '/@/store/modules/user';
|
||||
import { useAppStore } from '/@/store/modules/app';
|
||||
import { useLockStore } from '/@/store/modules/lock';
|
||||
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
import { useRootSetting } from '../setting/useRootSetting';
|
||||
|
||||
export function useLockPage() {
|
||||
const { getLockTime } = useRootSetting();
|
||||
const lockStore = useLockStore();
|
||||
const userStore = useUserStore();
|
||||
const appStore = useAppStore();
|
||||
|
||||
let timeId: TimeoutHandle;
|
||||
|
||||
function clear(): void {
|
||||
@ -16,7 +21,7 @@ export function useLockPage() {
|
||||
|
||||
function resetCalcLockTimeout(): void {
|
||||
// not login
|
||||
if (!userStore.getTokenState) {
|
||||
if (!userStore.getToken) {
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
@ -33,14 +38,14 @@ export function useLockPage() {
|
||||
}
|
||||
|
||||
function lockPage(): void {
|
||||
lockStore.commitLockInfoState({
|
||||
lockStore.setLockInfo({
|
||||
isLock: true,
|
||||
pwd: undefined,
|
||||
});
|
||||
}
|
||||
|
||||
watchEffect((onClean) => {
|
||||
if (userStore.getTokenState) {
|
||||
if (userStore.getToken) {
|
||||
resetCalcLockTimeout();
|
||||
} else {
|
||||
clear();
|
||||
|
@ -1,10 +1,10 @@
|
||||
import type { RouteLocationRaw } from 'vue-router';
|
||||
import type { RouteLocationRaw, Router } from 'vue-router';
|
||||
|
||||
import { PageEnum } from '/@/enums/pageEnum';
|
||||
import { isString } from '/@/utils/is';
|
||||
import { unref } from 'vue';
|
||||
|
||||
import router from '/@/router';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
export type RouteLocationRawEx = Omit<RouteLocationRaw, 'path'> & { path: PageEnum };
|
||||
|
||||
@ -13,10 +13,16 @@ function handleError(e: Error) {
|
||||
}
|
||||
|
||||
// page switch
|
||||
export function useGo() {
|
||||
const { push, replace } = router;
|
||||
export function useGo(_router?: Router) {
|
||||
let router;
|
||||
if (!_router) {
|
||||
router = useRouter();
|
||||
}
|
||||
const { push, replace } = _router || router;
|
||||
function go(opt: PageEnum | RouteLocationRawEx | string = PageEnum.BASE_HOME, isReplace = false) {
|
||||
if (!opt) return;
|
||||
if (!opt) {
|
||||
return;
|
||||
}
|
||||
if (isString(opt)) {
|
||||
isReplace ? replace(opt).catch(handleError) : push(opt).catch(handleError);
|
||||
} else {
|
||||
@ -30,8 +36,12 @@ export function useGo() {
|
||||
/**
|
||||
* @description: redo current page
|
||||
*/
|
||||
export const useRedo = () => {
|
||||
const { push, currentRoute } = router;
|
||||
export const useRedo = (_router?: Router) => {
|
||||
let router;
|
||||
if (!_router) {
|
||||
router = useRouter();
|
||||
}
|
||||
const { push, currentRoute } = _router || router;
|
||||
const { query, params } = currentRoute.value;
|
||||
function redo(): Promise<boolean> {
|
||||
return new Promise((resolve) => {
|
||||
|
@ -1,8 +1,8 @@
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { permissionStore } from '/@/store/modules/permission';
|
||||
import { userStore } from '/@/store/modules/user';
|
||||
import { useAppStore } from '/@/store/modules/app';
|
||||
import { usePermissionStore } from '/@/store/modules/permission';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
|
||||
import { useTabs } from './useTabs';
|
||||
|
||||
@ -15,15 +15,20 @@ import { RoleEnum } from '/@/enums/roleEnum';
|
||||
|
||||
import { intersection } from 'lodash-es';
|
||||
import { isArray } from '/@/utils/is';
|
||||
import { tabStore } from '/@/store/modules/tab';
|
||||
import { useMultipleTabStore } from '/@/store/modules/multipleTab';
|
||||
|
||||
// User permissions related operations
|
||||
export function usePermission() {
|
||||
const userStore = useUserStore();
|
||||
const appStore = useAppStore();
|
||||
const permissionStore = usePermissionStore();
|
||||
const { closeAll } = useTabs(router);
|
||||
|
||||
/**
|
||||
* Change permission mode
|
||||
*/
|
||||
async function togglePermissionMode() {
|
||||
appStore.commitProjectConfigState({
|
||||
appStore.setProjectConfig({
|
||||
permissionMode:
|
||||
projectSetting.permissionMode === PermissionModeEnum.BACK
|
||||
? PermissionModeEnum.ROLE
|
||||
@ -37,14 +42,14 @@ export function usePermission() {
|
||||
* @param id
|
||||
*/
|
||||
async function resume(id?: string | number) {
|
||||
tabStore.commitClearCache();
|
||||
const tabStore = useMultipleTabStore();
|
||||
tabStore.clearCacheTabs();
|
||||
resetRouter();
|
||||
const routes = await permissionStore.buildRoutesAction(id);
|
||||
routes.forEach((route) => {
|
||||
router.addRoute((route as unknown) as RouteRecordRaw);
|
||||
});
|
||||
permissionStore.commitLastBuildMenuTimeState();
|
||||
const { closeAll } = useTabs();
|
||||
permissionStore.setLastBuildMenuTime();
|
||||
closeAll();
|
||||
}
|
||||
|
||||
@ -53,22 +58,24 @@ export function usePermission() {
|
||||
*/
|
||||
function hasPermission(value?: RoleEnum | RoleEnum[] | string | string[], def = true): boolean {
|
||||
const permMode = projectSetting.permissionMode;
|
||||
|
||||
if (PermissionModeEnum.ROLE === permMode) {
|
||||
// Visible by default
|
||||
if (!value) {
|
||||
return def;
|
||||
}
|
||||
if (!isArray(value)) {
|
||||
return userStore.getRoleListState?.includes(value as RoleEnum);
|
||||
return userStore.getRoleList?.includes(value as RoleEnum);
|
||||
}
|
||||
return (intersection(value, userStore.getRoleListState) as RoleEnum[]).length > 0;
|
||||
return (intersection(value, userStore.getRoleList) as RoleEnum[]).length > 0;
|
||||
}
|
||||
|
||||
if (PermissionModeEnum.BACK === permMode) {
|
||||
// Visible by default
|
||||
if (!value) {
|
||||
return def;
|
||||
}
|
||||
const allCodeList = permissionStore.getPermCodeListState;
|
||||
const allCodeList = permissionStore.getPermCodeList;
|
||||
if (!isArray(value)) {
|
||||
return allCodeList.includes(value as string);
|
||||
}
|
||||
@ -90,7 +97,7 @@ export function usePermission() {
|
||||
if (!isArray(roles)) {
|
||||
roles = [roles];
|
||||
}
|
||||
userStore.commitRoleListState(roles);
|
||||
userStore.setRoleList(roles);
|
||||
await resume();
|
||||
}
|
||||
|
||||
|
@ -1,28 +1,85 @@
|
||||
import { tabStore } from '/@/store/modules/tab';
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import type { RouteLocationNormalized } from 'vue-router';
|
||||
import type { RouteLocationNormalized, Router } from 'vue-router';
|
||||
|
||||
export function useTabs() {
|
||||
function canIUseFn(): boolean {
|
||||
const { multiTabsSetting: { show } = {} } = appStore.getProjectConfig;
|
||||
import { useRouter } from 'vue-router';
|
||||
import { unref } from 'vue';
|
||||
|
||||
import { useMultipleTabStore } from '/@/store/modules/multipleTab';
|
||||
import { useAppStore } from '/@/store/modules/app';
|
||||
|
||||
enum TableActionEnum {
|
||||
REFRESH,
|
||||
CLOSE_ALL,
|
||||
CLOSE_LEFT,
|
||||
CLOSE_RIGHT,
|
||||
CLOSE_OTHER,
|
||||
CLOSE_CURRENT,
|
||||
CLOSE,
|
||||
}
|
||||
|
||||
export function useTabs(_router: Router) {
|
||||
const appStore = useAppStore();
|
||||
|
||||
function canIUseTabs(): boolean {
|
||||
const { show } = appStore.getMultiTabsSetting;
|
||||
if (!show) {
|
||||
throw new Error('The multi-tab page is currently not open, please open it in the settings!');
|
||||
}
|
||||
return !!show;
|
||||
}
|
||||
|
||||
return {
|
||||
refreshPage: async () => {
|
||||
if (canIUseFn()) {
|
||||
await tabStore.commitRedoPage();
|
||||
const tabStore = useMultipleTabStore();
|
||||
const router = _router || useRouter();
|
||||
|
||||
const { currentRoute } = router;
|
||||
|
||||
function getCurrentTab() {
|
||||
const route = unref(currentRoute);
|
||||
return tabStore.getTabList.find((item) => item.path === route.path)!;
|
||||
}
|
||||
|
||||
async function handleTabAction(action: TableActionEnum, tab?: RouteLocationNormalized) {
|
||||
const canIUse = canIUseTabs;
|
||||
if (!canIUse) {
|
||||
return;
|
||||
}
|
||||
const currentTab = getCurrentTab();
|
||||
switch (action) {
|
||||
case TableActionEnum.REFRESH:
|
||||
await tabStore.refreshPage(router);
|
||||
break;
|
||||
|
||||
case TableActionEnum.CLOSE_ALL:
|
||||
await tabStore.closeAllTab(router);
|
||||
break;
|
||||
|
||||
case TableActionEnum.CLOSE_LEFT:
|
||||
await tabStore.closeLeftTabs(currentTab, router);
|
||||
break;
|
||||
|
||||
case TableActionEnum.CLOSE_RIGHT:
|
||||
await tabStore.closeRightTabs(currentTab, router);
|
||||
break;
|
||||
|
||||
case TableActionEnum.CLOSE_OTHER:
|
||||
await tabStore.closeOtherTabs(currentTab, router);
|
||||
break;
|
||||
|
||||
case TableActionEnum.CLOSE_CURRENT:
|
||||
case TableActionEnum.CLOSE:
|
||||
await tabStore.closeTab(tab || currentTab, router);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
refreshPage: () => handleTabAction(TableActionEnum.REFRESH),
|
||||
closeAll: () => handleTabAction(TableActionEnum.CLOSE_ALL),
|
||||
closeLeft: () => handleTabAction(TableActionEnum.CLOSE_LEFT),
|
||||
closeRight: () => handleTabAction(TableActionEnum.CLOSE_RIGHT),
|
||||
closeOther: () => handleTabAction(TableActionEnum.CLOSE_OTHER),
|
||||
closeCurrent: () => handleTabAction(TableActionEnum.CLOSE_CURRENT),
|
||||
close: (tab?: RouteLocationNormalized) => {
|
||||
handleTabAction(TableActionEnum.CLOSE, tab);
|
||||
},
|
||||
closeAll: () => canIUseFn() && tabStore.closeAllTabAction(),
|
||||
closeLeft: () => canIUseFn() && tabStore.closeLeftTabAction(tabStore.getCurrentTab),
|
||||
closeRight: () => canIUseFn() && tabStore.closeRightTabAction(tabStore.getCurrentTab),
|
||||
closeOther: () => canIUseFn() && tabStore.closeOtherTabAction(tabStore.getCurrentTab),
|
||||
closeCurrent: () => canIUseFn() && tabStore.closeTabAction(tabStore.getCurrentTab),
|
||||
close: (tab?: RouteLocationNormalized) =>
|
||||
canIUseFn() && tabStore.closeTabAction(tab || tabStore.getCurrentTab),
|
||||
};
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
:mouseEnterDelay="0.5"
|
||||
@click="handleToErrorList"
|
||||
>
|
||||
<Badge :count="getCount" :offset="[0, 10]" dot :overflowCount="99">
|
||||
<Badge :count="getCount" :offset="[0, 10]" :overflowCount="99">
|
||||
<Icon icon="ion:bug-outline" />
|
||||
</Badge>
|
||||
</Tooltip>
|
||||
@ -16,7 +16,7 @@
|
||||
import Icon from '/@/components/Icon';
|
||||
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import { errorStore } from '/@/store/modules/error';
|
||||
import { useErrorLogStore } from '/@/store/modules/errorLog';
|
||||
import { PageEnum } from '/@/enums/pageEnum';
|
||||
|
||||
import { useRouter } from 'vue-router';
|
||||
@ -28,14 +28,13 @@
|
||||
setup() {
|
||||
const { t } = useI18n();
|
||||
const { push } = useRouter();
|
||||
const errorLogStore = useErrorLogStore();
|
||||
|
||||
const getCount = computed(() => {
|
||||
return errorStore.getErrorListCountState;
|
||||
});
|
||||
const getCount = computed(() => errorLogStore.getErrorLogListCount);
|
||||
|
||||
function handleToErrorList() {
|
||||
push(PageEnum.ERROR_LOG_PAGE).then(() => {
|
||||
errorStore.commitErrorListCountState(0);
|
||||
errorLogStore.setErrorLogListCount(0);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -31,8 +31,8 @@
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal/index';
|
||||
import { BasicForm, useForm } from '/@/components/Form/index';
|
||||
|
||||
import { userStore } from '/@/store/modules/user';
|
||||
import { lockStore } from '/@/store/modules/lock';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
import { useLockStore } from '/@/store/modules/lock';
|
||||
import headerImg from '/@/assets/images/header.jpg';
|
||||
export default defineComponent({
|
||||
name: 'LockModal',
|
||||
@ -41,10 +41,10 @@
|
||||
setup() {
|
||||
const { t } = useI18n();
|
||||
const { prefixCls } = useDesign('header-lock-modal');
|
||||
const userStore = useUserStore();
|
||||
const lockStore = useLockStore();
|
||||
|
||||
const getRealName = computed(() => {
|
||||
return userStore.getUserInfoState?.realName;
|
||||
});
|
||||
const getRealName = computed(() => userStore.getUserInfo?.realName);
|
||||
const [register, { closeModal }] = useModalInner();
|
||||
|
||||
const [registerForm, { validateFields, resetFields }] = useForm({
|
||||
@ -64,7 +64,7 @@
|
||||
const password: string | undefined = values.password;
|
||||
closeModal();
|
||||
|
||||
lockStore.commitLockInfoState({
|
||||
lockStore.setLockInfo({
|
||||
isLock: true,
|
||||
pwd: password,
|
||||
});
|
||||
|
@ -41,7 +41,7 @@
|
||||
|
||||
import { DOC_URL } from '/@/settings/siteSetting';
|
||||
|
||||
import { userStore } from '/@/store/modules/user';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
@ -71,9 +71,10 @@
|
||||
const { prefixCls } = useDesign('header-user-dropdown');
|
||||
const { t } = useI18n();
|
||||
const { getShowDoc } = useHeaderSetting();
|
||||
const userStore = useUserStore();
|
||||
|
||||
const getUserInfo = computed(() => {
|
||||
const { realName = '', desc } = userStore.getUserInfoState || {};
|
||||
const { realName = '', desc } = userStore.getUserInfo || {};
|
||||
return { realName, desc };
|
||||
});
|
||||
|
||||
|
@ -42,13 +42,9 @@
|
||||
},
|
||||
setup() {
|
||||
const { prefixCls } = useDesign('default-layout');
|
||||
|
||||
const { getIsMobile } = useAppInject();
|
||||
|
||||
const { getShowFullHeaderRef } = useHeaderSetting();
|
||||
|
||||
const { getShowSidebar, getIsMixSidebar } = useMenuSetting();
|
||||
|
||||
const layoutClass = computed(() => ({ 'ant-layout-has-sider': unref(getIsMixSidebar) }));
|
||||
|
||||
return {
|
||||
|
@ -9,7 +9,7 @@ import { useThrottle } from '/@/hooks/core/useThrottle';
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
|
||||
import { getChildrenMenus, getCurrentParentPath, getMenus, getShallowMenus } from '/@/router/menus';
|
||||
import { permissionStore } from '/@/store/modules/permission';
|
||||
import { usePermissionStore } from '/@/store/modules/permission';
|
||||
import { useAppInject } from '/@/hooks/web/useAppInject';
|
||||
|
||||
export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
|
||||
@ -17,6 +17,7 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
|
||||
const menusRef = ref<Menu[]>([]);
|
||||
const { currentRoute } = useRouter();
|
||||
const { getIsMobile } = useAppInject();
|
||||
const permissionStore = usePermissionStore();
|
||||
const { setMenuSetting, getIsHorizontal, getSplit } = useMenuSetting();
|
||||
|
||||
const [throttleHandleSplitLeftMenu] = useThrottle(handleSplitLeftMenu, 50);
|
||||
@ -55,7 +56,7 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
|
||||
|
||||
// Menu changes
|
||||
watch(
|
||||
[() => permissionStore.getLastBuildMenuTimeState, () => permissionStore.getBackMenuListState],
|
||||
[() => permissionStore.getLastBuildMenuTime, () => permissionStore.getBackMenuList],
|
||||
() => {
|
||||
genMenus();
|
||||
},
|
||||
|
@ -21,32 +21,36 @@
|
||||
|
||||
import { CopyOutlined, RedoOutlined } from '@ant-design/icons-vue';
|
||||
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { permissionStore } from '/@/store/modules/permission';
|
||||
import { tabStore } from '/@/store/modules/tab';
|
||||
import { userStore } from '/@/store/modules/user';
|
||||
import { useAppStore } from '/@/store/modules/app';
|
||||
import { usePermissionStore } from '/@/store/modules/permission';
|
||||
import { useMultipleTabStore } from '/@/store/modules/multipleTab';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
|
||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
||||
|
||||
import { updateColorWeak } from '/@/logics/theme/updateColorWeak';
|
||||
import { updateGrayMode } from '/@/logics/theme/updateGrayMode';
|
||||
|
||||
import defaultSetting from '/@/settings/projectSetting';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SettingFooter',
|
||||
components: { CopyOutlined, RedoOutlined },
|
||||
setup() {
|
||||
const { getRootSetting } = useRootSetting();
|
||||
const permissionStore = usePermissionStore();
|
||||
const { prefixCls } = useDesign('setting-footer');
|
||||
const { t } = useI18n();
|
||||
const { createSuccessModal, createMessage } = useMessage();
|
||||
const tabStore = useMultipleTabStore();
|
||||
const userStore = useUserStore();
|
||||
const appStore = useAppStore();
|
||||
|
||||
function handleCopy() {
|
||||
const { isSuccessRef } = useCopyToClipboard(JSON.stringify(unref(getRootSetting), null, 2));
|
||||
const { isSuccessRef } = useCopyToClipboard(
|
||||
JSON.stringify(unref(appStore.getProjectConfig), null, 2)
|
||||
);
|
||||
unref(isSuccessRef) &&
|
||||
createSuccessModal({
|
||||
title: t('layout.setting.operatingTitle'),
|
||||
@ -55,7 +59,7 @@
|
||||
}
|
||||
function handleResetSetting() {
|
||||
try {
|
||||
appStore.commitProjectConfigState(defaultSetting);
|
||||
appStore.setProjectConfig(defaultSetting);
|
||||
const { colorWeak, grayMode } = defaultSetting;
|
||||
// updateTheme(themeColor);
|
||||
updateColorWeak(colorWeak);
|
||||
@ -68,10 +72,10 @@
|
||||
|
||||
function handleClearAndRedo() {
|
||||
localStorage.clear();
|
||||
appStore.resumeAllState();
|
||||
permissionStore.commitResetState();
|
||||
tabStore.commitResetState();
|
||||
userStore.commitResetState();
|
||||
appStore.resetAllState();
|
||||
permissionStore.resetState();
|
||||
tabStore.resetState();
|
||||
userStore.resetState();
|
||||
location.reload();
|
||||
}
|
||||
return {
|
||||
|
@ -3,15 +3,16 @@ import { updateHeaderBgColor, updateSidebarBgColor } from '/@/logics/theme/updat
|
||||
import { updateColorWeak } from '/@/logics/theme/updateColorWeak';
|
||||
import { updateGrayMode } from '/@/logics/theme/updateGrayMode';
|
||||
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { useAppStore } from '/@/store/modules/app';
|
||||
import { ProjectConfig } from '/#/config';
|
||||
import { changeTheme } from '/@/logics/theme';
|
||||
import { updateDarkTheme } from '/@/logics/theme/dark';
|
||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
||||
|
||||
export function baseHandler(event: HandlerEnum, value: any) {
|
||||
const appStore = useAppStore();
|
||||
const config = handler(event, value);
|
||||
appStore.commitProjectConfigState(config);
|
||||
appStore.setProjectConfig(config);
|
||||
if (event === HandlerEnum.CHANGE_THEME) {
|
||||
updateHeaderBgColor();
|
||||
updateSidebarBgColor();
|
||||
@ -19,6 +20,8 @@ export function baseHandler(event: HandlerEnum, value: any) {
|
||||
}
|
||||
|
||||
export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConfig> {
|
||||
const appStore = useAppStore();
|
||||
|
||||
const { getThemeColor, getDarkMode } = useRootSetting();
|
||||
switch (event) {
|
||||
case HandlerEnum.CHANGE_LAYOUT:
|
||||
@ -50,7 +53,7 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf
|
||||
}
|
||||
updateDarkTheme(value);
|
||||
|
||||
return { darkMode: value };
|
||||
return {};
|
||||
|
||||
case HandlerEnum.MENU_HAS_DRAG:
|
||||
return { menuSetting: { canDrag: value } };
|
||||
@ -97,7 +100,7 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf
|
||||
|
||||
// ============transition==================
|
||||
case HandlerEnum.OPEN_PAGE_LOADING:
|
||||
appStore.commitPageLoadingState(false);
|
||||
appStore.setPageLoading(false);
|
||||
return { transitionSetting: { openPageLoading: value } };
|
||||
|
||||
case HandlerEnum.ROUTER_TRANSITION:
|
||||
|
@ -5,38 +5,33 @@
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, unref, computed } from 'vue';
|
||||
import { Icon } from '/@/components/Icon';
|
||||
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
|
||||
import Icon from '/@/components/Icon';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'FoldButton',
|
||||
components: { Icon },
|
||||
|
||||
setup() {
|
||||
const { prefixCls } = useDesign('multiple-tabs-content');
|
||||
const { getShowMenu, setMenuSetting } = useMenuSetting();
|
||||
const { getShowHeader, setHeaderSetting } = useHeaderSetting();
|
||||
|
||||
const getIsUnFold = computed(() => {
|
||||
return !unref(getShowMenu) && !unref(getShowHeader);
|
||||
});
|
||||
const getIsUnFold = computed(() => !unref(getShowMenu) && !unref(getShowHeader));
|
||||
|
||||
const getIcon = computed(() => {
|
||||
return unref(getIsUnFold) ? 'codicon:screen-normal' : 'codicon:screen-full';
|
||||
});
|
||||
const getIcon = computed(() =>
|
||||
unref(getIsUnFold) ? 'codicon:screen-normal' : 'codicon:screen-full'
|
||||
);
|
||||
|
||||
function handleFold() {
|
||||
const isScale = !unref(getShowMenu) && !unref(getShowHeader);
|
||||
const isUnFold = unref(getIsUnFold);
|
||||
setMenuSetting({
|
||||
show: isScale,
|
||||
hidden: !isScale,
|
||||
});
|
||||
setHeaderSetting({
|
||||
show: isScale,
|
||||
show: isUnFold,
|
||||
hidden: !isUnFold,
|
||||
});
|
||||
setHeaderSetting({ show: isUnFold });
|
||||
}
|
||||
|
||||
return { prefixCls, getIcon, handleFold };
|
||||
|
@ -1,21 +0,0 @@
|
||||
<template>
|
||||
<TabContent :type="TabContentEnum.EXTRA_TYPE" :tabItem="$route" />
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
import { TabContentEnum } from '../types';
|
||||
|
||||
import TabContent from './TabContent.vue';
|
||||
export default defineComponent({
|
||||
name: 'QuickButton',
|
||||
components: {
|
||||
TabContent,
|
||||
},
|
||||
setup() {
|
||||
return {
|
||||
TabContentEnum,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
@ -1,9 +1,8 @@
|
||||
<template>
|
||||
<Dropdown :dropMenuList="getDropMenuList" :trigger="getTrigger" @menuEvent="handleMenuEvent">
|
||||
<div :class="`${prefixCls}__info`" @contextmenu="handleContext" v-if="isTabs">
|
||||
<div :class="`${prefixCls}__info`" @contextmenu="handleContext" v-if="getIsTabs">
|
||||
<span class="ml-1">{{ getTitle }}</span>
|
||||
</div>
|
||||
|
||||
<span :class="`${prefixCls}__extra-quick`" v-else @click="handleContext">
|
||||
<Icon icon="ion:chevron-down" />
|
||||
</span>
|
||||
@ -11,18 +10,18 @@
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import type { PropType } from 'vue';
|
||||
import type { RouteLocationNormalized } from 'vue-router';
|
||||
|
||||
import { defineComponent, computed } from 'vue';
|
||||
import { defineComponent, computed, unref } from 'vue';
|
||||
import { Dropdown } from '/@/components/Dropdown/index';
|
||||
import Icon from '/@/components/Icon';
|
||||
import { Icon } from '/@/components/Icon';
|
||||
|
||||
import { TabContentProps, TabContentEnum } from '../types';
|
||||
import { TabContentProps } from '../types';
|
||||
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { useTabDropdown } from '../useTabDropdown';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import { useTabDropdown } from '../useTabDropdown';
|
||||
|
||||
import { RouteLocationNormalized } from 'vue-router';
|
||||
export default defineComponent({
|
||||
name: 'TabContent',
|
||||
components: { Dropdown, Icon },
|
||||
@ -31,11 +30,7 @@
|
||||
type: Object as PropType<RouteLocationNormalized>,
|
||||
default: null,
|
||||
},
|
||||
|
||||
type: {
|
||||
type: Number as PropType<TabContentEnum>,
|
||||
default: TabContentEnum.TAB_TYPE,
|
||||
},
|
||||
isExtra: Boolean,
|
||||
},
|
||||
setup(props) {
|
||||
const { prefixCls } = useDesign('multiple-tabs-content');
|
||||
@ -43,27 +38,29 @@
|
||||
|
||||
const getTitle = computed(() => {
|
||||
const { tabItem: { meta } = {} } = props;
|
||||
return meta && t(meta.title);
|
||||
return meta && t(meta.title as string);
|
||||
});
|
||||
|
||||
const {
|
||||
getDropMenuList,
|
||||
handleMenuEvent,
|
||||
handleContextMenu,
|
||||
getTrigger,
|
||||
isTabs,
|
||||
} = useTabDropdown(props as TabContentProps);
|
||||
const getIsTabs = computed(() => !props.isExtra);
|
||||
|
||||
function handleContext(e: ChangeEvent) {
|
||||
const getTrigger = computed(() => (unref(getIsTabs) ? ['contextmenu'] : ['click']));
|
||||
|
||||
const { getDropMenuList, handleMenuEvent, handleContextMenu } = useTabDropdown(
|
||||
props as TabContentProps,
|
||||
getIsTabs
|
||||
);
|
||||
|
||||
function handleContext(e) {
|
||||
props.tabItem && handleContextMenu(props.tabItem)(e);
|
||||
}
|
||||
|
||||
return {
|
||||
prefixCls,
|
||||
getDropMenuList,
|
||||
handleMenuEvent,
|
||||
handleContext,
|
||||
getTrigger,
|
||||
isTabs,
|
||||
getIsTabs,
|
||||
getTitle,
|
||||
};
|
||||
},
|
||||
|
@ -1,26 +1,22 @@
|
||||
<template>
|
||||
<Tooltip :title="t('common.redo')" placement="bottom" :mouseEnterDelay="0.5">
|
||||
<span :class="`${prefixCls}__extra-redo`" @click="handleRedo">
|
||||
<RedoOutlined :spin="loading" />
|
||||
</span>
|
||||
</Tooltip>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import { RedoOutlined } from '@ant-design/icons-vue';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { Tooltip } from 'ant-design-vue';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import { useTabs } from '/@/hooks/web/useTabs';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'TabRedo',
|
||||
components: { RedoOutlined, Tooltip },
|
||||
components: { RedoOutlined },
|
||||
|
||||
setup() {
|
||||
const loading = ref(false);
|
||||
|
||||
const { prefixCls } = useDesign('multiple-tabs-content');
|
||||
const { t } = useI18n();
|
||||
const { refreshPage } = useTabs();
|
||||
|
||||
async function handleRedo() {
|
||||
@ -29,9 +25,9 @@
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
// Animation execution time
|
||||
}, 1000);
|
||||
}, 1200);
|
||||
}
|
||||
return { prefixCls, t, handleRedo, loading };
|
||||
return { prefixCls, handleRedo, loading };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -8,13 +8,20 @@ html[data-theme='dark'] {
|
||||
}
|
||||
}
|
||||
|
||||
html[data-theme='light'] {
|
||||
.@{prefix-cls} {
|
||||
.ant-tabs-tab:not(.ant-tabs-tab-active) {
|
||||
border: 1px solid #d9d9d9 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{prefix-cls} {
|
||||
z-index: 10;
|
||||
height: @multiple-height + 2;
|
||||
line-height: @multiple-height + 2;
|
||||
background: @component-background;
|
||||
border-bottom: 1px solid @border-color-base;
|
||||
box-shadow: 0 1px 2px 0 rgba(29, 35, 41, 0.05);
|
||||
|
||||
.ant-tabs-small {
|
||||
height: @multiple-height;
|
||||
|
@ -20,26 +20,26 @@
|
||||
|
||||
<template #tabBarExtraContent v-if="getShowRedo || getShowQuick">
|
||||
<TabRedo v-if="getShowRedo" />
|
||||
<QuickButton v-if="getShowQuick" />
|
||||
<TabContent isExtra :tabItem="$route" v-if="getShowQuick" />
|
||||
<FoldButton v-if="getShowFold" />
|
||||
</template>
|
||||
</Tabs>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import type { RouteLocationNormalized } from 'vue-router';
|
||||
|
||||
import { defineComponent, computed, unref, ref } from 'vue';
|
||||
|
||||
import { Tabs } from 'ant-design-vue';
|
||||
import TabContent from './components/TabContent.vue';
|
||||
import QuickButton from './components/QuickButton.vue';
|
||||
import FoldButton from './components/FoldButton.vue';
|
||||
import TabRedo from './components/TabRedo.vue';
|
||||
import type { RouteLocationNormalized } from 'vue-router';
|
||||
|
||||
import { useGo } from '/@/hooks/web/usePage';
|
||||
|
||||
import { tabStore } from '/@/store/modules/tab';
|
||||
import { userStore } from '/@/store/modules/user';
|
||||
import { useMultipleTabStore } from '/@/store/modules/multipleTab';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
|
||||
import { initAffixTabs, useTabsDrag } from './useMultipleTabs';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
@ -48,13 +48,12 @@
|
||||
import { REDIRECT_NAME } from '/@/router/constant';
|
||||
import { listenerRouteChange } from '/@/logics/mitt/routeChange';
|
||||
|
||||
import router from '/@/router';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'MultipleTabs',
|
||||
components: {
|
||||
QuickButton,
|
||||
TabRedo: TabRedo,
|
||||
TabRedo,
|
||||
FoldButton,
|
||||
Tabs,
|
||||
TabPane: Tabs.TabPane,
|
||||
@ -65,12 +64,16 @@
|
||||
const activeKeyRef = ref('');
|
||||
|
||||
useTabsDrag(affixTextList);
|
||||
const tabStore = useMultipleTabStore();
|
||||
const userStore = useUserStore();
|
||||
const router = useRouter();
|
||||
|
||||
const { prefixCls } = useDesign('multiple-tabs');
|
||||
const go = useGo();
|
||||
const { getShowQuick, getShowRedo, getShowFold } = useMultipleTabSetting();
|
||||
|
||||
const getTabsState = computed(() => {
|
||||
return tabStore.getTabsState.filter((item) => !item.meta?.hideTab);
|
||||
return tabStore.getTabList.filter((item) => !item.meta?.hideTab);
|
||||
});
|
||||
|
||||
const unClose = computed(() => unref(getTabsState).length === 1);
|
||||
@ -86,10 +89,11 @@
|
||||
|
||||
listenerRouteChange((route) => {
|
||||
const { name } = route;
|
||||
if (name === REDIRECT_NAME || !route || !userStore.getTokenState) return;
|
||||
if (name === REDIRECT_NAME || !route || !userStore.getToken) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { path, fullPath, meta = {} } = route;
|
||||
|
||||
const { currentActiveMenu, hideTab } = meta;
|
||||
const isHide = !hideTab ? null : currentActiveMenu;
|
||||
const p = isHide || fullPath || path;
|
||||
@ -101,10 +105,11 @@
|
||||
const findParentRoute = router
|
||||
.getRoutes()
|
||||
.find((item) => item.path === currentActiveMenu);
|
||||
|
||||
findParentRoute &&
|
||||
tabStore.addTabAction((findParentRoute as unknown) as RouteLocationNormalized);
|
||||
tabStore.addTab((findParentRoute as unknown) as RouteLocationNormalized);
|
||||
} else {
|
||||
tabStore.addTabAction(unref(route));
|
||||
tabStore.addTab(unref(route));
|
||||
}
|
||||
});
|
||||
|
||||
@ -116,9 +121,11 @@
|
||||
// Close the current tab
|
||||
function handleEdit(targetKey: string) {
|
||||
// Added operation to hide, currently only use delete operation
|
||||
if (unref(unClose)) return;
|
||||
if (unref(unClose)) {
|
||||
return;
|
||||
}
|
||||
|
||||
tabStore.closeTabByKeyAction(targetKey);
|
||||
tabStore.closeTabByKey(targetKey, router);
|
||||
}
|
||||
return {
|
||||
prefixCls,
|
||||
|
@ -14,22 +14,12 @@ export interface TabContentProps {
|
||||
trigger?: ('click' | 'hover' | 'contextmenu')[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 右键:下拉菜单文字
|
||||
*/
|
||||
export enum MenuEventEnum {
|
||||
// 刷新
|
||||
REFRESH_PAGE,
|
||||
// 关闭当前
|
||||
CLOSE_CURRENT,
|
||||
// 关闭左侧
|
||||
CLOSE_LEFT,
|
||||
// 关闭右侧
|
||||
CLOSE_RIGHT,
|
||||
// 关闭其他
|
||||
CLOSE_OTHER,
|
||||
// 关闭所有
|
||||
CLOSE_ALL,
|
||||
// 放大
|
||||
SCALE,
|
||||
}
|
||||
|
@ -1,14 +1,17 @@
|
||||
import { toRaw, ref, nextTick } from 'vue';
|
||||
import { RouteLocationNormalized } from 'vue-router';
|
||||
import type { RouteLocationNormalized } from 'vue-router';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { useSortable } from '/@/hooks/web/useSortable';
|
||||
import router from '/@/router';
|
||||
import { tabStore } from '/@/store/modules/tab';
|
||||
import { useMultipleTabStore } from '/@/store/modules/multipleTab';
|
||||
import { isNullAndUnDef } from '/@/utils/is';
|
||||
import projectSetting from '/@/settings/projectSetting';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
export function initAffixTabs(): string[] {
|
||||
const affixList = ref<RouteLocationNormalized[]>([]);
|
||||
|
||||
const tabStore = useMultipleTabStore();
|
||||
const router = useRouter();
|
||||
/**
|
||||
* @description: Filter all fixed routes
|
||||
*/
|
||||
@ -30,7 +33,7 @@ export function initAffixTabs(): string[] {
|
||||
const affixTabs = filterAffixTabs((router.getRoutes() as unknown) as RouteLocationNormalized[]);
|
||||
affixList.value = affixTabs;
|
||||
for (const tab of affixTabs) {
|
||||
tabStore.addTabAction(({
|
||||
tabStore.addTab(({
|
||||
meta: tab.meta,
|
||||
name: tab.name,
|
||||
path: tab.path,
|
||||
@ -39,6 +42,7 @@ export function initAffixTabs(): string[] {
|
||||
}
|
||||
|
||||
let isAddAffix = false;
|
||||
|
||||
if (!isAddAffix) {
|
||||
addAffixTabs();
|
||||
isAddAffix = true;
|
||||
@ -47,8 +51,8 @@ export function initAffixTabs(): string[] {
|
||||
}
|
||||
|
||||
export function useTabsDrag(affixTextList: string[]) {
|
||||
const tabStore = useMultipleTabStore();
|
||||
const { multiTabsSetting } = projectSetting;
|
||||
|
||||
const { prefixCls } = useDesign('multiple-tabs');
|
||||
nextTick(() => {
|
||||
if (!multiTabsSetting.canDrag) return;
|
||||
@ -66,7 +70,7 @@ export function useTabsDrag(affixTextList: string[]) {
|
||||
return;
|
||||
}
|
||||
|
||||
tabStore.commitSortTabs({ oldIndex, newIndex });
|
||||
tabStore.sortTabs(oldIndex, newIndex);
|
||||
},
|
||||
});
|
||||
initSortable();
|
||||
|
@ -1,29 +1,28 @@
|
||||
import type { TabContentProps } from './types';
|
||||
import type { DropMenu } from '/@/components/Dropdown';
|
||||
import type { ComputedRef } from 'vue';
|
||||
|
||||
import { computed, unref, reactive } from 'vue';
|
||||
import { TabContentEnum, MenuEventEnum } from './types';
|
||||
import { tabStore } from '/@/store/modules/tab';
|
||||
import router from '/@/router';
|
||||
import { RouteLocationNormalized } from 'vue-router';
|
||||
import { MenuEventEnum } from './types';
|
||||
import { useMultipleTabStore } from '/@/store/modules/multipleTab';
|
||||
import { RouteLocationNormalized, useRouter } from 'vue-router';
|
||||
import { useTabs } from '/@/hooks/web/useTabs';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
export function useTabDropdown(tabContentProps: TabContentProps) {
|
||||
export function useTabDropdown(tabContentProps: TabContentProps, getIsTabs: ComputedRef<boolean>) {
|
||||
const state = reactive({
|
||||
current: null as Nullable<RouteLocationNormalized>,
|
||||
currentIndex: 0,
|
||||
});
|
||||
|
||||
const { currentRoute } = router;
|
||||
const { t } = useI18n();
|
||||
const tabStore = useMultipleTabStore();
|
||||
const { currentRoute } = useRouter();
|
||||
const { refreshPage, closeAll, close, closeLeft, closeOther, closeRight } = useTabs();
|
||||
|
||||
const isTabs = computed(() => tabContentProps.type === TabContentEnum.TAB_TYPE);
|
||||
|
||||
const getCurrentTab = computed(
|
||||
const getTargetTab = computed(
|
||||
(): RouteLocationNormalized => {
|
||||
return unref(isTabs) ? tabContentProps.tabItem : unref(currentRoute);
|
||||
return unref(getIsTabs) ? tabContentProps.tabItem : unref(currentRoute);
|
||||
}
|
||||
);
|
||||
|
||||
@ -31,8 +30,10 @@ export function useTabDropdown(tabContentProps: TabContentProps) {
|
||||
* @description: drop-down list
|
||||
*/
|
||||
const getDropMenuList = computed(() => {
|
||||
if (!unref(getCurrentTab)) return;
|
||||
const { meta } = unref(getCurrentTab);
|
||||
if (!unref(getTargetTab)) {
|
||||
return;
|
||||
}
|
||||
const { meta } = unref(getTargetTab);
|
||||
const { path } = unref(currentRoute);
|
||||
|
||||
// Refresh button
|
||||
@ -42,11 +43,11 @@ export function useTabDropdown(tabContentProps: TabContentProps) {
|
||||
// Close left
|
||||
const closeLeftDisabled = index === 0;
|
||||
|
||||
const disabled = tabStore.getTabsState.length === 1;
|
||||
const disabled = tabStore.getTabList.length === 1;
|
||||
|
||||
// Close right
|
||||
const closeRightDisabled =
|
||||
index === tabStore.getTabsState.length - 1 && tabStore.getLastDragEndIndexState >= 0;
|
||||
index === tabStore.getTabList.length - 1 && tabStore.getLastDragEndIndex >= 0;
|
||||
const dropMenuList: DropMenu[] = [
|
||||
{
|
||||
icon: 'ion:reload-sharp',
|
||||
@ -58,7 +59,7 @@ export function useTabDropdown(tabContentProps: TabContentProps) {
|
||||
icon: 'clarity:close-line',
|
||||
event: MenuEventEnum.CLOSE_CURRENT,
|
||||
text: t('layout.multipleTab.close'),
|
||||
disabled: meta?.affix || disabled,
|
||||
disabled: !!meta?.affix || disabled,
|
||||
divider: true,
|
||||
},
|
||||
{
|
||||
@ -92,15 +93,13 @@ export function useTabDropdown(tabContentProps: TabContentProps) {
|
||||
return dropMenuList;
|
||||
});
|
||||
|
||||
const getTrigger = computed(() => {
|
||||
return unref(isTabs) ? ['contextmenu'] : ['click'];
|
||||
});
|
||||
|
||||
function handleContextMenu(tabItem: RouteLocationNormalized) {
|
||||
return (e: Event) => {
|
||||
if (!tabItem) return;
|
||||
if (!tabItem) {
|
||||
return;
|
||||
}
|
||||
e?.preventDefault();
|
||||
const index = tabStore.getTabsState.findIndex((tab) => tab.path === tabItem.path);
|
||||
const index = tabStore.getTabList.findIndex((tab) => tab.path === tabItem.path);
|
||||
state.current = tabItem;
|
||||
state.currentIndex = index;
|
||||
};
|
||||
@ -108,12 +107,8 @@ export function useTabDropdown(tabContentProps: TabContentProps) {
|
||||
|
||||
// Handle right click event
|
||||
function handleMenuEvent(menu: DropMenu): void {
|
||||
const { refreshPage, closeAll, close, closeLeft, closeOther, closeRight } = useTabs();
|
||||
const { event } = menu;
|
||||
switch (event) {
|
||||
case MenuEventEnum.SCALE:
|
||||
scaleScreen();
|
||||
break;
|
||||
case MenuEventEnum.REFRESH_PAGE:
|
||||
// refresh page
|
||||
refreshPage();
|
||||
@ -140,5 +135,5 @@ export function useTabDropdown(tabContentProps: TabContentProps) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return { getDropMenuList, handleMenuEvent, handleContextMenu, getTrigger, isTabs };
|
||||
return { getDropMenuList, handleMenuEvent, handleContextMenu };
|
||||
}
|
||||
|
@ -2,18 +2,19 @@ import type { AppRouteRecordRaw } from '/@/router/types';
|
||||
|
||||
import { computed, toRaw, unref } from 'vue';
|
||||
|
||||
import { tabStore } from '/@/store/modules/tab';
|
||||
import { useMultipleTabStore } from '/@/store/modules/multipleTab';
|
||||
|
||||
import { uniqBy } from 'lodash-es';
|
||||
|
||||
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
||||
|
||||
import router from '/@/router';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
export function useFrameKeepAlive() {
|
||||
const router = useRouter();
|
||||
const { currentRoute } = router;
|
||||
const { getShowMultipleTab } = useMultipleTabSetting();
|
||||
|
||||
const tabStore = useMultipleTabStore();
|
||||
const getFramePages = computed(() => {
|
||||
const ret =
|
||||
getAllFramePages((toRaw(router.getRoutes()) as unknown) as AppRouteRecordRaw[]) || [];
|
||||
@ -21,7 +22,7 @@ export function useFrameKeepAlive() {
|
||||
});
|
||||
|
||||
const getOpenTabList = computed((): string[] => {
|
||||
return tabStore.getTabsState.reduce((prev: string[], next) => {
|
||||
return tabStore.getTabList.reduce((prev: string[], next) => {
|
||||
if (next.meta && Reflect.has(next.meta, 'frameSrc')) {
|
||||
prev.push(next.name as string);
|
||||
}
|
||||
|
@ -35,13 +35,14 @@
|
||||
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
||||
import { getTransitionName } from './transition';
|
||||
|
||||
import { useStore } from 'vuex';
|
||||
import { useMultipleTabStore } from '/@/store/modules/multipleTab';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'PageLayout',
|
||||
components: { FrameLayout },
|
||||
setup() {
|
||||
const { getShowMultipleTab } = useMultipleTabSetting();
|
||||
const tabStore = useMultipleTabStore();
|
||||
|
||||
const { getOpenKeepAlive, getCanEmbedIFramePage } = useRootSetting();
|
||||
|
||||
@ -49,15 +50,11 @@
|
||||
|
||||
const openCache = computed(() => unref(getOpenKeepAlive) && unref(getShowMultipleTab));
|
||||
|
||||
const { getters } = useStore();
|
||||
|
||||
const getCaches = computed((): string[] => {
|
||||
if (!unref(getOpenKeepAlive)) {
|
||||
return [];
|
||||
}
|
||||
// TODO The useStore is used here mainly to solve the problem of circular dependency hot update
|
||||
const cacheTabs = getters['app-tab/getCachedTabsState'];
|
||||
return cacheTabs;
|
||||
return tabStore.getCachedTabList;
|
||||
});
|
||||
|
||||
return {
|
||||
|
@ -3,14 +3,15 @@ import type { I18n, I18nOptions } from 'vue-i18n';
|
||||
|
||||
import { createI18n } from 'vue-i18n';
|
||||
|
||||
import { localeStore } from '/@/store/modules/locale';
|
||||
import { localeSetting } from '/@/settings/localeSetting';
|
||||
import { useLocaleStoreWithOut } from '/@/store/modules/locale';
|
||||
|
||||
const { fallback, availableLocales } = localeSetting;
|
||||
|
||||
export let i18n: ReturnType<typeof createI18n>;
|
||||
|
||||
async function createI18nOptions(): Promise<I18nOptions> {
|
||||
const localeStore = useLocaleStoreWithOut();
|
||||
const locale = localeStore.getLocale;
|
||||
const defaultLocal = await import(`./lang/${locale}.ts`);
|
||||
const message = defaultLocal.default?.message ?? {};
|
||||
|
@ -6,7 +6,7 @@ import type { LocaleType } from '/#/config';
|
||||
import moment from 'moment';
|
||||
|
||||
import { i18n } from './setupI18n';
|
||||
import { localeStore } from '/@/store/modules/locale';
|
||||
import { useLocaleStoreWithOut } from '/@/store/modules/locale';
|
||||
import { unref, computed } from 'vue';
|
||||
|
||||
interface LangModule {
|
||||
@ -18,6 +18,8 @@ interface LangModule {
|
||||
const loadLocalePool: LocaleType[] = [];
|
||||
|
||||
function setI18nLanguage(locale: LocaleType) {
|
||||
const localeStore = useLocaleStoreWithOut();
|
||||
|
||||
if (i18n.mode === 'legacy') {
|
||||
i18n.global.locale = locale;
|
||||
} else {
|
||||
@ -28,6 +30,7 @@ function setI18nLanguage(locale: LocaleType) {
|
||||
}
|
||||
|
||||
export function useLocale() {
|
||||
const localeStore = useLocaleStoreWithOut();
|
||||
const getLocale = computed(() => localeStore.getLocale);
|
||||
const getShowLocalePicker = computed(() => localeStore.getShowPicker);
|
||||
|
||||
@ -40,7 +43,9 @@ export function useLocale() {
|
||||
async function changeLocale(locale: LocaleType) {
|
||||
const globalI18n = i18n.global;
|
||||
const currentLocale = unref(globalI18n.locale);
|
||||
if (currentLocale === locale) return locale;
|
||||
if (currentLocale === locale) {
|
||||
return locale;
|
||||
}
|
||||
|
||||
if (loadLocalePool.includes(locale)) {
|
||||
setI18nLanguage(locale);
|
||||
|
@ -2,7 +2,10 @@
|
||||
* Used to configure the global error handling function, which can monitor vue errors, script errors, static resource errors and Promise errors
|
||||
*/
|
||||
|
||||
import { errorStore, ErrorInfo } from '/@/store/modules/error';
|
||||
import type { ErrorLogInfo } from '/#/store';
|
||||
|
||||
import { useErrorLogStoreWithOut } from '/@/store/modules/errorLog';
|
||||
|
||||
import { ErrorTypeEnum } from '/@/enums/exceptionEnum';
|
||||
import { App } from 'vue';
|
||||
import projectSetting from '/@/settings/projectSetting';
|
||||
@ -61,8 +64,9 @@ function formatComponentName(vm: any) {
|
||||
*/
|
||||
|
||||
function vueErrorHandler(err: Error, vm: any, info: string) {
|
||||
const errorLogStore = useErrorLogStoreWithOut();
|
||||
const { name, path } = formatComponentName(vm);
|
||||
errorStore.commitErrorInfoState({
|
||||
errorLogStore.addErrorLogInfo({
|
||||
type: ErrorTypeEnum.VUE,
|
||||
name,
|
||||
file: path,
|
||||
@ -86,7 +90,7 @@ export function scriptErrorHandler(
|
||||
if (event === 'Script error.' && !source) {
|
||||
return false;
|
||||
}
|
||||
const errorInfo: Partial<ErrorInfo> = {};
|
||||
const errorInfo: Partial<ErrorLogInfo> = {};
|
||||
colno = colno || (window.event && (window.event as any).errorCharacter) || 0;
|
||||
errorInfo.message = event as string;
|
||||
if (error?.stack) {
|
||||
@ -95,13 +99,14 @@ export function scriptErrorHandler(
|
||||
errorInfo.stack = '';
|
||||
}
|
||||
const name = source ? source.substr(source.lastIndexOf('/') + 1) : 'script';
|
||||
errorStore.commitErrorInfoState({
|
||||
const errorLogStore = useErrorLogStoreWithOut();
|
||||
errorLogStore.addErrorLogInfo({
|
||||
type: ErrorTypeEnum.SCRIPT,
|
||||
name: name,
|
||||
file: source as string,
|
||||
detail: 'lineno' + lineno,
|
||||
url: window.location.href,
|
||||
...(errorInfo as Pick<ErrorInfo, 'message' | 'stack'>),
|
||||
...(errorInfo as Pick<ErrorLogInfo, 'message' | 'stack'>),
|
||||
});
|
||||
return true;
|
||||
}
|
||||
@ -112,8 +117,9 @@ export function scriptErrorHandler(
|
||||
function registerPromiseErrorHandler() {
|
||||
window.addEventListener(
|
||||
'unhandledrejection',
|
||||
function (event: any) {
|
||||
errorStore.commitErrorInfoState({
|
||||
function (event) {
|
||||
const errorLogStore = useErrorLogStoreWithOut();
|
||||
errorLogStore.addErrorLogInfo({
|
||||
type: ErrorTypeEnum.PROMISE,
|
||||
name: 'Promise Error!',
|
||||
file: 'none',
|
||||
@ -136,10 +142,10 @@ function registerResourceErrorHandler() {
|
||||
'error',
|
||||
function (e: Event) {
|
||||
const target = e.target ? e.target : (e.srcElement as any);
|
||||
|
||||
errorStore.commitErrorInfoState({
|
||||
const errorLogStore = useErrorLogStoreWithOut();
|
||||
errorLogStore.addErrorLogInfo({
|
||||
type: ErrorTypeEnum.RESOURCE,
|
||||
name: 'Resouce Error!',
|
||||
name: 'Resource Error!',
|
||||
file: (e.target || ({} as any)).currentSrc,
|
||||
detail: JSON.stringify({
|
||||
tagName: target.localName,
|
||||
@ -147,7 +153,7 @@ function registerResourceErrorHandler() {
|
||||
type: e.type,
|
||||
}),
|
||||
url: window.location.href,
|
||||
stack: 'resouce is not found',
|
||||
stack: 'resource is not found',
|
||||
message: (e.target || ({} as any)).localName + ' is load error',
|
||||
});
|
||||
},
|
||||
@ -161,7 +167,9 @@ function registerResourceErrorHandler() {
|
||||
*/
|
||||
export function setupErrorHandle(app: App) {
|
||||
const { useErrorHandle } = projectSetting;
|
||||
if (!useErrorHandle) return;
|
||||
if (!useErrorHandle) {
|
||||
return;
|
||||
}
|
||||
// Vue exception monitoring;
|
||||
app.config.errorHandler = vueErrorHandler;
|
||||
|
||||
|
@ -12,18 +12,20 @@ import { updateGrayMode } from '/@/logics/theme/updateGrayMode';
|
||||
import { updateDarkTheme } from '/@/logics/theme/dark';
|
||||
import { changeTheme } from '/@/logics/theme';
|
||||
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { localeStore } from '/@/store/modules/locale';
|
||||
import { useAppStore } from '/@/store/modules/app';
|
||||
import { useLocaleStore } from '/@/store/modules/locale';
|
||||
|
||||
import { getCommonStoragePrefix, getStorageShortName } from '/@/utils/env';
|
||||
|
||||
import { primaryColor } from '../../build/config/themeConfig';
|
||||
import { Persistent } from '/@/utils/cache/persistent';
|
||||
import { deepMerge } from '/@/utils';
|
||||
import { ThemeEnum } from '../enums/appEnum';
|
||||
import { ThemeEnum } from '/@/enums/appEnum';
|
||||
|
||||
// Initial project configuration
|
||||
export function initAppConfigStore() {
|
||||
const localeStore = useLocaleStore();
|
||||
const appStore = useAppStore();
|
||||
let projCfg: ProjectConfig = Persistent.getLocal(PROJ_CFG_KEY) as ProjectConfig;
|
||||
projCfg = deepMerge(projectSetting, projCfg || {});
|
||||
const darkMode = appStore.getDarkMode;
|
||||
@ -45,7 +47,7 @@ export function initAppConfigStore() {
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
appStore.commitProjectConfigState(projCfg);
|
||||
appStore.setProjectConfig(projCfg);
|
||||
|
||||
// init dark mode
|
||||
updateDarkTheme(darkMode);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { colorIsDark, lighten, darken } from '/@/utils/color';
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { useAppStore } from '/@/store/modules/app';
|
||||
import { ThemeEnum } from '/@/enums/appEnum';
|
||||
import { setCssVar } from './util';
|
||||
|
||||
@ -16,12 +16,13 @@ const SIDER_LIGHTEN_BG_COLOR = '--sider-dark-lighten-bg-color';
|
||||
* @param color
|
||||
*/
|
||||
export function updateHeaderBgColor(color?: string) {
|
||||
const appStore = useAppStore();
|
||||
const darkMode = appStore.getDarkMode === ThemeEnum.DARK;
|
||||
if (!color) {
|
||||
if (darkMode) {
|
||||
color = '#151515';
|
||||
} else {
|
||||
color = appStore.getProjectConfig.headerSetting.bgColor;
|
||||
color = appStore.getHeaderSetting.bgColor;
|
||||
}
|
||||
}
|
||||
// bg color
|
||||
@ -35,7 +36,7 @@ export function updateHeaderBgColor(color?: string) {
|
||||
// Determine the depth of the color value and automatically switch the theme
|
||||
const isDark = colorIsDark(color!);
|
||||
|
||||
appStore.commitProjectConfigState({
|
||||
appStore.setProjectConfig({
|
||||
headerSetting: {
|
||||
theme: isDark || darkMode ? ThemeEnum.DARK : ThemeEnum.LIGHT,
|
||||
},
|
||||
@ -47,13 +48,15 @@ export function updateHeaderBgColor(color?: string) {
|
||||
* @param color bg color
|
||||
*/
|
||||
export function updateSidebarBgColor(color?: string) {
|
||||
const appStore = useAppStore();
|
||||
|
||||
// if (!isHexColor(color)) return;
|
||||
const darkMode = appStore.getDarkMode === ThemeEnum.DARK;
|
||||
if (!color) {
|
||||
if (darkMode) {
|
||||
color = '#212121';
|
||||
} else {
|
||||
color = appStore.getProjectConfig.menuSetting.bgColor;
|
||||
color = appStore.getMenuSetting.bgColor;
|
||||
}
|
||||
}
|
||||
setCssVar(SIDER_DARK_BG_COLOR, color);
|
||||
@ -64,7 +67,7 @@ export function updateSidebarBgColor(color?: string) {
|
||||
// Only when the background color is #fff, the theme of the menu will be changed to light
|
||||
const isLight = ['#fff', '#ffffff'].includes(color!.toLowerCase());
|
||||
|
||||
appStore.commitProjectConfigState({
|
||||
appStore.setProjectConfig({
|
||||
menuSetting: {
|
||||
theme: isLight && !darkMode ? ThemeEnum.LIGHT : ThemeEnum.DARK,
|
||||
},
|
||||
|
12
src/main.ts
12
src/main.ts
@ -5,15 +5,13 @@ import { createApp } from 'vue';
|
||||
import App from './App.vue';
|
||||
|
||||
import router, { setupRouter } from '/@/router';
|
||||
import { setupRouterGuard } from '/@/router/guard';
|
||||
import { setupStore } from '/@/store';
|
||||
import { setupErrorHandle } from '/@/logics/error-handle';
|
||||
import { setupGlobDirectives } from '/@/directives';
|
||||
import { setupI18n } from '/@/locales/setupI18n';
|
||||
import { registerGlobComp } from '/@/components/registerGlobComp';
|
||||
|
||||
// router-guard
|
||||
import '/@/router/guard';
|
||||
|
||||
// Register icon Sprite
|
||||
import 'vite-plugin-svg-icons/register';
|
||||
|
||||
@ -27,6 +25,10 @@ if (import.meta.env.DEV) {
|
||||
|
||||
(async () => {
|
||||
const app = createApp(App);
|
||||
|
||||
// Configure vuex store
|
||||
setupStore(app);
|
||||
|
||||
// Register global components
|
||||
registerGlobComp(app);
|
||||
|
||||
@ -36,8 +38,8 @@ if (import.meta.env.DEV) {
|
||||
// Configure routing
|
||||
setupRouter(app);
|
||||
|
||||
// Configure vuex store
|
||||
setupStore(app);
|
||||
// router-guard
|
||||
setupRouterGuard();
|
||||
|
||||
// Register global directive
|
||||
setupGlobDirectives(app);
|
||||
|
@ -20,13 +20,3 @@ export const getParentLayout = (_name?: string) => {
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// export const getParentLayout = (name: string) => {
|
||||
// return () =>
|
||||
// new Promise((resolve) => {
|
||||
// resolve({
|
||||
// ...ParentLayout,
|
||||
// name,
|
||||
// });
|
||||
// });
|
||||
// };
|
||||
|
@ -9,11 +9,13 @@ import { createHttpGuard } from './httpGuard';
|
||||
import { createPageGuard } from './pageGuard';
|
||||
import { createStateGuard } from './stateGuard';
|
||||
|
||||
createPageGuard(router);
|
||||
createPageLoadingGuard(router);
|
||||
createHttpGuard(router);
|
||||
createScrollGuard(router);
|
||||
createMessageGuard(router);
|
||||
createProgressGuard(router);
|
||||
createPermissionGuard(router);
|
||||
createStateGuard(router);
|
||||
export function setupRouterGuard() {
|
||||
createPageGuard(router);
|
||||
createPageLoadingGuard(router);
|
||||
createHttpGuard(router);
|
||||
createScrollGuard(router);
|
||||
createMessageGuard(router);
|
||||
createProgressGuard(router);
|
||||
createPermissionGuard(router);
|
||||
createStateGuard(router);
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
import type { Router } from 'vue-router';
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { userStore } from '/@/store/modules/user';
|
||||
import { useAppStoreWidthOut } from '/@/store/modules/app';
|
||||
import { useUserStoreWidthOut } from '/@/store/modules/user';
|
||||
import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
|
||||
import { unref } from 'vue';
|
||||
|
||||
const { getOpenPageLoading } = useTransitionSetting();
|
||||
export function createPageLoadingGuard(router: Router) {
|
||||
const userStore = useUserStoreWidthOut();
|
||||
const appStore = useAppStoreWidthOut();
|
||||
const { getOpenPageLoading } = useTransitionSetting();
|
||||
router.beforeEach(async (to) => {
|
||||
if (!userStore.getTokenState) {
|
||||
if (!userStore.getToken) {
|
||||
return true;
|
||||
}
|
||||
if (to.meta.loaded) {
|
||||
@ -24,7 +26,7 @@ export function createPageLoadingGuard(router: Router) {
|
||||
router.afterEach(async () => {
|
||||
if (unref(getOpenPageLoading)) {
|
||||
setTimeout(() => {
|
||||
appStore.commitPageLoadingState(false);
|
||||
appStore.setPageLoading(false);
|
||||
}, 220);
|
||||
}
|
||||
return true;
|
||||
|
@ -1,9 +1,9 @@
|
||||
import type { Router, RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { permissionStore } from '/@/store/modules/permission';
|
||||
import { usePermissionStoreWidthOut } from '/@/store/modules/permission';
|
||||
|
||||
import { PageEnum } from '/@/enums/pageEnum';
|
||||
import { userStore } from '/@/store/modules/user';
|
||||
import { useUserStoreWidthOut } from '/@/store/modules/user';
|
||||
|
||||
import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic';
|
||||
|
||||
@ -12,6 +12,8 @@ const LOGIN_PATH = PageEnum.BASE_LOGIN;
|
||||
const whitePathList: PageEnum[] = [LOGIN_PATH];
|
||||
|
||||
export function createPermissionGuard(router: Router) {
|
||||
const userStore = useUserStoreWidthOut();
|
||||
const permissionStore = usePermissionStoreWidthOut();
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
// Jump to the 404 page after processing the login
|
||||
if (from.path === LOGIN_PATH && to.name === PAGE_NOT_FOUND_ROUTE.name) {
|
||||
@ -25,7 +27,7 @@ export function createPermissionGuard(router: Router) {
|
||||
return;
|
||||
}
|
||||
|
||||
const token = userStore.getTokenState;
|
||||
const token = userStore.getToken;
|
||||
|
||||
// token does not exist
|
||||
if (!token) {
|
||||
@ -51,7 +53,7 @@ export function createPermissionGuard(router: Router) {
|
||||
next(redirectData);
|
||||
return;
|
||||
}
|
||||
if (permissionStore.getIsDynamicAddedRouteState) {
|
||||
if (permissionStore.getIsDynamicAddedRoute) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
@ -64,7 +66,7 @@ export function createPermissionGuard(router: Router) {
|
||||
const redirectPath = (from.query.redirect || to.path) as string;
|
||||
const redirect = decodeURIComponent(redirectPath);
|
||||
const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect };
|
||||
permissionStore.commitDynamicAddedRouteState(true);
|
||||
permissionStore.setDynamicAddedRoute(true);
|
||||
next(nextData);
|
||||
});
|
||||
}
|
||||
|
@ -6,9 +6,8 @@ import nProgress from 'nprogress';
|
||||
|
||||
import { unref } from 'vue';
|
||||
|
||||
const { getOpenNProgress } = useTransitionSetting();
|
||||
|
||||
export function createProgressGuard(router: Router) {
|
||||
const { getOpenNProgress } = useTransitionSetting();
|
||||
router.beforeEach(async (to) => {
|
||||
if (to.meta.loaded) return true;
|
||||
unref(getOpenNProgress) && nProgress.start();
|
||||
|
@ -1,19 +1,23 @@
|
||||
import type { Router } from 'vue-router';
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { tabStore } from '/@/store/modules/tab';
|
||||
import { userStore } from '/@/store/modules/user';
|
||||
import { permissionStore } from '/@/store/modules/permission';
|
||||
import { useAppStore } from '/@/store/modules/app';
|
||||
import { useMultipleTabStore } from '/@/store/modules/multipleTab';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
import { usePermissionStore } from '/@/store/modules/permission';
|
||||
import { PageEnum } from '/@/enums/pageEnum';
|
||||
import { removeTabChangeListener } from '/@/logics/mitt/routeChange';
|
||||
|
||||
export function createStateGuard(router: Router) {
|
||||
router.afterEach((to) => {
|
||||
const tabStore = useMultipleTabStore();
|
||||
const userStore = useUserStore();
|
||||
const appStore = useAppStore();
|
||||
const permissionStore = usePermissionStore();
|
||||
// Just enter the login page and clear the authentication information
|
||||
if (to.path === PageEnum.BASE_LOGIN) {
|
||||
appStore.resumeAllState();
|
||||
permissionStore.commitResetState();
|
||||
tabStore.commitResetState();
|
||||
userStore.commitResetState();
|
||||
appStore.resetAllState();
|
||||
permissionStore.resetState();
|
||||
tabStore.resetState();
|
||||
userStore.resetState();
|
||||
removeTabChangeListener();
|
||||
}
|
||||
});
|
||||
|
@ -1,8 +1,8 @@
|
||||
import type { Menu, MenuModule } from '/@/router/types';
|
||||
import type { RouteRecordNormalized } from 'vue-router';
|
||||
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { permissionStore } from '/@/store/modules/permission';
|
||||
import { useAppStoreWidthOut } from '/@/store/modules/app';
|
||||
import { usePermissionStore } from '/@/store/modules/permission';
|
||||
import { transformMenuModule, getAllParentPath } from '/@/router/helper/menuHelper';
|
||||
import { filter } from '/@/utils/helper/treeHelper';
|
||||
import { isUrl } from '/@/utils/is';
|
||||
@ -24,6 +24,7 @@ Object.keys(modules).forEach((key) => {
|
||||
// ==========Helper===========
|
||||
// ===========================
|
||||
const isBackMode = () => {
|
||||
const appStore = useAppStoreWidthOut();
|
||||
return appStore.getProjectConfig.permissionMode === PermissionModeEnum.BACK;
|
||||
};
|
||||
|
||||
@ -39,7 +40,8 @@ const staticMenus: Menu[] = [];
|
||||
})();
|
||||
|
||||
async function getAsyncMenus() {
|
||||
return !isBackMode() ? staticMenus : permissionStore.getBackMenuListState;
|
||||
const permissionStore = usePermissionStore();
|
||||
return !isBackMode() ? staticMenus : permissionStore.getBackMenuList;
|
||||
}
|
||||
|
||||
export const getMenus = async (): Promise<Menu[]> => {
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { ThemeEnum } from '../enums/appEnum';
|
||||
export default {
|
||||
prefixCls: 'vben',
|
||||
};
|
||||
|
||||
export const prefixCls = 'vben';
|
||||
|
||||
export const darkMode = ThemeEnum.LIGHT;
|
||||
|
||||
|
@ -61,7 +61,6 @@ const setting: ProjectConfig = {
|
||||
theme: ThemeEnum.LIGHT,
|
||||
// Whether to enable the lock screen function
|
||||
useLockPage: true,
|
||||
|
||||
// Whether to show the full screen button
|
||||
showFullScreen: true,
|
||||
// Whether to show the document button
|
||||
|
@ -1,6 +1,8 @@
|
||||
// github repo url
|
||||
export const GITHUB_URL = 'https://github.com/anncwb/vue-vben-admin';
|
||||
|
||||
// vue-vben-admin-next-doc
|
||||
export const DOC_URL = 'https://vvbin.cn/doc-next/';
|
||||
|
||||
// site url
|
||||
export const SITE_URL = 'https://vvbin.cn/next/';
|
||||
|
@ -1,16 +1,9 @@
|
||||
import type { App } from 'vue';
|
||||
import { createStore } from 'vuex';
|
||||
import { config } from 'vuex-module-decorators';
|
||||
import { isDevMode } from '/@/utils/env';
|
||||
|
||||
config.rawError = true;
|
||||
|
||||
const store = createStore({
|
||||
strict: isDevMode(),
|
||||
});
|
||||
import { createPinia } from 'pinia';
|
||||
const store = createPinia();
|
||||
|
||||
export function setupStore(app: App<Element>) {
|
||||
app.use(store);
|
||||
}
|
||||
|
||||
export default store;
|
||||
export { store };
|
||||
|
@ -1,109 +1,102 @@
|
||||
import type { ProjectConfig } from '/#/config';
|
||||
import type { BeforeMiniState } from '../types';
|
||||
import type { BeforeMiniState } from '/#/store';
|
||||
|
||||
import { VuexModule, getModule, Module, Mutation, Action } from 'vuex-module-decorators';
|
||||
import store from '/@/store';
|
||||
import { defineStore } from 'pinia';
|
||||
import { store } from '/@/store';
|
||||
|
||||
import { PROJ_CFG_KEY, APP_DARK_MODE_KEY_ } from '/@/enums/cacheEnum';
|
||||
|
||||
import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper';
|
||||
import { ThemeEnum } from '/@/enums/appEnum';
|
||||
import { APP_DARK_MODE_KEY_, PROJ_CFG_KEY } from '/@/enums/cacheEnum';
|
||||
import { Persistent } from '/@/utils/cache/persistent';
|
||||
import { darkMode } from '/@/settings/designSetting';
|
||||
import { resetRouter } from '/@/router';
|
||||
import { deepMerge } from '/@/utils';
|
||||
|
||||
import { resetRouter } from '/@/router';
|
||||
import { ThemeEnum } from '../../enums/appEnum';
|
||||
|
||||
import { darkMode } from '/@/settings/designSetting';
|
||||
|
||||
export interface LockInfo {
|
||||
pwd: string | undefined;
|
||||
isLock: boolean;
|
||||
}
|
||||
|
||||
let timeId: TimeoutHandle;
|
||||
const NAME = 'app';
|
||||
hotModuleUnregisterModule(NAME);
|
||||
@Module({ dynamic: true, namespaced: true, store, name: NAME })
|
||||
export default class App extends VuexModule {
|
||||
private darkMode;
|
||||
|
||||
interface AppState {
|
||||
darkMode: ThemeEnum;
|
||||
// Page loading status
|
||||
private pageLoadingState = false;
|
||||
|
||||
pageLoading: boolean;
|
||||
// project config
|
||||
private projectConfigState: ProjectConfig | null = Persistent.getLocal(PROJ_CFG_KEY);
|
||||
|
||||
// set main overflow hidden
|
||||
private lockMainScrollState = false;
|
||||
|
||||
projectConfig: ProjectConfig | null;
|
||||
// When the window shrinks, remember some states, and restore these states when the window is restored
|
||||
private beforeMiniState: BeforeMiniState = {};
|
||||
|
||||
get getPageLoading() {
|
||||
return this.pageLoadingState;
|
||||
}
|
||||
|
||||
get getDarkMode() {
|
||||
beforeMiniInfo: BeforeMiniState;
|
||||
}
|
||||
let timeId: TimeoutHandle;
|
||||
export const useAppStore = defineStore({
|
||||
id: 'app',
|
||||
state: (): AppState => ({
|
||||
darkMode: ThemeEnum.LIGHT,
|
||||
pageLoading: false,
|
||||
projectConfig: Persistent.getLocal(PROJ_CFG_KEY),
|
||||
beforeMiniInfo: {},
|
||||
}),
|
||||
getters: {
|
||||
getPageLoading() {
|
||||
return this.pageLoading;
|
||||
},
|
||||
getDarkMode() {
|
||||
return this.darkMode || localStorage.getItem(APP_DARK_MODE_KEY_) || darkMode;
|
||||
}
|
||||
},
|
||||
|
||||
get getBeforeMiniState() {
|
||||
return this.beforeMiniState;
|
||||
}
|
||||
getBeforeMiniInfo() {
|
||||
return this.beforeMiniInfo;
|
||||
},
|
||||
|
||||
get getLockMainScrollState() {
|
||||
return this.lockMainScrollState;
|
||||
}
|
||||
getProjectConfig(): ProjectConfig {
|
||||
return this.projectConfig || ({} as ProjectConfig);
|
||||
},
|
||||
|
||||
get getProjectConfig(): ProjectConfig {
|
||||
return this.projectConfigState || ({} as ProjectConfig);
|
||||
}
|
||||
getHeaderSetting() {
|
||||
return this.getProjectConfig.headerSetting;
|
||||
},
|
||||
getMenuSetting() {
|
||||
return this.getProjectConfig.menuSetting;
|
||||
},
|
||||
getTransitionSetting() {
|
||||
return this.getProjectConfig.transitionSetting;
|
||||
},
|
||||
getMultiTabsSetting() {
|
||||
return this.getProjectConfig.multiTabsSetting;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
setPageLoading(loading: boolean): void {
|
||||
this.pageLoading = loading;
|
||||
},
|
||||
|
||||
@Mutation
|
||||
commitPageLoadingState(loading: boolean): void {
|
||||
this.pageLoadingState = loading;
|
||||
}
|
||||
|
||||
@Mutation
|
||||
commitDarkMode(mode: ThemeEnum): void {
|
||||
setDarkMode(mode: ThemeEnum): void {
|
||||
this.darkMode = mode;
|
||||
localStorage.setItem(APP_DARK_MODE_KEY_, mode);
|
||||
}
|
||||
},
|
||||
|
||||
@Mutation
|
||||
commitBeforeMiniState(state: BeforeMiniState): void {
|
||||
this.beforeMiniState = state;
|
||||
}
|
||||
setBeforeMiniInfo(state: BeforeMiniState): void {
|
||||
this.beforeMiniInfo = state;
|
||||
},
|
||||
|
||||
@Mutation
|
||||
commitLockMainScrollState(lock: boolean): void {
|
||||
this.lockMainScrollState = lock;
|
||||
}
|
||||
setProjectConfig(config: DeepPartial<ProjectConfig>): void {
|
||||
this.projectConfig = deepMerge(this.projectConfig || {}, config);
|
||||
Persistent.setLocal(PROJ_CFG_KEY, this.projectConfig);
|
||||
},
|
||||
|
||||
@Mutation
|
||||
commitProjectConfigState(proCfg: DeepPartial<ProjectConfig>): void {
|
||||
this.projectConfigState = deepMerge(this.projectConfigState || {}, proCfg);
|
||||
Persistent.setLocal(PROJ_CFG_KEY, this.projectConfigState);
|
||||
}
|
||||
|
||||
@Action
|
||||
async resumeAllState() {
|
||||
async resetAllState() {
|
||||
resetRouter();
|
||||
Persistent.clearAll();
|
||||
}
|
||||
|
||||
@Action
|
||||
public async setPageLoadingAction(loading: boolean): Promise<void> {
|
||||
},
|
||||
async setPageLoadingAction(loading: boolean): Promise<void> {
|
||||
if (loading) {
|
||||
clearTimeout(timeId);
|
||||
// Prevent flicker
|
||||
timeId = setTimeout(() => {
|
||||
this.commitPageLoadingState(loading);
|
||||
this.setPageLoading(loading);
|
||||
}, 50);
|
||||
} else {
|
||||
this.commitPageLoadingState(loading);
|
||||
this.setPageLoading(loading);
|
||||
clearTimeout(timeId);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Need to be used outside the setup
|
||||
export function useAppStoreWidthOut() {
|
||||
return useAppStore(store);
|
||||
}
|
||||
export const appStore = getModule<App>(App);
|
||||
|
@ -1,81 +0,0 @@
|
||||
import store from '/@/store';
|
||||
import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper';
|
||||
import { VuexModule, getModule, Module, Mutation, Action } from 'vuex-module-decorators';
|
||||
|
||||
import { formatToDateTime } from '/@/utils/dateUtil';
|
||||
import { ErrorTypeEnum } from '/@/enums/exceptionEnum';
|
||||
import projectSetting from '/@/settings/projectSetting';
|
||||
|
||||
export interface ErrorInfo {
|
||||
type: ErrorTypeEnum;
|
||||
file: string;
|
||||
name?: string;
|
||||
message: string;
|
||||
stack?: string;
|
||||
detail: string;
|
||||
url: string;
|
||||
time?: string;
|
||||
}
|
||||
|
||||
export interface ErrorState {
|
||||
errorInfoState: ErrorInfo[] | null;
|
||||
errorListCountState: number;
|
||||
}
|
||||
|
||||
const NAME = 'app-error';
|
||||
hotModuleUnregisterModule(NAME);
|
||||
@Module({ dynamic: true, namespaced: true, store, name: NAME })
|
||||
class Error extends VuexModule implements ErrorState {
|
||||
// error log list
|
||||
errorInfoState: ErrorInfo[] = [];
|
||||
|
||||
// error log count
|
||||
errorListCountState = 0;
|
||||
|
||||
get getErrorInfoState() {
|
||||
return this.errorInfoState;
|
||||
}
|
||||
|
||||
get getErrorListCountState() {
|
||||
return this.errorListCountState;
|
||||
}
|
||||
|
||||
@Mutation
|
||||
commitErrorInfoState(info: ErrorInfo): void {
|
||||
const item = {
|
||||
...info,
|
||||
time: formatToDateTime(new Date()),
|
||||
};
|
||||
this.errorInfoState = [item, ...this.errorInfoState];
|
||||
this.errorListCountState += 1;
|
||||
}
|
||||
|
||||
@Mutation
|
||||
commitErrorListCountState(count: number): void {
|
||||
this.errorListCountState = count;
|
||||
}
|
||||
|
||||
@Action
|
||||
setupErrorHandle(error: any) {
|
||||
const { useErrorHandle } = projectSetting;
|
||||
if (!useErrorHandle) return;
|
||||
|
||||
const errInfo: Partial<ErrorInfo> = {
|
||||
message: error.message,
|
||||
type: ErrorTypeEnum.AJAX,
|
||||
};
|
||||
if (error.response) {
|
||||
const {
|
||||
config: { url = '', data: params = '', method = 'get', headers = {} } = {},
|
||||
data = {},
|
||||
} = error.response;
|
||||
errInfo.url = url;
|
||||
errInfo.name = 'Ajax Error!';
|
||||
errInfo.file = '-';
|
||||
errInfo.stack = JSON.stringify(data);
|
||||
errInfo.detail = JSON.stringify({ params, method, headers });
|
||||
}
|
||||
this.commitErrorInfoState(errInfo as ErrorInfo);
|
||||
}
|
||||
}
|
||||
export const errorStore = getModule<Error>(Error);
|
77
src/store/modules/errorLog.ts
Normal file
77
src/store/modules/errorLog.ts
Normal file
@ -0,0 +1,77 @@
|
||||
import type { ErrorLogInfo } from '/#/store';
|
||||
|
||||
import { defineStore } from 'pinia';
|
||||
import { store } from '/@/store';
|
||||
|
||||
import { formatToDateTime } from '/@/utils/dateUtil';
|
||||
import projectSetting from '/@/settings/projectSetting';
|
||||
|
||||
import { ErrorTypeEnum } from '/@/enums/exceptionEnum';
|
||||
|
||||
export interface ErrorLogState {
|
||||
errorLogInfoList: Nullable<ErrorLogInfo[]>;
|
||||
errorLogListCount: number;
|
||||
}
|
||||
|
||||
export const useErrorLogStore = defineStore({
|
||||
id: 'app-error-log',
|
||||
state: (): ErrorLogState => ({
|
||||
errorLogInfoList: null,
|
||||
errorLogListCount: 0,
|
||||
}),
|
||||
getters: {
|
||||
getErrorLogInfoList() {
|
||||
return this.errorLogInfoList || [];
|
||||
},
|
||||
getErrorLogListCount() {
|
||||
return this.errorLogListCount;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
addErrorLogInfo(info: ErrorLogInfo) {
|
||||
const item = {
|
||||
...info,
|
||||
time: formatToDateTime(new Date()),
|
||||
};
|
||||
this.errorLogInfoList = [item, ...(this.errorLogInfoList || [])];
|
||||
this.errorLogListCount += 1;
|
||||
},
|
||||
|
||||
setErrorLogListCount(count: number): void {
|
||||
this.errorLogListCount = count;
|
||||
},
|
||||
|
||||
/**
|
||||
* Triggered after ajax request error
|
||||
* @param error
|
||||
* @returns
|
||||
*/
|
||||
addAjaxErrorInfo(error) {
|
||||
const { useErrorHandle } = projectSetting;
|
||||
if (!useErrorHandle) {
|
||||
return;
|
||||
}
|
||||
const errInfo: Partial<ErrorLogInfo> = {
|
||||
message: error.message,
|
||||
type: ErrorTypeEnum.AJAX,
|
||||
};
|
||||
if (error.response) {
|
||||
const {
|
||||
config: { url = '', data: params = '', method = 'get', headers = {} } = {},
|
||||
data = {},
|
||||
} = error.response;
|
||||
errInfo.url = url;
|
||||
errInfo.name = 'Ajax Error!';
|
||||
errInfo.file = '-';
|
||||
errInfo.stack = JSON.stringify(data);
|
||||
errInfo.detail = JSON.stringify({ params, method, headers });
|
||||
}
|
||||
this.addErrorLogInfo(errInfo as ErrorLogInfo);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Need to be used outside the setup
|
||||
export function useErrorLogStoreWithOut() {
|
||||
return useErrorLogStore(store);
|
||||
}
|
@ -1,44 +1,55 @@
|
||||
import store from '/@/store';
|
||||
import type { LocaleSetting, LocaleType } from '/#/config';
|
||||
|
||||
import { VuexModule, getModule, Module, Mutation, Action } from 'vuex-module-decorators';
|
||||
import { defineStore } from 'pinia';
|
||||
import { store } from '/@/store';
|
||||
|
||||
import { LOCALE_KEY } from '/@/enums/cacheEnum';
|
||||
|
||||
import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper';
|
||||
import { LocaleSetting, LocaleType } from '/#/config';
|
||||
import { createLocalStorage } from '/@/utils/cache';
|
||||
import { localeSetting } from '/@/settings/localeSetting';
|
||||
|
||||
const ls = createLocalStorage();
|
||||
|
||||
const lsSetting = (ls.get(LOCALE_KEY) || localeSetting) as LocaleSetting;
|
||||
const lsLocaleSetting = (ls.get(LOCALE_KEY) || localeSetting) as LocaleSetting;
|
||||
|
||||
const NAME = 'app-locale';
|
||||
hotModuleUnregisterModule(NAME);
|
||||
@Module({ dynamic: true, namespaced: true, store, name: NAME })
|
||||
class Locale extends VuexModule {
|
||||
private info: LocaleSetting = lsSetting;
|
||||
interface LocaleState {
|
||||
localInfo: LocaleSetting;
|
||||
}
|
||||
|
||||
get getShowPicker(): boolean {
|
||||
return !!this.info?.showPicker;
|
||||
}
|
||||
|
||||
get getLocale(): LocaleType {
|
||||
return this.info?.locale;
|
||||
}
|
||||
|
||||
@Mutation
|
||||
setLocaleInfo(info: Partial<LocaleSetting>): void {
|
||||
this.info = { ...this.info, ...info };
|
||||
ls.set(LOCALE_KEY, this.info);
|
||||
}
|
||||
|
||||
@Action
|
||||
initLocale(): void {
|
||||
export const useLocaleStore = defineStore({
|
||||
id: 'app-locale',
|
||||
state: (): LocaleState => ({
|
||||
localInfo: lsLocaleSetting,
|
||||
}),
|
||||
getters: {
|
||||
getShowPicker() {
|
||||
return !!this.localInfo?.showPicker;
|
||||
},
|
||||
getLocale(): LocaleType {
|
||||
return this.localInfo?.locale ?? 'zh_CN';
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
/**
|
||||
* Set up multilingual information and cache
|
||||
* @param info multilingual info
|
||||
*/
|
||||
setLocaleInfo(info: Partial<LocaleSetting>) {
|
||||
this.localInfo = { ...this.localInfo, ...info };
|
||||
ls.set(LOCALE_KEY, this.localInfo);
|
||||
},
|
||||
/**
|
||||
* Initialize multilingual information and load the existing configuration from the local cache
|
||||
*/
|
||||
initLocale() {
|
||||
this.setLocaleInfo({
|
||||
...localeSetting,
|
||||
...this.info,
|
||||
...this.localInfo,
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Need to be used outside the setup
|
||||
export function useLocaleStoreWithOut() {
|
||||
return useLocaleStore(store);
|
||||
}
|
||||
export const localeStore = getModule<Locale>(Locale);
|
||||
|
@ -1,47 +1,50 @@
|
||||
import type { LockInfo } from '/@/store/types';
|
||||
import type { LockInfo } from '/#/store';
|
||||
|
||||
import { VuexModule, getModule, Module, Mutation, Action } from 'vuex-module-decorators';
|
||||
import store from '/@/store';
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
import { LOCK_INFO_KEY } from '/@/enums/cacheEnum';
|
||||
|
||||
import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper';
|
||||
import { Persistent } from '/@/utils/cache/persistent';
|
||||
import { useUserStore } from './user';
|
||||
|
||||
import { userStore } from './user';
|
||||
interface LockState {
|
||||
lockInfo: Nullable<LockInfo>;
|
||||
}
|
||||
|
||||
const NAME = 'app-lock';
|
||||
hotModuleUnregisterModule(NAME);
|
||||
@Module({ dynamic: true, namespaced: true, store, name: NAME })
|
||||
class Lock extends VuexModule {
|
||||
// lock info
|
||||
private lockInfoState: LockInfo | null = Persistent.getLocal(LOCK_INFO_KEY);
|
||||
|
||||
get getLockInfo(): LockInfo {
|
||||
return this.lockInfoState || ({} as LockInfo);
|
||||
}
|
||||
|
||||
@Mutation
|
||||
commitLockInfoState(info: LockInfo): void {
|
||||
this.lockInfoState = Object.assign({}, this.lockInfoState, info);
|
||||
Persistent.setLocal(LOCK_INFO_KEY, this.lockInfoState);
|
||||
}
|
||||
|
||||
@Mutation
|
||||
resetLockInfo(): void {
|
||||
export const useLockStore = defineStore({
|
||||
id: 'app-lock',
|
||||
state: (): LockState => ({
|
||||
lockInfo: Persistent.getLocal(LOCK_INFO_KEY),
|
||||
}),
|
||||
getters: {
|
||||
getLockInfo() {
|
||||
return this.lockInfo;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
setLockInfo(info: LockInfo) {
|
||||
this.lockInfo = Object.assign({}, this.lockInfo, info);
|
||||
Persistent.setLocal(LOCK_INFO_KEY, this.lockInfo);
|
||||
},
|
||||
resetLockInfo() {
|
||||
Persistent.removeLocal(LOCK_INFO_KEY);
|
||||
this.lockInfoState = null;
|
||||
this.lockInfo = null;
|
||||
},
|
||||
// Unlock
|
||||
async unLock(password?: string) {
|
||||
const userStore = useUserStore();
|
||||
if (this.lockInfo?.pwd === password) {
|
||||
this.resetLockInfo();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: unlock page
|
||||
*/
|
||||
@Action
|
||||
public async unLockAction({ password }: { password: string }) {
|
||||
const tryLogin = async () => {
|
||||
try {
|
||||
const username = userStore.getUserInfoState.username;
|
||||
const res = await userStore.login({ username, password, goHome: false, mode: 'none' });
|
||||
const username = userStore.getUserInfo?.username;
|
||||
const res = await userStore.login({
|
||||
username,
|
||||
password: password!,
|
||||
goHome: false,
|
||||
mode: 'none',
|
||||
});
|
||||
if (res) {
|
||||
this.resetLockInfo();
|
||||
}
|
||||
@ -50,12 +53,7 @@ class Lock extends VuexModule {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
if (this.getLockInfo?.pwd === password) {
|
||||
this.resetLockInfo();
|
||||
return true;
|
||||
}
|
||||
return await tryLogin();
|
||||
}
|
||||
}
|
||||
export const lockStore = getModule<Lock>(Lock);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
288
src/store/modules/multipleTab.ts
Normal file
288
src/store/modules/multipleTab.ts
Normal file
@ -0,0 +1,288 @@
|
||||
import type { RouteLocationNormalized, RouteLocationRaw, Router } from 'vue-router';
|
||||
|
||||
import { toRaw, unref } from 'vue';
|
||||
import { defineStore } from 'pinia';
|
||||
import { store } from '/@/store';
|
||||
|
||||
import { useGo, useRedo } from '/@/hooks/web/usePage';
|
||||
|
||||
import { PageEnum } from '/@/enums/pageEnum';
|
||||
import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '/@/router/routes/basic';
|
||||
import { getRawRoute } from '/@/utils';
|
||||
|
||||
export interface MultipleTabState {
|
||||
cacheTabList: Set<string>;
|
||||
tabList: RouteLocationNormalized[];
|
||||
lastDragEndIndex: number;
|
||||
}
|
||||
|
||||
function handleGotoPage(router: Router) {
|
||||
const go = useGo(router);
|
||||
go(unref(router.currentRoute).path, true);
|
||||
}
|
||||
|
||||
export const useMultipleTabStore = defineStore({
|
||||
id: 'app-multiple-tab',
|
||||
state: (): MultipleTabState => ({
|
||||
// Tabs that need to be cached
|
||||
cacheTabList: new Set(),
|
||||
// multiple tab list
|
||||
tabList: [],
|
||||
// Index of the last moved tab
|
||||
lastDragEndIndex: 0,
|
||||
}),
|
||||
getters: {
|
||||
getTabList() {
|
||||
return this.tabList;
|
||||
},
|
||||
getCachedTabList(): string[] {
|
||||
return Array.from(this.cacheTabList);
|
||||
},
|
||||
getLastDragEndIndex(): number {
|
||||
return this.lastDragEndIndex;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
/**
|
||||
* Update the cache according to the currently opened tabs
|
||||
*/
|
||||
async updateCacheTab() {
|
||||
const cacheMap: Set<string> = new Set();
|
||||
|
||||
for (const tab of this.tabList) {
|
||||
const item = getRawRoute(tab);
|
||||
// Ignore the cache
|
||||
const needCache = !item.meta?.ignoreKeepAlive;
|
||||
if (!needCache) {
|
||||
return;
|
||||
}
|
||||
const name = item.name as string;
|
||||
cacheMap.add(name);
|
||||
}
|
||||
this.cacheTabList = cacheMap;
|
||||
},
|
||||
|
||||
/**
|
||||
* Refresh tabs
|
||||
*/
|
||||
async refreshPage(router: Router) {
|
||||
const { currentRoute } = router;
|
||||
const route = unref(currentRoute);
|
||||
const name = route.name;
|
||||
|
||||
const findTab = this.getCachedTabList.find((item) => item === name);
|
||||
if (findTab) {
|
||||
this.cacheTabList.delete(findTab);
|
||||
}
|
||||
const redo = useRedo(router);
|
||||
await redo();
|
||||
},
|
||||
clearCacheTabs(): void {
|
||||
this.cacheTabList = new Set();
|
||||
},
|
||||
resetState(): void {
|
||||
this.tabList = [];
|
||||
this.clearCacheTabs();
|
||||
},
|
||||
goToPage(router: Router) {
|
||||
const go = useGo(router);
|
||||
const len = this.tabList.length;
|
||||
const { path } = unref(router.currentRoute);
|
||||
|
||||
let toPath: PageEnum | string = PageEnum.BASE_HOME;
|
||||
|
||||
if (len > 0) {
|
||||
const page = this.tabList[len - 1];
|
||||
const p = page.fullPath || page.path;
|
||||
if (p) {
|
||||
toPath = p;
|
||||
}
|
||||
}
|
||||
// Jump to the current page and report an error
|
||||
path !== toPath && go(toPath as PageEnum, true);
|
||||
},
|
||||
|
||||
async addTab(route: RouteLocationNormalized) {
|
||||
const { path, name, fullPath, params, query } = getRawRoute(route);
|
||||
// 404 The page does not need to add a tab
|
||||
if (
|
||||
path === PageEnum.ERROR_PAGE ||
|
||||
!name ||
|
||||
[REDIRECT_ROUTE.name, PAGE_NOT_FOUND_ROUTE.name].includes(name as string)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
let updateIndex = -1;
|
||||
// Existing pages, do not add tabs repeatedly
|
||||
const tabHasExits = this.tabList.some((tab, index) => {
|
||||
updateIndex = index;
|
||||
return (tab.fullPath || tab.path) === (fullPath || path);
|
||||
});
|
||||
|
||||
// If the tab already exists, perform the update operation
|
||||
if (tabHasExits) {
|
||||
const curTab = toRaw(this.tabList)[updateIndex];
|
||||
if (!curTab) {
|
||||
return;
|
||||
}
|
||||
curTab.params = params || curTab.params;
|
||||
curTab.query = query || curTab.query;
|
||||
curTab.fullPath = fullPath || curTab.fullPath;
|
||||
this.tabList.splice(updateIndex, 1, curTab);
|
||||
return;
|
||||
}
|
||||
// Add tab
|
||||
this.tabList.push(route);
|
||||
this.updateCacheTab();
|
||||
},
|
||||
|
||||
async closeTab(tab: RouteLocationNormalized, router: Router) {
|
||||
const getToTarget = (tabItem: RouteLocationNormalized) => {
|
||||
const { params, path, query } = tabItem;
|
||||
return {
|
||||
params: params || {},
|
||||
path,
|
||||
query: query || {},
|
||||
};
|
||||
};
|
||||
|
||||
const close = (route: RouteLocationNormalized) => {
|
||||
const { fullPath, meta: { affix } = {} } = route;
|
||||
if (affix) {
|
||||
return;
|
||||
}
|
||||
const index = this.tabList.findIndex((item) => item.fullPath === fullPath);
|
||||
index !== -1 && this.tabList.splice(index, 1);
|
||||
};
|
||||
|
||||
const { currentRoute, replace } = router;
|
||||
|
||||
const { path } = unref(currentRoute);
|
||||
if (path !== tab.path) {
|
||||
// Closed is not the activation tab
|
||||
close(tab);
|
||||
return;
|
||||
}
|
||||
|
||||
// Closed is activated atb
|
||||
let toTarget: RouteLocationRaw = {};
|
||||
|
||||
const index = this.tabList.findIndex((item) => item.path === path);
|
||||
|
||||
// If the current is the leftmost tab
|
||||
if (index === 0) {
|
||||
// There is only one tab, then jump to the homepage, otherwise jump to the right tab
|
||||
if (this.tabList.length === 1) {
|
||||
toTarget = PageEnum.BASE_HOME;
|
||||
} else {
|
||||
// Jump to the right tab
|
||||
const page = this.tabList[index + 1];
|
||||
toTarget = getToTarget(page);
|
||||
}
|
||||
} else {
|
||||
// Close the current tab
|
||||
const page = this.tabList[index - 1];
|
||||
toTarget = getToTarget(page);
|
||||
}
|
||||
close(currentRoute.value);
|
||||
replace(toTarget);
|
||||
},
|
||||
|
||||
// Close according to key
|
||||
async closeTabByKey(key: string, router: Router) {
|
||||
const index = this.tabList.findIndex((item) => (item.fullPath || item.path) === key);
|
||||
index !== -1 && this.closeTab(this.tabList[index], router);
|
||||
},
|
||||
|
||||
// Sort the tabs
|
||||
async sortTabs(oldIndex: number, newIndex: number) {
|
||||
const currentTab = this.tabList[oldIndex];
|
||||
this.tabList.splice(oldIndex, 1);
|
||||
this.tabList.splice(newIndex, 0, currentTab);
|
||||
this.lastDragEndIndex = this.lastDragEndIndex + 1;
|
||||
},
|
||||
|
||||
// Close the tab on the right and jump
|
||||
async closeLeftTabs(route: RouteLocationNormalized, router: Router) {
|
||||
const index = this.tabList.findIndex((item) => item.path === route.path);
|
||||
|
||||
if (index > 0) {
|
||||
const leftTabs = this.tabList.slice(0, index);
|
||||
const pathList: string[] = [];
|
||||
for (const item of leftTabs) {
|
||||
const affix = item?.meta?.affix ?? false;
|
||||
if (!affix) {
|
||||
pathList.push(item.fullPath);
|
||||
}
|
||||
}
|
||||
this.bulkCloseTabs(pathList);
|
||||
}
|
||||
this.updateCacheTab();
|
||||
handleGotoPage(router);
|
||||
},
|
||||
|
||||
// Close the tab on the left and jump
|
||||
async closeRightTabs(route: RouteLocationNormalized, router: Router) {
|
||||
const index = this.tabList.findIndex((item) => item.fullPath === route.fullPath);
|
||||
|
||||
if (index >= 0 && index < this.tabList.length - 1) {
|
||||
const rightTabs = this.tabList.slice(index + 1, this.tabList.length);
|
||||
|
||||
const pathList: string[] = [];
|
||||
for (const item of rightTabs) {
|
||||
const affix = item?.meta?.affix ?? false;
|
||||
if (!affix) {
|
||||
pathList.push(item.fullPath);
|
||||
}
|
||||
}
|
||||
this.bulkCloseTabs(pathList);
|
||||
}
|
||||
this.updateCacheTab();
|
||||
handleGotoPage(router);
|
||||
},
|
||||
|
||||
async closeAllTab(router: Router) {
|
||||
this.tabList = this.tabList.filter((item) => item?.meta?.affix ?? false);
|
||||
this.clearCacheTabs();
|
||||
this.goToPage(router);
|
||||
},
|
||||
|
||||
/**
|
||||
* Close other tabs
|
||||
*/
|
||||
async closeOtherTabs(route: RouteLocationNormalized, router: Router) {
|
||||
const closePathList = this.tabList.map((item) => item.fullPath);
|
||||
|
||||
const pathList: string[] = [];
|
||||
|
||||
for (const path of closePathList) {
|
||||
if (path !== route.fullPath) {
|
||||
const closeItem = this.tabList.find((item) => item.path === path);
|
||||
if (!closeItem) {
|
||||
return;
|
||||
}
|
||||
const affix = closeItem?.meta?.affix ?? false;
|
||||
if (!affix) {
|
||||
pathList.push(closeItem.fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.bulkCloseTabs(pathList);
|
||||
this.updateCacheTab();
|
||||
handleGotoPage(router);
|
||||
},
|
||||
|
||||
/**
|
||||
* Close tabs in bulk
|
||||
*/
|
||||
async bulkCloseTabs(pathList: string[]) {
|
||||
this.tabList = this.tabList.filter((item) => !pathList.includes(item.fullPath));
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Need to be used outside the setup
|
||||
export function useMultipleTabWithOutStore() {
|
||||
return useMultipleTabStore(store);
|
||||
}
|
@ -1,21 +1,20 @@
|
||||
import type { AppRouteRecordRaw, Menu } from '/@/router/types';
|
||||
|
||||
import store from '/@/store';
|
||||
import { defineStore } from 'pinia';
|
||||
import { store } from '/@/store';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import { useUserStore } from './user';
|
||||
import { useAppStoreWidthOut } from './app';
|
||||
import { toRaw } from 'vue';
|
||||
import { VuexModule, Mutation, Module, getModule, Action } from 'vuex-module-decorators';
|
||||
import { transformObjToRoute, flatMultiLevelRoutes } from '/@/router/helper/routeHelper';
|
||||
import { transformRouteToMenu } from '/@/router/helper/menuHelper';
|
||||
|
||||
import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper';
|
||||
import projectSetting from '/@/settings/projectSetting';
|
||||
|
||||
import { PermissionModeEnum } from '/@/enums/appEnum';
|
||||
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { userStore } from '/@/store/modules/user';
|
||||
import projectSetting from '/@/settings/projectSetting';
|
||||
|
||||
import { asyncRoutes } from '/@/router/routes';
|
||||
import { ERROR_LOG_ROUTE, PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic';
|
||||
import { transformObjToRoute, flatMultiLevelRoutes } from '/@/router/helper/routeHelper';
|
||||
import { transformRouteToMenu } from '/@/router/helper/menuHelper';
|
||||
|
||||
import { filter } from '/@/utils/helper/treeHelper';
|
||||
|
||||
@ -23,79 +22,75 @@ import { getMenuListById } from '/@/api/sys/menu';
|
||||
import { getPermCodeByUserId } from '/@/api/sys/user';
|
||||
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
|
||||
const NAME = 'app-permission';
|
||||
hotModuleUnregisterModule(NAME);
|
||||
@Module({ dynamic: true, namespaced: true, store, name: NAME })
|
||||
class Permission extends VuexModule {
|
||||
interface PermissionState {
|
||||
// Permission code list
|
||||
private permCodeListState: string[] = [];
|
||||
|
||||
permCodeList: string[];
|
||||
// Whether the route has been dynamically added
|
||||
private isDynamicAddedRouteState = false;
|
||||
|
||||
isDynamicAddedRoute: boolean;
|
||||
// To trigger a menu update
|
||||
private lastBuildMenuTimeState = 0;
|
||||
|
||||
lastBuildMenuTime: number;
|
||||
// Backstage menu list
|
||||
private backMenuListState: Menu[] = [];
|
||||
backMenuList: Menu[];
|
||||
}
|
||||
export const usePermissionStore = defineStore({
|
||||
id: 'app-permission',
|
||||
state: (): PermissionState => ({
|
||||
permCodeList: [],
|
||||
// Whether the route has been dynamically added
|
||||
isDynamicAddedRoute: false,
|
||||
// To trigger a menu update
|
||||
lastBuildMenuTime: 0,
|
||||
// Backstage menu list
|
||||
backMenuList: [],
|
||||
}),
|
||||
getters: {
|
||||
getPermCodeList() {
|
||||
return this.permCodeList;
|
||||
},
|
||||
getBackMenuList() {
|
||||
return this.backMenuList;
|
||||
},
|
||||
getLastBuildMenuTime() {
|
||||
return this.lastBuildMenuTime;
|
||||
},
|
||||
getIsDynamicAddedRoute() {
|
||||
return this.isDynamicAddedRoute;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
setPermCodeList(codeList: string[]) {
|
||||
this.permCodeList = codeList;
|
||||
},
|
||||
|
||||
get getPermCodeListState() {
|
||||
return this.permCodeListState;
|
||||
}
|
||||
setBackMenuList(list: Menu[]) {
|
||||
this.backMenuList = list;
|
||||
},
|
||||
|
||||
get getBackMenuListState() {
|
||||
return this.backMenuListState;
|
||||
}
|
||||
setLastBuildMenuTime() {
|
||||
this.lastBuildMenuTime = new Date().getTime();
|
||||
},
|
||||
|
||||
get getLastBuildMenuTimeState() {
|
||||
return this.lastBuildMenuTimeState;
|
||||
}
|
||||
|
||||
get getIsDynamicAddedRouteState() {
|
||||
return this.isDynamicAddedRouteState;
|
||||
}
|
||||
|
||||
@Mutation
|
||||
commitPermCodeListState(codeList: string[]): void {
|
||||
this.permCodeListState = codeList;
|
||||
}
|
||||
|
||||
@Mutation
|
||||
commitBackMenuListState(list: Menu[]): void {
|
||||
this.backMenuListState = list;
|
||||
}
|
||||
|
||||
@Mutation
|
||||
commitLastBuildMenuTimeState(): void {
|
||||
this.lastBuildMenuTimeState = new Date().getTime();
|
||||
}
|
||||
|
||||
@Mutation
|
||||
commitDynamicAddedRouteState(added: boolean): void {
|
||||
this.isDynamicAddedRouteState = added;
|
||||
}
|
||||
|
||||
@Mutation
|
||||
commitResetState(): void {
|
||||
this.isDynamicAddedRouteState = false;
|
||||
this.permCodeListState = [];
|
||||
this.backMenuListState = [];
|
||||
this.lastBuildMenuTimeState = 0;
|
||||
}
|
||||
|
||||
@Action
|
||||
setDynamicAddedRoute(added: boolean) {
|
||||
this.isDynamicAddedRoute = added;
|
||||
},
|
||||
resetState(): void {
|
||||
this.isDynamicAddedRoute = false;
|
||||
this.permCodeList = [];
|
||||
this.backMenuList = [];
|
||||
this.lastBuildMenuTime = 0;
|
||||
},
|
||||
async changePermissionCode(userId: string) {
|
||||
const codeList = await getPermCodeByUserId({ userId });
|
||||
this.commitPermCodeListState(codeList);
|
||||
}
|
||||
|
||||
@Action
|
||||
this.setPermCodeList(codeList);
|
||||
},
|
||||
async buildRoutesAction(id?: number | string): Promise<AppRouteRecordRaw[]> {
|
||||
const { t } = useI18n();
|
||||
const userStore = useUserStore();
|
||||
const appStore = useAppStoreWidthOut();
|
||||
|
||||
let routes: AppRouteRecordRaw[] = [];
|
||||
const roleList = toRaw(userStore.getRoleListState);
|
||||
const roleList = toRaw(userStore.getRoleList);
|
||||
const { permissionMode = projectSetting.permissionMode } = appStore.getProjectConfig;
|
||||
// role permissions
|
||||
if (permissionMode === PermissionModeEnum.ROLE) {
|
||||
@ -118,13 +113,14 @@ class Permission extends VuexModule {
|
||||
duration: 1,
|
||||
});
|
||||
// Here to get the background routing menu logic to modify by yourself
|
||||
const paramId = id || userStore.getUserInfoState.userId;
|
||||
const paramId = id || userStore.getUserInfo?.userId;
|
||||
|
||||
// !Simulate to obtain permission codes from the background,
|
||||
// this function may only need to be executed once, and the actual project can be put at the right time by itself
|
||||
try {
|
||||
this.changePermissionCode('1');
|
||||
} catch (error) {}
|
||||
|
||||
if (!paramId) {
|
||||
throw new Error('paramId is undefined!');
|
||||
}
|
||||
@ -135,13 +131,18 @@ class Permission extends VuexModule {
|
||||
|
||||
// Background routing to menu structure
|
||||
const backMenuList = transformRouteToMenu(routeList);
|
||||
this.commitBackMenuListState(backMenuList);
|
||||
this.setBackMenuList(backMenuList);
|
||||
|
||||
routeList = flatMultiLevelRoutes(routeList);
|
||||
routes = [PAGE_NOT_FOUND_ROUTE, ...routeList];
|
||||
}
|
||||
routes.push(ERROR_LOG_ROUTE);
|
||||
return routes;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Need to be used outside the setup
|
||||
export function usePermissionStoreWidthOut() {
|
||||
return usePermissionStore(store);
|
||||
}
|
||||
export const permissionStore = getModule<Permission>(Permission);
|
||||
|
@ -1,294 +0,0 @@
|
||||
import type { RouteLocationNormalized, RouteLocationRaw } from 'vue-router';
|
||||
|
||||
import { toRaw, unref } from 'vue';
|
||||
import { Action, Module, Mutation, VuexModule, getModule } from 'vuex-module-decorators';
|
||||
import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper';
|
||||
|
||||
import { PageEnum } from '/@/enums/pageEnum';
|
||||
|
||||
import store from '/@/store';
|
||||
import router from '/@/router';
|
||||
import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '/@/router/routes/basic';
|
||||
import { getRawRoute } from '/@/utils';
|
||||
|
||||
import { useGo, useRedo } from '/@/hooks/web/usePage';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
const NAME = 'app-tab';
|
||||
|
||||
hotModuleUnregisterModule(NAME);
|
||||
|
||||
function isGotoPage() {
|
||||
const go = useGo();
|
||||
go(unref(router.currentRoute).path, true);
|
||||
}
|
||||
|
||||
@Module({ namespaced: true, name: NAME, dynamic: true, store })
|
||||
class Tab extends VuexModule {
|
||||
cachedTabsState: Set<string> = new Set();
|
||||
|
||||
// tab list
|
||||
tabsState: RouteLocationNormalized[] = [];
|
||||
|
||||
lastDragEndIndexState = 0;
|
||||
|
||||
get getTabsState() {
|
||||
return this.tabsState;
|
||||
}
|
||||
|
||||
get getCurrentTab(): RouteLocationNormalized {
|
||||
const route = unref(router.currentRoute);
|
||||
return this.tabsState.find((item) => item.path === route.path)!;
|
||||
}
|
||||
|
||||
get getCachedTabsState(): string[] {
|
||||
return Array.from(this.cachedTabsState);
|
||||
}
|
||||
|
||||
get getLastDragEndIndexState(): number {
|
||||
return this.lastDragEndIndexState;
|
||||
}
|
||||
|
||||
@Mutation
|
||||
commitClearCache(): void {
|
||||
this.cachedTabsState = new Set();
|
||||
}
|
||||
|
||||
@Mutation
|
||||
goToPage() {
|
||||
const go = useGo();
|
||||
const len = this.tabsState.length;
|
||||
const { path } = unref(router.currentRoute);
|
||||
|
||||
let toPath: PageEnum | string = PageEnum.BASE_HOME;
|
||||
|
||||
if (len > 0) {
|
||||
const page = this.tabsState[len - 1];
|
||||
const p = page.fullPath || page.path;
|
||||
if (p) {
|
||||
toPath = p;
|
||||
}
|
||||
}
|
||||
// Jump to the current page and report an error
|
||||
path !== toPath && go(toPath as PageEnum, true);
|
||||
}
|
||||
|
||||
@Mutation
|
||||
commitCachedMapState(): void {
|
||||
const cacheMap: Set<string> = new Set();
|
||||
|
||||
this.tabsState.forEach((tab) => {
|
||||
const item = getRawRoute(tab);
|
||||
const needCache = !item.meta?.ignoreKeepAlive;
|
||||
if (!needCache) return;
|
||||
const name = item.name as string;
|
||||
cacheMap.add(name);
|
||||
});
|
||||
this.cachedTabsState = cacheMap;
|
||||
}
|
||||
|
||||
@Mutation
|
||||
commitTabRoutesState(route: RouteLocationNormalized) {
|
||||
const { path, fullPath, params, query } = route;
|
||||
|
||||
let updateIndex = -1;
|
||||
// Existing pages, do not add tabs repeatedly
|
||||
const hasTab = this.tabsState.some((tab, index) => {
|
||||
updateIndex = index;
|
||||
return (tab.fullPath || tab.path) === (fullPath || path);
|
||||
});
|
||||
if (hasTab) {
|
||||
const curTab = toRaw(this.tabsState)[updateIndex];
|
||||
if (!curTab) return;
|
||||
curTab.params = params || curTab.params;
|
||||
curTab.query = query || curTab.query;
|
||||
curTab.fullPath = fullPath || curTab.fullPath;
|
||||
this.tabsState.splice(updateIndex, 1, curTab);
|
||||
return;
|
||||
}
|
||||
this.tabsState = cloneDeep([...this.tabsState, route]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: close tab
|
||||
*/
|
||||
@Mutation
|
||||
commitCloseTab(route: RouteLocationNormalized): void {
|
||||
const { fullPath, meta: { affix } = {} } = route;
|
||||
if (affix) return;
|
||||
const index = this.tabsState.findIndex((item) => item.fullPath === fullPath);
|
||||
index !== -1 && this.tabsState.splice(index, 1);
|
||||
}
|
||||
|
||||
@Mutation
|
||||
commitCloseAllTab(): void {
|
||||
this.tabsState = this.tabsState.filter((item) => {
|
||||
return item.meta && item.meta.affix;
|
||||
});
|
||||
}
|
||||
|
||||
@Mutation
|
||||
commitResetState(): void {
|
||||
this.tabsState = [];
|
||||
this.cachedTabsState = new Set();
|
||||
}
|
||||
|
||||
@Mutation
|
||||
commitSortTabs({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }): void {
|
||||
const currentTab = this.tabsState[oldIndex];
|
||||
|
||||
this.tabsState.splice(oldIndex, 1);
|
||||
this.tabsState.splice(newIndex, 0, currentTab);
|
||||
this.lastDragEndIndexState = this.lastDragEndIndexState + 1;
|
||||
}
|
||||
|
||||
@Mutation
|
||||
closeMultipleTab({ pathList }: { pathList: string[] }): void {
|
||||
this.tabsState = toRaw(this.tabsState).filter((item) => !pathList.includes(item.fullPath));
|
||||
}
|
||||
|
||||
@Action
|
||||
addTabAction(route: RouteLocationNormalized) {
|
||||
const { path, name } = route;
|
||||
// 404 The page does not need to add a tab
|
||||
if (
|
||||
path === PageEnum.ERROR_PAGE ||
|
||||
!name ||
|
||||
[REDIRECT_ROUTE.name, PAGE_NOT_FOUND_ROUTE.name].includes(name as string)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
this.commitTabRoutesState(getRawRoute(route));
|
||||
|
||||
this.commitCachedMapState();
|
||||
}
|
||||
|
||||
@Mutation
|
||||
async commitRedoPage() {
|
||||
const route = router.currentRoute.value;
|
||||
const name = route.name;
|
||||
|
||||
const findVal = Array.from(this.cachedTabsState).find((item) => item === name);
|
||||
if (findVal) {
|
||||
this.cachedTabsState.delete(findVal);
|
||||
// this.cachedTabsState.splice(index, 1);
|
||||
}
|
||||
const redo = useRedo();
|
||||
await redo();
|
||||
}
|
||||
|
||||
@Action
|
||||
closeAllTabAction() {
|
||||
this.commitCloseAllTab();
|
||||
this.commitClearCache();
|
||||
this.goToPage();
|
||||
}
|
||||
|
||||
@Action
|
||||
closeTabAction(tab: RouteLocationNormalized) {
|
||||
function getObj(tabItem: RouteLocationNormalized) {
|
||||
const { params, path, query } = tabItem;
|
||||
return {
|
||||
params: params || {},
|
||||
path,
|
||||
query: query || {},
|
||||
};
|
||||
}
|
||||
const { currentRoute, replace } = router;
|
||||
|
||||
const { path } = unref(currentRoute);
|
||||
if (path !== tab.path) {
|
||||
// Closed is not the activation tab
|
||||
this.commitCloseTab(tab);
|
||||
return;
|
||||
}
|
||||
|
||||
// Closed is activated atb
|
||||
let toObj: RouteLocationRaw = {};
|
||||
|
||||
const index = this.getTabsState.findIndex((item) => item.path === path);
|
||||
|
||||
// If the current is the leftmost tab
|
||||
if (index === 0) {
|
||||
// There is only one tab, then jump to the homepage, otherwise jump to the right tab
|
||||
if (this.getTabsState.length === 1) {
|
||||
toObj = PageEnum.BASE_HOME;
|
||||
} else {
|
||||
// Jump to the right tab
|
||||
const page = this.getTabsState[index + 1];
|
||||
toObj = getObj(page);
|
||||
}
|
||||
} else {
|
||||
// Close the current tab
|
||||
const page = this.getTabsState[index - 1];
|
||||
toObj = getObj(page);
|
||||
}
|
||||
this.commitCloseTab(currentRoute.value);
|
||||
replace(toObj);
|
||||
}
|
||||
|
||||
@Action
|
||||
closeTabByKeyAction(key: string) {
|
||||
const index = this.tabsState.findIndex((item) => (item.fullPath || item.path) === key);
|
||||
index !== -1 && this.closeTabAction(this.tabsState[index]);
|
||||
}
|
||||
|
||||
@Action
|
||||
closeLeftTabAction(route: RouteLocationNormalized): void {
|
||||
const index = this.tabsState.findIndex((item) => item.path === route.path);
|
||||
|
||||
if (index > 0) {
|
||||
const leftTabs = this.tabsState.slice(0, index);
|
||||
const pathList: string[] = [];
|
||||
for (const item of leftTabs) {
|
||||
const affix = item.meta ? item.meta.affix : false;
|
||||
if (!affix) {
|
||||
pathList.push(item.fullPath);
|
||||
}
|
||||
}
|
||||
this.closeMultipleTab({ pathList });
|
||||
}
|
||||
this.commitCachedMapState();
|
||||
isGotoPage();
|
||||
}
|
||||
|
||||
@Action
|
||||
closeRightTabAction(route: RouteLocationNormalized): void {
|
||||
const index = this.tabsState.findIndex((item) => item.fullPath === route.fullPath);
|
||||
|
||||
if (index >= 0 && index < this.tabsState.length - 1) {
|
||||
const rightTabs = this.tabsState.slice(index + 1, this.tabsState.length);
|
||||
|
||||
const pathList: string[] = [];
|
||||
for (const item of rightTabs) {
|
||||
const affix = item.meta ? item.meta.affix : false;
|
||||
if (!affix) {
|
||||
pathList.push(item.fullPath);
|
||||
}
|
||||
}
|
||||
this.closeMultipleTab({ pathList });
|
||||
}
|
||||
this.commitCachedMapState();
|
||||
isGotoPage();
|
||||
}
|
||||
|
||||
@Action
|
||||
closeOtherTabAction(route: RouteLocationNormalized): void {
|
||||
const closePathList = this.tabsState.map((item) => item.fullPath);
|
||||
const pathList: string[] = [];
|
||||
closePathList.forEach((path) => {
|
||||
if (path !== route.fullPath) {
|
||||
const closeItem = this.tabsState.find((item) => item.path === path);
|
||||
if (!closeItem) return;
|
||||
const affix = closeItem.meta ? closeItem.meta.affix : false;
|
||||
if (!affix) {
|
||||
pathList.push(closeItem.fullPath);
|
||||
}
|
||||
}
|
||||
});
|
||||
this.closeMultipleTab({ pathList });
|
||||
this.commitCachedMapState();
|
||||
isGotoPage();
|
||||
}
|
||||
}
|
||||
export const tabStore = getModule<Tab>(Tab);
|
@ -1,83 +1,74 @@
|
||||
import type {
|
||||
LoginParams,
|
||||
GetUserInfoByUserIdModel,
|
||||
GetUserInfoByUserIdParams,
|
||||
} from '/@/api/sys/model/userModel';
|
||||
import type { UserInfo } from '/@/store/types';
|
||||
import type { UserInfo } from '/#/store';
|
||||
import type { ErrorMessageMode } from '/@/utils/http/axios/types';
|
||||
|
||||
import store from '/@/store/index';
|
||||
import { VuexModule, Module, getModule, Mutation, Action } from 'vuex-module-decorators';
|
||||
import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper';
|
||||
import { defineStore } from 'pinia';
|
||||
import { store } from '/@/store';
|
||||
|
||||
import { PageEnum } from '/@/enums/pageEnum';
|
||||
import { RoleEnum } from '/@/enums/roleEnum';
|
||||
import { PageEnum } from '/@/enums/pageEnum';
|
||||
import { ROLES_KEY, TOKEN_KEY, USER_INFO_KEY } from '/@/enums/cacheEnum';
|
||||
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { getAuthCache, setAuthCache } from '/@/utils/auth';
|
||||
import {
|
||||
GetUserInfoByUserIdModel,
|
||||
GetUserInfoByUserIdParams,
|
||||
LoginParams,
|
||||
} from '/@/api/sys/model/userModel';
|
||||
|
||||
import router from '/@/router';
|
||||
|
||||
import { loginApi, getUserInfoById } from '/@/api/sys/user';
|
||||
import { getUserInfoById, loginApi } from '/@/api/sys/user';
|
||||
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import { ErrorMessageMode } from '/@/utils/http/axios/types';
|
||||
import { getAuthCache, setAuthCache } from '/@/utils/auth/index';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import router from '/@/router';
|
||||
|
||||
const NAME = 'app-user';
|
||||
hotModuleUnregisterModule(NAME);
|
||||
interface UserState {
|
||||
userInfo: Nullable<UserInfo>;
|
||||
token?: string;
|
||||
roleList: RoleEnum[];
|
||||
}
|
||||
|
||||
@Module({ namespaced: true, name: NAME, dynamic: true, store })
|
||||
class User extends VuexModule {
|
||||
export const useUserStore = defineStore({
|
||||
id: 'app-user',
|
||||
state: (): UserState => ({
|
||||
// user info
|
||||
private userInfoState: UserInfo | null = null;
|
||||
|
||||
userInfo: null,
|
||||
// token
|
||||
private tokenState = '';
|
||||
|
||||
token: undefined,
|
||||
// roleList
|
||||
private roleListState: RoleEnum[] = [];
|
||||
|
||||
get getUserInfoState(): UserInfo {
|
||||
return this.userInfoState || getAuthCache<UserInfo>(USER_INFO_KEY) || {};
|
||||
}
|
||||
|
||||
get getTokenState(): string {
|
||||
return this.tokenState || getAuthCache<string>(TOKEN_KEY);
|
||||
}
|
||||
|
||||
get getRoleListState(): RoleEnum[] {
|
||||
return this.roleListState.length > 0 ? this.roleListState : getAuthCache<RoleEnum[]>(ROLES_KEY);
|
||||
}
|
||||
|
||||
@Mutation
|
||||
commitResetState(): void {
|
||||
this.userInfoState = null;
|
||||
this.tokenState = '';
|
||||
this.roleListState = [];
|
||||
}
|
||||
|
||||
@Mutation
|
||||
commitUserInfoState(info: UserInfo): void {
|
||||
this.userInfoState = info;
|
||||
setAuthCache(USER_INFO_KEY, info);
|
||||
}
|
||||
|
||||
@Mutation
|
||||
commitRoleListState(roleList: RoleEnum[]): void {
|
||||
this.roleListState = roleList;
|
||||
setAuthCache(ROLES_KEY, roleList);
|
||||
}
|
||||
|
||||
@Mutation
|
||||
commitTokenState(info: string): void {
|
||||
this.tokenState = info;
|
||||
roleList: [],
|
||||
}),
|
||||
getters: {
|
||||
getUserInfo(): UserInfo {
|
||||
return this.userInfo || getAuthCache<UserInfo>(USER_INFO_KEY) || {};
|
||||
},
|
||||
getToken(): string {
|
||||
return this.token || getAuthCache<string>(TOKEN_KEY);
|
||||
},
|
||||
getRoleList(): RoleEnum[] {
|
||||
return this.roleList.length > 0 ? this.roleList : getAuthCache<RoleEnum[]>(ROLES_KEY);
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
setToken(info: string) {
|
||||
this.token = info;
|
||||
setAuthCache(TOKEN_KEY, info);
|
||||
}
|
||||
|
||||
},
|
||||
setRoleList(roleList: RoleEnum[]) {
|
||||
this.roleList = roleList;
|
||||
setAuthCache(ROLES_KEY, roleList);
|
||||
},
|
||||
setUserInfo(info: UserInfo) {
|
||||
this.userInfo = info;
|
||||
setAuthCache(USER_INFO_KEY, info);
|
||||
},
|
||||
resetState() {
|
||||
this.userInfo = null;
|
||||
this.token = '';
|
||||
this.roleList = [];
|
||||
},
|
||||
/**
|
||||
* @description: login
|
||||
*/
|
||||
@Action
|
||||
async login(
|
||||
params: LoginParams & {
|
||||
goHome?: boolean;
|
||||
@ -87,12 +78,10 @@ class User extends VuexModule {
|
||||
try {
|
||||
const { goHome = true, mode, ...loginParams } = params;
|
||||
const data = await loginApi(loginParams, mode);
|
||||
|
||||
const { token, userId } = data;
|
||||
|
||||
// save token
|
||||
this.commitTokenState(token);
|
||||
|
||||
this.setToken(token);
|
||||
// get user info
|
||||
const userInfo = await this.getUserInfoAction({ userId });
|
||||
|
||||
@ -101,31 +90,26 @@ class User extends VuexModule {
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Action
|
||||
},
|
||||
async getUserInfoAction({ userId }: GetUserInfoByUserIdParams) {
|
||||
const userInfo = await getUserInfoById({ userId });
|
||||
const { roles } = userInfo;
|
||||
const roleList = roles.map((item) => item.value) as RoleEnum[];
|
||||
this.commitUserInfoState(userInfo);
|
||||
this.commitRoleListState(roleList);
|
||||
this.setUserInfo(userInfo);
|
||||
this.setRoleList(roleList);
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
},
|
||||
/**
|
||||
* @description: logout
|
||||
*/
|
||||
@Action
|
||||
async logout(goLogin = false) {
|
||||
logout(goLogin = false) {
|
||||
goLogin && router.push(PageEnum.BASE_LOGIN);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @description: Confirm before logging out
|
||||
*/
|
||||
@Action
|
||||
async confirmLoginOut() {
|
||||
confirmLoginOut() {
|
||||
const { createConfirm } = useMessage();
|
||||
const { t } = useI18n();
|
||||
createConfirm({
|
||||
@ -136,6 +120,11 @@ class User extends VuexModule {
|
||||
await this.logout(true);
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Need to be used outside the setup
|
||||
export function useUserStoreWidthOut() {
|
||||
return useUserStore(store);
|
||||
}
|
||||
export const userStore = getModule<User>(User);
|
||||
|
@ -1,24 +0,0 @@
|
||||
import { MenuModeEnum, MenuTypeEnum } from '../enums/menuEnum';
|
||||
|
||||
export interface LockInfo {
|
||||
pwd: string | undefined;
|
||||
isLock: boolean;
|
||||
}
|
||||
|
||||
export interface UserInfo {
|
||||
// 用户id
|
||||
userId: string | number;
|
||||
// 用户名
|
||||
username: string;
|
||||
// 真实名字
|
||||
realName: string;
|
||||
// 介绍
|
||||
desc?: string;
|
||||
}
|
||||
|
||||
export interface BeforeMiniState {
|
||||
menuCollapsed?: boolean;
|
||||
menuSplit?: boolean;
|
||||
menuMode?: MenuModeEnum;
|
||||
menuType?: MenuTypeEnum;
|
||||
}
|
5
src/utils/cache/persistent.ts
vendored
5
src/utils/cache/persistent.ts
vendored
@ -1,6 +1,5 @@
|
||||
import type { LockInfo, UserInfo } from '/@/store/types';
|
||||
|
||||
import { ProjectConfig } from '/#/config';
|
||||
import type { LockInfo, UserInfo } from '/#/store';
|
||||
import type { ProjectConfig } from '/#/config';
|
||||
|
||||
import { createLocalStorage, createSessionStorage } from '/@/utils/cache';
|
||||
import { Memory } from './memory';
|
||||
|
@ -35,6 +35,7 @@ export function getAppEnvConfig() {
|
||||
`VITE_GLOB_APP_SHORT_NAME Variables can only be characters/underscores, please modify in the environment variables and re-running.`
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
VITE_GLOB_APP_TITLE,
|
||||
VITE_GLOB_API_URL,
|
||||
|
@ -16,7 +16,8 @@ import { RequestEnum, ResultEnum, ContentTypeEnum } from '/@/enums/httpEnum';
|
||||
import { isString } from '/@/utils/is';
|
||||
import { getToken } from '/@/utils/auth';
|
||||
import { setObjToUrlParams, deepMerge } from '/@/utils';
|
||||
import { errorStore } from '/@/store/modules/error';
|
||||
import { useErrorLogStoreWithOut } from '/@/store/modules/errorLog';
|
||||
|
||||
import { errorResult } from './const';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import { createNow, formatRequestDate } from './helper';
|
||||
@ -150,7 +151,8 @@ const transform: AxiosTransform = {
|
||||
*/
|
||||
responseInterceptorsCatch: (error: any) => {
|
||||
const { t } = useI18n();
|
||||
errorStore.setupErrorHandle(error);
|
||||
const errorLogStore = useErrorLogStoreWithOut();
|
||||
errorLogStore.addAjaxErrorInfo(error);
|
||||
const { response, code, message } = error || {};
|
||||
const msg: string = response?.data?.error?.message ?? '';
|
||||
const err: string = error?.toString?.() ?? '';
|
||||
|
@ -10,7 +10,7 @@
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed } from 'vue';
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { useAppStore } from '/@/store/modules/app';
|
||||
import { PermissionModeEnum } from '/@/enums/appEnum';
|
||||
import { Divider } from 'ant-design-vue';
|
||||
import { usePermission } from '/@/hooks/web/usePermission';
|
||||
@ -18,9 +18,8 @@
|
||||
name: 'CurrentPermissionMode',
|
||||
components: { Divider },
|
||||
setup() {
|
||||
const permissionMode = computed(() => {
|
||||
return appStore.getProjectConfig.permissionMode;
|
||||
});
|
||||
const appStore = useAppStore();
|
||||
const permissionMode = computed(() => appStore.getProjectConfig.permissionMode);
|
||||
const { togglePermissionMode } = usePermission();
|
||||
|
||||
return {
|
||||
|
@ -5,7 +5,7 @@
|
||||
<CurrentPermissionMode />
|
||||
|
||||
<p>
|
||||
当前拥有的code列表: <a> {{ permissionStore.getPermCodeListState }} </a>
|
||||
当前拥有的code列表: <a> {{ permissionStore.getPermCodeList }} </a>
|
||||
</p>
|
||||
<Divider />
|
||||
<Alert class="mt-4" type="info" message="点击后请查看按钮变化" show-icon />
|
||||
@ -59,7 +59,7 @@
|
||||
import CurrentPermissionMode from '../CurrentPermissionMode.vue';
|
||||
import { usePermission } from '/@/hooks/web/usePermission';
|
||||
import { Authority } from '/@/components/Authority';
|
||||
import { permissionStore } from '/@/store/modules/permission';
|
||||
import { usePermissionStore } from '/@/store/modules/permission';
|
||||
import { PermissionModeEnum } from '/@/enums/appEnum';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
|
||||
@ -67,6 +67,7 @@
|
||||
components: { Alert, PageWrapper, CurrentPermissionMode, Divider, Authority },
|
||||
setup() {
|
||||
const { hasPermission } = usePermission();
|
||||
const permissionStore = usePermissionStore();
|
||||
|
||||
function changePermissionCode(userId: string) {
|
||||
permissionStore.changePermissionCode(userId);
|
||||
|
@ -8,7 +8,7 @@
|
||||
<CurrentPermissionMode />
|
||||
|
||||
<p>
|
||||
当前角色: <a> {{ userStore.getRoleListState }} </a>
|
||||
当前角色: <a> {{ userStore.getRoleList }} </a>
|
||||
</p>
|
||||
<Alert class="mt-4" type="info" message="点击后请查看按钮变化" show-icon />
|
||||
|
||||
@ -63,7 +63,7 @@
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import { Alert, Divider } from 'ant-design-vue';
|
||||
import CurrentPermissionMode from '../CurrentPermissionMode.vue';
|
||||
import { userStore } from '/@/store/modules/user';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
import { RoleEnum } from '/@/enums/roleEnum';
|
||||
import { usePermission } from '/@/hooks/web/usePermission';
|
||||
import { Authority } from '/@/components/Authority';
|
||||
@ -73,11 +73,13 @@
|
||||
components: { Alert, PageWrapper, CurrentPermissionMode, Divider, Authority },
|
||||
setup() {
|
||||
const { changeRole, hasPermission } = usePermission();
|
||||
const userStore = useUserStore();
|
||||
|
||||
return {
|
||||
userStore,
|
||||
RoleEnum,
|
||||
isSuper: computed(() => userStore.getRoleListState.includes(RoleEnum.SUPER)),
|
||||
isTest: computed(() => userStore.getRoleListState.includes(RoleEnum.TEST)),
|
||||
isSuper: computed(() => userStore.getRoleList.includes(RoleEnum.SUPER)),
|
||||
isTest: computed(() => userStore.getRoleList.includes(RoleEnum.TEST)),
|
||||
changeRole,
|
||||
hasPermission,
|
||||
};
|
||||
|
@ -8,7 +8,7 @@
|
||||
<CurrentPermissionMode />
|
||||
|
||||
<p>
|
||||
当前角色: <a> {{ userStore.getRoleListState }} </a>
|
||||
当前角色: <a> {{ userStore.getRoleList }} </a>
|
||||
</p>
|
||||
<Alert class="mt-4" type="info" message="点击后请查看左侧菜单变化" show-icon />
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import { Alert } from 'ant-design-vue';
|
||||
import CurrentPermissionMode from '../CurrentPermissionMode.vue';
|
||||
import { userStore } from '/@/store/modules/user';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
import { RoleEnum } from '/@/enums/roleEnum';
|
||||
import { usePermission } from '/@/hooks/web/usePermission';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
@ -38,11 +38,13 @@
|
||||
components: { Alert, CurrentPermissionMode, PageWrapper },
|
||||
setup() {
|
||||
const { changeRole } = usePermission();
|
||||
const userStore = useUserStore();
|
||||
|
||||
return {
|
||||
userStore,
|
||||
RoleEnum,
|
||||
isSuper: computed(() => userStore.getRoleListState.includes(RoleEnum.SUPER)),
|
||||
isTest: computed(() => userStore.getRoleListState.includes(RoleEnum.TEST)),
|
||||
isSuper: computed(() => userStore.getRoleList.includes(RoleEnum.SUPER)),
|
||||
isTest: computed(() => userStore.getRoleList.includes(RoleEnum.TEST)),
|
||||
changeRole,
|
||||
};
|
||||
},
|
||||
|
@ -5,6 +5,7 @@
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import type { PropType } from 'vue';
|
||||
import type { ErrorLogInfo } from '/#/store';
|
||||
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicModal } from '/@/components/Modal/index';
|
||||
@ -12,8 +13,6 @@
|
||||
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
|
||||
import { ErrorInfo } from '/@/store/modules/error';
|
||||
|
||||
import { getDescSchema } from './data';
|
||||
|
||||
export default defineComponent({
|
||||
@ -21,7 +20,7 @@
|
||||
components: { BasicModal, Description },
|
||||
props: {
|
||||
info: {
|
||||
type: Object as PropType<ErrorInfo>,
|
||||
type: Object as PropType<ErrorLogInfo>,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
@ -30,7 +29,7 @@
|
||||
|
||||
const [register] = useDescription({
|
||||
column: 2,
|
||||
schema: getDescSchema(),
|
||||
schema: getDescSchema()!,
|
||||
});
|
||||
|
||||
return {
|
||||
|
@ -57,7 +57,7 @@ export function getColumns(): BasicColumn[] {
|
||||
];
|
||||
}
|
||||
|
||||
export function getDescSchema() {
|
||||
export function getDescSchema(): any {
|
||||
return getColumns().map((column) => {
|
||||
return {
|
||||
field: column.dataIndex!,
|
||||
|
@ -28,6 +28,8 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import type { ErrorLogInfo } from '/#/store';
|
||||
|
||||
import { defineComponent, watch, ref, nextTick } from 'vue';
|
||||
|
||||
import DetailModal from './DetailModal.vue';
|
||||
@ -37,7 +39,7 @@
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
|
||||
import { errorStore, ErrorInfo } from '/@/store/modules/error';
|
||||
import { useErrorLogStore } from '/@/store/modules/errorLog';
|
||||
|
||||
import { fireErrorApi } from '/@/api/demo/error';
|
||||
|
||||
@ -49,11 +51,11 @@
|
||||
name: 'ErrorHandler',
|
||||
components: { DetailModal, BasicTable, TableAction },
|
||||
setup() {
|
||||
const rowInfo = ref<ErrorInfo>();
|
||||
const rowInfo = ref<ErrorLogInfo>();
|
||||
const imgList = ref<string[]>([]);
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const errorLogStore = useErrorLogStore();
|
||||
const [register, { setTableData }] = useTable({
|
||||
title: t('sys.errorLog.tableTitle'),
|
||||
columns: getColumns(),
|
||||
@ -67,7 +69,7 @@
|
||||
const [registerModal, { openModal }] = useModal();
|
||||
|
||||
watch(
|
||||
() => errorStore.getErrorInfoState,
|
||||
() => errorLogStore.getErrorLogInfoList,
|
||||
(list) => {
|
||||
nextTick(() => {
|
||||
setTableData(cloneDeep(list));
|
||||
@ -82,7 +84,7 @@
|
||||
createMessage.info(t('sys.errorLog.enableMessage'));
|
||||
}
|
||||
// 查看详情
|
||||
function handleDetail(row: ErrorInfo) {
|
||||
function handleDetail(row: ErrorLogInfo) {
|
||||
rowInfo.value = row;
|
||||
openModal(true);
|
||||
}
|
||||
|
@ -38,7 +38,7 @@
|
||||
class="enter-x"
|
||||
v-model:value="password"
|
||||
/>
|
||||
<span :class="`${prefixCls}-entry__err-msg enter-x`" v-if="errMsgRef">
|
||||
<span :class="`${prefixCls}-entry__err-msg enter-x`" v-if="errMsg">
|
||||
{{ t('sys.lock.alert') }}
|
||||
</span>
|
||||
<div :class="`${prefixCls}-entry__footer enter-x`">
|
||||
@ -46,7 +46,7 @@
|
||||
type="link"
|
||||
size="small"
|
||||
class="mt-2 mr-2 enter-x"
|
||||
:disabled="loadingRef"
|
||||
:disabled="loading"
|
||||
@click="handleShowForm(true)"
|
||||
>
|
||||
{{ t('common.back') }}
|
||||
@ -55,12 +55,12 @@
|
||||
type="link"
|
||||
size="small"
|
||||
class="mt-2 mr-2 enter-x"
|
||||
:disabled="loadingRef"
|
||||
:disabled="loading"
|
||||
@click="goLogin"
|
||||
>
|
||||
{{ t('sys.lock.backToLogin') }}
|
||||
</a-button>
|
||||
<a-button class="mt-2" type="link" size="small" @click="unLock()" :loading="loadingRef">
|
||||
<a-button class="mt-2" type="link" size="small" @click="unLock()" :loading="loading">
|
||||
{{ t('sys.lock.entry') }}
|
||||
</a-button>
|
||||
</div>
|
||||
@ -80,8 +80,8 @@
|
||||
import { defineComponent, ref, computed } from 'vue';
|
||||
import { Input } from 'ant-design-vue';
|
||||
|
||||
import { userStore } from '/@/store/modules/user';
|
||||
import { lockStore } from '/@/store/modules/lock';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
import { useLockStore } from '/@/store/modules/lock';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
|
||||
import { useNow } from './useNow';
|
||||
@ -95,19 +95,21 @@
|
||||
components: { LockOutlined, InputPassword: Input.Password },
|
||||
|
||||
setup() {
|
||||
const passwordRef = ref('');
|
||||
const loadingRef = ref(false);
|
||||
const errMsgRef = ref(false);
|
||||
const password = ref('');
|
||||
const loading = ref(false);
|
||||
const errMsg = ref(false);
|
||||
const showDate = ref(true);
|
||||
|
||||
const { prefixCls } = useDesign('lock-page');
|
||||
const lockStore = useLockStore();
|
||||
const userStore = useUserStore();
|
||||
|
||||
const { ...state } = useNow(true);
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const realName = computed(() => {
|
||||
const { realName } = userStore.getUserInfoState || {};
|
||||
const { realName } = userStore.getUserInfo || {};
|
||||
return realName;
|
||||
});
|
||||
|
||||
@ -115,16 +117,16 @@
|
||||
* @description: unLock
|
||||
*/
|
||||
async function unLock() {
|
||||
if (!passwordRef.value) {
|
||||
if (!password.value) {
|
||||
return;
|
||||
}
|
||||
let password = passwordRef.value;
|
||||
let pwd = password.value;
|
||||
try {
|
||||
loadingRef.value = true;
|
||||
const res = await lockStore.unLockAction({ password });
|
||||
errMsgRef.value = !res;
|
||||
loading.value = true;
|
||||
const res = await lockStore.unLock(pwd);
|
||||
errMsg.value = !res;
|
||||
} finally {
|
||||
loadingRef.value = false;
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,12 +143,12 @@
|
||||
goLogin,
|
||||
realName,
|
||||
unLock,
|
||||
errMsgRef,
|
||||
loadingRef,
|
||||
errMsg,
|
||||
loading,
|
||||
t,
|
||||
prefixCls,
|
||||
showDate,
|
||||
password: passwordRef,
|
||||
password,
|
||||
handleShowForm,
|
||||
headerImg,
|
||||
...state,
|
||||
|
@ -7,17 +7,13 @@
|
||||
import { defineComponent, computed } from 'vue';
|
||||
import LockPage from './LockPage.vue';
|
||||
|
||||
import { lockStore } from '/@/store/modules/lock';
|
||||
import { useLockStore } from '/@/store/modules/lock';
|
||||
export default defineComponent({
|
||||
name: 'Lock',
|
||||
components: { LockPage },
|
||||
setup() {
|
||||
const getIsLock = computed(() => {
|
||||
const { getLockInfo } = lockStore;
|
||||
const { isLock } = getLockInfo;
|
||||
return isLock;
|
||||
});
|
||||
|
||||
const lockStore = useLockStore();
|
||||
const getIsLock = computed(() => lockStore?.getLockInfo?.isLock ?? false);
|
||||
return { getIsLock };
|
||||
},
|
||||
});
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { dateUtil } from '/@/utils/dateUtil';
|
||||
import { reactive, toRefs } from 'vue';
|
||||
import { localeStore } from '/@/store/modules/locale';
|
||||
import { useLocaleStore } from '/@/store/modules/locale';
|
||||
import { tryOnMounted, tryOnUnmounted } from '@vueuse/core';
|
||||
|
||||
export function useNow(immediate = true) {
|
||||
const localeStore = useLocaleStore();
|
||||
const localData = dateUtil.localeData(localeStore.getLocale);
|
||||
let timer: IntervalHandle;
|
||||
|
||||
|
@ -58,7 +58,7 @@
|
||||
import { useGlobSetting } from '/@/hooks/setting';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { localeStore } from '/@/store/modules/locale';
|
||||
import { useLocaleStore } from '/@/store/modules/locale';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Login',
|
||||
@ -76,6 +76,7 @@
|
||||
const globSetting = useGlobSetting();
|
||||
const { prefixCls } = useDesign('login');
|
||||
const { t } = useI18n();
|
||||
const localeStore = useLocaleStore();
|
||||
|
||||
return {
|
||||
t,
|
||||
|
@ -85,7 +85,7 @@
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
|
||||
import { userStore } from '/@/store/modules/user';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
import { LoginStateEnum, useLoginState, useFormRules, useFormValid } from './useLogin';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { useKeyPress } from '/@/hooks/event/useKeyPress';
|
||||
@ -114,6 +114,7 @@
|
||||
const { t } = useI18n();
|
||||
const { notification } = useMessage();
|
||||
const { prefixCls } = useDesign('login');
|
||||
const userStore = useUserStore();
|
||||
|
||||
const { setLoginState, getLoginState } = useLoginState();
|
||||
const { getFormRules } = useFormRules();
|
||||
|
44
types/store.ts
Normal file
44
types/store.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { ErrorTypeEnum } from '/@/enums/exceptionEnum';
|
||||
import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
|
||||
|
||||
// Lock screen information
|
||||
export interface LockInfo {
|
||||
// Password required
|
||||
pwd?: string | undefined;
|
||||
// Is it locked?
|
||||
isLock?: boolean;
|
||||
}
|
||||
|
||||
// Error-log information
|
||||
export interface ErrorLogInfo {
|
||||
// Type of error
|
||||
type: ErrorTypeEnum;
|
||||
// Error file
|
||||
file: string;
|
||||
// Error name
|
||||
name?: string;
|
||||
// Error message
|
||||
message: string;
|
||||
// Error stack
|
||||
stack?: string;
|
||||
// Error detail
|
||||
detail: string;
|
||||
// Error url
|
||||
url: string;
|
||||
// Error time
|
||||
time?: string;
|
||||
}
|
||||
|
||||
export interface UserInfo {
|
||||
userId: string | number;
|
||||
username: string;
|
||||
realName: string;
|
||||
desc?: string;
|
||||
}
|
||||
|
||||
export interface BeforeMiniState {
|
||||
menuCollapsed?: boolean;
|
||||
menuSplit?: boolean;
|
||||
menuMode?: MenuModeEnum;
|
||||
menuType?: MenuTypeEnum;
|
||||
}
|
91
yarn.lock
91
yarn.lock
@ -1762,25 +1762,25 @@
|
||||
resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.0.11.tgz#20d22dd0da7d358bb21c17f9bde8628152642c77"
|
||||
integrity sha512-b+zB8A2so8eCE0JsxjL24J7vdGl8rzPQ09hZNhystm+KqSbKcAej1A+Hbva1rCMmTTqA+hFnUSDc5kouEo0JzA==
|
||||
|
||||
"@vueuse/core@^4.8.0":
|
||||
version "4.8.0"
|
||||
resolved "https://registry.npmjs.org/@vueuse/core/-/core-4.8.0.tgz#d86e36956521c0f9b6571cb58b27f0e2535259b3"
|
||||
integrity sha512-nUH4Hn1DN4kkuF1r5ZcfGnjoAKDD0Kw9oFnt/TUo1aueNijq4KujagtoQN8OC4Pei10TeTDdqhmZAWnaCE1NbA==
|
||||
"@vueuse/core@^4.8.1":
|
||||
version "4.8.1"
|
||||
resolved "https://registry.npmjs.org/@vueuse/core/-/core-4.8.1.tgz#d7a7fb2e72610d1962ecb9244bd93dacb96d921c"
|
||||
integrity sha512-oXFEDaKNU69Rj20/Hd7ZlmTpEtA2M19cRkZaL4A0Nl0w5Wb5In/8aK+0vtdi1VyMUXXbq6h1OGKCJcIhg5cziA==
|
||||
dependencies:
|
||||
"@vueuse/shared" "4.8.0"
|
||||
"@vueuse/shared" "4.8.1"
|
||||
vue-demi latest
|
||||
|
||||
"@vueuse/shared@4.8.0":
|
||||
version "4.8.0"
|
||||
resolved "https://registry.npmjs.org/@vueuse/shared/-/shared-4.8.0.tgz#abf3da96ca81b4be82e885928193fef2c676cdbc"
|
||||
integrity sha512-g1lSbHD4ptiS74qBUvffJ98QjRsoCH7ILjxVzJF488EPAmp5z3taLnoggt6NXfonnYve7fEPuqsJqd2BLOxT1A==
|
||||
"@vueuse/shared@4.8.1":
|
||||
version "4.8.1"
|
||||
resolved "https://registry.npmjs.org/@vueuse/shared/-/shared-4.8.1.tgz#45fd5f64bf4e8944db42a5b72fa2705cfc74608a"
|
||||
integrity sha512-ONKJoIvZPrGCA8loK7dX+ZcjgZLikI+vPiz1lWlXs6+jZiQiZSLkmvg1NjV6Cfb6OqbDCfEScTWLbZHB7EwrRw==
|
||||
dependencies:
|
||||
vue-demi latest
|
||||
|
||||
"@windicss/plugin-utils@0.12.5":
|
||||
version "0.12.5"
|
||||
resolved "https://registry.npmjs.org/@windicss/plugin-utils/-/plugin-utils-0.12.5.tgz#d03517d1ae7a48b5b459e3d670e873d38b63e4a1"
|
||||
integrity sha512-4ux2o4s6D/gRTD68os41oxs/0NFk/eSJxHhZL9nN2wy4RGt+pPMQJyOHV56l7zDh9B0ywU5+ZRxDjdw2cl5Yvg==
|
||||
"@windicss/plugin-utils@0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.npmjs.org/@windicss/plugin-utils/-/plugin-utils-0.13.1.tgz#e0e172855ebcf0b8a5f0f358befdcaf44bae5cf1"
|
||||
integrity sha512-Vr7f7yWxmB5AWwe+iDPV3JbhTlZHbDvM89IfJ0hyP6PqYmZNTtUfMXMbHXZJHVAbQ54dWBMG23WmeC9X327ETA==
|
||||
dependencies:
|
||||
debug "^4.3.2"
|
||||
fast-glob "^3.2.5"
|
||||
@ -1788,7 +1788,7 @@
|
||||
micromatch "^4.0.2"
|
||||
pirates "^4.0.1"
|
||||
sucrase "^3.17.1"
|
||||
windicss "^2.5.11"
|
||||
windicss "^2.5.12"
|
||||
|
||||
"@zxcvbn-ts/core@^0.3.0":
|
||||
version "0.3.0"
|
||||
@ -3670,21 +3670,11 @@ esbuild-register@^2.2.0:
|
||||
esbuild "^0.9.2"
|
||||
jsonc-parser "^3.0.0"
|
||||
|
||||
esbuild@^0.11.4:
|
||||
version "0.11.5"
|
||||
resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.11.5.tgz#25b18a2ff2fb9580683edce26a48f64c08c2f2df"
|
||||
integrity sha512-aRs6jAE+bVRp1tyfzUugAw1T/Y0Fwzp4Z2ROikF3h+UifoD5QlEbEYQGc6orNnnSIRhWR5VWBH7LozlAumaLHg==
|
||||
|
||||
esbuild@^0.11.6:
|
||||
esbuild@^0.11.4, esbuild@^0.11.6, esbuild@^0.9.2, esbuild@^0.9.3:
|
||||
version "0.11.6"
|
||||
resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.11.6.tgz#20961309c4cfed00b71027e18806150358d0cbb0"
|
||||
integrity sha512-L+nKW9ftVS/N2CVJMR9YmXHbkm+vHzlNYuo09rzipQhF7dYNvRLfWoEPSDRTl10and4owFBV9rJ2CTFNtLIOiw==
|
||||
|
||||
esbuild@^0.9.2, esbuild@^0.9.3:
|
||||
version "0.9.7"
|
||||
resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.9.7.tgz#ea0d639cbe4b88ec25fbed4d6ff00c8d788ef70b"
|
||||
integrity sha512-VtUf6aQ89VTmMLKrWHYG50uByMF4JQlVysb8dmg6cOgW8JnFCipmz7p+HNBl+RR3LLCuBxFGVauAe2wfnF9bLg==
|
||||
|
||||
escalade@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||
@ -3752,10 +3742,10 @@ eslint-visitor-keys@^2.0.0:
|
||||
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
|
||||
integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
|
||||
|
||||
eslint@^7.23.0:
|
||||
version "7.23.0"
|
||||
resolved "https://registry.npmjs.org/eslint/-/eslint-7.23.0.tgz#8d029d252f6e8cf45894b4bee08f5493f8e94325"
|
||||
integrity sha512-kqvNVbdkjzpFy0XOszNwjkKzZ+6TcwCQ/h+ozlcIWwaimBBuhlQ4nN6kbiM2L+OjDcznkTJxzYfRFH92sx4a0Q==
|
||||
eslint@^7.24.0:
|
||||
version "7.24.0"
|
||||
resolved "https://registry.npmjs.org/eslint/-/eslint-7.24.0.tgz#2e44fa62d93892bfdb100521f17345ba54b8513a"
|
||||
integrity sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==
|
||||
dependencies:
|
||||
"@babel/code-frame" "7.12.11"
|
||||
"@eslint/eslintrc" "^0.4.0"
|
||||
@ -6942,6 +6932,11 @@ pify@^4.0.1:
|
||||
resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
|
||||
integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
|
||||
|
||||
pinia@^2.0.0-alpha.12:
|
||||
version "2.0.0-alpha.12"
|
||||
resolved "https://registry.npmjs.org/pinia/-/pinia-2.0.0-alpha.12.tgz#690e9a7b4c176bb9d95fe0dc8ec4ab8847b09493"
|
||||
integrity sha512-qmcDpuoAwxQKAVp7/cOkXFYDaja+vyXMWR6kvdyzeJcGGMvZf1HQ2xFhUSW5lf1eW5IiQP0cBRdF3ZDyVa+JIQ==
|
||||
|
||||
pinkie-promise@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
|
||||
@ -7691,10 +7686,10 @@ rollup-plugin-visualizer@5.3.0:
|
||||
source-map "^0.7.3"
|
||||
yargs "^16.2.0"
|
||||
|
||||
rollup@^2.25.0, rollup@^2.38.5, rollup@^2.44.0:
|
||||
version "2.44.0"
|
||||
resolved "https://registry.npmjs.org/rollup/-/rollup-2.44.0.tgz#8da324d1c4fd12beef9ae6e12f4068265b6d95eb"
|
||||
integrity sha512-rGSF4pLwvuaH/x4nAS+zP6UNn5YUDWf/TeEU5IoXSZKBbKRNTCI3qMnYXKZgrC0D2KzS2baiOZt1OlqhMu5rnQ==
|
||||
rollup@^2.25.0, rollup@^2.38.5, rollup@^2.44.0, rollup@^2.45.1:
|
||||
version "2.45.1"
|
||||
resolved "https://registry.npmjs.org/rollup/-/rollup-2.45.1.tgz#eae2b94dc2088b4e0a3b7197a5a1ee0bdd589d5c"
|
||||
integrity sha512-vPD+JoDj3CY8k6m1bLcAFttXMe78P4CMxoau0iLVS60+S9kLsv2379xaGy4NgYWu+h2WTlucpoLPAoUoixFBag==
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.1"
|
||||
|
||||
@ -9187,15 +9182,15 @@ vite-plugin-theme@^0.6.3:
|
||||
esbuild-plugin-alias "^0.1.2"
|
||||
tinycolor2 "^1.4.2"
|
||||
|
||||
vite-plugin-windicss@0.12.5:
|
||||
version "0.12.5"
|
||||
resolved "https://registry.npmjs.org/vite-plugin-windicss/-/vite-plugin-windicss-0.12.5.tgz#74a5043db3615fe432855f6ecff13be36f7a6843"
|
||||
integrity sha512-M/eEA+x94kxZNpEEkJLdY7M6Lp3WFhN0Kb/a2zhdPxBviMwaHSA5A7fUqN1xTYMxlQe4xM7D7naxL7EpnSNlmg==
|
||||
vite-plugin-windicss@0.13.1:
|
||||
version "0.13.1"
|
||||
resolved "https://registry.npmjs.org/vite-plugin-windicss/-/vite-plugin-windicss-0.13.1.tgz#82a488f3395be710ae2166b83b0612a5eaec7738"
|
||||
integrity sha512-WmFfTLTMSY5gRC3MWX9o72Yni2HRdrtJ2im+cCyZ2W/p4WE6T702zFCScO8Tnz/E08GDx4OH6oFCZWeZYwgxzg==
|
||||
dependencies:
|
||||
"@windicss/plugin-utils" "0.12.5"
|
||||
"@windicss/plugin-utils" "0.13.1"
|
||||
chalk "^4.1.0"
|
||||
debug "^4.3.2"
|
||||
windicss "^2.5.11"
|
||||
windicss "^2.5.12"
|
||||
|
||||
vite@2.1.5:
|
||||
version "2.1.5"
|
||||
@ -9265,16 +9260,6 @@ vue@^3.0.0:
|
||||
"@vue/runtime-dom" "3.0.10"
|
||||
"@vue/shared" "3.0.10"
|
||||
|
||||
vuex-module-decorators@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/vuex-module-decorators/-/vuex-module-decorators-1.0.1.tgz#d34dafb5428a3636f1c26d3d014c15fc9659ccd0"
|
||||
integrity sha512-FLWZsXV5XAtl/bcKUyQFpnSBtpc3wK/7zSdy9oKbyp71mZd4ut5y2zSd219wWW9OG7WUOlVwac4rXFFDVnq7ug==
|
||||
|
||||
vuex@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmjs.org/vuex/-/vuex-4.0.0.tgz#ac877aa76a9c45368c979471e461b520d38e6cf5"
|
||||
integrity sha512-56VPujlHscP5q/e7Jlpqc40sja4vOhC4uJD1llBCWolVI8ND4+VzisDVkUMl+z5y0MpIImW6HjhNc+ZvuizgOw==
|
||||
|
||||
warning@^4.0.0:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
|
||||
@ -9326,10 +9311,10 @@ which@^2.0.1:
|
||||
dependencies:
|
||||
isexe "^2.0.0"
|
||||
|
||||
windicss@^2.5.11:
|
||||
version "2.5.11"
|
||||
resolved "https://registry.npmjs.org/windicss/-/windicss-2.5.11.tgz#dd4027c724c7b12a37746d1474b96a52239157d1"
|
||||
integrity sha512-u7b4rOPb8MwO1glkf0gdDygZ+lIzXb/PYLNjqni5Fe2684DCEt6dWTKdk3iMxXgbKoqRNncKu7xt3pFwXHdSAw==
|
||||
windicss@^2.5.12:
|
||||
version "2.5.12"
|
||||
resolved "https://registry.npmjs.org/windicss/-/windicss-2.5.12.tgz#7bc469b05d7a8fa3905d49d6521a1ff9107d0ea4"
|
||||
integrity sha512-BZ0Ps1C0RlCHBVOPcw/DAReeR9o/mKaoFgkBsVphQ23M5nsvVfVXgGlNJZssjAQsXnlDpj97pnIhtDn1ENBjXw==
|
||||
|
||||
wmf@~1.0.1:
|
||||
version "1.0.2"
|
||||
|
Loading…
Reference in New Issue
Block a user