diff --git a/apps/application/flow/step_node/condition_node/impl/base_condition_node.py b/apps/application/flow/step_node/condition_node/impl/base_condition_node.py index e0da03ace4c..239fe281f22 100644 --- a/apps/application/flow/step_node/condition_node/impl/base_condition_node.py +++ b/apps/application/flow/step_node/condition_node/impl/base_condition_node.py @@ -9,7 +9,7 @@ from typing import List from application.flow.i_step_node import NodeResult -from application.flow.compare import do_assertion +from application.flow.compare import _assertion from application.flow.step_node.condition_node.i_condition_node import IConditionNode @@ -17,21 +17,72 @@ class BaseConditionNode(IConditionNode): def save_context(self, details, workflow_manage): self.context['branch_id'] = details.get('branch_id') self.context['branch_name'] = details.get('branch_name') + self.context['branch_details'] = details.get('branch_details') self.context['exception_message'] = details.get('err_message') def execute(self, **kwargs) -> NodeResult: branch_list = self.node_params_serializer.data['branch'] - branch = self._execute(branch_list) - r = NodeResult({'branch_id': branch.get('id'), 'branch_name': branch.get('type')}, {}) + branch, branch_details = self._execute(branch_list) + r = NodeResult({ + 'branch_id': branch.get('id') if branch else None, + 'branch_name': branch.get('type') if branch else None, + 'branch_details': branch_details + }, {}) return r def _execute(self, branch_list: List): + branch_details = [] for branch in branch_list: - if self.branch_assertion(branch): - return branch + condition_details = self._evaluate_conditions(branch) + is_matched = all(cond.get('result', False) for cond in condition_details) if branch.get('condition') == 'and' else any(cond.get('result', False) for cond in condition_details) + + branch_details.append({ + 'id': branch.get('id'), + 'type': branch.get('type'), + 'condition_logic': branch.get('condition'), + 'is_matched': is_matched, + 'conditions': condition_details + }) + if is_matched: + return branch, branch_details + return None, branch_details - def branch_assertion(self, branch): - return do_assertion(self.workflow_manage, branch.get('condition'), branch.get('conditions')) + def _evaluate_conditions(self, branch): + condition_logic = branch.get('condition') + condition_list = branch.get('conditions', []) + condition_details = [] + + for condition in condition_list: + field_list = condition.get('field', []) + compare = condition.get('compare', '') + value = condition.get('value', '') + + try: + field_value = self.workflow_manage.get_reference_field(field_list[0], field_list[1:]) + except Exception: + field_value = None + + try: + evaluated_value = self.workflow_manage.generate_prompt(value) + except Exception: + evaluated_value = value + + result = _assertion(self.workflow_manage, field_list, compare, value) + + condition_details.append({ + 'field': field_list, + 'field_type': type(field_value).__name__ if field_value is not None else None, + 'field_value': field_value, + 'compare': compare, + 'target_type': type(evaluated_value).__name__ if evaluated_value is not None else None, + 'target_value': evaluated_value, + 'result': result + }) + + if (condition_logic == "and" and not result) or (condition_logic == 'or' and result): + break + + return condition_details def get_details(self, index: int, **kwargs): return { @@ -40,6 +91,7 @@ def get_details(self, index: int, **kwargs): 'run_time': self.context.get('run_time'), 'branch_id': self.context.get('branch_id'), 'branch_name': self.context.get('branch_name'), + 'branch_details': self.context.get('branch_details'), 'type': self.node.type, 'status': self.status, 'err_message': self.err_message, diff --git a/ui/src/components/execution-detail-card/index.vue b/ui/src/components/execution-detail-card/index.vue index f163b40c7a3..84861c12cfc 100644 --- a/ui/src/components/execution-detail-card/index.vue +++ b/ui/src/components/execution-detail-card/index.vue @@ -182,7 +182,43 @@ {{ $t('aiChat.executionDetails.conditionResult') }}
- {{ data.branch_name || '-' }} + + {{ data.branch_name || '-' }} + +
+ + +
+
+ + + {{ branch.type || '-' }} + + {{ $t('aiChat.executionDetails.branchEvaluationDetails') }} + + + {{ $t('aiChat.executionDetails.conditionLogic') }}: + + {{ branch.condition_logic === 'and' ? $t('aiChat.executionDetails.and') : $t('aiChat.executionDetails.or') }} + + +
+
+
+ + {{ formatValue(cond.field_value, cond.field_type) }} + + {{ getCompareLabel(cond.compare) }} + + {{ formatValue(cond.target_value, cond.target_type) }} + + = + + {{ cond.result ? 'True' : 'False' }} + +
@@ -1400,6 +1436,7 @@ import { ref, computed, type PropType } from 'vue' import ParagraphCard from '@/components/ai-chat/component/knowledge-source-component/ParagraphCard.vue' import DynamicsForm from '@/components/dynamics-form/index.vue' +import { compareList } from '@/workflow/common/data' import { iconComponent } from '@/workflow/icons/utils' import { WorkflowType } from '@/enums/application' import { getImgUrl } from '@/utils/common' @@ -1422,6 +1459,36 @@ const isKnowLedge = computed(() => props.type === 'knowledge') const currentLoopNode = ref(0) const currentParagraph = ref(0) const currentWriteContent = ref(0) + +// 格式化值显示 +const formatValue = (value: any, value_type: any): string => { + if (value === null || value === undefined) { + return 'null' + } + if (value === '') { + return `${value_type}: ""` + } + if (typeof value === 'string') { + return `${value_type}: "${value}"` + } + if (Array.isArray(value)) { + return `${value_type}: ${JSON.stringify(value)}` + } + if (typeof value === 'object') { + return `${value_type}: ${JSON.stringify(value)}` + } + return `${value_type}: ${value}` +} + +const compareMap: Record = compareList.reduce((acc, cur) => { + acc[cur.value] = cur.label + return acc +}, {} as Record) + +// 获取比较操作符标签 +const getCompareLabel = (compare: string): string => { + return compareMap[compare] || compare +} diff --git a/ui/src/locales/lang/en-US/ai-chat.ts b/ui/src/locales/lang/en-US/ai-chat.ts index cffe1baaaf3..d341065f3c6 100644 --- a/ui/src/locales/lang/en-US/ai-chat.ts +++ b/ui/src/locales/lang/en-US/ai-chat.ts @@ -109,6 +109,10 @@ export default { searchContent: 'Search Query', searchResult: 'Search Results', conditionResult: 'Condition Evaluation', + branchEvaluationDetails: 'Branch Evaluation Details', + conditionLogic: 'Condition Logic', + and: 'AND', + or: 'OR', currentChat: 'Current Chat', answer: 'AI Response', replyContent: 'Reply Content', diff --git a/ui/src/locales/lang/zh-CN/ai-chat.ts b/ui/src/locales/lang/zh-CN/ai-chat.ts index afa0a32a900..fdce690e4cc 100644 --- a/ui/src/locales/lang/zh-CN/ai-chat.ts +++ b/ui/src/locales/lang/zh-CN/ai-chat.ts @@ -107,6 +107,10 @@ export default { searchContent: '检索内容', searchResult: '检索结果', conditionResult: '判断结果', + branchEvaluationDetails: '分支判断详情', + conditionLogic: '条件逻辑', + and: '所有(AND)', + or: '任一(OR)', currentChat: '本次对话', answer: 'AI 回答', replyContent: '回复内容', diff --git a/ui/src/locales/lang/zh-Hant/ai-chat.ts b/ui/src/locales/lang/zh-Hant/ai-chat.ts index 9731cf2f238..9fdba0d4cdd 100644 --- a/ui/src/locales/lang/zh-Hant/ai-chat.ts +++ b/ui/src/locales/lang/zh-Hant/ai-chat.ts @@ -107,6 +107,10 @@ export default { searchContent: '檢索內容', searchResult: '檢索結果', conditionResult: '判斷結果', + branchEvaluationDetails: '分支判斷詳情', + conditionLogic: '條件邏輯', + and: '所有(AND)', + or: '任一(OR)', currentChat: '本次對話', answer: 'AI 回答', replyContent: '回覆內容',