SYB 商品展示取消状态,并将退货列改名“匹配退货”及缩窄 #357

Open
opened 2026-10-05 17:13:09 +08:00 by ila · 5 comments
Owner

状态、来源与确认

已实现并部署线上,待用户验收。2026-10-05 用户另行授权合并 main、发布及线上迁移;main 4567a24 已发布至 122.228.200.167,迁移 1791200000000 已回读确认。本机业务库未迁移。2026-10-05 用户授权将最新评论整合到标题和正文,并按“只展示状态”实施 #357。本正文 v2 取代原采购拦截方案;历史评论 8803 的采购风险分析保留供后续独立任务参考,8804/8805 与 SynapBus #32 的范围和布局已合入。

原始需求:SYB 网站订单取消后,本系统缺少来源状态展示;用户要求“匹配到的退货商品”改名“匹配退货”、宽度缩到当前的 80%,空出宽度用于“SYB状态”。后续确认先不改采购,仅展示;取消判据用 isCancel,允许少量横向滚动。

目标、非目标与影响

  • Server:新增可空取消标记和状态取得时间,正常 SYB 同步保存并更新,商品列表返回。
  • Web:只改 SYB 商品页,订单号后显示 SYB 状态三态;退货列改名、缩窄,保留所有原有内容与操作。
  • 不修改 Android、采购创建/重试/下发/Claim/Start/提交订单判断,不收敛任务,不增加旧订单按单号刷新、定时核验、筛选默认隐藏、审批或权限。不执行支付、不自动撤销采购事实。
  • 本单是显示能力,不是取消订单采购拦截;已取消订单仍遵循原采购逻辑。

基线与代码事实

main e4d4a6fa797c17dab9e7779962cc0ededae10149,2026-10-05 核验。

  • web/src/views/goauto/syb-products/index.vue:76:原列 min-width=200;包含图片、退货规格、截止告警及操作,无独立 SYB 状态列。
  • server/app/goauto/sybclient/columns.go:69 已请求 isCancel(t_stock.is_cancel);sybimport/sync.go 构造 OrderInput 未保存该字段;SYBProduct 无来源取消标记。
  • 上一轮授权只读样本观察到 isCancel=1 与“已取消”一致;实施前复核有效取值,不将真实订单、原始生产响应或凭据写入工单。
  • 正常同步以来源创建日期范围为界,不能自动刷新范围外旧订单。

确定的最小契约

  1. SYBProduct 新增 sybIsCancelled(bool|null)、sybStatusSyncedAt(时间|null);数据库列 syb_is_cancelled(可空 boolean,无 false 默认值)、syb_status_synced_at(可空时间)。追加幂等迁移,不回填猜测历史值,不新增权限/索引。
  2. 唯一判据为上游 isCancel,明确 1→true、0→false(实际值类型需只读样本核实);缺失/null/未知值不更新原状态和时间。禁止用 status/orderStatus 或 pdd_purchase_excluded 推断。为保持最小范围,不额外存档可选 orderStatus 原值。
  3. 成功同步拿到有效取消值时,同一货运单下本次同步的明细一并更新;值可从取消恢复为未取消。失败、缺失、空页不清掉旧值。新增历史无值记录为 null。沿用现有页面事务、店铺范围和过滤规则,不引入新并发或上游调用。
  4. 列表及复用同一产品响应结构的详情直接返回 nullable 字段,不增加网络核验;false 必须真实写入并返回,不能被零值省略。
  5. 已知限制:范围外旧订单保留上次同步值;从未获得状态的记录显示“未获取”。界面不称实时状态。

轻量设计 v2(已确认范围,复用现有组件)

确认人:用户;确认时间:2026-10-05;证据:评论 8804/8805 及本轮明确实施授权。小范围列调整,复用现有 Element Plus 表格、标签、加载/失败/空态,无新页面,无需导出独立原型。

  • 订单号后新增表头“SYB状态”,固定 width=72;若实测表头/标签截断或换行,最多调整至 80 并记录结果。
  • true 显示 danger 小号标签“已取消”;false 显示“未取消”;null/接口暂未返回字段显示中性“未获取”。状态用文字表达,不仅靠颜色。
  • “匹配到的退货商品”改为“匹配退货”,min-width=200→160,即原配置的80%,不是保证所有视口实际像素宽均严格为80%。图片、规格、截止告警、查看对比/备注/取消匹配全部保留;允许换行,不遮挡。
  • 其他列不改,采购/退货按钮和原权限不改;SYB 状态与处理阶段分开。
  • 空数据、加载、请求失败沿用列表状态,不伪造正常记录。原可访问角色均可见状态列,不增加权限分支。
  • 允许少量横向滚动;宽度配置预算 1520−40+72=1552px。实际桌面内容区域受侧栏与 padding 影响,以浏览器实测为准。
  • 用 mock 数据提供 1920×1080 和 1440 宽截图,验证表头、三态标签、长退货规格、告警及按钮。按 ui-ux-pro-max 检查可读性,不改变全站主题或组件。

前置依赖与顺序

以包含 #353/#354/#355 的 main 为基线;无新增前置单。顺序:同步字段/幂等迁移与接口 → Web → 单测/构建/浏览器 → Wiki/提交/证据。避免与其他分支同时改商品页,不合入无关 #356。实现与测试可在隔离测试库进行;本机业务库、线上库迁移执行及发布需另外授权。

验收与验证(实现验证见评论,用户验收待进行)

  • 迁移可重复执行、历史状态仍 null,无权限或采购状态写入。
  • 同步测试覆盖取消、未取消、缺失/null/无效值,false 覆盖 true、同订单多条明细一致,缺失保留旧值与时间。
  • 列表返回 nullable 字段正确,旧客户端兼容;无额外上游请求。
  • Web 三态正确,表头和“已取消”不换行不截断;退货列160,状态72或经实测80,1920/1440截图记录。
  • 原退货匹配/勾选/分页与权限不受影响;不改采购或 Android。
  • 受影响 Go 单元/接口/迁移测试、Server 构建、Web 构建、mock 浏览器测试通过,真实未测项明确记录。
  • 提交、推送并回写源码哈希与结果,保持待验收,不自动合并/发布/关闭。

文档与安全

