refactor: migrate Vue components and stores to Composition API

This commit is contained in:
2026-09-28 15:37:26 +08:00
parent 28fda43317
commit 1f016bb8a2
9 changed files with 268 additions and 231 deletions
+2 -4
View File
@@ -1,10 +1,8 @@
<template> <template>
<div></div> <div></div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; defineOptions({
export default defineComponent({
name: 'FrameBlank', name: 'FrameBlank',
}); });
</script> </script>
+7 -11
View File
@@ -9,21 +9,17 @@
</template> </template>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent, unref } from 'vue'; import { computed, unref } from 'vue';
import FrameContent from '../components/FrameContent.vue'; import FrameContent from '../components/FrameContent.vue';
import { useFrameKeepAlive } from './useFrameKeepAlive'; import { useFrameKeepAlive } from './useFrameKeepAlive';
export default defineComponent({ defineOptions({
name: 'FrameLayout', name: 'FrameLayout',
components: { FrameContent },
setup() {
const { getFramePages, hasRenderFrame, showIframe } = useFrameKeepAlive();
const showFrame = computed(() => unref(getFramePages).length > 0);
return { getFramePages, hasRenderFrame, showIframe, showFrame };
},
}); });
const { getFramePages, hasRenderFrame, showIframe } = useFrameKeepAlive();
const showFrame = computed(() => unref(getFramePages).length > 0);
</script> </script>
@@ -37,16 +37,12 @@
</div> </div>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; const { data } = defineProps({
data: {
export default defineComponent({ type: Object,
props: { default: () => {
data: { return {};
type: Object,
default: () => {
return {};
},
}, },
}, },
}); });
+19 -17
View File
@@ -1,4 +1,5 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { computed, ref } from 'vue';
import { t } from '@/locales'; import { t } from '@/locales';
import type { NotificationItem } from '@/types/interface'; import type { NotificationItem } from '@/types/interface';
@@ -44,21 +45,22 @@ const getMsgData = () => [
type MsgDataType = ReturnType<typeof getMsgData>; type MsgDataType = ReturnType<typeof getMsgData>;
export const useNotificationStore = defineStore('notification', { export const useNotificationStore = defineStore(
state: () => ({ 'notification',
msgData: getMsgData(), () => {
}), const msgData = ref<MsgDataType>(getMsgData());
getters: { const unreadMsg = computed(() => msgData.value.filter((item: NotificationItem) => item.status));
unreadMsg: (state) => state.msgData.filter((item: NotificationItem) => item.status), const readMsg = computed(() => msgData.value.filter((item: NotificationItem) => !item.status));
readMsg: (state) => state.msgData.filter((item: NotificationItem) => !item.status),
function setMsgData(data: MsgDataType) {
msgData.value = data;
}
function refreshMsgData() {
msgData.value = getMsgData();
}
return { msgData, unreadMsg, readMsg, setMsgData, refreshMsgData };
}, },
actions: { { persist: false },
setMsgData(data: MsgDataType) { );
this.msgData = data;
},
refreshMsgData() {
this.msgData = getMsgData();
},
},
persist: false,
});
+32 -31
View File
@@ -3,6 +3,7 @@
import cloneDeep from 'lodash/cloneDeep'; import cloneDeep from 'lodash/cloneDeep';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { ref } from 'vue';
import type { RouteRecordRaw } from 'vue-router'; import type { RouteRecordRaw } from 'vue-router';
import router, { allRoutes } from '@/router'; import router, { allRoutes } from '@/router';
@@ -29,41 +30,41 @@ function filterPermissionsRouters(routes: Array<RouteRecordRaw>, roles: Array<un
return { accessedRouters: res, removeRoutes }; return { accessedRouters: res, removeRoutes };
} }
export const usePermissionStore = defineStore('permission', { export const usePermissionStore = defineStore('permission', () => {
state: () => ({ const whiteListRouters = ref(['/login']);
whiteListRouters: ['/login'], const routers = ref<Array<RouteRecordRaw>>([]);
routers: [] as Array<RouteRecordRaw>, const removeRoutes = ref<Array<RouteRecordRaw>>([]);
removeRoutes: [] as Array<RouteRecordRaw>,
}),
actions: {
async initRoutes(roles: Array<unknown>) {
let accessedRouters = [];
let removeRoutes: Array<RouteRecordRaw> = []; async function initRoutes(roles: Array<unknown>) {
// special token let accessedRouters = [];
if (roles.includes('all')) {
accessedRouters = cloneDeep(allRoutes); let routesToRemove: Array<RouteRecordRaw> = [];
} else { // special token
const res = filterPermissionsRouters(allRoutes, roles); if (roles.includes('all')) {
accessedRouters = res.accessedRouters; accessedRouters = cloneDeep(allRoutes);
removeRoutes = res.removeRoutes; } else {
const res = filterPermissionsRouters(allRoutes, roles);
accessedRouters = res.accessedRouters;
routesToRemove = res.removeRoutes;
}
routers.value = accessedRouters;
removeRoutes.value = routesToRemove;
routesToRemove.forEach((item: RouteRecordRaw) => {
if (router.hasRoute(item.name!)) {
router.removeRoute(item.name!);
} }
});
}
this.routers = accessedRouters; async function restore() {
this.removeRoutes = removeRoutes; removeRoutes.value.forEach((item: RouteRecordRaw) => {
router.addRoute(item);
});
}
removeRoutes.forEach((item: RouteRecordRaw) => { return { whiteListRouters, routers, removeRoutes, initRoutes, restore };
if (router.hasRoute(item.name!)) {
router.removeRoute(item.name!);
}
});
},
async restore() {
this.removeRoutes.forEach((item: RouteRecordRaw) => {
router.addRoute(item);
});
},
},
}); });
export function getPermissionStore() { export function getPermissionStore() {
+39 -37
View File
@@ -1,5 +1,6 @@
import cloneDeep from 'lodash/cloneDeep'; import cloneDeep from 'lodash/cloneDeep';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { ref } from 'vue';
import type { RouteRecordRaw } from 'vue-router'; import type { RouteRecordRaw } from 'vue-router';
import type { RouteItem } from '@/api/model/permissionModel'; import type { RouteItem } from '@/api/model/permissionModel';
@@ -8,45 +9,46 @@ import router, { fixedRouterList, homepageRouterList } from '@/router';
import { store } from '@/store'; import { store } from '@/store';
import { transformObjectToRoute } from '@/utils/route'; import { transformObjectToRoute } from '@/utils/route';
export const usePermissionStore = defineStore('permission', { export const usePermissionStore = defineStore('permission', () => {
state: () => ({ const whiteListRouters = ref(['/login']);
whiteListRouters: ['/login'], const routers = ref<Array<RouteRecordRaw>>([]);
routers: [] as Array<RouteRecordRaw>, const removeRoutes = ref<Array<RouteRecordRaw>>([]);
removeRoutes: [] as Array<RouteRecordRaw>, const asyncRoutes = ref<Array<RouteRecordRaw>>([]);
asyncRoutes: [] as Array<RouteRecordRaw>,
}),
actions: {
async initRoutes() {
const accessedRouters = this.asyncRoutes;
// 在菜单展示全部路由 async function initRoutes() {
this.routers = cloneDeep([...homepageRouterList, ...accessedRouters, ...fixedRouterList]); const accessedRouters = asyncRoutes.value;
// 在菜单只展示动态路由和首页
// this.routers = [...homepageRouterList, ...accessedRouters]; // 在菜单展示全部路由
// 在菜单只展示动态路由 routers.value = cloneDeep([...homepageRouterList, ...accessedRouters, ...fixedRouterList]);
// this.routers = [...accessedRouters]; // 在菜单只展示动态路由和首页
}, // routers.value = [...homepageRouterList, ...accessedRouters];
async buildAsyncRoutes() { // 在菜单只展示动态路由
try { // routers.value = [...accessedRouters];
// 发起菜单权限请求 获取菜单列表 }
const asyncRoutes: Array<RouteItem> = (await getMenuList()).list;
this.asyncRoutes = transformObjectToRoute(asyncRoutes); async function buildAsyncRoutes() {
await this.initRoutes(); try {
return this.asyncRoutes; // 发起菜单权限请求 获取菜单列表
} catch (error) { const routeItems: Array<RouteItem> = (await getMenuList()).list;
throw new Error("Can't build routes", error as ErrorOptions); asyncRoutes.value = transformObjectToRoute(routeItems);
await initRoutes();
return asyncRoutes.value;
} catch (error) {
throw new Error("Can't build routes", error as ErrorOptions);
}
}
async function restoreRoutes() {
// 不需要在此额外调用initRoutes更新侧边导肮内容,在登录后asyncRoutes为空会调用
asyncRoutes.value.forEach((item: RouteRecordRaw) => {
if (item.name) {
router.removeRoute(item.name);
} }
}, });
async restoreRoutes() { asyncRoutes.value = [];
// 不需要在此额外调用initRoutes更新侧边导肮内容,在登录后asyncRoutes为空会调用 }
this.asyncRoutes.forEach((item: RouteRecordRaw) => {
if (item.name) { return { whiteListRouters, routers, removeRoutes, asyncRoutes, initRoutes, buildAsyncRoutes, restoreRoutes };
router.removeRoute(item.name);
}
});
this.asyncRoutes = [];
},
},
}); });
export function getPermissionStore() { export function getPermissionStore() {
+64 -49
View File
@@ -1,6 +1,7 @@
import keys from 'lodash/keys'; import keys from 'lodash/keys';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { Color } from 'tvision-color'; import { Color } from 'tvision-color';
import { computed, reactive, toRefs } from 'vue';
import type { TColorSeries } from '@/config/color'; import type { TColorSeries } from '@/config/color';
import { DARK_CHART_COLORS, LIGHT_CHART_COLORS } from '@/config/color'; import { DARK_CHART_COLORS, LIGHT_CHART_COLORS } from '@/config/color';
@@ -9,7 +10,7 @@ import { store } from '@/store';
import type { ModeType } from '@/types/interface'; import type { ModeType } from '@/types/interface';
import { generateColorMap, insertThemeStylesheet } from '@/utils/color'; import { generateColorMap, insertThemeStylesheet } from '@/utils/color';
const state: Record<string, any> = { const state = {
...STYLE_CONFIG, ...STYLE_CONFIG,
showSettingPanel: false, showSettingPanel: false,
colorList: {} as TColorSeries, colorList: {} as TColorSeries,
@@ -19,57 +20,53 @@ const state: Record<string, any> = {
export type TState = typeof state; export type TState = typeof state;
export type TStateKey = keyof typeof state; export type TStateKey = keyof typeof state;
export const useSettingStore = defineStore('setting', { export const useSettingStore = defineStore(
state: () => state, 'setting',
getters: { () => {
showSidebar: (state) => state.layout !== 'top', const settingState = reactive({ ...state });
showSidebarLogo: (state) => state.layout === 'side', const showSidebar = computed(() => settingState.layout !== 'top');
showHeaderLogo: (state) => state.layout !== 'side', const showSidebarLogo = computed(() => settingState.layout === 'side');
displayMode: (state): ModeType => { const showHeaderLogo = computed(() => settingState.layout !== 'side');
if (state.mode === 'auto') { const displayMode = computed((): ModeType => {
if (settingState.mode === 'auto') {
const media = window.matchMedia('(prefers-color-scheme:dark)'); const media = window.matchMedia('(prefers-color-scheme:dark)');
if (media.matches) { if (media.matches) {
return 'dark'; return 'dark';
} }
return 'light'; return 'light';
} }
return state.mode as ModeType; return settingState.mode as ModeType;
}, });
displaySideMode: (state): ModeType => { const displaySideMode = computed((): ModeType => settingState.sideMode as ModeType);
return state.sideMode as ModeType;
},
},
actions: {
async changeMode(mode: ModeType | 'auto') {
let theme = mode;
if (mode === 'auto') { function getMediaColor() {
theme = this.getMediaColor();
}
const isDarkMode = theme === 'dark';
document.documentElement.setAttribute('theme-mode', isDarkMode ? 'dark' : '');
this.chartColors = isDarkMode ? DARK_CHART_COLORS : LIGHT_CHART_COLORS;
},
async changeSideMode(mode: ModeType) {
const isDarkMode = mode === 'dark';
document.documentElement.setAttribute('side-mode', isDarkMode ? 'dark' : '');
},
getMediaColor() {
const media = window.matchMedia('(prefers-color-scheme:dark)'); const media = window.matchMedia('(prefers-color-scheme:dark)');
if (media.matches) { if (media.matches) {
return 'dark'; return 'dark';
} }
return 'light'; return 'light';
}, }
changeBrandTheme(brandTheme: string) {
const mode = this.displayMode; async function changeMode(mode: ModeType | 'auto') {
const theme = mode === 'auto' ? getMediaColor() : mode;
const isDarkMode = theme === 'dark';
document.documentElement.setAttribute('theme-mode', isDarkMode ? 'dark' : '');
settingState.chartColors = isDarkMode ? DARK_CHART_COLORS : LIGHT_CHART_COLORS;
}
async function changeSideMode(mode: ModeType) {
const isDarkMode = mode === 'dark';
document.documentElement.setAttribute('side-mode', isDarkMode ? 'dark' : '');
}
function changeBrandTheme(brandTheme: string) {
const mode = displayMode.value;
// 以主题色加显示模式作为键 // 以主题色加显示模式作为键
const colorKey = `${brandTheme}[${mode}]`; const colorKey = `${brandTheme}[${mode}]`;
let colorMap = this.colorList[colorKey]; let colorMap = settingState.colorList[colorKey];
// 如果不存在色阶,就需要计算 // 如果不存在色阶,就需要计算
if (colorMap === undefined) { if (colorMap === undefined) {
const [{ colors: newPalette, primary: brandColorIndex }] = Color.getColorGradations({ const [{ colors: newPalette, primary: brandColorIndex }] = Color.getColorGradations({
@@ -78,33 +75,51 @@ export const useSettingStore = defineStore('setting', {
remainInput: false, // 是否保留输入 不保留会矫正不合适的主题色 remainInput: false, // 是否保留输入 不保留会矫正不合适的主题色
}); });
colorMap = generateColorMap(brandTheme, newPalette, mode, brandColorIndex); colorMap = generateColorMap(brandTheme, newPalette, mode, brandColorIndex);
this.colorList[colorKey] = colorMap; settingState.colorList[colorKey] = colorMap;
} }
// TODO 需要解决不停切换时有反复插入 style 的问题 // TODO 需要解决不停切换时有反复插入 style 的问题
insertThemeStylesheet(brandTheme, colorMap, mode); insertThemeStylesheet(brandTheme, colorMap, mode);
document.documentElement.setAttribute('theme-color', brandTheme); document.documentElement.setAttribute('theme-color', brandTheme);
}, }
updateConfig(payload: Partial<TState>) {
function updateConfig(payload: Partial<TState>) {
for (const key in payload) { for (const key in payload) {
if (payload[key as TStateKey] !== undefined) { const value = payload[key as TStateKey];
this[key as TStateKey] = payload[key as TStateKey]; if (value !== undefined) {
Reflect.set(settingState, key, value);
} }
if (key === 'mode') { if (key === 'mode') {
this.changeMode(payload[key] as ModeType); changeMode(value as ModeType);
} }
if (key === 'sideMode') { if (key === 'sideMode') {
this.changeSideMode(payload[key] as ModeType); changeSideMode(value as ModeType);
} }
if (key === 'brandTheme') { if (key === 'brandTheme') {
this.changeBrandTheme(payload[key]); changeBrandTheme(value as string);
} }
} }
}
return {
...toRefs(settingState),
showSidebar,
showSidebarLogo,
showHeaderLogo,
displayMode,
displaySideMode,
changeMode,
changeSideMode,
getMediaColor,
changeBrandTheme,
updateConfig,
};
},
{
persist: {
pick: [...keys(STYLE_CONFIG), 'colorList', 'chartColors'],
}, },
}, },
persist: { );
pick: [...keys(STYLE_CONFIG), 'colorList', 'chartColors'],
},
});
export function getSettingStore() { export function getSettingStore() {
return useSettingStore(store); return useSettingStore(store);
+66 -42
View File
@@ -1,4 +1,5 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { computed, ref } from 'vue';
import { store } from '@/store'; import { store } from '@/store';
import type { TRouterInfo, TTabRouterType } from '@/types/interface'; import type { TRouterInfo, TTabRouterType } from '@/types/interface';
@@ -23,75 +24,98 @@ const state = {
// const ignoreCacheRoutes = ['DashboardDetail']; // const ignoreCacheRoutes = ['DashboardDetail'];
const ignoreCacheRoutes = ['login']; const ignoreCacheRoutes = ['login'];
export const useTabsRouterStore = defineStore('tabsRouter', { export const useTabsRouterStore = defineStore(
state: () => state, 'tabsRouter',
getters: { () => {
tabRouters: (state: TTabRouterType) => state.tabRouterList, const tabRouterList = ref<TTabRouterType['tabRouterList']>(state.tabRouterList);
refreshing: (state: TTabRouterType) => state.isRefreshing, const isRefreshing = ref(state.isRefreshing);
}, const tabRouters = computed(() => tabRouterList.value);
actions: { const refreshing = computed(() => isRefreshing.value);
// 处理刷新 // 处理刷新
toggleTabRouterAlive(routeIdx: number) { function toggleTabRouterAlive(routeIdx: number) {
this.isRefreshing = !this.isRefreshing; isRefreshing.value = !isRefreshing.value;
this.tabRouters[routeIdx].isAlive = !this.tabRouters[routeIdx].isAlive; tabRouters.value[routeIdx].isAlive = !tabRouters.value[routeIdx].isAlive;
}, }
// 处理新增 // 处理新增
appendTabRouterList(newRoute: TRouterInfo) { function appendTabRouterList(newRoute: TRouterInfo) {
// 不要将判断条件newRoute.meta.keepAlive !== false修改为newRoute.meta.keepAlive,starter默认开启保活,所以meta.keepAlive未定义时也需要进行保活,只有显式说明false才禁用保活。 // 不要将判断条件newRoute.meta.keepAlive !== false修改为newRoute.meta.keepAlive,starter默认开启保活,所以meta.keepAlive未定义时也需要进行保活,只有显式说明false才禁用保活。
const needAlive = !ignoreCacheRoutes.includes(newRoute.name as string) && newRoute.meta?.keepAlive !== false; const needAlive = !ignoreCacheRoutes.includes(newRoute.name as string) && newRoute.meta?.keepAlive !== false;
const normalizedPath = normalizePath(newRoute.path); const normalizedPath = normalizePath(newRoute.path);
const existed = this.tabRouters.some((route: TRouterInfo) => { const existed = tabRouters.value.some((route: TRouterInfo) => {
return route.path === normalizedPath || normalizePath(route.path) === normalizedPath; return route.path === normalizedPath || normalizePath(route.path) === normalizedPath;
}); });
if (!existed) { if (!existed) {
this.tabRouterList = this.tabRouterList.concat({ ...newRoute, path: normalizedPath, isAlive: needAlive }); tabRouterList.value = tabRouterList.value.concat({ ...newRoute, path: normalizedPath, isAlive: needAlive });
} }
}, }
// 处理关闭当前 // 处理关闭当前
subtractCurrentTabRouter(newRoute: TRouterInfo) { function subtractCurrentTabRouter(newRoute: TRouterInfo) {
const { routeIdx } = newRoute; const { routeIdx } = newRoute;
if (routeIdx === undefined) return; if (routeIdx === undefined) return;
this.tabRouterList = this.tabRouterList.slice(0, routeIdx).concat(this.tabRouterList.slice(routeIdx + 1)); tabRouterList.value = tabRouterList.value.slice(0, routeIdx).concat(tabRouterList.value.slice(routeIdx + 1));
}, }
// 处理关闭右侧 // 处理关闭右侧
subtractTabRouterBehind(newRoute: TRouterInfo) { function subtractTabRouterBehind(newRoute: TRouterInfo) {
const { routeIdx } = newRoute; const { routeIdx } = newRoute;
if (routeIdx === undefined) return; if (routeIdx === undefined) return;
const homeIdx: number = this.tabRouters.findIndex((route: TRouterInfo) => route.isHome); const homeIdx: number = tabRouters.value.findIndex((route: TRouterInfo) => route.isHome);
let tabRouterList: Array<TRouterInfo> = this.tabRouterList.slice(0, routeIdx + 1); let updatedTabRouterList: Array<TRouterInfo> = tabRouterList.value.slice(0, routeIdx + 1);
if (routeIdx < homeIdx) { if (routeIdx < homeIdx) {
tabRouterList = tabRouterList.concat(homeRoute); updatedTabRouterList = updatedTabRouterList.concat(homeRoute);
} }
this.tabRouterList = tabRouterList; tabRouterList.value = updatedTabRouterList;
}, }
// 处理关闭左侧 // 处理关闭左侧
subtractTabRouterAhead(newRoute: TRouterInfo) { function subtractTabRouterAhead(newRoute: TRouterInfo) {
const { routeIdx } = newRoute; const { routeIdx } = newRoute;
if (routeIdx === undefined) return; if (routeIdx === undefined) return;
const homeIdx: number = this.tabRouters.findIndex((route: TRouterInfo) => route.isHome); const homeIdx: number = tabRouters.value.findIndex((route: TRouterInfo) => route.isHome);
let tabRouterList: Array<TRouterInfo> = this.tabRouterList.slice(routeIdx); let updatedTabRouterList: Array<TRouterInfo> = tabRouterList.value.slice(routeIdx);
if (routeIdx > homeIdx) { if (routeIdx > homeIdx) {
tabRouterList = homeRoute.concat(tabRouterList); updatedTabRouterList = homeRoute.concat(updatedTabRouterList);
} }
this.tabRouterList = tabRouterList; tabRouterList.value = updatedTabRouterList;
}, }
// 处理关闭其他 // 处理关闭其他
subtractTabRouterOther(newRoute: TRouterInfo) { function subtractTabRouterOther(newRoute: TRouterInfo) {
const { routeIdx } = newRoute; const { routeIdx } = newRoute;
if (routeIdx === undefined) return; if (routeIdx === undefined) return;
const homeIdx: number = this.tabRouters.findIndex((route: TRouterInfo) => route.isHome); const homeIdx: number = tabRouters.value.findIndex((route: TRouterInfo) => route.isHome);
this.tabRouterList = routeIdx === homeIdx ? homeRoute : homeRoute.concat([this.tabRouterList?.[routeIdx]]); tabRouterList.value = routeIdx === homeIdx ? homeRoute : homeRoute.concat([tabRouterList.value?.[routeIdx]]);
}, }
removeTabRouterList() {
this.tabRouterList = []; function removeTabRouterList() {
}, tabRouterList.value = [];
initTabRouterList(newRoutes: TRouterInfo[]) { }
newRoutes?.forEach((route: TRouterInfo) => this.appendTabRouterList(route));
}, function initTabRouterList(newRoutes: TRouterInfo[]) {
newRoutes?.forEach(appendTabRouterList);
}
return {
tabRouterList,
isRefreshing,
tabRouters,
refreshing,
toggleTabRouterAlive,
appendTabRouterList,
subtractCurrentTabRouter,
subtractTabRouterBehind,
subtractTabRouterAhead,
subtractTabRouterOther,
removeTabRouterList,
initTabRouterList,
};
}, },
persist: true, { persist: true },
}); );
export function getTabsRouterStore() { export function getTabsRouterStore() {
return useTabsRouterStore(store); return useTabsRouterStore(store);
+33 -30
View File
@@ -1,4 +1,5 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { computed, ref } from 'vue';
import { t } from '@/locales'; import { t } from '@/locales';
import { usePermissionStore } from '@/store'; import { usePermissionStore } from '@/store';
@@ -9,18 +10,14 @@ const InitUserInfo: UserInfo = {
roles: [], // 前端权限模型使用 如果使用请配置modules/permission-fe.ts使用 roles: [], // 前端权限模型使用 如果使用请配置modules/permission-fe.ts使用
}; };
export const useUserStore = defineStore('user', { export const useUserStore = defineStore(
state: () => ({ 'user',
token: 'main_token', // 默认token不走权限 () => {
userInfo: { ...InitUserInfo }, const token = ref('main_token'); // 默认token不走权限
}), const userInfo = ref<UserInfo>({ ...InitUserInfo });
getters: { const roles = computed(() => userInfo.value?.roles);
roles: (state) => {
return state.userInfo?.roles; async function login(userInfo: Record<string, unknown>) {
},
},
actions: {
async login(userInfo: Record<string, unknown>) {
const mockLogin = async (userInfo: Record<string, unknown>) => { const mockLogin = async (userInfo: Record<string, unknown>) => {
// 登录请求流程 // 登录请求流程
console.log(`用户信息:`, userInfo); console.log(`用户信息:`, userInfo);
@@ -50,12 +47,13 @@ export const useUserStore = defineStore('user', {
const res = await mockLogin(userInfo); const res = await mockLogin(userInfo);
if (res.code === 200) { if (res.code === 200) {
this.token = res.data; token.value = res.data;
} else { } else {
throw res; throw res;
} }
}, }
async getUserInfo() {
async function getUserInfo() {
const mockRemoteUserInfo = async (token: string) => { const mockRemoteUserInfo = async (token: string) => {
if (token === 'main_token') { if (token === 'main_token') {
return { return {
@@ -68,21 +66,26 @@ export const useUserStore = defineStore('user', {
roles: ['UserIndex', 'DashboardBase', 'login'], // 前端权限模型使用 如果使用请配置modules/permission-fe.ts使用 roles: ['UserIndex', 'DashboardBase', 'login'], // 前端权限模型使用 如果使用请配置modules/permission-fe.ts使用
}; };
}; };
const res = await mockRemoteUserInfo(this.token); const res = await mockRemoteUserInfo(token.value);
this.userInfo = res; userInfo.value = res;
}, }
async logout() {
this.token = ''; async function logout() {
this.userInfo = { ...InitUserInfo }; token.value = '';
userInfo.value = { ...InitUserInfo };
}
return { token, userInfo, roles, login, getUserInfo, logout };
},
{
persist: {
afterHydrate: () => {
const permissionStore = usePermissionStore();
permissionStore.initRoutes();
},
key: 'user',
pick: ['token'],
}, },
}, },
persist: { );
afterHydrate: () => {
const permissionStore = usePermissionStore();
permissionStore.initRoutes();
},
key: 'user',
pick: ['token'],
},
});