import { excludedInJSON, immutable } from '../decorators'; import { LEVEL_ENUM, Vertex, Service, WebService, MicroService, SERVICE_TYPE, utils, History, updateGenericTypeList } from '..'; import appService from '../../service/app'; interface AppLoadAllOptions { asyncLoadServicesDetail?: boolean, asyncLoadViewsDetail?: boolean, } /** * 应用类 * @example OA * @category App */ export class App extends Vertex { /** * 概念类型 */ @immutable() public readonly level: LEVEL_ENUM = LEVEL_ENUM.app; /** * App Id */ @immutable() public readonly id: string = undefined; /** * Alias of id */ @immutable() public readonly appId: string = undefined; /** * 应用标识 */ @immutable() public readonly name: string = undefined; /** * 应用标题 */ @immutable() public readonly title: string = undefined; /** * 应用图标 */ @immutable() public readonly icon: string = undefined; /** * 应用描述 */ @immutable() public readonly description: string = undefined; /** * 域名 */ @immutable() public readonly dnsAddr: string = undefined; /** * 官方类型 */ @immutable() public readonly officialType: 'offical' | 'nonofficial'; /** * IDE 版本 */ @immutable() public readonly ideVersion: string = undefined; /** * 轻舟项目 Id */ @immutable() public readonly projectId: string = undefined; /** * 租户 Id */ @immutable() public readonly tenantId: string = undefined; /** * 租户 Id */ @immutable() public readonly userGroupId: string = undefined; /** * h5 pc type */ @immutable() public readonly scope: 'pc' | 'h5' = undefined; /** * 发布状态 */ @immutable() public readonly deploying: string = undefined; /** * 发布 Id,用于获取CICD详情 */ @immutable() public readonly deploymentId: string = undefined; /** * 应用下的服务 */ @immutable() public readonly services: Array = []; /** * 首个 Web 服务 * 后续 App 创建不了多个模块了,默认处理该服务 */ @immutable() public readonly firstWebService: WebService = undefined; /** * 首个 Web 服务 * 后续 App 创建不了多个模块了,默认处理该服务 */ @immutable() public readonly firstMicroService: MicroService = undefined; /** * 历史记录 * 用于处理撤销重做 */ @immutable() @excludedInJSON() public readonly history: History = undefined; /** * @param source 需要合并的部分参数 */ constructor(source?: Partial) { super(); source && this.assign(source); this.history = new History({ app: this }); } /** * 加载详情并同步 envList 信息 * @requires this.id */ async loadEnvList(appDetail: any) { if (!appDetail) { appDetail = await appService.loadApp({ query: { id: this.id, }, }); } const { envList } = appDetail.services .find((service: any) => service.type === 'microService') || {}; this.assign({ envList }); } /** * 加载详情并同步 App 信息 * @requires this.id */ async load() { const result = await appService.loadApp({ query: { id: this.id, }, }); await this.loadEnvList(result); delete result.services; this.assign(result); return this; } /** * 加载 App 下的所有服务 */ async loadServices() { const result = await appService.loadServices({ query: { appId: this.id, }, }); const services = result.map((service: Service) => { if (service.type === SERVICE_TYPE.web) { service = WebService.from(service, this); if (!this.firstWebService) this.assign({ firstWebService: service as WebService }); } else { service = MicroService.from(service, this); if (!this.firstMicroService) this.assign({ firstMicroService: service as MicroService }); } service.assign({ app: this }); return service; }); await this.firstWebService.loadPackageInfo(); this.assign({ services }); return services; } /** * 加载页面和逻辑详情 */ async _loadViewsDetail() { const tasks: Array> = []; this.firstWebService.pages.forEach((page) => { utils.traverse((current) => { if (current.node.level === 'view') { const view = current.node; view.$def.logics = []; // load syncDef 不会添加重复逻辑 tasks.push(view.load()); } }, { node: page.rootView }); }); // 自动 load,不用 await await Promise.all(tasks); this.emit('loadViewsDetail'); } /** * 需要先调用 loadServices 之后再调用此函数 * 加载 App 下的服务具体内容 */ private async _loadServicesDetail(options: AppLoadAllOptions = { asyncLoadServicesDetail: false, asyncLoadViewsDetail: false, }) { // 前端许多功能依赖后端数据,所以必须先 load 后端服务 // loadMicroService await Promise.all([ this.firstMicroService.loadEntities(), this.firstMicroService.loadStructures(), this.firstMicroService.loadEnums(), ]); // interfaces params 的 children 依赖 entities 和 structures,所以必须拆成两个 Promise await Promise.all([ this.firstMicroService.loadInterfaces(), this.firstMicroService.loadProcesses(), ]); // loadWebService await this.firstWebService.loadPages(); if (options.asyncLoadViewsDetail) this._loadViewsDetail(); else await this._loadViewsDetail(); this.emit('loadedAll'); } /** * 加载 App 下所有子节点 * @example * const app = new App({ id: appId }); * await app.loadAll(); */ async loadAll(options: AppLoadAllOptions = { asyncLoadServicesDetail: false, asyncLoadViewsDetail: false, }) { await Promise.all([ this.load(), this.loadServices(), updateGenericTypeList(), ]); if (options.asyncLoadServicesDetail) this._loadServicesDetail(options); else await this._loadServicesDetail(options); } /** * 从后端 JSON 生成规范的 App 对象 * @param source JSON */ from(source: any) { return new App(source); } } export default App;