feat(web): 采购管理与 SYB 商品按当前筛选导出全部页 Excel,采购管理新增下单日期筛选 #372

Open
opened 2026-10-09 10:07:31 +08:00 by ila · 11 comments
Owner

基本信息

  • 类型:新功能(Admin 列表导出:采购管理、SYB 商品)。
  • 状态:v1(72a15f8)、v2(4ad59bd)已于 2026-10-10 合并 main 并发布,待验收;v3 需求变更(见下)已确认,待实施。
  • 来源:2026-10-09 用户提问:「go-admin和go-admin-ui有导出页面上列表显示的数据呢,例如要导出syb商品也筛选出的已使用退货数据,和采购管理的筛选出来的成功采购数据」。
  • 用户确认的需求(2026-10-09):
    • 采购成功导出列:「syb订单号,虾皮商品id,颜色,尺码,数量,状态,pdd单号,下单时间,价格」。
    • 匹配退货导出列:「syb订单,虾皮商品id,syb颜色,syb尺码,syb数量,yeeke颜色,yeeke尺码,yeeke数量,匹配时间」。
    • 「会筛选出已用退货的数据,可以导出筛选的所有数据吗」:导出当前筛选条件下的全部页,不只当前页。
    • 价格:「从pdd待付款页面获取的价格」;颜色/尺码:「syb规格」;采购管理「加下单日期」筛选;权限:「采购员也可以」。
  • v2 需求变更(2026-10-10):用户:「syb商品页导出的数据增加个syb商品价格,放在"虾皮商品ID"右边新增列」。Claude Code 建议三点后,用户确认「按建议来」:
    1. 列名「SYB售价(TWD)」:该价格是 SYB 同步的虾皮订单成交单价,单位是元/TWD,不是人民币;
    2. 导出单价,不乘数量(与页面「售价」列同源);
    3. 写成数字单元格,不是文本;采购导出的「价格(元)」同步改为数字。
  • v3 需求变更(2026-10-10):用户:「#372的syb商品页导出的数据还需要在syb订单右键增加"店铺"列,"店铺"列显示这个虾皮商品对应的店铺」(「右键」按「右边」理解)。Claude Code 建议后,用户确认「按建议来」:
    1. 「店铺」列放在「SYB订单」右边;
    2. 取值为商品行 shopName,与页面「店铺」列一致,即 SYB 订单的店铺(虾皮商品档案的店铺也由此写入);不使用店铺筛选下拉里的显示名;
    3. 文本单元格,空值留空。

已核验事实(origin/main e450ac28989de6827328b411e4bdc050dded9ab3)

  • 现有导出:go-admin 自带的字典、参数、操作日志、岗位页面有「导出」,由前端 web/src/vendor/Export2Excel.js(xlsx + file-saver,已是依赖)把 this.list(当前页已加载的行)存成 Excel。服务端没有导出接口;web/src/api/admin/sys-user.js 的 /api/v1/sys-user/export 在服务端不存在。GoAuto 页面(采购管理、SYB 商品)没有导出。
  • 采购管理(web/src/views/goauto/purchase-tasks/index.vue,接口 GET /api/admin/v1/purchase-tasks):
    • AdminTaskItem 已有 shopeeOrderNoSnapshot、shopeeItemIdSnapshot、targetColorSnapshot、targetSizeSnapshot、quantity、status、pddOrderNo、orderSubmittedAt、pddOrderAmountCent。
    • pddOrderAmountCent 由 Agent 在结果页读取应付金额(PurchaseLiveAutomation.parsePayableAmount);旧版 Agent 或人工补录前可能为空。
    • 现有筛选:任务 ID、任务类型、虾皮订单号、状态、执行方式、SYB 商品 ID、PDD 单号;没有日期筛选。pageSize 服务端上限 100(admin_query.go)。
    • 访问权限:admin、purchaser、after_sales(handler_access_test.go)。
  • SYB 商品(web/src/views/goauto/syb-products/index.vue):
    • 筛选有店铺、订单号、解析状态、处理阶段(含 return_used「已用退货」、purchase_succeeded「采购成功」)、采购类型、创建时间;每页最多 500。
    • 匹配退货数据来自 GET /api/admin/v1/return-matches?sybProductId=…(returnmatch.Service.List),ListItem 含 matchedAt、status、orderSn、variationName,不含 yeeke 数量。
    • yeeke 规格只有一个 variation_name 字段,颜色和尺码写在一起(与 SYB 侧 颜色,尺码 对比,见 returnmatch/normalize.go)。
    • return-matches 列表对任何已登录 Admin 用户可读。

目标

  1. 采购管理和 SYB 商品页各加一个「导出」按钮,按当前筛选条件导出全部页,生成 Excel。
  2. 采购管理新增「下单日期」筛选。
  3. 能看到这两个列表的用户(包括采购员)都能导出。

非目标

  • 不做服务端生成文件的导出接口,不做后台异步导出任务。
  • 不导出收货人、地址、账号等个人信息,不导出页面上没有的字段。
  • 不改 go-admin 自带页面的导出。
  • 不改现有列表的分页、排序和其他筛选。

方案

共用

  • 新增一个前端导出工具:先按当前筛选条件查询第 1 页取得总数;总数超过 5000 条时提示「请缩小筛选范围」,不导出。否则用接口允许的最大页大小逐页读取,汇总后用现有 Export2Excel 生成 .xlsx。
  • 导出时,按钮显示进度(如「导出中 3/12」),禁用重复点击;任一页失败就停止并提示,不生成不完整的文件。
  • 读取时固定使用点击时刻的筛选条件,之后修改筛选不影响本次导出。
  • 时间格式 YYYY-MM-DD HH:mm:ss(本地时区);金额单位为元,保留两位小数;空值留空。
  • (v2)金额列写成 数字单元格(按分换算后保留两位小数精度,例如 1230 分 → 12.3 数值),Excel 可直接求和;空值仍留空,不写 0。能在不改变 go-admin 自带页面导出结果的前提下给这些列设置 0.00 显示格式时就设置;做不到就如实记录,不为此改动自带页面。
  • 文件名:采购导出_YYYYMMDD-HHmmss.xlsx、SYB商品导出_YYYYMMDD-HHmmss.xlsx。

采购管理

  • 导出列(按顺序):
列名 字段
SYB订单号 shopeeOrderNoSnapshot
虾皮商品ID shopeeItemIdSnapshot
颜色 targetColorSnapshot(SYB 规格)
尺码 targetSizeSnapshot(SYB 规格)
数量 quantity
状态 页面同款中文状态
PDD单号 pddOrderNo
下单时间 orderSubmittedAt
价格(元) pddOrderAmountCent / 100(PDD 待付款页读取的应付金额,没读到时留空);v2 起为数字单元格
  • 导出内容就是当前筛选结果。要导出成功采购,先把状态筛为「订单已创建」,并按需选择下单日期。
  • 下单日期筛选(服务端小改):AdminListRequest 新增 orderSubmittedFrom / orderSubmittedTo(日期,含首尾两天,按 order_submitted_at 过滤);前端在筛选栏加日期范围选择。时区处理与 SYB 商品页现有的创建时间筛选保持一致。没有下单时间的任务,在设置这个筛选时不会出现。

SYB 商品

  • 导出列(按顺序):
列名 来源
SYB订单 商品行的订单号
店铺 (v3 新增)商品行 shopName,与页面「店铺」列同值;空值留空
虾皮商品ID 商品行
SYB售价(TWD) (v2 新增)商品行 unitPriceCent / 100,即页面「售价」列的同一值(SYB detail/listByStock 的 productPrice,单件成交单价,元/TWD);数字单元格;为空时留空
SYB颜色 / SYB尺码 / SYB数量 商品行解析出的目标颜色、尺码、数量
yeeke颜色 / yeeke尺码 该商品的有效退货匹配(matched 或 confirmed)对应的 variationName,按第一个英文或中文逗号拆分;没有逗号时整段放在 yeeke 颜色
yeeke数量 有效匹配对应退货商品的数量
匹配时间 matchedAt
  • 先逐页读取商品,再按每批商品 ID 调用 return-matches 列表补齐匹配信息,不逐行请求。没有有效匹配的商品,yeeke 列和匹配时间留空。
  • 要导出已用退货,先把处理阶段筛为「已用退货」。
  • 服务端小改:returnmatch.ListItem 增加 yeeke 退货商品数量(只读字段,来自现有 join 查询),不改其他返回内容。

设计证据(低保真,待用户确认)

