本文档详细说明了系统中急诊模式的完整逻辑,包括 guest token 的获取、存储、传递机制以及急诊操作的完整流程。
src/API/softwareInfo.ts
- API 调用src/states/productSlice.ts
- Redux 状态管理在系统启动时,通过 initializeProductState
thunk 自动获取软件信息:
// API 调用
GET / pub / software_info;
// 返回数据结构
interface SoftwareInfo {
guest: string; // 用于急诊访问数据的 token
FPD: string;
GEN: string;
language: string[];
product: string;
sn: string;
server: Record<string, any>;
}
// productSlice.ts
export const initializeProductState = createAsyncThunk(
'product/initializeProductState',
async () => {
const softwareInfo = await fetchSoftwareInfo();
return {
productName: softwareInfo.product as 'DROS' | 'VETDROS',
language: softwareInfo.language[0],
source: 'Browser' as const,
guest: softwareInfo.guest, // 存储 guest token
};
}
);
guest
字段本质上就是急诊模式下使用的 tokenproductSlice
中,路径:state.product.guest
src/API/interceptor.ts
- Axios 拦截器在每个 API 请求发出前,axios 请求拦截器会自动根据当前系统模式选择合适的 token:
axiosInstance.interceptors.request.use((config) => {
const state = store.getState();
// 根据系统模式选择 token
const token =
state.systemMode.mode === SystemMode.Emergency
? state.product.guest // 急诊模式使用 guest token
: state.userInfo.token; // 正常模式使用登录 token
// 设置请求头
config.headers.Authorization = `Bearer ${token}`;
config.headers.Language = language;
config.headers.Product = productName;
config.headers.Source = source;
return config;
});
系统模式 | Token 来源 | 说明 |
---|---|---|
Emergency |
state.product.guest |
急诊模式,使用预先获取的 guest token |
Normal |
state.userInfo.token |
正常模式,使用用户登录后的 token |
Unknown |
state.userInfo.token |
未知状态,默认使用登录 token |
src/domain/patient/handleEmergencyOperation.ts
- 急诊操作主流程src/domain/patient/registrationGenerator.ts
- 生成注册信息src/API/patient/workActions.ts
- 注册 APIsrc/states/systemModeSlice.ts
- 系统模式管理开始
↓
1. 设置系统模式为 Emergency
↓
2. 生成急诊注册信息
↓
3. 调用注册 API (自动使用 guest token)
↓
4. 保存注册结果到缓存
↓
5. 切换业务流程到检查页面
↓
结束
const handleEmergencyOperation = async () => {
const dispatch = store.dispatch;
try {
// 步骤 1: 设置系统模式为急诊
dispatch(setSystemMode(SystemMode.Emergency));
// 步骤 2: 生成注册信息
const registrationInfo = generateRegistrationInfo();
// 返回的数据包含 study_type: 'Emergency'
// 步骤 3: 注册急诊工作
// 此时 API 请求会自动使用 guest token(通过拦截器)
const registrationResult = await registerWork(registrationInfo);
// 步骤 4: 保存结果到缓存
const task = mapToTask(registrationResult.data);
dispatch(addWork(task));
// 步骤 5: 切换到检查流程
dispatch(setBusinessFlow('exam'));
} catch (error) {
console.error('Error in handleEmergencyOperation:', error);
throw error;
}
};
// registrationGenerator.ts
function generateRegistrationInfo() {
return {
study_type: 'Emergency', // 标记为急诊类型
accession_number: maxNumber,
patient_id: `EMERGENCY_${timestamp}`,
patient_name: `急诊患者_${number}`,
// ... 其他字段
};
}
src/states/systemModeSlice.ts
export const SystemMode = {
Unknown: 'Unknown', // 未知状态
Emergency: 'Emergency', // 急诊模式
Normal: 'Normal', // 正常模式
};
interface SystemModeState {
mode: SystemMode;
}
const initialState: SystemModeState = {
mode: SystemMode.Unknown,
};
从状态 | 到状态 | 触发条件 |
---|---|---|
Unknown |
Emergency |
执行急诊操作 |
Unknown |
Normal |
用户正常登录 |
Emergency |
Normal |
急诊流程结束(待实现) |
Normal |
Emergency |
切换到急诊模式 |
// 设置为急诊模式
dispatch(setSystemMode(SystemMode.Emergency));
// 设置为正常模式
dispatch(setSystemMode(SystemMode.Normal));
// 获取当前模式
const currentMode = state.systemMode.mode;
initializeProductState
thunk 在应用启动时自动获取systemMode.mode
选择 tokenGET /pub/software_info
响应示例:
{
"code": "0x000000",
"data": {
"guest": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"product": "DROS",
"language": ["en", "zh"],
"FPD": "Simulator",
"GEN": "Simulator",
"sn": "2edbc382-044adc78-95bed11b-51c9328a"
}
}
POST /dr/api/v1/auth/study
Authorization: Bearer {guest_token}
请求体:
{
"study_type": "Emergency",
"accession_number": "ACC0012345",
"patient_id": "EMERGENCY_20250625143339",
"patient_name": "急诊患者_001"
// ... 其他患者信息
}
文件路径 | 作用 | 关键功能 |
---|---|---|
src/API/softwareInfo.ts |
获取软件信息 | 调用 /pub/software_info API,获取 guest token |
src/states/productSlice.ts |
产品状态管理 | 存储 guest token 到 Redux |
src/states/systemModeSlice.ts |
系统模式管理 | 管理 Emergency/Normal 模式切换 |
src/API/interceptor.ts |
API 拦截器 | 根据系统模式自动选择 token 并添加到请求头 |
src/domain/patient/handleEmergencyOperation.ts |
急诊操作主流程 | 执行完整的急诊注册流程 |
src/domain/patient/registrationGenerator.ts |
注册信息生成 | 生成急诊患者的注册信息 |
src/API/patient/workActions.ts |
工作注册 API | 调用后端注册接口 |
import handleEmergencyOperation from '@/domain/patient/handleEmergencyOperation';
// 在某个组件或页面中触发急诊
const handleEmergencyClick = async () => {
try {
await handleEmergencyOperation();
// 成功后会自动跳转到检查页面
} catch (error) {
console.error('急诊操作失败:', error);
message.error('急诊操作失败,请重试');
}
};
import { useSelector } from 'react-redux';
import { SystemMode } from '@/states/systemModeSlice';
const MyComponent = () => {
const currentMode = useSelector(state => state.systemMode.mode);
const isEmergencyMode = currentMode === SystemMode.Emergency;
return (
<div>
{isEmergencyMode ? '急诊模式' : '正常模式'}
</div>
);
};
import { useDispatch } from 'react-redux';
import { setSystemMode, SystemMode } from '@/states/systemModeSlice';
const MyComponent = () => {
const dispatch = useDispatch();
const switchToNormal = () => {
dispatch(setSystemMode(SystemMode.Normal));
};
const switchToEmergency = () => {
dispatch(setSystemMode(SystemMode.Emergency));
};
return (
<>
<button onClick={switchToNormal}>切换到正常模式</button>
<button onClick={switchToEmergency}>切换到急诊模式</button>
</>
);
};
/pub/software_info
获取新的 guest token// 在 handleEmergencyOperation 的 finally 中
finally {
dispatch(setSystemMode(SystemMode.Normal));
}
实现 guest token 的自动刷新:
// 在拦截器中检查 token 是否即将过期
if (isTokenExpiringSoon(state.product.guest)) {
await refreshGuestToken();
}
添加更详细的急诊流程状态:
enum EmergencyFlowStatus {
NotStarted = 'NotStarted',
Generating = 'Generating',
Registering = 'Registering',
Completed = 'Completed',
Failed = 'Failed',
}
实现急诊流程完成后自动退出急诊模式:
const handleEmergencyOperation = async () => {
try {
dispatch(setSystemMode(SystemMode.Emergency));
// ... 执行急诊流程
dispatch(setBusinessFlow('exam'));
} finally {
// 检查完成后自动退出急诊模式
dispatch(setSystemMode(SystemMode.Normal));
}
};
记录所有急诊操作以便审计:
const logEmergencyOperation = (operation: string, data: any) => {
console.log('[EMERGENCY]', {
timestamp: new Date().toISOString(),
operation,
data,
mode: store.getState().systemMode.mode,
});
};
急诊流程的设计充分体现了以下特点:
这种设计使得急诊功能既能快速响应紧急情况,又保持了代码的可维护性和可扩展性。