import { immutable, circular, action, excludedInJSON } from '../decorators'; import { config, history, LEVEL_ENUM, Vertex, Entity, Enum, PackageJSON, App, WebService, View, utils, Interface, updateDataTypeList, Structure, ActionOptions } from '..'; import pageService from '../../service/page'; import { traverse } from '../utils'; import { postServiceType } from '../../service/common/preprocess'; /** * 页面(入口页)类,后端路由控制 * @category page */ export class Page extends Vertex { /** * 概念类型 */ @immutable() public readonly level: LEVEL_ENUM = LEVEL_ENUM.page; /** * 页面 Id */ @immutable() public readonly id: string = undefined; /** * 页面名称 */ @immutable() public readonly name: string = undefined; /** * 页面标题 */ @immutable() public readonly title: string = undefined; /** * 是否接入权限 */ @immutable() public readonly auth: boolean = undefined; /** * 是否为首页 */ @immutable() public readonly isIndex: boolean = undefined; /** * 根页面视图 */ @immutable() public readonly rootView: View = undefined; /** * 所属前端服务 Id */ @immutable() public readonly serviceId: string = undefined; /** * 所属前端服务 */ @circular() @immutable() public readonly service: WebService = undefined; /** * 树组件的子节点字段 */ @excludedInJSON() @immutable() public readonly childrenField: string = 'rootView.children'; /** * 树组件的子节点字段 */ @excludedInJSON() @immutable() public readonly moreChildrenFields: Array = ['rootView.$def.params', 'rootView.$def.variables', 'rootView.$def.logics']; /** * @param source 需要合并的部分参数 */ constructor(source?: Partial) { super(); source && this.assign(source); } /** * 加载页面详情 * @requires this.id */ async load() { const result = await pageService.loadPage({ path: { id: this.id, }, }); this.assign(result); traverse((current) => { if (current.parent) { const view = current.parent.children[current.index] = new View(current.node); view.assign({ page: this, parent: current.parent }); // view.parseAll(); } }, { node: this.rootView }); const rootView = new View(this.rootView); rootView.assign({ page: this }); this.assign({ rootView }); } addData(res: any) { const microService = this.service.app.firstMicroService; const interfaces = res.interfaces as Array; if (interfaces && interfaces.length) { interfaces.forEach((item, index) => { const itface = interfaces[index] = Interface.from(item, microService); postServiceType(itface); }); microService.interfaces.unshift(...interfaces); microService.globalLogic.globalLogics.unshift(...interfaces); microService.emit('interfacesChange'); } const enums = res.enums as Array; if (enums && enums.length) { enums.forEach((item, index) => enums[index] = Enum.from(item, microService)); microService.data.enums.unshift(...enums); updateDataTypeList(); } const entities = res.entities as Array; if (entities && entities.length) { entities.forEach((item, index) => entities[index] = Entity.from(item, microService)); microService.data.entities.unshift(...entities); updateDataTypeList(); } const structures = res.structures as Array; if (structures && structures.length) { structures.forEach((item, index) => structures[index] = Structure.from(item, microService)); microService.data.structures.unshift(...structures); updateDataTypeList(); } } /** * 添加页面 */ @action('导入页面') async importPage(none?: void, actionOptions?: ActionOptions, then?: () => Promise) { config.defaultApp?.emit('saving'); const body = this.toJSON(); utils.logger.debug('添加页面', body); const result = await pageService.importPage({ headers: { appId: config.defaultApp?.id, operationAction: actionOptions?.actionName || 'Page.create', operationDesc: actionOptions?.actionDesc || `添加页面"${this.name}${this.title ? `(${this.title})` : ''}"`, }, body, }); this.deepPick(result.page, ['id']); // 添加数据和接口 this.addData(result); const rootView = View.from(result.page.rootView, null, this); rootView.assign({ tempPath: `/${rootView.name}`, code: `/ID_${rootView.id}`, }); // page 添加一次 rootView this.assign({ rootView }); // Destination选择页面时用的是page的code,这里需要赋值下 this.assign({ tempPath: `/${rootView.name}`, code: `/ID_${rootView.id}`, }); this.rootView.attachNodePath(); if(result.page.isIndex) { const tasks = this.service.pages.filter((page) => page.isIndex && page.id !== result.page.id) .map((page) => { page.assign({ isIndex: false }); return page.update(); }); Promise.all(tasks); } await then?.(); this.service.emit('pageTreeChange'); const microService = this.service.app.firstMicroService; microService.emit('dataTypesChange'); microService.emit('enumsChange'); microService.emit('vertexIdToNameChange'); this.rootView.emit('change'); // this.assign(Page.from(this, this.service)); await config.defaultApp?.history.load(); config.defaultApp?.emit('saved'); return this; } /** * 添加页面 */ @action('添加页面') async create(none?: void, actionOptions?: ActionOptions, then?: () => Promise) { config.defaultApp?.emit('saving'); const body = this.toJSON(); utils.logger.debug('添加页面', body); const result = await pageService.addPage({ headers: { appId: config.defaultApp?.id, operationAction: actionOptions?.actionName || 'Page.create', operationDesc: actionOptions?.actionDesc || `添加页面"${this.name}${this.title ? `(${this.title})` : ''}"`, }, body, }); this.deepPick(result, ['id']); this.rootView.attachNodePath(); if(result.isIndex) { const tasks = this.service.pages.filter((page) => page.isIndex && page.id !== result.id) .map((page) => { page.assign({ isIndex: false }); return page.update(); }); Promise.all(tasks); } await then?.(); this.service.emit('pageTreeChange'); this.rootView.emit('change'); // this.assign(Page.from(this, this.service)); await config.defaultApp?.history.load(); config.defaultApp?.emit('saved'); return this; } /** * 删除页面 */ @action('删除页面') async delete(none?: void, actionOptions?: ActionOptions) { config.defaultApp?.emit('saving'); try { await pageService.removePage({ headers: { appId: config.defaultApp?.id, operationAction: actionOptions?.actionName || 'Page.delete', operationDesc: actionOptions?.actionDesc || `删除页面"${this.name}${this.title ? `(${this.title})` : ''}"`, }, path: { id: this.id, }, }); } catch(err) { await config.defaultApp?.history.load(); throw err; } const index = this.service.pages.indexOf(this); ~index && this.service.pages.splice(index, 1); this.destroy(); this.service.emit('pageTreeChange'); await config.defaultApp?.history.load(); config.defaultApp?.emit('saved'); } /** * 修改页面 */ async update(none?: void, actionOptions?: ActionOptions, then?: () => Promise) { config.defaultApp?.emit('saving'); const body = this.toPlainJSON(); utils.logger.debug('修改页面', body); const result = await pageService.update({ headers: { appId: config.defaultApp?.id, operationAction: actionOptions?.actionName || 'Page.delete', operationDesc: actionOptions?.actionDesc || `修改页面"${this.name}${this.title ? `(${this.title})` : ''}"`, }, body, }); await config.defaultApp?.history.load(); config.defaultApp?.emit('saved'); return this; } /** * 设为首页 */ @action('设为首页') async setAsIndex() { config.defaultApp?.emit('saving'); const tasks = this.service.pages.filter((page) => page.isIndex) .map((page) => { page.assign({ isIndex: false }); return page.update(); }); this.assign({ isIndex: true }); tasks.push(this.update(undefined, { actionDesc: `设置页面"${this.name}"为首页`, })); await Promise.all(tasks); this.service.emit('pageTreeChange'); await config.defaultApp?.history.load(); config.defaultApp?.emit('saved'); } /** * 设置是否开启权限控制 */ @action('设置是否开启权限控制') async setAuth(auth: boolean) { this.assign({ auth }); await this.update(undefined, { actionDesc: `设置${this.auth ? '开启' : '关闭'}页面"${this.name}"权限控制`, }); } // /** // * 加载子页面详情 // * @requires this.id // * @deprecated // */ // async loadViewTree() { // let rootView = await pageService.loadViewTree({ // query: { // id: this.id, // }, // config: { // mock: config.mock, // }, // }); // traverse((current) => { // if (current.parent) { // const view = current.parent.children[current.index] = new View(current.node); // view.assign({ page: this, parent: current.parent }); // view.parseAll(); // } // }, { node: rootView, parent: null, index: null, nodePath: '' }); // rootView = new View(rootView); // rootView.parseAll(); // this.assign({ rootView }); // return rootView; // } /** * 从后端 JSON 生成规范的 Param 对象 */ public static from(source: any, service: WebService) { const page = new Page(source); page.assign({ rootView: View.from(page.rootView, null, page), service, tempPath: page.rootView? `/${page.rootView.name}`: '', code: page.rootView?`/ID_${page.rootView.id}`: '', }); return page; } } export default Page;