<title>数字人节点设计</title>

# 数字人节点：算力显示 + 抽卡功能

- 日期：2026-06-14
- 涉及文件：数字人节点前端脚本、前端多语言配置（中英文）
- 范围：**纯前端改动**，后端无需任何改动

## 背景

数字人节点原先：

- 不显示算力
- 抽卡次数固定为 1
- 节点内显示单个结果视频
- 只创建一个关联视频节点，用局部轮询逻辑（封装单个任务状态轮询）轮询

需求：显示算力 + 支持用户抽卡（1-4 个结果）。

## 前提（已验证，后端无需改动）

- 生成任务接口已支持 `count` 参数（1-4），按 count 循环创建任务，返回任务ID数组，按 count 扣算力。
- 任务配置接口已为数字人任务返回 `computing_power`。算力按实际使用量计费，具体定价以产品页为准；具体数值由服务端任务配置下发，管理员可动态调整。
- 视频状态查询接口返回的 `result.tasks` 每个 task 带任务ID，多结果可精确对应。

## 设计决策

| 决策点 | 选择 | 理由 |
|-|-|-|
| 算力显示样式 | 详细版（值 + 明细行） | 与视频节点/分镜节点视觉一致 |
| 抽卡次数范围 | 1-4 | 与现有视频节点一致 |
| 节点内结果展示 | **不显示** | 与视频/分镜节点一致，结果全部在关联视频节点展示 |
| 模型键取值 | 优先带语音的数字人模型键，回退基础数字人模型键（具体键名见前端数字人节点脚本中的常量） | 与现有提交逻辑一致 |
| duration | 固定 5 | 与现有提交逻辑一致 |
| 多结果轮询 | 全局视频状态轮询函数（内部实现） | 支持多任务，带任务级实时回调 |
| 多结果对应 | 按任务ID | 比按 index 稳健 |

## 实现要点

### UI 结构（bodyHtml）

```Plaintext
角色图片 *  → [上传/连接]
说话音频 *  → [上传/连接]
提示词 *    → [textarea]
─────────────────────
算力消耗：    N 算力        （新增，详细版）
单个 X 算力 × M 个 = N 算力
─────────────────────
[生成视频 ▾]  抽卡次数：XM   （改为抽卡选择器）
[状态显示：生成中/成功/失败]   （保留）
```

移除节点内的"生成结果"视频区域。

### 数据（defaultData）

- 新增 `drawCount: 1`
- `status` 保留
- 移除节点内 `videoUrl` 渲染（data 字段保留以兼容旧工作流）

### 算力计算

```JavaScript
// 算力计算（内部实现，节选）
function calculateDigitalHumanPower() {
  if (!window.TaskConfig || !window.TaskConfig.isLoaded()) return 0;
  var modelKey = 优先带语音的数字人模型键，回退基础键; // 具体键名见配置文件
  var single = TaskConfig.getComputingPower(modelKey, 5);
  return single * (node.data.drawCount || 1);
}
```

算力显示更新逻辑更新值 + 明细行。切换抽卡次数时立即更新；任务配置异步加载完成后再兜底更新。

### 抽卡选择器（复用现有 CSS）

`gen-container` + `gen-btn-main`（生成）+ `gen-btn-caret`（▾）+ `gen-menu`（X1/X2/X3/X4）。事件处理与视频节点一致：caret 切换菜单 / item 设 `drawCount`+更新 / document 点外关闭。

### 提交与多结果展示

- 提交时携带 `count = node.data.drawCount || 1`
- 后端返回任务ID数组 → 循环创建对应数量视频节点：

  - 纵向排列（`y = node.y + i*280`）
  - 每个绑定对应任务ID，命名 `数字人视频N`（单个时为 `数字人视频`）
  - 每个创建连接 `from = 数字人节点`
- 节点 data 中记录关联视频节点ID列表（替代单个节点ID）
- 重新生成：先清理所有旧关联节点的连接

### 轮询改造

移除局部轮询逻辑，改用全局视频状态轮询函数（内部实现），支持多任务：

- 任务级更新回调：按任务ID找到对应视频节点更新状态/结果（实时）
- 完成回调：按各自状态更新视频节点 url；刷新用户算力；恢复按钮
- 错误/超时：标记状态，恢复按钮

### 重新加载复原

- `drawCount` 从 data 恢复 → 算力显示正确
- 关联视频节点 + 连接 + 任务ID通过工作流数据自动恢复
- 节点内状态恢复显示

## 错误处理

- 任务配置未加载：算力先显示 0，加载后回调更新（非阻塞）
- 任务ID数组为空：报错（保留现有逻辑）
- 部分任务失败：完成回调内按各自状态更新（失败的标记失败，成功的正常显示）

## 不做的事

- 不改后端 / 不加接口 / 不动数据库
- 不改主页面（JS 独立文件）
- 抽卡范围固定 1-4

## 验证

1. 新建节点 → 算力正常显示；切 X4 → 算力按抽卡倍数变化
2. 生成 4 个 → 创建 4 个关联视频节点，各自轮询出结果
3. 重新生成 → 清理旧 4 个、创建新的
4. 保存→重载 → 抽卡次数 / 算力 / 关联节点连接均复原
5. 中英文切换 → 翻译正常
6. 兼容旧工作流（无抽卡次数字段的旧节点默认 X1）
