@lcap/asl
Version:
NetEase Application Specific Language
364 lines (332 loc) • 11.8 kB
text/typescript
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 {
/**
* 概念类型
*/
()
public readonly level: LEVEL_ENUM = LEVEL_ENUM.page;
/**
* 页面 Id
*/
()
public readonly id: string = undefined;
/**
* 页面名称
*/
()
public readonly name: string = undefined;
/**
* 页面标题
*/
()
public readonly title: string = undefined;
/**
* 是否接入权限
*/
()
public readonly auth: boolean = undefined;
/**
* 是否为首页
*/
()
public readonly isIndex: boolean = undefined;
/**
* 根页面视图
*/
()
public readonly rootView: View = undefined;
/**
* 所属前端服务 Id
*/
()
public readonly serviceId: string = undefined;
/**
* 所属前端服务
*/
()
()
public readonly service: WebService = undefined;
/**
* 树组件的子节点字段
*/
()
()
public readonly childrenField: string = 'rootView.children';
/**
* 树组件的子节点字段
*/
()
()
public readonly moreChildrenFields: Array<string> = ['rootView.$def.params', 'rootView.$def.variables', 'rootView.$def.logics'];
/**
* @param source 需要合并的部分参数
*/
constructor(source?: Partial<Page>) {
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<Interface>;
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<Enum>;
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<Entity>;
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<Structure>;
if (structures && structures.length) {
structures.forEach((item, index) => structures[index] = Structure.from(item, microService));
microService.data.structures.unshift(...structures);
updateDataTypeList();
}
}
/**
* 添加页面
*/
('导入页面')
async importPage(none?: void, actionOptions?: ActionOptions, then?: () => Promise<any>) {
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;
}
/**
* 添加页面
*/
('添加页面')
async create(none?: void, actionOptions?: ActionOptions, then?: () => Promise<any>) {
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;
}
/**
* 删除页面
*/
('删除页面')
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<any>) {
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;
}
/**
* 设为首页
*/
('设为首页')
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');
}
/**
* 设置是否开启权限控制
*/
('设置是否开启权限控制')
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;