import { ControlVOBase, deepCopy, LayoutUtil, verifyDynamicLogic, } from '@/core'; import { IParam, IPanelControllerParams, ICtrlActionResult, IEvent, IViewLogicInput, IHttpResponse, IPanelModel, } from '@/core/interface'; import { IPanelAbility } from '@/core/interface/widgets/ability'; import { IPanelController } from '@/core/interface/widgets/controller'; import { PanelActionType } from '@/core/interface/widgets/event'; import { IPanelStore } from '@/core/interface/widgets/store'; import PanelService from '@/core/modules/ctrl-service/panel-service'; import { DECtrlController } from './de-ctrl-controller'; /** * 面板控制器 * * @export * @class PanelController * @extends {(DECtrlController)} * @implements {IPanelController} * @template A */ export class PanelController extends DECtrlController implements IPanelController { /** * 面板模型 * * @protected * @type {IPanelModel} * @memberof PanelController */ protected declare readonly model: IPanelModel; /** * 部件服务 * * @type {PanelService} * @memberof PanelController */ declare ctrlService: PanelService; /** * Creates an instance of PanelController. * @param {IPanelControllerParams} params * @memberof PanelController */ public constructor( params: IPanelControllerParams ) { super(params); this.ctrlInit(params); } /** * 处理部件初始化 * * @protected * @param { IPanelControllerParams} params * @memberof PanelController */ protected processCtrlInit( params: IPanelControllerParams ) { super.processCtrlInit(params); this.isLoadDefault = params.isLoadDefault === true; this.viewType = params.viewType; this.data = params.data; Object.assign(this.store, { layoutData: {}, data: {}, layoutModelDetails: {}, }); } /** * 初始化后(对store做处理) * * @protected * @param {ICtrlControllerParams} params * @memberof PanelController */ protected afterCtrlInit( params: IPanelControllerParams ) { super.afterCtrlInit(params); this.computedUIData(); } /** * 默认加载 * * @type {boolean} * @memberof PanelController */ public isLoadDefault = false; /** * 视图类型 * * @private * @type {string} * @memberof PanelController */ private viewType?: string; /** * 传入面板数据 * * @private * @type {IParam} * @memberof PanelController */ private data?: IParam; /** * 初始化面板 * * @protected * @return {*} * @memberof PanelController */ protected async initLayout() { const { rootLayoutDetailNames, layoutItems } = this.model; if (rootLayoutDetailNames && layoutItems) { this.beforeAsyncAction('initLayout', {}, {}); for (let i = 0; i < rootLayoutDetailNames.length; i++) { const name = rootLayoutDetailNames[i]; const rootItem = layoutItems[name]; if (!rootItem) { return; } await this.initLayoutItem(rootItem); } this.afterAsyncAction('initLayout', { data: {}, success: true }); } } /** * 初始化面板项 * * @private * @param {*} layoutModelItem * @param {number} [index] * @memberof PanelController */ private async initLayoutItem(layoutModelItem: any, index?: number) { const { name } = layoutModelItem; const { layoutItems } = this.model; const { context, viewParams } = this.store; const layoutModelDetail = LayoutUtil.getLayoutItemInstance({ ...layoutModelItem, viewType: this.viewType, panel: this, }, context, viewParams); if (!(index || index === 0)) { await layoutModelDetail.load(context, viewParams); this.store.layoutModelDetails[name] = layoutModelDetail; this.store.layoutData[name] = layoutModelDetail.getData(); this.panelLogic(''); } else { layoutModelDetail.setIndex(index); await layoutModelDetail.load(context, viewParams); this.store.layoutModelDetails[`${name}_${index}`] = layoutModelDetail; this.store.layoutData[`${name}_${index}`] = layoutModelDetail.getData(); this.panelLogic('', index); } if (layoutModelDetail && layoutModelDetail.details) { if (layoutModelDetail.dataRegionType === 'MULTIDATA') { const multiData = layoutModelDetail.getData(); if (multiData && multiData.length > 0) { for (let i = 0; i < multiData.length; i++) { for (let j = 0; j < layoutModelDetail.details.length; j++) { const key = layoutModelDetail.details[j]; if (layoutItems && layoutItems[key]) { await this.initLayoutItem(layoutItems[key], i); } } } } } else { for (let i = 0; i < layoutModelDetail.details.length; i++) { const key = layoutModelDetail.details[i]; if (layoutItems && layoutItems[key]) { await this.initLayoutItem(layoutItems[key], index); } } } } } /** * 计算UI展示数据 * * @param {IParam} args * @memberof PanelController */ public async computedUIData(args?: IParam) { const { dataMode } = this.model; if (dataMode === 3) { // this.viewCtx.appGlobal[this.controlInstance.M.dataName] = this.data; } else if (dataMode === 4) { // this.viewCtx.routeViewGlobal[this.controlInstance.M.dataName] = this.data; } else if (dataMode === 5) { // this.viewCtx.viewGlobal[this.controlInstance.M.dataName] = this.data; } else { if (this.isLoadDefault) { await this.computeLoadState(args); } } await this.initLayout(); } /** * 计算数据加载模式 * * @param {IParam} [args] * @memberof PanelController */ public async computeLoadState(args?: IParam) { const { dataMode } = this.model; if (dataMode === 0) { // 0:不获取,使用传入数据 if (this.data) { this.store.data = this.data; } } else if (dataMode === 1) { // 1:存在传入数据时,不获取 if (this.data) { this.store.data = this.data; } else { await this.load(); } } else if (dataMode === 2) { // 2:始终获取 await this.load(); } } /** * 数据加载 * * @param {IParam} [opts={}] * @param {boolean} [pageReset=false] * @return {*} {Promise} * @memberof PanelController */ public async load(opts: IParam = {}): Promise { const { context, viewParams } = this.store; const { fetchAction } = this.actions; if (!fetchAction) { console.warn(App.ts("widget.panel.notconfigfetch","未配置加载行为")); return { ok: false, data: this.getData(), rowData: { status: 500 } }; } const arg: any = {}; const queryParams: IParam = {}; const parentData: IParam = {}; this.emit('beforeLoad', [parentData]); // 视图查询参数 if (parentData && Object.keys(parentData).length > 0) { Object.assign(queryParams, parentData); } // 额外查询参数 if (opts && Object.keys(opts).length > 0) { Object.assign(queryParams, opts); } const tempViewParams = Object.assign(deepCopy(viewParams), queryParams); Object.assign(arg, { viewParams: tempViewParams }); const tempContext = deepCopy(context); this.beforeAsyncAction('load', tempContext, arg); try { const response: IHttpResponse = await this.ctrlService.search( fetchAction, tempContext, arg ); if (!response.success) { this.afterAsyncAction('load', response); return { ok: false, data: this.getData(), rowData: response, }; } this.handleLoadDataChange(response.data); this.emit('load', response.data); this.afterAsyncAction('load', response); return { ok: true, data: this.getData(), rowData: response, }; } catch (error: any) { this.afterAsyncAction('load', error); return { ok: false, data: this.getData(), rowData: error, }; } } /** * 处理加载数据变更 * * @protected * @param {IParam[]} data * @memberof PanelController */ protected handleLoadDataChange(data: IParam[]): void { this.store.data = data; } /** * 处理组件行为 * * @param {IEvent} actionParam * @memberof PanelController */ public handleComponentAction( actionParam: IEvent, index?: number ): void { const { name, action, data } = actionParam; switch (action) { case 'panelButtonAction': this.handlePanelButtonAction(name, data, index); break; case 'valueChange': this.handlePanelValueChange(name, data, index); break; default: break; } } /** * 处理面板按钮行为 * * @private * @param {string} name * @param {MouseEvent} event * @param {number} [index] * @memberof PanelController */ private handlePanelButtonAction( name: string, event: MouseEvent, index?: number ) { const { context, viewParams } = this.store; const fullName = index || index === 0 ? `${name}_${index}` : name; const layoutModel = this.store.layoutModelDetails[fullName]; if (layoutModel) { let tempData: IParam[] = []; const data: IParam = layoutModel.getData(); const ability: any = layoutModel.getAbility(); const logic = layoutModel.uiAction; if (data) { if (data instanceof Array) { tempData = [...data]; } else { tempData = [data]; } } App.getViewLogicHelper().executeViewLogic( context, viewParams, tempData, event, ability, logic ); } } /** * 处理面板值变化 * * @private * @param {string} name * @param {*} value * @param {number} [index] * @return {*} * @memberof PanelController */ private handlePanelValueChange(name: string, value: any, index?: number) { const fullName = index || index === 0 ? `${name}_${index}` : name; if (!fullName || !this.store.layoutData.hasOwnProperty(fullName)) { return; } this.store.layoutData[fullName] = value; this.store.layoutModelDetails[fullName].setData(value); this.panelLogic(name, index); this.computeButtonAuthState(); } /** * 计算按钮权限状态 * * @private * @memberof PanelController */ private async computeButtonAuthState() { for (const key in this.store.layoutModelDetails) { const layoutModel = this.store.layoutModelDetails[key]; if (layoutModel.itemType == 'BUTTON') { await layoutModel.computeActionAuthState(); } } } /** * 面板逻辑 * * @private * @param {string} name * @param {number} [index] * @memberof PanelController */ private panelLogic(name: string, index?: number): void { const { layoutData } = this.store; const { layoutItems } = this.model; if (layoutItems) { Object.values(layoutItems).forEach((item: IParam) => { item.groupLogics?.forEach((logic: IParam) => { const relatedNames = logic.relatedDetailNames || []; if (Object.is(name, '') || relatedNames.indexOf(name) != -1) { const tempLogic = deepCopy(logic); if (index || index === 0) { tempLogic.dEFDName = `${tempLogic.dEFDName}_${index}`; } const fullName = index || index === 0 ? `${item.name}_${index}` : item.name; const ret = verifyDynamicLogic(layoutData, tempLogic); switch (tempLogic.logicCat) { // 动态空输入,不满足则必填 case 'ITEMBLANK': if (this.store.layoutModelDetails[fullName]) { this.store.layoutModelDetails[fullName].required = !ret; } break; // 动态启用,满足则启用 case 'ITEMENABLE': if (this.store.layoutModelDetails[fullName]) { this.store.layoutModelDetails[fullName].disabled = !ret; } break; // 动态显示,满足则显示 case 'PANELVISIBLE': if (this.store.layoutModelDetails[fullName]) { this.store.layoutModelDetails[fullName].visible = ret; } break; } } }); }); } } /** * 获取部件能力 * * @return {*} {A} * @memberof PanelController */ public getAbility(): IPanelAbility { return { ...super.getAbility(), load: this.load.bind(this), }; } }