长期数据/API/UI说明变化:更新 Architecture-and-Code-Map、Business-Rules-and-Glossary、Android-Agent-API-Contract 对应管理端契约;线上回读 revision,再一轮 sync 与 sync --check。无本地任务快照。历史采购拦截风险留在评论,不纳入实现。

不记录账号/订单原始生产信息;只用脱敏只读状态样本及 mock 测试。本次仅线上迁移与发布已取得授权并执行;本机业务库未迁移。本会话无 Gitea MCP,按规则使用私有安全配置访问 REST API,不暴露凭据。

## 状态、来源与确认 已实现并部署线上,待用户验收。2026-10-05 用户另行授权合并 main、发布及线上迁移;main 4567a24 已发布至 122.228.200.167,迁移 1791200000000 已回读确认。本机业务库未迁移。2026-10-05 用户授权将最新评论整合到标题和正文,并按“只展示状态”实施 #357。本正文 v2 取代原采购拦截方案;历史评论 8803 的采购风险分析保留供后续独立任务参考,8804/8805 与 SynapBus #32 的范围和布局已合入。 原始需求:SYB 网站订单取消后,本系统缺少来源状态展示;用户要求“匹配到的退货商品”改名“匹配退货”、宽度缩到当前的 80%,空出宽度用于“SYB状态”。后续确认先不改采购,仅展示;取消判据用 isCancel,允许少量横向滚动。 ## 目标、非目标与影响 - Server:新增可空取消标记和状态取得时间,正常 SYB 同步保存并更新,商品列表返回。 - Web:只改 SYB 商品页,订单号后显示 SYB 状态三态;退货列改名、缩窄,保留所有原有内容与操作。 - 不修改 Android、采购创建/重试/下发/Claim/Start/提交订单判断,不收敛任务,不增加旧订单按单号刷新、定时核验、筛选默认隐藏、审批或权限。不执行支付、不自动撤销采购事实。 - 本单是显示能力,不是取消订单采购拦截;已取消订单仍遵循原采购逻辑。 ## 基线与代码事实 main e4d4a6fa797c17dab9e7779962cc0ededae10149,2026-10-05 核验。 - web/src/views/goauto/syb-products/index.vue:76:原列 min-width=200;包含图片、退货规格、截止告警及操作,无独立 SYB 状态列。 - server/app/goauto/sybclient/columns.go:69 已请求 isCancel(t_stock.is_cancel);sybimport/sync.go 构造 OrderInput 未保存该字段;SYBProduct 无来源取消标记。 - 上一轮授权只读样本观察到 isCancel=1 与“已取消”一致;实施前复核有效取值,不将真实订单、原始生产响应或凭据写入工单。 - 正常同步以来源创建日期范围为界,不能自动刷新范围外旧订单。 ## 确定的最小契约 1. SYBProduct 新增 sybIsCancelled(bool|null)、sybStatusSyncedAt(时间|null);数据库列 syb_is_cancelled(可空 boolean,无 false 默认值)、syb_status_synced_at(可空时间)。追加幂等迁移,不回填猜测历史值,不新增权限/索引。 2. 唯一判据为上游 isCancel,明确 1→true、0→false(实际值类型需只读样本核实);缺失/null/未知值不更新原状态和时间。禁止用 status/orderStatus 或 pdd_purchase_excluded 推断。为保持最小范围,不额外存档可选 orderStatus 原值。 3. 成功同步拿到有效取消值时,同一货运单下本次同步的明细一并更新;值可从取消恢复为未取消。失败、缺失、空页不清掉旧值。新增历史无值记录为 null。沿用现有页面事务、店铺范围和过滤规则,不引入新并发或上游调用。 4. 列表及复用同一产品响应结构的详情直接返回 nullable 字段,不增加网络核验;false 必须真实写入并返回,不能被零值省略。 5. 已知限制:范围外旧订单保留上次同步值;从未获得状态的记录显示“未获取”。界面不称实时状态。 ## 轻量设计 v2(已确认范围,复用现有组件) 确认人:用户;确认时间:2026-10-05;证据:评论 8804/8805 及本轮明确实施授权。小范围列调整,复用现有 Element Plus 表格、标签、加载/失败/空态,无新页面,无需导出独立原型。 - 订单号后新增表头“SYB状态”,固定 width=72;若实测表头/标签截断或换行,最多调整至 80 并记录结果。 - true 显示 danger 小号标签“已取消”;false 显示“未取消”;null/接口暂未返回字段显示中性“未获取”。状态用文字表达,不仅靠颜色。 - “匹配到的退货商品”改为“匹配退货”,min-width=200→160,即原配置的80%,不是保证所有视口实际像素宽均严格为80%。图片、规格、截止告警、查看对比/备注/取消匹配全部保留;允许换行,不遮挡。 - 其他列不改,采购/退货按钮和原权限不改;SYB 状态与处理阶段分开。 - 空数据、加载、请求失败沿用列表状态,不伪造正常记录。原可访问角色均可见状态列,不增加权限分支。 - 允许少量横向滚动;宽度配置预算 1520−40+72=1552px。实际桌面内容区域受侧栏与 padding 影响,以浏览器实测为准。 - 用 mock 数据提供 1920×1080 和 1440 宽截图,验证表头、三态标签、长退货规格、告警及按钮。按 ui-ux-pro-max 检查可读性,不改变全站主题或组件。 ## 前置依赖与顺序 以包含 #353/#354/#355 的 main 为基线;无新增前置单。顺序:同步字段/幂等迁移与接口 → Web → 单测/构建/浏览器 → Wiki/提交/证据。避免与其他分支同时改商品页,不合入无关 #356。实现与测试可在隔离测试库进行;本机业务库、线上库迁移执行及发布需另外授权。 ## 验收与验证(实现验证见评论,用户验收待进行) - [ ] 迁移可重复执行、历史状态仍 null,无权限或采购状态写入。 - [ ] 同步测试覆盖取消、未取消、缺失/null/无效值,false 覆盖 true、同订单多条明细一致,缺失保留旧值与时间。 - [ ] 列表返回 nullable 字段正确,旧客户端兼容;无额外上游请求。 - [ ] Web 三态正确,表头和“已取消”不换行不截断;退货列160,状态72或经实测80,1920/1440截图记录。 - [ ] 原退货匹配/勾选/分页与权限不受影响;不改采购或 Android。 - [ ] 受影响 Go 单元/接口/迁移测试、Server 构建、Web 构建、mock 浏览器测试通过,真实未测项明确记录。 - [ ] 提交、推送并回写源码哈希与结果,保持待验收,不自动合并/发布/关闭。 ## 文档与安全 长期数据/API/UI说明变化:更新 Architecture-and-Code-Map、Business-Rules-and-Glossary、Android-Agent-API-Contract 对应管理端契约;线上回读 revision,再一轮 sync 与 sync --check。无本地任务快照。历史采购拦截风险留在评论,不纳入实现。 不记录账号/订单原始生产信息;只用脱敏只读状态样本及 mock 测试。本次仅线上迁移与发布已取得授权并执行;本机业务库未迁移。本会话无 Gitea MCP,按规则使用私有安全配置访问 REST API,不暴露凭据。
Author
Owner

