mi-assessment/docs/报告状态拆分需求文档.md
2026-03-18 01:13:44 +08:00

187 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 报告状态拆分需求文档
## 一、背景
当前测评记录的状态定义如下:
| 状态值 | 含义 |
|--------|------|
| 1 | 待测评 |
| 2 | 测评中 |
| 3 | 生成中 |
| 4 | 已完成 |
| 5 | 生成失败 |
"生成中"(状态 3实际包含了两个阶段
1. **数据计算阶段**:根据答案计算得分、排名、星级、匹配结论,写入 `assessment_results``assessment_record_conclusions`
2. **PDF 生成阶段**:截图各报告网页 → 组装 PDF → 上传 COS
这两个阶段被合并在同一个状态 3 下,导致以下问题:
### 问题 1截图服务截到空白页
PDF 生成阶段需要截图报告网页,但报告网页的数据接口(`ReportDataService`)检查状态必须为 4已完成才返回数据。此时状态还是 3所以所有页面都返回"报告尚未生成完成",截出来全是空白。
### 问题 2网页报告不必等 PDF
数据计算完成后,网页报告所需的数据已经全部就绪,用户完全可以查看网页版报告。但因为状态还是 3前端不显示"网页报告"按钮,用户必须等 PDF 生成完(状态变为 4才能看到任何报告内容。
### 问题 3职责不清晰
"数据是否就绪"和"PDF 是否生成"是两件独立的事,不应该用同一个状态来表示。
## 二、方案
新增状态值 6数据已就绪将原来的状态 3 拆分为两个阶段:
| 状态值 | 含义 | 说明 |
|--------|------|------|
| 1 | 待测评 | 不变 |
| 2 | 测评中 | 不变 |
| 3 | 生成中 | 数据计算阶段(得分、排名、星级、结论尚未完成) |
| **6** | **数据已就绪** | **数据计算完成PDF 正在生成中** |
| 4 | 已完成 | PDF 生成完成,全部就绪 |
| 5 | 生成失败 | 不变(数据计算失败或 PDF 生成失败均为此状态) |
### 状态流转图
```
[1 待测评] → [2 测评中] → [3 生成中]
数据计算完成
[6 数据已就绪]
PDF 生成完成
[4 已完成]
失败路径:
[3 生成中] → [5 生成失败](数据计算失败,重试 3 次后)
[6 数据已就绪] → [5 生成失败]PDF 生成失败)
```
### 各状态下的功能可用性
| 功能 | 状态 3 | 状态 6 | 状态 4 | 状态 5 |
|------|--------|--------|--------|--------|
| 查看网页报告 | ❌ | ✅ | ✅ | ❌ |
| 查看 PDF | ❌ | ❌ | ✅(需有 reportUrl | ❌ |
| 下载 PDF | ❌ | ❌ | ✅(需有 reportUrl | ❌ |
| 重新生成 | ✅ | ✅ | ✅ | ✅ |
| 查看报告数据(后台) | ❌ | ✅ | ✅ | ❌ |
## 三、涉及修改的文件清单
### 3.1 后端 - 核心流程
| 文件 | 修改内容 |
|------|----------|
| `MiAssessment.Core/Services/ReportGenerationService.cs` | `PersistResultsAsync` 方法:数据写入完成后将状态从 3 改为 6 |
| `MiAssessment.Core/Services/ReportDataService.cs` | `GetReportDataAsync` 方法:状态检查从 `== 4` 改为 `== 6 \|\| == 4` |
| `MiAssessment.Core/Services/PdfGenerationService.cs` | `GeneratePdfAsync` 方法PDF 生成失败时状态从 6 改为 5已修复的静态图片路径问题保留 |
| `MiAssessment.Api/BackgroundServices/ReportQueueConsumer.cs` | `ProcessMessageAsync` 方法PDF 生成失败时调用 `UpdateRecordStatusToFailedAsync` 不变,但此时记录状态是从 6 变为 5 |
### 3.2 后端 - 后台管理
| 文件 | 修改内容 |
|------|----------|
| `MiAssessment.Admin.Business/Services/AssessmentRecordService.cs` | 1. `StatusNames` 字典新增 `{ 6, "数据已就绪" }`<br>2. `RegenerateReportAsync`:状态检查增加 6允许 3、4、5、6 重新生成)<br>3. `BatchRegenerateReportAsync`:同上 |
| `MiAssessment.Admin.Business/Services/AssessmentRecordService.cs` | `GetRecordReportAsync` 方法:状态检查从 `== 4` 改为 `== 6 \|\| == 4` |
### 3.3 前端 - 后台管理
| 文件 | 修改内容 |
|------|----------|
| `admin-web/src/views/business/assessment/record/index.vue` | 1. 搜索表单状态下拉:新增选项 `<el-option label="数据已就绪" :value="6" />`<br>2. "报告"按钮:`v-if` 从 `row.status === 4` 改为 `row.status === 6 \|\| row.status === 4`<br>3. "网页报告"按钮:`v-if` 从 `row.status === 4` 改为 `row.status === 6 \|\| row.status === 4`<br>4. "查看PDF"按钮:保持 `v-if="row.reportUrl"` 不变(状态 6 时 reportUrl 为空,自然不显示)<br>5. "下载PDF"按钮:保持 `v-if="row.reportUrl"` 不变<br>6. "重新生成"按钮:`v-if` 增加 `row.status === 6`<br>7. `getStatusTagType` 函数:新增 `case 6: return 'primary'`<br>8. 批量重新生成 `eligibleRows` 过滤:增加状态 6 |
### 3.4 前端 - 小程序(如已实现相关页面)
| 文件 | 修改内容 |
|------|----------|
| 测评结果状态轮询页 | 状态 6 时可跳转查看网页报告,不再需要等到状态 4 |
| 往期测评列表 | 状态 6 显示"报告已就绪",允许查看网页报告 |
> 注:小程序前端如果尚未开发对应页面,此部分可后续处理。
## 四、详细修改说明
### 4.1 ReportGenerationService.PersistResultsAsync
当前代码(状态保持 3
```csharp
// 重新加载测评记录(带跟踪),保持 Status=3生成中等待 PDF 生成后再更新为4
var record = await _dbContext.AssessmentRecords
.FirstAsync(r => r.Id == recordId);
record.UpdateTime = now;
```
修改为(状态改为 6
```csharp
// 数据计算完成,状态更新为 6数据已就绪等待 PDF 生成后再更新为 4
var record = await _dbContext.AssessmentRecords
.FirstAsync(r => r.Id == recordId);
record.Status = 6;
record.UpdateTime = now;
```
### 4.2 ReportDataService.GetReportDataAsync
当前代码:
```csharp
if (record.Status != 3 && record.Status != 4)
```
修改为:
```csharp
if (record.Status != 6 && record.Status != 4)
```
说明:去掉状态 3 的放行(上一轮临时加的),改为只允许 6 和 4。状态 3 时数据还没算完,不应该渲染。
### 4.3 前端按钮逻辑汇总
```
报告按钮(后台抽屉): row.status === 6 || row.status === 4
网页报告按钮: row.status === 6 || row.status === 4
查看 PDF 按钮: row.reportUrl不变状态 6 时 reportUrl 为空)
下载 PDF 按钮: row.reportUrl不变
重新生成按钮: row.status === 3 || row.status === 4 || row.status === 5 || row.status === 6
```
## 五、数据库影响
### 5.1 无需修改表结构
`assessment_records.Status` 字段为 `int` 类型,直接使用新值 6 即可,无需 DDL 变更。
### 5.2 历史数据兼容
- 已有的状态 4 记录不受影响
- 已有的状态 3 记录(如果有卡在生成中的)不受影响,重新生成时会走新流程
- 已有的状态 5 记录不受影响
## 六、测试要点
| 场景 | 预期结果 |
|------|----------|
| 提交答案后触发报告生成 | 状态从 2 → 3 → 6 → 4 |
| 数据计算完成、PDF 未生成时 | 状态为 6网页报告可查看PDF 按钮不显示 |
| PDF 生成完成后 | 状态为 4网页报告和 PDF 均可查看 |
| 数据计算失败(重试 3 次后) | 状态为 5 |
| PDF 生成失败 | 状态从 6 → 5网页报告不可查看因为状态变为 5 |
| 状态 6 时点击重新生成 | 状态从 6 → 3重新走完整流程 |
| 状态 4 时点击重新生成 | 状态从 4 → 3ReportUrl 清空,重新走完整流程 |
| 后台搜索状态筛选 | 下拉框包含"数据已就绪"选项,可正确筛选 |
| 批量重新生成 | 状态 3、4、5、6 的记录均可被选中 |
## 七、关于 PDF 生成失败的状态处理
当前方案PDF 生成失败时状态从 6 改为 5生成失败
这意味着用户在 PDF 生成失败后也无法查看网页报告了(因为状态 5 不允许)。
**备选方案**PDF 生成失败时状态保持 6只是 reportUrl 为空。这样用户至少还能看网页报告。但这样的话"生成失败"状态就只表示数据计算失败了。
**建议采用当前方案**(失败改为 5理由
- 状态 5 明确告诉管理员"这条记录有问题需要处理"
- 管理员可以点击"重新生成"重试
- 如果保持 6管理员可能不知道 PDF 生成失败了
如果你觉得 PDF 失败后还应该能看网页报告,我可以调整方案。