import { immutable, circular, excludedInJSON, action } from '../decorators'; import { config, utils, LEVEL_ENUM, Vertex, Schema, Structure, ActionOptions, } from '..'; import { structureService } from '../../service/data'; import { getBasicTypeDefaultValue } from './basicTypes'; import { convert2RefType } from './dataTypeUtils'; import { updateAllVariablesChildrenSchema } from '../logic/BaseVariable'; import { schemaService } from '../../service/common'; /** * 数据结构属性类 */ export class StructureProperty extends Vertex implements Schema { /** * 概念类型 */ @immutable() public level: LEVEL_ENUM = LEVEL_ENUM.property; /** * Id */ @immutable() public readonly id: string = undefined; /** * 名称 */ @immutable() public readonly name: string = undefined; /** * 标签 */ @immutable() public readonly label: string = undefined; /** * 描述 */ @immutable() public readonly description: string = undefined; /** * type */ @immutable() public readonly type: string = undefined; /** * 数据格式 */ @immutable() public readonly format: string = undefined; /** * generic 数据格式 */ @immutable() public readonly typeInstantiation: Schema = undefined; /** * 是否必须 */ @immutable() public readonly required: boolean = undefined; /** * 数据类型 */ @immutable() public readonly $ref: string = undefined; /** * 是否为数组,老的 Schema 中仍然用这种形式 */ @immutable() public readonly isArray: boolean = undefined; /** * 规则列表 */ @immutable() public readonly rules: any = undefined; /** * 默认值 */ @immutable() public readonly defaultValue: string | boolean | number = undefined; /** * 父级 Id */ @immutable() public readonly structureId: string = undefined; /** * 父级引用 */ @circular() @immutable() public root: Structure = undefined; /** * 节点是否为叶子节点 * 前端 UI 状态 */ @excludedInJSON() public isLeaf = true; /** * 周边存在的名称 */ @excludedInJSON() public existingNames: Array = []; /** * @param source 需要合并的部分参数 */ constructor(source?: Partial) { super(); source && this.assign(source); } /** * 添加数据结构属性 */ @action('添加数据结构属性') async create(none?: void, actionOptions?: ActionOptions) { config.defaultApp?.emit('saving'); const body = this.toJSON(); body._posIndex = this.root.propertyList.indexOf(this); utils.logger.debug('添加数据结构属性', body); const result: StructureProperty = await structureService.addProperty({ headers: { appId: config.defaultApp?.id, operationAction: actionOptions?.actionName || 'StructureProperty.create', operationDesc: actionOptions?.actionDesc || `添加数据结构"${this.root.name}"属性"${this.name}"`, }, body, }); // convert2RefType(result); this.deepPick(result, ['id']); updateAllVariablesChildrenSchema(); this.root.dataNode.service.emit('dataTypesChange'); this.root.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.deleteProperty({ headers: { appId: config.defaultApp?.id, operationAction: actionOptions?.actionName || 'StructureProperty.delete', operationDesc: actionOptions?.actionDesc || `删除数据结构"${this.root.name}"属性"${this.name}"`, }, query: { id: this.id, }, }); } const index = this.root.propertyList.indexOf(this); ~index && this.root.propertyList.splice(index, 1); updateAllVariablesChildrenSchema(); this.destroy(); this.root.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(); delete body.schemaRef; utils.logger.debug('修改数据结构属性', body); const result = await structureService.updateProperty({ headers: { appId: config.defaultApp?.id, operationAction: actionOptions?.actionName || 'StructureProperty.update', operationDesc: actionOptions?.actionDesc || `修改数据结构"${this.root.name}"属性"${this.name}"`, }, body, }); 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: `设置数据结构"${this.root.name}"的属性"${oldName}"的名称为"${name}"`, }); this.root.dataNode.service.emit('dataTypesChange'); this.root.dataNode.service.emit('vertexIdToNameChange', this.id, this.name); } /** * 设置数据结构属性标题 * @param label 标题 */ @action('设置数据结构属性标题') async setLabel(label: string) { this.assign({ label }); await this.update(undefined, { actionDesc: `设置数据结构"${this.root.name}"的属性"${this.name}"的标题为"${label}"`, }); } /** * 设置数据结构属性描述 * @param description 描述 */ @action('设置数据结构属性描述') async setDescription(description: string) { this.assign({ description }); await this.update(undefined, { actionDesc: `设置数据结构"${this.root.name}"的属性"${this.name}"的描述为"${description}"`, }); } /** * 查找schema 顶点被引用的逻辑顶点列表 */ async getSchemaUsage() { const result = await schemaService.getSchemaUsage({ query: { schemaId: this.id, valSource: 'structure', }, }); return result; } /** * 设置数据结构属性类型 */ @action('设置数据结构属性类型') async setDataType(schema: Schema) { // 用于update失败后还原数据 const originalData = { $ref: this.$ref, type: this.type, format: this.format, typeInstantiation: this.typeInstantiation, defaultValue: this.defaultValue, rules: this.rules, }; this.assign({ $ref: undefined, //引用到Entity或者structure type: undefined, format: undefined, typeInstantiation: undefined, }); this.assign(schema); this.assign({ defaultValue: getBasicTypeDefaultValue(), rules: [], }); try { await this.update(undefined, { actionDesc: `设置数据结构"${this.root.name}"的属性"${this.name}"的类型为"${schema.typeKey}"`, }); updateAllVariablesChildrenSchema(); this.root.dataNode.service.emit('dataTypesChange'); } catch (err) { this.assign(convert2RefType(originalData)); config.defaultApp?.emit('saved'); throw err; } } /** * 设置数据结构属性是否为列表 * @param isArray */ @action('设置数据结构属性是否为列表') async setAsList(isArray: boolean) { this.assign({ isArray }); this.assign({ defaultValue: getBasicTypeDefaultValue() }); await this.update(undefined, { actionDesc: `设置数据结构"${this.root.name}"的属性"${this.name}"${isArray ? '为' : '不为'}列表`, }); this.root.dataNode.service.emit('dataTypesChange'); } /** * 设置数据结构属性默认值 */ @action('设置数据结构属性默认值') async setDefaultValue(defaultValue: string) { this.assign({ defaultValue }); await this.update(undefined, { actionDesc: `设置数据结构"${this.root.name}"的属性"${this.name}"的默认值为"${defaultValue}"`, }); this.root.dataNode.service.emit('dataTypesChange'); } /** * 设置数据结构属性必须 * @param required 必须 */ @action('设置数据结构属性必须') async setRequired(required: boolean) { this.assign({ required }); await this.update(undefined, { actionDesc: `设置数据结构"${this.root.name}"的属性"${this.name}"为"${required ? '必须' : '不必须'}"`, }); this.root.dataNode.service.emit('dataTypesChange'); } @action('设置数据结构属性规则') async setRules(rules: any) { this.assign({ rules }); await this.update(undefined, { actionDesc: `设置数据结构属性规则`, }); } /** * 从后端 JSON 生成规范的 StructureProperty 对象 */ public static from(source: any, root: Structure) { convert2RefType(source.schema); } } export default StructureProperty;