方案审核意见(2026-10-05,Claude Code,基于 main e4d4a6f)

审核由用户授权,经 SynapBus #goauto 发起;只做方案与范围审核,未改代码。

结论:方向正确,但有 2 个阻塞项,须先修订方案;另有 3 项需要用户决定。 工单引用的代码事实已逐条核对无误(sybclient/columns.go:27-28,69 已请求 order_status/is_cancel;sybimport/sync.go 组装 OrderInput 时未带入状态;采购校验中没有取消检查)。

阻塞项

B1. 拦截点不能放在提交订单边界(order-submit-started);在不改 Android 的前提下,这样做会让设备卡死。

  • Android 在 beforeOrderSubmit 中先 purchaseStore.markOrderSubmitStarted(...) 写本地边界标记,再调用 api.markPurchaseOrderSubmitStarted(...)(AgentForegroundService.kt:632-633)。服务端拒绝时,AgentApiException 不是执行器捕获的 PurchaseLiveException(PurchaseRehearsalExecutor.kt:154-161),会跳出执行流程。订单不会被提交,但本地标记会保留下来。
  • 之后每次心跳,recoverInterruptedPurchases 都会重放同一个请求(AgentForegroundService.kt:721-745);服务端再次拒绝时,catch (_: AgentApiException) 会继续保留标记(注释说明这是为断网场景设计的)。activeTaskId() 会持续返回这个任务(PurchaseTaskStore.kt:227-230),设备一直处于执行中,不再领取新任务。
  • 最小闭环的拦截点应前移到 Android 写本地标记之前:
    1. 服务端用户入口:单条创建、批量预检/批量创建、重试。
    2. 设备入口:任务下发列表、Claim、Start。Android 在 claim/start 成功之后才调用 recordRunning(AgentForegroundService.kt:581-588),被拒时由外层 catch (AgentApiException) 处理,不会留下本地标记。
  • 实现陷阱:如果在 Claim 事务里先把任务改成终态、再返回错误,事务回滚会撤销这个修改,设备会反复拿到同一个任务。正确做法:
    • 写入取消状态时(同步或核验成功写入时),把尚未领取的 pending/spec_probe_pending 任务收敛为终态,复用 failed 加新错误码(例如 SYB_ORDER_CANCELLED),不新增状态机状态;
    • 下发列表过滤这些任务;
    • Claim/Start 只做兜底拒绝。
  • 领取之后到点击提交之间的时间窗口写成已知边界。如果确实要在提交边界也拦截,需要另建 Android 工单:识别专用错误码、清除本地边界标记、按失败上报。不应混入本单。

B2. 「明确取消」的判定字段和状态显示的来源尚未确定。

  • 上游有 status、order_status、is_cancel 三个字段,工单没有确定以哪一个判定取消,也没有 orderStatus 数字到文字的映射来源。工单写「显示源状态文字」,但上游返回的是数字。
  • 建议:以 is_cancel 作为唯一的取消判据。实施前用脱敏的只读样本确认它的取值,例如 1 表示已取消。order_status 原值只存档,可放在悬浮提示里。列中只显示三种状态:已取消 / 未取消 / 未获取,不显示没有映射的数字。

需要用户决定

  • D1. 核验 SYB 状态失败时是否放行创建。 建议放行,但仍按最后一次已知状态判断(已知取消照样拦截),并提示「SYB 状态核验失败」。否则 SYB 登录、OCR 或网络故障会阻断全部采购,属于过度门禁。
  • D2. 上游成功返回「未取消」时,是否覆盖本地的取消标记。 建议允许,以上游为准;只有请求失败或数据缺失时不能清除。工单原文「不能把既有取消事实清为正常」需要明确区分这两种情况。
  • D3. 布局。 三种状态都是 2~3 个字的标签,表头「SYB状态」也只有 5 个字,88px 足够。建议状态列用固定 width="88"(不用 min-width,避免被挤宽),放在订单号后;「匹配退货」改为 min-width="160"。表格总宽多出约 48px,靠横向滚动解决。是否接受需要用户确认,不应视为已通过。

上游查询时机与失败处理(建议补入方案)

  1. 正常同步:OrderInput 带入 is_cancel/order_status,同一货运单下的所有明细一起更新,覆盖近期订单。
  2. 用户发起的创建、批量、重试:同步核验。
    • 按订单号去重;最近 10 分钟内已核验过的跳过。
    • ListByOrderNumber 一次只能查一个订单号,批量最多 100 条(purchase/batch.go:21、retry.go:19),所以要限制并发(3~4)、单次超时(约 5 秒)和总预算(约 20 秒)。超出预算的按「核验失败」处理(见 D1)。
    • 返回结果要精确比对订单号;复用现有的 SYB 会话和 SYBSessionAuthLease,不新增并发登录。
  3. 已排队任务:Claim/Start 只读已存储的状态,不在事务内调用上游,否则会在持有行锁时发外部请求。
  4. 列表加载:不调用上游(同意工单原方案)。

可后续优化(不阻塞本单)

  • 定时对 pending 任务所属的订单做去重核验,缩短「同步之后才取消」的发现时间。
  • 筛选或默认隐藏已取消订单,同意另行建单。
  • 「已取消但已下单」的人工处理提示可放进状态列的悬浮提示。

