From 93f6e87220235f185d394059e818ea04e4db5955 Mon Sep 17 00:00:00 2001 From: iven Date: Tue, 5 May 2026 13:01:14 +0800 Subject: [PATCH] =?UTF-8?q?fix(web+config):=20E2E=20=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E5=8F=91=E7=8E=B0=E7=9A=84=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 排班状态过滤 'active' → 'enabled'(与后端 validation.rs 一致) - 全局 403 拦截器不再弹出"权限不足" toast(AuthButton 已隐藏入口) - 角色未关联菜单时回退显示全部(避免种子数据阶段菜单空白) --- apps/web/src/api/client.ts | 12 +++++++++++- apps/web/src/pages/health/AppointmentList.tsx | 2 +- apps/web/src/test/fixtures/healthFixtures.ts | 2 +- apps/web/src/test/mocks/healthHandlers.ts | 2 +- crates/erp-config/src/service/menu_service.rs | 7 +++++-- 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/apps/web/src/api/client.ts b/apps/web/src/api/client.ts index b4f1260..077310b 100644 --- a/apps/web/src/api/client.ts +++ b/apps/web/src/api/client.ts @@ -160,13 +160,23 @@ function showGlobalError(msg: string) { } // 全局错误拦截 — 在响应拦截器之后、组件 catch 之前执行 +// 组件可通过 axios config 中设置 skipGlobalError: true 来抑制全局提示 +declare module 'axios' { + interface InternalAxiosRequestConfig { + skipGlobalError?: boolean; + } +} + client.interceptors.response.use( (response) => response, (error) => { + if (error.config?.skipGlobalError) { + return Promise.reject(error); + } if (!error.response) { showGlobalError('网络连接异常,请检查网络'); } else if (error.response.status === 403) { - showGlobalError('权限不足,无法执行此操作'); + // 403 通常是权限不足,不全局提示 — 组件层通过 AuthButton 已隐藏操作入口 } else if (error.response.status === 404) { // 404 通常由组件自行处理(如跳转),不全局提示 } else if (error.response.status >= 500) { diff --git a/apps/web/src/pages/health/AppointmentList.tsx b/apps/web/src/pages/health/AppointmentList.tsx index fcee3c8..54c1434 100644 --- a/apps/web/src/pages/health/AppointmentList.tsx +++ b/apps/web/src/pages/health/AppointmentList.tsx @@ -229,7 +229,7 @@ export default function AppointmentList() { setScheduleHint(`该医生在 ${selectedDate} 暂无排班,请确认是否需要先创建排班`); } else { const slots = schedules - .filter((s) => s.status === 'active' && s.current_appointments < s.max_appointments) + .filter((s) => s.status === 'enabled' && s.current_appointments < s.max_appointments) .map((s) => `${s.start_time}-${s.end_time}(${s.current_appointments}/${s.max_appointments})`) .join('、'); setScheduleHint(slots ? `可约时段:${slots}` : `该医生在 ${selectedDate} 排班已满或已停用`); diff --git a/apps/web/src/test/fixtures/healthFixtures.ts b/apps/web/src/test/fixtures/healthFixtures.ts index 7950201..92db118 100644 --- a/apps/web/src/test/fixtures/healthFixtures.ts +++ b/apps/web/src/test/fixtures/healthFixtures.ts @@ -223,7 +223,7 @@ export function createScheduleFixture(overrides: Record = {}) { end_time: '12:00', max_appointments: 10, current_appointments: 3, - status: 'active', + status: 'enabled', created_at: '2026-04-01T10:00:00Z', updated_at: '2026-04-01T10:00:00Z', version: 1, diff --git a/apps/web/src/test/mocks/healthHandlers.ts b/apps/web/src/test/mocks/healthHandlers.ts index b7475a5..71f3425 100644 --- a/apps/web/src/test/mocks/healthHandlers.ts +++ b/apps/web/src/test/mocks/healthHandlers.ts @@ -359,7 +359,7 @@ const mockSchedules = Array.from({ length: 8 }, (_, i) => ({ end_time: i % 2 === 0 ? '12:00' : '17:00', max_appointments: 10, current_appointments: i % 3, - status: 'active', + status: 'enabled', created_at: '2026-04-01T10:00:00Z', updated_at: '2026-04-01T10:00:00Z', version: 1, diff --git a/crates/erp-config/src/service/menu_service.rs b/crates/erp-config/src/service/menu_service.rs index 205ca42..dffe534 100644 --- a/crates/erp-config/src/service/menu_service.rs +++ b/crates/erp-config/src/service/menu_service.rs @@ -47,9 +47,12 @@ impl MenuService { let ids: Vec = mr_rows.iter().map(|mr| mr.menu_id).collect(); if ids.is_empty() { - return Ok(vec![]); + // 角色未关联菜单时回退到显示全部菜单, + // 避免种子数据阶段 menu_roles 为空导致所有有角色用户看不到菜单 + None + } else { + Some(ids) } - Some(ids) } else { None };