采购管理 筛选栏
[任务ID][类型][虾皮订单号][状态▼][执行方式][SYB商品ID][PDD单号][下单日期 起~止] [查询][重置] [导出]
                                                                 ^新增               ^新增
导出中:[导出中 3/12 …](禁用)   超限:提示「共 6200 条,超过 5000 条上限,请缩小筛选范围」
失败:提示「导出失败:第 4 页读取失败,未生成文件」   无数据:提示「当前筛选没有数据」,不生成文件

SYB 商品 工具栏
[…现有筛选…][查询][重置] [导出] [AI 匹配][图搜采集][创建采集]…
                         ^新增(状态同上)

状态:正常、空(无数据提示)、加载中(进度、禁用)、失败(提示,不生成文件)、超限(提示)。权限:能打开列表的用户都可以用,不新增按钮权限。

子项目影响、依赖与并行

  • Web:两个页面、一个导出工具,以及对应测试。
  • Server:purchase 列表新增下单日期筛选;returnmatch.ListItem 新增 yeeke 数量。无数据库迁移、无新接口。
  • Android:无。
  • 无前置依赖,可并行。

验收标准

  • 服务端测试:下单日期筛选含首尾两天、与其他筛选组合正确、日期格式错误时返回 INVALID_REQUEST;return-matches 列表返回 yeeke 数量。
  • 前端测试(按项目现有测试方式):行到列的映射、金额换算、空值、yeeke 规格拆分(英文逗号、中文逗号、无逗号)、超过 5000 条不导出、中途失败不生成文件。
  • 浏览器验证:
    • 采购管理按「订单已创建 + 下单日期」筛选,结果超过一页时导出,行数等于总数、列与顺序正确;
    • SYB 商品按「已用退货」筛选,结果多页时导出,行数等于总数、yeeke 列有值;
    • 采购员账号可以导出。
      如实记录。
  • Web 构建、服务端相关回归测试通过。
  • (v2)前端测试:SYB 导出表头为 SYB订单、虾皮商品ID、SYB售价(TWD)、SYB颜色、SYB尺码、SYB数量、yeeke颜色、yeeke尺码、yeeke数量、匹配时间;售价 unitPriceCent 1230 → 数值 12.3、0 → 0、空 → 留空;采购导出价格列同样为数值,空值留空;生成的工作表中这两列单元格类型为数字。
  • (v2)浏览器验证:SYB 商品导出的「SYB售价(TWD)」与页面「售价」列一致,Excel 中可直接求和。
  • (v3)前端测试:SYB 导出表头为 SYB订单、店铺、虾皮商品ID、SYB售价(TWD)、SYB颜色、SYB尺码、SYB数量、yeeke颜色、yeeke尺码、yeeke数量、匹配时间;shopName 有值时原样输出,null/undefined 留空;售价列仍为数字单元格且 0.00 格式落在新的列号上。
  • (v3)浏览器验证:SYB 商品导出的「店铺」与页面「店铺」列一致。
  • 发布需用户另行授权。

风险与回退

  • 一次最多读取 50 页(采购每页 100 条)或 10 页(SYB 每页 500 条),对服务端压力有限;上限 5000 条可调整。
  • 导出期间数据变化,可能出现重复或遗漏的行(按页读取的固有限制);以导出时刻的近似结果为准,在提示中说明。
  • 导出文件保存在用户电脑上,含订单号等业务数据,不含个人信息。
  • 回退:移除按钮和筛选;服务端改动只增加可选参数和字段,向后兼容。

文档影响

  • 更新 Wiki Business-Rules-and-Glossary:导出范围(当前筛选的全部页)、上限、列定义、价格来源。
  • (v3)更新同页 #372 段落:SYB 导出新增「店铺」列(SYB 订单店铺,与页面一致)。v3 只改 Web。
  • (v2)更新同页 #372 段落:SYB 导出新增「SYB售价(TWD)」列及其来源和币种;两处金额列为数字单元格。v2 只改 Web,不改服务端、接口和数据库,Architecture-and-Code-Map 只在入口或调用路径变化时更新。
  • 更新 Architecture-and-Code-Map:采购管理列表新增下单日期参数、return-matches 列表新增数量字段。
  • 先改线上 Wiki 并回读 revision,再执行一次 sync 与 sync --check。

备注

本单由 Claude Code 依据代码阅读和用户确认的需求起草。