测试补充建议

  • 服务端:取消状态写入后,pending 任务收敛为终态并被下发列表过滤;Claim/Start 兜底拒绝且不出现回滚陷阱;批量核验的去重、预算超时、核验失败放行或拦截(依 D1)。
  • Android(不改代码,只验证):claim/start 被拒后没有本地标记残留,设备可以继续领取下一个任务。可以用现有单测或真机演练任务验证。

结论

先修订 B1、B2,并由用户确认 D1~D3 后再实施。其余部分(迁移字段、同步带入状态、已下单事实保留、状态与处理阶段分开表达、Wiki 影响)同意工单原方案。

## 方案审核意见(2026-10-05,Claude Code,基于 main `e4d4a6f`) 审核由用户授权,经 SynapBus #goauto 发起;只做方案与范围审核,未改代码。 **结论:方向正确,但有 2 个阻塞项,须先修订方案;另有 3 项需要用户决定。** 工单引用的代码事实已逐条核对无误(`sybclient/columns.go:27-28,69` 已请求 `order_status`/`is_cancel`;`sybimport/sync.go` 组装 `OrderInput` 时未带入状态;采购校验中没有取消检查)。 ### 阻塞项 **B1. 拦截点不能放在提交订单边界(`order-submit-started`);在不改 Android 的前提下,这样做会让设备卡死。** - Android 在 `beforeOrderSubmit` 中先 `purchaseStore.markOrderSubmitStarted(...)` 写本地边界标记,再调用 `api.markPurchaseOrderSubmitStarted(...)`(`AgentForegroundService.kt:632-633`)。服务端拒绝时,`AgentApiException` 不是执行器捕获的 `PurchaseLiveException`(`PurchaseRehearsalExecutor.kt:154-161`),会跳出执行流程。**订单不会被提交**,但本地标记会保留下来。 - 之后每次心跳,`recoverInterruptedPurchases` 都会重放同一个请求(`AgentForegroundService.kt:721-745`);服务端再次拒绝时,`catch (_: AgentApiException)` 会继续保留标记(注释说明这是为断网场景设计的)。`activeTaskId()` 会持续返回这个任务(`PurchaseTaskStore.kt:227-230`),设备一直处于执行中,不再领取新任务。 - **最小闭环的拦截点应前移到 Android 写本地标记之前**: 1. 服务端用户入口:单条创建、批量预检/批量创建、重试。 2. 设备入口:任务下发列表、`Claim`、`Start`。Android 在 claim/start 成功之后才调用 `recordRunning`(`AgentForegroundService.kt:581-588`),被拒时由外层 `catch (AgentApiException)` 处理,不会留下本地标记。 - **实现陷阱**:如果在 `Claim` 事务里先把任务改成终态、再返回错误,事务回滚会撤销这个修改,设备会反复拿到同一个任务。正确做法: - 写入取消状态时(同步或核验成功写入时),把尚未领取的 pending/spec_probe_pending 任务收敛为终态,复用 `failed` 加新错误码(例如 `SYB_ORDER_CANCELLED`),不新增状态机状态; - 下发列表过滤这些任务; - `Claim`/`Start` 只做兜底拒绝。 - 领取之后到点击提交之间的时间窗口写成已知边界。如果确实要在提交边界也拦截,需要另建 Android 工单:识别专用错误码、清除本地边界标记、按失败上报。不应混入本单。 **B2. 「明确取消」的判定字段和状态显示的来源尚未确定。** - 上游有 `status`、`order_status`、`is_cancel` 三个字段,工单没有确定以哪一个判定取消,也没有 `orderStatus` 数字到文字的映射来源。工单写「显示源状态文字」,但上游返回的是数字。 - 建议:以 `is_cancel` 作为唯一的取消判据。实施前用脱敏的只读样本确认它的取值,例如 1 表示已取消。`order_status` 原值只存档,可放在悬浮提示里。列中只显示三种状态:**已取消 / 未取消 / 未获取**,不显示没有映射的数字。 ### 需要用户决定 - **D1. 核验 SYB 状态失败时是否放行创建。** 建议放行,但仍按最后一次已知状态判断(已知取消照样拦截),并提示「SYB 状态核验失败」。否则 SYB 登录、OCR 或网络故障会阻断全部采购,属于过度门禁。 - **D2. 上游成功返回「未取消」时,是否覆盖本地的取消标记。** 建议允许,以上游为准;只有请求失败或数据缺失时不能清除。工单原文「不能把既有取消事实清为正常」需要明确区分这两种情况。 - **D3. 布局。** 三种状态都是 2~3 个字的标签,表头「SYB状态」也只有 5 个字,88px 足够。建议状态列用固定 `width="88"`(不用 `min-width`,避免被挤宽),放在订单号后;「匹配退货」改为 `min-width="160"`。表格总宽多出约 48px,靠横向滚动解决。是否接受需要用户确认,不应视为已通过。 ### 上游查询时机与失败处理(建议补入方案) 1. **正常同步**:`OrderInput` 带入 `is_cancel`/`order_status`,同一货运单下的所有明细一起更新,覆盖近期订单。 2. **用户发起的创建、批量、重试**:同步核验。 - 按订单号去重;最近 10 分钟内已核验过的跳过。 - `ListByOrderNumber` 一次只能查一个订单号,批量最多 100 条(`purchase/batch.go:21`、`retry.go:19`),所以要限制并发(3~4)、单次超时(约 5 秒)和总预算(约 20 秒)。超出预算的按「核验失败」处理(见 D1)。 - 返回结果要精确比对订单号;复用现有的 SYB 会话和 `SYBSessionAuthLease`,不新增并发登录。 3. **已排队任务**:`Claim`/`Start` 只读已存储的状态,**不在事务内调用上游**,否则会在持有行锁时发外部请求。 4. **列表加载**:不调用上游(同意工单原方案)。 ### 可后续优化(不阻塞本单) - 定时对 pending 任务所属的订单做去重核验,缩短「同步之后才取消」的发现时间。 - 筛选或默认隐藏已取消订单,同意另行建单。 - 「已取消但已下单」的人工处理提示可放进状态列的悬浮提示。 ### 测试补充建议 - 服务端:取消状态写入后,pending 任务收敛为终态并被下发列表过滤;`Claim`/`Start` 兜底拒绝且不出现回滚陷阱;批量核验的去重、预算超时、核验失败放行或拦截(依 D1)。 - Android(不改代码,只验证):claim/start 被拒后没有本地标记残留,设备可以继续领取下一个任务。可以用现有单测或真机演练任务验证。 ### 结论 先修订 B1、B2,并由用户确认 D1~D3 后再实施。其余部分(迁移字段、同步带入状态、已下单事实保留、状态与处理阶段分开表达、Wiki 影响)同意工单原方案。
Author
Owner

