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,18 +37,14 @@
</div> </div>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; const { data } = defineProps({
export default defineComponent({
props: {
data: { data: {
type: Object, type: Object,
default: () => { default: () => {
return {}; return {};
}, },
}, },
},
}); });
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
+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,
});
+19 -18
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>,
}), async function initRoutes(roles: Array<unknown>) {
actions: {
async initRoutes(roles: Array<unknown>) {
let accessedRouters = []; let accessedRouters = [];
let removeRoutes: Array<RouteRecordRaw> = []; let routesToRemove: Array<RouteRecordRaw> = [];
// special token // special token
if (roles.includes('all')) { if (roles.includes('all')) {
accessedRouters = cloneDeep(allRoutes); accessedRouters = cloneDeep(allRoutes);
} else { } else {
const res = filterPermissionsRouters(allRoutes, roles); const res = filterPermissionsRouters(allRoutes, roles);
accessedRouters = res.accessedRouters; accessedRouters = res.accessedRouters;
removeRoutes = res.removeRoutes; routesToRemove = res.removeRoutes;
} }
this.routers = accessedRouters; routers.value = accessedRouters;
this.removeRoutes = removeRoutes; removeRoutes.value = routesToRemove;
removeRoutes.forEach((item: RouteRecordRaw) => { routesToRemove.forEach((item: RouteRecordRaw) => {
if (router.hasRoute(item.name!)) { if (router.hasRoute(item.name!)) {
router.removeRoute(item.name!); router.removeRoute(item.name!);
} }
}); });
}, }
async restore() {
this.removeRoutes.forEach((item: RouteRecordRaw) => { async function restore() {
removeRoutes.value.forEach((item: RouteRecordRaw) => {
router.addRoute(item); router.addRoute(item);
}); });
}, }
},
return { whiteListRouters, routers, removeRoutes, initRoutes, restore };
}); });
export function getPermissionStore() { export function getPermissionStore() {
+27 -25
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>,
}), async function initRoutes() {
actions: { const accessedRouters = asyncRoutes.value;
async initRoutes() {
const accessedRouters = this.asyncRoutes;
// 在菜单展示全部路由 // 在菜单展示全部路由
this.routers = cloneDeep([...homepageRouterList, ...accessedRouters, ...fixedRouterList]); routers.value = cloneDeep([...homepageRouterList, ...accessedRouters, ...fixedRouterList]);
// 在菜单只展示动态路由和首页 // 在菜单只展示动态路由和首页
// this.routers = [...homepageRouterList, ...accessedRouters]; // routers.value = [...homepageRouterList, ...accessedRouters];
// 在菜单只展示动态路由 // 在菜单只展示动态路由
// this.routers = [...accessedRouters]; // routers.value = [...accessedRouters];
}, }
async buildAsyncRoutes() {
async function buildAsyncRoutes() {
try { try {
// 发起菜单权限请求 获取菜单列表 // 发起菜单权限请求 获取菜单列表
const asyncRoutes: Array<RouteItem> = (await getMenuList()).list; const routeItems: Array<RouteItem> = (await getMenuList()).list;
this.asyncRoutes = transformObjectToRoute(asyncRoutes); asyncRoutes.value = transformObjectToRoute(routeItems);
await this.initRoutes(); await initRoutes();
return this.asyncRoutes; return asyncRoutes.value;
} catch (error) { } catch (error) {
throw new Error("Can't build routes", error as ErrorOptions); throw new Error("Can't build routes", error as ErrorOptions);
} }
}, }
async restoreRoutes() {
async function restoreRoutes() {
// 不需要在此额外调用initRoutes更新侧边导肮内容,在登录后asyncRoutes为空会调用 // 不需要在此额外调用initRoutes更新侧边导肮内容,在登录后asyncRoutes为空会调用
this.asyncRoutes.forEach((item: RouteRecordRaw) => { asyncRoutes.value.forEach((item: RouteRecordRaw) => {
if (item.name) { if (item.name) {
router.removeRoute(item.name); router.removeRoute(item.name);
} }
}); });
this.asyncRoutes = []; asyncRoutes.value = [];
}, }
},
return { whiteListRouters, routers, removeRoutes, asyncRoutes, initRoutes, buildAsyncRoutes, restoreRoutes };
}); });
export function getPermissionStore() { export function getPermissionStore() {
+59 -44
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 media = window.matchMedia('(prefers-color-scheme:dark)');
if (media.matches) {
return 'dark';
} }
return 'light';
}
async function changeMode(mode: ModeType | 'auto') {
const theme = mode === 'auto' ? getMediaColor() : mode;
const isDarkMode = theme === 'dark'; const isDarkMode = theme === 'dark';
document.documentElement.setAttribute('theme-mode', isDarkMode ? 'dark' : ''); document.documentElement.setAttribute('theme-mode', isDarkMode ? 'dark' : '');
settingState.chartColors = isDarkMode ? DARK_CHART_COLORS : LIGHT_CHART_COLORS;
}
this.chartColors = isDarkMode ? DARK_CHART_COLORS : LIGHT_CHART_COLORS; async function changeSideMode(mode: ModeType) {
},
async changeSideMode(mode: ModeType) {
const isDarkMode = mode === 'dark'; const isDarkMode = mode === 'dark';
document.documentElement.setAttribute('side-mode', isDarkMode ? 'dark' : ''); document.documentElement.setAttribute('side-mode', isDarkMode ? 'dark' : '');
},
getMediaColor() {
const media = window.matchMedia('(prefers-color-scheme:dark)');
if (media.matches) {
return 'dark';
} }
return 'light';
}, function changeBrandTheme(brandTheme: string) {
changeBrandTheme(brandTheme: string) { const mode = displayMode.value;
const mode = this.displayMode;
// 以主题色加显示模式作为键 // 以主题色加显示模式作为键
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: { persist: {
pick: [...keys(STYLE_CONFIG), 'colorList', 'chartColors'], 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]]);
}
function removeTabRouterList() {
tabRouterList.value = [];
}
function initTabRouterList(newRoutes: TRouterInfo[]) {
newRoutes?.forEach(appendTabRouterList);
}
return {
tabRouterList,
isRefreshing,
tabRouters,
refreshing,
toggleTabRouterAlive,
appendTabRouterList,
subtractCurrentTabRouter,
subtractTabRouterBehind,
subtractTabRouterAhead,
subtractTabRouterOther,
removeTabRouterList,
initTabRouterList,
};
}, },
removeTabRouterList() { { persist: true },
this.tabRouterList = []; );
},
initTabRouterList(newRoutes: TRouterInfo[]) {
newRoutes?.forEach((route: TRouterInfo) => this.appendTabRouterList(route));
},
},
persist: true,
});
export function getTabsRouterStore() { export function getTabsRouterStore() {
return useTabsRouterStore(store); return useTabsRouterStore(store);
+26 -23
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,15 +66,19 @@ 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: { persist: {
afterHydrate: () => { afterHydrate: () => {
const permissionStore = usePermissionStore(); const permissionStore = usePermissionStore();
@@ -85,4 +87,5 @@ export const useUserStore = defineStore('user', {
key: 'user', key: 'user',
pick: ['token'], pick: ['token'],
}, },
}); },
);