import { getPSUIActionByModelObject, IPSAppDataEntity, IPSAppDEField, IPSAppDERedirectView, IPSAppDEUIAction, IPSAppDEView, IPSAppView, IPSAppViewRef, IPSNavigateContext, IPSNavigateParam, } from '@ibizstudio/runtime'; import { LogUtil, ModelTool, StringUtil, UIActionTool, Util, ViewTool, AppServiceBase } from '@ibizstudio/runtime'; import { UIServiceRegister } from '@ibizstudio/runtime'; import { Observable, Subject } from 'rxjs'; import { AppGlobalService } from '../app-service'; import { AppPopover, AppModal, AppDrawer, NoticeHandler, appPopup } from '../utils'; import { AppDEUIAction } from './app-ui-action'; import { UIActionResult } from './appuilogic'; import { winMsg } from '../ibz-studio-plugins'; import { notNilEmpty } from 'qx-util'; /** * 应用设计前端界面行为 * * @export * @class AppDesignFrontAction * @extends {AppDEUIAction} */ export class AppDesignFrontAction extends AppDEUIAction { /** * 抽屉打开 * * @type {AppDrawer} * @memberof AppDesignFrontAction */ $appdrawer: AppDrawer = AppDrawer.getInstance(); /** * 模态打开 * * @type {AppModal} * @memberof AppDesignFrontAction */ $appmodal: AppModal = AppModal.getInstance(); /** * 气泡打开 * * @type {AppPopover} * @memberof AppDesignFrontAction */ $apppopover: AppPopover = AppPopover.getInstance(); /** * 路由对象 * * @type {*} * @memberof AppDesignFrontAction */ $router: any = AppServiceBase.getInstance().getRouter(); /** * 初始化AppFrontAction * * @memberof AppFrontAction */ constructor(opts: IPSAppDEUIAction, context?: any) { super(opts, context); } /** * 执行界面行为 * * @param {any[]} args * @param {*} [context={}] * @param {*} [params={}] * @param {*} [$event] * @param {*} [xData] * @param {*} [actionParam] * @param {string} [srfParentDeName] * @param {*} [deUIService] * @return {*} * @memberof AppDesignFrontAction */ async execute(args: any[], context: any = {}, params: any = {}, $event?: any, xData?: any, actionParam?: any, srfParentDeName?: string, deUIService?: any) { if (Object.is(this.actionModel?.uILogicAttachMode, 'REPLACE')) { if (actionParam.context) { Object.assign(context, actionParam.context); } return this.executeDEUILogic(args, context, params, $event, xData, actionParam, srfParentDeName); } const actionTarget: string | null = this.actionModel.actionTarget; if (Object.is(actionTarget, 'MULTIDATA')) { NoticeHandler.errorHandler('多数据主键不支持'); } else { // 处理数据 let data: any = {}; let tempData: any = {}; let parentContext: any = {}; let parentViewParam: any = {}; if (this.actionModel.saveTargetFirst) { const result: any = await xData.save(args, false); if (Object.is(actionTarget, 'SINGLEDATA')) { Object.assign(args[0], result.data); } else { args = [result.data]; } } const _args: any[] = Util.deepCopy(args); if (this.actionModel.getPSAppDataEntity() && (Object.is(actionTarget, 'SINGLEKEY') || Object.is(actionTarget, 'MULTIKEY'))) { const entityName = this.actionModel.getPSAppDataEntity()?.codeName.toLowerCase(); const key = (ModelTool.getAppEntityKeyField(this.actionModel.getPSAppDataEntity()) as IPSAppDEField)?.codeName.toLowerCase(); const majorKey = (ModelTool.getAppEntityMajorField(this.actionModel.getPSAppDataEntity()) as IPSAppDEField)?.codeName.toLowerCase(); if (_args[0]?.[key]) { Object.assign(context, { [entityName!]: `%${key}%` }); } else { Object.assign(context, { [entityName!]: `%${entityName}%` }); } Object.assign(params, { [key!]: `%${key}%` }); Object.assign(params, { [majorKey]: `%${majorKey}%` }); } else if (Object.is(actionTarget, 'SINGLEDATA')) { data = args[0]; } // 自定义导航参数优先级大于预置导航参数 if (this.actionModel.getPSNavigateContexts() && (this.actionModel.getPSNavigateContexts() as IPSNavigateContext[]).length > 0) { const localContext = Util.formatNavParam(this.actionModel.getPSNavigateContexts()); Object.assign(context, localContext); } if (this.actionModel.getPSNavigateParams() && (this.actionModel.getPSNavigateParams() as IPSNavigateParam[]).length > 0) { const localParam = Util.formatNavParam(this.actionModel.getPSNavigateParams()); Object.assign(params, localParam); } if (actionParam.context) { parentContext = actionParam.context; } if (actionParam.viewparams) { parentViewParam = actionParam.viewparams; } context = UIActionTool.handleContextParam(actionTarget, _args, parentContext, parentViewParam, context); if (Object.is(actionTarget, 'SINGLEDATA')) { tempData = UIActionTool.handleActionParam(actionTarget, _args, parentContext, parentViewParam, params); Object.assign(data, tempData); } else { data = UIActionTool.handleActionParam(actionTarget, _args, parentContext, parentViewParam, params); } context = Object.assign({}, actionParam.context, context); // 构建srfparentdename和srfparentkey let parentObj: any = { srfparentdename: srfParentDeName ? srfParentDeName : null, srfparentkey: srfParentDeName ? context[srfParentDeName.toLowerCase()] : null, }; Object.assign(data, parentObj); Object.assign(context, parentObj); const frontPSAppView: IPSAppView | null = this.actionModel.getFrontPSAppView(); return this.oPenView(frontPSAppView, actionParam, context, args, deUIService, params, $event, data, xData, _args); } } /** * 打开视图 * * @param {*} frontPSAppView * @param {*} actionParam * @param {*} context * @param {*} args * @param {*} deUIService * @param {*} params * @param {*} $event * @param {*} data * @param {*} xData * @param {*} _args * @return {*} {Promise} * @memberof AppDesignFrontAction */ async oPenView(frontPSAppView: any, actionParam: any, context: any, args: any, deUIService: any, params: any, $event: any, data: any, xData: any, _args: any): Promise { return new Promise(async (resolve: any, reject: any) => { //打开视图后续逻辑 const openViewNextLogic: any = async (actionModel: any, actionParam: any, xData: any, resultDatas?: any) => { if (actionModel.reloadData && xData && xData.refresh && xData.refresh instanceof Function) { if (args && args.length > 0) { Object.assign(args[0], { refreshMode: actionModel.refreshMode }); } else { args.push({ refreshMode: actionModel.refreshMode }); } xData.refresh(args); } if (actionModel.closeEditView) { actionParam.closeView(null); } // 后续界面行为 if (this.actionModel.M?.getNextPSUIAction) { const nextUIaction: any = await getPSUIActionByModelObject(this.actionModel); if (nextUIaction.getPSAppDataEntity()) { let [tag, appDeName] = (nextUIaction as IPSAppDEUIAction).id.split('@'); const UIService = await UIServiceRegister.getService(actionParam.context, `${appDeName.toLowerCase()}`); await UIService.loaded(); if (UIService) { return UIService.excuteAction(tag, resultDatas, context, params, $event, xData, actionParam, undefined, UIService); } } else { return (AppGlobalService.getInstance() as any).executeGlobalAction(nextUIaction.id, resultDatas, context, params, $event, xData, actionParam, undefined); } } else { if (Object.is(actionModel?.uILogicAttachMode, 'AFTER')) { if (actionParam.context) { Object.assign(context, actionParam.context); } return this.executeDEUILogic(args, context, params, $event, xData, actionParam, context?.srfparentdename); } else { return new UIActionResult({ ok: true, result: resultDatas }); } } }; if (Object.is(this.actionModel.frontProcessType, 'OPENHTMLPAGE') && this.actionModel.htmlPageUrl) { const url = StringUtil.fillStrData(this.actionModel.htmlPageUrl, context, data); window.open(url, '_blank'); resolve(new UIActionResult({ ok: true, result: data })); // 打开顶级视图,打开顶级视图或向导(模态) } else if (Object.is(this.actionModel.frontProcessType, 'TOP') || Object.is(this.actionModel.frontProcessType, 'WIZARD')) { if (!this.actionModel.getFrontPSAppView()) { NoticeHandler.warningHandler(`${this.actionModel.caption} 无打开视图`); return; } await frontPSAppView?.fill(true); if (!frontPSAppView) { return; } // 准备deResParameters参数和parameters参数 let deResParameters: any[] = []; let parameters: any[] = []; if (frontPSAppView.getPSAppDataEntity()) { // 处理视图关系参数 (只是路由打开模式才计算) if (!frontPSAppView.openMode || frontPSAppView.openMode == 'INDEXVIEWTAB' || frontPSAppView.openMode == 'POPUPAPP') { deResParameters = Util.formatAppDERSPath(context, (frontPSAppView as IPSAppDEView).getPSAppDERSPaths()); } } if (!frontPSAppView.openMode || frontPSAppView.openMode == 'INDEXVIEWTAB' || frontPSAppView.openMode == 'POPUPAPP') { if (frontPSAppView.getPSAppDataEntity()) { parameters = [ { pathName: Util.srfpluralize((frontPSAppView.getPSAppDataEntity() as IPSAppDataEntity)?.codeName).toLowerCase(), parameterName: (frontPSAppView.getPSAppDataEntity() as IPSAppDataEntity)?.codeName.toLowerCase(), }, { pathName: 'views', parameterName: ((frontPSAppView as IPSAppDEView).getPSDEViewCodeName() as string).toLowerCase(), }, ]; } else { parameters = [{ pathName: 'views', parameterName: frontPSAppView.codeName.toLowerCase() }]; } } else { if (frontPSAppView.getPSAppDataEntity()) { parameters = [ { pathName: Util.srfpluralize((frontPSAppView.getPSAppDataEntity() as IPSAppDataEntity)?.codeName).toLowerCase(), parameterName: (frontPSAppView.getPSAppDataEntity() as IPSAppDataEntity)?.codeName.toLowerCase(), }, ]; } if (frontPSAppView && frontPSAppView.modelPath) { Object.assign(context, { viewpath: frontPSAppView.modelPath }); } } // 打开重定向视图 if (frontPSAppView.redirectView) { const data = args[0]; const field: IPSAppDEField | null = (frontPSAppView as IPSAppDERedirectView).getTypePSAppDEField(); if (frontPSAppView.codeName === 'PSSysAppLinkRedirectView') { const type = context.linktype; if (notNilEmpty(type)) { winMsg.openView(type, context, params, [data]); } else { console.warn(`未找到对应重定向类型 ${type} ,暂时无法打开iframe级别视图跳转!`); } return; } if (field) { const type = data[field.codeName.toLocaleLowerCase()]; const appViewRefs = (frontPSAppView as IPSAppDERedirectView).getRedirectPSAppViewRefs()!; let appViewRef: IPSAppViewRef | undefined = appViewRefs?.find((appViewRef: IPSAppViewRef) => appViewRef.name === type || appViewRef.name === `EDITVIEW:${type}`); if (!appViewRef) { appViewRef = appViewRefs?.find((appViewRef: IPSAppViewRef) => { const entityName = frontPSAppView.getPSAppDataEntity()?.name; return appViewRef.name === type || appViewRef.name === `${entityName}:EDITVIEW:${type}`; }); } if (appViewRef) { const appView: any = await appViewRef.getRefPSAppView()?.fill(); const localContext = Util.formatNavParam(appViewRef.getPSNavigateContexts()); for (let key in localContext) { localContext[key] = StringUtil.fillStrData(localContext[key], context); } Object.assign(context, localContext); return this.oPenView(appView, actionParam, context, args, deUIService, params, $event, data, xData, _args); } } } else if (!frontPSAppView.openMode || frontPSAppView.openMode == 'INDEXVIEWTAB') { const routePath = ViewTool.buildUpRoutePath(this.$router.currentRoute, context, deResParameters, parameters, _args, data); this.$router.push(routePath); resolve(openViewNextLogic(this.actionModel, actionParam, xData, data)); } else if (frontPSAppView.openMode == 'POPUPAPP') { const routePath = ViewTool.buildUpRoutePath(this.$router.currentRoute, context, deResParameters, parameters, _args, data); window.open('./#' + routePath, '_blank'); resolve(openViewNextLogic(this.actionModel, actionParam, xData, data)); } else if (frontPSAppView.openMode == 'POPUPMODAL') { const view: any = { viewname: 'app-view-shell', height: frontPSAppView.height, width: frontPSAppView.width, title: frontPSAppView.caption, }; let container: Subject = this.$appmodal.openModal(view, context, data, args); container.subscribe((result: any) => { if (!result || !Object.is(result.ret, 'OK')) { return; } resolve(openViewNextLogic(this.actionModel, actionParam, xData, result.datas)); }); } else if (frontPSAppView.openMode?.indexOf('DRAWER') !== -1) { const view: any = { viewname: 'app-view-shell', height: frontPSAppView.height, width: frontPSAppView.width, title: frontPSAppView.caption, placement: frontPSAppView.openMode, }; let container: Subject = this.$appdrawer.openDrawer(view, Util.getViewProps(context, data, args)); container.subscribe((result: any) => { if (!result || !Object.is(result.ret, 'OK')) { return; } resolve(openViewNextLogic(this.actionModel, actionParam, xData, result.datas)); }); } else if (frontPSAppView.openMode === 'POPUP') { const view: any = { viewname: 'app-view-shell', height: frontPSAppView.height, width: frontPSAppView.width, title: frontPSAppView.caption, placement: frontPSAppView.openMode, }; const container = appPopup.openDrawer(view, Util.getViewProps(context, data, args)); container.subscribe((result: any) => { if (!result || !Object.is(result.ret, 'OK')) { return; } resolve(openViewNextLogic(this.actionModel, actionParam, xData, result.datas)); }); } else if (frontPSAppView.openMode == 'POPOVER') { const view: any = { viewname: 'app-view-shell', height: frontPSAppView.height, width: frontPSAppView.width, title: frontPSAppView.caption, placement: frontPSAppView.openMode, }; let container: Observable = this.$apppopover.openPop($event, view, context, data, 'left-end', true, args); container.subscribe((result: any) => { if (!result || !Object.is(result.ret, 'OK')) { return; } resolve(openViewNextLogic(this.actionModel, actionParam, xData, result.datas)); }); } else { NoticeHandler.warningHandler(`${frontPSAppView.title} 不支持该模式打开`); } // 用户自定义 } else { LogUtil.warn(`${this.actionModel.caption}自定义界面行为空执行`); resolve(openViewNextLogic(this.actionModel, actionParam, xData, data)); } }); } }