import Vue from 'vue'; import qs from 'qs'; import { IPSAppView } from '@ibiz/dynamic-model-api'; import { AppServiceBase, GetModelService, SandboxInstance, Util } from 'ibiz-core'; import { AppNavHistory, ViewCacheService } from '../app-service'; import { CommunicationService } from '@ibiz/model-location'; /** * 视图容器基类 * * @export * @class ViewContainerBase * @extends {Vue} */ export class ViewContainerBase extends Vue { /** * 部件静态参数 * * @memberof ViewContainerBase */ public staticProps!: any; /** * 部件动态参数 * * @memberof ViewContainerBase */ public dynamicProps!: any; /** * 动态模型文件路径 * * @public * @type {StringConstructor} * @memberof ViewContainerBase */ public dynaModelFilePath: string = ''; /** * 视图标识 * * @type {string} * @memberof ViewContainerBase */ public viewtag: string = ''; /** * 视图容器 * * @type {any} * @memberof ViewContainerBase */ public viewContainerName: string = ''; /** * 临时动态视图上下文环境参数 * * @type {ViewContext} * @memberof ViewBase */ public tempViewContext: any = {}; /** * 动态视图上下文环境参数 * * @type {*} * @memberof ViewBase */ public viewContext: any = {}; /** * 模型数据实例 * * @type {boolean} * @memberof ViewContainerBase */ public modeldata!: IPSAppView; /** * 应用上下文 * * @type {*} * @memberof ViewContainerBase */ public context: any = {}; /** * @description 服务实例 * @protected * @type {(CommunicationService | null)} * @memberof ViewContainerBase */ protected eventInstance: CommunicationService | null = null; created(): void { const env = AppServiceBase.getInstance().getAppEnvironment(); if (env.devMode) { this.selfPreview = this.selfPreview.bind(this); this.eventInstance = CommunicationService.getInstance(); this.eventInstance.evt.on('preview-view', this.selfPreview); } } destroyed(): void { const env = AppServiceBase.getInstance().getAppEnvironment(); if (env.devMode && this.eventInstance) { this.eventInstance.evt.off('preview-view', this.selfPreview); } } protected async selfPreview(res: any): Promise<void> { const model = res.model; if (model.dynaModelFilePath === this.dynaModelFilePath) { const s = await GetModelService(this.context); s.store.modelObject.delete(model.dynaModelFilePath); const view = await s.getPSAppView(model); this.initViewContext({ modeldata: view }); this.viewContainerName = ''; setTimeout(() => { // 发布扩展视图专用 if(Object.is(view?.viewStyle,'EXTEND')){ this.viewContainerName = Util.srfFilePath2(view?.codeName); }else{ this.viewContainerName = AppServiceBase.getInstance().getAppComponentService().getViewComponents( view?.viewType, view?.viewStyle, view?.getPSSysPFPlugin?.pluginCode, ); } this.$forceUpdate(); }, 100); this.$forceUpdate(); } } /** * 视图容器初始化 * * @memberof ViewContainerBase */ public async ViewContainerInit() { if (this.dynamicProps && this.dynamicProps.viewdata) { if (typeof this.dynamicProps.viewdata == 'string') { this.context = JSON.parse(this.dynamicProps.viewdata); } else { this.context = Util.deepCopy(this.dynamicProps.viewdata); } // 初始化沙箱实例 if (this.context && this.context.hasOwnProperty('srfsandboxtag')) { await this.initSandBoxInst(this.context); } } await this.computeDynaModelFilePath(); // 路由打开 if (this.$route && this.$route.fullPath && this.$route.fullPath.indexOf('?') > -1) { let tempViewParam: any = {}; const tempViewparam: any = this.$route.fullPath.slice(this.$route.fullPath.indexOf('?') + 1); const viewparamArray: Array<string> = decodeURIComponent(tempViewparam).split(';'); if (viewparamArray.length > 0) { viewparamArray.forEach((item: any) => { Object.assign(tempViewParam, qs.parse(item)); }); } // 初始化沙箱实例 if (tempViewParam && tempViewParam.hasOwnProperty('srfsandboxtag')) { await this.initSandBoxInst(tempViewParam); } // 补充沙箱实例参数(路由) if (tempViewParam && tempViewParam.hasOwnProperty('srfsandboxtag')) { Object.assign(this.context, { 'srfsandboxtag': tempViewParam.srfsandboxtag }); } } this.loadDynamicModelData(); } /** * 初始化沙箱实例 * * @memberof ViewContainerBase */ public async initSandBoxInst(args: any) { if (args && args.srfsandboxtag) { const tempSandboxInst: SandboxInstance = new SandboxInstance(args); await tempSandboxInst.initSandBox(); } } /** * 加载动态模型数据 * * @type {Array<*>} * @memberof ViewContainerBase */ public async loadDynamicModelData() { if (this.staticProps && this.staticProps.viewModelData) { this.modeldata = this.staticProps.viewModelData; } else { if (this.dynaModelFilePath) { this.modeldata = await ((await GetModelService(this.context)).getPSAppView(this.dynaModelFilePath)) as IPSAppView; } } // 未找到模型数据跳转404页面 if (Util.isEmpty(this.modeldata)) { this.$router.push('/404'); return; } // 视图壳加载视图数据 await this.modeldata?.fill?.(true); this.initViewContext({ modeldata: this.modeldata }); this.initViewMateInfo(this.modeldata); // 发布扩展视图专用 if(Object.is(this.modeldata?.viewStyle,'EXTEND')){ this.viewContainerName = Util.srfFilePath2(this.modeldata?.codeName); }else{ this.viewContainerName = AppServiceBase.getInstance().getAppComponentService().getViewComponents( this.modeldata?.viewType, this.modeldata?.viewStyle, this.modeldata?.getPSSysPFPlugin()?.pluginCode, ); } this.$forceUpdate(); } /** * 初始化动态视图上下文环境参数 * * @type {*} opts * @memberof ViewContainerBase */ public initViewContext(opts: any) { let temp: any = {}; Object.defineProperty(temp, 'modeldata', { enumerable: false, writable: true }); Object.assign(temp, this.tempViewContext, opts, { viewtag: this.viewtag, viewcontainer: this.context, ...this.staticProps, }); // 删除viewModelData,避免递归 if (temp.viewModelData) { delete temp.viewModelData; } this.viewContext = temp; } /** * 初始化视图容器元数据 * * @type {*} opts * @memberof ViewContainerBase */ public initViewMateInfo(opts: any) { if (!this.dynamicProps || !this.dynamicProps.viewdata) { ViewCacheService.setViewCache(opts, this.$route.fullPath); const initNavData: Function = () => { if (this.$route.meta && !this.$route.meta.ignoreAddPage) { let navHistory: AppNavHistory = AppServiceBase.getInstance().getAppNavDataService(); if (!navHistory) { AppServiceBase.getInstance().setAppNavDataService(new AppNavHistory); navHistory = AppServiceBase.getInstance().getAppNavDataService(); } navHistory.add(this.$route); } } // 设置路由meta数据 let activedView: any = this.$route.meta.parameters.find((item: any) => { return item.pathName === 'views'; }); if (Object.is(activedView.parameterName, 'view') && Object.is(activedView.pathName, 'views')) { this.$route.meta.captionTag = opts.getCapPSLanguageRes()?.lanResTag; this.$route.meta.caption = opts?.caption; this.$route.meta.imgPath = opts?.getPSSysImage()?.imagePath; this.$route.meta.iconCls = opts?.getPSSysImage()?.cssClass; if (opts.accUserMode && ((opts.accUserMode == 0) || (opts.accUserMode == 3))) { this.$route.meta.requireAuth = false; } else { this.$route.meta.requireAuth = true; } this.$store.commit("setCurPageCaption", { route: this.$route, caption: this.$route.meta.caption, captionTag: opts.getCapPSLanguageRes()?.lanResTag, info: '', }); initNavData(); } else { initNavData(); } } } /** * 处理部件事件 * * @memberof ViewContainerBase */ public handleViewEvent(opts: any) { if (opts.action) { this.$emit(opts.action, opts.data ? opts.data : null, opts.viewName); } } /** * 计算视图动态路径 * * @memberof ViewContainerBase */ public async computeDynaModelFilePath() { if (this.dynamicProps && this.dynamicProps.viewdata) { // 嵌入视图 if (this.context.viewpath) { this.dynaModelFilePath = this.context.viewpath; delete this.context.viewpath; } } else { // 路由打开 if (this.$route && this.$route.meta && this.$route.meta.parameters) { let resource: string = this.$route.meta.resource ? this.$route.meta.resource.toLowerCase() : ''; let activedView: any = this.$route.meta.parameters.find((item: any) => { return item.pathName === 'views'; }); let localActivedView: any = Util.deepCopy(activedView); if (Object.is(localActivedView.parameterName, 'view') && Object.is(localActivedView.pathName, 'views')) { localActivedView.parameterName = this.parseUrlDynamicParam().view; } if (localActivedView && localActivedView.parameterName) { const path = (await GetModelService(this.context)).getPSAppViewPath(`${resource}${localActivedView.parameterName}`); if (path) { this.dynaModelFilePath = path; } } } } } /** * 解析路由动态参数 * * @memberof ViewContainerBase */ public parseUrlDynamicParam(): any { const path = (this.$route.matched[this.$route.matched.length - 1]).path; const keys: Array<any> = []; const curReg = (this as any).$pathToRegExp.pathToRegexp(path, keys); const matchArray = curReg.exec(this.$route.path); let tempValue: Object = {}; keys.forEach((item: any, index: number) => { if (matchArray[index + 1]) { Object.defineProperty(tempValue, item.name, { enumerable: true, value: decodeURIComponent(matchArray[index + 1]) }); } }); return tempValue; } }