import { immutable, circular, excludedInJSON, action } from '../decorators'; import { config, utils, LEVEL_ENUM, Vertex, DataNode, ObjectSchema, Service, dataTypesMap, updateDataTypeList, StructureProperty, ActionOptions, } from '..'; import { structureService } from '../../service/data'; import { convert2RefType } from './dataTypeUtils'; import { updateAllVariablesChildrenSchema } from '../index'; /** * 数据结构类 */ export class Structure extends Vertex implements ObjectSchema { /** * 概念类型 */ @immutable() public readonly level: LEVEL_ENUM = LEVEL_ENUM.structure; /** * Id */ @immutable() public readonly id: string = undefined; /** * dataTypes 中的唯一标识 */ @immutable() public readonly schemaRef: string = undefined; /** * 名称 */ @immutable() public readonly name: string = undefined; /** * 描述 */ @immutable() public readonly description: string = undefined; /** * 类型 */ @immutable() public readonly type: 'object' = 'object'; /** * 属性列表 */ @immutable() readonly propertyList: Array = []; @immutable() public readonly resolvers: string = undefined; /** * 所属服务 Id */ @immutable() public readonly serviceId: string = undefined; /** * catogory Name */ @immutable() public readonly category: string = undefined; /** * 所属服务类型 */ @immutable() public readonly serviceType: string = undefined; /** * 所属实体 Id */ @immutable() public readonly entityId: string = undefined; /** * 所属服务 */ @immutable() public readonly service: Service = undefined; /** * 父节点 */ @circular() @immutable() public readonly dataNode: DataNode = undefined; /** * 周边存在的名称 */ @excludedInJSON() public existingNames: Array = []; /** * 周边存在的名称 */ constructor(source?: Partial) { super(); source && this.assign(source); } /** * 按当前 id 加载数据结构数据 * @requires this.id */ async load() { const result = await structureService.loadDetail({ query: { id: this.id, }, config: { mock: config.mock, }, }); this.assign(result); return this; } /** * 按当前 id 加载数据结构数据 * @requires this.id */ async loadPro() { const result = await structureService.loadDetail({ query: { id: this.id, }, }); Object.assign(result, result.definition); delete result.definition; convert2RefType(result); const structure = new Structure(result); const propertyList = structure.propertyList as Array; propertyList.forEach((property, index) => { property = propertyList[index] = new StructureProperty(property); property.assign({ root: structure }); }); const service = this.dataNode.service; structure.assign({ schemaRef: `#/${service.id}/${structure.id}`, dataNode: service.data, expanded: true, }); dataTypesMap[structure.schemaRef] = structure; this.assign(structure); const pos = this.dataNode.structures.findIndex((item) => item.id === this.id); if (pos === -1) this.dataNode.structures.unshift(this); else { this.dataNode.structures.splice(pos, 1, structure); } updateDataTypeList(); updateAllVariablesChildrenSchema(); this.dataNode.service.emit('dataTypesChange'); this.dataNode.service.emit('vertexIdToNameChange', this.id, this.name); 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: Structure = await structureService.create({ headers: { appId: config.defaultApp?.id, operationAction: actionOptions?.actionName || 'Structure.create', operationDesc: actionOptions?.actionDesc || `添加数据结构"${this.name}"`, }, body, }); this.deepPick(result, ['id']); this.assign({ schemaRef: `#/${this.dataNode.service.id}/${result.id}`, }); dataTypesMap[this.schemaRef] = this; await then?.(); updateDataTypeList(); this.dataNode.service.emit('dataTypesChange'); this.dataNode.service.emit('vertexIdToNameChange', this.id, this.name); await config.defaultApp?.history.load(); config.defaultApp?.emit('saved'); return this; } /** * 删除数据结构 */ @action('删除数据结构') async delete(none?: void, actionOptions?: ActionOptions) { config.defaultApp?.emit('saving'); if (this.id) { await structureService.delete({ headers: { appId: config.defaultApp?.id, operationAction: actionOptions?.actionName || 'Structure.delete', operationDesc: actionOptions?.actionDesc || `删除数据结构"${this.name}"`, }, query: { id: this.id, }, }); } const index = this.dataNode.structures.indexOf(this); ~index && this.dataNode.structures.splice(index, 1); this.dataNode.service.globalLogic.removeCategoryStructure(this); delete dataTypesMap[this.schemaRef]; updateDataTypeList(); this.destroy(); this.dataNode.service.emit('dataTypesChange'); await config.defaultApp?.history.load(); config.defaultApp?.emit('saved'); } /** * 修改数据结构 */ async update(none?: void, actionOptions?: ActionOptions, then?: () => Promise) { config.defaultApp?.emit('saving'); const body = this.toJSON('', ['propertyList']); utils.logger.debug('修改数据结构', body); const result: Structure = await structureService.update({ headers: { appId: config.defaultApp?.id, operationAction: actionOptions?.actionName || 'Structure.update', operationDesc: actionOptions?.actionDesc || `修改数据结构"${this.name}"`, }, body, }); convert2RefType(result); this.plainAssign(result); await then?.(); await config.defaultApp?.history.load(); config.defaultApp?.emit('saved'); return this; } /** * 设置数据结构名称 * @param name 名称 */ @action('设置数据结构名称') async setName(name: string) { const oldName = this.name; this.assign({ name }); await this.update(undefined, { actionDesc: `设置数据结构"${oldName}"的名称为"${name}"`, }); updateDataTypeList(); this.dataNode.service.emit('dataTypesChange'); this.dataNode.service.emit('vertexIdToNameChange', this.id, this.name); } /** * 设置数据结构描述 * @param description 描述 */ @action('设置数据结构描述') async setDescription(description: string) { this.assign({ description }); await this.update(undefined, { actionDesc: `设置数据结构"${this.name}"的描述为"${description}"`, }); } /** * 从后端 JSON 生成规范的 Structure 对象 */ public static from(source: any, service: Service) { convert2RefType(source); const structure = new Structure(source); structure.assign({ dataNode: service.data, schemaRef: `#/${service.id}/${structure.id}`, }); const propertyList = structure.propertyList as Array; propertyList.forEach((property, index) => { property = propertyList[index] = new StructureProperty(property); property.assign({ root: structure }); }); structure.assign({ resolvers: undefined }); dataTypesMap[structure.schemaRef] = structure; return structure; } } export default Structure;