mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-10-02 08:29:21 +00:00
chore: 清理冗余代码与配置,优化项目结构
1. 删除无用文件与废弃代码:移除locale枚举、element-plus插件、sse路由、api token模块等 2. 简化类型导入与依赖:移除大量未使用的类型导入,统一echarts导入方式 3. 优化配置与样式:调整gitignore、样式引入顺序,新增列表动画样式 4. 修复接口与模型:修正接口返回类型、查询参数配置,更新部门模型字段 5. 优化性能与体验:添加图片懒加载,优化加载逻辑与表格渲染 6. 调整环境配置:新增并更新开发/生产环境配置文件
This commit is contained in:
@@ -30,7 +30,6 @@
|
||||
*/
|
||||
import { defineStore } from "pinia";
|
||||
import { ref, computed } from "vue";
|
||||
import { AppRouteRecord } from "@/types/router";
|
||||
import { getFirstMenuPath } from "@utils";
|
||||
import { HOME_PAGE_PATH } from "@/router";
|
||||
import { mergeShellRoutesIntoMenu } from "@/router/staticRoutes";
|
||||
@@ -52,11 +51,10 @@ export const useMenuStore = defineStore(
|
||||
const removeRouteFns = ref<(() => void)[]>([]);
|
||||
|
||||
/**
|
||||
* 可见菜单列表,直接返回所有菜单,不做 scope 过滤
|
||||
* 可见菜单列表,当前直接返回所有菜单(保留 computed 以供未来 scope 过滤扩展)
|
||||
* TODO: 移除本别名,消费者直接使用 menuList
|
||||
*/
|
||||
const visibleMenus = computed(() => {
|
||||
return menuList.value;
|
||||
});
|
||||
const visibleMenus = computed(() => menuList.value);
|
||||
|
||||
/**
|
||||
* 设置菜单列表
|
||||
|
||||
@@ -49,7 +49,7 @@ export const useNoticeStore = defineStore(
|
||||
*/
|
||||
async function getNotice() {
|
||||
const response = await NoticeAPI.listNoticeAvailable();
|
||||
const items = response.data.data.items || [];
|
||||
const items = response.data.data || [];
|
||||
// 过滤掉已读的通知
|
||||
const readSet = new Set(readIds.value);
|
||||
const filtered = items.filter(
|
||||
|
||||
@@ -4,9 +4,8 @@
|
||||
*/
|
||||
import { defineStore } from "pinia";
|
||||
import { ref, computed, watch } from "vue";
|
||||
import { MenuThemeType } from "@/types/store";
|
||||
import { SystemThemeEnum, MenuTypeEnum, MenuThemeEnum, ContainerWidthEnum } from "@/enums/appEnum";
|
||||
import AppConfig from "@/config";
|
||||
import { SystemThemeEnum, MenuThemeEnum, MenuTypeEnum, ContainerWidthEnum } from "@/enums/appEnum";
|
||||
import { SETTING_DEFAULT_CONFIG } from "@/config/setting";
|
||||
import {
|
||||
setElementThemeColor,
|
||||
|
||||
@@ -6,13 +6,11 @@ import { router } from "@/router";
|
||||
import { useWorktabStore } from "./worktab.store";
|
||||
import { useMenuStore } from "./menu.store";
|
||||
import { useConfigStore } from "./config.store";
|
||||
import { AppRouteRecord } from "@/types/router";
|
||||
import { Auth, setPageTitle, StorageConfig } from "@utils";
|
||||
import AuthAPI from "@/api/module_system/auth";
|
||||
import AuthAPI, { type LoginFormData } from "@/api/module_system/auth";
|
||||
import UserAPI from "@/api/module_system/user";
|
||||
import type { MenuTable } from "@/api/module_system/menu";
|
||||
import { ResultEnum } from "@/enums/api/result.enum";
|
||||
import { ElNotification } from "element-plus";
|
||||
import { ElNotification } from "@/utils/message";
|
||||
import { store, useDictStore } from "@stores";
|
||||
import type { UserInfo } from "@/api/module_system/user";
|
||||
|
||||
@@ -64,22 +62,15 @@ export const useUserStore = defineStore(
|
||||
// 记住我状态
|
||||
const rememberMe = ref(Auth.getRememberMe());
|
||||
/** info 扩展类型:兼容 API 返回 `user_id`(非标准 UserInfo 字段) */
|
||||
type UserInfoLike = Partial<UserInfo> & Record<string, any>;
|
||||
type UserInfoLike = Partial<UserInfo> & { user_id?: number; [key: string]: unknown };
|
||||
|
||||
// 计算属性:基础用户信息
|
||||
const basicInfo = computed(() => info.value as UserInfoLike);
|
||||
// 计算属性:获取路由列表
|
||||
const getRouteList = computed(() => routeList.value);
|
||||
// 计算属性:获取权限列表
|
||||
const getPerms = computed(() => prems.value);
|
||||
// 计算属性:是否已获取路由
|
||||
const getHasGetRoute = computed(() => hasGetRoute.value);
|
||||
|
||||
/**
|
||||
* 设置用户信息
|
||||
* @param newInfo 新的用户信息
|
||||
*/
|
||||
const setUserInfo = (newInfo: UserInfo | UserInfo) => {
|
||||
const setUserInfo = (newInfo: UserInfo) => {
|
||||
info.value = newInfo;
|
||||
// 设置用户信息后自动更新权限
|
||||
setPermissions([]);
|
||||
@@ -231,7 +222,7 @@ export const useUserStore = defineStore(
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
async function login(loginForm: any) {
|
||||
async function login(loginForm: LoginFormData) {
|
||||
const response = await AuthAPI.login(loginForm);
|
||||
const data = response.data.data;
|
||||
if (response.data.code === ResultEnum.SUCCESS) {
|
||||
@@ -241,7 +232,7 @@ export const useUserStore = defineStore(
|
||||
type: "success",
|
||||
});
|
||||
}
|
||||
rememberMe.value = loginForm.remember;
|
||||
rememberMe.value = loginForm.remember ?? false;
|
||||
|
||||
const accessToken = data?.access_token || "";
|
||||
const refreshToken = data?.refresh_token || "";
|
||||
@@ -275,7 +266,7 @@ export const useUserStore = defineStore(
|
||||
const token = Auth.getAccessToken();
|
||||
if (token) {
|
||||
try {
|
||||
const response = await AuthAPI.logout({ token });
|
||||
const response = await AuthAPI.logout(token);
|
||||
if (response.data.code === ResultEnum.SUCCESS) {
|
||||
ElNotification({
|
||||
title: "通知",
|
||||
@@ -380,9 +371,6 @@ export const useUserStore = defineStore(
|
||||
rememberMe,
|
||||
getUserInfo,
|
||||
basicInfo,
|
||||
getRouteList,
|
||||
getPerms,
|
||||
getHasGetRoute,
|
||||
setUserInfo,
|
||||
setLoginStatus,
|
||||
setLanguage,
|
||||
@@ -406,6 +394,7 @@ export const useUserStore = defineStore(
|
||||
persist: {
|
||||
key: "user",
|
||||
storage: localStorage,
|
||||
pick: ["language", "isLogin", "searchHistory", "rememberMe"],
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
@@ -41,7 +41,7 @@ import { defineStore } from "pinia";
|
||||
import { ref, computed } from "vue";
|
||||
import { router } from "@/router";
|
||||
import { LocationQueryRaw, Router } from "vue-router";
|
||||
import { WorkTab } from "@/types";
|
||||
|
||||
import { useCommon } from "@/hooks/core/useCommon";
|
||||
import { ROUTE_PATH_LOGIN_ALT } from "@/router/staticRoutes";
|
||||
|
||||
@@ -95,7 +95,7 @@ export const useWorktabStore = defineStore(
|
||||
*/
|
||||
const safeRouterPush = (tab: Partial<WorkTab>): void => {
|
||||
if (!tab.path) {
|
||||
console.warn("尝试跳转到无效路径的标签页");
|
||||
if (import.meta.env.DEV) console.warn("尝试跳转到无效路径的标签页");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ export const useWorktabStore = defineStore(
|
||||
query: tab.query as LocationQueryRaw,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("路由跳转失败:", error);
|
||||
if (import.meta.env.DEV) console.error("路由跳转失败:", error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -127,7 +127,7 @@ export const useWorktabStore = defineStore(
|
||||
*/
|
||||
const openTab = (tab: WorkTab): void => {
|
||||
if (!tab.path) {
|
||||
console.warn("尝试打开无效的标签页");
|
||||
if (import.meta.env.DEV) console.warn("尝试打开无效的标签页");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -194,12 +194,12 @@ export const useWorktabStore = defineStore(
|
||||
const targetIndex = findTabIndex(path);
|
||||
|
||||
if (targetIndex === -1) {
|
||||
console.warn(`尝试关闭不存在的标签页: ${path}`);
|
||||
if (import.meta.env.DEV) console.warn(`尝试关闭不存在的标签页: ${path}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetTab && !isTabClosable(targetTab)) {
|
||||
console.warn(`尝试关闭固定标签页: ${path}`);
|
||||
if (import.meta.env.DEV) console.warn(`尝试关闭固定标签页: ${path}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ export const useWorktabStore = defineStore(
|
||||
const targetIndex = findTabIndex(path);
|
||||
|
||||
if (targetIndex === -1) {
|
||||
console.warn(`尝试关闭左侧标签页,但目标标签页不存在: ${path}`);
|
||||
if (import.meta.env.DEV) console.warn(`尝试关闭左侧标签页,但目标标签页不存在: ${path}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ export const useWorktabStore = defineStore(
|
||||
const closableLeftTabs = leftTabs.filter(isTabClosable);
|
||||
|
||||
if (closableLeftTabs.length === 0) {
|
||||
console.warn("左侧没有可关闭的标签页");
|
||||
if (import.meta.env.DEV) console.warn("左侧没有可关闭的标签页");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -275,7 +275,7 @@ export const useWorktabStore = defineStore(
|
||||
const targetIndex = findTabIndex(path);
|
||||
|
||||
if (targetIndex === -1) {
|
||||
console.warn(`尝试关闭右侧标签页,但目标标签页不存在: ${path}`);
|
||||
if (import.meta.env.DEV) console.warn(`尝试关闭右侧标签页,但目标标签页不存在: ${path}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -284,7 +284,7 @@ export const useWorktabStore = defineStore(
|
||||
const closableRightTabs = rightTabs.filter(isTabClosable);
|
||||
|
||||
if (closableRightTabs.length === 0) {
|
||||
console.warn("右侧没有可关闭的标签页");
|
||||
if (import.meta.env.DEV) console.warn("右侧没有可关闭的标签页");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ export const useWorktabStore = defineStore(
|
||||
const targetTab = getTab(path);
|
||||
|
||||
if (!targetTab) {
|
||||
console.warn(`尝试关闭其他标签页,但目标标签页不存在: ${path}`);
|
||||
if (import.meta.env.DEV) console.warn(`尝试关闭其他标签页,但目标标签页不存在: ${path}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ export const useWorktabStore = defineStore(
|
||||
const closableTabs = otherTabs.filter(isTabClosable);
|
||||
|
||||
if (closableTabs.length === 0) {
|
||||
console.warn("没有其他可关闭的标签页");
|
||||
if (import.meta.env.DEV) console.warn("没有其他可关闭的标签页");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -350,7 +350,7 @@ export const useWorktabStore = defineStore(
|
||||
});
|
||||
|
||||
if (closableTabs.length === 0) {
|
||||
console.warn("没有可关闭的标签页");
|
||||
if (import.meta.env.DEV) console.warn("没有可关闭的标签页");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -432,7 +432,7 @@ export const useWorktabStore = defineStore(
|
||||
const targetIndex = findTabIndex(path);
|
||||
|
||||
if (targetIndex === -1) {
|
||||
console.warn(`尝试切换不存在标签页的固定状态: ${path}`);
|
||||
if (import.meta.env.DEV) console.warn(`尝试切换不存在标签页的固定状态: ${path}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -464,12 +464,12 @@ export const useWorktabStore = defineStore(
|
||||
*/
|
||||
const validateWorktabs = (routerInstance: Router): void => {
|
||||
try {
|
||||
const allRoutes = routerInstance.getRoutes(); // 只调用一次,避免在循环中重复拷贝
|
||||
// 动态路由校验:优先使用路由 name 判断有效性;否则用 resolve 匹配参数化路径
|
||||
const isTabRouteValid = (tab: Partial<WorkTab>): boolean => {
|
||||
try {
|
||||
if (tab.name) {
|
||||
const routes = routerInstance.getRoutes();
|
||||
if (routes.some((r) => r.name === tab.name)) return true;
|
||||
if (allRoutes.some((r) => r.name === tab.name)) return true;
|
||||
}
|
||||
if (tab.path) {
|
||||
const resolved = routerInstance.resolve({
|
||||
@@ -494,7 +494,7 @@ export const useWorktabStore = defineStore(
|
||||
);
|
||||
|
||||
if (validTabs.length !== opened.value.length) {
|
||||
console.warn("发现无效的标签页路由,已自动清理");
|
||||
if (import.meta.env.DEV) console.warn("发现无效的标签页路由,已自动清理");
|
||||
const validPaths = new Set(validTabs.map((t) => t.path));
|
||||
// 未走 removeTab 批量剔除的标签:须同步 exclude;同名多标签时仅最后一条删尽才 exclude
|
||||
for (const tab of opened.value) {
|
||||
@@ -510,23 +510,31 @@ export const useWorktabStore = defineStore(
|
||||
current.value && isTabRouteValid(current.value) && !isLoginWorktab(current.value);
|
||||
|
||||
if (!isCurrentValid && validTabs.length > 0) {
|
||||
console.warn("当前激活标签无效,已自动切换");
|
||||
if (import.meta.env.DEV) console.warn("当前激活标签无效,已自动切换");
|
||||
const firstValid = validTabs[0];
|
||||
if (firstValid) current.value = firstValid;
|
||||
} else if (!isCurrentValid) {
|
||||
current.value = {};
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("验证工作台标签页失败:", error);
|
||||
if (import.meta.env.DEV) console.error("验证工作台标签页失败:", error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 清空所有状态(用于登出等场景)
|
||||
*
|
||||
* 保留固定标签页(fixedTab: true),登出后重新登录时首页等常驻标签依然存在。
|
||||
*/
|
||||
const clearAll = (): void => {
|
||||
current.value = {};
|
||||
opened.value = [];
|
||||
const fixedTabs = opened.value.filter((tab) => tab.fixedTab);
|
||||
if (fixedTabs.length > 0) {
|
||||
opened.value = fixedTabs;
|
||||
current.value = { ...fixedTabs[0] };
|
||||
} else {
|
||||
current.value = {};
|
||||
opened.value = [];
|
||||
}
|
||||
keepAliveExclude.value = [];
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user