# 任务日志层级关系优化方案

## 改造背景

### 原有问题

1. **日志表缺少层级关系字段**: `vwed_tasklog` 表只有基本字段,没有记录父子关系、迭代索引等信息
2. **层级重构困难**: `get_block_results` 接口需要解析日志中的 JSON `output.iterationResults` 来重构层级,不稳定
3. **循环日志分散**: 循环块的日志("第1次循环")和子块执行日志是分开的,前端难以组织嵌套显示

### 期望效果

对于循环任务,期望返回的数据结构为:

```json
{
  "children": [
    {
      "iterationIndex": 0,
      "success": true,
      "iterationLogs": [
        {"message": "第1次循环, item=1"}
      ],
      "children": [
        {
          "blockName": "b4",
          "blockType": "PrintBp",
          "logs": [
            {"message": "打印: 0"}
          ]
        }
      ]
    }
  ]
}
```

## 改造方案

### 1. 数据库表结构扩展

#### 新增字段

为 `vwed_tasklog` 表添加以下字段:

| 字段名 | 类型 | 说明 |
|-------|------|------|
| `parent_log_id` | VARCHAR(255) | 父日志ID,用于建立层级关系 |
| `iteration_index` | INT | 迭代索引,记录是第几次循环(从0开始) |
| `block_record_id` | VARCHAR(255) | 关联的块执行记录ID |
| `log_type` | VARCHAR(50) | 日志类型: `iteration_start`, `iteration_end`, `block_execution`, `branch_execution` |

#### 迁移脚本

位置: `migrations/versions/004_add_tasklog_hierarchy_fields.py`

执行迁移:
```bash
cd /mnt/d/jsw_code/project/VWED_server
alembic upgrade head
```

### 2. 日志记录逻辑改造

#### TaskContext 扩展

在 `services/execution/task_context.py` 中添加:

```python
self.parent_log_id = None  # 当前父日志ID
self.current_iteration_index = None  # 当前迭代索引

def set_iteration_context(self, parent_log_id: str = None, iteration_index: int = None):
    """设置当前迭代上下文"""
    self.parent_log_id = parent_log_id
    self.current_iteration_index = iteration_index
```

#### BlockHandler 日志记录方法

修改 `services/execution/handlers/base.py` 的 `_record_task_log` 方法:

```python
async def _record_task_log(
    self,
    block: Dict[str, Any],
    result: Dict[str, Any],
    context: Any,
    log_type: str = "block_execution",
    parent_log_id: str = None,
    iteration_index: int = None
) -> str:
    """记录任务日志,返回日志ID"""
    # ... 记录时包含 parent_log_id, iteration_index, log_type 等字段
```

#### IterateListBlockHandler 改造

在 `services/execution/handlers/progress.py` 的迭代处理逻辑中:

```python
for index, item in enumerate(array_data):
    # 1. 记录迭代开始日志,作为该次迭代的父日志
    iteration_start_log_id = await self._record_task_log(
        block,
        {"success": True, "message": f"第{index+1}次循环, item={item}"},
        context,
        log_type="iteration_start",
        iteration_index=index
    )

    # 2. 设置迭代上下文,后续子块日志都会关联到这个父日志
    context.set_iteration_context(parent_log_id=iteration_start_log_id, iteration_index=index)

    # 3. 执行循环体(子块日志会自动记录parent_log_id和iteration_index)
    loop_result = await executor.execute_children(block, "default")

    # 4. 清除迭代上下文
    context.clear_iteration_context()
```

### 3. 查询接口优化

#### 新版 get_block_results_v2

创建新文件 `services/task_record_service_new.py`,实现基于层级关系字段的查询逻辑:

**核心思路**:

1. **构建映射表**:
   - `log_map_by_block`: 按块名称分组日志
   - `log_map_by_parent`: 按父日志ID分组子日志

2. **识别迭代块**:
   - 检查 `block_type` 是否为 `ITERATE_LIST`, `WHILE`, `REPEAT_NUM`
   - 找出所有 `log_type="iteration_start"` 的日志

