# 审批意见栏字段升级 - 运维操作手册

**版本**: v2.0  
**目标读者**: 系统运维人员  
**风险等级**: 中等（可完全回滚）  
**预计耗时**: 测试环境 30-60 分钟，生产环境 15-30 分钟

---

## 📑 目录

1. [升级概述](#一升级概述)
2. [前置条件](#二前置条件)
3. [测试环境验证](#三测试环境验证)
4. [生产环境执行](#四生产环境执行)
5. [回滚方案](#五回滚方案)
6. [验证检查清单](#六验证检查清单)
7. [常见问题](#七常见问题)
8. [附录](#八附录)

---

## 一、升级概述

### 1.1 升级目的

将老版本审批意见栏字段的非标准配置（如 `{traces.审批}`、`{yijianlan:{step:'审核'}}`）转换为结构化的 `config` 对象格式。

### 1.2 升级影响范围

| 项目 | 影响说明 |
|------|---------|
| **数据库集合** | `forms` 集合（表单定义） |
| **处理范围** | 仅处理 `state: 'enabled'` 的表单 |
| **不影响** | ① 已提交的申请单（`instances` 集合）<br>② 流程定义（`flows` 集合）<br>③ 禁用状态的表单 |
| **可回滚性** | ✅ 完全可回滚 |

### 1.3 核心转换规则

#### 场景1: 简单 traces 模式
```json
// 转换前
{
  "type": "input",
  "formula": "{traces.部门审批}"
}

// 转换后
{
  "type": "steedos-field",
  "__approval_comments_transformed": true,
  "__approval_comments_original_type": "input",
  "__approval_comments_original_formula": "{traces.部门审批}",
  "config": {
    "type": "approval_comments",
    "label": "部门审批意见",
    "name": "部门审批意见",
    "object": "",
    "steps": [{
      "name": "部门审批",
      "show_cc": true,
      "show_handler": true,
      "show_image_sign": false
    }]
  }
}
```

#### 场景2: signature.traces 模式（带签章）
```json
// 转换前
{
  "type": "textarea",
  "default_value": "${signature.traces.技术审核}"
}

// 转换后
{
  "type": "steedos-field",
  "__approval_comments_transformed": true,
  "__approval_comments_original_type": "textarea",
  "__approval_comments_original_default_value": "${signature.traces.技术审核}",
  "config": {
    "type": "approval_comments",
    "steps": [{
      "name": "技术审核",
      "show_cc": true,
      "show_handler": true,
      "show_image_sign": true  // signature 前缀自动启用
    }]
  }
}
```

#### 场景3: yijianlan 复杂配置
```json
// 转换前
{
  "type": "input",
  "formula": "{yijianlan:{step:'财务审批',only_cc:true,default:'已审核'}}"
}

// 转换后
{
  "type": "steedos-field",
  "__approval_comments_transformed": true,
  "__approval_comments_original_type": "input",
  "__approval_comments_original_formula": "{yijianlan:{step:'财务审批',only_cc:true,default:'已审核'}}",
  "config": {
    "type": "approval_comments",
    "steps": [{
      "name": "财务审批",
      "show_cc": true,
      "show_handler": false,  // only_cc 逻辑
      "show_image_sign": false,
      "default": "已审核"
    }]
  }
}
```

#### 场景4: AMIS Schema 转换
```json
// amis_schema 字符串内的节点转换
// 转换前
{
  "type": "input-text",
  "label": "审批意见",
  "value": "${signature.traces.总经理审批}",
  "id": "u:abc123"
}

// 转换后
{
  "type": "sfield-approvalcomments",  // 注意：AMIS 用不同的 type
  "label": "审批意见",
  "__approval_comments_original_type": "input-text",
  "config": {
    "type": "approval_comments",
    "steps": [{ "name": "总经理审批", ... }]
  },
  "id": "u:abc123"
  // value 属性已移除
}
```

---

## 二、前置条件

### 2.1 权限要求

- ✅ 数据库管理员权限
- ✅ 应用管理员账号
- ✅ API 接口访问权限

### 2.2 数据库备份（🔴 必须执行）

```bash
# 1. 完整备份
mongodump --host=<host> --port=<port> --db=<database> --out=/backup/$(date +%Y%m%d_%H%M%S)

# 2. 额外备份 forms 集合
mongoexport --host=<host> --port=<port> --db=<database> --collection=forms --out=/backup/forms_backup.json

# 3. 验证备份完整性
ls -lh /backup/
```

**⚠️ 关键**: 没有备份，不允许执行升级操作！

### 2.3 记录当前状态

```bash
# 记录表单数量
mongo <database> --eval "db.forms.countDocuments({state: 'enabled'})"

# 导出样本数据
mongo <database> --eval "db.forms.find({state: 'enabled'}).limit(1).pretty()" > /tmp/sample_before.json
```

---

## 三、测试环境验证

### 3.1 测试数据准备

```bash
# 方案A: 从生产库复制测试数据
mongorestore --host=<test_host> --db=<test_db> /backup/forms_backup.json

# 方案B: 仅复制包含签字字段的表单
mongoexport --host=<prod_host> --db=<prod_db> --collection=forms \
  --query='{"$or":[{"current.fields.formula":{"$regex":"traces|yijianlan"}},{"amis_schema":{"$regex":"signature.traces"}}]}' \
  --out=/tmp/signature_forms.json
mongoimport --host=<test_host> --db=<test_db> --collection=forms --file=/tmp/signature_forms.json
```

### 3.2 执行升级（干跑模式）

```bash
# 干跑测试（不修改数据）
curl "http://<test_server>/api/workflow/migrateApprovalCommentsField?dryRun=true"
```

**检查返回结果**:
```json
{
  "dryRun": true,
  "totalForms": 150,
  "totalFields": 230,
  "errors": []
}
```

### 3.3 执行真实升级

```bash
# 实际执行升级
curl "http://<test_server>/api/workflow/migrateApprovalCommentsField"
```

**预期结果**: `{ "totalForms": 150, "totalFields": 230, "errors": [] }`

### 3.4 验证升级结果

#### 验证 1: 数据库层面
```javascript
// 检查转换后的字段
db.forms.findOne(
  {"current.fields.__approval_comments_transformed": true},
  {"current.fields.$": 1}
).pretty()

// 应包含:
// - type: "steedos-field"
// - __approval_comments_transformed: true
// - __approval_comments_original_type: "input"
// - __approval_comments_original_formula: "{traces.xxx}"
// - config.type: "approval_comments"
// - config.steps: [...]
```

#### 验证 2: 应用层面
1. 登录审批王系统
2. 打开任一包含签字字段的表单
3. 发起新申请
4. **预期**: 审批意见栏正常显示，功能正常

#### 验证 3: 设计器场景（重要！）
```
操作步骤:
1. 选择一个已升级的表单
2. 打开表单设计器 (/api/workflow/form_design?fid=<表单ID>)
3. 查看签字字段的配置

预期结果:
- 设计器中字段显示为 "sfield-approvalcomments" 类型
- 配置完整（type, label, name, config, id 等属性都存在）
- 保存后不会丢失配置
```

**特殊场景: 没有 amis_schema 的表单**
```
操作步骤:
1. 找一个数据库中没有 amis_schema 属性的表单
2. 先执行升级接口（转换 current.fields）
3. 再打开表单设计器

预期结果:
- 设计器自动生成 amis_schema
- 生成的 amis_schema 中签字字段格式正确（sfield-approvalcomments）
- 所有属性完整，无数据丢失
```

### 3.5 执行回滚测试（🔴 必须测试）

```bash
# 执行回滚
curl "http://<test_server>/api/workflow/rollbackApprovalCommentsField"
```

**验证回滚结果**:
```javascript
// 检查字段已还原
db.forms.findOne(
  {"name": "测试表单"},
  {"current.fields": 1}
)

// 应该:
// - type 恢复为原始值（如 "input", "textarea"）
// - formula 或 default_value 恢复
// - 所有 __approval_comments_* 备份属性已清除
// - config 属性已移除
```

**⚠️ 重要**: 如果回滚测试失败，不允许在生产环境执行！

---

## 四、生产环境执行

### 4.1 执行前检查清单

- [ ] 测试环境验证通过
- [ ] 回滚测试通过
- [ ] 生产数据库已完整备份
- [ ] 已通知相关业务人员暂停申请提交（可选）
- [ ] 确认当前时间符合维护窗口

### 4.2 执行升级

```bash
# Step 1: 最后一次备份
mongodump --host=<prod_host> --db=<prod_db> --out=/backup/final_$(date +%Y%m%d_%H%M%S)

# Step 2: 执行升级
curl "http://<prod_server>/api/workflow/migrateApprovalCommentsField"

# Step 3: 记录执行时间和结果
echo "升级执行时间: $(date)" >> /tmp/upgrade_log.txt
```

**执行时长估算**:
- 500 个表单 ≈ 2-3 分钟
- 2000 个表单 ≈ 5-8 分钟

### 4.3 快速验证（5分钟内完成）

```bash
# 1. 检查转换数量
mongo <prod_db> --eval "db.forms.countDocuments({'current.fields.__approval_comments_transformed': true})"

# 2. 抽查样本
mongo <prod_db> --eval "db.forms.findOne({'current.fields.__approval_comments_transformed': true}, {'current.fields.$': 1}).pretty()"

# 3. 检查错误
# 如果返回结果中 errors 数组不为空，立即查看错误详情
```

### 4.4 应用验证（10分钟内完成）

1. 登录审批王
2. 发起一个新申请（选择包含签字字段的表单）
3. 提交审批
4. 审批人查看审批意见栏是否正常

### 4.5 业务用户验证（30分钟内完成）

通知 2-3 个业务用户进行真实业务操作，确认无异常。

---

## 五、回滚方案

### 5.1 回滚触发条件

以下任一情况需立即回滚:
- ❌ 升级后无法发起新申请
- ❌ 审批意见栏无法显示
- ❌ 设计器打开报错或字段配置丢失
- ❌ 业务用户报告关键功能异常

### 5.2 回滚步骤

#### 方式1: API 快速回滚（推荐）

```bash
# 执行回滚接口
curl "http://<server>/api/workflow/rollbackApprovalCommentsField"

# 验证回滚
mongo <database> --eval "db.forms.countDocuments({'current.fields.__approval_comments_transformed': true})"
# 应返回 0
```

#### 方式2: 数据库备份还原（紧急）

```bash
# 停止应用服务（避免数据不一致）
systemctl stop steedos

# 还原备份
mongorestore --host=<host> --db=<database> --drop /backup/final_<timestamp>/

# 启动应用服务
systemctl start steedos

# 验证还原
mongo <database> --eval "db.forms.countDocuments({})"
```

### 5.3 回滚后验证

- [ ] 字段 type 恢复为原始值
- [ ] formula/default_value 恢复
- [ ] 无 __approval_comments_* 备份属性
- [ ] 应用功能正常

---

## 六、验证检查清单

### 6.1 测试环境检查清单

- [ ] 数据备份完成
- [ ] 干跑模式测试通过
- [ ] 实际升级执行成功
- [ ] 数据库字段格式正确
- [ ] 应用层字段显示正常
- [ ] 设计器能正常打开和保存
- [ ] 设计器生成的 amis_schema 格式正确
- [ ] 没有 amis_schema 的表单也能正常处理
- [ ] 新发起申请流程正常
- [ ] 审批流程正常
- [ ] 回滚测试通过
- [ ] 回滚后功能正常
- [ ] 所有转换场景都覆盖（traces, signature.traces, yijianlan）
- [ ] 错误日志检查无异常

### 6.2 生产环境检查清单

- [ ] 测试环境验证全部通过
- [ ] 生产数据库备份完成
- [ ] 维护窗口确认
- [ ] 升级执行成功
- [ ] 快速验证通过（5分钟）
- [ ] 应用验证通过（10分钟）
- [ ] 设计器验证通过
- [ ] 业务用户验证通过（30分钟）
- [ ] 监控24小时无异常
- [ ] 备份文件归档保存

---

## 七、常见问题

### Q1: 升级后发现部分表单字段未转换？

**可能原因**:
1. 字段 formula/default_value 格式不匹配（如拼写错误、括号不匹配）
2. 步骤名为空（如 `{traces.}`）
3. 表单状态不是 'enabled'

**解决方案**:
```bash
# 检查未转换字段
db.forms.find({
  "state": "enabled",
  "$or": [
    {"current.fields.formula": {"$regex": "traces|yijianlan"}},
    {"current.fields.default_value": {"$regex": "traces|yijianlan"}}
  ],
  "current.fields.__approval_comments_transformed": {"$ne": true}
}).pretty()
```

### Q2: 部分表单没有 amis_schema 属性？

**说明**: 这是正常现象，老版本表单可能缺少该属性。

**处理**:
1. 升级脚本会跳过这些表单的 amis_schema 转换
2. 只转换 current.fields 和 historys.fields
3. 当用户打开表单设计器时，设计器会自动生成 amis_schema
4. 设计器现已支持新格式，会正确生成 sfield-approvalcomments 节点

**验证步骤**:
```
1. 找一个没有 amis_schema 的表单
2. 执行升级（current.fields 被转换）
3. 打开设计器 (/api/workflow/form_design?fid=xxx)
4. 检查生成的 amis_schema 格式是否正确
5. 保存并重新打开，确认配置不丢失
```

### Q3: 执行速度慢怎么办？

**原因**: 数据量大或批处理大小不合适。

**解决方案**:
```bash
# 使用 fid 参数分批处理
curl "http://<server>/api/workflow/migrateApprovalCommentsField?fid=<流程ID>"

# 或调整批处理大小（仅用于调优）
curl "http://<server>/api/workflow/migrateApprovalCommentsField?batchSize=200"
```

### Q4: 遇到错误如何处理？

**步骤**:
1. 检查返回的 errors 数组
2. 记录 formId, fieldPath, error 信息
3. 查看具体表单数据
4. 修正数据后重新执行（幂等性保证安全）

### Q5: 如何处理特殊字符或格式？

**示例**:
```javascript
// 特殊字符步骤名
{yijianlan:{step:'部门经理/主管审核'}}

// 中文引号
{yijianlan:{step:"部门审核"}}

// 混合配置
{yijianlan:{step:'审核',only_cc:true,image_sign:true,default:'同意'}}
```

**说明**: 代码已处理这些场景，正常执行即可。

---

## 八、附录

### 8.1 接口参数说明

#### migrateApprovalCommentsField 接口

```
GET /api/workflow/migrateApprovalCommentsField

参数:
  - dryRun: boolean (可选) - true时不修改数据，仅返回统计
  - fid: string (可选) - 流程ID，仅处理指定流程的表单
  - batchSize: number (可选，默认500) - 批处理大小

返回:
  {
    "dryRun": false,
    "totalForms": 150,
    "totalFields": 230,
    "errors": []
  }
```

#### rollbackApprovalCommentsField 接口

```
GET /api/workflow/rollbackApprovalCommentsField

参数:
  - dryRun: boolean (可选) - true时不修改数据，仅返回统计
  - fid: string (可选) - 流程ID，仅回滚指定流程的表单
  - batchSize: number (可选，默认500) - 批处理大小

返回:
  {
    "dryRun": false,
    "totalForms": 150,
    "totalFields": 230,
    "errors": []
  }
```

### 8.2 MongoDB 查询参考

```javascript
// 查找所有已转换的表单
db.forms.find({"current.fields.__approval_comments_transformed": true}).count()

// 查找特定表单的转换字段
db.forms.findOne(
  {"name": "表单名称"},
  {"current.fields": 1}
)

// 查看备份属性
db.forms.findOne(
  {"__approval_comments_original__amis_schema": {"$exists": true}},
  {"amis_schema": 1, "__approval_comments_original__amis_schema": 1}
)

// 检查是否有遗漏
db.forms.find({
  "state": "enabled",
  "$or": [
    {"current.fields.formula": {"$regex": "traces|yijianlan|signature"}},
    {"current.fields.default_value": {"$regex": "traces|yijianlan|signature"}},
    {"amis_schema": {"$regex": "traces|yijianlan|signature"}}
  ],
  "current.fields.__approval_comments_transformed": {"$exists": false}
})
```

### 8.3 联系支持

如遇到无法解决的问题，请收集以下信息联系技术支持:

1. 错误返回的完整 JSON
2. 具体表单的 MongoDB 数据（脱敏后）
3. 操作步骤和时间
4. 数据库版本和表单数量

---

**文档版本**: v2.0  
**最后更新**: 2026-01-31  
**维护人员**: DevOps Team

---

## 附录 D: Web 控制台界面

### 控制台访问

为了提供更好的用户体验，我们开发了一个 Web 控制台界面，运维人员可以通过浏览器直接访问和操作：

**访问地址**: `http://your-server/api/workflow/upgrade/approval-comments-console`

**要求**: 必须以管理员身份登录

### 控制台功能

Web 控制台提供以下功能：

#### 1. 文档查看
- **技术文档**: 详细的技术设计和实现说明
- **操作手册**: 本文档的完整内容

#### 2. 可视化操作
- **升级操作**: 通过表单和按钮执行升级
- **还原操作**: 通过表单和按钮执行还原
- **实时结果显示**: 操作结果即时反馈

#### 3. 集成测试（仅测试环境）
- **自动化测试**: 一键执行完整的升级-还原测试流程
- **结果验证**: 自动验证数据正确性
- **详细报告**: 生成完整的测试报告

### 使用建议

**推荐使用 Web 控制台**，因为它提供了：
- ✅ 更直观的操作界面
- ✅ 实时的结果反馈
- ✅ 内置的安全检查
- ✅ 集成的文档查看
- ✅ 自动化测试功能

**命令行方式**仍然可用，适合：
- 自动化脚本集成
- 批处理任务
- 远程服务器操作

### 安全特性

Web 控制台包含多项安全特性：
- 🔒 仅管理员可访问
- 🔒 生产环境中禁用集成测试
- 🔒 默认启用 Dry Run 模式
- 🔒 关键操作需要确认
- 🔒 环境标识清晰显示

### 界面预览

控制台包含 4 个主要标签页：
1. **技术文档** - 查看详细技术文档
2. **操作手册** - 查看本操作手册
3. **执行操作** - 执行升级和还原操作
4. **集成测试** - 运行自动化测试（测试环境）

每个操作都提供：
- 参数配置（Dry Run、Flow ID、Batch Size）
- 一键执行按钮
- 实时进度显示
- 详细结果展示

---

**使用 Web 控制台可以大大提升操作效率和安全性！**
