From 38554e90f6c6c9fd41e9ec7651437582bcb94526 Mon Sep 17 00:00:00 2001 From: wangdan-fit2cloud Date: Fri, 13 Nov 2026 18:39:05 +0800 Subject: [PATCH] feat: error page --- ui/src/api/admin/core/request.ts | 2 +- ui/src/assets/error/404.png | Bin 0 -> 21002 bytes ui/src/assets/error/500.png | Bin 0 -> 6106 bytes ui/src/router/ROUTE_README.md | 19 ++++++++++++------- ui/src/router/admin/index.ts | 8 ++++++-- ui/src/router/chat/index.ts | 13 +++++-------- ui/src/router/chat/routes.ts | 9 +++++---- ui/src/stores/chat/auth.ts | 5 ++++- ui/src/views/VIEW_README.md | 3 ++- ui/src/views/chat/error/404.vue | 12 ++++++++++++ ui/src/views/chat/error/NoService.vue | 8 ++++++++ ui/src/views/chat/error/index.vue | 5 ----- ui/src/views/chat/index.vue | 15 ++++++++++----- ui/src/views/chat/login/index.vue | 6 +++++- ui/src/views/error/404.vue | 12 ++++++++++++ ui/src/views/error/NoPermission.vue | 8 ++++++++ ui/src/views/error/NoService.vue | 8 ++++++++ ui/src/views/error/index.vue | 20 -------------------- ui/src/views/portal/index.vue | 15 ++++++++++----- 19 files changed, 108 insertions(+), 60 deletions(-) create mode 100644 ui/src/assets/error/404.png create mode 100644 ui/src/assets/error/500.png create mode 100644 ui/src/views/chat/error/404.vue create mode 100644 ui/src/views/chat/error/NoService.vue delete mode 100644 ui/src/views/chat/error/index.vue create mode 100644 ui/src/views/error/404.vue create mode 100644 ui/src/views/error/NoPermission.vue create mode 100644 ui/src/views/error/NoService.vue delete mode 100644 ui/src/views/error/index.vue diff --git a/ui/src/api/admin/core/request.ts b/ui/src/api/admin/core/request.ts index 5ed369db5e4..8ac4e123ecc 100644 --- a/ui/src/api/admin/core/request.ts +++ b/ui/src/api/admin/core/request.ts @@ -127,7 +127,7 @@ request.interceptors.response.use( console.error(error) } if (status === 404 && !requestUrl.includes('/application/authentication')) { - void router.replace({ name: 'not-found', params: { pathMatch: ['404'] } }) + void router.replace({ name: '404' }) } if (status === 401 && !requestUrl.includes('application/profile')) { const { auth } = useStore() diff --git a/ui/src/assets/error/404.png b/ui/src/assets/error/404.png new file mode 100644 index 0000000000000000000000000000000000000000..251157c1c665c7b5c7746f137dd45374b4c7ecd1 GIT binary patch literal 21002 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 Li(Tb!e#w6az+jk> literal 0 HcmV?d00001 diff --git a/ui/src/assets/error/500.png b/ui/src/assets/error/500.png new file mode 100644 index 0000000000000000000000000000000000000000..0717ad6a1f0f69cadc79d45438209c7decb81685 GIT binary patch literal 6106 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 X(X+C@As%G?hhV5@qFb*059 import('@/views/error/index.vue'), meta: { title: '页面不存在' } }, + // 承接权限守卫在没有可访问后续页面时的兜底跳转 + { path: '/no-permission', name: 'no-permission', component: () => import('@/views/error/NoPermission.vue'), meta: { title: '无访问权限' } }, + { path: '/no-service', name: 'no-service', component: () => import('@/views/error/NoService.vue'), meta: { title: '服务不可用' } }, + { path: '/404', name: '404', component: () => import('@/views/error/404.vue'), meta: { title: '页面不存在' } }, + { path: '/:pathMatch(.*)*', redirect: { name: '404' } }, ], }) router.beforeEach(async (to, from) => { if (to.path !== from.path) NProgress.start() - const notAuthRouteNameList = ['login', 'forgot-password', 'not-found', 'details-demo'] + const notAuthRouteNameList = ['login', 'forgot-password', '404', 'details-demo'] const { auth, user } = useStore() if (!notAuthRouteNameList.includes(to.name ? to.name.toString() : '')) { diff --git a/ui/src/router/chat/index.ts b/ui/src/router/chat/index.ts index a475903f7c4..3c924591390 100644 --- a/ui/src/router/chat/index.ts +++ b/ui/src/router/chat/index.ts @@ -28,11 +28,6 @@ function getLoginRoute(scope: string, to: RouteLocationNormalized) { return scope === PORTAL_AUTH_SCOPE ? { name: 'portal-login', query } : { name: 'chat-login', params: { accessToken: scope }, query } } -/** 渲染 404 页面并保留原地址,刷新时可重新尝试。 */ -function getNotFoundRoute(to: RouteLocationNormalized) { - return { name: 'chat-not-found', params: { pathMatch: to.path.substring(1).split('/') }, query: to.query, hash: to.hash } -} - chatRouter.beforeEach(async (to) => { if (isUnknownPortalPath(to)) return { name: 'portal-home', replace: true } @@ -52,12 +47,13 @@ chatRouter.beforeEach(async (to) => { : { name: 'chat-home', params: { accessToken: scope }, query, replace: true } } - // accessToken 无效、应用已停用或门户未开放时,认证前置配置与匿名认证会失败,统一进入 404 页面 + // accessToken 无效、应用已停用或门户未开放时,认证前置配置与匿名认证会失败,在原地址展示服务不可用页面 let authProfile: AuthProfile try { authProfile = await auth.fetchAuthProfile(scope) } catch { - return getNotFoundRoute(to) + auth.unavailablePath = to.fullPath + return true } // 登录页始终放行:开启认证时必须登录,未开启认证时匿名用户也可主动登录 @@ -76,7 +72,8 @@ chatRouter.beforeEach(async (to) => { try { await auth.postAnonymousAuth(scope) } catch { - return getNotFoundRoute(to) + auth.unavailablePath = to.fullPath + return true } auth.activate(scope, authProfile) return true diff --git a/ui/src/router/chat/routes.ts b/ui/src/router/chat/routes.ts index cb9c94a5208..9035aee0607 100644 --- a/ui/src/router/chat/routes.ts +++ b/ui/src/router/chat/routes.ts @@ -41,7 +41,7 @@ const applicationRoutes: RouteRecordRaw[] = [ component: () => import('@/views/chat/login/index.vue'), meta: { title: '登录' }, }, - { + { path: '/:accessToken', redirect: (to) => { return `/${to.params.accessToken}/` @@ -66,9 +66,10 @@ export const chatRoutes: RouteRecordRaw[] = [ ...portalRoutes, ...applicationRoutes, { - path: '/:pathMatch(.*)*', - name: 'chat-not-found', - component: () => import('@/views/chat/error/index.vue'), + path: '/404', + name: '404', + component: () => import('@/views/chat/error/404.vue'), meta: { title: '页面不存在' }, }, + { path: '/:pathMatch(.*)*', redirect: { name: '404' } }, ] diff --git a/ui/src/stores/chat/auth.ts b/ui/src/stores/chat/auth.ts index 1b404c743a9..1c79915b3eb 100644 --- a/ui/src/stores/chat/auth.ts +++ b/ui/src/stores/chat/auth.ts @@ -57,11 +57,13 @@ interface ChatAuthState { token: string /** 本次页面中已失效(401)的 token;仍保留在本地存储中,供重新认证时携带。 */ expiredToken: string + /** 初始化失败的对话地址;只在该地址展示服务不可用,避免影响其他应用或分享页。 */ + unavailablePath: string authProfile: AuthProfile | null } export const useChatAuthStore = defineStore('chat-auth', { - state: (): ChatAuthState => ({ scope: '', token: '', expiredToken: '', authProfile: null }), + state: (): ChatAuthState => ({ scope: '', token: '', expiredToken: '', unavailablePath: '', authProfile: null }), getters: { isAuthenticated: (state) => Boolean(state.token), @@ -100,6 +102,7 @@ export const useChatAuthStore = defineStore('chat-auth', { /** 切换当前场景,由守卫在放行前调用。 */ activate(scope: string, authProfile: AuthProfile) { if (scope !== this.scope) useChatUserStore().clearCurrentUser() + this.unavailablePath = '' this.scope = scope this.authProfile = authProfile this.token = this.getStoredToken(scope) diff --git a/ui/src/views/VIEW_README.md b/ui/src/views/VIEW_README.md index 69eab787139..6874fb847f1 100644 --- a/ui/src/views/VIEW_README.md +++ b/ui/src/views/VIEW_README.md @@ -63,7 +63,8 @@ | `login/`、`login/forgot-password/` | Admin 登录与找回密码 | | `chat/`、`portal/` | 单应用与门户对话 | | `chat/share/` | 公开分享链接的只读问答展示与失败重试 | -| `chat/login/`、`chat/error/`、`error/` | Chat 登录、Chat/Admin 错误页 | +| `chat/login/`、`chat/error/` | Chat 登录、独立 404 与服务不可用展示 | +| `error/404.vue`、`error/NoPermission.vue`、`error/NoService.vue` | Admin 页面不存在、无访问权限与服务不可用展示 | | `details-demo/` | 临时执行详情预览 | ## 资源列表与详情 diff --git a/ui/src/views/chat/error/404.vue b/ui/src/views/chat/error/404.vue new file mode 100644 index 00000000000..1618039228c --- /dev/null +++ b/ui/src/views/chat/error/404.vue @@ -0,0 +1,12 @@ + + + diff --git a/ui/src/views/chat/error/NoService.vue b/ui/src/views/chat/error/NoService.vue new file mode 100644 index 00000000000..8e380143bd3 --- /dev/null +++ b/ui/src/views/chat/error/NoService.vue @@ -0,0 +1,8 @@ + diff --git a/ui/src/views/chat/error/index.vue b/ui/src/views/chat/error/index.vue deleted file mode 100644 index bd94c07c1cf..00000000000 --- a/ui/src/views/chat/error/index.vue +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/ui/src/views/chat/index.vue b/ui/src/views/chat/index.vue index 76c99ce25c3..8a3064a8477 100644 --- a/ui/src/views/chat/index.vue +++ b/ui/src/views/chat/index.vue @@ -1,5 +1,7 @@