import { DataViewCtrlActionType, IDataViewCtrlStore, IDataViewCtrlAbility, IDataViewCtrlController, IDataViewCtrlControllerParams, IParam, IHttpResponse, ICtrlActionResult, IDataViewCtrlModel, IUIService, ICodeListItem, } from '@/core/interface'; import { ControlVOBase } from '@/core/modules'; import DataViewService from '@/core/modules/ctrl-service/data-view-service'; import { AuthUtil, deepCopy } from '@/core/utils'; import { MDCtrlController } from './md-ctrl-controller'; /** * 卡片视图部件控制器 * * @export * @class DataViewCtrlController * @extends {(MDCtrlController)} * @implements {IDataViewCtrlController} * @template T */ export class DataViewCtrlController extends MDCtrlController< DataViewCtrlActionType, IDataViewCtrlStore, IDataViewCtrlAbility > implements IDataViewCtrlController { /** * 加载模式 * * @protected * @type {('loadDefault' | 'loadMore')} * @memberof DataViewCtrlController */ protected isLoadMore = false; /** * data数据copy * * @protected * @type IParam[] * @memberof DataViewCtrlController */ protected copyData: IParam[] = []; /** * 行激活模式 (0: 无激活、1: 单击激活、2: 双击激活) * * @protected * @type {(0 | 1 | 2)} * @memberof DataViewCtrlController */ protected rowActiveMode!: 0 | 1 | 2; /** * 卡片视图部件服务 * * @type {GridService} * @memberof GridController */ declare ctrlService: DataViewService; /** * 卡片视图部件模型 * * @protected * @type {IDataViewCtrlModel} * @memberof DataViewCtrlController */ protected declare readonly model: IDataViewCtrlModel; /** * Creates an instance of DataViewCtrlController. * @param {IDataViewCtrlControllerParams} params * @memberof DataViewCtrlController */ public constructor( params: IDataViewCtrlControllerParams< DataViewCtrlActionType, IDataViewCtrlAbility > ) { super(params); this.rowActiveMode = params.rowActiveMode; this.ctrlInit(params); } /** * 处理部件初始化 * * @protected * @param {IDataViewCtrlControllerParams} params * @memberof DataViewCtrlController */ protected processCtrlInit( params: IDataViewCtrlControllerParams< DataViewCtrlActionType, IDataViewCtrlAbility > ) { super.processCtrlInit(params); this.name = 'dataview'; Object.assign(this.store, { loadMoreStatus: false }); } /** * 卡片视图部件项单击 * * @param {IParam} item * @param {MouseEvent} event * @memberof DataViewCtrlController */ public handleItemClick(item: IParam, event: MouseEvent) { const selections = this.store.selections; if (this.singleSelect) { selections.length = 0; selections.push(item); } else { const index = selections.findIndex( (select: IParam) => select.srfkey === item.srfkey ); // 未选中 if (index === -1) { this.store.selections.push(item); } else { this.store.selections.splice(index, 1); } } this.emit('selectionChange', this.getData()); if (this.rowActiveMode === 1) { this.emit('dataActive', [item]); } } /** * 卡片视图部件项双击 * * @param {IParam} item * @param {MouseEvent} event * @memberof DataViewCtrlController */ public handleItemDbClick(item: IParam, event: MouseEvent) { const selections = this.store.selections; if (this.singleSelect) { selections.length = 0; selections.push(item); } else { const index = selections.findIndex( (select: IParam) => select.srfkey === item.srfkey ); // 未选中 if (index === -1) { this.store.selections.push(item); } else { this.store.selections.splice(index, 1); } } this.emit('selectionChange', this.getData()); if (this.rowActiveMode === 2) { this.emit('dataActive', [item]); } } /** * 选中数据 * * @param {IParam[]} selections * @memberof DataViewCtrlController */ public handleSelectionChange(selections: IParam[]) { this.store.selections = selections; this.emit('selectionChange', this.getData()); } /** * 加载更多 * * @return {*} * @memberof DataViewCtrlController */ async loadMore() { if (this.store.data.length >= this.store.totalRecord) { return; } this.isLoadMore = true; this.store.curPage++; await this.load(); this.isLoadMore = false; } /** * 异步行为之后 * * @param {string} action * @param {IHttpResponse} response * @memberof DataViewCtrlController */ public afterAsyncAction(action: string, response: IHttpResponse) { this.store.loadMoreStatus = this.store.data.length < this.store.totalRecord; return super.afterAsyncAction(action, response); } /** * 删除 * * @param {string} action * @param {IHttpResponse} response * @memberof DataViewCtrlController */ async remove(datas: IParam[] = []): Promise { const { removeAction } = this.actions; if (!removeAction) { App.getNotificationHelper().warning(App.ts("widget.common.warn","警告"), App.ts("widget.dataview.nodeleteaction","未配置删除行为")); return { ok: false, data: this.getData(), rowData: { status: 500 } }; } const deleteItems: IParam[] = []; // 已选中数据 datas.forEach((record: IParam) => { if (record.srfuf === '0') { const index = this.store.data.findIndex( (i: IParam) => i.srfkey === record.srfkey ); if (index !== -1) { this.store.data.splice(index, 1); } } else { deleteItems.push(record); } }); if (deleteItems.length === 0) { return { ok: true, data: this.getData(), rowData: { status: 200 } }; } let dataInfo = ''; deleteItems.forEach((item: IParam, index: number) => { if (index < 5) { if (dataInfo !== '') { dataInfo += '、'; } dataInfo += item.srfmajortext ? item.srfmajortext : ''; } }); if (!dataInfo) { dataInfo = `${App.ts("widget.dataview.check","选中")}${deleteItems.length}${App.ts("widget.dataview.piece","条数据")}`; } else { if (deleteItems.length < 5) { dataInfo += ` ${App.ts("widget.dataview.total","共")}${deleteItems.length}${App.ts("widget.dataview.piece","条数据")}`; } else { dataInfo += `...${deleteItems.length}${App.ts("widget.dataview.piece","条数据")}`; } } // 去除null和undefined dataInfo = dataInfo.replace(/[null]/g, '').replace(/[undefined]/g, ''); const removeData = () => { const keys: string[] = []; deleteItems.forEach((item: IParam) => keys.push(item.srfkey)); if (keys.length === 0) { return; } const { context, viewParams } = this.store; let _removeAction = removeAction; if (Object.is(removeAction, 'RemoveTemp') && keys.length > 1) { _removeAction = 'RemoveBatchTemp'; } const tempContext: any = deepCopy(context); const _keys: string[] | string = keys.length > 1 ? keys : keys[0]; const { entityCodeName } = this.model; const arg = { [entityCodeName.toLowerCase()]: _keys }; let promises: Promise | null = null; if (keys && keys.length > 1) { const promiseArr: any = []; (_keys as string[]).forEach((ele: any) => { Object.assign(tempContext, { [entityCodeName.toLowerCase()]: ele }); Object.assign(arg, { viewParams: deepCopy(viewParams) }); Object.assign(arg, { [entityCodeName.toLowerCase()]: ele }); promiseArr.push( this.ctrlService.delete(_removeAction, tempContext, arg) ); }); promises = Promise.all(promiseArr); } else { Object.assign(tempContext, { [entityCodeName.toLowerCase()]: _keys }); Object.assign(arg, { viewParams: deepCopy(viewParams) }); promises = this.ctrlService.delete(_removeAction, tempContext, arg); } this.beforeAsyncAction('remove', tempContext, arg); if (promises) { promises .then(async (response: any) => { this.afterAsyncAction('remove', response); if (!response.success && !Array.isArray(response)) { App.getNotificationHelper().error( App.ts("widget.common.error","错误"), `${App.ts("widget.dataview.deletefail","删除数据失败")}, ${response.info}` ); return; } else { App.getNotificationHelper().success(App.ts("widget.common.success","成功"),App.ts("widget.dataview.deletesuccess","删除数据成功")); } //删除items中已删除的项 this.store.totalRecord -= deleteItems.length; this.emit('remove', deleteItems); this.store.selections = []; this.refresh(); }) .catch(async (error: any) => { this.afterAsyncAction('remove', error); }); } }; App.getDialogHelper().confirm( App.ts("widget.common.warn","警告"), `${App.ts("widget.common.confirmtodelete","确认要删除")}${dataInfo},${App.ts("widget.common.delnotberecoverable","删除操作将不可恢复")}?`, () => { removeData(); } ); return { ok: true, data: this.getData(), rowData: { status: 200 } }; } /** * 刷新 * * @param {(IParam | undefined)} [args] * @return {*} {Promise} * @memberof DataViewCtrlController */ public async refresh(args?: IParam | undefined): Promise { try { const result = await this.load(); if (result.ok) { return true; } } catch (error) { return false; } return false; } /** * 处理加载数据变化 * * @protected * @param {IParam[]} data * @memberof DataViewCtrlController */ protected handleLoadDataChange(data: IParam[]): void { if (!this.isLoadMore) { this.store.data = data; this.copyData = []; this.handleGroup(); } else { this.store.data = [...this.store.data, ...data]; this.handleGroup(data); } this.handleDefaultSelect(); this.handleItemUIActionGroup(); setTimeout(() => { this.copyData = [...this.store.data]; }, 0); } /** * 处理分组 * * @protected * @return {*} * @memberof MDCtrlController */ protected handleGroup(data: IParam[] = []) { const { enableGroup, groupMode } = this.model; if (!enableGroup) { return; } if (groupMode === 'AUTO') { if (this.copyData && this.copyData.length > 0) { this.handleAutoLoadMoreData(data); } else { this.handleAutoGroup(); } } else if (groupMode === 'CODELIST') { if (this.copyData && this.copyData.length > 0) { this.handleCodeListLoadMoreData(data); } else { this.handleCodeListGroup(); } } } /** * @description 处理自动分组时点击 加载更多 获取的数据 * @protected * @param {IParam[]} data * @memberof DataViewCtrlController */ protected async handleAutoLoadMoreData(_data: IParam[]) { if (_data.length === 0) { return; } const { data } = this.store; if (data.length === 0) { return; } // 分组属性标识 const field = this.model.groupField as string; // 分组属性代码表 const fieldCodeList = this.model.groupFieldCodeListTag; // 分组列标识 const dataIndex = this.model.groupDataIndex as string; const resultMap: Map = new Map(); const codeItems: IParam[] = []; if (fieldCodeList) { const result = await App.getAppCodeListHelper().getCodeListItems( fieldCodeList ); if (result.ok) { codeItems.push(...result.data); } } _data.forEach((item: IParam) => { const items = resultMap.get(item[field]) || []; items.push(item); resultMap.set(item[field], items); }); resultMap.forEach((value: IParam[], key: string) => { const item = codeItems.length > 0 ? codeItems.find((item: IParam) => item.value === key) : { text: key }; const index = this.copyData.findIndex((item: IParam) => Object.is(item.key, `group-item__${key}`) ); if (index < 0) { this.copyData.push({ key: `group-item__${key}`, srfkey: `group-item__${key}`, srfmajortext: item ? item.text : App.ts('widget.dataview.other', '其他'), [dataIndex]: item ? item.text : App.ts('widget.dataview.other', '其他'), isGroupItem: true, children: value, }); } else { if (!this.copyData[index].children) { this.copyData[index].children = []; } this.copyData[index].children.push(...value); } }); this.store.data = this.copyData; } /** * @description 处理代码表分组时点击 加载更多 获取的数据 * @protected * @param {IParam[]} data * @memberof DataViewCtrlController */ protected async handleCodeListLoadMoreData(_data: IParam[]) { // 分组代码表标识 const codeListTag = this.model.groupCodeListTag as string; // 分组属性标识 const field = this.model.groupField as string; // 分组列标识 const dataIndex = this.model.groupDataIndex as string; if (!codeListTag) { return; } const { context, viewParams } = this.store; const result = await App.getAppCodeListHelper().getCodeListItems( codeListTag, context, viewParams ); if (!result.ok || result.data.length === 0) { return; } const keys: (string | number)[] = result.data.map( (d: ICodeListItem) => d.value ); this.copyData.forEach((item: IParam) => { const _items = _data.filter((_item: IParam) => { return _item[field] === item.value; }); if (!item.children) { item.children = []; } if (_items.length > 0) { item.children.push(..._items); } }); const otherItems = _data.filter( (d: IParam) => keys.indexOf(d[field]) === -1 ); if (otherItems.length > 0) { const index = this.copyData.findIndex((item: IParam) => Object.is(item.key, 'group-other-item') ); if (index < 0) { this.copyData.push({ key: `group-other-item`, srfkey: `group-other-item`, srfmajortext: App.ts('widget.dataview.other', '其他'), [dataIndex]: App.ts('widget.dataview.other', '其他'), isGroupItem: true, children: otherItems, }); } else { this.copyData[index].children.push(...otherItems); } } this.store.data = this.copyData; } /** * 处理项界面行为组 * * @protected * @memberof DataViewCtrlController */ protected async handleItemUIActionGroup() { const { uIActionGroup } = this.model; if (uIActionGroup) { const uIActionGroupModel = deepCopy(uIActionGroup); this.handleChildrenUIAction(this.store.data, uIActionGroupModel); } } /** * 处理子项界面行为 * * @param {IParam[]} data * @memberof DataViewCtrlController */ handleChildrenUIAction(data: IParam[], model: any): void { if (data && data instanceof Array) { data.forEach((item: IParam) => { if (item && !item.isGroupItem) { AuthUtil.calcActionItemAuthState( item.getDo(), model, this.uiService as IUIService, this.store.viewCtx.view?.getModel() ); item.uIActionGroup = model; } else if (item && item.isGroupItem) { this.handleChildrenUIAction(item.children, model); } }); } } /** * 获取能力 * * @template A * @return {*} {A} * @memberof GridController */ getAbility(): IDataViewCtrlAbility { return { ...super.getAbility(), remove: this.remove.bind(this), loadMore: this.loadMore.bind(this), }; } }