# 新项目交叉评查实现方案设计稿 > 目标:基于 `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 第三风险:权限校验分散 当前部分前端仍尝试自行查表判断权限。 迁移时应尽快把权限判断收敛到后端。