| 291 | best_node_id = best.id |
| 292 | |
| 293 | def dfs_html(node_id: str, indent_level: int): |
| 294 | if node_id not in nodes: |
| 295 | return "" |
| 296 | |
| 297 | node = nodes[node_id] |
| 298 | |
| 299 | # 确定样式类 |
| 300 | status_class = "success" if node.run_status == "SUCCESS" else "failed" if node.run_status == "FAILED" else "" |
| 301 | style_classes = [node.stage] |
| 302 | if node.is_terminal: |
| 303 | style_classes.append("terminal") |
| 304 | if node.id == best_node_id: |
| 305 | style_classes.append("best-node") |
| 306 | |
| 307 | margin_left = indent_level * 30 |
| 308 | html_content = f'<div class="node {" ".join(style_classes)}" style="margin-left: {margin_left}px;">' |
| 309 | html_content += f'<span class="{status_class}">{str(node)}</span>' |
| 310 | html_content += '</div>\n' |
| 311 | |
| 312 | # 递归子节点 |
| 313 | for child_id in node.children_ids: |
| 314 | html_content += dfs_html(child_id, indent_level + 1) |
| 315 | |
| 316 | return html_content |
| 317 | |
| 318 | html += dfs_html(root_id, 0) |
| 319 | |