# 104 Admin:PDD 商品支持批量导入 Excel 链接 - 类型:需求 - 父级大工单:#14 - 所属 MVP / 版本:#15 Admin 四模块可用闭环 - 状态:待验收 - 日期:2026-08-10 - Gitea 工单:http://ilaer.eicp.net:8418/chengma/cmautobuy/issues/104 ## 背景与目标 PDD 商品原来只能逐条粘贴链接创建。采购员需要把一列式 `.xlsx` 中的完整 PDD 商品链接批量导入商品档案,并在核对统计和失败明细后,显式为本次导入的 完整商品集合创建采集任务,不受当前列表分页限制。 ## 最终方案 - PDD 工具条增加“批量导入”,弹窗上传不超过 10MB 的 `.xlsx`。 - 读取第一个非空工作表,要求第一列标题为“拼多多链接”,忽略空工作表和空行, 最多处理 5000 条非空数据行。 - 每行复用现有完整链接解析和 `goods_id` 去重规则;无效行保留行号、原始内容和原因, 其他合法行继续导入。 - Repository 在不改变原 `EnsurePddProduct` 调用方式的前提下返回新建、复用、复活分类; 已存在商品保留采集结果,软删除商品沿用原有复活和清理规则。 - 合法行在同一事务中写入,任一数据库错误整批回滚。 - 结果区显示总行数、新建、已存在、恢复、文件内重复和失败数量;保存本次合法且去重后的 `goods_id` 隐藏集合,显式确认后复用现有可选客户端和批量采集规则。 - 上传不会自动建任务;提交按钮在上传或创建任务期间显示忙碌状态并防止重复提交。 - 上传文件使用服务端生成的临时文件名,解析完成即删除;不保存原始上传文件。 - 与原方案相比,发现 CSRF 中间件会先于 Handler 解析 multipart,因此把 PDD 和既有蝦皮 上传请求体上限前移到 CSRF 解析之前,确保大小限制真正生效;普通表单和 Client API 不变。 - 没有新增数据库结构、迁移或依赖,也没有改变 Client 四接口。 ## 改了哪些 - `admin/handler/web/csrf.go`:在 CSRF 解析 multipart 前应用上传请求体上限。 - `admin/handler/web/pdd.go`、`web.go`:增加导入路由、临时文件处理和统一列表结果渲染。 - `admin/service/pdd_import.go`:实现文件校验、流式逐行解析、去重、统计和事务编排。 - `admin/repository/pdd.go`:为既有建档逻辑增加新建/复用/复活结果分类。 - `admin/templates/pdd/list.html`:增加上传弹窗、结果区、失败明细和本批采集确认弹窗。 - `admin/static/js/app.js`、`admin/static/css/app.css`:增加上传反馈、支持两个采集确认入口及结果布局。 - `admin/service/pdd_import_test.go`、`admin/pdd_import_template_test.go`:覆盖格式、边界、事务、 重复导入、HTML 转义和跨分页集合渲染。 - `admin/testdata/pdd_links.xlsx`:可提交的脱敏一列式测试固件。 - `docs/admin/01-requirements.md`、`05-ui-specification.md`、`06-quality-security.md`:同步稳定需求、UI 和测试安全规则。 ## 验收结果 | 验收标准 | 结果 | |---|---| | PDD 页显示批量导入弹窗,写路由受登录和 CSRF 保护 | 通过 | | 真实 `raw_data/pdd链接.xlsx` 的 8 条链接及两个域名可识别,空 Sheet2/Sheet3 忽略 | 通过(Go 解析器人工核对) | | 扩展名、xlsx 文件头、空文件、10MB、表头和 5000 条上限校验 | 通过 | | 新建、复用、复活、文件内重复分别处理,重复导入不清空采集结果 | 通过 | | 无效行不阻塞合法行,完整显示行号、原文和原因 | 通过 | | 数据库中途失败时合法行整体回滚 | 通过(自动化事务故障测试) | | 结果统计完整且不只靠颜色表达 | 通过 | | 上传不自动建任务,显式确认后才复用现有批量任务规则 | 通过 | | 本次导入集合不依赖当前分页 | 通过(模板隐藏集合测试) | | 不新增数据库迁移,不改变 Client 四接口和采购/下单行为 | 通过 | | Go 1.23.0 build、test、vet 与脱敏固件测试 | 通过 | ## 测试 - 执行的命令: - `GOTOOLCHAIN=go1.23.0 go mod verify` - `GOTOOLCHAIN=go1.23.0 go build ./...` - `GOTOOLCHAIN=go1.23.0 go test ./... -count=1` - `GOTOOLCHAIN=go1.23.0 go vet ./...` - `node --check static/js/app.js` - `go test ./service -run '^TestManualPddRawSample$' -count=1 -v`(临时人工测试只读取 `raw_data`,测试文件未提交) - 结果:全部通过;真实样本得到 8 行、8 个合法且唯一的商品链接、0 个失败。 - **没验证到的部分**:未设置 `CMAUTOBUY_MYSQL_TEST=1` 和独立 `_test` 基础库, 因此没有执行真实 MySQL 8.4 的 HTTP 上传到落库集成测试;没有在浏览器中人工核对 1366×768 布局和管理员/采购员实际点击流程。未连接或修改生产数据库。 ## 相关提交 - `188725f` feat: 支持批量导入 PDD 商品链接 (#104)