范围调整(2026-10-05,用户确认)

用户原话:「先不要管采购,先把列加上去。尽量不要横向滚动。」

本单范围改为:仅展示 SYB 状态

  • 纳入:同步时保存上游取消状态(迁移新增字段);列表接口返回该状态;SYB 商品页新增「SYB状态」列;「匹配到的退货商品」改名为「匹配退货」并缩窄。
  • 移出本单(另行建单,之前的审核意见保留供后续使用):创建、批量、重试、Claim/Start 的取消拦截;按订单号刷新旧订单状态;任务收敛。B1 和 D1 不再阻塞本单。
  • 仍需在实施前确定:B2,取消判据字段。建议只用 is_cancel,实施前用脱敏只读样本核实取值;order_status 原值只存档。列中只显示「已取消 / 未取消 / 未获取」三态。D2 按同步结果覆盖,以上游为准;同步失败或缺失时不改动已有状态。
  • 已知限制:超出近期同步日期范围的旧订单,状态会停留在上次同步的值,从未同步过的显示「未获取」。按订单号刷新旧订单状态随拦截功能一起另行建单。

布局(替代原 88px 草案)

  • 当前采购员/管理员视图各列最小宽度合计 1520px:勾选 48 + 参考图 76 + 订单号 120 + 虾皮商品 260 + 店铺 100 + 颜色/尺码 128 + 数量 56 + 售价 110 + 解析状态 80 + 处理阶段 210 + 退货 200 + 操作 132。
  • 方案:
    • 「匹配退货」min-width 改为 160(−40);
    • 「SYB状态」放在订单号后,固定 width="72",使用小号标签,表头文字为「SYB状态」;
    • 合计 +32px,总计 1552px;其他列不动。
  • 估算:1920 宽屏幕减去侧边栏约 210px 和页面边距后,可用宽度约 1650px,不出现横向滚动。1440 宽屏幕在改动前已需横向滚动(1520 大于可用宽度),本次只增加 32px。
  • 验收要求:用 Playwright 在 1920×1080 下截图,确认表格没有横向滚动条;同时截取 1440 宽度的对照图。72px 下「已取消」标签和表头不能换行或截断;如果不够,最多放宽到 80px,并回报实际宽度。
## 范围调整(2026-10-05,用户确认) 用户原话:「先不要管采购,先把列加上去。尽量不要横向滚动。」 ### 本单范围改为:仅展示 SYB 状态 - **纳入**:同步时保存上游取消状态(迁移新增字段);列表接口返回该状态;SYB 商品页新增「SYB状态」列;「匹配到的退货商品」改名为「匹配退货」并缩窄。 - **移出本单(另行建单,之前的审核意见保留供后续使用)**:创建、批量、重试、Claim/Start 的取消拦截;按订单号刷新旧订单状态;任务收敛。B1 和 D1 不再阻塞本单。 - **仍需在实施前确定**:B2,取消判据字段。建议只用 `is_cancel`,实施前用脱敏只读样本核实取值;`order_status` 原值只存档。列中只显示「已取消 / 未取消 / 未获取」三态。D2 按同步结果覆盖,以上游为准;同步失败或缺失时不改动已有状态。 - **已知限制**:超出近期同步日期范围的旧订单,状态会停留在上次同步的值,从未同步过的显示「未获取」。按订单号刷新旧订单状态随拦截功能一起另行建单。 ### 布局(替代原 88px 草案) - 当前采购员/管理员视图各列最小宽度合计 **1520px**:勾选 48 + 参考图 76 + 订单号 120 + 虾皮商品 260 + 店铺 100 + 颜色/尺码 128 + 数量 56 + 售价 110 + 解析状态 80 + 处理阶段 210 + 退货 200 + 操作 132。 - 方案: - 「匹配退货」`min-width` 改为 160(−40); - 「SYB状态」放在订单号后,固定 `width="72"`,使用小号标签,表头文字为「SYB状态」; - 合计 +32px,总计 1552px;其他列不动。 - 估算:1920 宽屏幕减去侧边栏约 210px 和页面边距后,可用宽度约 1650px,**不出现横向滚动**。1440 宽屏幕在改动前已需横向滚动(1520 大于可用宽度),本次只增加 32px。 - **验收要求**:用 Playwright 在 1920×1080 下截图,确认表格没有横向滚动条;同时截取 1440 宽度的对照图。72px 下「已取消」标签和表头不能换行或截断;如果不够,最多放宽到 80px,并回报实际宽度。
Author
Owner

用户确认(2026-10-05)

用户原话:「用isCancel字段来判断是否取消。横向滚动一些也没关系。」

  • B2 已确定:取消判据为上游 isCancel(t_stock.is_cancel),不使用 status/orderStatus 判定取消;orderStatus 原值可存档。实施前仍用脱敏只读样本核实 isCancel 的取值含义(哪个值表示已取消),并在实现说明中记录。列中显示「已取消 / 未取消 / 未获取」三态。
  • 布局放宽:允许少量横向滚动。仍按 #issuecomment-8804 的方案执行(退货列 min-width 160、状态列 width 72,必要时最多 80)。1920 下无横向滚动不再作为硬性验收项,改为在实施说明中记录 1920 和 1440 下的实测效果和截图。
## 用户确认(2026-10-05) 用户原话:「用isCancel字段来判断是否取消。横向滚动一些也没关系。」 - **B2 已确定**:取消判据为上游 `isCancel`(`t_stock.is_cancel`),不使用 `status`/`orderStatus` 判定取消;`orderStatus` 原值可存档。实施前仍用脱敏只读样本核实 `isCancel` 的取值含义(哪个值表示已取消),并在实现说明中记录。列中显示「已取消 / 未取消 / 未获取」三态。 - **布局放宽**:允许少量横向滚动。仍按 #issuecomment-8804 的方案执行(退货列 `min-width` 160、状态列 `width` 72,必要时最多 80)。1920 下无横向滚动不再作为硬性验收项,改为在实施说明中记录 1920 和 1440 下的实测效果和截图。
ila changed title from SYB 订单取消状态同步与采购拦截,新增 SYB状态列并压缩匹配退货列 to SYB 商品展示取消状态,并将退货列改名“匹配退货”及缩窄 2026-10-05 17:38:06 +08:00
Author
Owner