## 基本信息 - 类型:新功能(Admin 列表导出:采购管理、SYB 商品)。 - 状态:v1(`72a15f8`)、v2(`4ad59bd`)已于 2026-10-10 合并 main 并发布,待验收;**v3 需求变更(见下)已确认,待实施**。 - 来源:2026-10-09 用户提问:「go-admin和go-admin-ui有导出页面上列表显示的数据呢,例如要导出syb商品也筛选出的已使用退货数据,和采购管理的筛选出来的成功采购数据」。 - 用户确认的需求(2026-10-09): - 采购成功导出列:「syb订单号,虾皮商品id,颜色,尺码,数量,状态,pdd单号,下单时间,价格」。 - 匹配退货导出列:「syb订单,虾皮商品id,syb颜色,syb尺码,syb数量,yeeke颜色,yeeke尺码,yeeke数量,匹配时间」。 - 「会筛选出已用退货的数据,可以导出筛选的所有数据吗」:导出当前筛选条件下的**全部页**,不只当前页。 - 价格:「从pdd待付款页面获取的价格」;颜色/尺码:「syb规格」;采购管理「加下单日期」筛选;权限:「采购员也可以」。 - **v2 需求变更(2026-10-10)**:用户:「syb商品页导出的数据增加个syb商品价格,放在"虾皮商品ID"右边新增列」。Claude Code 建议三点后,用户确认「按建议来」: 1. 列名「SYB售价(TWD)」:该价格是 SYB 同步的虾皮订单成交单价,单位是元/TWD,不是人民币; 2. 导出单价,不乘数量(与页面「售价」列同源); 3. 写成数字单元格,不是文本;采购导出的「价格(元)」同步改为数字。 - **v3 需求变更(2026-10-10)**:用户:「#372的syb商品页导出的数据还需要在syb订单右键增加"店铺"列,"店铺"列显示这个虾皮商品对应的店铺」(「右键」按「右边」理解)。Claude Code 建议后,用户确认「按建议来」: 1. 「店铺」列放在「SYB订单」右边; 2. 取值为商品行 `shopName`,与页面「店铺」列一致,即 SYB 订单的店铺(虾皮商品档案的店铺也由此写入);不使用店铺筛选下拉里的显示名; 3. 文本单元格,空值留空。 ## 已核验事实(`origin/main` `e450ac28989de6827328b411e4bdc050dded9ab3`) - 现有导出:go-admin 自带的字典、参数、操作日志、岗位页面有「导出」,由前端 `web/src/vendor/Export2Excel.js`(`xlsx` + `file-saver`,已是依赖)把 `this.list`(**当前页已加载的行**)存成 Excel。服务端没有导出接口;`web/src/api/admin/sys-user.js` 的 `/api/v1/sys-user/export` 在服务端不存在。GoAuto 页面(采购管理、SYB 商品)没有导出。 - 采购管理(`web/src/views/goauto/purchase-tasks/index.vue`,接口 `GET /api/admin/v1/purchase-tasks`): - `AdminTaskItem` 已有 `shopeeOrderNoSnapshot`、`shopeeItemIdSnapshot`、`targetColorSnapshot`、`targetSizeSnapshot`、`quantity`、`status`、`pddOrderNo`、`orderSubmittedAt`、`pddOrderAmountCent`。 - `pddOrderAmountCent` 由 Agent 在结果页读取应付金额(`PurchaseLiveAutomation.parsePayableAmount`);旧版 Agent 或人工补录前可能为空。 - 现有筛选:任务 ID、任务类型、虾皮订单号、状态、执行方式、SYB 商品 ID、PDD 单号;**没有日期筛选**。`pageSize` 服务端上限 100(`admin_query.go`)。 - 访问权限:admin、purchaser、after_sales(`handler_access_test.go`)。 - SYB 商品(`web/src/views/goauto/syb-products/index.vue`): - 筛选有店铺、订单号、解析状态、处理阶段(含 `return_used`「已用退货」、`purchase_succeeded`「采购成功」)、采购类型、创建时间;每页最多 500。 - 匹配退货数据来自 `GET /api/admin/v1/return-matches?sybProductId=…`(`returnmatch.Service.List`),`ListItem` 含 `matchedAt`、`status`、`orderSn`、`variationName`,**不含 yeeke 数量**。 - yeeke 规格只有一个 `variation_name` 字段,颜色和尺码写在一起(与 SYB 侧 `颜色,尺码` 对比,见 `returnmatch/normalize.go`)。 - `return-matches` 列表对任何已登录 Admin 用户可读。 ## 目标 1. 采购管理和 SYB 商品页各加一个「导出」按钮,按**当前筛选条件导出全部页**,生成 Excel。 2. 采购管理新增「下单日期」筛选。 3. 能看到这两个列表的用户(包括采购员)都能导出。 ## 非目标 - 不做服务端生成文件的导出接口,不做后台异步导出任务。 - 不导出收货人、地址、账号等个人信息,不导出页面上没有的字段。 - 不改 go-admin 自带页面的导出。 - 不改现有列表的分页、排序和其他筛选。 ## 方案 ### 共用 - 新增一个前端导出工具:先按当前筛选条件查询第 1 页取得总数;总数超过 **5000** 条时提示「请缩小筛选范围」,不导出。否则用接口允许的最大页大小逐页读取,汇总后用现有 `Export2Excel` 生成 `.xlsx`。 - 导出时,按钮显示进度(如「导出中 3/12」),禁用重复点击;任一页失败就停止并提示,不生成不完整的文件。 - 读取时固定使用点击时刻的筛选条件,之后修改筛选不影响本次导出。 - 时间格式 `YYYY-MM-DD HH:mm:ss`(本地时区);金额单位为元,保留两位小数;空值留空。 - (v2)金额列写成 **数字单元格**(按分换算后保留两位小数精度,例如 1230 分 → 12.3 数值),Excel 可直接求和;空值仍留空,不写 0。能在不改变 go-admin 自带页面导出结果的前提下给这些列设置 `0.00` 显示格式时就设置;做不到就如实记录,不为此改动自带页面。 - 文件名:`采购导出_YYYYMMDD-HHmmss.xlsx`、`SYB商品导出_YYYYMMDD-HHmmss.xlsx`。 ### 采购管理 - 导出列(按顺序): | 列名 | 字段 | |---|---| | SYB订单号 | `shopeeOrderNoSnapshot` | | 虾皮商品ID | `shopeeItemIdSnapshot` | | 颜色 | `targetColorSnapshot`(SYB 规格) | | 尺码 | `targetSizeSnapshot`(SYB 规格) | | 数量 | `quantity` | | 状态 | 页面同款中文状态 | | PDD单号 | `pddOrderNo` | | 下单时间 | `orderSubmittedAt` | | 价格(元) | `pddOrderAmountCent / 100`(PDD 待付款页读取的应付金额,没读到时留空);v2 起为数字单元格 | - 导出内容就是当前筛选结果。要导出成功采购,先把状态筛为「订单已创建」,并按需选择下单日期。 - **下单日期筛选(服务端小改)**:`AdminListRequest` 新增 `orderSubmittedFrom` / `orderSubmittedTo`(日期,含首尾两天,按 `order_submitted_at` 过滤);前端在筛选栏加日期范围选择。时区处理与 SYB 商品页现有的创建时间筛选保持一致。没有下单时间的任务,在设置这个筛选时不会出现。 ### SYB 商品 - 导出列(按顺序): | 列名 | 来源 | |---|---| | SYB订单 | 商品行的订单号 | | 店铺 | (v3 新增)商品行 `shopName`,与页面「店铺」列同值;空值留空 | | 虾皮商品ID | 商品行 | | SYB售价(TWD) | (v2 新增)商品行 `unitPriceCent / 100`,即页面「售价」列的同一值(SYB `detail/listByStock` 的 `productPrice`,单件成交单价,元/TWD);数字单元格;为空时留空 | | SYB颜色 / SYB尺码 / SYB数量 | 商品行解析出的目标颜色、尺码、数量 | | yeeke颜色 / yeeke尺码 | 该商品的有效退货匹配(`matched` 或 `confirmed`)对应的 `variationName`,按第一个英文或中文逗号拆分;没有逗号时整段放在 yeeke 颜色 | | yeeke数量 | 有效匹配对应退货商品的数量 | | 匹配时间 | `matchedAt` | - 先逐页读取商品,再按每批商品 ID 调用 `return-matches` 列表补齐匹配信息,不逐行请求。没有有效匹配的商品,yeeke 列和匹配时间留空。 - 要导出已用退货,先把处理阶段筛为「已用退货」。 - **服务端小改**:`returnmatch.ListItem` 增加 yeeke 退货商品数量(只读字段,来自现有 join 查询),不改其他返回内容。 ## 设计证据(低保真,待用户确认) ``` 采购管理 筛选栏 [任务ID][类型][虾皮订单号][状态▼][执行方式][SYB商品ID][PDD单号][下单日期 起~止] [查询][重置] [导出] ^新增 ^新增 导出中:[导出中 3/12 …](禁用) 超限:提示「共 6200 条,超过 5000 条上限,请缩小筛选范围」 失败:提示「导出失败:第 4 页读取失败,未生成文件」 无数据:提示「当前筛选没有数据」,不生成文件 SYB 商品 工具栏 […现有筛选…][查询][重置] [导出] [AI 匹配][图搜采集][创建采集]… ^新增(状态同上) ``` 状态:正常、空(无数据提示)、加载中(进度、禁用)、失败(提示,不生成文件)、超限(提示)。权限:能打开列表的用户都可以用,不新增按钮权限。 ## 子项目影响、依赖与并行 - Web:两个页面、一个导出工具,以及对应测试。 - Server:`purchase` 列表新增下单日期筛选;`returnmatch.ListItem` 新增 yeeke 数量。无数据库迁移、无新接口。 - Android:无。 - 无前置依赖,可并行。 ## 验收标准 - [ ] 服务端测试:下单日期筛选含首尾两天、与其他筛选组合正确、日期格式错误时返回 `INVALID_REQUEST`;`return-matches` 列表返回 yeeke 数量。 - [ ] 前端测试(按项目现有测试方式):行到列的映射、金额换算、空值、yeeke 规格拆分(英文逗号、中文逗号、无逗号)、超过 5000 条不导出、中途失败不生成文件。 - [ ] 浏览器验证: - 采购管理按「订单已创建 + 下单日期」筛选,结果超过一页时导出,行数等于总数、列与顺序正确; - SYB 商品按「已用退货」筛选,结果多页时导出,行数等于总数、yeeke 列有值; - 采购员账号可以导出。 如实记录。 - [ ] Web 构建、服务端相关回归测试通过。 - [ ] (v2)前端测试:SYB 导出表头为 `SYB订单、虾皮商品ID、SYB售价(TWD)、SYB颜色、SYB尺码、SYB数量、yeeke颜色、yeeke尺码、yeeke数量、匹配时间`;售价 `unitPriceCent` 1230 → 数值 12.3、0 → 0、空 → 留空;采购导出价格列同样为数值,空值留空;生成的工作表中这两列单元格类型为数字。 - [ ] (v2)浏览器验证:SYB 商品导出的「SYB售价(TWD)」与页面「售价」列一致,Excel 中可直接求和。 - [ ] (v3)前端测试:SYB 导出表头为 `SYB订单、店铺、虾皮商品ID、SYB售价(TWD)、SYB颜色、SYB尺码、SYB数量、yeeke颜色、yeeke尺码、yeeke数量、匹配时间`;`shopName` 有值时原样输出,null/undefined 留空;售价列仍为数字单元格且 `0.00` 格式落在新的列号上。 - [ ] (v3)浏览器验证:SYB 商品导出的「店铺」与页面「店铺」列一致。 - [ ] 发布需用户另行授权。 ## 风险与回退 - 一次最多读取 50 页(采购每页 100 条)或 10 页(SYB 每页 500 条),对服务端压力有限;上限 5000 条可调整。 - 导出期间数据变化,可能出现重复或遗漏的行(按页读取的固有限制);以导出时刻的近似结果为准,在提示中说明。 - 导出文件保存在用户电脑上,含订单号等业务数据,不含个人信息。 - 回退:移除按钮和筛选;服务端改动只增加可选参数和字段,向后兼容。 ## 文档影响 - 更新 Wiki Business-Rules-and-Glossary:导出范围(当前筛选的全部页)、上限、列定义、价格来源。 - (v3)更新同页 #372 段落:SYB 导出新增「店铺」列(SYB 订单店铺,与页面一致)。v3 只改 Web。 - (v2)更新同页 #372 段落:SYB 导出新增「SYB售价(TWD)」列及其来源和币种;两处金额列为数字单元格。v2 只改 Web,不改服务端、接口和数据库,Architecture-and-Code-Map 只在入口或调用路径变化时更新。 - 更新 Architecture-and-Code-Map:采购管理列表新增下单日期参数、`return-matches` 列表新增数量字段。 - 先改线上 Wiki 并回读 revision,再执行一次 sync 与 sync --check。 ## 备注 本单由 Claude Code 依据代码阅读和用户确认的需求起草。
Author
Owner

