import type { FlowNode } from '@/pages/Workflow/Design/types'; /** * 正则1:匹配 ${...} 块 */ const BLOCK_PATTERN = /\$\{([^}]+)\}/g; /** * 正则2:在表达式内匹配 节点名.字段 引用 * 支持中文节点名、UUID格式节点ID */ const NODE_REF_PATTERN = /([a-zA-Z0-9_\u4e00-\u9fa5\-]+)\.([a-zA-Z0-9_.]+)/g; /** * 将显示名称格式转换为UUID格式 * ${节点名称.字段名} → ${节点UUID.字段名} * * @param displayText 包含显示名称的文本 * @param allNodes 所有节点列表(用于查找UUID) * @returns 转换后的UUID格式文本 * * @example * convertToUUID("构建${Jenkins构建.buildStatus}完成", allNodes) * // 返回: "构建${uuid-123.buildStatus}完成" */ export const convertToUUID = ( displayText: string, allNodes: FlowNode[] ): string => { if (!displayText || typeof displayText !== 'string') { return displayText; } // 阶段1:处理 ${...} 块 return displayText.replace(BLOCK_PATTERN, (blockMatch, blockContent) => { // 阶段2:在块内容中查找并替换所有 节点名.字段 引用 const transformedContent = blockContent.replace(NODE_REF_PATTERN, (refMatch: string, nodeNameOrId: string, fieldPath: string) => { // 特殊处理:表单字段 if (nodeNameOrId === '启动表单' || nodeNameOrId === 'form' || nodeNameOrId === 'notification') { return `${nodeNameOrId}.${fieldPath}`; } // 尝试通过名称查找节点 const nodeByName = allNodes.find(n => { const nodeName = n.data?.label || n.data?.nodeDefinition?.nodeName; return nodeName === nodeNameOrId; }); if (nodeByName) { return `${nodeByName.id}.${fieldPath}`; } // 可能已经是UUID格式,保持原样 return refMatch; }); return `\${${transformedContent}}`; }); }; /** * 将UUID格式转换为显示名称格式 * ${节点UUID.字段名} → ${节点名称.字段名} * * @param uuidText 包含UUID的文本 * @param allNodes 所有节点列表(用于查找显示名称) * @returns 转换后的显示名称格式文本 * * @example * convertToDisplayName("构建${uuid-123.buildStatus}完成", allNodes) * // 返回: "构建${Jenkins构建.buildStatus}完成" */ export const convertToDisplayName = ( uuidText: string, allNodes: FlowNode[] ): string => { if (!uuidText || typeof uuidText !== 'string') { return uuidText; } // 阶段1:处理 ${...} 块 return uuidText.replace(BLOCK_PATTERN, (blockMatch, blockContent) => { // 阶段2:在块内容中查找并替换所有 UUID.字段 引用为 节点名.字段 const transformedContent = blockContent.replace(NODE_REF_PATTERN, (refMatch: string, nodeIdOrName: string, fieldPath: string) => { // 特殊处理:表单字段 if (nodeIdOrName === 'form' || nodeIdOrName === '启动表单' || nodeIdOrName === 'notification') { return `${nodeIdOrName}.${fieldPath}`; } // 尝试通过UUID查找节点 const nodeById = allNodes.find(n => n.id === nodeIdOrName); if (nodeById) { // 找到了,替换为显示名称 const nodeName = nodeById.data?.label || nodeById.data?.nodeDefinition?.nodeName || nodeIdOrName; return `${nodeName}.${fieldPath}`; } // 可能已经是显示名称格式,保持原样 return refMatch; }); return `\${${transformedContent}}`; }); }; /** * 转换对象中的所有字符串值(从显示名称到UUID) * 递归处理嵌套对象和数组 * * @param obj 要转换的对象 * @param allNodes 所有节点列表 * @returns 转换后的对象 */ export const convertObjectToUUID = >( obj: T, allNodes: FlowNode[] ): T => { if (!obj || typeof obj !== 'object') { return obj; } const result: any = Array.isArray(obj) ? [] : {}; for (const key in obj) { const value = obj[key]; if (typeof value === 'string') { // 字符串类型:进行转换 result[key] = convertToUUID(value, allNodes); } else if (value && typeof value === 'object') { // 对象或数组:递归转换 result[key] = convertObjectToUUID(value, allNodes); } else { // 其他类型:保持原样 result[key] = value; } } return result as T; }; /** * 转换对象中的所有字符串值(从UUID到显示名称) * 递归处理嵌套对象和数组 * * @param obj 要转换的对象 * @param allNodes 所有节点列表 * @returns 转换后的对象 */ export const convertObjectToDisplayName = >( obj: T, allNodes: FlowNode[] ): T => { if (!obj || typeof obj !== 'object') { return obj; } const result: any = Array.isArray(obj) ? [] : {}; for (const key in obj) { const value = obj[key]; if (typeof value === 'string') { // 字符串类型:进行转换 result[key] = convertToDisplayName(value, allNodes); } else if (value && typeof value === 'object') { // 对象或数组:递归转换 result[key] = convertObjectToDisplayName(value, allNodes); } else { // 其他类型:保持原样 result[key] = value; } } return result as T; };