diff --git a/src/control/drbar/drbar.controller.ts b/src/control/drbar/drbar.controller.ts index f3ca952aa231278509a8c9997397923725104261..e2c8beecce0a762ef86f1d2956e59984fe881e0a 100644 --- a/src/control/drbar/drbar.controller.ts +++ b/src/control/drbar/drbar.controller.ts @@ -246,16 +246,20 @@ export class DRBarController if (ctrlName === 'form') { if (viewForm) { viewForm.state.visible = true; + viewForm.state.keepAlive = true; } if (this.navPos) { this.navPos.state.visible = false; + this.navPos.state.keepAlive = true; } } else { if (viewForm) { viewForm.state.visible = false; + viewForm.state.keepAlive = true; } if (this.navPos) { this.navPos.state.visible = true; + this.navPos.state.keepAlive = true; } } } diff --git a/src/control/drtab/drtab.controller.ts b/src/control/drtab/drtab.controller.ts index 30422b94dcca67b05073990192bbc6e6f23740be..9e822447cb7654ee507e59d24119f424cac67754 100644 --- a/src/control/drtab/drtab.controller.ts +++ b/src/control/drtab/drtab.controller.ts @@ -233,16 +233,20 @@ export class DRTabController if (ctrlName === 'form') { if (viewForm) { viewForm.state.visible = true; + viewForm.state.keepAlive = true; } if (this.navPos) { this.navPos.state.visible = false; + this.navPos.state.keepAlive = true; } } else { if (viewForm) { viewForm.state.visible = false; + viewForm.state.keepAlive = true; } if (this.navPos) { this.navPos.state.visible = true; + this.navPos.state.keepAlive = true; } } } diff --git a/src/control/form/edit-form/edit-form.service.ts b/src/control/form/edit-form/edit-form.service.ts index e7074ca7d51a8516b0f2f7889c4882d94ba5f1f4..631bee1e51d53fdd644cbb5bc2e6fd0eb897e12c 100644 --- a/src/control/form/edit-form/edit-form.service.ts +++ b/src/control/form/edit-form/edit-form.service.ts @@ -166,7 +166,7 @@ export class EditFormService< context: IParams, params: IParams = {}, ): Promise> { - let res = await this.entityService.exec(methodName, context, params); + let res = await this.exec(methodName, context, params); res = this.handleResponse(res); return res as IHttpResponse; } @@ -187,11 +187,14 @@ export class EditFormService< data: IData, ): Promise> { const wfForm = this.model as IWFEditForm; - const methodName = wfForm.wfstartControlAction?.appDEMethodId; + const methodName = wfForm.wfstartControlAction?.appDEMethodId || 'wfstart'; if (!methodName) { throw new RuntimeModelError(this.model, `不存在工作流启动行为`); } - return this.entityService.wf.exec( + const entityService = await this.app.deService.getService( + this.model.appDataEntityId!, + ); + return entityService.wf.exec( methodName, context, params, @@ -215,11 +218,15 @@ export class EditFormService< data: IData, ): Promise> { const wfForm = this.model as IWFEditForm; - const methodName = wfForm.wfsubmitControlAction?.appDEMethodId; + const methodName = + wfForm.wfsubmitControlAction?.appDEMethodId || 'wfsubmit'; if (!methodName) { throw new RuntimeModelError(this.model, `不存在工作流提交行为`); } - return this.entityService.wf.exec( + const entityService = await this.app.deService.getService( + this.model.appDataEntityId!, + ); + return entityService.wf.exec( methodName, context, params, diff --git a/src/view-engine/edit-view.engine.ts b/src/view-engine/edit-view.engine.ts index 391e20688c9e64e1fc128ba80e073367507e63e2..65a69ad20f668aa4eaa88d7aa0ccb673e28bdcba 100644 --- a/src/view-engine/edit-view.engine.ts +++ b/src/view-engine/edit-view.engine.ts @@ -98,8 +98,17 @@ export class EditViewEngine extends ViewEngineBase { return this.form.getData(); } - load() { - this.form.load(); + async load() { + return this.form.load(); + } + + async save() { + return this.form.save(); + } + + async refresh() { + await this.load(); + // this.view.evt.emit('refreshed', [data]); } // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -119,6 +128,9 @@ export class EditViewEngine extends ViewEngineBase { if (key === SysUIActionTag.SAVE_AND_NEW) { this.saveAndNew(); } + if (key === SysUIActionTag.REFRESH) { + await this.refresh(); + } return super.call(key, args); } diff --git a/src/view-engine/index.ts b/src/view-engine/index.ts index eeec6e1b51df79cea6aeed4440ef6498265e9764..5113ee11a6721bbdde5264d90af0abf20449d9fd 100644 --- a/src/view-engine/index.ts +++ b/src/view-engine/index.ts @@ -19,6 +19,8 @@ import { DataViewExpViewEngine } from './data-view-exp-view.engine'; import { TreeExpViewEngine } from './tree-exp-view.engine'; import { WizardViewEngine } from './wizard-view-engine'; import { ChartViewEngine } from './chart-view.engine'; +import { WFDynaEditView3Engine } from './wf-dyna-edit-view3.engine'; +import { WFDynaActionViewEngine } from './wf-dyna-action-view.engine'; export * from './grid-view.engine'; export * from './index-view.engine'; @@ -109,5 +111,39 @@ export const IBizViewEngine = { 'VIEW_WizardView', (c: IViewController) => new WizardViewEngine(c), ); + ibiz.engine.register( + 'VIEW_DEWFDYNAEDITVIEW3', + (c: IViewController) => new WFDynaEditView3Engine(c), + ); + ibiz.engine.register( + 'VIEW_DEWFDYNAACTIONVIEW', + (c: IViewController) => new WFDynaActionViewEngine(c), + ); + + // 注册部件视图 + ibiz.engine.register( + 'VIEW_GridView9', + (c: IViewController) => new GridViewEngine(c), + ); + ibiz.engine.register( + 'VIEW_ListView9', + (c: IViewController) => new ListViewEngine(c), + ); + ibiz.engine.register( + 'VIEW_EditView9', + (c: IViewController) => new EditViewEngine(c), + ); + ibiz.engine.register( + 'VIEW_DataView9', + (c: IViewController) => new DataViewEngine(c), + ); + ibiz.engine.register( + 'VIEW_TreeView9', + (c: IViewController) => new TreeViewEngine(c), + ); + ibiz.engine.register( + 'VIEW_DETABEXPVIEW9', + (c: IViewController) => new TabExpViewEngine(c), + ); }, }; diff --git a/src/view-engine/wf-dyna-action-view.engine.ts b/src/view-engine/wf-dyna-action-view.engine.ts new file mode 100644 index 0000000000000000000000000000000000000000..e56ab251e7f914a840a47ced6c1f9efde07cb081 --- /dev/null +++ b/src/view-engine/wf-dyna-action-view.engine.ts @@ -0,0 +1,108 @@ +import { RuntimeError } from '@ibiz-template/core'; +import { + ViewController, + IWFDynaActionViewState, + IWFDynaActionViewEvent, + SysUIActionTag, + IEditFormController, +} from '@ibiz-template/runtime'; +import { IAppDEWFDynaActionView } from '@ibiz/model-core'; +import { WFEditViewEngine } from './wf-edit-view.engine'; + +export class WFDynaActionViewEngine extends WFEditViewEngine { + /** + * 视图控制器 + * + * @protected + * @type {ViewController} + * @memberof WFDynaActionViewEngine + */ + protected declare view: ViewController< + IAppDEWFDynaActionView, + IWFDynaActionViewState, + IWFDynaActionViewEvent + >; + + get form() { + const processForm = this.view.context.activeForm + ? `wfform_${this.view.context.activeForm}` + : 'form'; + return this.view.getController( + processForm.toLowerCase(), + ) as IEditFormController; + } + + async doCreated() { + await super.doCreated(); + const { childNames } = this.view; + const processForm = this.view.context.activeForm + ? `wfform_${this.view.context.activeForm}` + : 'form'; + childNames.push(processForm.toLowerCase()); + } + + /** + * 计算当前步骤的表单(通过视图参数获取) + * + * @author lxm + * @date 2022-09-29 15:09:07 + * @returns {*} {Promise} + */ + async calcActiveForm(): Promise { + const processForm = this.view.context.activeForm + ? `wfform_${this.view.context.activeForm}` + : 'form'; + const formModel = this.view.model.viewLayoutPanel!.controls?.find( + control => { + return control.name === processForm.toLowerCase(); + }, + ); + if (!formModel) { + throw new RuntimeError(`找不到表单${processForm}的模型`); + } + this.activeForm = formModel; + + if (!this.view.slotProps.form) { + this.view.slotProps.form = {}; + } + this.view.slotProps.form.modelData = this.activeForm as IData; + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + async call(key: string, args: any): Promise { + if (key === SysUIActionTag.WF_ACTION_OK) { + this.onOkButtonClick(); + return null; + } + if (key === SysUIActionTag.WF_ACTION_CANCEL) { + await this.onCancelButtonClick(); + return null; + } + return super.call(key, args); + } + + /** + * 确认按钮回调 + * + * @author lxm + * @date 2022-09-12 20:09:13 + */ + async onOkButtonClick(): Promise { + // 先保存数据在提交工作流 + if (this.view.context.isEditable) { + await this.save(); + } + await this.form.wfSubmit({}); + await this.view.closeView({ ok: true, data: this.getData() }); + } + + /** + * 取消按钮回调 + * + * @author lxm + * @date 2022-09-12 20:09:00 + */ + async onCancelButtonClick() { + await this.view.closeView({ ok: false, data: [] }); + } +} diff --git a/src/view-engine/wf-dyna-edit-view.engine.ts b/src/view-engine/wf-dyna-edit-view.engine.ts new file mode 100644 index 0000000000000000000000000000000000000000..54e8fe56239e0e9049fb64dee7986634fc34688d --- /dev/null +++ b/src/view-engine/wf-dyna-edit-view.engine.ts @@ -0,0 +1,160 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable no-unused-vars */ +import { + ViewController, + IWFDynaEditViewState, + IWFDynaEditViewEvent, + WFLink, + IModalData, + OpenAppViewCommand, +} from '@ibiz-template/runtime'; +import { IAppDEWFDynaEditView } from '@ibiz/model-core'; +import { WFEditViewEngine } from './wf-edit-view.engine'; + +export class WFDynaEditViewEngine extends WFEditViewEngine { + /** + * 视图控制器 + * + * @protected + * @type {ViewController} + * @memberof WFDynaEditViewEngine + */ + protected declare view: ViewController< + IAppDEWFDynaEditView, + IWFDynaEditViewState, + IWFDynaEditViewEvent + >; + + /** + * 工作流links + * + * @author lxm + * @date 2022-10-08 16:10:53 + * @type {WFLink[]} + */ + wfLinks: WFLink[] = []; + + async doMounted() { + await super.doMounted(); + + this.toolbar?.evt.on('onClick', async event => { + if (event.eventArg) { + this.onLinkClick(event.eventArg); + } + }); + } + + async load() { + const res = await super.load(); + this.calcWfToolbar(); + return res; + } + + /** + * 计算工作流工具栏,需要在表单加载回来之后执行 + * + * @author lxm + * @date 2022-09-30 19:09:44 + * @returns {*} {Promise} + */ + async calcWfToolbar(): Promise { + const app = ibiz.hub.getApp(this.view.context.srfappid); + const entityService = await app.deService.getService( + this.view.model.appDataEntityId!, + ); + + const res = await entityService.wf.getWFLink( + Object.assign(this.view.context.clone(), { + taskDefinitionKey: this.view.params.taskDefinitionKey, + }), + this.getData()[0].getOrigin(), + ); + this.wfLinks = res.data as WFLink[]; + + const extraButtons = this.wfLinks.map(link => { + return { + id: link.sequenceFlowId, + caption: link.sequenceFlowName, + buttonType: 'extra', + tooltip: link.sequenceFlowName, + }; + }); + this.toolbar?.setExtraButtons('before', extraButtons); + } + + /** + * 工作流工具栏点击回调处理 + * + * @author lxm + * @date 2022-10-08 17:10:29 + * @param {id} link 点击按钮对应的id + * @returns {*} {Promise} + */ + async onLinkClick(id: string): Promise { + const link = this.wfLinks.find(wfLink => { + return wfLink.sequenceFlowId === id; + }); + if (link) { + if (link.type) { + // todo 处理有type的情况 + } else { + // 没有type的都走流程提交 + return this.wfSubmitByLink(link); + } + } + } + + /** + * 根据工作流link处理工作流提交 + * + * @param {WFLink} link + * @returns {*} + * @memberof WFDynaEditViewController + */ + async wfSubmitByLink(link: WFLink) { + // 流程表单可以编辑才会先保存 + if (this.isEditable) { + await this.save(); + } + + // 处理视图上下文 + const newContext = Object.assign(this.view.context.clone(), { + isEditable: this.isEditable, + activeForm: link.sequenceFlowForm, + }); + // 处理视图参数 + const newParams = { + ...link, + }; + + const { sequenceFlowView } = link; + + // 查找工作流提交视图 + const submitViewRef = this.view.model.viewLayoutPanel!.appViewRefs?.find( + viewRef => { + return viewRef.name === `WFACTION@${sequenceFlowView}`; + }, + ); + const submitView = submitViewRef?.refAppViewId; + + // *没有工作流操作视图的,自己提交工作流 + if (!submitView) { + await this.form.wfSubmit(newParams); + await this.view.closeView(); + return; + } + + // *有工作流操作视图的,由提交视图执行工作流提交 + const result: IModalData = await ibiz.commands.execute( + OpenAppViewCommand.TAG, + submitView, + newContext, + newParams, + ); + + // 提交视图正常关闭后关闭当前视图 + if (result.ok) { + await this.view.closeView(); + } + } +} diff --git a/src/view-engine/wf-dyna-edit-view3.engine.ts b/src/view-engine/wf-dyna-edit-view3.engine.ts new file mode 100644 index 0000000000000000000000000000000000000000..b45b066f0c7ad4a86e5fbb1ffe9d80d0ab0ad8ad --- /dev/null +++ b/src/view-engine/wf-dyna-edit-view3.engine.ts @@ -0,0 +1,39 @@ +/* eslint-disable no-restricted-syntax */ +import { + ViewController, + IWFDynaEditView3State, + IWFDynaEditView3Event, + Srfuf, +} from '@ibiz-template/runtime'; +import { IAppDEWFDynaEditView } from '@ibiz/model-core'; +import { WFDynaEditViewEngine } from './wf-dyna-edit-view.engine'; + +export class WFDynaEditView3Engine extends WFDynaEditViewEngine { + /** + * 视图控制器 + * + * @protected + * @type {ViewController} + * @memberof WFDynaEditView3Engine + */ + protected declare view: ViewController< + IAppDEWFDynaEditView, + IWFDynaEditView3State, + IWFDynaEditView3Event + >; + + /** + * 是否是新建数据 + * + * @author lxm + * @date 2022-08-31 22:08:44 + * @type {boolean} + */ + isNewData: boolean = true; + + async load() { + const data = await super.load(); + this.isNewData = data.srfuf === Srfuf.CREATE; + return data; + } +} diff --git a/src/view-engine/wf-edit-view.engine.ts b/src/view-engine/wf-edit-view.engine.ts new file mode 100644 index 0000000000000000000000000000000000000000..573455b2bc462c576be2c08768a6e55237ce82c5 --- /dev/null +++ b/src/view-engine/wf-edit-view.engine.ts @@ -0,0 +1,118 @@ +import { RuntimeModelError } from '@ibiz-template/core'; +import { + ViewController, + IWFEditViewState, + IWFEditViewEvent, +} from '@ibiz-template/runtime'; +import { IAppDEWFEditView, IDEEditForm } from '@ibiz/model-core'; +import { EditViewEngine } from './edit-view.engine'; + +export class WFEditViewEngine extends EditViewEngine { + /** + * 视图控制器 + * + * @protected + * @type {ViewController} + * @memberof WFEditViewEngine + */ + protected declare view: ViewController< + IAppDEWFEditView, + IWFEditViewState, + IWFEditViewEvent + >; + + /** + * 流程表单是否可编辑 + * + * @author lxm + * @date 2022-09-29 15:09:16 + * @type {boolean} + */ + isEditable: boolean = false; + + /** + * 当前激活表单模型 + * + * @author lxm + * @date 2022-09-29 17:09:44 + * @type {IDEEditForm} + */ + activeForm?: IDEEditForm; + + /** + * 是否已经完成视图的第一次加载 + * + * @author lxm + * @date 2022-09-29 17:09:49 + * @type {boolean} + */ + isFirstLoaded: boolean = false; + + async doCreated() { + await super.doCreated(); + // 第一次计算 + await this.calcActiveForm(); + } + + /** + * 加载 + * @return {*} + * @author: zhujiamin + * @Date: 2023-06-09 15:18:51 + */ + async load() { + const res = await super.load(); + this.isFirstLoaded = true; + return res; + } + + /** + * 刷新页面 + * + * @author lxm + * @date 2022-09-29 15:09:03 + * @returns {*} {Promise} + */ + async refresh() { + const previous = this.activeForm; + await this.calcActiveForm(); + // 表单没有变化的时候调用表单的刷新 + if (previous === this.activeForm) { + await super.refresh(); + } + } + + /** + * 计算当前步骤的表单 + * + * @author lxm + * @date 2022-09-29 15:09:07 + * @returns {*} {Promise} + */ + async calcActiveForm(): Promise { + const app = ibiz.hub.getApp(this.view.context.srfappid); + const entityService = await app.deService.getService( + this.view.model.appDataEntityId!, + ); + const res = await entityService.wf.getWFStep(this.view.params); + + this.isEditable = res.data.isEditable === 'true'; + const processForm = res.data['process-form'] + ? `wfform_${res.data['process-form']}` + : 'form'; + const formModel = this.view.model.viewLayoutPanel!.controls?.find( + control => { + return control.name === processForm.toLowerCase(); + }, + ); + if (!formModel) { + throw new RuntimeModelError(`找不到表单${processForm}的模型`); + } + this.activeForm = formModel; + + if (!this.view.slotProps.form) { + this.view.slotProps.form = {}; + } + this.view.slotProps.form.modelData = this.activeForm as IData; + } +}