# 危化品证上传迁移期间的既有问题记录 原迁移范围:只记录迁移范围外的问题,不修改 Web 或其他既有页面。2026-10-17 用户追加授权修复问题 1、4,问题 2、3 按要求忽略,保留记录但不修改对应功能。 ## 1. Web 上传证书时,保存未等待附件上传结束(已修复) - 位置:`web-admin/src/components/business/pl-plan-cert-upload-dialog/index.vue` 的 `handleSubmit` 和保存按钮。 - 原因:原保存按钮仅按 `hazardProducts.length` 禁用;提交函数直接读取三个证书 URL。`AttachmentUploadField` 在上传完成后才同步 URL,虽暴露 `hasUploading()`,但原弹窗没有引用或检查它。 - 可能影响:慢网下选中文件后立即保存,可能提交旧 URL 并关闭弹窗,刚选文件未绑定到计划。 - 建议复现:浏览器网络限速,选择一个证书文件,在上传返回前点击保存,对比 PATCH 请求载荷与上传返回后的 URL。 - 修复:收集所有证书附件组件引用,提交前检查 `hasUploading()`;上传中提示“附件正在上传,请稍候再保存”且不提交、不关闭。保存请求期间禁用附件编辑,加载中及重复提交也被拦截。 - 验证:真实 Web 弹窗和附件组件的 Playwright 测试(API 边界替身)先复现旧代码上传中仍发送 1 次 PATCH,再确认修复后发送 0 次;上传完成后保存包含新 URL,关闭销毁后重开也能正常保存。未写入真实业务数据。 - 状态:已按追加授权修复。测试脚本:`web-admin/scripts/test-pl-plan-cert-upload-dialog.mjs`。 ## 2. H5 模块接入文档引用的运输计划菜单 SQL 不存在 - 位置:`docs/web-admin-mp-webview-modules.md` 的双权限说明引用 `docs/sql/migrations/2026-09-14-mini-pl-plan-webview-menus.sql`。 - 依据:当前工作区读取该路径返回不存在,`docs/sql/` 文件检索也未找到同名脚本。 - 影响:按旧文档发布运输计划时无法直接定位该菜单初始化脚本;不代表数据库现有菜单缺失。 - 状态:按用户要求忽略,本次未修改旧文档该引用。本模块已有独立菜单脚本,不代表旧运输计划文档问题已修复。 ## 3. 证书写接口未接入对应按钮权限校验(代码审查发现,未越权实测) - 位置:`backend/app/api/pl/plan.py` 的 `patch_plan_product_certs`、`patch_plan_hazard_cert_ready`;权限工具在 `backend/app/services/pl_plan_cert_perm.py`。 - 依据:两个接口检查登录、租户、计划数据范围后调用业务服务,路由聚合未配置相应菜单权限依赖;`user_can_upload_plan_cert`、`user_can_manage_plan_cert_ready` 在当前后端仅有定义、没有调用。Web 页显示按钮的检查不能代替服务端权限检查。 - 可能影响:有计划数据访问范围但没有对应按钮权限的登录用户,可能仍可直接调用证书写接口。 - 状态:按用户要求忽略,本次未修改权限校验;未使用真实账号实施越权请求。新移动页保留独立的按钮及提交前权限检查,但不能声称已修复服务端权限问题。 ## 4. 证书附件保存服务未拒绝已取消计划(已修复) - 位置:`backend/app/services/pl_plan_service.py` 的 `update_plan_product_certs`。 - 原因:原函数拒绝已归档计划,但没有与 `set_hazard_cert_ready` 一样检查 `follow_status == 'cancelled'`;前端 Web 的 `canUploadCert` 则禁止已取消计划操作。 - 可能影响:页面打开后计划被另一用户取消,仍可能保存证书附件,前后端状态限制不一致。 - 修复:读取计划后、查询及修改产品证书前,检查已作废状态并返回 HTTP 400:“已作废的计划不能修改危化品证书”。保留原租户、软删除和归档检查;不改变按钮权限。 - 验证:服务回归测试先确认旧代码对已作废计划不抛错,修复后确认拒绝且不修改 URL、修改人、齐备状态,不提交事务;另覆盖已归档、不存在及正常计划保存。测试使用数据库边界替身,不写入真实业务库;不声明已解决数据库事务之间的并发锁定问题。 - 状态:已按追加授权修复。测试文件:`backend/tests/test_pl_plan_product_certs.py`。 ## 5. CRM 六个移动菜单未回灌全量 SQL 基线(仅记录) - 位置:`docs/sql/shanxia2.0.sql` 与 `docs/sql/migrations/2026-10-15-mini-crm-*-webview-menus.sql`、`2026-10-17-mini-crm-customer-webview-menus.sql`。 - 依据:当前全量基线未包含 `MINI_CRM_*` 菜单;客户、产品、报价、报价审批、合同、合同审批只存在于增量迁移。 - 可能影响:仅使用全量基线初始化的新环境不会出现六个工作台入口,必须额外执行对应迁移。 - 状态:本轮先记录。用户当前授权是界面标准化,不据此写数据库;在 CRM 六页收尾时再评估是否同步基线 SQL。 ## 6. 旧 CRM 菜单迁移对软删除记录的幂等性不足(仅记录) - 位置:2026-10-15 的产品、报价和合同工作台菜单迁移。 - 依据:脚本的 `NOT EXISTS` 仅检查 `del_flag=0`,但插入使用固定主键;若同主键记录已软删除,重新执行会触发主键冲突。客户迁移已使用 `ON DUPLICATE KEY UPDATE del_flag=0`,行为更稳健。 - 可能影响:环境曾软删除菜单后重跑迁移可能失败,祖先角色绑定也可能无法恢复。 - 状态:本轮先记录,不修改数据库迁移或真实数据。 ## 7. 旧小程序 CRM 回归说明仍标记已启用入口为“未开放”(仅记录) - 位置:`bak/miniprogram-e2e/cases/01-crm.md`。 - 依据:文档仍把产品管理、合同审批描述为灰卡/未开放;当前 `workbench-menus.js` 中六个 CRM WebView 入口均已启用并受权限过滤。 - 可能影响:人工验收人员可能按过期说明跳过页面或误报入口状态。 - 状态:本轮只记录;CRM 六页交付时统一修订回归说明。 ## 8. Demo 原“证书上传时间”没有可对应的 Web/API 筛选字段(已校准文档) - 位置:`bak/mobile-ui/shanxia-mp-crm-pl-cert-style-align-demo.html` 的危化品证「更多」示意字段。 - 依据:Web 端 `columnFilterDefs.ts` 与计划列表 API 只有计划日期、送货时间、证书齐备状态等已生效条件,没有独立的证书上传时刻字段。 - 处理:按用户“功能完全参考 Web 端”的要求,删除 Demo 中无法生效的示意字段,并在 OpenSpec/UI 规范中明确单页不得为凑控件类型伪造查询条件;未改动后端或其他页面功能。 ## 本次验证 - 后端:`venv/bin/python -m pytest tests/test_pl_plan_product_certs.py tests/test_pl_plan_cert_list_filters.py tests/test_pl_menu_badge_plan_cert.py tests/test_pl_plan_product_upsert.py tests/test_pl_plan_draft_save.py -q`(在 `backend/`):17 项通过。 - Web:`node scripts/test-pl-plan-cert-upload-dialog.mjs`(在 `web-admin/`,本地 Vite 默认端口 3006):通过。 - 构建:`pnpm build` 通过;保留原有组件重名和包体积警告。`pnpm exec vue-tsc --noEmit` 仍未通过,其输出与修复前基线完全一致,无本次新增类型错误。 - 本次没有新增字段、数据库结构或菜单权限变更,无需执行 SQL。