diff --git a/.env.production b/.env.production index f868eaf..c715e62 100644 --- a/.env.production +++ b/.env.production @@ -1,2 +1,2 @@ # 生产环境接口 -VITE_API_BASE_URL='https://backend.yunzer.cn' +VITE_API_BASE_URL='https://api.yunzer.cn' diff --git a/src/main.js b/src/main.js index 5813324..0478597 100644 --- a/src/main.js +++ b/src/main.js @@ -37,9 +37,18 @@ authStore.checkAuth() // 如果用户已登录,在应用启动时加载动态路由 if (authStore.isLoggedIn) { - loadAndAddDynamicRoutes().catch(err => { - console.error('应用启动时加载动态路由失败:', err); - }); + loadAndAddDynamicRoutes() + .catch(err => { + console.error('应用启动时加载动态路由失败:', err); + }) + .then(() => { + // 检查是否因为 token 无效而导致路由加载失败 + const token = localStorage.getItem('token'); + if (!token) { + authStore.clearToken(); + window.location.href = '#/login'; + } + }); } app.mount('#app') \ No newline at end of file diff --git a/src/router/index.js b/src/router/index.js index 70c88c9..3b54348 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -61,17 +61,17 @@ export async function loadAndAddDynamicRoutes() { if (routesLoadingPromise) { return routesLoadingPromise; } - + if (dynamicRoutesAdded) { return Promise.resolve(); } - + routesLoadingPromise = (async () => { try { const { useMenuStore } = await import("@/stores/menu"); const menuStore = useMenuStore(); const menuData = await menuStore.fetchMenus(); - + if (menuData && menuData.length > 0) { addDynamicRoutes(menuData); dynamicRoutesAdded = true; @@ -86,10 +86,10 @@ export async function loadAndAddDynamicRoutes() { console.error('加载动态路由失败:', error); dynamicRoutesAdded = true; routesLoadingPromise = null; - return Promise.resolve(); + throw error; } })(); - + return routesLoadingPromise; } diff --git a/src/stores/menu.js b/src/stores/menu.js index 36a480c..4a128e1 100644 --- a/src/stores/menu.js +++ b/src/stores/menu.js @@ -170,7 +170,14 @@ export const useMenuStore = defineStore('menu', () => { response: err.response, stack: err.stack }); - + + // 如果是 token 无效错误,不使用缓存,直接抛出 + if (err.message === 'token无效' || err.response?.status === 401) { + clearCache(); + menus.value = []; + throw err; + } + // 如果出错,尝试使用缓存数据 const cachedMenus = loadFromCache(); if (cachedMenus && cachedMenus.length > 0) { @@ -178,7 +185,7 @@ export const useMenuStore = defineStore('menu', () => { menus.value = cachedMenus; return cachedMenus; } - + // 如果连缓存都没有,设置空数组,避免页面崩溃 menus.value = []; throw err; diff --git a/src/utils/request.js b/src/utils/request.js index aa9f24c..7e4571d 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -40,16 +40,14 @@ service.interceptors.response.use( if (error.response) { switch (error.response.status) { case 401: - // 处理未授权的错误 - 清除token并跳转登录页 console.error('未授权,请重新登录'); localStorage.removeItem('token'); - // 避免循环导入,直接使用路由 + localStorage.removeItem('userInfo'); if (window.location.hash !== '#/login') { window.location.href = '#/login'; } - break; + return Promise.reject(new Error('token无效')); case 404: - // 处理资源不存在的错误 console.error('请求的资源不存在'); break; default: diff --git a/src/views/apps/cms/templates/index.vue b/src/views/apps/cms/templates/index.vue index 48e814f..aef49a1 100644 --- a/src/views/apps/cms/templates/index.vue +++ b/src/views/apps/cms/templates/index.vue @@ -74,14 +74,17 @@ import { ref, onMounted } from 'vue' import { ElMessage } from 'element-plus' import { Refresh, Loading } from '@element-plus/icons-vue' import { getThemeList, switchTheme } from '@/api/theme' +import { useAuthStore } from '@/stores/auth' const API_BASE_URL = import.meta.env.VITE_API_BASE_URL +const authStore = useAuthStore() // 状态 const loading = ref(false) const switching = ref('') const templateList = ref([]) const currentTheme = ref('default') +const currentTid = ref(0) // 获取完整预览图URL const getPreviewUrl = (path: string) => { @@ -94,7 +97,8 @@ const getPreviewUrl = (path: string) => { const fetchTemplates = async () => { loading.value = true try { - const res = await getThemeList() + currentTid.value = (authStore.user as any)?.tid || 0 + const res = await getThemeList({ tid: currentTid.value }) if (res.code === 200) { templateList.value = res.data.list || [] currentTheme.value = res.data.currentTheme || 'default' @@ -110,9 +114,13 @@ const fetchTemplates = async () => { // 切换模板 const handleUse = async (item: any) => { + if (!currentTid.value) { + ElMessage.error('请先选择租户') + return + } switching.value = item.key try { - const res = await switchTheme({ theme_key: item.key }) + const res = await switchTheme({ tid: currentTid.value, theme_key: item.key }) if (res.code === 200) { currentTheme.value = item.key ElMessage.success('切换成功') diff --git a/src/views/basicSettings/siteSettings/components/normalSettings.vue b/src/views/basicSettings/siteSettings/components/normalSettings.vue index c81de3e..d4e4313 100644 --- a/src/views/basicSettings/siteSettings/components/normalSettings.vue +++ b/src/views/basicSettings/siteSettings/components/normalSettings.vue @@ -39,11 +39,30 @@ + + + + + +
请上传ico格式文件
+
- - + + + + + @@ -76,17 +95,21 @@ const normalFormRef = ref(); const sitename = ref(""); const companyname = ref(""); +const companyintroduction = ref(""); const logo = ref(""); const logow = ref(""); const description = ref(""); const copyright = ref(""); const icp = ref(""); +const ico = ref(""); const formData = { sitename, companyname, + companyintroduction, logo, logow, + ico, description, copyright, icp, @@ -102,8 +125,10 @@ const initNormalInfos = async () => { if (res.code === 200 && res.data) { const data = res.data; sitename.value = data.sitename || ""; + companyintroduction.value = data.companyintroduction || ""; logo.value = data.logo || ""; logow.value = data.logow || ""; + ico.value = data.ico || ""; description.value = data.description || ""; copyright.value = data.copyright || ""; icp.value = data.icp || ""; @@ -154,8 +179,10 @@ const handleSaveNormalInfos = async () => { const data = { tid: authStore.user.tid, sitename: sitename.value, + companyintroduction: companyintroduction.value, logo: logo.value, logow: logow.value, + ico: ico.value, description: description.value, companyname: companyname.value, copyright: copyright.value, @@ -171,21 +198,39 @@ const handleSaveNormalInfos = async () => { }); }; +const handleIconChange = (file: UploadFile) => { + const uploadFormData = new FormData(); + uploadFormData.append("file", file.raw); + uploadFormData.append("cate", "site"); + + uploadFile(uploadFormData).then((uploadRes) => { + if ((uploadRes.code === 200 || uploadRes.code === 201) && uploadRes.data?.url) { + ico.value = uploadRes.data.url.replace(/\\/g, "/"); + } else { + ElMessage.error(uploadRes.msg || "上传失败"); + } + }); +}; + const resetnormalForm = () => { sitename.value = ""; companyname.value = ""; + companyintroduction.value = ""; logo.value = ""; logow.value = ""; + ico.value = ""; description.value = ""; - copyright.value = ""; + copyright.value = ""; icp.value = ""; }; defineExpose({ sitename, companyname, + companyintroduction, logo, logow, + ico, description, copyright, icp, @@ -198,10 +243,17 @@ onMounted(() => {