refactor: migrate Vue components and stores to Composition API
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
@@ -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 { getFramePages, hasRenderFrame, showIframe } = useFrameKeepAlive();
|
||||||
|
|
||||||
const showFrame = computed(() => unref(getFramePages).length > 0);
|
const showFrame = computed(() => unref(getFramePages).length > 0);
|
||||||
|
|
||||||
return { getFramePages, hasRenderFrame, showIframe, showFrame };
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</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>
|
||||||
|
|||||||
@@ -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,
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
@@ -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'],
|
||||||
},
|
},
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user