当手术计费弹窗中点击"签发"耗材时,因耗材的locationId(发放库房)为空导致后端异常。 在DoctorStationAdviceAppServiceImpl.handDevice方法中,当locationId为null时,使用登录用户的科室ID作为默认值, 与NurseBillingAppService中的处理方式保持一致。
197 lines
5.3 KiB
JavaScript
Executable File
197 lines
5.3 KiB
JavaScript
Executable File
import globalRequestController from './globalRequestController.js';
|
||
|
||
/**
|
||
* API请求管理器 - 用于合并相同参数的请求,避免重复请求
|
||
* 在医院信息系统中特别重要,因为医疗数据的频繁请求可能影响系统性能
|
||
*/
|
||
|
||
class ApiRequestManager {
|
||
constructor() {
|
||
// 存储正在进行的请求
|
||
this.pendingRequests = new Map();
|
||
// 缓存成功的响应结果
|
||
this.responseCache = new Map();
|
||
// 缓存过期时间(毫秒)
|
||
this.cacheTimeout = 10000; // 10秒,医疗系统中数据更新可能较频繁
|
||
|
||
// 添加调试模式
|
||
this.debugMode = true;
|
||
}
|
||
|
||
/**
|
||
* 生成请求的唯一键值
|
||
* @param {string} url - 请求URL
|
||
* @param {object} params - 请求参数
|
||
* @returns {string} 唯一键值
|
||
*/
|
||
generateRequestKey(url, params = {}) {
|
||
// 对参数进行排序以确保相同参数产生相同键值
|
||
const sortedParams = Object.keys(params)
|
||
.sort()
|
||
.reduce((acc, key) => {
|
||
acc[key] = params[key];
|
||
return acc;
|
||
}, {});
|
||
|
||
const key = `${url}?${JSON.stringify(sortedParams)}`;
|
||
|
||
if (this.debugMode) {
|
||
console.log(`Generated request key: ${key}`);
|
||
}
|
||
|
||
return key;
|
||
}
|
||
|
||
/**
|
||
* 检查是否存在相同的进行中请求
|
||
* @param {string} requestKey - 请求键值
|
||
* @returns {Promise|undefined} 如果存在则返回Promise,否则返回undefined
|
||
*/
|
||
getPendingRequest(requestKey) {
|
||
return this.pendingRequests.get(requestKey);
|
||
}
|
||
|
||
/**
|
||
* 添加进行中的请求
|
||
* @param {string} requestKey - 请求键值
|
||
* @param {Promise} promise - 请求Promise
|
||
*/
|
||
addPendingRequest(requestKey, promise) {
|
||
this.pendingRequests.set(requestKey, promise);
|
||
}
|
||
|
||
/**
|
||
* 移除进行中的请求
|
||
* @param {string} requestKey - 请求键值
|
||
*/
|
||
removePendingRequest(requestKey) {
|
||
this.pendingRequests.delete(requestKey);
|
||
}
|
||
|
||
/**
|
||
* 检查是否存在缓存的响应
|
||
* @param {string} requestKey - 请求键值
|
||
* @returns {object|undefined} 如果存在则返回缓存的响应,否则返回undefined
|
||
*/
|
||
getCachedResponse(requestKey) {
|
||
const cached = this.responseCache.get(requestKey);
|
||
if (cached && Date.now() < cached.expiry) {
|
||
return cached.data;
|
||
}
|
||
// 如果缓存已过期,删除它
|
||
if (cached) {
|
||
this.responseCache.delete(requestKey);
|
||
}
|
||
return undefined;
|
||
}
|
||
|
||
/**
|
||
* 添加缓存的响应
|
||
* @param {string} requestKey - 请求键值
|
||
* @param {object} data - 响应数据
|
||
*/
|
||
addCachedResponse(requestKey, data) {
|
||
this.responseCache.set(requestKey, {
|
||
data,
|
||
expiry: Date.now() + this.cacheTimeout
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 清除指定的缓存
|
||
* @param {string} requestKey - 请求键值
|
||
*/
|
||
clearCache(requestKey) {
|
||
this.responseCache.delete(requestKey);
|
||
}
|
||
|
||
/**
|
||
* 清除所有缓存
|
||
*/
|
||
clearAllCache() {
|
||
this.responseCache.clear();
|
||
}
|
||
|
||
/**
|
||
* 清除所有进行中的请求
|
||
*/
|
||
clearAllPending() {
|
||
this.pendingRequests.clear();
|
||
}
|
||
|
||
/**
|
||
* 执行API请求(带去重和缓存)
|
||
* @param {Function} apiFunction - API函数
|
||
* @param {string} url - 请求URL
|
||
* @param {object} params - 请求参数
|
||
* @returns {Promise} API响应Promise
|
||
*/
|
||
async execute(apiFunction, url, params = {}) {
|
||
const requestKey = this.generateRequestKey(url, params);
|
||
|
||
if (this.debugMode) {
|
||
console.log(`Executing request with key: ${requestKey}`);
|
||
console.log(`Pending requests count: ${this.pendingRequests.size}`);
|
||
console.log(`Cached responses count: ${this.responseCache.size}`);
|
||
}
|
||
|
||
// 检查是否有缓存的响应
|
||
const cachedResponse = this.getCachedResponse(requestKey);
|
||
if (cachedResponse) {
|
||
if (this.debugMode) {
|
||
console.log(`Returning cached response for: ${requestKey}`);
|
||
}
|
||
return Promise.resolve(cachedResponse);
|
||
}
|
||
|
||
// 使用全局请求控制器来确保唯一性
|
||
const requestPromise = globalRequestController.execute(apiFunction, url, params)
|
||
.then(response => {
|
||
if (this.debugMode) {
|
||
console.log(`Request completed for: ${requestKey}`, response);
|
||
}
|
||
// 请求成功后,添加到缓存
|
||
this.addCachedResponse(requestKey, response);
|
||
return response;
|
||
})
|
||
.catch(error => {
|
||
if (this.debugMode) {
|
||
console.error(`Request failed for: ${requestKey}`, error);
|
||
}
|
||
throw error; // 不在这里处理错误,让调用方处理
|
||
});
|
||
|
||
return requestPromise;
|
||
}
|
||
|
||
/**
|
||
* 执行POST请求(带去重和缓存)
|
||
* @param {Function} apiFunction - API函数
|
||
* @param {string} url - 请求URL
|
||
* @param {object} data - 请求数据
|
||
* @returns {Promise} API响应Promise
|
||
*/
|
||
async executePost(apiFunction, url, data = {}) {
|
||
const requestKey = this.generateRequestKey(url, data);
|
||
|
||
// POST请求通常不缓存,但仍然可以去重
|
||
const pendingRequest = this.getPendingRequest(requestKey);
|
||
if (pendingRequest) {
|
||
return pendingRequest;
|
||
}
|
||
|
||
const requestPromise = apiFunction(data)
|
||
.finally(() => {
|
||
this.removePendingRequest(requestKey);
|
||
});
|
||
|
||
this.addPendingRequest(requestKey, requestPromise);
|
||
|
||
return requestPromise;
|
||
}
|
||
}
|
||
|
||
// 创建全局实例
|
||
const apiRequestManager = new ApiRequestManager();
|
||
|
||
export default apiRequestManager; |