feat: 全局 loading
This commit is contained in:
parent
1fde986af6
commit
e20e082658
|
@ -13,6 +13,7 @@
|
||||||
:collapsed="collapsed"
|
:collapsed="collapsed"
|
||||||
:collapsible="true"
|
:collapsible="true"
|
||||||
:width="menuWidth"
|
:width="menuWidth"
|
||||||
|
:collapsed-width="collapsedWidth"
|
||||||
:style="{ paddingTop: navbar ? navbarHeight : '' }"
|
:style="{ paddingTop: navbar ? navbarHeight : '' }"
|
||||||
:hide-trigger="true"
|
:hide-trigger="true"
|
||||||
@collapse="setCollapsed"
|
@collapse="setCollapsed"
|
||||||
|
@ -33,11 +34,13 @@
|
||||||
<Menu />
|
<Menu />
|
||||||
</a-drawer>
|
</a-drawer>
|
||||||
<a-layout class="layout-content" :style="paddingStyle">
|
<a-layout class="layout-content" :style="paddingStyle">
|
||||||
|
<a-spin :loading="appStore.loading" :tip="appStore.loadingTip">
|
||||||
<TabBar v-if="appStore.tabBar" />
|
<TabBar v-if="appStore.tabBar" />
|
||||||
<a-layout-content>
|
<a-layout-content>
|
||||||
<PageLayout />
|
<PageLayout />
|
||||||
</a-layout-content>
|
</a-layout-content>
|
||||||
<Footer v-if="footer" />
|
<Footer v-if="footer" />
|
||||||
|
</a-spin>
|
||||||
</a-layout>
|
</a-layout>
|
||||||
</a-layout>
|
</a-layout>
|
||||||
</a-layout>
|
</a-layout>
|
||||||
|
@ -68,8 +71,9 @@
|
||||||
const renderMenu = computed(() => appStore.menu && !appStore.topMenu);
|
const renderMenu = computed(() => appStore.menu && !appStore.topMenu);
|
||||||
const hideMenu = computed(() => appStore.hideMenu);
|
const hideMenu = computed(() => appStore.hideMenu);
|
||||||
const footer = computed(() => appStore.footer);
|
const footer = computed(() => appStore.footer);
|
||||||
|
const collapsedWidth = 86;
|
||||||
const menuWidth = computed(() => {
|
const menuWidth = computed(() => {
|
||||||
return appStore.menuCollapse ? 48 : appStore.menuWidth;
|
return appStore.menuCollapse ? collapsedWidth : appStore.menuWidth;
|
||||||
});
|
});
|
||||||
const collapsed = computed(() => {
|
const collapsed = computed(() => {
|
||||||
return appStore.menuCollapse;
|
return appStore.menuCollapse;
|
||||||
|
@ -159,7 +163,7 @@
|
||||||
background-color: var(--color-bg-3);
|
background-color: var(--color-bg-3);
|
||||||
transition: padding 0.2s cubic-bezier(0.34, 0.69, 0.1, 1);
|
transition: padding 0.2s cubic-bezier(0.34, 0.69, 0.1, 1);
|
||||||
.arco-layout-content {
|
.arco-layout-content {
|
||||||
padding: 16px 16px 0;
|
padding: 16px 16px 16px 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -2,6 +2,9 @@ export default {
|
||||||
// 消息提醒相关
|
// 消息提醒相关
|
||||||
'message.errorTip': 'Error Tip',
|
'message.errorTip': 'Error Tip',
|
||||||
'message.logoutSuccess': 'Logout success',
|
'message.logoutSuccess': 'Logout success',
|
||||||
|
'message.menuLoading': 'Loading the menu...',
|
||||||
|
'message.menuLoadSuccess': 'Menu loaded successfully',
|
||||||
|
'message.menuLoadError': 'Menu load failed',
|
||||||
// API相关
|
// API相关
|
||||||
'api.apiTimeoutMessage': 'The interface request timed out, please refresh the page and try again!',
|
'api.apiTimeoutMessage': 'The interface request timed out, please refresh the page and try again!',
|
||||||
'api.apiRequestFailed': 'The interface request failed, please try again later!',
|
'api.apiRequestFailed': 'The interface request failed, please try again later!',
|
||||||
|
|
|
@ -2,6 +2,9 @@ export default {
|
||||||
// 消息提醒相关
|
// 消息提醒相关
|
||||||
'message.errorTip': '错误提示',
|
'message.errorTip': '错误提示',
|
||||||
'message.logoutSuccess': '登出成功',
|
'message.logoutSuccess': '登出成功',
|
||||||
|
'message.menuLoading': '菜单加载中...',
|
||||||
|
'message.menuLoadSuccess': '菜单加载成功',
|
||||||
|
'message.menuLoadError': '菜单加载失败',
|
||||||
// API相关
|
// API相关
|
||||||
'api.apiTimeoutMessage': '接口请求超时,请刷新页面重试!',
|
'api.apiTimeoutMessage': '接口请求超时,请刷新页面重试!',
|
||||||
'api.apiRequestFailed': '请求出错,请稍候重试',
|
'api.apiRequestFailed': '请求出错,请稍候重试',
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { Notification } from '@arco-design/web-vue';
|
import { Notification } from '@arco-design/web-vue';
|
||||||
import type { NotificationReturn } from '@arco-design/web-vue/es/notification/interface';
|
|
||||||
import type { RouteRecordNormalized } from 'vue-router';
|
|
||||||
import defaultSettings from '@/config/settings.json';
|
import defaultSettings from '@/config/settings.json';
|
||||||
import { getMenuList } from '@/api/modules/user';
|
import { getMenuList } from '@/api/modules/user';
|
||||||
import { AppState } from './types';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
import type { AppState } from './types';
|
||||||
|
import type { NotificationReturn } from '@arco-design/web-vue/es/notification/interface';
|
||||||
|
import type { RouteRecordNormalized } from 'vue-router';
|
||||||
|
|
||||||
const useAppStore = defineStore('app', {
|
const useAppStore = defineStore('app', {
|
||||||
state: (): AppState => ({ ...defaultSettings }),
|
state: (): AppState => ({ ...defaultSettings, loading: false, loadingTip: '加载中...' }),
|
||||||
|
|
||||||
getters: {
|
getters: {
|
||||||
appCurrentSetting(state: AppState): AppState {
|
appCurrentSetting(state: AppState): AppState {
|
||||||
|
@ -22,6 +24,9 @@ const useAppStore = defineStore('app', {
|
||||||
getCustomTheme(state: AppState): string {
|
getCustomTheme(state: AppState): string {
|
||||||
return state.customTheme as string;
|
return state.customTheme as string;
|
||||||
},
|
},
|
||||||
|
getLoadingStatus(state: AppState): boolean {
|
||||||
|
return state.loading;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
@ -51,25 +56,26 @@ const useAppStore = defineStore('app', {
|
||||||
* 获取服务端菜单配置
|
* 获取服务端菜单配置
|
||||||
*/
|
*/
|
||||||
async fetchServerMenuConfig() {
|
async fetchServerMenuConfig() {
|
||||||
|
const { t } = useI18n();
|
||||||
let notifyInstance: NotificationReturn | null = null;
|
let notifyInstance: NotificationReturn | null = null;
|
||||||
try {
|
try {
|
||||||
notifyInstance = Notification.info({
|
notifyInstance = Notification.info({
|
||||||
id: 'menuNotice', // Keep the instance id the same
|
id: 'menuNotice', // Keep the instance id the same
|
||||||
content: 'loading',
|
content: t('message.menuLoading'),
|
||||||
closable: true,
|
closable: true,
|
||||||
});
|
});
|
||||||
const data = await getMenuList();
|
const data = await getMenuList();
|
||||||
this.serverMenu = data;
|
this.serverMenu = data;
|
||||||
notifyInstance = Notification.success({
|
notifyInstance = Notification.success({
|
||||||
id: 'menuNotice',
|
id: 'menuNotice',
|
||||||
content: 'success',
|
content: t('message.menuLoadSuccess'),
|
||||||
closable: true,
|
closable: true,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
notifyInstance = Notification.error({
|
notifyInstance = Notification.error({
|
||||||
id: 'menuNotice',
|
id: 'menuNotice',
|
||||||
content: 'error',
|
content: t('message.menuLoadError'),
|
||||||
closable: true,
|
closable: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -80,6 +86,20 @@ const useAppStore = defineStore('app', {
|
||||||
clearServerMenu() {
|
clearServerMenu() {
|
||||||
this.serverMenu = [];
|
this.serverMenu = [];
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 显示全局 loading
|
||||||
|
*/
|
||||||
|
showLoading(tip = '加载中...') {
|
||||||
|
this.loading = true;
|
||||||
|
this.loadingTip = tip;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 隐藏全局 loading
|
||||||
|
*/
|
||||||
|
hideLoading() {
|
||||||
|
this.loading = false;
|
||||||
|
this.loadingTip = '加载中...';
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@ export interface AppState {
|
||||||
device: string;
|
device: string;
|
||||||
tabBar: boolean;
|
tabBar: boolean;
|
||||||
serverMenu: RouteRecordNormalized[];
|
serverMenu: RouteRecordNormalized[];
|
||||||
|
loading: boolean;
|
||||||
|
loadingTip: string;
|
||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ const formatTag = (route: RouteLocationNormalized): TabProps => {
|
||||||
|
|
||||||
const BAN_LIST = [REDIRECT_ROUTE_NAME];
|
const BAN_LIST = [REDIRECT_ROUTE_NAME];
|
||||||
|
|
||||||
const useAppStore = defineStore('tabBar', {
|
const useTabBarStore = defineStore('tabBar', {
|
||||||
state: (): TabBarState => ({
|
state: (): TabBarState => ({
|
||||||
cacheTabList: new Set([DEFAULT_ROUTE_NAME]),
|
cacheTabList: new Set([DEFAULT_ROUTE_NAME]),
|
||||||
tabList: [DEFAULT_ROUTE],
|
tabList: [DEFAULT_ROUTE],
|
||||||
|
@ -92,4 +92,4 @@ const useAppStore = defineStore('tabBar', {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default useAppStore;
|
export default useTabBarStore;
|
||||||
|
|
|
@ -74,10 +74,13 @@ const useUserStore = defineStore('user', {
|
||||||
clearToken();
|
clearToken();
|
||||||
removeRouteListener();
|
removeRouteListener();
|
||||||
appStore.clearServerMenu();
|
appStore.clearServerMenu();
|
||||||
|
appStore.hideLoading();
|
||||||
},
|
},
|
||||||
// 登出
|
// 登出
|
||||||
async logout() {
|
async logout() {
|
||||||
try {
|
try {
|
||||||
|
const appStore = useAppStore();
|
||||||
|
appStore.showLoading('正在退出登录...');
|
||||||
await userLogout();
|
await userLogout();
|
||||||
} finally {
|
} finally {
|
||||||
this.logoutCallBack();
|
this.logoutCallBack();
|
||||||
|
|
Loading…
Reference in New Issue