563 lines
13 KiB
Markdown
563 lines
13 KiB
Markdown
# 新项目交叉评查实现方案设计稿
|
||
|
||
> 目标:基于 `leaudit-platform` 当前代码结构,给出交叉评查在新项目中的推荐实现方案,并明确数据模型、接口设计、目录落点、迁移顺序与实施边界。
|
||
|
||
## 1. 背景判断
|
||
|
||
结合当前仓库代码可以确认:
|
||
|
||
- 前端交叉评查页面已经存在于 `new_doc_review`
|
||
- RBAC 路由中已经存在 `/cross-checking`
|
||
- 新平台文档与评查底座已经切到 `leaudit_*`
|
||
- 但交叉评查协作层仍未完整迁入 `fastapi_modules/fastapi_leaudit`
|
||
|
||
当前现状更接近:
|
||
|
||
- 页面壳子是新的
|
||
- 文档与评查引擎底座是新的
|
||
- 交叉评查业务逻辑仍然大量沿用老系统思维和老接口口径
|
||
|
||
因此,交叉评查在新项目中的核心任务,不是“新做一个页面”,而是把“协作复核层”从老系统迁到新平台。
|
||
|
||
## 2. 总体设计原则
|
||
|
||
推荐遵循以下原则:
|
||
|
||
### 2.1 交叉评查是协作层,不是评查引擎层
|
||
|
||
交叉评查不负责:
|
||
|
||
- OCR
|
||
- 文本抽取
|
||
- 规则执行
|
||
- 原始机器评查结果生成
|
||
|
||
交叉评查只负责:
|
||
|
||
- 任务
|
||
- 参与人
|
||
- 文档挂载
|
||
- 提案
|
||
- 投票
|
||
- 完成确认
|
||
- 结果展示叠加
|
||
|
||
### 2.2 原始评查结果尽量不可变
|
||
|
||
不建议像老系统那样把通过提案直接回写到旧 `evaluation_results.final_score`。
|
||
|
||
新平台里更合理的方式是:
|
||
|
||
- `leaudit_rule_results` 保留机器评查真相
|
||
- `leaudit_review_point_audits` 保留人工审核覆盖
|
||
- `leaudit_cross_review_proposals` 保留交叉评查加减分提案
|
||
- 页面展示时动态聚合出最终展示分数
|
||
|
||
### 2.3 交叉评查单独建模,不污染 LeAudit 核心表
|
||
|
||
推荐新增专属表:
|
||
|
||
- `leaudit_cross_review_tasks`
|
||
- `leaudit_cross_review_task_members`
|
||
- `leaudit_cross_review_task_documents`
|
||
- `leaudit_cross_review_proposals`
|
||
- `leaudit_cross_review_votes`
|
||
|
||
### 2.4 版本归纳使用新平台版本能力
|
||
|
||
不要继续使用老系统“同名 + 同类型推断版本”的方案作为主路径。
|
||
|
||
新平台已有:
|
||
|
||
- `leaudit_documents.versionGroupKey`
|
||
- `leaudit_documents.versionNo`
|
||
- `leaudit_documents.previousVersionId`
|
||
- `leaudit_documents.rootVersionId`
|
||
- `leaudit_documents.isLatestVersion`
|
||
|
||
交叉评查列表应优先基于这些字段实现版本归纳。
|
||
|
||
### 2.5 权限必须后端收口
|
||
|
||
前端可以决定是否显示按钮,但最终权限校验必须在后端 service 层完成。
|
||
|
||
不能继续依赖前端自己拼 PostgREST 查询判断权限。
|
||
|
||
## 3. 新项目里可直接复用的基础能力
|
||
|
||
## 3.1 文档主链路
|
||
|
||
现有能力:
|
||
|
||
- 上传文档:`fastapi_modules/fastapi_leaudit/controllers/documentController.py`
|
||
- 文档服务:`fastapi_modules/fastapi_leaudit/services/impl/documentServiceImpl.py`
|
||
- 文档主表:`fastapi_modules/fastapi_leaudit/models/leauditDocument.py`
|
||
- 文档文件表:`fastapi_modules/fastapi_leaudit/models/leauditDocumentFile.py`
|
||
|
||
可复用点:
|
||
|
||
- 文档上传
|
||
- OSS 存储
|
||
- 文档版本管理
|
||
- 附件追加
|
||
- 文档详情读取
|
||
|
||
## 3.2 评查运行与结果主链路
|
||
|
||
现有能力:
|
||
|
||
- 评查运行主表:`fastapi_modules/fastapi_leaudit/models/leauditAuditRun.py`
|
||
- 评查运行控制器:`fastapi_modules/fastapi_leaudit/controllers/auditController.py`
|
||
- 评查详情聚合:`DocumentServiceImpl.GetReviewPoints()`
|
||
|
||
可复用点:
|
||
|
||
- 评查运行追踪
|
||
- 详情页规则结果聚合
|
||
- 人工审核结果叠加
|
||
|
||
## 3.3 详情页结果聚合
|
||
|
||
现有 VO:
|
||
|
||
- `fastapi_modules/fastapi_leaudit/domian/vo/reviewPointVo.py`
|
||
|
||
现有能力:
|
||
|
||
- `ReviewPointsAggregateVO`
|
||
- `scoring_proposals`
|
||
- `ReviewPointResultVO.finalScore`
|
||
- `ReviewPointResultVO.machineScore`
|
||
|
||
这意味着:
|
||
|
||
- 详情页主结构已经可承载交叉评查提案数据
|
||
- 只需把“提案来源”和“最终分数计算方式”替换为新模型
|
||
|
||
## 4. 目标架构
|
||
|
||
推荐架构分成两层:
|
||
|
||
### 4.1 LeAudit 评查结果层
|
||
|
||
职责:
|
||
|
||
- 文档上传
|
||
- 规则执行
|
||
- 机器评查结果生成
|
||
- 人工审核覆盖记录
|
||
|
||
主要表:
|
||
|
||
- `leaudit_documents`
|
||
- `leaudit_document_files`
|
||
- `leaudit_audit_runs`
|
||
- `leaudit_rule_results`
|
||
- `leaudit_review_point_audits`
|
||
|
||
### 4.2 Cross Review 协作层
|
||
|
||
职责:
|
||
|
||
- 交叉评查任务
|
||
- 成员管理
|
||
- 任务文档挂载
|
||
- 加减分提案
|
||
- 投票
|
||
- 文档完成确认
|
||
- 协作态进度管理
|
||
|
||
主要表:
|
||
|
||
- `leaudit_cross_review_tasks`
|
||
- `leaudit_cross_review_task_members`
|
||
- `leaudit_cross_review_task_documents`
|
||
- `leaudit_cross_review_proposals`
|
||
- `leaudit_cross_review_votes`
|
||
|
||
## 5. 新数据模型设计
|
||
|
||
## 5.1 `leaudit_cross_review_tasks`
|
||
|
||
任务主表。
|
||
|
||
建议字段:
|
||
|
||
- `id`
|
||
- `task_name`
|
||
- `task_type`
|
||
- `doc_type_id`
|
||
- `doc_type_code`
|
||
- `assigner_id`
|
||
- `status`
|
||
- `created_at`
|
||
- `updated_at`
|
||
- `deleted_at`
|
||
|
||
说明:
|
||
|
||
- `status` 建议值:`pending`、`in_progress`、`completed`
|
||
- `doc_type_id` 可用于快速关联新平台文档类型
|
||
- `doc_type_code` 用于兼容前端和历史口径
|
||
|
||
## 5.2 `leaudit_cross_review_task_members`
|
||
|
||
任务成员表。
|
||
|
||
建议字段:
|
||
|
||
- `id`
|
||
- `task_id`
|
||
- `user_id`
|
||
- `member_role`
|
||
- `created_at`
|
||
- `updated_at`
|
||
- `deleted_at`
|
||
|
||
说明:
|
||
|
||
- `member_role` 建议值:`participant`、`principal`
|
||
- 任务创建者不建议仅放数组,应显式保存在任务主表 `assigner_id`
|
||
|
||
## 5.3 `leaudit_cross_review_task_documents`
|
||
|
||
任务文档表。
|
||
|
||
建议字段:
|
||
|
||
- `id`
|
||
- `task_id`
|
||
- `document_id`
|
||
- `audit_status`
|
||
- `created_at`
|
||
- `updated_at`
|
||
- `deleted_at`
|
||
|
||
说明:
|
||
|
||
- `audit_status=0` 表示未完成
|
||
- `audit_status=1` 表示已确认完成
|
||
- 这是任务内状态,不是文档全局状态
|
||
|
||
## 5.4 `leaudit_cross_review_proposals`
|
||
|
||
提案表。
|
||
|
||
建议字段:
|
||
|
||
- `id`
|
||
- `task_id`
|
||
- `document_id`
|
||
- `rule_result_id`
|
||
- `proposer_id`
|
||
- `proposed_score_delta`
|
||
- `reason`
|
||
- `status`
|
||
- `created_at`
|
||
- `updated_at`
|
||
- `deleted_at`
|
||
|
||
说明:
|
||
|
||
- `rule_result_id` 应关联 `leaudit_rule_results.id`
|
||
- `proposed_score_delta` 使用增量值,正数加分,负数扣分
|
||
- `status` 建议值:`pending`、`approved`、`rejected`、`cancelled`
|
||
|
||
## 5.5 `leaudit_cross_review_votes`
|
||
|
||
投票表。
|
||
|
||
建议字段:
|
||
|
||
- `id`
|
||
- `proposal_id`
|
||
- `voter_id`
|
||
- `vote_type`
|
||
- `created_at`
|
||
- `updated_at`
|
||
- `deleted_at`
|
||
|
||
说明:
|
||
|
||
- `vote_type` 建议值:`agree`、`disagree`
|
||
- `cancel` 建议用软删除表示,不必单独存为最终值
|
||
|
||
## 6. 关键业务规则如何映射到新平台
|
||
|
||
## 6.1 创建任务
|
||
|
||
目标保留的老规则:
|
||
|
||
- 创建者强制加入任务成员
|
||
- 可指定普通参与人和主要负责人
|
||
- 任务创建时可同时挂一批文档
|
||
|
||
新实现建议:
|
||
|
||
- 创建任务时先写 `leaudit_cross_review_tasks`
|
||
- 再写 `leaudit_cross_review_task_members`
|
||
- 再写 `leaudit_cross_review_task_documents`
|
||
|
||
## 6.2 文档访问校验
|
||
|
||
目标保留的老规则:
|
||
|
||
- 只有任务成员才能看任务文档
|
||
- 提案必须绑定任务内文档
|
||
|
||
新实现建议:
|
||
|
||
- 不再让前端自己查 `cross_task_document_mapping`
|
||
- 提供统一后端方法:
|
||
- `CheckTaskMember(taskId, userId)`
|
||
- `CheckTaskDocument(taskId, documentId)`
|
||
- `CheckTaskDocumentRuleResult(documentId, ruleResultId)`
|
||
|
||
## 6.3 提案创建
|
||
|
||
目标保留的老规则:
|
||
|
||
- 必须是任务参与者
|
||
- 同一用户不能对同一评查点重复创建有效提案
|
||
- 不允许 0 分提案
|
||
- 当前分数为 0 时不能继续扣
|
||
- 当前已满分时不能继续加
|
||
|
||
新实现建议:
|
||
|
||
- 通过 `rule_result_id` 读取对应规则结果
|
||
- 计算当前展示分数
|
||
- 校验是否还能继续加减
|
||
- 写入 `leaudit_cross_review_proposals`
|
||
- 自动插入一条提案人同意票
|
||
|
||
## 6.4 投票与状态流转
|
||
|
||
目标保留的老规则:
|
||
|
||
- 采用绝对多数制
|
||
- 阈值为 `floor(n / 2) + 1`
|
||
|
||
新实现建议:
|
||
|
||
- `n` 基于 `leaudit_cross_review_task_members` 统计活跃成员
|
||
- 同意达到阈值 -> `approved`
|
||
- 反对达到阈值 -> `rejected`
|
||
- 剩余票全部同意也无法通过 -> `rejected`
|
||
|
||
## 6.5 文档完成确认
|
||
|
||
目标保留的老规则:
|
||
|
||
- 只有创建者或负责人可确认
|
||
- 文档完成改的是任务内状态
|
||
- 全部文档完成后任务才完成
|
||
|
||
新实现建议:
|
||
|
||
- 确认文档完成时更新 `leaudit_cross_review_task_documents.audit_status`
|
||
- 若同任务下所有未删除文档都为完成,则更新 `leaudit_cross_review_tasks.status = completed`
|
||
|
||
## 6.6 分数计算
|
||
|
||
这是新实现里最重要的变化。
|
||
|
||
### 不建议
|
||
|
||
- 直接更新 `leaudit_rule_results.score`
|
||
- 直接写回机器结果源字段
|
||
|
||
### 建议
|
||
|
||
按聚合方式计算展示分数:
|
||
|
||
- `machineScore`:来自 `leaudit_rule_results`
|
||
- `auditOverride`:来自 `leaudit_review_point_audits`
|
||
- `crossReviewDelta`:来自所有已通过的 `leaudit_cross_review_proposals`
|
||
- `finalScore`:在详情页聚合阶段动态计算
|
||
|
||
建议公式:
|
||
|
||
1. 先根据机器结果与人工审核确定基础结果
|
||
2. 基础结果换算出基础得分
|
||
3. 加上 `approved` 提案累计增量
|
||
4. 最终再做上下限裁剪:
|
||
- 不低于 0
|
||
- 不高于规则满分
|
||
|
||
## 7. 详情页如何接入新实现
|
||
|
||
当前详情页主入口已经存在:
|
||
|
||
- `fastapi_modules/fastapi_leaudit/controllers/documentController.py`
|
||
- `GET /v3/review-points/{DocumentId}`
|
||
|
||
建议做法:
|
||
|
||
### 7.1 保留 `GetReviewPoints()` 作为主入口
|
||
|
||
这样前端详情页无需大改。
|
||
|
||
### 7.2 修改 `_loadScoringProposals()`
|
||
|
||
当前只是兼容读取旧 `cross_scoring_proposals`。
|
||
|
||
建议改为:
|
||
|
||
- 优先读取 `leaudit_cross_review_proposals`
|
||
- 若尚未迁移完成,可保留旧表兼容兜底一段时间
|
||
|
||
### 7.3 修改评查点聚合逻辑
|
||
|
||
在 `_loadReviewPointResults()` 或其上层聚合逻辑中:
|
||
|
||
- 读取单点所有已批准提案的分值增量
|
||
- 计算 `finalScore`
|
||
- 继续把提案列表放入 `scoring_proposals`
|
||
|
||
### 7.4 前端详情页不用重构为新的页面协议
|
||
|
||
保持 `ReviewPointsAggregateVO` 不变或小幅扩展即可。
|
||
|
||
## 8. 任务列表和任务文档列表如何实现
|
||
|
||
## 8.1 任务列表
|
||
|
||
返回建议字段:
|
||
|
||
- `task_id`
|
||
- `task_name`
|
||
- `task_status`
|
||
- `doc_type`
|
||
- `task_type`
|
||
- `task_created_at`
|
||
- `progress`
|
||
- `total_documents`
|
||
- `evaluation_region`
|
||
|
||
实现来源:
|
||
|
||
- 任务主表
|
||
- 成员表
|
||
- 任务文档表
|
||
|
||
## 8.2 任务文档列表
|
||
|
||
建议按以下逻辑组织:
|
||
|
||
1. 先取任务绑定文档
|
||
2. 通过 `leaudit_documents.versionGroupKey` 做版本归组
|
||
3. 当前版本优先取 `isLatestVersion = true`
|
||
4. 统计信息来自 `leaudit_rule_results`
|
||
5. 最终展示分数叠加 `approved` 提案增量
|
||
|
||
## 8.3 不建议继续使用旧版“同名同类型猜版本”
|
||
|
||
因为新平台已经有更稳定的版本链字段,不必再依赖脆弱的文件名规则。
|
||
|
||
## 9. 上传与追加附件的实现建议
|
||
|
||
## 9.1 推荐长期方案
|
||
|
||
采用“文档系统”和“交叉评查系统”解耦:
|
||
|
||
1. 先用通用文档接口上传
|
||
2. 拿到 `documentId`
|
||
3. 再把文档挂入交叉任务
|
||
|
||
优点:
|
||
|
||
- 复用现有 `DocumentServiceImpl.Upload`
|
||
- 文档生命周期统一
|
||
- 附件处理逻辑不重复
|
||
|
||
## 9.2 推荐短期兼容方案
|
||
|
||
为兼容当前前端,可先提供聚合接口:
|
||
|
||
- `UploadAndCreateTask`
|
||
- `UploadDocumentsToTask`
|
||
- `AppendTaskDocumentAttachments`
|
||
|
||
这些接口内部再调用:
|
||
|
||
- `DocumentService.Upload`
|
||
- `DocumentService.AppendAttachments`
|
||
|
||
这样前端先不需要大改。
|
||
|
||
## 10. 权限设计
|
||
|
||
建议保留现有 RBAC 权限点:
|
||
|
||
- `cross_review:task:read`
|
||
- `cross_review:task:create`
|
||
- `cross_review:progress:view`
|
||
- `cross_review:proposal:create`
|
||
- `cross_review:proposal:read`
|
||
- `cross_review:proposal:delete`
|
||
- `cross_review:proposal:vote`
|
||
- `cross_review:document:complete`
|
||
|
||
同时叠加业务层权限判断:
|
||
|
||
- 是否任务成员
|
||
- 是否创建者
|
||
- 是否主要负责人
|
||
- 文档是否属于任务
|
||
- 评查点结果是否属于该文档
|
||
|
||
## 11. 推荐实施顺序
|
||
|
||
### 第一阶段:先建协作层表和后端接口
|
||
|
||
目标:
|
||
|
||
- 新建 `leaudit_cross_review_*` 表
|
||
- 新建 `CrossReviewController / Service / DTO / VO`
|
||
- 打通任务、提案、投票、完成确认
|
||
|
||
### 第二阶段:详情页切新提案逻辑
|
||
|
||
目标:
|
||
|
||
- `GetReviewPoints()` 改读新提案表
|
||
- 动态计算最终分数
|
||
- 详情页不再依赖旧 `cross_scoring_proposals`
|
||
|
||
### 第三阶段:任务文档列表切新版本底座
|
||
|
||
目标:
|
||
|
||
- 改用 `leaudit_documents` 版本字段归组
|
||
- 任务内分数与统计改读新平台结果
|
||
|
||
### 第四阶段:前端路径和历史兼容收口
|
||
|
||
目标:
|
||
|
||
- 逐步下线 `/admin/v2/cross_review/*` 历史兼容口径
|
||
- 清理前端直查旧表逻辑
|
||
- 清理旧 `cross_*` 兼容读取
|
||
|
||
## 12. 风险与注意事项
|
||
|
||
### 12.1 最大风险:最终分数语义变化
|
||
|
||
如果继续沿用老系统“直接回写”的做法,会污染新平台结果底座。
|
||
|
||
建议统一改为聚合展示分数。
|
||
|
||
### 12.2 第二风险:前端隐式依赖旧接口字段
|
||
|
||
当前 `new_doc_review/app/api/cross-checking/*` 里仍存在很多历史字段名和旧路径假设。
|
||
|
||
新后端第一期最好兼容这些字段,避免前端同步改动过大。
|
||
|
||
### 12.3 第三风险:权限校验分散
|
||
|
||
当前部分前端仍尝试自行查表判断权限。
|
||
|
||
迁移时应尽快把权限判断收敛到后端。
|
||
|