解析值中的变量引用 支持格式: - ${varName} - 标准格式 - {varName} - 简化格式 - {listName[0]} - 列表索引访问 - {dictName[key]} 或 {dictName["key"]} - 字典键访问 - {data[0][name]} - 嵌套访问 - {listName[{indexVar}]} - 嵌套变量引用(索引本身是变量)
(self, value: Any)
| 495 | self._current_node_name = node_name |
| 496 | |
| 497 | def resolve_value(self, value: Any) -> Any: |
| 498 | """解析值中的变量引用 |
| 499 | |
| 500 | 支持格式: |
| 501 | - ${varName} - 标准格式 |
| 502 | - {varName} - 简化格式 |
| 503 | - {listName[0]} - 列表索引访问 |
| 504 | - {dictName[key]} 或 {dictName["key"]} - 字典键访问 |
| 505 | - {data[0][name]} - 嵌套访问 |
| 506 | - {listName[{indexVar}]} - 嵌套变量引用(索引本身是变量) |
| 507 | """ |
| 508 | if isinstance(value, str): |
| 509 | import re |
| 510 | |
| 511 | # 凭据库引用解析(最前置,先于普通变量解析): |
| 512 | # {{cred:名称}} / {{cred:名称.字段}} / {{凭据:名称}} / {{凭据:名称.字段}} |
| 513 | if '{{' in value and ('cred:' in value or 'cred:' in value or '凭据:' in value or '凭据:' in value): |
| 514 | def _resolve_cred(m): |
| 515 | ref = m.group(1).strip() |
| 516 | if '.' in ref: |
| 517 | cname, fld = ref.split('.', 1) |
| 518 | cname, fld = cname.strip(), fld.strip() |
| 519 | else: |
| 520 | cname, fld = ref, 'value' |
| 521 | try: |
| 522 | from app.services import credential_manager |
| 523 | val = credential_manager.get_field(cname, fld) |
| 524 | return val if val is not None else m.group(0) |
| 525 | except Exception: |
| 526 | return m.group(0) |
| 527 | value = re.sub(r'\{\{\s*(?:cred|凭据)\s*[::]\s*([^{}]+?)\s*\}\}', _resolve_cred, value) |
| 528 | |
| 529 | _MISSING = object() |
| 530 | |
| 531 | def to_replacement_text(resolved: Any) -> str: |
| 532 | # 变量存在但值为空(None)时,按空字符串处理,避免保留原始 {var} |
| 533 | if resolved is None: |
| 534 | return '' |
| 535 | if isinstance(resolved, (list, dict)): |
| 536 | import json |
| 537 | return json.dumps(resolved, ensure_ascii=False) |
| 538 | return str(resolved) |
| 539 | |
| 540 | def resolve_nested_variables(text: str, max_depth: int = 5) -> str: |
| 541 | """递归解析嵌套的变量引用,最多解析max_depth层""" |
| 542 | if max_depth <= 0: |
| 543 | return text |
| 544 | |
| 545 | # 查找所有 {xxx} 格式的变量引用 |
| 546 | pattern = r'(?<!\$)\{([^{}]+)\}' |
| 547 | matches = list(re.finditer(pattern, text)) |
| 548 | |
| 549 | if not matches: |
| 550 | return text |
| 551 | |
| 552 | # 从后向前替换,避免索引偏移问题 |
| 553 | for match in reversed(matches): |
| 554 | var_expr = match.group(1).strip() |