Files
ctms/docs/audits/setup-config-code-audit.md
T
2026-03-30 17:36:09 +08:00

4.5 KiB
Raw Blame History

立项配置代码审计报告

状态: archived 适用范围: setup-config 审计时间: 2026-02

范围

  • 前端:frontend/src/views/admin/ProjectDetail.vuefrontend/src/api/studies.tsfrontend/src/types/setupConfig.tsfrontend/src/utils/setupFieldLocator.ts
  • 后端:backend/app/api/v1/studies.pybackend/app/crud/study_setup_config.pybackend/app/schemas/study_setup_config.pybackend/app/services/setup_config_excel.py
  • 文档:docs/guides/setup-config-api.mddocs/setup-config-curl-smoke.shdocs/postman/setup-config.postman_collection.jsonbackend/scripts/smoke_setup_config.py

发现清单

严重(会导致错误或明显行为偏差)

  • 无新增严重问题。

中等(会导致交互不一致或维护风险)

  1. ProjectDetail.vue 中存在大量 v-if="false" 历史分支(Step4-7),增加阅读成本并容易引发误改。
  2. 步骤表格从“输入态表格”转“展示态 + 抽屉编辑”后,存在未清理的旧方法与旧样式残留,导致逻辑路径复杂。
  3. “发布预览”语义已切换为“当前草稿只读预览”,但文档未明确,容易与后端 published_data 概念混淆。

低(代码异味/重复/可读性)

  1. ProjectDetail.vue 文件过长(约 3800+ 行),后续改动冲突概率高。
  2. 多个步骤编辑抽屉逻辑重复,适合后续抽象为通用 RowEditorDrawer
  3. 表格列模板重复,适合后续改为列配置驱动。

本轮已处理

  1. 删除 Step4-7 全部 v-if="false" 模板分支。
  2. 删除上述分支遗留的无用方法:
    • handleSiteMilestoneSiteChange
    • handleSiteEnrollmentSiteChange
    • handleCenterConfirmSiteChange
    • touchStrategy
    • applyStrategy
  3. 清理无用样式:
    • .section-toolbar
    • .setup-content.is-published-preview .section-toolbar 相关规则
  4. 保持现有交互行为不变并完成构建验证。
  5. 修复步骤标题行按钮保护不一致问题:
    • 第2/4/5/6/7步标题行功能键增加 :disabled="!canEditSetup",避免锁定项目或无权限时误触发。
    • 对应新增/删除/抽屉打开与保存方法统一加守卫,防止外部调用绕过前端可见状态。
  6. 收敛重复的草稿可编辑判定,新增 canMutateDraft() 供步骤行编辑方法复用(不改变界面行为)。
  7. 抽取步骤行编辑通用控制器(IndexedEditorController)与通用函数:
    • openIndexedEditor
    • getEditingIndex
    • closeIndexedEditor 复用到 Step2/4/5/6/7 的单行抽屉编辑逻辑,减少重复代码。
  8. 合并重复 onMounted 注册逻辑,统一在单一入口完成 loadProjectbeforeunload 监听初始化。
  9. 新增 frontend/src/composables/useSetupConfig.ts
    • 将 setup-config 相关 API 编排从页面中收口到 composable(获取/保存/发布/版本列表/回滚/版本删除/Excel 导入导出)。
    • ProjectDetail.vue 改为依赖 composable 暴露的方法,降低页面对 API 层的直接耦合。
  10. 新增 frontend/src/utils/setupDiffRows.ts
  • 将“步骤差异明细”计算与字段路径可读化逻辑从 ProjectDetail.vue 抽离为工具函数。
  • 页面保留项目主字段差异拼装,步骤差异统一由工具输出,降低页面认知负担。
  1. 将步骤标题行按钮显隐规则收敛为 stepActionMode 计算属性:
  • 去除模板中多段 activeStep === n && !isPublishedView 分支。
  • 保持按钮行为与权限控制不变,降低后续步骤扩展的修改面。

验证结果

  1. frontend npm run build 通过。
  2. 后端 setup-config 核心文件通过 AST 语法解析检查。
  3. 当前环境 npx tsc --noEmit 失败主要来自项目既有依赖类型版本不匹配(vue/element-plus/csstype),非本轮立项配置改动引入。

一致性核对结果

  1. 前后端 setup-config 路由一致:
    • GET/PUT /setup-config
    • POST /setup-config/publish
    • GET /setup-config/versions
    • POST /setup-config/rollback
    • DELETE /setup-config/versions/{target_version}
    • GET /setup-config/export-excel
    • POST /setup-config/import-excel
  2. 前端 setupConfig 类型与后端 schema 字段一致(published_data 仍保留用于发布快照与差异比较)。

下一步建议(不改行为)

  1. 拆分 ProjectDetail.vue 为步骤子组件(先拆 Step4-7)。
  2. 抽象通用行编辑抽屉组件,统一校验和保存流程。
  3. 使用列配置对象复用 el-table-column 渲染,降低重复模板。