3. **按迭代组织**:
   ```python
   for iter_log in iteration_start_logs:
       iteration_item = {
           "iterationIndex": iter_log.iteration_index,
           "iterationLogs": [iter_log],  # 迭代开始日志
           "children": []  # 该次迭代的子块
       }

       # 查找 parent_log_id = iter_log.id 的所有子日志
       child_logs = log_map_by_parent.get(iter_log.id, [])
       # ... 递归构建子块
   ```

4. **递归处理嵌套**:
   - 如果子块也是迭代块,继续应用相同逻辑
   - 普通块直接递归处理其子块

#### 兼容旧版本

在 `services/task_record_service.py` 中:

```python
@staticmethod
async def get_block_results(task_record_id: str, use_new_version: bool = True):
    if use_new_version:
        from services.task_record_service_new import get_block_results_v2
        return await get_block_results_v2(task_record_id)
    # ... 旧版本逻辑(基于JSON解析)
```

## 数据流示例

### 任务定义

```json
{
  "rootBlock": {
    "id": -1,
    "name": "-1",
    "blockType": "RootBp",
    "children": {
      "default": [
        {
          "id": 5,
          "name": "b3",
          "blockType": "IterateListBp",
          "inputParams": {
            "list": {"value": "[1, 2, 3]"}
          },
          "children": {
            "default": [
              {
                "id": 6,
                "name": "b4",
                "blockType": "PrintBp",
                "inputParams": {
                  "message": {"value": "blocks.b3.index"}
                }
              }
            ]
          }
        }
      ]
    }
  }
}
```

### 日志记录流程

| 时间 | 操作 | 日志记录 |
|------|------|---------|
| T1 | 开始第1次循环 | `log_id=L1, task_block_id=b3, log_type=iteration_start, iteration_index=0, parent_log_id=null` |
| T2 | 执行打印块 | `log_id=L2, task_block_id=b4, log_type=block_execution, iteration_index=0, parent_log_id=L1` |
| T3 | 开始第2次循环 | `log_id=L3, task_block_id=b3, log_type=iteration_start, iteration_index=1, parent_log_id=null` |
| T4 | 执行打印块 | `log_id=L4, task_block_id=b4, log_type=block_execution, iteration_index=1, parent_log_id=L3` |

### 查询结果组织

```json
{
  "blockName": "b3",
  "blockType": "IterateListBp",
  "children": [
    {
      "iterationIndex": 0,
      "iterationLogs": [
        {"logId": "L1", "message": "第1次循环, item=1"}
      ],
      "children": [
        {
          "blockName": "b4",
          "logs": [
            {"logId": "L2", "message": "打印: 0", "parent_log_id": "L1"}
          ]
        }
      ]
    },
    {
      "iterationIndex": 1,
      "iterationLogs": [
        {"logId": "L3", "message": "第2次循环, item=2"}
      ],
      "children": [
        {
          "blockName": "b4",
          "logs": [
            {"logId": "L4", "message": "打印: 1", "parent_log_id": "L3"}
          ]
        }
      ]
    }
  ]
}
```

## 优势

1. **数据完整性**: 日志记录时就建立层级关系,不依赖运行时的内存状态
2. **查询性能**: 通过索引直接查询层级关系,无需解析JSON
3. **前端友好**: 返回的嵌套结构清晰,循环日志和子块日志自然组织在一起
4. **可扩展性**: `log_type` 字段便于未来扩展其他类型的日志
5. **向后兼容**: 保留旧版本逻辑,可通过参数切换

## 测试建议

1. **功能测试**:
   - 执行简单循环任务(1层循环)
   - 执行嵌套循环任务(2-3层循环)
   - 验证返回的层级结构正确

2. **性能测试**:
   - 对比新旧版本的查询性能
   - 测试大量循环(>100次)的场景

3. **边界测试**:
   - 空循环(数组为空)
   - 循环中断(break)
   - 循环失败(子块报错)

## 后续优化

1. 为其他循环块(`WhileBlockHandler`, `RepeatNumBlockHandler`)应用相同逻辑
2. 考虑为条件分支(`IfBlockHandler`)也记录分支信息
3. 添加日志清理策略(历史数据归档)
