From 8701a06f34611e230da6afb51d4c7c5a774efcaa Mon Sep 17 00:00:00 2001 From: shi <936384804@qq.com> Date: Sat, 15 Nov 2025 16:40:35 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84ue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 23 ++ src/assets/large/outscreen.png | Bin 0 -> 4427 bytes src/permission.ts | 5 + src/utils/request.ts | 113 ++++++-- src/views/ueScreen/components/date.vue | 255 +++++++++++++++++++ src/views/ueScreen/components/header.vue | 109 +++++++- src/views/ueScreen/components/options.ts | 2 +- src/views/ueScreen/components/project.vue | 206 +++++++++++++++ src/views/ueScreen/components/smalltitle.vue | 13 +- src/views/ueScreen/index.vue | 73 +++++- 10 files changed, 757 insertions(+), 42 deletions(-) create mode 100644 src/assets/large/outscreen.png create mode 100644 src/views/ueScreen/components/date.vue create mode 100644 src/views/ueScreen/components/project.vue diff --git a/index.html b/index.html index a732a19..6cbd66f 100644 --- a/index.html +++ b/index.html @@ -212,5 +212,28 @@ + diff --git a/src/assets/large/outscreen.png b/src/assets/large/outscreen.png new file mode 100644 index 0000000000000000000000000000000000000000..0e139619e2ca3cadb258d3032033a80150ede1b1 GIT binary patch literal 4427 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 S<0@lu*i4NqNwo&l*#7}?*T|9p literal 0 HcmV?d00001 diff --git a/src/permission.ts b/src/permission.ts index 7649149..c8c1acb 100644 --- a/src/permission.ts +++ b/src/permission.ts @@ -22,6 +22,11 @@ const isWhiteList = (path: string) => { router.beforeEach(async (to, from) => { NProgress.start(); + // 特殊页面放行 + if (['/ueScreen'].includes(to.path)) { + return true; + } + // 已登录 if (getToken()) { if (to.meta.title) useSettingsStore().setTitle(to.meta.title); diff --git a/src/utils/request.ts b/src/utils/request.ts index ca0e341..e53f32c 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -14,6 +14,10 @@ import router from '@/router'; const encryptHeader = 'encrypt-key'; let downloadLoadingInstance: LoadingInstance; + +let silentLoginPromise: Promise | null = null; +let retryQueue: Array<() => void> = []; // 等待重试的请求队列 + // 是否显示重新登录 export const isRelogin = { show: false }; export const globalHeaders = () => { @@ -105,7 +109,7 @@ service.interceptors.request.use( // 响应拦截器 service.interceptors.response.use( - (res: AxiosResponse) => { + async (res: AxiosResponse) => { if (import.meta.env.VITE_APP_ENCRYPT === 'true') { // 加密后的 AES 秘钥 const keyStr = res.headers[encryptHeader]; @@ -131,6 +135,65 @@ service.interceptors.response.use( return res.data; } if (code === 401) { + // 处理ueScreen未登录 + const isInExternalPage = window.self !== window.top || window.location.pathname.includes('/ueScreen'); + + if (isInExternalPage) { + console.log('[外链页] 检测到 401'); + + // 统一处理并发401 + if (silentLoginPromise) { + // 登录正在进行时,等待完成 + console.log('[外链页] 等待静默登录完成'); + return new Promise((resolve) => { + retryQueue.push(() => { + const newToken = getToken(); + if (newToken) { + res.config.headers.Authorization = 'Bearer ' + newToken; + } + resolve(axios.request(res.config)); + }); + }); + } + + // 启动新的静默登录 + if (typeof window['silentLogin'] === 'function') { + silentLoginPromise = window + .silentLogin(true) + .catch(() => false) + .finally(() => { + silentLoginPromise = null; + }); + + const ok = await silentLoginPromise; + const newToken = getToken(); + + if (ok && newToken) { + axios.defaults.headers.common['Authorization'] = 'Bearer ' + newToken; + + // ✅ 每个请求返回自己的 Promise + return new Promise((resolve) => { + retryQueue.push((config) => { + axios.request(config).then((newRes) => { + console.log('🚀 ~ config:', newRes.data); + resolve(newRes.data); // 保持统一结构 + }); + }); + + // 如果登录刚好完成,就立即执行回调 + retryQueue.forEach((cb) => cb(res.config)); + retryQueue = []; + }); + } else { + retryQueue = []; + console.warn('[外链页] 静默登录失败'); + return Promise.reject('静默登录失败'); + } + } + + return Promise.reject('外链页未配置静默登录'); + } + // prettier-ignore if (!isRelogin.show) { isRelogin.show = true; @@ -184,31 +247,31 @@ export function download(url: string, params: any, fileName: string) { downloadLoadingInstance = ElLoading.service({ text: '正在下载数据,请稍候', background: 'rgba(0, 0, 0, 0.7)' }); // prettier-ignore return service.post(url, params, { - transformRequest: [ - (params: any) => { - return tansParams(params); - } - ], - headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, - responseType: 'blob' - }).then(async (resp: any) => { - const isLogin = blobValidate(resp); - if (isLogin) { - const blob = new Blob([resp]); - FileSaver.saveAs(blob, fileName); - } else { - const blob = new Blob([resp]); - const resText = await blob.text(); - const rspObj = JSON.parse(resText); - const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']; - ElMessage.error(errMsg); + transformRequest: [ + (params: any) => { + return tansParams(params); } - downloadLoadingInstance.close(); - }).catch((r: any) => { - console.error(r); - ElMessage.error('下载文件出现错误,请联系管理员!'); - downloadLoadingInstance.close(); - }); + ], + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + responseType: 'blob' + }).then(async (resp: any) => { + const isLogin = blobValidate(resp); + if (isLogin) { + const blob = new Blob([resp]); + FileSaver.saveAs(blob, fileName); + } else { + const blob = new Blob([resp]); + const resText = await blob.text(); + const rspObj = JSON.parse(resText); + const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']; + ElMessage.error(errMsg); + } + downloadLoadingInstance.close(); + }).catch((r: any) => { + console.error(r); + ElMessage.error('下载文件出现错误,请联系管理员!'); + downloadLoadingInstance.close(); + }); } // 导出 axios 实例 export default service; diff --git a/src/views/ueScreen/components/date.vue b/src/views/ueScreen/components/date.vue new file mode 100644 index 0000000..682ef36 --- /dev/null +++ b/src/views/ueScreen/components/date.vue @@ -0,0 +1,255 @@ + + + + + \ No newline at end of file diff --git a/src/views/ueScreen/components/header.vue b/src/views/ueScreen/components/header.vue index a4a8e44..5f71bda 100644 --- a/src/views/ueScreen/components/header.vue +++ b/src/views/ueScreen/components/header.vue @@ -1,38 +1,79 @@ + + \ No newline at end of file diff --git a/src/views/ueScreen/components/smalltitle.vue b/src/views/ueScreen/components/smalltitle.vue index 69d5af2..4f2bb25 100644 --- a/src/views/ueScreen/components/smalltitle.vue +++ b/src/views/ueScreen/components/smalltitle.vue @@ -18,7 +18,18 @@ const props = defineProps({ })