实现交付与验证(2026-10-05,待验收)

实现与范围

按正文 v2 严格只做展示,无采购/重试/Claim/Start/Android 代码变化,无权限、任务状态或外部订单写入。分支 feat/357-syb-cancel-status 已提交推送,工作区干净。

  • 源码:d6639a4a0d6954b678822fbc1ce2a9603105073f
  • Wiki 镜像:90e9fa7e79a298de362d0c0168ac5b7bfd583f3b
  • 迁移:server/cmd/migrate/migration/version-local/1791200000000_syb_cancel_status.go;仅在隔离 SQLite 测试中执行,未执行本机业务库或线上库迁移。
  • 两个 nullable 字段 sybIsCancelled / sybStatusSyncedAt 随正常同步导入,JSON 明确返回 false/null;有效 0 可覆盖 1,缺失/无效值不更新旧状态与时间。
  • 只读现场核验:已有会话下返回成功,脱敏取消样本 isCancel=1、类型数值;既有本地 HAR /am/stock/list 中 20 条为数值 0。没有重新登录、触发同步或写生产数据库,也未保存原始响应。
  • 状态列最终固定 72px,在订单号后;退货列 min-width=160,改名“匹配退货”。ui-ux-pro-max 检查后仅补充列内长文本换行、图片不收缩和状态单行样式,不改全站样式。

测试结果

  1. 新增 Go 三组测试通过:取消判据解码(含错误类型/未知值)、同步同订单两明细/旧状态保留/true→false/列表及详情 nullable 契约、追加迁移重复执行/历史留 null/重复迁移保留 false。只用 mock / 内存 SQLite。
  2. go test ./app/goauto/sybclient ./cmd/migrate/migration/version-local -count=1 通过;go build ./... 通过。
  3. sybimport 全包运行存在 12 项既有失败,已在干净 main e4d4a6f 复跑,失败名称完全一致;并非宣称全包通过。排除这 12 项后,sybimport、sybclient、version-local 三包测试通过。既有失败涉及角色纠正/AI 解析/旧 uncertain 预期/重解析与查询预期,本单未修改:
    • TestRepairReversedSpecRolesKeepsAmbiguousColorUncertain
    • TestScheduledAIParseConfirmsClosedCandidatesAndDoesNotRepeat
    • TestScheduledAIParseLeavesLowConfidenceUnmatchedForSameFingerprint
    • TestScheduledAIParseRetriesProviderFailureAtMostThreeTimes
    • TestApplyDetailOnlyMergesSuccessfullyParsedSpecIntoArchive
    • TestParseRealSample_AmbiguousColorWithAnnotationAndSeparator
    • TestParseNoSeparatorIsUncertainNotFailed
    • TestParseBothSidesEmptyAfterStrippingIsUncertain
    • TestReparseUpdatesStatusWhenRuleImproves
    • TestManualCorrectMergesIntoArchiveLikeASuccessfulParse
    • TestReimportPreservesIdenticalAIInputAndInvalidatesChangedSource
    • TestServiceListFiltersByOrderCodesShopAndParseStatus
  4. pnpm run build:prod 通过;既有 CSS minifier / chunk size 警告保留。受改 Vue 文件 ESLint 为 0 error / 0 warning,与 main 一致;未声称全仓 lint 通过。
  5. 浏览器生产构建 + mock 接口,运行 syb-cancel-status、syb-product-layout、syb-return-cancel、syb-return-confirm 共 29 项:28 通过,1 项既有失败。唯一失败“去重后超过100个PDD商品”预期按钮启用,但当前 main 已禁用超限按钮;重新构建 main 后单独复现同一失败,不修改无关测试/功能。原批量使用、取消、混选、权限、分页回归通过。
  6. 新增状态布局测试最终重跑 4/4 通过,含 1920 管理员、1440 售后、375/812 采购员,reduced-motion;三态及旧接口缺字段、72px 不截断、图片44px和原操作保留均验证。取消行仍保留原采购资格,证明没有混入拦截。
  7. git diff --check 通过。harness.py check --strict 仍有 main 既有问题:未登记镜像 docs/evidence/pdd-home-35727-summary.md,本单不修旁支问题。Wiki sync 和 sync --check 各执行一轮,17 个映射页面一致。

实测截图(全部 mock,无生产/个人数据)

截图为指定视口下的 full-page 截图,长文本会增加行高。1920 下表格可完整展示,1440 下沿用表格内部横向滚动。表头和“已取消”标签均单行完整显示。

Wiki revision

  • Architecture-and-Code-Map:f38dbf924894686f3ac1f91b669163ea11fc862b
  • Business-Rules-and-Glossary:bfb8d7abd4d11466fc107ef8f26e0abf5ab13f41
  • Android-Agent-API-Contract:730ddd7a4596a1ff3ed20395f84a9f0760af1d23

镜像遵循线上事实完整同步,包含此前线上已存在、明确标记分支未发布的 #356 文档;没有合入 #356 代码。

未执行与下一步

未合并 main、未重启业务服务、未发布、未执行本机/线上 MySQL 迁移、未触发真实 SYB 同步或采购;临时 mock 预览服务已停止。正式 MySQL 迁移及真实同步页面仍需后续授权验证。仅重启旧服务不会生效;需后续合并、迁移、构建发布。旧订单状态只在同步到对应创建日期范围后更新,未获取记录显示“未获取”。用户验收前保持开放。

