移除调试日志并优化代码结构

refactor: 移除调试日志并优化代码结构
This commit is contained in:
fastapiadmin
2025-10-06 23:22:49 +08:00
committed by GitHub
9 changed files with 77 additions and 52 deletions
+24 -3
View File
@@ -137,7 +137,7 @@ const permissionStore = usePermissionStore();
const isModalVisible = ref(false); const isModalVisible = ref(false);
const searchKeyword = ref(""); const searchKeyword = ref("");
const searchInputRef = ref(); const searchInputRef = ref();
const excludedRoutes = ref(["/redirect", "/login", "/401", "/404"]); const excludedRoutes = ref(["/redirect", "/login", "/401", "/404", "/500", "/:pathMatch(.*)*"]);
const menuItems = ref<SearchItem[]>([]); const menuItems = ref<SearchItem[]>([]);
const searchResults = ref<SearchItem[]>([]); const searchResults = ref<SearchItem[]>([]);
const activeIndex = ref(-1); const activeIndex = ref(-1);
@@ -290,14 +290,35 @@ function navigateToRoute(item: SearchItem) {
function loadRoutes(routes: RouteRecordRaw[], parentPath = "") { function loadRoutes(routes: RouteRecordRaw[], parentPath = "") {
routes.forEach((route) => { routes.forEach((route) => {
// 计算完整路径
const path = route.path.startsWith("/") const path = route.path.startsWith("/")
? route.path ? route.path
: `${parentPath}${parentPath.endsWith("/") ? "" : "/"}${route.path}`; : `${parentPath}${parentPath.endsWith("/") ? "" : "/"}${route.path}`;
if (excludedRoutes.value.includes(route.path) || isExternal(route.path)) return;
// 检查是否需要排除
if (excludedRoutes.value.includes(route.path) || isExternal(route.path) || route.meta?.hidden) return;
// 处理有子路由的情况
if (route.children) { if (route.children) {
// 如果父路由本身有title,也添加到menuItems中
if (route.meta?.title) {
const title = route.meta.title === "dashboard" ? "首页" : route.meta.title;
menuItems.value.push({
title,
path,
name: typeof route.name === "string" ? route.name : undefined,
icon: route.meta.icon,
redirect: typeof route.redirect === "string" ? route.redirect : undefined,
params: route.meta.params
? JSON.parse(JSON.stringify(toRaw(route.meta.params)))
: undefined,
});
}
// 递归处理子路由
loadRoutes(route.children, path); loadRoutes(route.children, path);
} else if (route.meta?.title) { }
// 处理没有子路由但有title的情况
else if (route.meta?.title) {
const title = route.meta.title === "dashboard" ? "首页" : route.meta.title; const title = route.meta.title === "dashboard" ? "首页" : route.meta.title;
menuItems.value.push({ menuItems.value.push({
title, title,
@@ -13,7 +13,7 @@
<router-link <router-link
v-for="tag in displayedViews" :key="tag.fullPath" v-for="tag in displayedViews" :key="tag.fullPath"
:class="['tags-item', { active: tagsViewStore.isActive(tag) }]" :to="{ path: tag.path, query: tag.query }" :class="['tags-item', { active: tagsViewStore.isActive(tag) }]" :to="{ path: tag.path, query: tag.query }"
@click="router.push({path: tag.fullPath, query: tag.query})" @click="tagSwitchSource = 'tab'"
@click.middle="handleMiddleClick(tag)"> @click.middle="handleMiddleClick(tag)">
<!-- 为所有标签添加右键菜单 --> <!-- 为所有标签添加右键菜单 -->
<el-dropdown <el-dropdown
@@ -340,14 +340,6 @@ const updateCurrentTag = () => {
}); });
}; };
/**
* 处理标签点击
*/
// const handleTabClick = (tag: TagView) => {
// // 设置标签切换来源为标签容器点击
// tagSwitchSource.value = 'tab';
// };
/** /**
* 处理中键点击 * 处理中键点击
*/ */
@@ -606,7 +598,7 @@ const scrollState = ref({
}) })
/** /**
* 自动滚动到最新标签 * 自动滚动到最新标签或确保当前激活标签可见
*/ */
const autoScrollToLatestTag = () => { const autoScrollToLatestTag = () => {
const scrollWrapper = scrollbarRef.value?.wrapRef const scrollWrapper = scrollbarRef.value?.wrapRef
@@ -619,7 +611,36 @@ const autoScrollToLatestTag = () => {
// 判断容器是否已满(内容宽度是否超过容器宽度) // 判断容器是否已满(内容宽度是否超过容器宽度)
const isContainerFull = contentWidth > containerWidth const isContainerFull = contentWidth > containerWidth
// 如果容器已满且还没有滚动到最新标签,则滚动到最右边 // 查找当前激活的标签元素
const activeTagElement = document.querySelector('.tags-item.active')
if (activeTagElement) {
// 将Element类型断言为HTMLElement类型以访问offsetWidth属性
const activeHtmlElement = activeTagElement as HTMLElement;
// 计算激活标签的位置信息
const activeTagRect = activeHtmlElement.getBoundingClientRect()
const containerRect = scrollWrapper.getBoundingClientRect()
// 计算标签相对于容器的位置
const tagLeft = activeTagRect.left - containerRect.left + scrollWrapper.scrollLeft
const tagRight = tagLeft + activeHtmlElement.offsetWidth
// 检查标签是否完全在可见区域内
if (tagLeft < scrollWrapper.scrollLeft || tagRight > scrollWrapper.scrollLeft + containerWidth) {
// 如果标签不在可见区域内,滚动到使标签居中的位置
const targetScrollLeft = tagLeft - (containerWidth - activeHtmlElement.offsetWidth) / 2
const maxScrollLeft = contentWidth - containerWidth
const minScrollLeft = 0
const clampedScrollLeft = Math.max(minScrollLeft, Math.min(maxScrollLeft, targetScrollLeft))
scrollbarRef.value.setScrollLeft(clampedScrollLeft)
scrollState.value.hasScrolledToLatest = true
scrollState.value.isContainerFull = isContainerFull
return
}
}
// 如果没有找到激活标签或激活标签已经在可见区域内,则使用原来的逻辑
if (isContainerFull && !scrollState.value.hasScrolledToLatest) { if (isContainerFull && !scrollState.value.hasScrolledToLatest) {
// 计算需要滚动到的位置,确保最新标签在右侧可见 // 计算需要滚动到的位置,确保最新标签在右侧可见
const maxScrollLeft = contentWidth - containerWidth const maxScrollLeft = contentWidth - containerWidth
@@ -633,7 +654,6 @@ const autoScrollToLatestTag = () => {
scrollState.value.hasScrolledToLatest = false scrollState.value.hasScrolledToLatest = false
scrollState.value.isContainerFull = false scrollState.value.isContainerFull = false
} }
// 如果容器已满且已经滚动过,则保持当前位置
} }
// 监听路由变化 // 监听路由变化
@@ -666,15 +686,15 @@ watch(
} }
); );
// 监听当前路由变化,确保点击隐藏标签时滚动到最新位置 // 监听当前路由变化,确保路由切换时自动滚动到当前标签
// watch( watch(
// () => route.path, () => route.path,
// () => { () => {
// nextTick(() => { nextTick(() => {
// autoScrollToLatestTag(); autoScrollToLatestTag();
// }); });
// } }
// ); );
// 初始化 // 初始化
onMounted(() => { onMounted(() => {
-3
View File
@@ -89,9 +89,6 @@ const router = createRouter({
// 全局注册 router // 全局注册 router
// 为了捕获并处理全局错误,在注册路由时添加错误处理 // 为了捕获并处理全局错误,在注册路由时添加错误处理
export function setupRouter(app: App<Element>) { export function setupRouter(app: App<Element>) {
app.config.errorHandler = (err, instance, info) => {
console.error('全局错误捕获:', err, '实例:', instance, '信息:', info);
};
app.use(router); app.use(router);
} }
@@ -82,7 +82,7 @@ export const usePermissionStore = defineStore("permission", () => {
* *
* @returns Promise<RouteRecordRaw[]> 解析后的动态路由列表 * @returns Promise<RouteRecordRaw[]> 解析后的动态路由列表
*/ */
async function generateRoutes() { async function generateRoutes():Promise<RouteRecordRaw[]> {
try { try {
const userStore = useUserStore(); const userStore = useUserStore();
// 确保获取用户信息和路由列表 // 确保获取用户信息和路由列表
@@ -103,7 +103,6 @@ export const usePermissionStore = defineStore("permission", () => {
} catch (error: any) { } catch (error: any) {
// 即使失败也要设置状态,避免无限重试 // 即使失败也要设置状态,避免无限重试
isRouteGenerated.value = false; isRouteGenerated.value = false;
throw error; throw error;
} }
} }
-2
View File
@@ -60,8 +60,6 @@ httpRequest.interceptors.response.use((response: AxiosResponse<ApiResponse>) =>
return response; return response;
}, async (error: AxiosError<ApiResponse>) => { }, async (error: AxiosError<ApiResponse>) => {
console.log(error);
const data = error.response?.data; const data = error.response?.data;
// 处理blob类型的错误响应 // 处理blob类型的错误响应
+3 -3
View File
@@ -66,12 +66,12 @@
<el-button v-hasPerm="['generator:demo:delete']" type="danger" icon="delete" :disabled="selectIds.length === 0" @click="handleDelete(selectIds)">批量删除</el-button> <el-button v-hasPerm="['generator:demo:delete']" type="danger" icon="delete" :disabled="selectIds.length === 0" @click="handleDelete(selectIds)">批量删除</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-dropdown trigger="click"> <el-dropdown v-hasPerm="['generator:demo:batch']" trigger="click">
<el-button type="default" :disabled="selectIds.length === 0" icon="ArrowDown">更多</el-button> <el-button type="default" :disabled="selectIds.length === 0" icon="ArrowDown">更多</el-button>
<template #dropdown> <template #dropdown>
<el-dropdown-menu> <el-dropdown-menu>
<el-dropdown-item v-hasPerm="['generator:demo:batch_available']" icon="Check" @click="handleMoreClick(true)">批量启用</el-dropdown-item> <el-dropdown-item icon="Check" @click="handleMoreClick(true)">批量启用</el-dropdown-item>
<el-dropdown-item v-hasPerm="['generator:demo:batch_available']" icon="CircleClose" @click="handleMoreClick(false)">批量停用</el-dropdown-item> <el-dropdown-item icon="CircleClose" @click="handleMoreClick(false)">批量停用</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</template> </template>
</el-dropdown> </el-dropdown>
@@ -228,9 +228,10 @@ async function handleLoginSubmit() {
appStore.showGuide(true); appStore.showGuide(true);
} catch (error: any) { } catch (error: any) {
console.error(error); if (error) {
// 5. 统一错误处理 getCaptcha(); // 刷新验证码
getCaptcha(); // 刷新验证码 }
} finally { } finally {
loading.value = false; loading.value = false;
} }
@@ -27,7 +27,6 @@
:data="{ type: key }" :data="{ type: key }"
:name="'file'" :name="'file'"
:max-file-size="item.maxFileSize" :max-file-size="item.maxFileSize"
:file-list="fileLists[key] || []"
@on-success="(fileInfo: UploadFilePath) => handleUploadSuccess(fileInfo, key)" @on-success="(fileInfo: UploadFilePath) => handleUploadSuccess(fileInfo, key)"
@on-error="handleUploadError" @on-error="handleUploadError"
@input="markModified(key)" @input="markModified(key)"
@@ -55,12 +54,6 @@ import SingleImageUpload from '@/components/Upload/SingleImageUpload.vue';
import { useAppStore } from "@/store/modules/app.store"; import { useAppStore } from "@/store/modules/app.store";
import { DeviceEnum } from "@/enums/settings/device.enum"; import { DeviceEnum } from "@/enums/settings/device.enum";
// 文件列表类型定义
interface FileListItem {
url: string;
}
const appStore = useAppStore(); const appStore = useAppStore();
const drawerSize = computed(() => (appStore.device === DeviceEnum.DESKTOP ? "500px" : "90%")); const drawerSize = computed(() => (appStore.device === DeviceEnum.DESKTOP ? "500px" : "90%"));
@@ -78,9 +71,6 @@ const configState = reactive<ConfigTable>({
description: '' description: ''
}); });
// 存储文件上传列表
const fileLists = reactive<Record<string, FileListItem[]>>({});
// 记录修改过的字段 // 记录修改过的字段
const modifiedFields = reactive<Record<string, boolean>>({}); const modifiedFields = reactive<Record<string, boolean>>({});
@@ -175,9 +165,6 @@ const handleUploadSuccess = (fileInfo: UploadFilePath, type: string) => {
logoConfigs.value[type as keyof typeof logoConfigs.value].config_value = fileUrl; logoConfigs.value[type as keyof typeof logoConfigs.value].config_value = fileUrl;
} }
// 更新文件列表
fileLists[type] = [{ url: fileUrl }];
// 标记为已修改 // 标记为已修改
markModified(type); markModified(type);
}; };
+4 -2
View File
@@ -70,7 +70,6 @@ export default defineConfig(({ mode }: ConfigEnv) => {
}, },
vueTemplate: true, vueTemplate: true,
// 导入函数类型声明文件路径 (false:关闭自动生成) // 导入函数类型声明文件路径 (false:关闭自动生成)
// dts: true,
dts: "src/types/auto-imports.d.ts", dts: "src/types/auto-imports.d.ts",
}), }),
// 组件自动导入 // 组件自动导入
@@ -82,7 +81,6 @@ export default defineConfig(({ mode }: ConfigEnv) => {
// 指定自定义组件位置(默认:src/components) // 指定自定义组件位置(默认:src/components)
dirs: ["src/components", "src/**/components"], dirs: ["src/components", "src/**/components"],
// 导入组件类型声明文件路径 (false:关闭自动生成) // 导入组件类型声明文件路径 (false:关闭自动生成)
// dts: false,
dts: "src/types/components.d.ts", dts: "src/types/components.d.ts",
}), }),
], ],
@@ -189,6 +187,10 @@ export default defineConfig(({ mode }: ConfigEnv) => {
"element-plus/es/components/container/style/index", "element-plus/es/components/container/style/index",
"element-plus/es/components/main/style/index", "element-plus/es/components/main/style/index",
"element-plus/es/components/aside/style/index", "element-plus/es/components/aside/style/index",
"element-plus/es/components/footer/style/index",
"element-plus/es/components/header/style/index",
"element-plus/es/components/slider/style/index",
"element-plus/es/components/button-group/style/index",
], ],
}, },
// 构建配置 // 构建配置