mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-09-21 12:52:26 +00:00
移除调试日志并优化代码结构
refactor: 移除调试日志并优化代码结构
This commit is contained in:
@@ -137,7 +137,7 @@ const permissionStore = usePermissionStore();
|
||||
const isModalVisible = ref(false);
|
||||
const searchKeyword = 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 searchResults = ref<SearchItem[]>([]);
|
||||
const activeIndex = ref(-1);
|
||||
@@ -290,14 +290,35 @@ function navigateToRoute(item: SearchItem) {
|
||||
|
||||
function loadRoutes(routes: RouteRecordRaw[], parentPath = "") {
|
||||
routes.forEach((route) => {
|
||||
// 计算完整路径
|
||||
const path = route.path.startsWith("/")
|
||||
? 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) {
|
||||
// 如果父路由本身有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);
|
||||
} else if (route.meta?.title) {
|
||||
}
|
||||
// 处理没有子路由但有title的情况
|
||||
else if (route.meta?.title) {
|
||||
const title = route.meta.title === "dashboard" ? "首页" : route.meta.title;
|
||||
menuItems.value.push({
|
||||
title,
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<router-link
|
||||
v-for="tag in displayedViews" :key="tag.fullPath"
|
||||
: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)">
|
||||
<!-- 为所有标签添加右键菜单 -->
|
||||
<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 scrollWrapper = scrollbarRef.value?.wrapRef
|
||||
@@ -619,7 +611,36 @@ const autoScrollToLatestTag = () => {
|
||||
// 判断容器是否已满(内容宽度是否超过容器宽度)
|
||||
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) {
|
||||
// 计算需要滚动到的位置,确保最新标签在右侧可见
|
||||
const maxScrollLeft = contentWidth - containerWidth
|
||||
@@ -633,7 +654,6 @@ const autoScrollToLatestTag = () => {
|
||||
scrollState.value.hasScrolledToLatest = false
|
||||
scrollState.value.isContainerFull = false
|
||||
}
|
||||
// 如果容器已满且已经滚动过,则保持当前位置
|
||||
}
|
||||
|
||||
// 监听路由变化
|
||||
@@ -666,15 +686,15 @@ watch(
|
||||
}
|
||||
);
|
||||
|
||||
// 监听当前路由变化,确保点击隐藏标签时滚动到最新位置
|
||||
// watch(
|
||||
// () => route.path,
|
||||
// () => {
|
||||
// nextTick(() => {
|
||||
// autoScrollToLatestTag();
|
||||
// });
|
||||
// }
|
||||
// );
|
||||
// 监听当前路由变化,确保路由切换时自动滚动到当前标签
|
||||
watch(
|
||||
() => route.path,
|
||||
() => {
|
||||
nextTick(() => {
|
||||
autoScrollToLatestTag();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
|
||||
@@ -89,9 +89,6 @@ const router = createRouter({
|
||||
// 全局注册 router
|
||||
// 为了捕获并处理全局错误,在注册路由时添加错误处理
|
||||
export function setupRouter(app: App<Element>) {
|
||||
app.config.errorHandler = (err, instance, info) => {
|
||||
console.error('全局错误捕获:', err, '实例:', instance, '信息:', info);
|
||||
};
|
||||
app.use(router);
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ export const usePermissionStore = defineStore("permission", () => {
|
||||
*
|
||||
* @returns Promise<RouteRecordRaw[]> 解析后的动态路由列表
|
||||
*/
|
||||
async function generateRoutes() {
|
||||
async function generateRoutes():Promise<RouteRecordRaw[]> {
|
||||
try {
|
||||
const userStore = useUserStore();
|
||||
// 确保获取用户信息和路由列表
|
||||
@@ -103,7 +103,6 @@ export const usePermissionStore = defineStore("permission", () => {
|
||||
} catch (error: any) {
|
||||
// 即使失败也要设置状态,避免无限重试
|
||||
isRouteGenerated.value = false;
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,8 +60,6 @@ httpRequest.interceptors.response.use((response: AxiosResponse<ApiResponse>) =>
|
||||
|
||||
return response;
|
||||
}, async (error: AxiosError<ApiResponse>) => {
|
||||
console.log(error);
|
||||
|
||||
const data = error.response?.data;
|
||||
|
||||
// 处理blob类型的错误响应
|
||||
|
||||
@@ -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-col>
|
||||
<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>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item v-hasPerm="['generator:demo:batch_available']" 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="Check" @click="handleMoreClick(true)">批量启用</el-dropdown-item>
|
||||
<el-dropdown-item icon="CircleClose" @click="handleMoreClick(false)">批量停用</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
|
||||
@@ -228,9 +228,10 @@ async function handleLoginSubmit() {
|
||||
appStore.showGuide(true);
|
||||
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
// 5. 统一错误处理
|
||||
getCaptcha(); // 刷新验证码
|
||||
if (error) {
|
||||
getCaptcha(); // 刷新验证码
|
||||
}
|
||||
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
:data="{ type: key }"
|
||||
:name="'file'"
|
||||
:max-file-size="item.maxFileSize"
|
||||
:file-list="fileLists[key] || []"
|
||||
@on-success="(fileInfo: UploadFilePath) => handleUploadSuccess(fileInfo, key)"
|
||||
@on-error="handleUploadError"
|
||||
@input="markModified(key)"
|
||||
@@ -55,12 +54,6 @@ import SingleImageUpload from '@/components/Upload/SingleImageUpload.vue';
|
||||
import { useAppStore } from "@/store/modules/app.store";
|
||||
import { DeviceEnum } from "@/enums/settings/device.enum";
|
||||
|
||||
// 文件列表类型定义
|
||||
interface FileListItem {
|
||||
url: string;
|
||||
}
|
||||
|
||||
|
||||
const appStore = useAppStore();
|
||||
const drawerSize = computed(() => (appStore.device === DeviceEnum.DESKTOP ? "500px" : "90%"));
|
||||
|
||||
@@ -78,9 +71,6 @@ const configState = reactive<ConfigTable>({
|
||||
description: ''
|
||||
});
|
||||
|
||||
// 存储文件上传列表
|
||||
const fileLists = reactive<Record<string, FileListItem[]>>({});
|
||||
|
||||
// 记录修改过的字段
|
||||
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;
|
||||
}
|
||||
|
||||
// 更新文件列表
|
||||
fileLists[type] = [{ url: fileUrl }];
|
||||
|
||||
// 标记为已修改
|
||||
markModified(type);
|
||||
};
|
||||
|
||||
@@ -70,7 +70,6 @@ export default defineConfig(({ mode }: ConfigEnv) => {
|
||||
},
|
||||
vueTemplate: true,
|
||||
// 导入函数类型声明文件路径 (false:关闭自动生成)
|
||||
// dts: true,
|
||||
dts: "src/types/auto-imports.d.ts",
|
||||
}),
|
||||
// 组件自动导入
|
||||
@@ -82,7 +81,6 @@ export default defineConfig(({ mode }: ConfigEnv) => {
|
||||
// 指定自定义组件位置(默认:src/components)
|
||||
dirs: ["src/components", "src/**/components"],
|
||||
// 导入组件类型声明文件路径 (false:关闭自动生成)
|
||||
// dts: false,
|
||||
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/main/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",
|
||||
],
|
||||
},
|
||||
// 构建配置
|
||||
|
||||
Reference in New Issue
Block a user