## 实现交付与验证(2026-10-05,待验收) ### 实现与范围 按正文 v2 严格只做展示,无采购/重试/Claim/Start/Android 代码变化,无权限、任务状态或外部订单写入。分支 `feat/357-syb-cancel-status` 已提交推送,工作区干净。 - 源码:`d6639a4a0d6954b678822fbc1ce2a9603105073f` - Wiki 镜像:`90e9fa7e79a298de362d0c0168ac5b7bfd583f3b` - 迁移:`server/cmd/migrate/migration/version-local/1791200000000_syb_cancel_status.go`;仅在隔离 SQLite 测试中执行,未执行本机业务库或线上库迁移。 - 两个 nullable 字段 `sybIsCancelled` / `sybStatusSyncedAt` 随正常同步导入,JSON 明确返回 false/null;有效 0 可覆盖 1,缺失/无效值不更新旧状态与时间。 - 只读现场核验:已有会话下返回成功,脱敏取消样本 `isCancel=1`、类型数值;既有本地 HAR `/am/stock/list` 中 20 条为数值 0。没有重新登录、触发同步或写生产数据库,也未保存原始响应。 - 状态列最终固定 72px,在订单号后;退货列 min-width=160,改名“匹配退货”。ui-ux-pro-max 检查后仅补充列内长文本换行、图片不收缩和状态单行样式,不改全站样式。 ### 测试结果 1. 新增 Go 三组测试通过:取消判据解码(含错误类型/未知值)、同步同订单两明细/旧状态保留/true→false/列表及详情 nullable 契约、追加迁移重复执行/历史留 null/重复迁移保留 false。只用 mock / 内存 SQLite。 2. `go test ./app/goauto/sybclient ./cmd/migrate/migration/version-local -count=1` 通过;`go build ./...` 通过。 3. sybimport 全包运行存在 **12 项既有失败**,已在干净 main e4d4a6f 复跑,失败名称完全一致;并非宣称全包通过。排除这 12 项后,sybimport、sybclient、version-local 三包测试通过。既有失败涉及角色纠正/AI 解析/旧 uncertain 预期/重解析与查询预期,本单未修改: - TestRepairReversedSpecRolesKeepsAmbiguousColorUncertain - TestScheduledAIParseConfirmsClosedCandidatesAndDoesNotRepeat - TestScheduledAIParseLeavesLowConfidenceUnmatchedForSameFingerprint - TestScheduledAIParseRetriesProviderFailureAtMostThreeTimes - TestApplyDetailOnlyMergesSuccessfullyParsedSpecIntoArchive - TestParseRealSample_AmbiguousColorWithAnnotationAndSeparator - TestParseNoSeparatorIsUncertainNotFailed - TestParseBothSidesEmptyAfterStrippingIsUncertain - TestReparseUpdatesStatusWhenRuleImproves - TestManualCorrectMergesIntoArchiveLikeASuccessfulParse - TestReimportPreservesIdenticalAIInputAndInvalidatesChangedSource - TestServiceListFiltersByOrderCodesShopAndParseStatus 4. `pnpm run build:prod` 通过;既有 CSS minifier / chunk size 警告保留。受改 Vue 文件 ESLint 为 0 error / 0 warning,与 main 一致;未声称全仓 lint 通过。 5. 浏览器生产构建 + mock 接口,运行 `syb-cancel-status`、`syb-product-layout`、`syb-return-cancel`、`syb-return-confirm` 共 **29 项:28 通过,1 项既有失败**。唯一失败“去重后超过100个PDD商品”预期按钮启用,但当前 main 已禁用超限按钮;重新构建 main 后单独复现同一失败,不修改无关测试/功能。原批量使用、取消、混选、权限、分页回归通过。 6. 新增状态布局测试最终重跑 **4/4 通过**,含 1920 管理员、1440 售后、375/812 采购员,reduced-motion;三态及旧接口缺字段、72px 不截断、图片44px和原操作保留均验证。取消行仍保留原采购资格,证明没有混入拦截。 7. `git diff --check` 通过。`harness.py check --strict` 仍有 main 既有问题:未登记镜像 `docs/evidence/pdd-home-35727-summary.md`,本单不修旁支问题。Wiki `sync` 和 `sync --check` 各执行一轮,17 个映射页面一致。 ### 实测截图(全部 mock,无生产/个人数据) - [1920×1080 视口:状态三态与整体表格](https://git.ilapage.cn/attachments/eb9896cb-cdd4-4b09-b2d5-c2c7c7fc9c4f) - [1440 视口:状态列](https://git.ilapage.cn/attachments/5fc8cc27-1e68-44c1-94d4-6d492d1999d6) - [1440 视口:横向滚动查看退货图片、长规格、告警和操作](https://git.ilapage.cn/attachments/5f50f509-5bec-4014-9894-29cca300e566) 截图为指定视口下的 full-page 截图,长文本会增加行高。1920 下表格可完整展示,1440 下沿用表格内部横向滚动。表头和“已取消”标签均单行完整显示。 ### Wiki revision - Architecture-and-Code-Map:`f38dbf924894686f3ac1f91b669163ea11fc862b` - Business-Rules-and-Glossary:`bfb8d7abd4d11466fc107ef8f26e0abf5ab13f41` - Android-Agent-API-Contract:`730ddd7a4596a1ff3ed20395f84a9f0760af1d23` 镜像遵循线上事实完整同步,包含此前线上已存在、明确标记分支未发布的 #356 文档;没有合入 #356 代码。 ### 未执行与下一步 未合并 main、未重启业务服务、未发布、未执行本机/线上 MySQL 迁移、未触发真实 SYB 同步或采购;临时 mock 预览服务已停止。正式 MySQL 迁移及真实同步页面仍需后续授权验证。仅重启旧服务不会生效;需后续合并、迁移、构建发布。旧订单状态只在同步到对应创建日期范围后更新,未获取记录显示“未获取”。用户验收前保持开放。
Author
Owner

授权合并、线上迁移与发布完成(2026-10-05,待用户验收)

