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 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(() => {
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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类型的错误响应
|
||||||
|
|||||||
@@ -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);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
// 构建配置
|
// 构建配置
|
||||||
|
|||||||
Reference in New Issue
Block a user