import { IParam, IGridControllerParams, IContext, IOpenViewResult, ICtrlActionResult, IEvent, IGridModel, IHttpResponse, } from '@/core/interface'; import { IGridAbility } from '@/core/interface/widgets/ability'; import { IGridController } from '@/core/interface/widgets/controller'; import { GridActionType } from '@/core/interface/widgets/event'; import { IGridStore } from '@/core/interface/widgets/store'; import { ControlVOBase } from '@/core/modules'; import GridService from '@/core/modules/ctrl-service/grid-service'; import { AuthUtil, DataTypeUtil, dateFormat, deepCopy, VerifyUtil, } from '@/core/utils'; import { FormatController } from '@/core/utils/format'; import { MDCtrlController } from './md-ctrl-controller'; /** * 表格控制器(todo:方法属性需要加修饰符/能力不完整) * * @export * @class GridController * @extends {(MDCtrlController)} * @implements {IGridController} * @template A */ export class GridController extends MDCtrlController implements IGridController { /** * 表格模型 * * @protected * @type {IGridModel} * @memberof GridController */ protected declare model: IGridModel; /** * 表格部件服务 * * @type {GridService} * @memberof GridController */ declare ctrlService: GridService; /** * 行激活模式 (0: 无激活、1: 单击激活、2: 双击激活) * * @protected * @type {(0 | 1 | 2)} * @memberof GridController */ protected rowActiveMode!: 0 | 1 | 2; /** * 备份值规则模型 * * @private * @type {IParam} * @memberof GridController */ private backRuleModel: IParam = {}; /** * 错误信息 * * @private * @type {string[]} * @memberof GridController */ private errorMessages: string[] = []; /** * 行为模型 * * @private * @type {IParam} * @memberof GridController */ private actionModel: IParam = {}; /** * Creates an instance of GridController. * @param {IGridControllerParams} params * @memberof GridController */ public constructor( params: IGridControllerParams ) { super(params); this.rowActiveMode = params.rowActiveMode; this.ctrlInit(params); } /** * 处理部件初始化 * * @protected * @param {IGridControllerParams} params * @memberof GridController */ protected processCtrlInit( params: IGridControllerParams ) { super.processCtrlInit(params); Object.assign(this.store, { enableRowEdit: params.defaultEnableRowEdit === true, aggData: {}, columnFilter: {}, }); this.initRules(); this.initActionModel(); } /** * 初始化值规则 * * @private * @return {*} * @memberof GridController */ private initRules() { if (!this.model.rules) { Object.assign(this.store, { rules: {} }); return; } const rules: IParam = {}; const ruleModel: IParam = {}; const { staticRules, editRules } = this.model.rules; if (editRules && editRules.length > 0) { editRules.forEach((item: IParam) => { ruleModel[item.name] = { error: '' }; const editorRules = item.editor ? VerifyUtil.buildVerConditions(item.editor) : []; const otherRules = staticRules[item.name] || []; rules[item.name] = [ // 非空值规则 { validator(rule: any, value: any, callback: Function) { const result = !item.allowEmpty && (value === null || value === undefined || value === '') ? false : true; // if (result) { // return Promise.resolve(); // } // return Promise.reject(); return result; }, message: `${item.caption || item.name} ${App.ts( 'widget.grid.mandatory', '必须填写' )}`, trigger: ['change', 'blur'], }, ...otherRules, ...editorRules, ]; }); } this.backRuleModel = ruleModel; Object.assign(this.store, { rules, ruleModel }); } /** * 初始化行为模型 * * @private * @return {*} * @memberof GridController */ private initActionModel() { const columns = this.model.columns; if (!columns || columns.length === 0) { return; } const actionModel: IParam = {}; columns.forEach((column: IParam) => { if ( column.columnType === 'UAGRIDCOLUMN' && column.uIActionDetails && column.uIActionDetails.length > 0 ) { column.uIActionDetails.forEach((detail: IParam) => { Object.assign(actionModel, { [detail.uIActionTag]: { uIActionTag: detail.uIActionTag, codeName: detail.uIActionTag, disabled: detail.disabled, noPrivDisplayMode: detail.noPrivDisplayMode, visible: detail.visible, dataAccessAction: detail.dataAccessAction, }, }); }); } }); this.actionModel = actionModel; } /** * 处理加载数据变更 * * @protected * @param {IParam[]} data * @memberof GridController */ protected handleLoadDataChange(data: IParam[]): void { this.store.data = data; const ruleModel = {}; this.store.data.forEach((item: IParam, index: number) => { this.handleDataScript(item); Object.assign(ruleModel, { [index]: deepCopy(this.backRuleModel) }); Object.assign(item, this.computeItemAuthState(item)); }); this.store.ruleModel = ruleModel; if (this.model.aggMode !== 'NONE') { this.handleDataAgg(); } this.handleGroup(); this.handleDefaultSelect(); } /** * 计算表格列脚本 * * @private * @param {IParam} data * @memberof GridController */ private handleDataScript(data: IParam) { const dataItems: IParam[] = this.model.dataItems; dataItems.forEach((dataItem: IParam) => { if (dataItem.customCode && dataItem.scriptCode) { try { data[dataItem.name] = eval(dataItem.scriptCode); } catch (error) { console.error(`${App.ts('app.error.scripterror')} ${error}`); } } }) } /** * 表格数据聚合 * * @private * @return {*} * @memberof GridController */ private handleDataAgg() { const { aggMode, columns } = this.model; // 聚合数据 const aggData: IParam = {}; // 值格式化工具 const formatUtil = FormatController.getInstance(); // 当前页聚合 if (aggMode === 'PAGE') { columns.forEach((column: IParam) => { const { aggMode: cAggMode, aggField, dataItemName, aggValueFormat, } = column; if (cAggMode === 'NONE') { return; } const values = this.store.data.map((data: IParam) => { return data[aggField]; }); // 合计 if (cAggMode === 'SUM') { const aggValue = values.reduce((prev: any, curr: any) => { const value = Number(curr); if (!isNaN(value)) { return prev + curr; } else { return prev; } }, 0); aggData[dataItemName] = aggValueFormat ? formatUtil.format(aggValue, aggValueFormat) : `${App.ts('widget.grid.totalvalue', '合计')}: ${aggValue}`; return; } // 平均值 if (cAggMode === 'AVG') { const aggValue = values.reduce((prev: any, curr: any) => { const value = Number(curr); if (!isNaN(value)) { return prev + curr; } else { return prev; } }, 0) / values.length; aggData[dataItemName] = aggValueFormat ? formatUtil.format(aggValue, aggValueFormat) : `${App.ts('widget.grid.averagevalue', '平均值')}: ${aggValue}`; return; } // 最大值 if (cAggMode === 'MAX') { let maxValue: number | null = null; values.forEach((v: any) => { const value = Number(v); if (!isNaN(value)) { if (maxValue === null || value > maxValue) { maxValue = value; } } }); aggData[dataItemName] = aggValueFormat ? formatUtil.format(maxValue, aggValueFormat) : `${App.ts('widget.grid.maxvalue', '最大值')}: ${maxValue}`; return; } // 最小值 if (cAggMode === 'MIN') { let minValue: number | null = null; values.forEach((v: any) => { const value = Number(v); if (!isNaN(value)) { if (minValue === null || value < minValue) { minValue = value; } } }); aggData[dataItemName] = aggValueFormat ? formatUtil.format(minValue, aggValueFormat) : `${App.ts('widget.grid.minvalue', '最小值')}: ${minValue}`; return; } }); this.store.aggData = aggData; return; } // 全部数据聚合 if (aggMode === 'ALL') { const { aggDeCodeName, aggDataSet } = this.model; if (!aggDeCodeName || !aggDataSet) { App.getNotificationHelper().warning( App.ts('widget.common.warn', '警告'), '未配置聚合实体或聚合行为' ); return; } App.getDataService(aggDeCodeName, this.store.context).then( (service: any) => { if ( service && service[aggDataSet] && service[aggDataSet] instanceof Function ) { service[aggDataSet](this.store.context, this.store.viewParams).then( (response: IHttpResponse) => { if (response.success && response.data) { columns.forEach((column: IParam) => { const { aggMode: cAggMode, aggField, dataItemName, aggValueFormat, } = column; if (cAggMode === 'NONE') { return; } const aggValue = Number(response.data[aggField]); if (isNaN(aggValue)) { return; } // 合计 if (cAggMode === 'SUM') { aggData[dataItemName] = aggValueFormat ? formatUtil.format(aggValue, aggValueFormat) : `${App.ts( 'widget.grid.totalvalue', '合计' )}: ${aggValue}`; return; } // 平均值 if (cAggMode === 'AVG') { aggData[dataItemName] = aggValueFormat ? formatUtil.format(aggValue, aggValueFormat) : `${App.ts( 'widget.grid.averagevalue', '平均值' )}: ${aggValue}`; return; } // 最大值 if (cAggMode === 'MAX') { aggData[dataItemName] = aggValueFormat ? formatUtil.format(aggValue, aggValueFormat) : `${App.ts( 'widget.grid.maxvalue', '最大值' )}: ${aggValue}`; return; } // 最小值 if (cAggMode === 'MIN') { aggData[dataItemName] = aggValueFormat ? formatUtil.format(aggValue, aggValueFormat) : `${App.ts( 'widget.grid.minvalue', '最小值' )}: ${aggValue}`; return; } }); this.store.aggData = aggData; } } ); } } ); } } /** * 计算项权限状态 * * @private * @param {IParam} data * @return {*} * @memberof GridController */ private computeItemAuthState(data: IParam) { if (!this.actionModel || Object.keys(this.actionModel).length === 0) { return; } const tempActionModel = deepCopy(this.actionModel); if (this.uiService) { AuthUtil.calcActionItemAuthState( data.getDo(), tempActionModel, this.uiService, this.store.viewCtx.view?.getModel() ); } return tempActionModel; } /** * 新建默认值 * * @param {IParam} data * @memberof GridController */ public createDefault(data: IParam) { const { viewParams, context } = this.store; const { createDefaultItems } = this.model; if (createDefaultItems.length === 0) { return; } createDefaultItems.forEach((item: IParam) => { const { createDVT, createDV, property, valueFormat, dataType } = item; if (createDVT && data.hasOwnProperty(property)) { switch (createDVT) { case 'CONTEXT': if (createDV) { data[property] = viewParams[createDV]; } break; case 'SESSION': case 'APPDATA': if (createDV) { data[property] = context[createDV]; } break; case 'OPERATORNAME': data[property] = context['srfusername']; break; case 'OPERATOR': data[property] = context['srfuserid']; break; case 'CURTIME': data[property] = valueFormat ? dateFormat(new Date(), valueFormat) : new Date().toDateString(); break; case 'PARAM': if (item.createDV) { data[property] = this.computeDefaultValueWithParam( 'CREATE', item.createDV, data ); } break; } } else if (createDV && data.hasOwnProperty(property)) { data[property] = dataType && DataTypeUtil.isNumber(dataType) ? Number(createDV) : createDV; } }); } /** * 更新默认值 * * @param {IParam} row * @memberof GridController */ public updateDefault(row: IParam) { const { viewParams, context, data } = this.store; const { updateDefaultItems } = this.model; if (updateDefaultItems.length === 0 || data.length === 0) { return; } updateDefaultItems.forEach((item: IParam) => { const { updateDV, updateDVT, property, valueFormat, dataType } = item; if (updateDVT && row.hasOwnProperty(property)) { switch (updateDVT) { case 'CONTEXT': if (updateDV) { row[property] = viewParams[updateDV]; } break; case 'SESSION': case 'APPDATA': if (updateDV) { row[property] = context[updateDV]; } break; case 'OPERATORNAME': row[property] = context['srfusername']; break; case 'OPERATOR': row[property] = context['srfuserid']; break; case 'CURTIME': row[property] = valueFormat ? dateFormat(new Date(), valueFormat) : new Date().toDateString(); break; case 'PARAM': if (item.createDV) { row[property] = this.computeDefaultValueWithParam( 'UPDATE', updateDV, row ); } break; } } else if (updateDV && row.hasOwnProperty(property)) { row[property] = dataType && DataTypeUtil.isNumber(dataType) ? Number(updateDV) : updateDV; } }); } /** * 计算数据对象类型的默认值 * @param {string} action 行为 * @param {string} param 默认值参数 * @param {*} data 当前行数据 * @memberof GridControlBase */ public computeDefaultValueWithParam( action: string, param: string, data: any ) { if (Object.is(action, 'UPDATE')) { const nativeData: IParam[] = this.ctrlService.getCopynativeData(); if (nativeData && nativeData instanceof Array && nativeData.length > 0) { const deCodeName = this.model.entityCodeName.toLowerCase(); const targetData: IParam | undefined = nativeData.find((item: any) => { return item[deCodeName] === data.srfkey; }); if (targetData) { return targetData[param] ? targetData[param] : null; } else { return null; } } else { return null; } } else { return this.ctrlService.getRemoteCopyData()[param] ? this.ctrlService.getRemoteCopyData()[param] : null; } } /** * 处理组件事件 * * @param {IEvent} actionParam * @param {number} index * @memberof GridController */ public handleComponentAction(actionParam: IEvent, index: number) { const { name, action, data } = actionParam; switch (action) { case 'valueChange': this.handleItemValueChange(name, data, index); break; case 'editorClick': this.handleEditorClick(name, data, index); break; case 'editorFocus': this.handleEditorFocus(name, data, index); break; case 'editorBlur': this.handleEditorBlur(name, data, index); break; } } /** * @description 表单编辑器点击事件 * @date 2023/02/03 10:02:48 * @param {string} name * @param {*} data * @memberof GridController */ public handleEditorClick(name: string, data: any, index: number) { //todo 表单编辑器点击事件 console.log(`编辑器${name}点击了`); } /** * @description 表单编辑器聚焦事件 * @date 2023/02/03 10:02:24 * @param {string} name * @param {*} data * @memberof GridController */ public handleEditorFocus(name: string, data: any, index: number) { //todo 表单编辑器聚焦事件 console.log(`编辑器${name}聚焦了`); } /** * @description 表单编辑器失去焦点事件 * @date 2023/02/03 10:02:37 * @param {string} name * @param {*} data * @memberof GridController */ public handleEditorBlur(name: string, data: any, index: number) { //todo 表单编辑器失去焦点事件 console.log(`编辑器${name}失去焦点了`); } /** * 处理值变更 * * @protected * @param {string} name * @param {*} value * @param {number} index * @return {*} * @memberof GridController */ protected handleItemValueChange(name: string, value: any, index: number) { const data = this.store.data[index]; if (!data || !data.hasOwnProperty(name) || data[name] === value) { return; } this.store.data[index][name] = value; // 修改行数据状态 if (this.store.data[index].srfuf === '0') { this.store.data[index].$rowDataState = 'create'; } else { this.store.data[index].$rowDataState = 'update'; } this.resetItemData(name, value, index); this.validateItem(name, value, index); this.handleItemUpdate(name, value, index); } /** * 处理表格编辑项更新 * * @private * @param {string} name * @param {*} value * @param {number} index * @memberof GridController */ private handleItemUpdate(name: string, value: any, index: number) { const { columns } = this.model; const column = columns.find((c: IParam) => c.dataItemName === name); if (column && column.itemUpdate) { const { details, method, showBusyIndicator, scriptCode } = column.itemUpdate; // 脚本代码 if (scriptCode) { const context = this.store.context; const viewParams = this.store.viewParams; const data = this.store.data[index]; eval(scriptCode); } else { this.updateGridEditItem( method, this.store.data[index], details, index, showBusyIndicator ); } } } /** * 表格编辑项更新 * * @param {string} action 更新行为 * @param {IParam} data 更新行数据 * @param {string[]} updateDetails 更新影响项 * @param {number} index 数据下标 * @param {boolean} [showInfo] 是否显示处理结果 * @return {*} * @memberof GridController */ public updateGridEditItem( action: string, data: IParam, updateDetails: string[], index: number, showInfo?: boolean ) { if (!action || action === '') { return; } const tempContext = deepCopy(this.store.context); const deCodeName = this.model.entityCodeName.toLowerCase(); Object.assign(tempContext, { [deCodeName]: data[deCodeName] || data.srfkey, }); const arg: IParam = data.getDo(); Object.assign(arg, this.store.viewParams); this.beforeAsyncAction('updateGridEditItem', tempContext, arg); this.ctrlService .frontLogic(action, tempContext, arg) .then((response: IHttpResponse) => { this.afterAsyncAction('updateGridEditItem', response); if (!response.success) { if (showInfo) { App.getNotificationHelper().error( '', response.message ? response.message : App.ts('widget.grid.editupdatefail', '表格编辑项更新失败') ); } return; } const _data: any = response.data; if (!_data) { return; } updateDetails.forEach((name: string) => { if (!_data.hasOwnProperty(name)) { return; } this.store.data[index][name] = _data[name]; }); }) .catch((error: any) => { this.afterAsyncAction('updateGridEditItem', error); if (showInfo) { App.getNotificationHelper().error( '', error && error.message ? error.message : App.ts('widget.grid.editupdatefail', '表格编辑项更新失败') ); } }); } /** * 重置表格项数据 * * @private * @param {string} name 表格列标识 * @param {*} value 值 * @param {number} index 行下标 * @memberof GridController */ private resetItemData(name: string, value: any, index: number) { const { columns } = this.model; columns.forEach((column: IParam) => { if (column.resetItemName && column.resetItemName === name) { this.handleItemValueChange(column.dataItemName, null, index); if (column.valueItemName) { this.handleItemValueChange(column.valueItemName, null, index); } } }); } /** * 校验项 * * @private * @param {string} name * @param {*} value * @param {number} index * @memberof GridController */ private validateItem( name: string, value: any, index: number ): Promise { const data = this.store.data[index]; const { ruleModel } = this.store; return new Promise((resolve: any) => { VerifyUtil.validateItem(name, data, this.store.rules) .then((result: any) => { ruleModel[index][name] = { error: null }; resolve(true); }) .catch(({ errors }: any) => { if (errors && errors.length > 0) { ruleModel[index][name] = { error: errors[0].message }; } else { ruleModel[index][name] = { error: App.ts('widget.grid.ruleverifyerror', '值规则校验错误'), }; } resolve(false); }); }); } /** * 校验 * * @private * @param {IParam[]} [items] 需要检验的项(不传入则校验全部数据) * @return {*} {Promise} * @memberof GridController */ private async validate(items?: IParam[]): Promise { this.errorMessages = []; let validateState = true; let index = -1; const validateItems = items && items.length > 0 ? items : this.store.data; for (const item of validateItems) { let tempMessage = ''; index += 1; if (item.$rowDataState === 'create' || item.$rowDataState === 'update') { for (const property of Object.keys(this.store.rules)) { if (!(await this.validateItem(property, item, index))) { validateState = false; tempMessage = tempMessage + '

' + this.store.ruleModel[index][property].error + '

'; } } } if (tempMessage) { this.errorMessages.push(tempMessage); } } return validateState; } /** * 新建行 * * @param {*} [opts] * @return {*} {Promise} * @memberof GridController */ async newRow(opts: IParam[] = []): Promise { const { loadDraftAction } = this.actions; if (!loadDraftAction) { App.getNotificationHelper().warning( App.ts('widget.common.warn', '警告'), App.ts('widget.grid.notconfignewaction', '未配置新建行为') ); return { ok: false, data: this.getData(), rowData: { status: 500 } }; } const { context, viewParams } = this.store; const arg = opts && opts.length > 0 ? opts[0] : { viewParams: deepCopy(viewParams) }; const tempContext: IContext = deepCopy(context); const res = await this.beforeAsyncAction('loadDraft', tempContext, arg); if(!res.ok){ return { ok: false, data: this.getData(), rowData: { status: 500 } }; } try { const response = await this.ctrlService.loadDraft( loadDraftAction, context, arg ); await this.afterAsyncAction('loadDraft', response); if (!response.success) { return { ok: false, data: this.getData(), rowData: { status: 500 } }; } const data = response.data; this.createDefault(data); this.store.data.unshift(data); this.store.ruleModel[this.store.data.length - 1] = deepCopy( this.backRuleModel ); return { ok: true, data: this.getData(), rowData: response }; } catch (error: any) { await this.afterAsyncAction('loadDraft', error); return { ok: false, data: this.getData(), rowData: error }; } } /** * 保存数据 * * @param {IParam} [opts={}] * @return {*} {Promise} * @memberof GridController */ async save(opts: IParam = {}): Promise { const { viewParams, data, context } = this.store; const { enableGroup, groupMode } = this.model; const items: IParam[] = []; if (enableGroup && groupMode) { return { ok: true, data: this.getData(), rowData: {} }; } else { this.store.data.forEach((item: IParam) => { items.push(item.toObject()); }); } if ( viewParams && (viewParams.copymode === true || viewParams.copymode === 'true') && data.length > 0 ) { items.forEach((item: IParam) => { item.$rowDataState = 'create'; }); } // 更新默认值 items.forEach((item: IParam) => { if (item.$rowDataState === 'update') { this.updateDefault(item); } }); // 没有新建或更新状态的数据直接返回 if ( items.filter( (_item: IParam) => _item.$rowDataState === 'create' || _item.$rowDataState === 'update' ).length === 0 ) { // 如果没有可保存的数据也抛出保存事件,适配表单多数据部件 this.emit('save', []); return { ok: true, data: this.getData(), rowData: {} }; } if (!(await this.validate(items))) { this.showValidateMessage(); return { ok: true, data: this.getData(), rowData: { status: 500 } }; } const tempViewParams = deepCopy(viewParams); const successItems: IParam[] = []; const errorItems: IParam[] = []; const errorMessage: IParam[] = []; const { createAction, updateAction } = this.actions; const res = await this.beforeAsyncAction('save', context, items); if(!res.ok){ return { ok: false, data: this.getData(), rowData: { status: 500 } }; } for (const item of items) { try { if (Object.is(item.$rowDataState, 'create') || item.srfuf === '0') { if (!createAction) { App.getNotificationHelper().warning( App.ts('widget.common.warn', '警告'), App.ts('widget.grid.notconfignewaction', '未配置新建行为') ); } else { Object.assign(item, { viewParams: tempViewParams }); const tempContext = deepCopy(context); await this.beforeAsyncAction('create', tempContext, item); const response = await this.ctrlService.add( createAction, tempContext, item ); await this.afterAsyncAction('create', response); successItems.push(response.data); } } else if (Object.is(item.$rowDataState, 'update')) { if (!updateAction) { App.getNotificationHelper().warning( App.ts('widget.common.warn', '警告'), App.ts('widget.grid.notconfigupdateaction', '未配置更新行为') ); } else { Object.assign(item, { viewParams: tempViewParams }); const tempContext = deepCopy(context); const entityCodeName = this.model.entityCodeName.toLowerCase(); if (entityCodeName) { Object.assign(tempContext, { [entityCodeName.toLowerCase()]: item[entityCodeName.toLowerCase()], }); } await this.beforeAsyncAction('update', tempContext, item); const response = await this.ctrlService.update( updateAction, tempContext, item ); await this.afterAsyncAction('update', response); successItems.push(response.data); } } } catch (error: any) { await this.afterAsyncAction('save', error); errorItems.push(item); errorMessage.push(error); } } this.emit('save', successItems); const success: boolean = errorItems.length === 0 && successItems.length > 0; const afterRes = await this.afterAsyncAction('save', { success, data: successItems }); if(!afterRes.ok){ return { ok: false, data: this.getData(), rowData: { status: 500 } }; } if (success) { this.refresh(); if ( !( opts && ((opts.hasOwnProperty('srfshowinfo') && (opts['srfshowinfo'] === false || opts['srfshowinfo'] === 'false')) || (opts.hasOwnProperty('showResultInfo') && (opts['showResultInfo'] === false || opts['showResultInfo'] === 'false'))) ) ) { App.getNotificationHelper().success( '', App.ts('widget.grid.successmsg', '保存成功') ); } } else { // TODO 处理保存错误 if ( !( opts && ((opts.hasOwnProperty('srfshowinfo') && (opts['srfshowinfo'] === false || opts['srfshowinfo'] === 'false')) || (opts.hasOwnProperty('showResultInfo') && (opts['showResultInfo'] === false || opts['showResultInfo'] === 'false'))) ) ) { App.getNotificationHelper().error( '', App.ts('widget.grid.successmsg', 'failmsg') ); } } return { ok: success, data: this.getData(), rowData: { status: success ? 200 : 500 }, }; } /** * 删除数据 * * @param {IParam} [datas={}] * @return {*} {Promise} * @memberof GridController */ async remove(datas: IParam[] = []): Promise { const { removeAction } = this.actions; if (!removeAction) { App.getNotificationHelper().warning( App.ts('widget.common.warn', '警告'), App.ts('widget.grid.notconfigdelaction', '未配置删除行为') ); return { ok: false, data: this.getData(), rowData: { status: 500 } }; } const deleteItems: IParam[] = []; // 已选中数据 datas.forEach((record: IParam) => { if (record.$rowDataState === 'create' || 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.grid.check', '选中')}${ deleteItems.length }${App.ts('widget.grid.piece', '条数据')}`; } else { if (deleteItems.length < 5) { dataInfo += ` ${App.ts('widget.grid.total', '共')}${ deleteItems.length }${App.ts('widget.grid.piece', '条数据')}`; } else { dataInfo += `...${deleteItems.length}${App.ts( 'widget.grid.piece', '条数据' )}`; } } // 去除null和undefined dataInfo = dataInfo.replace(/[null]/g, '').replace(/[undefined]/g, ''); const removeData = async () => { 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); } const res = await this.beforeAsyncAction('remove', tempContext, arg); if(!res.ok){ return { ok: false, data: this.getData(), rowData: { status: 500 } }; } if (promises) { promises .then(async (response: any) => { await this.afterAsyncAction('remove', response); if (!response.success && !Array.isArray(response)) { App.getNotificationHelper().error( '', `${App.ts('widget.grid.deletefail', '删除数据失败')}, ${ response.info }` ); return; } else { App.getNotificationHelper().success( '', App.ts('widget.grid.deletesuccess', '删除数据成功') ); } //删除items中已删除的项 deleteItems.forEach((data: any) => { this.store.data.some((item: any, index: number) => { if (Object.is(item.srfkey, data.srfkey)) { this.store.data.splice(index, 1); delete this.store.ruleModel[index]; return true; } }); }); this.store.totalRecord -= deleteItems.length; this.emit('remove', deleteItems); this.store.selections = []; this.refresh(); }) .catch(async (error: any) => { await 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 GridController */ public async refresh(args?: IParam | undefined): Promise { try { const result = await this.load({ srfpagereset: true }); if (result.ok) { return true; } } catch (error) { return false; } return false; } /** * 表格行点击 * * @param {IParam} row * @param {MouseEvent} event * @memberof GridController */ public rowClick(row: IParam, event: MouseEvent) { const selections = this.store.selections; if (this.singleSelect) { selections.length = 0; selections.push(row); } else { const index = selections.findIndex( (select: IParam) => select.srfkey === row.srfkey ); // 未选中 if (index === -1) { this.store.selections.push(row); } else { this.store.selections.splice(index, 1); } } this.emit('selectionChange', this.getData()); if (this.rowActiveMode === 1) { this.emit('dataActive', [row]); } } /** * 表格行双击 * * @param {IParam} row * @param {MouseEvent} event * @memberof GridController */ public rowDbClick(row: IParam, event: MouseEvent) { const selections = this.store.selections; if (this.singleSelect) { selections.length = 0; selections.push(row); } else { const index = selections.findIndex( (select: IParam) => select.srfkey === row.srfkey ); // 未选中 if (index === -1) { this.store.selections.push(row); } else { this.store.selections.splice(index, 1); } } this.emit('selectionChange', this.getData()); if (this.rowActiveMode === 2) { this.emit('dataActive', [row]); } } /** * 选中数据 * * @param {IParam[]} selections * @memberof GridController */ public selectionChange(selections: IParam[]) { this.store.selections = selections; this.emit('selectionChange', this.getData()); } /** * @description 数据导入 * @param {IContext} context * @param {IParam} viewParams * @param {IParam[]} data * @memberof GridController */ public async importExcel(context: IContext, viewParams: IParam, data: IParam[]) { if (!this.model.dataImport) { App.getNotificationHelper().warning( App.ts('widget.common.warn', '警告'), App.ts('widget.grid.pleaseconfigdataimport', '请配置数据导入项') ); return; } const view: any = { name: 'app-data-import', caption: App.ts('widget.grid.dataimport', '导入数据'), codeName: 'AppDataImport', width: 550, height: 370, }; const { dataImport } = this.model; const tempContext = deepCopy(context); const tempViewParams = deepCopy(viewParams); Object.assign(tempViewParams, { importId: dataImport.codeName, serviceName: this.model.entityCodeName, appDeLogicName: this.model.entityLogicName, ignoreError: dataImport.ignoreError, }); if ( dataImport.importItems && dataImport.importItems.length > 0 && import.meta.env.VITE_MODE === 'R7' ) { Object.assign(tempViewParams, { importItems: dataImport.importItems }); } App.getOpenViewHelper() .openModal(view, tempContext, tempViewParams) .then(async (result: IOpenViewResult) => { if (!result.ok) { return { ok: false, data: this.getData(), rowData: { status: 500 } }; } if (result.ok && result.data) { this.refresh(); } }).catch((error:any) => { return { ok: false, data: this.getData(), rowData: { status: 500 } }; }); } /** * 选择全部 * * @memberof GridController */ public selectAll(): void { // TODO 暂不考虑单选情况 this.store.selections = this.store.data; this.emit('selectionChange', this.getData()); } /** * 选中数据 * * @param {IParam[]} items 选中数据 * @param {boolean} [reverse] 是否反选 * @memberof GridController */ public selectItems(items: IParam[], reverse?: boolean) { // TODO 暂不考虑单选情况 const selections: IParam[] = []; this.store.data.forEach((item: IParam) => { const index = items.findIndex((i: IParam) => i.srfkey === item.srfkey); // 反选时未在items中选中,正选时在items中选中 if ((reverse && index === -1) || (!reverse && index !== -1)) { selections.push(item); } }); this.store.selections = selections; this.emit('selectionChange', this.getData()); } /** * 切换行编辑 * * @memberof GridController */ public toggleRowEdit(): void { this.store.enableRowEdit = !this.store.enableRowEdit; } /** * 显示校验信息 * * @memberof GridController */ public showValidateMessage() { if (this.errorMessages.length > 0) { // TODO 目前只显示第一行信息,后续考虑优化 App.getNotificationHelper().error( App.ts('widget.grid.gridvaluerulevarifyerror', '表格值规则校验错误'), this.errorMessages[0] ); } } /** * 自定义表格参数 * * @memberof GridController */ public customCallBack() { if (this.UIEngineContainer) { return this.UIEngineContainer.executeCustomEvent.bind(this.UIEngineContainer); } } /** * 处理列过滤值改变 * * @param {IParam} filter * @memberof GridController */ public handleFilterChange(filter: IParam) { const opts = { srfpagereset: true }; Object.assign(this.store.columnFilter, filter); if (this.store.columnFilter && Object.keys(this.store.columnFilter).length > 0) { Object.keys(this.store.columnFilter).forEach((name: string) => { if (this.store.columnFilter[name]) { Object.assign(opts, { [name]: this.store.columnFilter[name] }) } }) } this.load(opts); } /** * 获取能力 * * @template A * @return {*} {A} * @memberof GridController */ getAbility(): IGridAbility { return { ...super.getAbility(), importExcel: this.importExcel.bind(this), newRow: this.newRow.bind(this), toggleRowEdit: this.toggleRowEdit.bind(this), save: this.save.bind(this), remove: this.remove.bind(this), // loadDraft: this.newRow.bind(this) }; } }