用户先授权“#357合并main,发布到线上”,后明确“授权迁移”。本次只针对 122.228.200.167 线上 Server/Web 和 #357 追加迁移;本机业务库、Android 和真实业务执行不在范围。

  • main 合并提交 4567a24f05c9307d66d189a1fd28225b98b2a16e,Server/Linux amd64 与 Web 从该提交构建;原实现与回归结果见评论 8811,既有失败没有隐去。合并后相关 Go 定向测试、Linux 构建、Web 生产构建通过。
  • 发布目录 /home/goauto/releases/20261005-4567a24-357,current 已切换,goauto.service 重启 active。旧发布 /home/goauto/releases/20261005-ddc18f5-353-355 保留用于代码回滚;共享 static/temp/var 未删除或覆盖。
  • 迁移前核对所有注册版本,唯一待执行为 1791200000000。使用 MySQL 8.4.8 mysqldump 完成服务器内 single-transaction 备份,目录 /home/goauto/backups/20261005-357 0700、database.sql 0600。迁移返回0,使用新数据库会话回读确认 sys_migration 和 nullable tinyint(1)/datetime(3) 两列,待迁移集合为空。没有执行其他版本或历史状态补值。
  • 迁移后首次检查连接复用了 MySQL 一致性读快照,仍看到迁移前集合;新连接回读已确认成功,未重复执行或误判后重置数据。迁移日志仅在服务器受限文件保存。
  • 发布前等待运行中的采集和 SYB 同步结束;切换前采集/采购/同步/AI/回填/批次检查均无执行中记录,既有 pending 保留。sys_job 启停与原来一致,未改 Cron、参数或权限,不主动触发采集、采购、SYB 同步或回填。
  • Nginx 配置检测通过;沿用原静态根目录和代理,无需改配置或 reload。公网首页 HTTP200 且与本次构建 index.html 字节一致,包含 SPA 根节点,不是 GO-ADMIN 欢迎页;10 项入口 JS/CSS 均200;健康和验证码接口200。已认证 SYB 商品列表 code=200,明确返回 sybIsCancelled/sybStatusSyncedAt;历史记录为null。发布附近日志检查 panic/fatal/1054/1146 均0。
  • Server SHA256 73f169cc8091c34dac29f76b6125e68596b54517a18c4e1c7507a3f02f1dbd5d;Web包 SHA256 3edd072d0e44a8ea9768ba906f603c84ca872fad3f553ee91aff0815b58ab488。

文档闭环

线上 Wiki 已更新并回读,sync / sync --check 各一轮通过(17页),镜像提交 b787473429a21069eb929eacc1a088800c43250a 已推送 main;该提交仅文档,不需重新发布运行包。

  • Architecture-and-Code-Map:570383858b934c4d0550f2dff7b755f1dd962888
  • Business-Rules-and-Glossary:8ee23d9c80ebba3cb6cff51e8e25eb1579ab9ac7
  • Android-Agent-API-Contract:5818776a54c3784fbe5d691d830920f9b8f8b888
  • Deployment-and-Operations:84231a25479bb6563645f5b8104805d4f5336349

待验收与限制

刷新线上 SYB 商品页检查状态列和缩窄的“匹配退货”。历史数据先显示“未获取”,只有正常同步覆盖对应来源日期、取得有效 isCancel 后才更新;本次没有额外触发真实同步,所以不宣称线上真实三态端到端已验收。只展示状态,不阻止已取消订单采购。未做本机业务库迁移,未修改或安装 Android。用户确认前保持工单开放。

## 授权合并、线上迁移与发布完成(2026-10-05,待用户验收) 用户先授权“#357合并main,发布到线上”,后明确“授权迁移”。本次只针对 122.228.200.167 线上 Server/Web 和 #357 追加迁移;本机业务库、Android 和真实业务执行不在范围。 - main 合并提交 `4567a24f05c9307d66d189a1fd28225b98b2a16e`,Server/Linux amd64 与 Web 从该提交构建;原实现与回归结果见评论 8811,既有失败没有隐去。合并后相关 Go 定向测试、Linux 构建、Web 生产构建通过。 - 发布目录 `/home/goauto/releases/20261005-4567a24-357`,current 已切换,goauto.service 重启 active。旧发布 `/home/goauto/releases/20261005-ddc18f5-353-355` 保留用于代码回滚;共享 static/temp/var 未删除或覆盖。 - 迁移前核对所有注册版本,唯一待执行为 `1791200000000`。使用 MySQL 8.4.8 mysqldump 完成服务器内 single-transaction 备份,目录 `/home/goauto/backups/20261005-357` 0700、database.sql 0600。迁移返回0,使用新数据库会话回读确认 sys_migration 和 nullable tinyint(1)/datetime(3) 两列,待迁移集合为空。没有执行其他版本或历史状态补值。 - 迁移后首次检查连接复用了 MySQL 一致性读快照,仍看到迁移前集合;新连接回读已确认成功,未重复执行或误判后重置数据。迁移日志仅在服务器受限文件保存。 - 发布前等待运行中的采集和 SYB 同步结束;切换前采集/采购/同步/AI/回填/批次检查均无执行中记录,既有 pending 保留。sys_job 启停与原来一致,未改 Cron、参数或权限,不主动触发采集、采购、SYB 同步或回填。 - Nginx 配置检测通过;沿用原静态根目录和代理,无需改配置或 reload。公网首页 HTTP200 且与本次构建 index.html 字节一致,包含 SPA 根节点,不是 GO-ADMIN 欢迎页;10 项入口 JS/CSS 均200;健康和验证码接口200。已认证 SYB 商品列表 code=200,明确返回 sybIsCancelled/sybStatusSyncedAt;历史记录为null。发布附近日志检查 panic/fatal/1054/1146 均0。 - Server SHA256 `73f169cc8091c34dac29f76b6125e68596b54517a18c4e1c7507a3f02f1dbd5d`;Web包 SHA256 `3edd072d0e44a8ea9768ba906f603c84ca872fad3f553ee91aff0815b58ab488`。 ### 文档闭环 线上 Wiki 已更新并回读,sync / sync --check 各一轮通过(17页),镜像提交 `b787473429a21069eb929eacc1a088800c43250a` 已推送 main;该提交仅文档,不需重新发布运行包。 - Architecture-and-Code-Map:`570383858b934c4d0550f2dff7b755f1dd962888` - Business-Rules-and-Glossary:`8ee23d9c80ebba3cb6cff51e8e25eb1579ab9ac7` - Android-Agent-API-Contract:`5818776a54c3784fbe5d691d830920f9b8f8b888` - Deployment-and-Operations:`84231a25479bb6563645f5b8104805d4f5336349` ### 待验收与限制 刷新线上 SYB 商品页检查状态列和缩窄的“匹配退货”。历史数据先显示“未获取”,只有正常同步覆盖对应来源日期、取得有效 isCancel 后才更新;本次没有额外触发真实同步,所以不宣称线上真实三态端到端已验收。只展示状态,不阻止已取消订单采购。未做本机业务库迁移,未修改或安装 Android。用户确认前保持工单开放。
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OPC/goauto#357