开始实施

  • 日期:2026-10-10
  • 实施者:Claude Code(Sonnet subagent)
  • 授权:2026-10-10 用户在对话中说:「现在codex做着#378,你可以安排subagent用sonnet做#372吗」。主 Agent 理解为用户确认 #372 当前正文(含低保真设计和 5000 条上限)并授权按正文实施;授权不包括合并到 main、发布、部署、装机、改生产数据。
  • 基线提交:3ee8dfc(origin/main;正文核验基线为 e450ac2,动手前会重新核对)
  • 分支:feat/372-list-export
  • worktree:D:/OPC/goauto-worktrees/issue-372
## 开始实施 - 日期:2026-10-10 - 实施者:Claude Code(Sonnet subagent) - 授权:2026-10-10 用户在对话中说:「现在codex做着#378,你可以安排subagent用sonnet做#372吗」。主 Agent 理解为用户确认 #372 当前正文(含低保真设计和 5000 条上限)并授权按正文实施;授权不包括合并到 main、发布、部署、装机、改生产数据。 - 基线提交:`3ee8dfc`(`origin/main`;正文核验基线为 `e450ac2`,动手前会重新核对) - 分支:`feat/372-list-export` - worktree:`D:/OPC/goauto-worktrees/issue-372`
Author
Owner

待验收回写(Claude Code,Sonnet subagent,2026-10-10)

分支 feat/372-list-export,已推送,未合并、未发布、未删除 worktree(D:/OPC/goauto-worktrees/issue-372)。基线 origin/main 3ee8dfc。

