import { AppCodeListHelperBase, DataServiceBase, IAppCodeListHelper, ICodeList, ICodeListItem, ICodeListResult, IContext, IHttpResponse, IParam, } from '@/core'; import { deepCopy } from '@/core/utils'; export class AppCodeListHelper extends AppCodeListHelperBase implements IAppCodeListHelper { /** * 单例服务 * * @protected * @static * @type {IAppCodeListHelper} * @memberof AppCodeListHelper */ private static service: IAppCodeListHelper; /** * 获取实例 * * @static * @return {*} {IAppCodeListHelper} * @memberof AppCodeListHelper */ static getInstance(): IAppCodeListHelper { if (!this.service) { this.service = new AppCodeListHelper(); } return this.service; } /** * 动态代码表缓存(加载中) * * @type {Map} * @memberof AppCodeListHelper */ private static codeListCache: Map = new Map(); /** * 动态代码表缓存(已完成) * * @type {Map} * @memberof AppCodeListHelper */ private static codeListCached: Map< string, { result: ICodeListResult; expirationTime?: number } > = new Map(); /** * 获取代码表数据(包含动态/静态/预定义统一入口) * @param tag 代码表标识 * @param context 应用上下文 * @param viewParams 视图参数 */ getCodeListItems( tag: string, context?: IContext, viewParams?: IParam ): Promise { // 根据tag 获取代码表标识 const codeList = App.getAppCodeListConfig()[tag]; if (!codeList) return Promise.resolve(this.handleCodeListData([], false)); // 根据代码表类型 if (Object.is(codeList.codeListType, 'STATIC')) { return this.getItemsWithStatic(codeList, context, viewParams); } else { if (codeList.predefinedType) { return this.getItemsWithPredefined(codeList, context, viewParams); } else { return this.getItemsWithDynamic(codeList, context, viewParams); } } } /** * 获取静态代码表数据 * @param tag 代码表标识 * @param context 应用上下文 * @param viewParams 视图参数 */ getItemsWithStatic( codeList: ICodeList, context?: IContext, viewParams?: IParam ): Promise { const { items } = codeList; if (!codeList || !items) { return Promise.resolve(this.handleCodeListData([], false)); } return Promise.resolve(this.handleCodeListData(items)); } /** * 获取动态代码表数据 * @param tag 代码表标识 * @param context 应用上下文 * @param viewParams 视图参数 */ getItemsWithDynamic( codeList: ICodeList, context?: IContext, viewParams?: IParam ): Promise { return new Promise((resolve: any) => { const { isEnableCache, cacheTimeout } = codeList; // 启用缓存 if (isEnableCache) { const tag: string = codeList.codeName; // 加载完成执行回调 const callback = (tag: string, promise: Promise) => { promise.then((result: ICodeListResult) => { const { data } = result; if (data.length > 0) { AppCodeListHelper.codeListCached.set(tag, { result, expirationTime: cacheTimeout === -1 ? -1 : new Date().getTime() + cacheTimeout, }); AppCodeListHelper.codeListCache.delete(tag); resolve(deepCopy(result)); } else { resolve(this.handleCodeListData([], false)); } }); }; // 先从已缓存完成的代码表Map中获取 const activeCodeList = AppCodeListHelper.codeListCached.get(tag); if (activeCodeList?.expirationTime) { if ( activeCodeList.expirationTime === -1 || new Date().getTime() <= activeCodeList.expirationTime ) { resolve(activeCodeList.result); } } // 加载中,UI又需要数据,解决连续加载同一代码表问题 if (AppCodeListHelper.codeListCache.get(tag)) { callback(tag, AppCodeListHelper.codeListCache.get(tag)); } else { const result = this.getCodeListData(codeList, context, viewParams); AppCodeListHelper.codeListCache.set(tag, result); callback(tag, result); } } else { resolve(this.getCodeListData(codeList, context, viewParams)); } }); } /** * 获取预定义代码表数据 * @param tag 代码表标识 * @param context 应用上下文 * @param viewParams 视图参数 */ getItemsWithPredefined( codeList: ICodeList, context?: IContext, viewParams?: IParam ): Promise { return new Promise((resolve: any) => { const { codeName } = codeList; const callback = (tag: string, promise: Promise) => { promise .then((res: IHttpResponse) => { if (res.data && res.data.items) { // 兼容两者,有的从items里取,有的直接拿 const result: ICodeListResult = this.handleCodeListData(res.data.items); if (result.data.length > 0) { AppCodeListHelper.codeListCached.set(`${tag}`, { result: result, }); return resolve(deepCopy(result)); } } return resolve([]); }) .catch((error: any) => { console.error(`获取预定义代码表数据[${JSON.stringify(error)}]`); return resolve([]); }); }; // 加载中,UI又需要数据,解决连续加载同一代码表问题 if (AppCodeListHelper.codeListCache.get(`${codeName}`)) { callback( codeName, AppCodeListHelper.codeListCache.get(`${codeName}`) ); } else { const dataServiceBase = new DataServiceBase(context); if (!dataServiceBase) { return resolve(this.handleCodeListData([], false)); } const result: Promise = dataServiceBase.getPredefinedCodelist(codeName); AppCodeListHelper.codeListCache.set(`${codeName}`, result); callback(codeName, result); } }); } /** * 获取代码表数据(动态代码表) * * @param {IParam} codeList 代码表对象 * @param {IContext} [context={}] 应用上下文 * @param {IParam} [viewParams={}] 视图参数 * @memberof AppCodeListHelper */ private async getCodeListData( codeList: IParam, context?: IContext, viewParams?: IParam ): Promise { try { const { appDataEntity, appDEDataSet, textPSAppDEField, valuePSAppDEField, pValuePSAppDEField, disablePSAppDEField } = codeList; if ( !appDataEntity || !appDEDataSet || !textPSAppDEField || !valuePSAppDEField ) { console.error('动态代码表获取数据异常[查询参数不足]'); } const dataService = await App.getDataService(appDataEntity, context); const response: IHttpResponse = await dataService[appDEDataSet]( context, viewParams, false ); const { success, data } = response; if (success) { const items: IParam[] = []; if (data && data.length > 0) { data.forEach((element: IParam) => { items.push({ value: element[valuePSAppDEField], text: element[textPSAppDEField], pvalue: element[pValuePSAppDEField], disabled: element[disablePSAppDEField], }); }); } return this.handleCodeListData(items); } else { console.error('动态代码表获取数据异常[网络请求异常]'); return this.handleCodeListData([], false); } } catch (error: any) { console.error(`动态代码表获取数据异常[${JSON.stringify(error)}]`); return this.handleCodeListData([], false); } } /** * 处理返回结果 * * @private * @param {IParam[]} items * @param {boolean} [ok=true] * @return {*} {ICodeListResult} * @memberof AppCodeListHelper */ private handleCodeListData(items: IParam[], ok = true): ICodeListResult { const data: ICodeListItem[] = []; items.forEach((item: IParam) => { data.push({ color: item.color, text: item.text, value: item.value, pvalue: item.pvalue, codeName: item.codeName, textResTag: item.textResTag, icon: item.icon, textClass: item.textClass, data: item.data, disabled: item.disabled, userData: item.userData, }); }); return { ok: ok, data: data }; } }