import { immutable, circular, action, excludedInJSON } from '../decorators'; import { config, history, LEVEL_ENUM, Vertex, vertexsMap, Process, Logic, utils, ProcessComponentReturn, ProcessComponentVariable, ProcessComponentAttribute, ProcessComponentProperty, ProcessInterface, typeCheck, ActionOptions } from '..'; import processService from '../../service/process'; /** * 流程组件类 */ export class ProcessComponent extends Vertex { /** * 概念类型 */ @immutable() public readonly level: LEVEL_ENUM = LEVEL_ENUM.processComponent; /** * 流程组件 Id */ @immutable() public readonly id: string = undefined; /** * 流程组件名称 */ @immutable() public readonly name: string = undefined; /** * 流程组件标题 */ @immutable() public readonly title: string = undefined; /** * 流程组件描述 */ @immutable() public readonly description: string = undefined; /** * 流程组件类型 */ @immutable() public readonly type: string = undefined; /** * 流程组件输出参数 */ @immutable() public readonly returns: Array = []; /** * 流程组件局部变量 */ @immutable() public readonly variables: Array = []; /** * 流程组件逻辑 ID */ @immutable() public readonly logicId: string = undefined; /** * 流程组件逻辑 */ @immutable() public readonly logic: Logic = undefined; /** * 流程组件属性 */ @immutable() public readonly destination: ProcessComponentAttribute = undefined; /** * 完成任务接口 */ @immutable() public readonly completeTaskInterface: ProcessInterface = undefined; /** * 所属流程 Id */ @immutable() public readonly parentId: string = undefined; /** * 树组件的隐藏属性 */ @excludedInJSON() public readonly hidden: boolean = false; /** * 类型检查详情 */ @excludedInJSON() public readonly typeCheckResult: any = {}; /** * 类型检查状态 */ @excludedInJSON() public readonly typeCheckStatus: string = 'success'; /** * 所属流程 */ @circular() @immutable() public readonly process: Process = undefined; /** * 树组件的子节点字段 */ @excludedInJSON() @immutable() public readonly moreChildrenFields: Array = ['returns', 'variables', 'properties', 'interfaces']; /** * 已存在名称集合 */ @excludedInJSON() @immutable() public readonly existingNames: Array = []; /** * 接口列表,单纯用于 tree 展示 */ @excludedInJSON() @immutable() public readonly interfaces: Array = []; /** * @param source 需要合并的部分参数 */ constructor(source?: Partial) { super(); this.assign(source); } /** * 添加流程组件 */ @action('添加流程组件') create() { this.process.childShapes.push(this); return this; } /** * 删除流程组件 */ @action('删除流程组件') delete() { const index = this.process.childShapes.indexOf(this); ~index && this.process.childShapes.splice(index, 1); this.destroy(); } /** * 修改流程组件属性 */ async updateAttr(updateInterface?: boolean, actionOptions?: ActionOptions) { config.defaultApp?.emit('saving'); const body = this.toPlainJSON(); utils.logger.debug('修改流程组件', body); const { completeTaskInterface } = await processService.updateComponent({ headers: { appId: config.defaultApp?.id, operationAction: actionOptions?.actionName || 'ProcessComponent.updateAttr', operationDesc: actionOptions?.actionDesc || `修改流程组件属性"${this.name}${this.title ? `(${this.title})` : ''}"`, }, body, }); // 流程接口会自动根据流程组件名称变化,更新流程接口的名称 if (updateInterface && completeTaskInterface) { const { name, path, method } = completeTaskInterface; this.completeTaskInterface.assign({ name, path, method }); this.completeTaskInterface.logic.assign({ name }); this.process.service.emit('interfacesChange'); } 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.updateAttr(true, { actionDesc: `设置流程组件"${oldName}"的名称为"${name}"`, }); // 流程逻辑会自动根据流程组件名称变化,更新逻辑的名称 if (this.logic) { this.logic.assign({ name }); } } /** * 设置流程组件标题 * @param title 标题 */ @action('设置流程组件标题') async setTitle(title: string) { this.assign({ title }); await this.updateAttr(false, { actionDesc: `设置流程组件"${this.name}"的标题为"${title}"`, }); } /** * 设置流程组件描述 * @param description 描述 */ @action('设置流程组件描述') async setDescription(description: string) { this.assign({ description }); await this.updateAttr(false, { actionDesc: `设置流程组件"${this.name}"的描述为"${description}"`, }); } /** * 设置流程组件值 (SequenceFlow) * @param flowValue 值 */ @action('设置流程组件值') async setFlowValue(flowValue: string) { this.assign({ flowValue }); await this.updateAttr(false, { actionDesc: `设置流程组件值`, }); } /** * 设置流程组件任务完成人 (UserTask) * @param assignee 任务完成人 */ @action('设置流程组件任务完成人') async setAssignee(assignee: Array) { this.assign({ assignee }); await this.updateAttr(false, { actionDesc: `设置流程组件任务完成人`, }); } /** * 从后端 JSON 生成规范的 Param 对象 */ public static from(source: any, process: Process) { const processComponent = new ProcessComponent(source); processComponent.assign({ process, }); if (source) { const { returns = [], variables = [], properties = [], logicId, destination, completeTaskInterface, type } = source; processComponent.assign({ hidden: ['StartNoneEvent', 'EndNoneEvent', 'SequenceFlow'].includes(type), returns: returns.map((rn: any) => (ProcessComponentReturn.from(rn, processComponent))), variables: variables.map((variable: any) => (ProcessComponentVariable.from(variable, processComponent))), properties: properties.map((property: any) => (ProcessComponentProperty.from(property, processComponent))), }); // 包含 logicId 时,自动初始化 logic if (logicId) { // 可能情况下,复用已有 Logic 缓存,防止重复打开多个同样的 logic 编辑器 processComponent.assign({ logic: vertexsMap.get(logicId) || Logic.from({ id: logicId }, processComponent), }); } if (destination) { processComponent.assign({ destination: ProcessComponentAttribute.from(destination, processComponent), }); } if (completeTaskInterface) { const ifce = ProcessInterface.from(completeTaskInterface, processComponent); processComponent.assign({ completeTaskInterface: ifce, interfaces: [ifce], }); } } return processComponent; } static assignTypeCheckResult(processComponent: ProcessComponent, typeCheckResult: any) { if (!processComponent || !typeCheckResult) return; typeCheck.push(typeCheckResult); const typeCheckStatus = typeCheckResult.typeCheckNote?.status || 'success'; processComponent.assign({ typeCheckResult, typeCheckStatus, }); } } export default ProcessComponent;