提交

  • a4a793f feat(web): export all filtered pages to Excel for purchase tasks and SYB products (#372)
  • b311885 docs: sync Wiki mirror for list export (#372)

动手前核对

  • 正文代码事实在 3ee8dfc 上仍成立:AdminListRequest 无日期筛选、pageSize 上限 100;returnmatch.ListItem 无 yeeke 数量;return-matches 列表本来就支持一次传多个 sybProductId(c.QueryArray),不需要扩展接口。
  • 无数据库迁移、无新接口、无新权限,范围没有扩大。

实现摘要

  • Server:purchase.AdminListRequest 新增 OrderSubmittedFrom/To,handler 读取 orderSubmittedFrom/orderSubmittedTo;含首尾两天,按 order_submitted_at,日期边界 UTC+8(与 SYB 创建时间筛选一致);格式错误或起止倒置返回 INVALID_REQUEST。returnmatch.ListItem 新增只读 yeekeQuantity,来自既有 yeeke_return_item join。
  • Web:新增 web/src/utils/list-export.js(总数超 5000 不导出、逐页读取、进度、任一页/批次失败不生成文件、无数据提示、时间/金额/文件名格式、yeeke 规格拆分、行映射)和 web/src/utils/save-excel.js(按需加载 Export2Excel)。采购管理页新增「下单日期」范围筛选和「导出」按钮;SYB 商品页新增「导出」按钮,逐页读商品后每 200 个商品 ID 调一次 return-matches,只用 matched/confirmed,variationName 按第一个英文或中文逗号拆分。导出期间按钮显示「导出中 n/m」并禁用,筛选条件在点击时复制固定。不新增按钮权限,不导出收货人、地址、账号。
  • 价格列输出文本 12.30(保证两位小数);若用户希望 Excel 里可求和的数值列,需另行确认。

改动文件

  • server/app/goauto/purchase/admin_query.go、handler.go、admin_submitted_range_test.go(新增)
  • server/app/goauto/returnmatch/service.go、service_test.go
  • web/src/utils/list-export.js、web/src/utils/save-excel.js、web/tests/unit/list-export.test.cjs(均新增)
  • web/src/views/goauto/purchase-tasks/index.vue、web/src/views/goauto/syb-products/index.vue
  • docs/02-architecture-and-code-map.md、docs/03-business-rules-and-glossary.md(Wiki 镜像)

测试(真实结果)

本机默认 go 1.24 不满足 go.mod 要求,用已缓存的 go1.26.5 工具链、CGO_ENABLED=1、GOTOOLCHAIN=local 运行。

  • go test -count=1 ./app/goauto/purchase/ ./app/goauto/returnmatch/:通过。新增覆盖:下单日期首尾两天含边界、仅起/仅止/单日、与 status 组合、无下单时间行、日期格式错误与起止倒置(service 和 handler 均 INVALID_REQUEST、purchaser 角色可访问);return-matches 列表返回 yeekeQuantity(含 JSON 字段)。
  • go test -count=1 ./app/goauto/...:除 sybimport 外全部 ok;go build ./... 通过。
  • sybimport 有 12 个失败(解析/AI 解析相关)。我在干净的 origin/main 临时 worktree 上单独跑 go test ./app/goauto/sybimport 同样 FAIL,所以是既有失败,与本单无关,未处理(临时 worktree 已删除)。
  • node --test web/tests/unit/*.cjs:90 个全部通过,其中新增 10 个(行到列映射、金额换算、空值、yeeke 英文逗号/中文逗号/无逗号拆分、取消的匹配被忽略、5000 条允许与 5001 条只读第 1 页后拒绝、无数据不保存、中途失败不保存、批量补匹配按批而非逐行并在失败时不保存)。
  • pnpm install --frozen-lockfile:通过。pnpm run build:prod:通过。
  • pnpm run lint:失败,但失败是既有的(collection-tasks、devices.js、syb-product-filters.js、yeeke-returns、purchase-tasks 里已有的混用 tab/缩进错误等)。本单新增代码已单独检查,没有新增 lint 错误;purchase-tasks/index.vue 里剩余的 brace-style 等错误在原有代码行上。
  • 没有使用 scripts/verify.ps1,因为 go test ./... 会撞上上面的既有 sybimport 失败,改为按包分别执行。

未验证项

  • 未执行浏览器验证:本机没有已知的本地开发环境和 seed/fixture 测试账号,按要求不登录生产或远程 Admin。因此验收项中「采购管理按订单已创建+下单日期筛选多页导出」「SYB 已用退货多页导出」「采购员账号导出」都未实机验证,也没有实际打开生成的 xlsx。Export2Excel 的 xlsx 生成路径只靠既有 vendor 代码,未跑过真实下载。
  • 导出期间数据变化可能有少量重复/遗漏(按页读取的固有限制),已写入成功提示和 Wiki。
  • 未发布、未部署。

Wiki

有长期文档影响,已处理:先读取线上最新内容和 revision(写前未发现他人并发修改),只追加 #372 段落,写后回读核对一致。

  • Architecture-and-Code-Map:76854d9 → 08da88a4f106004cb5f02448260d2fc22a83e9cc
  • Business-Rules-and-Glossary:7cdfe55 → 1c57a8670034fe08420bcac48b58a9c4b2755f23
  • 已在 worktree 运行一次 harness.py sync 和一次 sync --check(通过)。镜像同步还带入了线上他人已更新的部分内容(与 #372 无关的旧差异)。docs/06-troubleshooting.md 因线上已更新也被同步改动,但不属于本单,已还原未提交;该镜像在 main 上本来就滞后,需要时另行同步。

其它

  • worktree 保留,因为分支尚未合并。
## 待验收回写(Claude Code,Sonnet subagent,2026-10-10) 分支 `feat/372-list-export`,已推送,**未合并、未发布、未删除 worktree**(`D:/OPC/goauto-worktrees/issue-372`)。基线 `origin/main` `3ee8dfc`。 ### 提交 - `a4a793f` feat(web): export all filtered pages to Excel for purchase tasks and SYB products (#372) - `b311885` docs: sync Wiki mirror for list export (#372) ### 动手前核对 - 正文代码事实在 `3ee8dfc` 上仍成立:`AdminListRequest` 无日期筛选、`pageSize` 上限 100;`returnmatch.ListItem` 无 yeeke 数量;`return-matches` 列表本来就支持一次传多个 `sybProductId`(`c.QueryArray`),**不需要扩展接口**。 - 无数据库迁移、无新接口、无新权限,范围没有扩大。 ### 实现摘要 - Server:`purchase.AdminListRequest` 新增 `OrderSubmittedFrom/To`,handler 读取 `orderSubmittedFrom/orderSubmittedTo`;含首尾两天,按 `order_submitted_at`,日期边界 UTC+8(与 SYB 创建时间筛选一致);格式错误或起止倒置返回 `INVALID_REQUEST`。`returnmatch.ListItem` 新增只读 `yeekeQuantity`,来自既有 `yeeke_return_item` join。 - Web:新增 `web/src/utils/list-export.js`(总数超 5000 不导出、逐页读取、进度、任一页/批次失败不生成文件、无数据提示、时间/金额/文件名格式、yeeke 规格拆分、行映射)和 `web/src/utils/save-excel.js`(按需加载 `Export2Excel`)。采购管理页新增「下单日期」范围筛选和「导出」按钮;SYB 商品页新增「导出」按钮,逐页读商品后每 200 个商品 ID 调一次 `return-matches`,只用 `matched`/`confirmed`,`variationName` 按第一个英文或中文逗号拆分。导出期间按钮显示「导出中 n/m」并禁用,筛选条件在点击时复制固定。不新增按钮权限,不导出收货人、地址、账号。 - 价格列输出文本 `12.30`(保证两位小数);若用户希望 Excel 里可求和的数值列,需另行确认。 ### 改动文件 - `server/app/goauto/purchase/admin_query.go`、`handler.go`、`admin_submitted_range_test.go`(新增) - `server/app/goauto/returnmatch/service.go`、`service_test.go` - `web/src/utils/list-export.js`、`web/src/utils/save-excel.js`、`web/tests/unit/list-export.test.cjs`(均新增) - `web/src/views/goauto/purchase-tasks/index.vue`、`web/src/views/goauto/syb-products/index.vue` - `docs/02-architecture-and-code-map.md`、`docs/03-business-rules-and-glossary.md`(Wiki 镜像) ### 测试(真实结果) 本机默认 go 1.24 不满足 `go.mod` 要求,用已缓存的 go1.26.5 工具链、`CGO_ENABLED=1`、`GOTOOLCHAIN=local` 运行。 - `go test -count=1 ./app/goauto/purchase/ ./app/goauto/returnmatch/`:通过。新增覆盖:下单日期首尾两天含边界、仅起/仅止/单日、与 status 组合、无下单时间行、日期格式错误与起止倒置(service 和 handler 均 `INVALID_REQUEST`、purchaser 角色可访问);`return-matches` 列表返回 `yeekeQuantity`(含 JSON 字段)。 - `go test -count=1 ./app/goauto/...`:除 `sybimport` 外全部 ok;`go build ./...` 通过。 - `sybimport` 有 12 个失败(解析/AI 解析相关)。我在干净的 `origin/main` 临时 worktree 上单独跑 `go test ./app/goauto/sybimport` 同样 FAIL,所以是既有失败,与本单无关,未处理(临时 worktree 已删除)。 - `node --test web/tests/unit/*.cjs`:90 个全部通过,其中新增 10 个(行到列映射、金额换算、空值、yeeke 英文逗号/中文逗号/无逗号拆分、取消的匹配被忽略、5000 条允许与 5001 条只读第 1 页后拒绝、无数据不保存、中途失败不保存、批量补匹配按批而非逐行并在失败时不保存)。 - `pnpm install --frozen-lockfile`:通过。`pnpm run build:prod`:通过。 - `pnpm run lint`:**失败,但失败是既有的**(`collection-tasks`、`devices.js`、`syb-product-filters.js`、`yeeke-returns`、`purchase-tasks` 里已有的混用 tab/缩进错误等)。本单新增代码已单独检查,没有新增 lint 错误;`purchase-tasks/index.vue` 里剩余的 `brace-style` 等错误在原有代码行上。 - 没有使用 `scripts/verify.ps1`,因为 `go test ./...` 会撞上上面的既有 `sybimport` 失败,改为按包分别执行。 ### 未验证项 - **未执行浏览器验证**:本机没有已知的本地开发环境和 seed/fixture 测试账号,按要求不登录生产或远程 Admin。因此验收项中「采购管理按订单已创建+下单日期筛选多页导出」「SYB 已用退货多页导出」「采购员账号导出」都未实机验证,也没有实际打开生成的 xlsx。`Export2Excel` 的 xlsx 生成路径只靠既有 vendor 代码,未跑过真实下载。 - 导出期间数据变化可能有少量重复/遗漏(按页读取的固有限制),已写入成功提示和 Wiki。 - 未发布、未部署。 ### Wiki 有长期文档影响,已处理:先读取线上最新内容和 revision(写前未发现他人并发修改),只追加 #372 段落,写后回读核对一致。 - `Architecture-and-Code-Map`:`76854d9` → `08da88a4f106004cb5f02448260d2fc22a83e9cc` - `Business-Rules-and-Glossary`:`7cdfe55` → `1c57a8670034fe08420bcac48b58a9c4b2755f23` - 已在 worktree 运行一次 `harness.py sync` 和一次 `sync --check`(通过)。镜像同步还带入了线上他人已更新的部分内容(与 #372 无关的旧差异)。`docs/06-troubleshooting.md` 因线上已更新也被同步改动,但不属于本单,已还原未提交;该镜像在 `main` 上本来就滞后,需要时另行同步。 ### 其它 - worktree 保留,因为分支尚未合并。
Author
Owner

2026-10-10 合并 main 与线上发布(Claude Code)

用户授权:「合并到main,并发布」。

合并

  • feat/372-list-export 以 --no-ff 合并为 main 72a15f8。合并前 main 已含 #377 的 Android 提交(8b75a95、309dce3、4a669bc)。
  • docs/03-business-rules-and-glossary.md 镜像冲突:选用同时包含 #377 和 #372 段落的较新导出版本(Business-Rules-and-Glossary@1c57a86),sync --check 通过。
  • 合并后复验:go test ./app/goauto/purchase/ ./app/goauto/returnmatch/ 通过;node --test web/tests/unit/*.cjs 90/90 通过;pnpm run build:prod 通过。

发布(122.228.200.167)

  • 发布目录 /home/goauto/releases/20261010-72a15f8-372;回滚目录 /home/goauto/releases/20261009-e26743c-integrated 保留。
  • 自上次发布 e26743c 以来,Server/Web 源码只有 #372 的变化;无数据库迁移、无权限变更,未执行 migrate。
  • 切换前复查:没有执行中的采集、采购或 attempt;1 个 pending 采购任务保持原状。config 与上一发布一致,static/temp/var 沿用原目录,旧 js/css 哈希资源保留。
  • Server SHA256 ab3943a1261f438eaad4d4acf006910e8a996cf97afc18a399ad5bee6c8f3a1f(运行进程一致);index.html SHA256 c3465960bd6f450d7b0d51994475bfdc126c7b6a47068d92bad9b4ac751d0529。
  • current 原子切换,goauto.service 重启后 active;Nginx 未改、未 reload。
  • 按内容验收:/、/login 返回同一 index(含 id="app",无欢迎页);10 项 JS/CSS 200;health 200;验证码 code=200;未登录访问采购列表(带下单日期参数)和 return-matches 业务码 401;日志无 panic/fatal/1146/1054。

Wiki

  • Deployment-and-Operations:3f69f2e → ad212f537b7d153e6337b3f2851e661680bfba20,回读一致。
  • 镜像提交 main 919744e,sync --check 通过。

未验证(待业务验收)

  • 登录后采购管理按「订单已创建 + 下单日期」多页导出。
  • SYB 商品按「已用退货」多页导出。
  • 采购员账号导出。

价格列目前导出为文本(如 12.30),是否改为数值待用户决定。

### 2026-10-10 合并 main 与线上发布(Claude Code) 用户授权:「合并到main,并发布」。 **合并** - `feat/372-list-export` 以 `--no-ff` 合并为 main `72a15f8`。合并前 main 已含 #377 的 Android 提交(`8b75a95`、`309dce3`、`4a669bc`)。 - `docs/03-business-rules-and-glossary.md` 镜像冲突:选用同时包含 #377 和 #372 段落的较新导出版本(Business-Rules-and-Glossary@`1c57a86`),`sync --check` 通过。 - 合并后复验:`go test ./app/goauto/purchase/ ./app/goauto/returnmatch/` 通过;`node --test web/tests/unit/*.cjs` 90/90 通过;`pnpm run build:prod` 通过。 **发布**(122.228.200.167) - 发布目录 `/home/goauto/releases/20261010-72a15f8-372`;回滚目录 `/home/goauto/releases/20261009-e26743c-integrated` 保留。 - 自上次发布 `e26743c` 以来,Server/Web 源码只有 #372 的变化;无数据库迁移、无权限变更,未执行 migrate。 - 切换前复查:没有执行中的采集、采购或 attempt;1 个 pending 采购任务保持原状。config 与上一发布一致,static/temp/var 沿用原目录,旧 js/css 哈希资源保留。 - Server SHA256 `ab3943a1261f438eaad4d4acf006910e8a996cf97afc18a399ad5bee6c8f3a1f`(运行进程一致);index.html SHA256 `c3465960bd6f450d7b0d51994475bfdc126c7b6a47068d92bad9b4ac751d0529`。 - current 原子切换,goauto.service 重启后 active;Nginx 未改、未 reload。 - 按内容验收:`/`、`/login` 返回同一 index(含 `id="app"`,无欢迎页);10 项 JS/CSS 200;health 200;验证码 code=200;未登录访问采购列表(带下单日期参数)和 return-matches 业务码 401;日志无 panic/fatal/1146/1054。 **Wiki** - Deployment-and-Operations:`3f69f2e` → `ad212f537b7d153e6337b3f2851e661680bfba20`,回读一致。 - 镜像提交 main `919744e`,`sync --check` 通过。 **未验证(待业务验收)** - 登录后采购管理按「订单已创建 + 下单日期」多页导出。 - SYB 商品按「已用退货」多页导出。 - 采购员账号导出。 价格列目前导出为文本(如 `12.30`),是否改为数值待用户决定。
Author
Owner

2026-10-10 worktree 清理(Claude Code)

  • D:/OPC/goauto-worktrees/issue-372、D:/OPC/goauto-worktrees/release-372:删除前确认 HEAD 是 origin/main 的祖先、git status --porcelain 为空、没有进程或 supervisor 配置引用、没有指向外部的链接。
  • 已执行 git worktree remove(未加 --force)和 git worktree prune。两个 worktree 都已取消登记,分支 feat/372-list-export 和提交历史保留。
  • 残留:两个目录下的 web/node_modules 是 pnpm 依赖(各约 5 万个被 Git 忽略的文件),git 没能删掉,按规则没有强删。残留路径:
    • D:/OPC/goauto-worktrees/issue-372/web/node_modules
    • D:/OPC/goauto-worktrees/release-372/web/node_modules
      里面不含源码或数据,可以之后手动删除。
### 2026-10-10 worktree 清理(Claude Code) - `D:/OPC/goauto-worktrees/issue-372`、`D:/OPC/goauto-worktrees/release-372`:删除前确认 HEAD 是 `origin/main` 的祖先、`git status --porcelain` 为空、没有进程或 supervisor 配置引用、没有指向外部的链接。 - 已执行 `git worktree remove`(未加 `--force`)和 `git worktree prune`。两个 worktree 都已取消登记,分支 `feat/372-list-export` 和提交历史保留。 - **残留**:两个目录下的 `web/node_modules` 是 pnpm 依赖(各约 5 万个被 Git 忽略的文件),git 没能删掉,按规则没有强删。残留路径: - `D:/OPC/goauto-worktrees/issue-372/web/node_modules` - `D:/OPC/goauto-worktrees/release-372/web/node_modules` 里面不含源码或数据,可以之后手动删除。
Author
Owner

v2 开始实施

  • 日期:2026-10-10
  • 实施者:Claude Code(Sonnet subagent)
  • 用户授权原话(2026-10-10):「按建议来,更新#372后安排sonnet实施」;授权仅含实施、测试、提交、推送分支和回写工单,不含合并 main、发布、部署。
  • 基线提交:919744e(origin/main)
  • 分支:feat/372-export-price;worktree:D:/OPC/goauto-worktrees/issue-372-v2
  • 范围:只改 Web(SYB 导出新增「SYB售价(TWD)」列;两处金额列写成数字单元格)。
## v2 开始实施 - 日期:2026-10-10 - 实施者:Claude Code(Sonnet subagent) - 用户授权原话(2026-10-10):「按建议来,更新#372后安排sonnet实施」;授权仅含实施、测试、提交、推送分支和回写工单,不含合并 main、发布、部署。 - 基线提交:`919744e`(origin/main) - 分支:`feat/372-export-price`;worktree:`D:/OPC/goauto-worktrees/issue-372-v2` - 范围:只改 Web(SYB 导出新增「SYB售价(TWD)」列;两处金额列写成数字单元格)。
Author
Owner

v2 待验收(回写)

分支 feat/372-export-price,未合并 main、未发布。

实现

  • SYB 商品导出在「虾皮商品ID」右侧新增「SYB售价(TWD)」,值为 unitPriceCent / 100(与页面「售价」列同源),数字单元格;空值留空,0 写 0。表头顺序:SYB订单、虾皮商品ID、SYB售价(TWD)、SYB颜色、SYB尺码、SYB数量、yeeke颜色、yeeke尺码、yeeke数量、匹配时间。
  • 采购导出「价格(元)」改为数字单元格,空值留空(centToYuanNumber)。
  • 已设置 0.00 显示格式:export_json_to_excel 新增可选参数 numberFormatCols(默认空数组),只对传入的列、且值为数字的单元格设置 z='0.00';go-admin 自带页面(字典、参数、日志、岗位)不传该参数,导出结果不变(测试中验证了不传时无 0.00 格式)。
  • 不改服务端、接口、数据库,不改页面「售价」列的 ¥ 显示。

改动文件

  • web/src/utils/list-export.js
  • web/src/vendor/Export2Excel.js
  • web/src/views/goauto/purchase-tasks/index.vue
  • web/src/views/goauto/syb-products/index.vue
  • web/tests/unit/list-export.test.cjs
  • docs/03-business-rules-and-glossary.md(Wiki 镜像)

测试(真实结果)

  • cd web && node --test tests/unit/*.cjs:93 项通过,0 失败。新增覆盖:表头顺序;售价 1230→12.3、0→0、null/undefined→'';采购价格数值与空值;用真实 Export2Excel 写出 xlsx 后读回,验证这两列单元格类型为 n、格式 0.00、未传参数时不带该格式。说明:空值在工作表里是空字符串单元格(与既有其他空列写法一致),类型不是数字。
  • pnpm run build:prod:成功(exit 0)。
  • eslint 对三个相关文件:修改前后均为 35 个问题(24 error、11 warning,既有),未新增。

未验证项

  • 浏览器验证(SYB 导出「SYB售价(TWD)」与页面「售价」列一致、Excel 中可直接求和):未执行。
  • 未登录生产或任何远程 Admin,未用真实 Excel 软件打开文件。

提交

  • 代码:d8d9ab9
  • Wiki 镜像:d528c74

Wiki

  • Business-Rules-and-Glossary,#372 段落已更新:线上 revision 35c42f6136426bd3c295fe912d491c3fd980fcb4,已回读与写入内容一致;sync 与 sync --check 各执行一次,仅提交该页镜像。
  • 过程说明:第一次 PATCH 时误把 title 写成带 .- 的路径名,导致页面标题与路径被改(...Glossary.-.-);已立即用原标题 Business-Rules-and-Glossary 修回,路径恢复为 Business-Rules-and-Glossary.-,页面列表核对仅此一个同名页。
## v2 待验收(回写) 分支 `feat/372-export-price`,未合并 main、未发布。 **实现** - SYB 商品导出在「虾皮商品ID」右侧新增「SYB售价(TWD)」,值为 `unitPriceCent / 100`(与页面「售价」列同源),数字单元格;空值留空,0 写 0。表头顺序:SYB订单、虾皮商品ID、SYB售价(TWD)、SYB颜色、SYB尺码、SYB数量、yeeke颜色、yeeke尺码、yeeke数量、匹配时间。 - 采购导出「价格(元)」改为数字单元格,空值留空(`centToYuanNumber`)。 - 已设置 `0.00` 显示格式:`export_json_to_excel` 新增可选参数 `numberFormatCols`(默认空数组),只对传入的列、且值为数字的单元格设置 `z='0.00'`;go-admin 自带页面(字典、参数、日志、岗位)不传该参数,导出结果不变(测试中验证了不传时无 `0.00` 格式)。 - 不改服务端、接口、数据库,不改页面「售价」列的 ¥ 显示。 **改动文件** - `web/src/utils/list-export.js` - `web/src/vendor/Export2Excel.js` - `web/src/views/goauto/purchase-tasks/index.vue` - `web/src/views/goauto/syb-products/index.vue` - `web/tests/unit/list-export.test.cjs` - `docs/03-business-rules-and-glossary.md`(Wiki 镜像) **测试(真实结果)** - `cd web && node --test tests/unit/*.cjs`:93 项通过,0 失败。新增覆盖:表头顺序;售价 1230→12.3、0→0、null/undefined→'';采购价格数值与空值;用真实 `Export2Excel` 写出 xlsx 后读回,验证这两列单元格类型为 `n`、格式 `0.00`、未传参数时不带该格式。说明:空值在工作表里是空字符串单元格(与既有其他空列写法一致),类型不是数字。 - `pnpm run build:prod`:成功(exit 0)。 - `eslint` 对三个相关文件:修改前后均为 35 个问题(24 error、11 warning,既有),未新增。 **未验证项** - 浏览器验证(SYB 导出「SYB售价(TWD)」与页面「售价」列一致、Excel 中可直接求和):未执行。 - 未登录生产或任何远程 Admin,未用真实 Excel 软件打开文件。 **提交** - 代码:`d8d9ab9` - Wiki 镜像:`d528c74` **Wiki** - Business-Rules-and-Glossary,#372 段落已更新:线上 revision `35c42f6136426bd3c295fe912d491c3fd980fcb4`,已回读与写入内容一致;`sync` 与 `sync --check` 各执行一次,仅提交该页镜像。 - 过程说明:第一次 PATCH 时误把 `title` 写成带 `.-` 的路径名,导致页面标题与路径被改(`...Glossary.-.-`);已立即用原标题 `Business-Rules-and-Glossary` 修回,路径恢复为 `Business-Rules-and-Glossary.-`,页面列表核对仅此一个同名页。
Author
Owner

2026-10-10 v2 合并 main 与纯 Web 发布(Claude Code)

用户授权:「合并 #372 v2,并部署到线上」「先让sonnet做完,在合并 #372 v2在更新线上」。

合并前审核

  • 读了 d8d9ab9 的 diff:
    • 新列取 unitPriceCent,与页面「售价」同源;
    • 金额用 centToYuanNumber,空值留空、0 保留;
    • Export2Excel 的 numberFormatCols 是可选参数,默认空,go-admin 自带页面导出不变。
  • 未发现问题。

合并

  • feat/372-export-price(d528c74)以 --no-ff 合并为 main 4ad59bd;sync --check 通过。
  • 合并后复验:node --test tests/unit/*.cjs 93/93 通过,pnpm run build:prod 通过。
  • 与上一发布 72a15f8 相比,Server 源码没有变化。

纯 Web 发布(122.228.200.167)

  • 发布目录 /home/goauto/releases/20261010-4ad59bd-372v2-web,只替换 dist:
    • goauto-server 从上一发布逐字复制,cmp 一致;
    • config 一致,static/temp/var 沿用原目录;
    • 旧 js/css 哈希资源保留。
  • index.html SHA256 83c2dfa845c29073234bbdaaabac0690c46b51d32c85609aaf2743b854915a57。
  • Nginx root 和进程 GOAUTO_WEB_DIST 都指向 /home/goauto/current/dist,所以只原子切换 current,没有重启 GoAuto 和 Nginx:切换前后 PID 4786 不变,服务 active。
  • 按内容验收:
    • /、/login 返回新 index;
    • 10 项 JS/CSS 200;
    • 导出模块包含「SYB售价(TWD)」;
    • health 200,验证码 code=200;
    • 未登录访问业务接口返回 401。
  • 回滚:把 current 切回 /home/goauto/releases/20261010-72a15f8-372,不需要重启。
  • Wiki Deployment-and-Operations:ad212f5 → 77f9ed70e5cd9ab0fffa20e0899fdbef4adaadb5,回读一致。

未验证(待业务验收)

  • 登录后实际导出:
    • SYB 导出的售价与页面「售价」一致;
    • Excel 中两处金额可以直接求和;
    • 采购员账号可以导出。
### 2026-10-10 v2 合并 main 与纯 Web 发布(Claude Code) 用户授权:「合并 #372 v2,并部署到线上」「先让sonnet做完,在合并 #372 v2在更新线上」。 **合并前审核** - 读了 `d8d9ab9` 的 diff: - 新列取 `unitPriceCent`,与页面「售价」同源; - 金额用 `centToYuanNumber`,空值留空、0 保留; - `Export2Excel` 的 `numberFormatCols` 是可选参数,默认空,go-admin 自带页面导出不变。 - 未发现问题。 **合并** - `feat/372-export-price`(`d528c74`)以 `--no-ff` 合并为 main `4ad59bd`;`sync --check` 通过。 - 合并后复验:`node --test tests/unit/*.cjs` 93/93 通过,`pnpm run build:prod` 通过。 - 与上一发布 `72a15f8` 相比,Server 源码没有变化。 **纯 Web 发布**(122.228.200.167) - 发布目录 `/home/goauto/releases/20261010-4ad59bd-372v2-web`,只替换 dist: - goauto-server 从上一发布逐字复制,cmp 一致; - config 一致,static/temp/var 沿用原目录; - 旧 js/css 哈希资源保留。 - index.html SHA256 `83c2dfa845c29073234bbdaaabac0690c46b51d32c85609aaf2743b854915a57`。 - Nginx root 和进程 `GOAUTO_WEB_DIST` 都指向 `/home/goauto/current/dist`,所以只原子切换 current,**没有重启** GoAuto 和 Nginx:切换前后 PID 4786 不变,服务 active。 - 按内容验收: - `/`、`/login` 返回新 index; - 10 项 JS/CSS 200; - 导出模块包含「SYB售价(TWD)」; - health 200,验证码 code=200; - 未登录访问业务接口返回 401。 - 回滚:把 current 切回 `/home/goauto/releases/20261010-72a15f8-372`,不需要重启。 - Wiki Deployment-and-Operations:`ad212f5` → `77f9ed70e5cd9ab0fffa20e0899fdbef4adaadb5`,回读一致。 **未验证(待业务验收)** - 登录后实际导出: - SYB 导出的售价与页面「售价」一致; - Excel 中两处金额可以直接求和; - 采购员账号可以导出。
Author
Owner

2026-10-10 v2 worktree 清理(Claude Code)

  • 已检查 issue-372-v2 和 release-372-v2:HEAD 都是 origin/main 的祖先,git status 为空。
  • 已执行 git worktree remove(未加 --force)和 prune。两个 worktree 已取消登记,分支 feat/372-export-price 保留。镜像提交在 main 上,为 575d5f3。
  • 和 v1 一样,目录下各剩一个 Git 忽略的 web/node_modules,按规则没有强删。残留路径:
    • D:/OPC/goauto-worktrees/issue-372-v2/web/node_modules
    • D:/OPC/goauto-worktrees/release-372-v2/web/node_modules
  • 加上 v1 的两处,共四个残留目录。里面不含源码或数据,可以手动删除。
### 2026-10-10 v2 worktree 清理(Claude Code) - 已检查 `issue-372-v2` 和 `release-372-v2`:HEAD 都是 `origin/main` 的祖先,`git status` 为空。 - 已执行 `git worktree remove`(未加 `--force`)和 `prune`。两个 worktree 已取消登记,分支 `feat/372-export-price` 保留。镜像提交在 main 上,为 `575d5f3`。 - 和 v1 一样,目录下各剩一个 Git 忽略的 `web/node_modules`,按规则没有强删。残留路径: - `D:/OPC/goauto-worktrees/issue-372-v2/web/node_modules` - `D:/OPC/goauto-worktrees/release-372-v2/web/node_modules` - 加上 v1 的两处,共四个残留目录。里面不含源码或数据,可以手动删除。
Author
Owner

v3 开始实施

  • 日期:2026-10-10
  • 实施者:Claude Code(Sonnet subagent)
  • 用户授权原话:「按建议来,更新#372后安排sonnet实施」
  • 授权范围:实施、测试、提交、推送分支、回写工单;不包括合并 main、发布、部署、重启、改生产数据。
  • 基线提交:db64a49(origin/main)
  • 分支:feat/372-export-shop,worktree D:/OPC/goauto-worktrees/issue-372-v3
  • 范围:只改 Web,SYB 导出在「SYB订单」右边新增「店铺」列(shopName),同步调整售价数字格式列号。
## v3 开始实施 - 日期:2026-10-10 - 实施者:Claude Code(Sonnet subagent) - 用户授权原话:「按建议来,更新#372后安排sonnet实施」 - 授权范围:实施、测试、提交、推送分支、回写工单;不包括合并 main、发布、部署、重启、改生产数据。 - 基线提交:`db64a49`(origin/main) - 分支:`feat/372-export-shop`,worktree `D:/OPC/goauto-worktrees/issue-372-v3` - 范围:只改 Web,SYB 导出在「SYB订单」右边新增「店铺」列(`shopName`),同步调整售价数字格式列号。
Author
Owner

v3 待验收

实现:SYB 商品导出在「SYB订单」右边新增「店铺」列,取商品行 shopName(与页面「店铺」列同值),文本单元格,null/undefined 留空。SYB_PRODUCT_EXPORT_NUMBER_COLS 由 [2] 改为 [3],0.00 格式仍落在「SYB售价(TWD)」列。采购导出、服务端、接口、数据库、Export2Excel.js 均未改。

提交:e351a69,分支 feat/372-export-shop(已推送,基线 db64a49,未合并、未发布)。

改动文件

  • web/src/utils/list-export.js
  • web/tests/unit/list-export.test.cjs
  • docs/03-business-rules-and-glossary.md(Wiki 镜像,仅 revision 和 #372 段落变化)

测试

  • node --test tests/unit/*.cjs(web 目录):93 项通过,0 失败。新增或更新覆盖:表头顺序为 SYB订单、店铺、虾皮商品ID、SYB售价(TWD)、SYB颜色、SYB尺码、SYB数量、yeeke颜色、yeeke尺码、yeeke数量、匹配时间;shopName 有值原样输出、null/undefined 留空;用真实 Export2Excel 写出再读回,售价列(D 列)为数字且格式 0.00,店铺列(B 列)为文本且无 0.00 格式。
  • pnpm run build:prod:成功(退出码 0)。
  • npx eslint src/utils/list-export.js:无告警(退出码 0)。

未验证:浏览器验证(导出的「店铺」与页面「店铺」列一致、Excel 实际打开效果)未执行;未登录任何 Admin;未发布。

Wiki:Business-Rules-and-Glossary 的 #372 段落已加入「店铺」列,写入后回读确认;新 revision d427a46283561df71714929c13b7156ee42debea。已执行一次 sync 和一次 sync --check(通过),镜像只带出 docs/03-business-rules-and-glossary.md,无其他无关变化。PATCH 的 title 使用 Business-Rules-and-Glossary,回读标题正确。

worktree:D:/OPC/goauto-worktrees/issue-372-v3 保留,未删除。

## v3 待验收 **实现**:SYB 商品导出在「SYB订单」右边新增「店铺」列,取商品行 `shopName`(与页面「店铺」列同值),文本单元格,null/undefined 留空。`SYB_PRODUCT_EXPORT_NUMBER_COLS` 由 `[2]` 改为 `[3]`,`0.00` 格式仍落在「SYB售价(TWD)」列。采购导出、服务端、接口、数据库、`Export2Excel.js` 均未改。 **提交**:`e351a69`,分支 `feat/372-export-shop`(已推送,基线 `db64a49`,未合并、未发布)。 **改动文件** - `web/src/utils/list-export.js` - `web/tests/unit/list-export.test.cjs` - `docs/03-business-rules-and-glossary.md`(Wiki 镜像,仅 revision 和 #372 段落变化) **测试** - `node --test tests/unit/*.cjs`(web 目录):93 项通过,0 失败。新增或更新覆盖:表头顺序为 `SYB订单、店铺、虾皮商品ID、SYB售价(TWD)、SYB颜色、SYB尺码、SYB数量、yeeke颜色、yeeke尺码、yeeke数量、匹配时间`;`shopName` 有值原样输出、null/undefined 留空;用真实 `Export2Excel` 写出再读回,售价列(D 列)为数字且格式 `0.00`,店铺列(B 列)为文本且无 `0.00` 格式。 - `pnpm run build:prod`:成功(退出码 0)。 - `npx eslint src/utils/list-export.js`:无告警(退出码 0)。 **未验证**:浏览器验证(导出的「店铺」与页面「店铺」列一致、Excel 实际打开效果)未执行;未登录任何 Admin;未发布。 **Wiki**:Business-Rules-and-Glossary 的 #372 段落已加入「店铺」列,写入后回读确认;新 revision `d427a46283561df71714929c13b7156ee42debea`。已执行一次 `sync` 和一次 `sync --check`(通过),镜像只带出 `docs/03-business-rules-and-glossary.md`,无其他无关变化。PATCH 的 `title` 使用 `Business-Rules-and-Glossary`,回读标题正确。 **worktree**:`D:/OPC/goauto-worktrees/issue-372-v3` 保留,未删除。
Author
Owner

2026-10-10 v3 合并 main 与纯 Web 发布(Claude Code)

用户授权:「合并 #372 v3,并部署到线上」。

合并

  • 合并前审核了 e351a69 的 diff:新列取 shopName;SYB_PRODUCT_EXPORT_NUMBER_COLS 从 2 改为 3,售价格式跟着移到新列号。未发现问题。
  • feat/372-export-shop 以 --no-ff 合并为 main 3d5e964。
  • 合并后 Web 单元测试 93/93 通过,build:prod 通过,sync --check 通过。

纯 Web 发布

  • 发布目录:/home/goauto/releases/20261010-3d5e964-372v3-web。
    • goauto-server 与 config 从上一发布复制,cmp 和 diff 均一致。
    • 只原子切换 current,没有重启,PID 4786 前后不变。
  • index.html SHA256:b900a40ec4691f0fb2c3d89e1e20826e7ca3205db311a33c24087767a515979a。
  • 按内容验收:
    • / 和 /login 返回新 index;
    • 10 项 JS/CSS 返回 200;
    • 线上导出模块的表头为 SYB订单, 店铺, 虾皮商品ID, SYB售价(TWD), …;
    • health 200,验证码 code=200,未登录访问业务接口返回 401。
  • main 已包含 #378 的 Server 代码和迁移,本次没有部署:线上 Server 仍是 72a15f8 构建。
  • 回滚:把 current 切回 /home/goauto/releases/20261010-4ad59bd-372v2-web,不需要重启。
  • Wiki Deployment-and-Operations:b50250e → d08a0dfbb8356f9cd7212d495e4f11beca59e293,回读一致;镜像已提交 main 23dafcf。

未验证(待业务验收)

  • 登录后的实际导出,包括「店铺」与页面一致、售价可以求和、采购员账号能导出。
### 2026-10-10 v3 合并 main 与纯 Web 发布(Claude Code) 用户授权:「合并 #372 v3,并部署到线上」。 **合并** - 合并前审核了 `e351a69` 的 diff:新列取 `shopName`;`SYB_PRODUCT_EXPORT_NUMBER_COLS` 从 2 改为 3,售价格式跟着移到新列号。未发现问题。 - `feat/372-export-shop` 以 `--no-ff` 合并为 main `3d5e964`。 - 合并后 Web 单元测试 93/93 通过,`build:prod` 通过,`sync --check` 通过。 **纯 Web 发布** - 发布目录:`/home/goauto/releases/20261010-3d5e964-372v3-web`。 - goauto-server 与 config 从上一发布复制,cmp 和 diff 均一致。 - 只原子切换 current,**没有重启**,PID 4786 前后不变。 - index.html SHA256:`b900a40ec4691f0fb2c3d89e1e20826e7ca3205db311a33c24087767a515979a`。 - 按内容验收: - `/` 和 `/login` 返回新 index; - 10 项 JS/CSS 返回 200; - 线上导出模块的表头为 `SYB订单, 店铺, 虾皮商品ID, SYB售价(TWD), …`; - health 200,验证码 code=200,未登录访问业务接口返回 401。 - **main 已包含 #378 的 Server 代码和迁移,本次没有部署**:线上 Server 仍是 `72a15f8` 构建。 - 回滚:把 current 切回 `/home/goauto/releases/20261010-4ad59bd-372v2-web`,不需要重启。 - Wiki Deployment-and-Operations:`b50250e` → `d08a0dfbb8356f9cd7212d495e4f11beca59e293`,回读一致;镜像已提交 main `23dafcf`。 **未验证**(待业务验收) - 登录后的实际导出,包括「店铺」与页面一致、售价可以求和、采购员账号能导出。
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OPC/goauto#372