RIS自动同步功能在后台静默运行,定期从RIS系统同步数据到本地,确保worklist显示最新信息。
自动同步机制
配置管理
状态反馈
src/
├── states/
│ └── ris/
│ └── risSyncSlice.ts # RIS配置和状态管理
├── hooks/
│ └── useRisAutoSync.ts # 自动同步Hook
├── services/
│ └── risSync/
│ └── RisSyncService.ts # 同步服务类
├── pages/
│ ├── index/
│ │ └── AppInitializer.tsx # [修改] 启动时获取配置
│ └── patient/
│ └── worklist.tsx # [修改] 集成自动同步
└── states/
└── store.ts # [修改] 注册reducer
sequenceDiagram
participant App as 应用启动
participant Init as AppInitializer
participant API
participant Redux
App->>Init: 初始化应用
Init->>API: getRisConfig()
API-->>Init: RIS配置
Init->>Redux: 保存配置到全局state
Redux-->>Init: 配置保存成功
sequenceDiagram
participant User
participant Worklist
participant Hook as useRisAutoSync
participant Redux
participant Service as RisSyncService
participant API
participant Message
User->>Worklist: 进入worklist页面
Worklist->>Hook: 组件挂载,启动Hook
Hook->>Redux: 读取RIS配置
Redux-->>Hook: 返回配置
alt 自动同步启用
Hook->>Service: 启动定时器
loop 每N分钟
Service->>API: syncRis()
API-->>Service: 同步结果
Service->>API: fetchTaskList()
API-->>Service: 任务列表
Service->>Redux: 更新worklist数据
Service->>Message: 显示同步结果
Note over Message: 3秒后自动消失
end
end
User->>Worklist: 离开worklist页面
Worklist->>Hook: 组件卸载
Hook->>Service: 清理定时器
// RIS同步状态(精简版)
interface RisSyncState {
// 配置信息(程序启动时获取)
config: {
mwl_enable: boolean;
mwl_refresh_enable: boolean;
mwl_refresh_interval: number;
} | null;
// 运行时状态(不需要UI显示)
isRunning: boolean; // 同步是否正在运行
lastSyncTime: string | null; // 最后同步时间
}
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
import { getRisConfig, RisConfigData } from '@/API/patient/risActions';
interface RisSyncState {
config: RisConfigData | null;
isRunning: boolean;
lastSyncTime: string | null;
}
const initialState: RisSyncState = {
config: null,
isRunning: false,
lastSyncTime: null,
};
// 获取配置的thunk(程序启动时调用)
export const fetchRisConfigThunk = createAsyncThunk(
'risSync/fetchConfig',
async () => {
const response = await getRisConfig();
return response.data;
}
);
const risSyncSlice = createSlice({
name: 'risSync',
initialState,
reducers: {
setRunning: (state, action: PayloadAction<boolean>) => {
state.isRunning = action.payload;
},
setLastSyncTime: (state, action: PayloadAction<string>) => {
state.lastSyncTime = action.payload;
},
},
extraReducers: (builder) => {
builder.addCase(fetchRisConfigThunk.fulfilled, (state, action) => {
state.config = action.payload;
console.log('[RIS] 配置加载成功:', action.payload);
});
},
});
export const { setRunning, setLastSyncTime } = risSyncSlice.actions;
export default risSyncSlice.reducer;
// 在现有的 AppInitializer 中添加
import { fetchRisConfigThunk } from '@/states/ris/risSyncSlice';
// 在 useEffect 中添加
useEffect(() => {
const fetchData = async () => {
// ... 现有的初始化代码
// 获取RIS配置
try {
await dispatch(fetchRisConfigThunk());
console.log('[AppInitializer] RIS配置加载完成');
} catch (error) {
console.error('[AppInitializer] RIS配置加载失败:', error);
// 配置加载失败不影响应用启动
}
};
fetchData();
}, [dispatch]);
import { useEffect, useRef } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { message } from 'antd';
import { RootState, AppDispatch } from '@/states/store';
import { setRunning, setLastSyncTime } from '@/states/ris/risSyncSlice';
import { RisSyncService } from '@/services/risSync/RisSyncService';
import { fetchWorkThunk } from '@/states/patient/worklist/slices/workSlice';
export const useRisAutoSync = () => {
const dispatch = useDispatch<AppDispatch>();
const config = useSelector((state: RootState) => state.risSync.config);
const filters = useSelector((state: RootState) => state.workFilters);
const page = useSelector((state: RootState) => state.workPagination.page);
const pageSize = useSelector((state: RootState) => state.workPagination.pageSize);
const serviceRef = useRef<RisSyncService | null>(null);
useEffect(() => {
// 检查是否应该启动同步
if (!config?.mwl_enable || !config?.mwl_refresh_enable) {
console.log('[useRisAutoSync] RIS自动同步未启用');
return;
}
console.log('[useRisAutoSync] 启动RIS自动同步,间隔:', config.mwl_refresh_interval, '分钟');
// 创建服务实例
serviceRef.current = new RisSyncService({
interval: config.mwl_refresh_interval * 60 * 1000, // 转换为毫秒
onSyncComplete: (success, count) => {
if (success) {
message.success(`RIS同步成功,同步了 ${count} 条数据`, 3);
dispatch(setLastSyncTime(new Date().toISOString()));
// 刷新worklist
dispatch(fetchWorkThunk({ page, pageSize, filters }));
} else {
// 错误只在控制台显示,不打扰用户
console.error('[useRisAutoSync] 同步失败');
}
},
});
// 启动同步
serviceRef.current.start();
dispatch(setRunning(true));
// 清理函数
return () => {
console.log('[useRisAutoSync] 停止RIS自动同步');
if (serviceRef.current) {
serviceRef.current.stop();
serviceRef.current = null;
}
dispatch(setRunning(false));
};
}, [config, dispatch, page, pageSize, filters]);
};
import { syncRis, RisTimeUtils } from '@/API/patient/risActions';
interface RisSyncServiceOptions {
interval: number;
onSyncComplete?: (success: boolean, count: number) => void;
}
export class RisSyncService {
private timer: NodeJS.Timeout | null = null;
private isRunning = false;
private options: RisSyncServiceOptions;
constructor(options: RisSyncServiceOptions) {
this.options = options;
}
async start() {
if (this.isRunning) {
console.log('[RisSyncService] 服务已在运行');
return;
}
this.isRunning = true;
// 立即执行一次同步
await this.performSync();
// 设置定时器
this.timer = setInterval(() => {
this.performSync();
}, this.options.interval);
console.log('[RisSyncService] 自动同步已启动');
}
stop() {
if (this.timer) {
clearInterval(this.timer);
this.timer = null;
}
this.isRunning = false;
console.log('[RisSyncService] 自动同步已停止');
}
private async performSync() {
try {
console.log('[RisSyncService] 开始同步RIS数据...');
// 获取今天的时间范围
const timeRange = RisTimeUtils.getTodayRange();
// 执行同步
const result = await syncRis({
start_time: timeRange.start,
end_time: timeRange.end,
});
console.log(`[RisSyncService] 同步成功,共同步 ${result.data.count} 条数据`);
// 回调通知
if (this.options.onSyncComplete) {
this.options.onSyncComplete(true, result.data.count);
}
} catch (error) {
console.error('[RisSyncService] 同步失败:', error);
// 回调通知
if (this.options.onSyncComplete) {
this.options.onSyncComplete(false, 0);
}
}
}
}
// 在 import 部分添加
import { useRisAutoSync } from '@/hooks/useRisAutoSync';
// 在组件内部添加(其他代码保持不变)
const WorklistPage: React.FC = () => {
// ... 现有的代码
// 启用RIS自动同步
useRisAutoSync();
// ... 现有的代码
};
// 添加 import
import risSyncReducer from './ris/risSyncSlice';
// 在 reducer 对象中添加
const store = configureStore({
reducer: {
// ... 现有的 reducers
risSync: risSyncReducer,
},
// ... 其他配置
});
1. 启动应用
2. 打开浏览器控制台
3. 查看是否有 "[RIS] 配置加载成功" 日志
1. 进入worklist页面
2. 查看控制台是否有 "[useRisAutoSync] 启动RIS自动同步" 日志
3. 等待配置的时间间隔
4. 观察是否出现同步成功的消息弹框
5. 验证列表是否刷新
1. 在worklist页面等待同步启动
2. 切换到其他页面
3. 查看控制台是否有 "[useRisAutoSync] 停止RIS自动同步" 日志
4. 返回worklist页面
5. 验证同步重新启动
文档版本:2.0.0 更新日期:2025-01-31