优化
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
# 自营业务文档入口
|
||||
|
||||
本目录维护平台自营业务的设计与规则。自营外部系统数据与客户物流订单、仓储作业库存分开管理。
|
||||
|
||||
- [领星一件代发数据统计一期方案](领星一件代发数据统计一期方案.md):Java 服务归属、分仓同步、表结构、自营菜单、货主经营概览与 SKU 库存关注、每日库存观测、销量图表、采集进度、查询性能及验收;后续库龄、内部评级与成本分摊边界。
|
||||
- [经营总览图表设计](经营总览图表设计.md):新增经营总览页面、指标带、出库趋势、消化天数分布、三类 SKU 图形榜单、统一版本聚合及下钻验收;保持 SKU 为中心。
|
||||
- [库存周转视图设计](库存周转视图设计.md):库存分析默认视图、7/15/30 天同屏、SKU 与货主汇总、可售天数与期间件数周转、数据资格、查询结构及验收。
|
||||
- [数据采集页面设计](数据采集页面设计.md):采集首页与任务详情、来源依赖、阶段进度图、数量摘要、预计剩余时间、结果可用性及逐操作验收。
|
||||
- [领星统计查询性能优化方案](领星统计查询性能优化方案.md):查询耗时定位、总览共享结果与复杂筛选优化顺序、正确性对照及性能验收;业务口径仍以一期方案和总览设计为准。
|
||||
- [领星 WMS 接口联调手册](领星WMS接口联调手册.md):自研系统(OMP)的签名、仓库发现、一件代发出库、产品库存请求参数及只读实测依据,后续批次库龄接口核验入口。
|
||||
|
||||
后端实现先读 [Integration 指引](../../baiyue-firstleg/integration-service/AGENTS.md)与 [Lastleg 指引](../../baiyue-firstleg/lastleg-service/AGENTS.md)。统一部署、认证和服务通信继续遵循现行主契约。
|
||||
@@ -0,0 +1,211 @@
|
||||
# 库存周转视图设计
|
||||
|
||||
在 Admin「自营业务 → 库存分析」增加默认打开的“库存周转”视图,让运营在同一处比较各 SKU 的 7/15/30 天出库、当前库存和消化速度,并按货主汇总,筛选需要复核库存安排及内部仓储成本的对象。
|
||||
|
||||
本设计整理自 2026-10-13 [优化数据采集页面状态提示中的业务讨论](codex://threads/01a134a1-0ccd-7b61-add0-945d47eec5de)。用户已要求整理方案并交开发总控安排。本文件是新增视图、指标扩展、查询合同与验收的维护入口;基础数据、采集及权限沿用[一期方案](领星一件代发数据统计一期方案.md),总览原有下钻沿用[经营总览图表设计](经营总览图表设计.md)。设计交付不表示功能已实现、部署或通过验收。
|
||||
|
||||
## 业务目标与本次边界
|
||||
|
||||
业务需要回答四个问题:哪些货现在存得多;哪些 SKU 近期不动或消化慢;哪些货主的库存需要优先复核;哪些商品持续流转,可以进一步评估仓储支持或成本优惠。
|
||||
|
||||
继续按仓库独立查看全部授权货主,当前仍是自营业务的内部评估与成本分摊准备。领星货主不是平台收费客户,不自动绑定财务账户。件数、出库速度与当前可售天数是经营依据,不直接给出“加价”“优惠”“优级客户”或费率结论。
|
||||
|
||||
| 本次交付 | 后续另行核验 |
|
||||
| --- | --- |
|
||||
| 默认进入即查;SKU 与货主两种视图;7/15/30 天出库同屏;按所选窗口的日均及可售天数;无出库、消化较慢/较快、冻结/次品及待评估筛选 | 真实批次库龄、占用体积、托盘/库位及占用时间、货主与内部成本中心映射 |
|
||||
| 有完整日库存样本时计算期间件数周转次数;不足时展示样本数与缺口,不阻断其他指标 | 正式内部评级、仓租加价/优惠规则、生效期、例外、审批及财务联动 |
|
||||
| 库存与销量时间分别展示;同版本分页、汇总、图表及趋势下钻 | 新外部接口、提高领星并发、补造历史库存、任意历史时点库存重建 |
|
||||
|
||||
本轮扩展了早前“期间周转留待后续”的范围:实现有资格才计算的查询与展示,但不放宽日样本标准。新品、战略备货、季节性、断货与促销尚未建模,所有关注标签都供人工复核。
|
||||
|
||||
## 菜单与首次进入
|
||||
|
||||
保持 `/self-operated/inventory` 和现有菜单,页内提供「库存周转」「库存明细」两个视图。普通菜单进入默认“库存周转”,其中默认“按 SKU”;“按货主”是可选切换,不要求先选择货主,不在经营总览和销量分析恢复货主面板。
|
||||
|
||||
原库存明细继续承接已确认的 10/30 天查询与经营总览严格下钻,不得被新默认页签吞掉或转换成相似的新筛选。它是现有查询能力的明确入口,不增加旧协议别名。
|
||||
|
||||
仓库优先级为合法深链仓库、当前页面保留的有权限仓库、服务端返回的首个有权限仓库;不硬编码仓库编码。确定仓库后自动加载,默认截止日为北京时间昨天,计算基准为 30 天,按实物件数降序、未知末尾。无可用仓库不发经营请求。非法深链或无权仓库明确报错,不静默改查其他仓。
|
||||
|
||||
新视图路由参数使用 `view=TURNOVER,groupBy=SKU|OWNER,endDate,baseWindowDays=7|15|30`,以及其合法筛选/排序和查询上下文。显式 `view=DETAIL` 或原总览严格下钻走原合同;相互冲突的参数拒绝,不混合两套筛选。重置保留仓库,恢复新视图默认条件并重新查询;刷新、查询都只读本地已发布数据,不创建采集任务。
|
||||
|
||||
页签判定按以下顺序执行:总览严格下钻(`from=overview`/`drilldownFrom=DASHBOARD`)进入 DETAIL;其次采用合法显式 view;未指定 view 但有明细专属 `salesWindowDays,attention,coverageSelection,coverageBucket,bucketRuleVersion` 时进入 DETAIL;其余默认 TURNOVER。`warehouseCode,sku,customerCode,endDate` 和公共版本字段本身不决定页签。优先级不吞掉冲突:显式 TURNOVER 同时携带总览来源或明细专属条件必须报错,所有参数再按选定视图校验。
|
||||
|
||||
## 页面示意与交互
|
||||
|
||||
以下是布局与承载设计,不是实际数据或已验收截图。沿用模块 ECharts、蓝紫主色及浅色指标卡,数量、异常和数据状态同时有文字,不只靠颜色。
|
||||
|
||||
```text
|
||||
库存分析 库存周转〔默认〕 库存明细 数据采集
|
||||
仓库 [当前仓] 截止日 [昨天] 日均及消化基准 [7 / 15 / 30天] 查询 刷新
|
||||
按 SKU / 按货主 SKU 搜索〔仅 SKU 视图〕 关注条件 / 阈值 / 排序
|
||||
销量:7日完整、15日缺2日、30日缺12日 当前库存采集:开始……完成……
|
||||
────────────────────────────────────────────────────────────────────
|
||||
实物件数 正品可售件数 近30日无出库 SKU 待评估 SKU
|
||||
────────────────────────────────────────────────────────────────────
|
||||
货主实物件数 Top10(横条) 7/15/30日日均出库对比(柱图)
|
||||
────────────────────────────────────────────────────────────────────
|
||||
全部 | 实物件数最多 | 近30日无出库 | 消化较慢 | 消化较快 | 待评估
|
||||
SKU/商品/货主 | 实物/可售 | 7日/15日/30日出库 | 日均 | 可售天数 | 状态
|
||||
……服务端分页,20条/页…… 扩展列/统计说明
|
||||
```
|
||||
|
||||
图表约 220~260px 高,可折叠且记住本页偏好,表格仍是比较明细的主区。四张指标卡和两图显示当前仓库及精确货主范围的整体情况,不随 SKU 关键字、关注筛选及翻页改变;区块标明“本仓概览”或“本货主概览”。列表上方单独显示筛选结果条数,不能让全仓卡片被误读为当前页合计。
|
||||
|
||||
货主 Top10 按有效全品质实物件数排序,未知货主不按零参与排名,图旁显示未能完整计算的货主数;标题必须是“实物件数”,不写“占仓面积/占仓最多”。相同件数按货主编码稳定排序。点击条目切入本仓该货主的 SKU 视图,显示可清除的货主条件,保留上下文;不足十个按实际数展示。
|
||||
|
||||
日均对比使用该范围内完整的 7/15/30 天总出库分别除以 7/15/30,各柱独立判覆盖,不比较不同天数的原始累计量;无完整口径的柱留空并显示原因,不画零柱。图表用于观察平均速度,不直接生成增长率或客户等级。
|
||||
|
||||
| 操作 | 承载与行为 |
|
||||
| --- | --- |
|
||||
| 切仓/截止日/计算基准/分组 | 同页 QueryToolbar;更新条件并回到第一页;切仓清旧数据,取消旧请求并校验请求世代 |
|
||||
| 关注与阈值 | 同页紧凑控件;选择消化较慢/较快时展开整数天阈值,输入有效后查询;不新增确认弹框 |
|
||||
| 按货主切换 | 同页服务端分页汇总;切换时清除 SKU 关键字及仅适用 SKU 的排序,提示条件已调整;保留仓库、截止日、基准及有效精确货主条件 |
|
||||
| 点击货主 | 同页切回 SKU 列表并添加精确货主 chip;返回货主汇总恢复原页码、筛选和上下文 |
|
||||
| 点击 SKU | 复用当前 1120px 居中 SKU 日趋势 AppDialog,带真实货主+SKU与所选基准区间;不加抽屉或独立详情页 |
|
||||
| 样本与未知原因 | 行内短说明;详细覆盖/日样本证据用现有 1040px 居中证据 AppDialog,最多 30 日;关闭取消请求 |
|
||||
| 图表完整明细 | 沿用 1040px 居中图表明细框,支持键盘等价下钻;不默认重复展示第二张表 |
|
||||
| 统计说明 | 同页折叠文字,集中说明三种指标、时间及未知规则;主表不重复长段说明 |
|
||||
|
||||
SKU 列表是只读分析表,无须新增“操作”列。第一组身份列为 SKU、商品名称、所属货主;长名称可换行,不以内部 ID 回退。首屏保留三窗出库及主要库存/速度指标;冻结、次品、期间平均库存、周转次数、最近已观测出库日、样本证据放扩展列。允许表格内部横向滚动,不挤小全页字体。
|
||||
|
||||
本节是新视图的逐操作设计依据,总控实施时并入模块 `operation-matrix.md`;原明细和总览承载继续沿用既有矩阵。视觉验收为人工 1920×1080、100% 截图,缺证据记“待人工截图确认”。
|
||||
|
||||
## 统计时间与三种指标
|
||||
|
||||
所有窗口使用同一个北京时间截止日 D,默认昨天且不允许未来或未结束的今日。N 天范围为 `[D-N+1 00:00, D+1 00:00)`,N 固定取 7、15、30;不是自然周/自然月,也不复用包含今日的销量图表预设。例:截止 2026-10-12,三个起始日分别为 10-06、09-28、09-13。
|
||||
|
||||
三列出库量始终同屏;`baseWindowDays` 只决定日均、可售天数、快慢查询和期间周转的计算基准,默认 30,不会偷偷把未齐的 30 天换成 7 天。每窗独立返回完整量、已采集量、完整/部分/未知日数、实际日期及原因。部分窗口显示“已采集 X,覆盖不足”,所有日均与派生判断不采用该部分量。
|
||||
|
||||
| 指标 | 计算与命名 | 资格 |
|
||||
| --- | --- | --- |
|
||||
| N 日日均出库 | 同期完整实际出库件数 ÷ N,含真实零出库日 | 使用固定销量版日事实及完整日规则;不只除以有出库的天数 |
|
||||
| 预计可售天数 | 当前正品可售量 ÷ N 日日均出库 | 沿用库存有效性、窗口完整性和本仓 SKU 观察资格;描述正品可售库存,不代表全部实物消化时间 |
|
||||
| N 日件数周转次数 | 同期完整实际出库件数 ÷ 同期每日全品质实物观测均值 | N 个合格同口径日代表、范围/单位/商品身份可靠、同期销量完整;显示“次/N日”,不叫财务周转率 |
|
||||
|
||||
期间平均库存为 `N 个每日代表的实物量之和 ÷ N`,沿用主方案 `DAILY_SCHEDULED_FIRST_V1`:每天指定的首次合格计划采集,不改用每天最新快照,不使用期初/期末二点平均,不是日终或时间加权平均。每个日代表的商品库存先按品质聚合一次,冻结和次品是实物子集,在途不加入。出库分子为同商品同单位全部实际出库,不以某个库存品质过滤重复累加订单。
|
||||
|
||||
当前库存和历史期间独立:更改截止日只改变销量及平均库存的历史区间,预计可售天数仍使用查询时固定的当前库存,页面必须保留库存观测时间。历史周转有完整样本时,不因当前库存过期而抹去历史结果;当前可售天数仍须失效。不同 N 的周转次数不是同一期间,不能直接比较次数得出速度变快。
|
||||
|
||||
计算保留原六位小数精度;日均显示两位、天数一位、周转次数两位,筛选和排序使用未舍入值。很小的正数按显示精度显示“<0.01/<0.1”,不伪装为真实零;前端不重新推算业务指标。
|
||||
|
||||
### 零值与数据不足
|
||||
|
||||
| 条件 | 结果 |
|
||||
| --- | --- |
|
||||
| 窗口完整,当前正可售,但出库为零 | 日均 0,可售天数为空,显示“所选窗口无出库”;不填无限大 |
|
||||
| 当前库存有效且可售为 0 | 可售天数 0 并标“无可售库存”;不进入消化较快,不代表库存健康或货主优秀 |
|
||||
| 当前库存未知/异常/过期 | 可售天数为空并说明;可靠历史出库及历史周转独立展示 |
|
||||
| 7 天完整、15/30 天缺失 | 7 天可独立输出正式值,其他窗口显示已采集量/缺口;默认 30 日基准的日均及天数仍为空 |
|
||||
| N 日日代表齐全且平均实物大于零、出库为零 | 件数周转次数为 0;仍要满足商品观察与销量完整性 |
|
||||
| 平均实物为零 | 周转次数为空;有出库时说明“每日观测未捕获存量”,不输出无穷大或直接认定数据造假 |
|
||||
| 有 30 天出库,但库存只有 2 个合格日样本 | 显示 2/30、缺口和积累起点;周转次数为空,不缩小分母、不用当前库存倒推历史 |
|
||||
| 首采以前、人工 TEST 库存、日代表缺商品行或品质/单位异常 | 沿原规则保留未知/缺口;不补零,不把人工批次事后标成计划日代表 |
|
||||
|
||||
最近已观测出库日期取固定销量版的有效正出库最大日期,不以任意首采日充当。没有可靠日期显示“已采集历史内未见出库”;只有该日期至截止日连续覆盖且商品存在证据可靠时,才可显示“距最近出库 N 天”。不得将有限观察窗口内未见出库写成“从未售出”或真实库龄。
|
||||
|
||||
## 筛选与内部评估规则
|
||||
|
||||
新视图使用独立 `focus`,不改写原 `attention`、总览分桶或 30 日严格下钻含义。观察与异常证据沿用主方案。快慢阈值是本次查询输入,按仓库保存页面偏好但不是正式仓租政策;初始不预设未经确认的 90/180 天,不因未设阈值阻止默认列表。
|
||||
|
||||
| 快捷入口/focus | 规则与默认排序 |
|
||||
| --- | --- |
|
||||
| 全部 ALL | 固定版本候选全集,保留零值、售空及未知;默认实物件数降序 |
|
||||
| 实物件数最多 | ALL+实物降序;不得称为占用空间最大 |
|
||||
| 近30日无出库 NO_OUTBOUND_30D | 有效正实物、同截止日完整 30 日出库为零及本仓观察资格;包含全冻结/次品;基准选 7 日也不改变该按钮的 30 日语义 |
|
||||
| 消化较慢 COVERAGE_GT | 有效正品可售量和 N 日日均均为正且正式可售天数 > 查询阈值;天数降序 |
|
||||
| 消化较快 COVERAGE_LE | 有效正品可售量和 N 日日均均为正且正式可售天数 ≤ 查询阈值;天数升序;只是消化估算,不代表持续销售或正式高周转等级 |
|
||||
| 冻结/次品 FROZEN/DEFECTIVE | 对应有效数量 >0,不依赖销量完整性;这些库存可能无法按日均正常售出 |
|
||||
| 待评估 UNASSESSABLE | 当前库存、所选 N 日窗口或 SKU 观察资格不足,无法完整评估流转表现;有效零可售仍按优先规则显示0天,窗口不足时可同时标“待评估:销量覆盖不足”;完整零出库不属于此类 |
|
||||
|
||||
可售天数判定固定为库存有效性 → 明确零可售 → 正可售的窗口/观察资格 → 分母是否为零;待评估标签不覆盖这一数值顺序,也不等同“可售天数必为空”。另提供“周转样本不足”状态/筛选 `turnoverStatus=INSUFFICIENT`,它与经营待评估独立:已有完整出库和可售天数的 SKU 可以仅缺历史库存样本。无出库与慢消化是不同集合,不将空天数伪装为超大数;冻结/次品与其他关注可重叠,不把标签命中数相加当总 SKU 数。
|
||||
|
||||
货主视图不把整个货主简单分为快/慢:使用“含此类 SKU 的货主”筛选,行内同时显示该类已确认 SKU 数、实物件数和待判断数;未输入阈值时快慢相关值为空并显示“未设查询阈值”。
|
||||
|
||||
## 货主汇总
|
||||
|
||||
货主汇总是一条服务端分页聚合查询,不先获取货主选项再逐个调用 `owner-overview`。身份键为来源账号+仓库+货主;SKU 继续以货主+SKU 去重,不跨货主合并同名商品。
|
||||
|
||||
每行展示货主名称/编码、有实物 SKU 数、实物/正品可售/冻结/次品件数、7/15/30 日出库、所选 N 日日均、近30日无出库 SKU 数及实物件数、慢消化命中和待评估数量;期间周转放扩展列。不平均 SKU 可售天数,也不输出“总库存÷总日均”作为货主整体可售天数。
|
||||
|
||||
货主历史出库和平均实物候选必须涵盖期间曾有库存或出库而当前已售空的商品;不能先筛当前正库存再算周转。货主平均实物先按每个合格日代表汇总该货主全部同口径商品,再取 N 日均值;完整时用货主同期总出库除以该平均量。它仍是混合商品的件数指标,不作为跨货主奖惩排名,不能用高销量小件掩盖积压大件。
|
||||
|
||||
每项总量分别提供正式总量、已知小计和未知数量。销售窗口完整即可展示货主真实出库总量;单个 SKU 库存观察不足不抹掉已可靠的出库事实。无出库等正式命中件数占比,只有整个候选范围及判断均可靠才输出;否则仅给已确认小计与待判断数。比例为实物件数比例,不是空间占比;分母零时比例为空。
|
||||
|
||||
## 服务端合同与数据结构
|
||||
|
||||
新增 Lastleg 只读 `GET /api/platform/v1/last-leg/self-operated-analytics/inventory-turnover`,供新视图使用;原 `/inventory-coverage`、`owner-overview`、经营总览及其严格下钻合同保留各自用途,不把原单窗口接口改成三次调用。复用平台 list 权限、仓库范围检查和既有异常响应。最终 Controller、DTO、OpenAPI、前端类型必须一起收口,以下是开发目标,不宣称接口已经存在。
|
||||
|
||||
| 入参 | 约束 |
|
||||
| --- | --- |
|
||||
| sourceAccount、warehouseCode | 沿现有受控配置及服务端范围检查;只查单仓 |
|
||||
| endDate、baseWindowDays | 截止日含当天且必须为已结束日期;基准 7/15/30,默认昨天/30;三窗固定返回,不传任意窗口数组 |
|
||||
| groupBy、customerCode、sku | SKU/OWNER;customerCode 可选精确身份,用于下钻;sku 沿用现有合法搜索语义但只适用 SKU 分组,OWNER 携带则拒绝 |
|
||||
| focus、coverageDaysThreshold、turnoverStatus | 按上节枚举;GT/LE 必须有正整数阈值,其他关注可带阈值展示标签;拒绝原 attention/coverageBucket 等混入 |
|
||||
| sortBy、current、size | 按分组白名单排序;默认 PHYSICAL_DESC,1/20,size≤100;同值以 SKU+货主或货主编码稳定排序,未知末尾 |
|
||||
| 查询上下文 | 复用固定版本、queryAsOf 和有效期;新增历史日代表集合的固定证据,不能由客户端任填 run ID 绕过检查 |
|
||||
|
||||
SKU 排序至少提供实物/可售降序、7/15/30 日出库降序、所选基准可售天数升降序、期间件数周转次数降序;正式值优先,部分出库只能以明确的“已采集量排序”独立模式参与,不伪装成完整销量排序。OWNER 不支持 SKU 天数排序;支持实物、完整窗口出库、已确认无出库实物小计等明确排序,未知状态随值返回。
|
||||
|
||||
一次响应返回 `context,summary,charts,rows,total`。首次/整体刷新返回概览与两图,普通列表翻页用同一上下文及 `includeOverview=false` 省去重复汇总;筛选 SKU 或关注不改变概览范围。切仓、截止日、基准、精确货主或分组变化时,重新请求对应概览;不得把新上下文的行与旧图拼屏。
|
||||
|
||||
`context` 固定账号、仓库、销量版、当前库存版、queryAsOf、有效期、三个真实窗口、当前库存观测起止、历史日样本规则与最多30个日期到代表批次的映射摘要。历史样本只纳入首次上下文时已经发布且合格的代表;后续样本补齐不能悄悄改变旧查询。实际代表映射须可由服务端验证/重建,缺失日期也冻结,不只是返回一个不可校验的哈希。受引用版本按现有保留策略保护,到期或无法重建时明确要求整体刷新。
|
||||
|
||||
每窗指标至少返回 `days,startDate,endDateExclusive,outboundQuantity,observedQuantity,averageDailyOutboundQuantity,completeDayCount,partialDayCount,unknownDayCount,dataStatus,reasonCodes`;行另外返回 `inventoryCoverageDays,averagePhysicalQuantity,quantityTurnoverCount,qualifiedSampleDays,requiredSampleDays,attentionReasons` 及各自状态。不能用一个行级 COMPLETE 掩盖部分指标未知。内部版本标识用于程序,不作为用户可见业务编号。
|
||||
|
||||
### 复用表与最小结构要求
|
||||
|
||||
| 数据 | 复用与约束 |
|
||||
| --- | --- |
|
||||
| 三窗实际出库 | `ll_selfop_sku_daily_sales`,按固定销量版、仓库及最长30日读取,一次条件聚合三窗;仓级概览优先复用 `ll_selfop_warehouse_daily_sales` 及原覆盖证据 |
|
||||
| 当前实物/可售库存 | `ll_selfop_inventory_snapshot`+其固定 profile,同 SKU 全品质先聚合,避免与日销量多行连接后乘倍 |
|
||||
| 历史平均库存 | `ll_selfop_sync_run.inventory_daily_sample_date/inventory_sample_rule_version` 对应的 snapshot、profile、范围与发布证据;最多30个不可变代表批次 |
|
||||
| 商品观察与缺日 | 固定版本 profile+销量覆盖证明+各库存代表的资格;缺行不补零,不读取可变最新档案污染旧上下文 |
|
||||
| 查询上下文 | 沿现有版本上下文机制扩展日代表集合;可用服务端签名令牌或既有上下文存储,但冻结字段及权限行为一致,实施前总控确定唯一方式 |
|
||||
|
||||
本轮不新增 7/15/30 天销量表、不复制库存日明细、不存一张会被实时覆盖的“SKU 周转结果表”,也不新增采集调度。若实际执行计划证明需要索引或有界聚合缓存,由总控在唯一 SQL 基线中评审;不凭设计先引入缓存平台。没有历史代表时,周转值为空即可交付页面,不能为得到数值额外扫描领星或修改原样本标记。
|
||||
|
||||
## 查询性能与一致性
|
||||
|
||||
所有查询读取本地已发布数据,不查原始订单明细,不调用 Integration。禁止前端逐 SKU/逐货主请求、把第一页求和当全仓汇总、先取 Top100 后筛选、为三窗执行三套完整扫描。
|
||||
|
||||
候选身份是本次固定当前库存版 profile/snapshot、固定销量版所选最长30日事实及相关 profile、同期合格日代表 profile/snapshot 中货主+SKU 的并集;不读取后续可变档案。仅历史存在而当前缺行的商品保留为当前库存未知,不能补零。rows、total、summary 和图表使用同一候选定义,再分别应用各自已声明的范围与列表筛选。
|
||||
|
||||
默认实物排序且无销量/天数/周转等依赖筛选时,可先对完整候选身份分页,再补该页三窗和历史样本,不能只从当前 snapshot 选页而丢失未知/售空商品。依赖销量、可售天数、周转次数的筛选/排序必须先在完整候选计算资格,再排序分页。货主聚合与图表独立按完整范围计算;复用现有性能方案中已验证的路径,不原样重复已无收益的优化实验。
|
||||
|
||||
验收采用单仓至少1万货主+SKU、最多30日代表、多历史销量版、10并发只读用户及后台构建场景。新增目标:首屏含概览 HTTP P95≤1.5s;默认列表翻页 P95≤1s。复杂筛选、货主汇总和完整30日周转排序分别报告,不用缺样本快速返回证明达标;未达目标记录瓶颈交总控安排,不能伪报通过。保留 P50/P95/P99、SQL 数、扫描行、响应大小及结果对照,压测不请求领星。
|
||||
|
||||
相同条件刷新失败可以保留旧结果并明确时间;切仓清旧结果。当前库存过期时只失效依赖当前库存的判断,历史销量/历史周转仍按各自证据展示。页面刷新不会改变采集状态,开发与发布不得为本视图重置采集任务。
|
||||
|
||||
## 开发顺序与职责
|
||||
|
||||
1. 总控冻结新增接口、窗口/零值规则、历史样本上下文和文件写权;明确 SKU 默认与货主可选视图是本轮新增例外,同步最近模块指引及操作矩阵,不恢复其他页面货主控件。
|
||||
2. 指标查询工作包实现一次三窗聚合、库存资格、分页排序、全范围汇总与有资格的期间周转;样本不足作为正常业务状态,补定向公式/覆盖/版本测试。
|
||||
3. 前端工作包实现默认打开、表格两视图、紧凑图表、筛选与既有趋势/证据弹框;先按冻结 DTO 并行,随后联调。共享类型与导航由总控协调唯一写者。
|
||||
4. 采集工作包只核对已有日代表选择、保留及查询证据是否满足合同,不默认改采集或放大请求;必要缺口另交总控精确派工。
|
||||
5. 总控完成接口、SQL 基线、权限及受影响门禁,安排人工页面验收。实现、自动测试、部署、人工验收分别记录;运行状态仍只维护正式工程契约。
|
||||
|
||||
优先交付能立即使用的默认查询、三窗出库、日均/可售天数、关注筛选与货主汇总;期间周转的合成样本测试同期完成,真实数值等待合格日样本自然积累,不让积累期阻断功能开发。不得以“已有可售天数”宣称正式周转已完成。
|
||||
|
||||
## 验收清单
|
||||
|
||||
| 场景 | 必须结果 |
|
||||
| --- | --- |
|
||||
| 普通菜单进入/有效深链/无仓库 | 自动选合法仓并查询;深链优先;无仓不查;不要求先选货主 |
|
||||
| 截止2026-10-12 | 三窗起止分别为10-06/09-28/09-13至10-13不含,均不包含今日 |
|
||||
| 示例 SKU:7/15/30日出库70/150/300,当前可售600;选30日 | 三列各自真实显示;日均10,可售60.0天;切7日仍日均10,不改三窗累计 |
|
||||
| 同一SKU同期30个日代表实物均值500,30日出库300 | 30日件数周转0.60次;不能用当前可售600算成0.50次 |
|
||||
| 7日齐、15/30日未齐 | 7日正式值可用;其他显示已采集量与不足;30日基准天数空,不自动缩短窗口 |
|
||||
| 30日出库齐、仅2个日代表/只有人工TEST库存 | 显示真实样本缺口,正式周转空;销量和符合资格的可售天数继续展示 |
|
||||
| 全冻结/次品正实物且完整30日零出库 | 可命中无出库和库存品质关注;可售为零不判消化较快,不重复累加实物 |
|
||||
| 新品/来源缺行/负数/过期 | 对依赖指标逐项传播未知,不认定无出库、快消化或优秀;负数不取绝对值 |
|
||||
| 库存有效且可售0,但销量窗口不足 | 可售天数0并标无可售库存,同时保留销量覆盖不足及待评估;不因0天进入消化较快 |
|
||||
| 平均库存正且零出库/平均库存零且有出库 | 前者周转0;后者为空并说明单日观测局限,不显示无限大 |
|
||||
| 当前售空但期间有出库与历史库存 | 仍计入货主期间出库及平均库存;不因当前零库存丢失历史贡献 |
|
||||
| 同仓同名SKU不同货主、两仓同货主SKU | 分行、分仓、独立窗口资格,不混合库存或借另一仓历史 |
|
||||
| 货主有部分未知商品 | 出库、库存及关注分别传播;保留已知小计与未知数,不用合格样本比率冒充完整风险占比 |
|
||||
| 切货主/筛选/分页/图表下钻 | 统计范围标签准确;列表 total 与全量谓词一致;图表不由当前页拼出;身份与上下文不丢 |
|
||||
| 原经营总览无出库/最长天数/分桶跳入库存 | 进入原库存明细,保留原30日资格、严格版本及时效,不落入新近似筛选 |
|
||||
| 新版发布、日样本新增、旧上下文读取 | 旧上下文结果不漂移;整体刷新才切新;过期明确要求刷新 |
|
||||
| 页面与性能 | 1920×1080人工核对;三窗与主库存可读;未知有原因;性能按上述真实完整样本分别报告 |
|
||||
|
||||
本轮评审已明确:7/15/30是完整滚动窗口;原10/30明细继续有入口;货主汇总仅在新视图可选;件数不是空间;可售天数不是库龄或期间周转;历史样本不足不造数;新视图查询不增加领星请求。待后续业务确认的是正式仓租/优惠阈值、空间数据和成本主体,均不阻断本次只读功能开发。
|
||||
@@ -0,0 +1,200 @@
|
||||
# 数据采集页面设计
|
||||
|
||||
把采集首页和任务详情改成能直接看懂的进度界面:**正在做什么、总量多少、完成多少、还剩多少、预计还要多久、结果是否已经可用。** 历史尝试、配置和诊断按需展开,不再让用户从多段文字和两张宽表中寻找答案。
|
||||
|
||||
2026-10-13 用户已确认本文方案及配套交互示意,并明确交由开发总控 `01a12feb-0474-77f1-afe0-a3b491733dca` 安排开发。方案维护对话只维护文档,不修改业务代码;图形示意不是实时任务监控,方案确认也不等于正式页面视觉验收。采集范围、统计口径、发布条件和账号保护继续以[一期方案](领星一件代发数据统计一期方案.md)为准,查询性能按[优化方案](领星统计查询性能优化方案.md)验收。
|
||||
|
||||
## 从这条任务暴露的问题
|
||||
|
||||
用户关注任务为 `LXCOL-20261013-FC1699DFFB6E4EC7`,截图显示 US01、2026-10-12 的出库销量采集。本仓状态为“等待数据准备”,详情却显示来源任务 `LXCOL-20261013-0D70D251A9C5488F` 正在获取详情,已处理 339 / 2,787 单。两种状态可以同时成立:来源数据还在准备,本仓尚未开始归并。
|
||||
|
||||
上述数量只代表截图时刻的来源阶段,不能当成此刻实时进度、US01 单量、SKU 销量或整个同步的完成比例。按截图口径剩余 2,448 单,阶段百分比为 12.1%;展示沿用服务端统一舍入口径。
|
||||
|
||||
| 当前问题 | 用户需要看到的解释 | 设计处理 |
|
||||
| --- | --- | --- |
|
||||
| 首页只写等待,关键列被截断 | 后台到底有没有在干活 | 首屏聚焦当前关注任务,同时展示已确认关联的来源进度 |
|
||||
| 本仓执行 0 次,来源却正在执行 | 两段状态是什么关系 | 用“来源准备 → 本仓归并 → 统计计算 → 结果发布”阶段流串起来,范围分别标注 |
|
||||
| 详情重复任务号并铺满文字 | 总量、已完成、剩余在哪里 | 标题保留一次完整任务号;主体用数字摘要、阶段进度图和一句状态解释 |
|
||||
| “完成时间暂无法预计”长期不变 | 大概要等多久 | 增加基于可靠检查点的速度与当前阶段剩余时间;不具备条件时解释具体原因 |
|
||||
| 空执行历史占大块区域,仍展示恢复表单 | 是否有需要我处理的事 | 历史默认收起;无尝试显示一行摘要;不可恢复时不铺表单 |
|
||||
| 页面更新时间看起来很新,但数量未动 | 是页面在刷新,还是任务在推进 | 区分状态读取时间、进度推进时间和执行心跳 |
|
||||
|
||||
### 源码核对结论与边界
|
||||
|
||||
当前前端已有阶段计数、尝试信息、共享来源和结果状态,不需要另起一个监控系统。但后端 `currentTasks` 按最新创建任务选取,不保证它正在执行;详情上游依据直接关联,概览另有时间窗口关联。调度占位任务还可能没有自己的执行尝试。因此,改版必须补齐“当前实际执行”和“本任务等待对象”的语义,不能只改变文字或给现有最新记录套进度条。
|
||||
|
||||
源码入口为 [CollectionView](../../apps/admin-web/src/modules/self-operated/pages/CollectionView.vue)、[CollectionQueryService](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/query/CollectionQueryService.java)、[CollectionReadMapper](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/query/CollectionReadMapper.java) 和 [SelfopProgressProjection](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/model/SelfopProgressProjection.java)。这些是只读源码结论,不证明截图任务最新运行情况或部署状态。
|
||||
|
||||
## 首页:先看正在发生什么
|
||||
|
||||
### 2026-10-13 单账号首屏收敛(优先于下方原方案)
|
||||
|
||||
用户在最新截图中明确:只有一个领星账号,首页只关心账号正在做什么、完成/剩余多少、预计本阶段多久结束及后续处理。首屏改为账号运行看板,直接使用账号活动与各仓实际活动摘要,不受历史任务号或仓库筛选影响;不能把停止的历史记录作为主进度。布局按配套原型重构为运行看板,配色使用现有 Admin 白色卡片与蓝紫色强调,保留环形进度、三项数量、预计时间和阶段流程;待机时显示最近发布结果与各仓可用状态,不把待机画成100%完成。
|
||||
|
||||
按用户最新要求,采集页移除仓库筛选、任务定位、配置、历史详情、诊断与恢复表单,只读一个账号概览接口;旧链接中的仓库和任务号不改变账号首屏。后续阶段用流程说明展示,不宣称已确定执行顺序;待处理只列服务端已返回的活动摘要(每仓每类型有上限),不能将其数量冒充全账号剩余任务总数。没有完整队列与总任务ETA契约时如实说明,继续展示可靠的当前阶段剩余量和阶段ETA。
|
||||
|
||||
保留“自营业务 → 数据采集”和现有页面路由,按以下顺序组织。沿用 [Admin 高密度规范](../Admin高密度界面规范.md),使用连续白底区域、轻分隔和紧凑间距,不为每个字段单独放一张大卡片。
|
||||
|
||||
1. **查询栏:** 仓库、采集内容、任务号定位、查询/刷新;北京时间作为统一辅助说明。任务号支持完整粘贴。选择仓库后定位该仓任务,错误仓库返回明确提示,不自动跨权限搜索。
|
||||
2. **当前关注任务:** 一行完整任务号、仓库、采集内容和数据日期;下面是阶段流、当前阶段数量、等待原因、预计剩余时间和最近推进时间。普通用户无需先打开详情就能理解进展。
|
||||
3. **各仓数据可用情况:** 紧凑表展示仓库+采集内容、当前活动、最近可用数据、覆盖/新鲜度。出库与产品库存各自独立,库存已发布不代表销量已完成。
|
||||
4. **任务记录:** 保留分页、筛选和历史详情。初始展示较少行,把视觉重点留给当前任务;历史列表不能代替实时运行概览。
|
||||
|
||||
首屏焦点默认采用服务端明确的实际活动/阻塞任务,不将“最新创建”冒充“正在执行”。同仓有多个关联任务时给出数量和可切换入口,切换后持续关注所选任务,不被刷新自动换掉。手动选择历史记录时标明“查看历史任务”,保留返回当前活动入口。
|
||||
|
||||
任务号定位同步到现有路由查询参数 `warehouseCode,taskNo`,读取已有受权限约束的任务详情;不要求用户先翻到该任务所在页。轮询不重置历史分页,不丢弃手动选择。任务不存在、无权访问、首次读取失败、暂无任务分别呈现。
|
||||
|
||||
### 历史记录压缩为六列
|
||||
|
||||
| 顺序 | 列 | 呈现方式 |
|
||||
| --- | --- | --- |
|
||||
| 1 | 操作 | “查看详情”;需要固定时固定左侧,不统一写“详情/恢复” |
|
||||
| 2 | 任务/范围 | 完整任务号允许两行;辅助行放仓库、出库/库存、正式/验证用途 |
|
||||
| 3 | 数据时间段 | 显示明确日期区间,精确起止时间进入详情;统一北京时间,结束边界不歧义 |
|
||||
| 4 | 当前阶段与进度 | 阶段标签+简短计数;等待来源时标注来源范围,不塞完整解释段落 |
|
||||
| 5 | 最近进展 | 推进时间及多久前;没有执行尝试时显示未开始本仓执行,不能用读取时间填充 |
|
||||
| 6 | 执行/发布结果 | 如“等待来源 · 未发布”“已完成 · 已发布”“本次失败 · 旧数据可用” |
|
||||
|
||||
完整技术字段、重试资格、尝试历史和诊断从详情查看,不继续横向增加列。按 1920×1080、100% 缩放及展开侧栏验收:关键状态与进度不依赖横向滚动,任务号不只剩无法区分的前缀,长内容自然换行,不缩小字号硬塞。
|
||||
|
||||
## 详情:图形进度在上,诊断记录在下
|
||||
|
||||
继续使用已确认的 **1200px 居中 AppDialog**,保留全屏与关闭;不新增抽屉或独立详情页。弹框标题只出现一次完整业务任务号,内容分为三层。
|
||||
|
||||
### 第一层:数量、进度与时间
|
||||
|
||||
顶部显示“US01 · 出库销量 · 2026-10-12”和简短状态。当前正在等待来源时,主状态为“等待来源数据”,其下突出“关联来源正在获取出库详情”,避免一个大大的“未开始”盖过真实活动。
|
||||
|
||||
主体左侧为当前阶段的环形进度图,右侧为一组数字和时间摘要,共用一个区域:
|
||||
|
||||
| 位置 | 本次截图对应的呈现 | 规则 |
|
||||
| --- | --- | --- |
|
||||
| 图形标题 | 来源详情采集 · 账号共享 | 图形旁持续显示范围,不能只放在提示浮层中 |
|
||||
| 中心数字 | 12.1% · 当前阶段 | 只有可靠分母才能画确定比例;不叫“同步总进度” |
|
||||
| 数量摘要 | 总数 2,787 单/已完成 339 单/剩余 2,448 单 | 同一计数范围、阶段和基准;“单”不是 SKU 件数 |
|
||||
| 时间摘要 | 任务累计耗时(含排队与重试);最近处理速度;预计本阶段还需多久 | 累计耗时使用 Task.elapsedSeconds,从 createdAt 起算,活动任务截止读取时间,终态截止任务最后更新时间;不受 attempt 或阶段切换影响,缺失显示 —;当前阶段 ETA 与任务累计耗时分别标注 |
|
||||
| 提示 | 本仓尚未归并;来源完成后继续计算与发布 | 一句话解释下一步,不复述整段技术规则 |
|
||||
|
||||
未知总量显示“已完成 N 单/总量待确认”(库存按实际单位),使用不表达百分比的阶段状态图,不画 0% 或假转动的确定进度。零量仅表示数量,状态继续取服务端证据:如“0 单,正在核验”或“0 单,结果已发布”;库存显示对应页/行单位,不由 `total=0` 推断正在校验或已经完成。异常计数或总量变化时撤去比例,说明正在复核。
|
||||
|
||||
进度图只表达当前阶段。按 2026-10-13 用户确认,与自营业务其他图表统一使用 ECharts+vue-echarts 的 Canvas 配置,通过 `AnalyticsChart.vue` 复用;当前阶段环图使用无指针、无刻度的环形进度配置。未知、零分母及异常计数只显示空环,不填入虚假百分比。状态同时使用文字和图形,不只靠红绿颜色区分。
|
||||
|
||||
### 第二层:阶段流与结果可用性
|
||||
|
||||
出库流程画为五个节点:**来源目录 → 来源详情 → 更新本仓出库数据 → 统计计算 → 结果发布**。前两个节点标“账号共享”,后三个标“本仓”。完成节点用勾、当前节点用突出色、阻塞节点用原因、未开始节点用灰色;只有服务器确认适用时显示“复用完成/无需此步骤”。不能把完成两个节点直接换算为整体 40%。
|
||||
|
||||
节点完成必须有对应任务、尝试/轮次及切片的服务端完成证据,不能因当前进入后一个阶段就自动勾选之前全部节点。重复扫描、恢复或多切片时标明当前适用范围;缺少阶段历史证据显示“状态未确认”,不补造完成时间或完成结论。
|
||||
|
||||
产品库存采用自己的流程:**本仓库存分页 → 完整性校验 → 统计计算 → 结果发布**。展示页数、读取行数和去重业务键时分别标单位;库存行数不能冒充 SKU 数。
|
||||
|
||||
阶段流下方只保留两条业务说明:
|
||||
|
||||
- **本次结果:** 未发布/已发布/沿用已有结果/失败。来源完成或详情 100% 不等于本仓报表更新。
|
||||
- **当前报表:** 正在使用哪次已发布数据、销量连续覆盖到哪天、库存观测时间。首次没有结果时显示尚无可用数据;已有旧版则继续展示其真实时效。
|
||||
|
||||
多日首采另显示目标日期范围和已发布覆盖/缺口摘要,目标从服务端读取。当前 TEST 最近 30 个完整日和生产首次最近 2 个月不得写成同一个固定标签;单个 12 日任务完成也不代表近 10/30 天可售天数观察窗口已经齐全。
|
||||
|
||||
### 第三层:按需查看与处理
|
||||
|
||||
“执行记录(N 次)”“校验与诊断”按需展开。配置只保留必要摘要,完整配置继续从原页面入口使用只读 AppDialog 查看,不在详情里另造配置区或叠开弹框。没有本仓尝试时只占一行:“本仓尚未开始执行;来源准备进度见上方”,不显示空表、空分页器。来源任务号与其尝试信息独立展示,不混进本仓尝试次数。
|
||||
|
||||
失败、长时间无推进或账号保护生效时,将简短原因提到上方;完整错误码、历史检查点和请求用量留在诊断区。质量尚未计算时摘要写“待校验”,不在多个区块重复长解释。可恢复任务且具备独立写权限时,才展示原有原因填写、核对与恢复操作;等待来源、正常运行或会话终止时不展示不可使用的表单。
|
||||
|
||||
恢复仍沿已有 `POST /sync-tasks` 的 `RETRY`、原任务号和幂等键,受服务端 `allowedActions/actionBlockReason` 控制。受理后只提示已排队,不能提示同步成功;页面不增加绕过账号暂停、会话截止或预算的“强制继续”。
|
||||
|
||||
## 预计时间:先给可靠的阶段估算
|
||||
|
||||
用户需要大概同步时间,因此把速度与预计剩余时间纳入本次设计,不无限期留一句“无法预计”。先交付**当前可计量阶段的剩余时间**;整个任务还需归并、计算、发布时明确说明。完整同步 ETA 只有所有剩余阶段均有可信工作量或校准过的历史耗时模型后才开放,不能把当前阶段 ETA 改个标题当总 ETA。
|
||||
|
||||
计算由服务端产生,页面只显示,不按页面轮询次数、请求次数或截图里的“339 单/78 秒”推算。78 秒可能是尝试耗时,且已完成数量可能包含检查点复用,两者并非同一个测速口径。
|
||||
|
||||
### 计算条件与公式
|
||||
|
||||
- 采样来自已提交的进度检查点。使用同一来源任务、尝试、阶段、扫描轮次、范围、单位和计数基准;分母已确认且在采样窗口内稳定,执行健康正常。
|
||||
- 建议初始参数:最近不超过 3 分钟的有界样本,至少跨度 60 秒、至少 3 次真实推进。阈值集中配置,并用实际采集验证;这是实现建议,不是当前已测得的领星吞吐能力。
|
||||
- `处理速度 = 窗口内新增实际处理完成量 / 窗口实际经过秒数`;正常运行期间没有推进的间隔也计入耗时,不能只统计快的请求。完成总数允许包含复用对象,但测速增量独立排除复用;窗口内新识别的历史复用也不能抬高速度。实现可保留可靠的实际处理增量,无法区分时遇到复用跳变重新建立基线,暂不估算。
|
||||
- 同身份且完成数不变的保存不重置样本,也不计为有效推进;复用导致完成数增加仍重新采样。本次执行至少积累60秒、3次实际推进后估算,累计完成比例不能作为本次测速的样本量。有效期为最多30秒,为10秒轮询留出请求时间,仍受最近推进、执行健康及180秒采样窗口约束;选取在有效期内不会移出窗口的采样起点,避免窗口滚动造成短暂失效。
|
||||
- 估算使用同一份进度身份、完成数、分母和时点。采样窗口截止到本次估算时刻,最后一次检查点后正常等待的时间也计入分母,补充的只读端点不伪造新推进。不能将旧估算与新 completed/total 混合返回;页面按身份和有效期整体接收或丢弃。
|
||||
- `本阶段预计剩余秒数 = (可靠总量 - 已完成量) / 处理速度`。速度必须大于零、剩余量非负;以“约 N 分钟”向上取整展示,小于一分钟显示“约 1 分钟内”,不显示精确到秒的完成承诺。
|
||||
- 阶段切换、尝试重开、轮次变化、分母变化或冷却后恢复均重建测速窗口。建议样本按 10 秒桶合并、最多保留 20 个端点,ETA 持久采样数据不超过 1 KiB,并与已有阶段记录合计遵守进度 JSON 8 KiB 上限。优先保留业务检查点及审计摘要;接近上限时压缩/丢弃 ETA 样本并返回暂不可估算,不能让估算附加数据导致采集提交失败。不为 ETA 扫描全部订单或引入独立时序平台。
|
||||
|
||||
| 情况 | 预计时间区域 |
|
||||
| --- | --- |
|
||||
| 正常推进且样本充分 | “当前阶段预计还需约 N 分钟”,同时显示最近处理速度与估算更新时间 |
|
||||
| 刚启动/恢复后样本不足 | “正在测速”,照常显示已有完成量 |
|
||||
| 总量未确定/正在变化 | “总量待确认,暂不估算” |
|
||||
| 明确限流冷却 | “限流暂停;最早恢复时刻……;恢复后重新估算”,不把冷却结束当完成时刻 |
|
||||
| 预算耗尽/人工暂停/失败/健康待确认 | “已暂停估算”+具体原因,不保留看似继续倒计时的旧 ETA |
|
||||
| 超过配置的无推进期限 | 保留最后真实计数,显示“近期无新增进度,暂不估算”;心跳正常不等于有处理速度 |
|
||||
| 页面读取失败/估算已过期 | 标记最后观测时间,撤去活动倒计时,显示更新失败或估算已过期 |
|
||||
| 本阶段结束但后续阶段未知 | “本阶段已完成;正在归并/计算/发布”,不显示整个同步还剩 0 分钟 |
|
||||
|
||||
服务端返回 ETA 适用阶段、有效期及不可估算原因。全任务 ETA 留作后续校准能力,不阻塞本轮数量、阶段图、测速和阶段预计时间交付;不以提高领星请求并发来让预计时间变短。
|
||||
|
||||
## 任务关联、等待与活动状态合同
|
||||
|
||||
继续扩展现有运行查询 DTO,不新增平行的监控 API,不改采集任务身份。以下为需补齐的语义;已有等价字段优先复用,开发总控确认最终 DTO 命名并同步 OpenAPI、直接调用方和契约测试。
|
||||
|
||||
| 数据组 | 已有基础 | 必须补齐或明确的语义 |
|
||||
| --- | --- | --- |
|
||||
| 关注任务与实际执行 | `currentTask,latestAttempt,taskNo` | 显式区分最新逻辑任务与活动执行;无本仓 run 是合法状态。不能依赖创建时间推断活动任务 |
|
||||
| 依赖与阻塞 | `sharedUpstream`、直接上游关联、概览窗口关联 | 建议返回 `dependencyState,blockingReason,progressSourceTaskNo`;服务端确认关联后才标“为本任务准备”。窗口相交只表示相关候选,不能证明直接依赖;多个实际依赖以有界摘要呈现 |
|
||||
| 阶段计数 | `progressScope,countBasis,attemptNo,phase,scanRound,completed,total,totalKnown,unit,sliceFrom,sliceUntil` | 数量保留范围、来源和分母依据;本仓无投影不能借账号总数填充。本仓页可展示共享进度,但标题必须标账号共享 |
|
||||
| 状态时钟 | `observedAt,progressUpdatedAt,heartbeatAt,executionHealth` | 读取时间、最后提交推进时间、执行心跳分别返回;终态尝试冻结可靠摘要时间。当前终态读取 `summaryAsOf` 而标准冻结路径未写此值,需补实际快照证据,不用查询时刻伪装 |
|
||||
| 等待与保护 | `nextRetryAt,accountCooldownUntil,accountPauseReason` 和预算摘要 | 等待原因与不能重试原因分开;区分来源未齐、排队、冷却、会话截止、预算耗尽。前端不靠本地时钟自行判失败或宣布已恢复 |
|
||||
| 速度与预计时间 | 现有可靠计数和阶段时间 | 建议有界 `stageEstimate`:状态、`progressIdentity`(来源任务、尝试、阶段、轮次、范围、单位、基准)、所依据的 completed/total,以及 `sampleFrom,sampleUntil,completedDelta,ratePerSecond,remainingSeconds,estimatedAt,validUntil,unavailableReason`;completedDelta 仅指实际处理增量。估算和进度依据一致才返回数值,有效期同时受状态观测及无推进期限约束 |
|
||||
| 结果与覆盖 | `resultPublicationState,lastPublishedAt,initialCoverageStatus` 等 | 本次结果和目前报表可用结果独立;来源 `ROUTED`、预算 `YIELDED`、目录完整不能当成本仓发布 |
|
||||
|
||||
依赖不明确时,展示“本任务等待来源;关联进度尚未确认”。如服务端确有其他账号活动,可以另外显示“账号正在执行其他采集”,不能挂在这条任务下面冒充它的完成量。`actionBlockReason` 是操作资格,不能直接当成执行等待原因。
|
||||
|
||||
共享采集可能服务两个仓库,在全部仓库视图按来源任务号去重展示一次;本仓任务不重复累加共享数量或尝试次数。数据范围与权限由服务端核验,不暴露来源密钥、内部数据库 ID 或原始订单载荷。
|
||||
|
||||
## 状态刷新与查询成本
|
||||
|
||||
页面可见且有本仓活动、来源活动、等待来源或待执行任务时,沿用每 10 秒刷新运行元数据;没有活动时每 60 秒刷新。来源仍在推进时,不因本仓执行次数为零降为闲置。切页或浏览器隐藏停止,恢复可见立即读取。
|
||||
|
||||
只保留一个轮询调度器:概览和所关注任务读取有界摘要;任务详情展开时复用同一任务数据,历史尝试分页按需获取,不为每一行各开请求,也不每 10 秒反复拉不变的历史页。仓库切换、任务切换、旧尝试迟到响应均进行取消/身份校验,不覆盖新选择。
|
||||
|
||||
轮询失败保留最后成功读到的数量和时间,提示“状态更新失败”,不把运行状态改成失败。无新推进且心跳正常显示“执行中,最近一次推进在……”,是否超时或失联由服务端判定。页面刷新成功不更新任务推进时间;只有下一次服务端健康与保护状态确认后,才撤销冷却/暂停提示。
|
||||
|
||||
运行查询只读 scope、task、run 与有界投影,不扫描订单、商品明细、统计全表或完整 manifest,不调用领星。阶段 ETA 也不增加外部请求。已有运行元数据 P95 ≤500 ms 的目标继续适用;后续与候选构建混合负载验证按性能方案安排,本轮不新增真实采集或压测。
|
||||
|
||||
## 逐操作设计与验收
|
||||
|
||||
视觉依据是本轮首页与任务详情两张用户截图及用户已确认的配套交互示意;现有承载以 [模块操作矩阵](../../apps/admin-web/src/modules/self-operated/operation-matrix.md)为准。下表为已确认的改版设计,由开发者实施时更新该矩阵;本轮不把设计图写成已实现/已验收。
|
||||
|
||||
| 操作 | 承载与关键验收 |
|
||||
| --- | --- |
|
||||
| 打开采集页 | 现有独立页面;首屏读到活动/等待对象、当前计数、最近推进和结果可用性 |
|
||||
| 输入任务号 | 现有查询栏;可直接定位,不依赖历史首屏;当前关注区保留完整任务号和仓库 |
|
||||
| 切换仓库/关注任务 | 原页更新;旧响应不串仓、不替换手动选择;共享数量不重复合计 |
|
||||
| 查看任务详情 | 原 1200px AppDialog;首屏为数量摘要、阶段图、阶段预计时间和结果提示;全屏/关闭保留 |
|
||||
| 查看历史/诊断 | 当前详情内折叠;空历史无表格和分页;失败原因在首层有短摘要 |
|
||||
| 查看配置 | 复用原只读 AppDialog,不把查看变成修改配置 |
|
||||
| 恢复任务 | 原详情内受权限与资格控制的确认流程;无资格不铺表单,不能绕过账号保护 |
|
||||
| 跳转销量/库存 | 复用已有页面与仓库上下文;目标展示已发布版本,不把运行计数当销量 |
|
||||
|
||||
### 必测状态
|
||||
|
||||
1. **本次截图场景:** 本仓未启动,已确认关联来源正处理 339 / 2,787 单。首页和详情均明确来源在工作,本仓等待;两个任务号、尝试次数和计数范围不混用。
|
||||
2. **关联缺失:** 账号有活动但无法证明属于该任务。明确待确认,不把无关进度贴过来;详情与概览采用同一关联语义。
|
||||
3. **计数边界:** 总量未知、零单、分母变化、分页轮次变化、对象复用、尝试重开。没有虚假百分比、剩余负数、重复完成数或从阶段序号算整体比例。
|
||||
4. **预计时间:** 样本未齐不估算,稳定采样可估算;窗口内外复用都不抬高速度;最后推进后的正常停顿计入窗口;阶段/尝试变化重置,旧估算不得配新数量,冷却和陈旧数据暂停估算,阶段 100% 不等于任务剩余 0。高频推进且历史阶段摘要接近 8 KiB 时,样本仍有界、可降级,采集提交不受 ETA 影响。
|
||||
5. **更新故障:** HTTP 失败、旧响应迟到、心跳过期、心跳正常但无推进。最后观测值保留,任务不被浏览器误判失败;来源活动下保持活动轮询。
|
||||
6. **发布与覆盖:** 来源完成但本仓计算中、本次失败但旧版可用、首次无版本、单日已发布但 10/30 日窗口不足、库存独立发布。所有结论均与实际覆盖一致。
|
||||
7. **权限与布局:** 只读账号可看详情但不可恢复;无资格任务无恢复表单;1920×1080/100% 截图核对首页、普通详情、全屏详情、长任务号和错误状态,关键内容不靠横向滚动或极小字号查看。
|
||||
|
||||
前端状态用受控样本和组件验证,后端关联、计数、ETA 和权限用合同测试;不为验收设计扩大真实领星采集。源码检查、接口验证和人工截图分别交付,缺少人工截图时保留“待人工视觉确认”。
|
||||
|
||||
## 交给开发总控的建议顺序
|
||||
|
||||
| 顺序 | 工作包 | 交付判断 |
|
||||
| --- | --- | --- |
|
||||
| 1 | 统一活动任务、等待依赖与计数范围 | 服务端能解释这条任务在等谁;概览和详情一致;未确认关联如实显示 |
|
||||
| 2 | 首页与现有详情改版 | 先用已有可靠计数呈现阶段图、大数字和结果状态,收起历史及无效操作;不等待复杂总 ETA 才改善可读性 |
|
||||
| 3 | 阶段速度与预计时间 | 补有界采样和服务端估算合同;所有不可估算状态有具体解释,页面显示约数 |
|
||||
| 4 | 联合验收 | 跑上述状态矩阵、元数据查询检查和人工截图,核对两仓/出库/库存;已通过项目不无故重复 |
|
||||
|
||||
用户已授权开发总控将本设计纳入开发安排,由总控协调现有模块写入者、共享接口与执行顺序;方案维护对话不改业务代码,不另建监控服务、任务表、调度系统或用户可见对话。代码、部署和正式验收进度继续只维护在工程主契约;本次设计交接不扩大环境操作授权。
|
||||
|
||||
页面阶段名称 MERGE 显示“更新本仓出库数据”:将已校验的来源出库单按所属仓库写入或更新本地出库数据,再计算销量;不表示库存合并。库存流程独立为获取产品库存、完整性校验、统计计算、结果发布。
|
||||
@@ -0,0 +1,178 @@
|
||||
# 自营经营总览图表设计
|
||||
|
||||
新增 Admin「自营业务 → 经营总览」,用图表回答本仓近期出库是否变化、库存大约需要多久消化、哪些 SKU 出库多、哪些库存值得关注。页面以 SKU 为中心,所属货主只作识别;保持同仓同名 SKU 跨货主分开,不恢复已取消的货主独立筛选或经营面板。
|
||||
|
||||
本文件是经营总览页面、聚合接口、下钻和验收的维护入口;原始事实、同步、可售天数、观察资格、版本与权限沿用[一期方案](领星一件代发数据统计一期方案.md)。本次范围为设计与开发交接,不表示页面已经实现、上线或通过视觉验收。采集和环境操作继续按当前正式契约及用户授权执行,图表查询不调用领星。
|
||||
|
||||
## 菜单与页面布局
|
||||
|
||||
新增路由 `/self-operated/overview`,模块页建议为 `apps/admin-web/src/modules/self-operated/pages/OverviewView.vue`。菜单顺序为经营总览、销量分析、库存分析、数据采集;沿用 `platform:self-operated-analytics:list`,总控统一集成路由、导航及 IAM。保留原三个页面的查询与作业入口,不更改登录后的全局首页。
|
||||
|
||||
总览只选一个仓库,不合并两仓库存、规则或可售天数;不增加来源账号、货主或 SKU 输入框。仓库首次为空时提示选择,返回页面可恢复最近选择;无有效仓库不查询经营接口。来源账号由已有受控配置确定,不在业务页面显示技术键。
|
||||
|
||||
在 `1920×1080`、100% 缩放下采用以下设计布局,正常纵向滚动,不为挤进一屏压缩图形和字体:
|
||||
|
||||
```text
|
||||
经营总览 查看销量 查看库存 数据采集
|
||||
仓库 [选择] 出库趋势范围 [今日/近3天/本周/近15天/本月/自定义] 查询 刷新
|
||||
销量覆盖截至…… 库存采集于…… 有新数据可刷新 / 部分资料提示
|
||||
──────────────────────────────────────────────────────────────────────
|
||||
区间出库量 | 近30日日均出库 | 实物库存 | 正品可售 | 有库存SKU | 无出库SKU
|
||||
──────────────────────────────────────────────────────────────────────
|
||||
出库趋势(日折线,约 2/3 宽) 库存消化天数分布(横向条形,约 1/3 宽)
|
||||
所选日期范围;真实每日点 固定近30个完整日;分类数量与待核验范围
|
||||
──────────────────────────────────────────────────────────────────────
|
||||
所选时段热销Top10 预计消化时间最长Top10 近30日无出库库存Top10
|
||||
按出库件数的横向条形 按可售天数的横向条形 按实物件数的横向条形
|
||||
```
|
||||
|
||||
出库趋势范围默认近 15 天,支持主方案确认的五种自然周期和最多 366 天的自定义范围。该控件同时影响趋势、区间出库 KPI 与热销榜;热销按所选日期内已采集有效出库量排序,未采齐显示部分覆盖。日均、分布、最长消化及无出库库存榜仍标注近 30 个完整日范围。
|
||||
|
||||
KPI 采用紧凑的一行指标带;图表是主要内容,不再以整页描述表承载。复用 Admin 密度令牌,图表不套详情字段网格或普通表格行高。图表行建议趋势约 280~320px 高;榜单给 10 条保留可读高度,不强制全部首屏可见。长 SKU 可换行或省略并提供可聚焦的完整文字;名称与货主为辅助文本,不以内部 ID 回退。
|
||||
|
||||
## 指标带
|
||||
|
||||
数值来自服务端,保留版本、单位、覆盖和未知原因。这里的件数均为出库或库存数量,不是订单数、成交收入或净销售额。
|
||||
|
||||
| 指标 | 展示口径 |
|
||||
| --- | --- |
|
||||
| 区间出库量 | 与当前全仓趋势的日点合计守恒;全日均完整才显示正式总量,否则标为“区间已采集出库量”,全无可靠值为“—” |
|
||||
| 近 30 日日均出库 | 本仓最近 30 个完整自然日实际出库总量÷30;完整仓级覆盖即可计算,不因某个 SKU 库存观察不足抹去有效出库。不用当前图表天数做分母 |
|
||||
| 实物库存 | 当前固定库存版各货主/SKU/品质的有效实物量;冻结、次品已经包含在实物中,不重复相加;在途不加入 |
|
||||
| 正品可售 | 只汇总正品有效可用数量,不再减冻结、不加在途或次品 |
|
||||
| 有库存 SKU | 全品质实物量已核验大于零的货主+SKU 去重数;品质行不是独立 SKU;存在库存未知时标记“已确认 N,另 M 待核验” |
|
||||
| 近 30 日无出库 SKU | 有实物且满足完整 30 日零出库及本仓观察资格的 SKU 数;观察不足和未知另外说明,不认定卖不掉 |
|
||||
|
||||
库存或风险总量存在依赖未知时,正式值为空,允许显示“已知小计”及未知 SKU 数;不把未知过滤后仍显示成全仓总数。单项完整性独立:库存失败不阻止完整销量图;销量不足不掩盖已核验库存。全仓可售天数、平均 SKU 可售天数、评分和“优级客户”不在指标带中。
|
||||
|
||||
## 五张图表
|
||||
|
||||
### 出库趋势
|
||||
|
||||
使用日折线图,横轴为北京时间业务日期,纵轴为件数,零基线;日期轴包含完整选择区间。后台按仓库及固定销量版直接汇总有效日事实,包含现在已无库存的出库商品,不从库存列表或 Top 榜单反推总量。仓级全日覆盖完整且无出库时可为零,不要求每个 SKU 均满足 30 日库存观察期。
|
||||
|
||||
每个日点返回正式量、已采集量、完整性和覆盖原因。缺日断线,部分日用明确的点形/虚线及“未完整”文字;不平滑跨越缺口。今日只有一个日累计点,不画小时趋势;自定义长区间减少坐标标签密度但保留全部日点和提示。整段已采集合计等于可靠日点已采集量之和;所有日点未知时合计为空。
|
||||
|
||||
仓级零值与部分值单独判断:全天覆盖完整时,正式量=已采集量=有效日行合计,无行可为 0;只有部分已证明覆盖且无日行时,正式量为空、已采集量为 0、状态 PARTIAL;没有覆盖证明但存在已确认日行时仍保留日行合计为已采集量、状态 PARTIAL;没有覆盖证明且没有日行时,两值均为空、状态 UNKNOWN。连续水位外的已确认日行不能被丢弃,整个仓级趋势不套单 SKU 存在时间或库存观察门槛。
|
||||
|
||||
点击已知日点进入销量分析当日自定义范围;未知日不可伪造零数据下钻,改显示该日覆盖不足原因。鼠标提示和键盘聚焦均显示日期、件数、状态;不能仅依赖颜色解释未知。
|
||||
|
||||
### 库存消化天数分布
|
||||
|
||||
使用横向条形图,单位为 SKU 个数,显示“有实物库存或库存待核验 SKU 的分布”。候选取固定两版 profile 的货主+SKU 并集:明确有效且实物为零的 SKU 排除;有效正实物以及实物未知/过期的候选保留。整个库存版尚不可用时显示无库存资料,不将全部销售候选画成一个伪造的库存总量。
|
||||
|
||||
`bucketRuleVersion=COVERAGE_DISTRIBUTION_V1` 按以下先后顺序将每个候选只归入一个桶;上一步命中后不再落入后续桶。销量与观察资格沿用主方案,不直接将没有日行视为零出库:
|
||||
|
||||
| 桶 | 判定 |
|
||||
| --- | --- |
|
||||
| `UNKNOWN` 库存或销量待核验 | 先检查本 SKU 实物或用于可售天数的正品可售数据异常/未知/过期;命中即归此桶。后续因销量窗口或观察资格不足无法计算时也归此桶,分别统计原因 |
|
||||
| `NO_AVAILABLE` 无可售库存 | 库存有效、实物大于零且正品可售量明确为零;可包含冻结或次品,不宣称周转良好,不依赖销量资格 |
|
||||
| `NO_OUTBOUND_30D` 近 30 日无出库 | 有效正可售量、完整 30 日及观察资格且出库为零;天数为空,不转成无限大 |
|
||||
| `DAYS_0_30`、`DAYS_30_60`、`DAYS_60_90`、`DAYS_GT_90` | 正可售量、正日均且资格完整,按未舍入天数分别落 `(0,30]`、`(30,60]`、`(60,90]`、`(90,+∞)` |
|
||||
|
||||
在无可售库存判断之后、零出库或数值分桶之前检查销量/观察资格;不足回到 UNKNOWN。展示顺序为四个数值桶、无出库、无可售、待核验,不等于执行判定顺序。30/60/90 仅为本版图形分组边界,不是收费、补货或优劣政策。
|
||||
|
||||
各桶 `skuCount` 之和必须等于 `candidateSkuCount`,并同时返回已排除的确定零实物 SKU 数。图表不展示“风险率”百分比;待核验量无法被藏进已评估分母。可在提示中显示桶内已知实物小计及未知件数范围,不把件数与 SKU 个数混用。
|
||||
|
||||
此分布为互斥展示分组,主方案 attention 是可并存的关注条件,两者不等价。例:全冻结且近 30 日零出库 SKU 归 NO_AVAILABLE,但仍可出现在无出库库存榜。冻结、次品、可售、在途不能作为可相加的饼图组成部分。
|
||||
|
||||
### 三个 SKU 榜单
|
||||
|
||||
均为横向条形图,最多 10 个候选;热销使用页面所选日期,另两个库存榜固定至昨日的 30 个完整自然日;无合格候选显示原因,不造空条或补足 10 个。每条展示 SKU、可用名称、所属货主及主指标,提示补充库存/日均/日期依据。同名 SKU 不跨货主合并;坐标从零开始,条长按真实数值,不截成相同最大长度。数量过大可用统一刻度单位,提示保留原值。
|
||||
|
||||
| 图表 | 资格与排序 | 下钻 |
|
||||
| --- | --- | --- |
|
||||
| 所选时段热销 Top 10 | 按所选日期已采集有效正出库量降序、单数降序、SKU/货主编码升序;部分覆盖也展示,明确标记未完整,不将未采集当零。库存缺失或售罄不阻止进入 | 条目打开同窗口 SKU 趋势;“查看 Top 100”进入销量分析相同 CUSTOM 日期范围 |
|
||||
| 预计消化时间最长 Top 10 | 有效正可售、正日均、完整窗口及观察资格;按未舍入可售天数降序,SKU/货主编码升序。零销量单列,不冒充无限天数;不等同原 slow-skus 低销量榜 | 条目打开 SKU 趋势;“查看全部”进入库存分析相同有限天数候选及天数降序 |
|
||||
| 近 30 日无出库库存 Top 10 | 主方案 attention=NO_OUTBOUND_30D:全品质有效正实物、完整窗口和观察资格、出库零;包含全冻结/次品有实物者。按实物量降序,SKU/货主编码升序 | 条目打开 SKU 趋势;“查看全部”进入库存分析无出库关注及实物量降序 |
|
||||
|
||||
排名从全仓所有已授权货主的候选先算资格/排序后截取,不先截 SKU 清单或逐货主各取十个再汇总。观察不足时返回待评估数量;榜单明确是“符合条件的 SKU”,不以没有合格候选推断库存健康。可售天数很长仍是按历史速度的估算,不标成真实库龄或一定卖不掉。
|
||||
|
||||
## 图表交互与视觉依据
|
||||
|
||||
本文件作为新增页面的设计依据,布局由上面的页面示意和本矩阵约束;实现前总控将对应记录并入模块现有 `operation-matrix.md`。既有页面承载以该矩阵的用户截图纠正为准,不读取或恢复更早的货主面板。
|
||||
|
||||
| 页面操作 | 承载与行为 | 设计验收 |
|
||||
| --- | --- | --- |
|
||||
| 仓库/趋势范围查询 | 同页紧凑 QueryToolbar;查询先校验再更新,切仓清旧数据并取消旧请求 | 不增加独立货主控件,不在主区堆账号键、时区技术值、长规则 |
|
||||
| 刷新 | 明确按钮整体更新版本与 queryAsOf;新数据提示不自行替换某张图 | 过期上下文显示刷新提示,不混合版本 |
|
||||
| 柱/条与日点提示 | 图内提示,键盘可聚焦查看同等内容;未知日只展示缺口原因 | 不是新业务弹框,不仅靠颜色或悬浮识别数值 |
|
||||
| SKU 条目趋势 | 沿用当前 1120px 居中 AppDialog,支持已有全屏/关闭;传该行 customerCode+sku 和上下文,热销使用所选范围,另两个榜固定 30 日范围 | 不改为列表下方详情、抽屉或新详情页;关闭取消请求 |
|
||||
| 分桶或查看全部 | 导航至既有销量/库存正式页面并带准确筛选、版本和返回来源 | 目标页显示可清除的“来自经营总览”条件摘要,不重新引入货主选择器 |
|
||||
| 查看采集状态 | 导航至所选仓的数据采集页 | 只查看当前状态,不触发采集/重试 |
|
||||
|
||||
保留屏幕阅读名称、键盘入口、焦点和足够对比度;趋势每日数值、SKU覆盖证据、库存分组说明、分布与排行榜按2026-10-13用户截图反馈统一使用居中弹框;分布与排行榜使用“查看完整明细”1040px居中弹框,提供完整名称、数值、证据及同资格的键盘下钻入口,长字段换行,正文滚动;悬浮提示只展示名称和数量并限制宽度,Top100/查看全部仍进入对应列表,不将全页默认变回表格。主图使用折线与条形,不使用 3D、雷达、仪表盘、双轴、装饰动画或无依据的“健康分”。按 2026-10-13 用户确认,自营业务图表统一使用 ECharts+vue-echarts,通过模块内 `AnalyticsChart.vue` 按需注册并使用 Canvas 渲染;坐标轴、提示框、缩放、条形及环形进度用配置维护,删除手写 SVG/CSS 绘图。日趋势与 SKU 趋势共用有效数据连线配置,未完整日用虚线,未知或缺失日期仍断线。
|
||||
|
||||
功能/合同评审和人工视觉验收分别记录。本设计不代替真实页面的人工 `1920×1080`、100% 截图验收,未提供截图时保留待人工确认,不声称视觉通过。
|
||||
|
||||
## 服务端聚合接口
|
||||
|
||||
新增 `GET /api/platform/v1/last-leg/self-operated-analytics/dashboard`,前端使用独立 `analyticsApi.dashboard`。现有前端 `overview` 实际调用 `sync-overview`,是采集状态接口,不能用它冒充经营聚合或改掉原语义。
|
||||
|
||||
入参要求 `sourceAccount,warehouseCode`,趋势参数复用 `rangePreset` 和 CUSTOM 的 `startDate,endDate`;不接受 customerCode、SKU、跨仓合并或任意 Top N。首次查询固定主方案中的两版、范围摘要、queryAsOf 及到期时间;后续只切趋势范围复用上下文,显式刷新/切仓重新建立。榜单数量服务端固定 10,消化天数分组固定 V1。
|
||||
|
||||
在一次短只读一致快照中校验范围/版本并读取所需数据;整个响应共同使用同一上下文,不由前端并发获取多个“最新版本”后拼屏。某一数据族不可用时仅返回该族不可用,不妨碍另一族可用图形;鉴权失败、参数错误、版本无效或 SQL 失败是请求错误,不吞掉后转零或正常空图。
|
||||
|
||||
| 响应块 | 主要字段与要求 |
|
||||
| --- | --- |
|
||||
| `context` | 主方案现有完整版本上下文、实际趋势范围、固定 30 日窗口、salesCoveredFrom/Until、库存观测起止、inventoryFreshUntil、queryExpiresAt,另含 inventoryDrilldownExpiresAt(有效库存时取前两截止时间的较早值,否则不可用);技术字段用于程序,不放主页面占位 |
|
||||
| `kpis` | 六项指标各有 value/knownSubtotal、单位、dataStatus、unknownSkuCount、reasonCodes;区间出库另有正式量/已采集量,日均使用独立完整日窗口 |
|
||||
| `salesTrend` | 每日 points 及区间汇总;每点 businessDate、outboundQuantity、observedQuantity、dataStatus、reasonCodes,最多 366 点,日轴不省略缺日 |
|
||||
| `coverageDistribution` | bucketRuleVersion、candidateSkuCount、excludedZeroPhysicalSkuCount、各 bucketCode/skuCount、可选已知实物小计/未知数、dataStatus/reasonCodes;分组未知原因有摘要 |
|
||||
| `hotSkus`/`longCoverageSkus`/`noOutboundSkus` | 各自实际窗口(windowStartDate/windowEndDateExclusive/calculationWindowDays)、eligibleCount、unassessableCount、items(最多 10)、dataStatus/reasonCodes;每项包含实际 customerCode+sku、名称、主指标及其单位/必要辅助值,窗口出库字段为windowOutboundQuantity。热销部分覆盖返回PARTIAL与SALES_WINDOW_INCOMPLETE,不返回该部分量推算的日均和消化天数。单点弹框复用原 daily API,不因图形新增另一份销量公式 |
|
||||
|
||||
计数无法确定时用空值和原因,不能把未计算的 eligibleCount/unassessableCount 默认为零。冻结、次品、在途可作为必要辅助数量,不新增会被误加总的库存占比饼图。所有经营数量的已知小计/完整总量遵守主方案;日均销售不依赖 SKU 的库存观察期,风险分类则依赖。
|
||||
|
||||
### 精确下钻合同
|
||||
|
||||
现有销量/库存页仅解析并传递 warehouseCode、sku,不能只拼一个新 URL 就宣称下钻已完成。此次必须扩展目标页的参数解析、初始化、取消请求、校验与返回上下文;来源条件只作为查询条件,权限仍由服务端核验。
|
||||
|
||||
- 通用路由条件:`warehouseCode`、可选精确 `sku,customerCode`(仅行身份,不显示独立货主选择器)、原完整版本上下文、`from=overview`。使用固定本地路由,不接受任意 return URL;编码/日期/枚举非法显式提示,不能静默忽略成全仓查询。
|
||||
- 趋势日点:销量页 `analysis=SKU`、`rangePreset=CUSTOM` 且 startDate=endDate=该日。热销 Top 100:`analysis=HOT,rangePreset=CUSTOM,startDate,endDate`,日期来自榜单窗口(endDate 为 exclusive 截止前一日),不再携带 windowDays。这两个路由枚举是新增初始化合同,开发映射到现有页面状态,不能原样当作新的外部 API 字段。dashboard 的 eligibleCount 是当前已采集有效正出库候选数,热销明细沿用原 Top 100 上限,故 total=min(eligibleCount,100),前 10 名及主值必须一致;不扩展成无限热销榜。
|
||||
- 无出库全部:库存页 `attention=NO_OUTBOUND_30D,sortBy=PHYSICAL_DESC`。最长可售全部:`/inventory-coverage` 和路由均新增 `coverageSelection=FINITE_POSITIVE`,在服务端 SQL 分页前过滤为正式有限正可售天数候选,`sortBy=COVERAGE_DAYS_DESC`;不能仅在浏览器当前页过滤,也不能把零库存、未知天数放进候选冒充同一榜单。该字段属于本地报表接口,不传领星。
|
||||
- 分布条形:库存页新增 `coverageBucket` 与 `bucketRuleVersion=COVERAGE_DISTRIBUTION_V1`。服务端 `/inventory-coverage` 同步接收并按上述唯一分组谓词过滤;不能把区间点击近似替换成 attention 或一个“大于”阈值。coverageBucket 与 coverageSelection、非 ALL attention 互斥,冲突拒绝;未带 bucket 时不接收单独 ruleVersion。FINITE_POSITIVE 与非 ALL attention 也互斥。
|
||||
- 日点、整榜、分桶或具体 SKU 下钻均携带同一版本上下文;条件 chip 可清除,清除后恢复目标页常规范围,但不更换仍有效的上下文。返回总览恢复原仓库、趋势范围、上下文及滚动位置;到期或版本不可用时提示整体刷新,不能悄悄换新后声称与原图一致。
|
||||
|
||||
库存严格下钻额外携带 `drilldownFrom=DASHBOARD` 给 `/inventory-coverage`,用于声明与原图一致的读取要求,不授予额外权限;from=overview 的目标页必须映射此参数。服务端从原上下文及库存 run 的真实时效重新计算 inventoryDrilldownExpiresAt,不信任客户端传入的截止时间。库存已超过有效期或上下文到期时返回明确的“原图库存已过期,请刷新总览”错误,不能按过期后的 UNKNOWN 重新分桶再冒充原图结果;前端同时禁用原库存图的分桶/榜单列表下钻。此时趋势与热销的有效读取仍可继续,普通库存页的历史/过期展示保持原规则;重新加载的过期总览仅提供普通库存诊断入口,不提供严格分桶下钻。单条 SKU 的出库趋势不受库存过期阻断。
|
||||
|
||||
## 数据模型与查询性能
|
||||
|
||||
本页不新增采集任务、调度、周月汇总、缓存平台或库龄表。2026-10-13 用户确认允许新增仓库每日汇总表 `ll_selfop_warehouse_daily_sales`,按销量版本、来源账号、仓库、业务日保存有效已采集量、异常日行数与源日行数,数量沿用六位小数。每批 SKU 日行与对应仓日汇总在同一事务写入并推进构建检查点;发布前核对汇总覆盖的源行数,成功后同事务设置销量版本 `warehouse_daily_ready`。空销量版也必须完成该验证,不能以汇总表无记录推断为零。缺少就绪证据的版本明确拒绝总览读取,重新构建发布,不回退到旧查询或补写旧版本。
|
||||
|
||||
趋势和仓库销量合计读取已发布仓日汇总,日期完整性、部分采集与异常口径仍由原版本覆盖证据判定;仓日汇总不证明完整自然日。SKU 明细、库存与榜单继续复用已发布 daily、snapshot、profile、run;SQL 按版本、仓库、日期限缩,库存先按货主+SKU/品质聚合,再与销量连接,禁止原始订单 Join 或逐 SKU/逐货主 N+1。版本保留与受保护版本规则同时覆盖仓日汇总;不引入额外清理调度。
|
||||
|
||||
趋势在数据库按业务日期聚合;三个榜单分别在完整候选上计算并排序 LIMIT 10;分桶在 SQL 中 CASE 聚合,不能从第一页库存或 Top 100 拼出全仓分布。前端一次 dashboard 响应只接收最多 366 个日点、7 个桶和 30 条榜单记录及固定 KPI,不请求全部库存,不逐货主调用 owner-overview。下钻的库存计数及谓词必须与 dashboard 共享,避免边界漂移。
|
||||
|
||||
沿用主方案的代表性合成数据档位:单仓 1 万货主+SKU、多个历史统计版、有后台构建及 10 个并发只读用户。新增目标为 dashboard HTTP P95≤1.5s;报告 P50/P95/P99、SQL 数、扫描行及响应大小,查询数量须为固定少量、不得随 SKU/货主数线性增长。目标未实测,不以 SVG 绘图流畅代替后端验收。首次与预热分别记录,任何测试不对领星发起压力请求。
|
||||
|
||||
首次加载用结构占位;无仓、无业务版本、可靠全零、观察不足、过期和失败分别呈现。主动切仓立即清旧仓图并隔离迟到响应;相同条件刷新失败可以保留旧图,但明确“刷新失败,展示上次查询”,不伪装新成功。到达库存有效期或上下文到期后,相应指标标为历史/待刷新,不继续作为当前可信结论;不靠后台轮询替换单张图。点击刷新只读本地接口,不意味着立即同步领星。
|
||||
|
||||
## 离线验收与评审
|
||||
|
||||
下表均为合成数据设计,不作为真实经营结果;开发需同步 OpenAPI、权限、目标页路由解析和直接测试,API 门禁沿后端根指引执行。原模块已有功能与人工截图结论保留,不因新增总览回退 SKU 中心布局。
|
||||
|
||||
| 用例 | 必须得到的结果 |
|
||||
| --- | --- |
|
||||
| 近 15 天含今日,另选今日/本周/本月/CUSTOM | 趋势轴、区间出库与热销榜随选择变化,另两榜/分布/日均仍固定 30 日;今日单点无小时数据 |
|
||||
| 日量 2、未知、5,今日部分 1 | 可靠值合计 8 标已采集,正式总量为空;缺日断线,今日部分;全未知合计为空,不为 0 |
|
||||
| 同仓 SKU X 属货主 A 出库 2、B 出库 5,均有效 | 全仓对应日为 7;榜单与点击身份保留两条,下钻分别为 2/5 |
|
||||
| 库存缺失但完整 30 日热销数据存在 | 日均、趋势、热销可用,依赖库存的图形显示未就绪,不让库存失败清空销售 |
|
||||
| A 正可售 3000、30 日出库 300;B 正可售 30、出库 30 | A 可售 300、B 30,分别归 >90 和 (0,30],最长榜 A 在前;不按低销量将 B 当更积压 |
|
||||
| 候选 5 个:有效正可售零出库、全冻结且零出库、库存未知、有效天数 30、有效天数 30.04;再有明确零实物 1 个 | 分别落无出库/无可售/待核验/(0,30]/(30,60];桶合计 5、排除数 1;冻结 SKU 仍能进入独立无出库库存榜 |
|
||||
| 正品实物 120 含冻结 20,可售 100;次品实物 8,在途 30 | 实物 128、可售 100,不相加为 278;图中不出现这几个重叠量的库存组成饼图 |
|
||||
| 整体存在未知库存或观察不足;热销和无出库候选不足 10 个 | 标已知小计和待评估,不补齐榜单、不宣称整体无风险;完全无可靠资料不显示健康零值 |
|
||||
| 90、90.04 天显示均可能接近 90;零出库的天数为空 | 比较与分桶按未舍入值,分别≤90/>90;零出库不进最长有限天数榜、不放成无限值 |
|
||||
| 每个分桶点击、榜单跳转、单条趋势,随后返回;另测 200 个热销候选 | 库存分桶/最长/无出库的 total 等于对应完整候选数;热销 total=min(eligibleCount,100),200 个候选时为 100,前 10 一致。身份/版本不变,复用 1120px 趋势弹框,返回保留范围及滚动位置 |
|
||||
| 图表加载途中切仓、后台发布新版、跨午夜或上下文过期 | 旧仓响应不覆盖新仓;不单图切版或自动滚动今天;到期明确刷新,库存过期不继续显示当前有效 |
|
||||
| 同一版本和 30 分钟上下文仍有效,但库存先到 freshUntil,再点击原分桶/库存榜单 | 前端阻止旧图严格下钻,服务端同样拒绝,不返回改变分类的结果冒充一致;要求刷新总览,出库趋势/热销仍按其独立资格读取 |
|
||||
| dashboard 或路由参数缺仓、非法桶、互斥参数冲突、客户身份调用 | 明确拒绝,不能悄悄全仓查询;平台鉴权和来源范围校验不因汇总而弱化 |
|
||||
|
||||
设计评审收口项:SKU 中心与现有页面一致;两套窗口分开;分布互斥且守恒;零出库与有限天数分开;全品质实物不重叠相加;未知不隐藏;下钻需要真实参数接线和共用谓词;新增聚合接口与运行概览分开。评审不覆盖生产吞吐、真实数据对账或人工视觉验收。
|
||||
|
||||
本轮已分别完成数据口径、页面/接口两项独立评审,并复核修正后的合同:补齐仓级部分日零值规则、库存时效先于查询上下文到期的严格下钻门禁,以及热销完整候选数与原 Top 100 上限的区别。设计范围内无剩余阻塞,可交开发总控安排;不把该结论作为代码、性能或视觉验收通过。
|
||||
|
||||
后续可在真实库龄、空间占用和内部经营规则核验后增加库龄分布及成本分析,不在本页放无数据的库龄饼图、平均周转率、货主评分或费用预测。开发总控按本设计安排前后端工作,计划和测试状态由其当前对话及正式工程契约维护。
|
||||
|
||||
图表明细与说明弹框通过 append-to-body 挂到页面根部,避免图表卡片动画/transform限制遮罩与弹框;更换数据关闭旧弹框,日期下钻先关闭明细,长表只滚动弹框正文。库存分组说明宽760px,每日数值/覆盖证据和排行明细宽1040px,可全屏。
|
||||
|
||||
热销Top10完整明细按用户最新截图去重:使用1280px居中弹框,按排名、SKU、商品名称、货主、所选时段出库量、实物库存、可售库存、窗口日均、预计可售天数分列;不再拼接重复说明段落,窗口与覆盖状态只在表格上方展示。商品名称与SKU完全相同时显示—,以“SKU+空格”起始时仅去掉该重复前缀;货主+SKU身份及点击下钻保持不变,未知指标不补零。
|
||||
@@ -0,0 +1,350 @@
|
||||
# 领星 WMS 一件代发与产品库存接口联调手册
|
||||
|
||||
本手册是后续开发的外部 API 入口,说明请求方式、参数、字段映射、实测差异和验收方法。业务同步、表结构、统计口径和开发顺序以[一期方案](领星一件代发数据统计一期方案.md)为准。本期只使用 **WMS 一件代发出库单和 SKU 产品库存**,不接整箱中转出库单或整箱库存,不做箱数到件数的推算。
|
||||
|
||||
接口体系为领星 WMS 管理后台的“自研系统/服务商内部系统对接”,官方文档站为 OMP。不要换成 OMS 货主端或 WMS 智能设备的路径和签名。
|
||||
|
||||
**当前执行边界:首次正式历史采集改为最近 2 个月,放在生产执行;测试只做有硬上限的小样本。** 同一真实账号由一个环境独占,测试不能与生产并行请求;默认最多累计 10 次分页、20 次详情、40 次总 HTTP 及 5 分钟,任一上限即停止,预算含复核及失败请求。详细边界与用途隔离以[生产首采与测试请求边界](领星一件代发数据统计一期方案.md#生产首采与测试请求边界)为准。下文此前一个月样本、全库存扫描及重读均是历史联调证据,不是现在要求测试环境重复执行的步骤;本轮未发起新请求。
|
||||
|
||||
**时间口径已确认:2026-10-12 用户说明领星返回时间已转换为北京时间。** 本期两个仓库均按 `Asia/Shanghai` 解析出库时间和统计日期,直接使用有效返回日期;查询 `startTime/endTime` 同样按北京时间传参。不要再按洛杉矶、纽约或仓库资料中的 `timeZone` 二次转换。08:00/20:00 出库同步、建议的每日 08:00 库存同步及五种图表自然周期均采用北京时间;分仓任务、覆盖与时效继续独立。
|
||||
|
||||
原始时间字符串保持不变,业务日期直接取其日期;内部 UTC 字段按既有存储规范标准化,不使用 UTC 日期替代业务日。认证包络的 Unix 秒级 `timestamp` 仍按当前时间点生成,不能因业务时间为北京时间而手动加减 8 小时。完整实现与验收见一期方案的[同步时间和统计日期](领星一件代发数据统计一期方案.md#同步时间和统计日期)。
|
||||
|
||||
## 接口和当前实现
|
||||
|
||||
| 用途 | 方法与路径 | 返回主体 | 本地 Java 当前能力 |
|
||||
| --- | --- | --- | --- |
|
||||
| 发现正常仓库 | `POST /openapi/v2/warehouse/page` | `data.records[]` | 已有内部仓库目录接口源码;外部接口已直接 HTTP 联调 |
|
||||
| 一件代发已出库单目录 | `POST /openapi/v2/order/delivery/page` | `data.records[]` | 已有只读内部分页摘要接口 |
|
||||
| 一件代发单的实际 SKU 明细 | `POST /openapi/v2/order/delivery/detail` | `data` | 已有内部详情接口及 SKU 数量 DTO 源码;外部接口已直接 HTTP 联调 |
|
||||
| 产品库存 | `POST /openapi/v2/stock/stockSku/page` | `data.records[]` | 已有内部产品库存接口源码;外部接口已直接 HTTP 联调 |
|
||||
|
||||
当前 Java 已有五个内部 POST 入口,共用 `/internal/integrations/lingxing/wms` 前缀并要求内部服务令牌:`/warehouses/query`、`/outbound-orders/query`、`/outbound-orders/locate`、`/outbound-orders/detail`、`/product-inventory/query`。出库发现接口返回单据摘要,实际 SKU 数量须通过详情接口获取;不能把摘要当作完整明细。接口职责和字段见[一期方案的接口约定](领星一件代发数据统计一期方案.md#平台查询接口和权限建议)。本轮只核对源码,不把外部直接 HTTP 联调成功推定为这五个 Java 入口已全部运行验收。[本地启动说明](../../baiyue-firstleg/integration-service/README.md)
|
||||
|
||||
## 认证和请求格式
|
||||
|
||||
基础地址为 `https://api.xlwms.com`;所有请求使用 HTTPS POST,`Content-Type: application/json; charset=UTF-8`,响应按 JSON 解析。认证参数放在请求体中,不需要 OAuth 获取 Token 的前置调用。
|
||||
|
||||
| 包络字段 | 类型 | 约束 |
|
||||
| --- | --- | --- |
|
||||
| `appKey` | string | 自研系统的 App Key,官方长度 32 |
|
||||
| `timestamp` | string | 当前 Unix 秒时间戳,官方为 10 位数字;不是毫秒 |
|
||||
| `data` | object | 对应接口的业务参数 |
|
||||
| `sign` | string | HMAC-SHA256 小写十六进制,64 位 |
|
||||
|
||||
领星凭据按用户在开发总控对话中的确认配置为 `LINGXING_OMS_APP_KEY` 和 `LINGXING_OMS_APP_SECRET`,应用、示例及 Compose 已采用这两个名称;产品仍为 WMS OMP,真实出口开关仍为 `LINGXING_WMS_ENABLED`。真实值仅通过私有环境配置/Jenkins 凭据注入,不复制到文档。本地私有配置由 Git 忽略;Spring 不会自动加载 `.env.local`,运行前按上述 README 核对变量名和加载方式,不输出凭据值。内部服务令牌是本平台自身的调用保护,与领星凭据分开。
|
||||
|
||||
```json
|
||||
{
|
||||
"appKey": "<运行时注入>",
|
||||
"data": {"current": 1, "size": 2, "whCode": "WH-DEMO", "isHideInventory": 0},
|
||||
"timestamp": "<当前秒时间戳>",
|
||||
"sign": "<本次计算的签名>"
|
||||
}
|
||||
```
|
||||
|
||||
以上占位符不是可直接发送的凭据。先确定业务参数与路径,再为每次请求重新生成时间戳和签名,不能把分页接口的签名复用于详情或库存。[官方加签算法](https://apidoc-omp.xlwms.com/docs/%E5%BC%80%E5%8F%91%E9%AA%8C%E7%AD%BE%E5%B7%A5%E5%85%B7.md)的当前参数拼接为:
|
||||
|
||||
```text
|
||||
待签名串 = appSecret + path
|
||||
+ "appKey" + appKey
|
||||
+ "data" + data的Map/List字符串表示
|
||||
+ "timestamp" + timestamp
|
||||
+ appSecret
|
||||
sign = hexLower(HMAC_SHA256(key=appSecret, message=待签名串, UTF-8))
|
||||
|
||||
库存例子的 data 表示:{current=1, size=2, whCode=WH-DEMO, isHideInventory=0}
|
||||
不是 JSON:{"current":1,"size":2,"whCode":"WH-DEMO","isHideInventory":0}
|
||||
```
|
||||
|
||||
保留业务对象的插入顺序,使用同一数据对象参与签名和实际发送;对象以 `k=v`、逗号加空格连接,数组也按 Map/List 规则递归表示。`path` 包括 `/openapi/v2/...`,不包括域名和查询串。Java 已有 `LingxingWmsSigner`,后续优先复用它,避免新增第二份签名实现:
|
||||
|
||||
```java
|
||||
Map<String, Object> data = new LinkedHashMap<>();
|
||||
data.put("current", 1);
|
||||
data.put("size", 2);
|
||||
data.put("whCode", warehouseCode); // 来自已配置仓库,不能用文档占位值
|
||||
data.put("isHideInventory", 0);
|
||||
var signed = signer.sign(appKey, appSecret,
|
||||
"/openapi/v2/stock/stockSku/page", data, Instant.now());
|
||||
// POST signed.body();不可打印请求体、签名、密钥或原始响应。
|
||||
```
|
||||
|
||||
客户端使用超时、HTTPS、禁止重定向及受控并发;认证错误不能盲目重试。现有本地适配器请求间隔为 1 秒,这只是保护配置,不表示领星承诺 1 QPS。正式初始化前确认账号配额和详情调用量,使用统一账号级限流。
|
||||
|
||||
## 一件代发出库分页
|
||||
|
||||
[官方 WMS 分页说明](https://apidoc-omp.xlwms.com/reference/post_openapi-v2-order-delivery-page-1.md)明确对应管理端的一件代发出库单列表。
|
||||
|
||||
一期使用的 `data` 参数如下;首采固定起止时刻,后续翻页不能移动窗口:
|
||||
|
||||
| 参数 | 类型 | 本期值与说明 |
|
||||
| --- | --- | --- |
|
||||
| `current` | integer | 从 1 开始 |
|
||||
| `size` | integer | 官方默认 10、最大 1000;联调先 1 |
|
||||
| `timeType` | string | 固定 `outboundTime`;不用创建时间代替出库时间 |
|
||||
| `startTime`、`endTime` | string | `yyyy-MM-dd HH:mm:ss`,按已确认的北京时间口径传入,与返回的出库时间保持一致。2026-10-12 已出库单样本观察到起点、终点均包含,见后文边界验证;不能外推为全部仓库/时间类型的保证 |
|
||||
| `status` | integer | `100` 已出库;`99` 已取消。已知单的修订复查走详情,不只查状态 100 |
|
||||
| `customerCodes` | string | 官方类型为字符串、描述为客户编码;不是已确认的数组,多货主拼接方式未验证。本期账号全集省略该参数;与库存单数 `customerCode` 名称不同 |
|
||||
| `deliveryNo` | string | 官方描述“发货单单号”;已验证正常单和取消单省略时间/状态可定位,本期默认新单发现不传。仍须校验单号完全一致与货主身份,不能假定所有输入均精确匹配 |
|
||||
|
||||
公开分页入参没有 `whCode` 或 `whCodeList`。因此出库目录按账号共享发现,再用返回的 `whCode` 路由至每仓独立任务和统计范围;不得发送未声明字段并假定已经按仓过滤,也不为每个仓重复抓取全账号目录。详情可使用仓库标识,已知单的复查按所属仓执行;跨仓修订必须同时处理旧、新仓贡献。
|
||||
|
||||
```json
|
||||
{
|
||||
"current": 1,
|
||||
"size": 1,
|
||||
"timeType": "outboundTime",
|
||||
"startTime": "2026-09-12 08:00:00",
|
||||
"endTime": "2026-10-12 08:00:00",
|
||||
"status": 100
|
||||
}
|
||||
```
|
||||
|
||||
正式任务按已确认账号全集读取,不传 `customerCodes`。用户已确认当前可见全部 70 个货主、2 个仓库均为自营统计范围,货主数量不作为硬编码上限。若后续加入货主子集筛选,应先实测该字符串参数,不能依据复数名称自行发送 JSON 数组。
|
||||
|
||||
目录保留 `deliveryNo`、`sourceNo`、`customerCode`、`whCode`、`status`、`createTime`、`outboundTime`。`productList[].qty` 不直接作为正式实际出库量;本期明细统一来自详情。
|
||||
|
||||
## 一件代发出库详情
|
||||
|
||||
[官方详情说明](https://apidoc-omp.xlwms.com/reference/post_openapi-v2-order-delivery-detail-1.md)的业务参数仅有以下三个字符串。Schema 未声明 `required`,但本平台合同要求三个值齐全,全部来自同一条已验证分页记录:
|
||||
|
||||
```json
|
||||
{
|
||||
"whCode": "WH-DEMO",
|
||||
"customerCode": "CUSTOMER-DEMO",
|
||||
"deliveryNo": "DO-DEMO-001"
|
||||
}
|
||||
```
|
||||
|
||||
不要用来源单号 `sourceNo` 代替出库单号 `deliveryNo`,也不要从单号格式推断货主或仓库。
|
||||
|
||||
| 响应路径 | 含义与处理 |
|
||||
| --- | --- |
|
||||
| `data.deliveryNo/customerCode/whCode` | 必须与查询主体相符;同单仓库变更进入修订核对 |
|
||||
| `data.status` | 当前状态;以当前事实决定是否计入 |
|
||||
| `data.orderCreateTime` | 详情的创建时间字段名;分页中对应 `createTime`,不能照搬 DTO 名称 |
|
||||
| `data.outboundTime` | 实际出库时间,已由领星转换为北京时间;保留源字符串,按 `Asia/Shanghai` 解析并直接使用其业务日期,不再转美国时间 |
|
||||
| `data.skuVOList[].productSku` | SKU;货主和仓库从详情主体继承 |
|
||||
| `data.skuVOList[].actualDeliveryQty` | 实际出库量;官方 integer,实测为 JSON number;Java 使用 BigDecimal 统一保留精度 |
|
||||
| `data.skuVOList[].deliveryQty` | 预报出库量,只作对照,不用于销量替代 |
|
||||
| `data.packageList[].skuList[]` | 包裹维度重复明细,不与 `skuVOList` 累加;其 `actualDeliveryQty` 官方类型是 string |
|
||||
|
||||
同单同 SKU 多行先归并。完整详情缺失、数量无法解析或身份不符时,不能把该单视为零销量后推进完整水位。原始响应可能含面单链接、物流信息等,日志和持久化只能保留本期白名单字段。
|
||||
|
||||
### 列表数量与实际数量对照的证据缺口
|
||||
|
||||
2026-10-13 按用户要求只读检查 TEST 已保存数据,目标是寻找预报量与实际量不同的一件代发出库单。检查在只读事务中执行,单条 SELECT 限时5秒;本次没有向领星发起请求,没有修改采集任务或统计数据。
|
||||
|
||||
- 当前查得12,823条有效出库暂存、12,740个不同订单业务键;预报量字段检查命中0。核对最新完整载荷及代码,商品行仅保留 `skuCode,productName,quantityUnit,actualQuantity`。Integration 的详情 DTO 虽有 `deliveryQty`,Lastleg 转为统计载荷时未保留它,订单事实也不保存预报量。
|
||||
- 同时查询已出库状态100、商品实际量为0的候选,结果为空;不能据此推断所有订单预报量等于实际量。
|
||||
- Integration 列表映射只保留订单头,不返回 `productList[].qty`。所以当前库不能直接筛选预报/实出差异,现有内部列表接口也不能完成三值对照。当前检索结果是“缺比较字段”,不是“已证明一致”。
|
||||
|
||||
下一步最小验证应优先附着正常采集已经收到的响应,采集少量白名单对照证据:同一账号、仓库、货主、出库单、SKU 的列表 `qty`、详情 `deliveryQty`、详情 `actualDeliveryQty`,订单状态/出库时间及列表、详情观测时间。按同 SKU 汇总后比较,同时核对 SKU 集合完整性。最多保留100个完整配对订单或首次出现差异即停止;不额外创建历史采集,不输出面单、收件信息、签名或凭据。该诊断需要开发总控协调列表字段与预报量的有限保留,当前尚未实施。
|
||||
|
||||
命中预报量不等于实际量时,优先使用同次配对的列表证据;若列表/详情时点相差或订单被修订,则仅针对该订单在现有账号预算和统一出口内最多补一次列表与一次详情核验,限流即停止。已保存匹配证据不重新请求。
|
||||
|
||||
验收判定:列表量等于预报且不等于实际量,可否定“列表直接替代实际量”;列表量等于实际量且不等于预报,只证明该差异样本支持替代方向,还需确认 SKU 完整性、修订与取消边界;三值相同不能区分语义。未取得差异样本时明确保留未验证,不停用详情链路。
|
||||
|
||||
### 数量对照验证的采集保护与开发交接
|
||||
|
||||
2026-10-13 用户指定已有对话 [开启新对话](codex://threads/01a135d0-f5c7-7422-892f-037b0c9ea00e) 实施本次有界验证,要求不影响采集。仅接管数量对照与所需只读状态判断,不恢复其他对话已暂停的开发、服务或采集。业务销量继续以详情实际量为准;验证通过前不切换统计来源。
|
||||
|
||||
开发先核对当前代码、运行版本及改动归属。只读状态使用实际生效配置、账号预算/冷却/暂停原因、未完成请求许可、任务/执行尝试/租约和真实进度观测时间联合判断,不凭聊天状态、“无活动任务”、页面等待文案或心跳正常推断可发请求。前后两次轻量只读观测可识别正常推进与证据变化,不轮询原始订单或 SKU 明细。
|
||||
|
||||
| 状态证据 | 对照行为 |
|
||||
| --- | --- |
|
||||
| 正常采集运行,有有效租约/在途请求或成功数量推进 | 只附着正在发生的正常响应保留白名单字段;不发独立扫描或插队详情,不调整并发 |
|
||||
| 等待间隔/自动冷却/预算耗尽/授权失效 | 按实际原因展示等待或不可验证;不缩短间隔、清零预算、延长期限或自动重试探测 |
|
||||
| 人工暂停、模式OFF、复核暂停、服务正在切换 | 保留暂停;允许准备代码和离线对照,运行取样等后续启用,不为验证开启采集或重启服务 |
|
||||
| 证据缺失/前后冲突/许可结果未知/版本不一致 | 返回“状态待确认”和缺失证据,禁止主动核验;不把未知解释为安全空闲 |
|
||||
| 已确认空闲且无在途/遗留未结许可,账号预算及授权均有效 | 如确需补验,只通过现有持久账号预算和统一出口领取一次性许可,最多一单的列表+详情共2次;空闲检查不能代替发请求时的原子许可校验 |
|
||||
|
||||
旁路取样必须默认关闭,使用一次有上限的验证会话。会话冻结范围、开始/截止时间、最多100个完整配对订单、接收记录及字节上限;建议最长30分钟,到期或首次预报/实出差异即结束本次捕获,没有差异也按“未命中”结束。不能每次轮询、翻页、重试或重启重置额度。字段来自同一次来源采集代次,配对键至少包含账号/仓库/货主/单号/SKU与观测证据;同单同SKU多行以十进制数量汇总,缺值保留未知,不能按总件数相等掩盖SKU替换或缺行。
|
||||
|
||||
诊断字段与业务事实分离,不改变业务内容摘要、修订号、任务就绪条件、归并、发布或现有返回状态。捕获失败、配对超时、存储满时停止诊断并记录脱敏原因,不能让正常采集失败,也不能无限缓存或同步写大量日志。不得保存原始全响应、面单、地址或凭据;三值与必要业务身份仅留在受控诊断存储,文档和报告使用样本别名。
|
||||
|
||||
最小代码范围是 Integration 列表/详情响应映射旁的白名单观察、独立有界配对组件及直接测试。优先在 Integration 层完成三值观察,避免为了找样本修改 Lastleg 业务事实表;如必须新增字段传递或内部诊断合同,先声明精确 DTO/调用方/OpenAPI 影响,再由唯一写者同步。不改 Egress 的预算、许可、限流逻辑或已经冻结的持续采集候选,不新增公开绕过出口的接口。开发可以在当前工作区完成,发布需另按当前授权协调;不能把“新增代码不影响运行”扩大成“重启后无损”。
|
||||
|
||||
交付须分别给出:采集状态证据和是否具备取样条件;三值对照的有界实现与离线测试;真实差异样本是否命中;额外供应商请求数;是否可以替代及尚未覆盖的边界。至少测试预报10/实际8且列表分别为10和8、SKU集合不一致、重复行、部分字段缺失、跨代次拒配、取消单、会话到期/上限、诊断失败不影响业务返回、暂停/429/许可未知不发请求。没有真实差异样本时只能交付验证能力,不能宣称字段语义已证实。
|
||||
|
||||
已实测当前取消单可查详情,且正常单、取消单均可按单号重新定位;实际改仓后的旧三标识行为尚无样本。若旧仓三标识无法取得详情,使用出库分页的按单重新定位方式,以下为合成业务参数:
|
||||
|
||||
```json
|
||||
{"current": 1, "size": 10, "deliveryNo": "DO-DEMO-001"}
|
||||
```
|
||||
|
||||
官方业务 Schema 没有将时间参数和 `status` 列为必填。2026-10-12 的正常、取消两个样本均省略这些字段,分别返回唯一同货主、同单号记录;样本未受到默认已出库过滤。必须读完返回页、逐条校验单号完全一致及货主身份,再取当前仓库查详情;不能只按模糊单号命中就迁移事实。无结果、权限失败、多个身份冲突均进入待核对,不认定取消、不清零。
|
||||
|
||||
当前 Java 已有独立的 `/outbound-orders/locate` 入口和按单定位请求 DTO,不传时间/状态条件;默认摘要发现接口仍用于状态 100 的新单发现,不能用它替代取消定位。新单发现和已知单修订复核使用不同查询意图,仍共用账号限流和签名器。该源码能力仍须完成内部 HTTP 和编排验收。当前取消样本的详情仍有实际数量 `1`,但 `outboundTime` 为空;必须先按状态和有效出库时间判定,不因数量大于零计入销量,也不能据此证明该单过去已经出库。
|
||||
|
||||
## 仓库发现和分仓配置
|
||||
|
||||
用户已确认按仓库分别采集和管理时效。先调用 [正常仓库列表](https://apidoc-omp.xlwms.com/reference/post_openapi-v2-warehouse-page-1.md):
|
||||
|
||||
```json
|
||||
{"current": 1, "size": 1000}
|
||||
```
|
||||
|
||||
请求路径为 `/openapi/v2/warehouse/page`,业务入参 `current` 默认 1、`size` 默认 10、最大 1000。可按 `whCode`、`whNameCn`、`countryCode` 筛选,但一期发现当前全部正常仓库时不传过滤。接口没有 `status` 请求参数,也不要因为业务是“自营”就添加 `warehouseType=0`,自营商品可能存放在代理仓。
|
||||
|
||||
响应分页字段是 **`data.page/pageSize/pages/total`**,不是产品库存的 `current/size`;2026-10-12 已实测这一差异。每行保留 `whCode`、`whNameCn`、`warehouseType`、`status`、`timeZone`;不用仓库地址、联系人或联系方式。`warehouseType` 为 0 自营仓、1 代理仓;`status` 为 0 正常、1 停用、2 冻结,但该接口只返回正常仓库,缺失仓不能解释为“库存归零”。
|
||||
|
||||
仓库编号是任务、快照、时效与未来预警规则的必需维度。每仓保存来源时区、报表时区、出库计划、库存计划及过期阈值;本期两个时区字段均已确认填写 `Asia/Shanghai`,每天北京时间 08:00/20:00 出库、建议每天北京时间 08:00 库存。返回的 `timeZone` 只是仓库所在地资料,不覆盖领星已转换好的北京时间。某仓失败不阻止另一仓发布完整库存,不能用成功仓的采集时间刷新失败仓。
|
||||
|
||||
## 产品库存分页
|
||||
|
||||
[官方产品库存说明](https://apidoc-omp.xlwms.com/reference/post_openapi-v2-stock-stocksku-page-1.md)与管理端「产品库存-库存信息」口径一致。库存接口没有日期筛选,也不使用出库的最近两个月窗口。
|
||||
|
||||
正式任务必须按仓发送 `whCode`,以下是单仓全量产品库存 `data` 模板:
|
||||
|
||||
```json
|
||||
{
|
||||
"current": 1,
|
||||
"size": 1000,
|
||||
"whCode": "WH-DEMO",
|
||||
"isHideInventory": 0
|
||||
}
|
||||
```
|
||||
|
||||
对每个已确认仓库独立从第 1 页读完,每页只增加 `current`,同仓其他参数保持一致。**不传 `productQuality`,采集正品和次品;不设置 SKU、数量、预警或品类过滤。** 该仓全部货主均纳入,正常全量不传 `customerCode`;它只用于定向核验。每仓独立记录执行状态、覆盖范围、采集起止和发布版本,统计只使用正品 `productQuality=0` 的可用库存。
|
||||
|
||||
| 参数 | 类型 | 官方规则与使用方式 |
|
||||
| --- | --- | --- |
|
||||
| `current`、`size` | integer | 默认 1、10;每页最大 1000 |
|
||||
| `customerCode`、`whCode` | string | 官方均未标必填,实测可省略;本平台分仓采集要求 `whCode` 必填,`customerCode` 可省略读取该仓全部货主 |
|
||||
| `whCodeList` | string[] | 仓库列表,最多 500;不要同时混用单仓与多仓参数,优先关系未核验 |
|
||||
| `productQuality` | integer | `0` 正品、`1` 次品;全量不传,专题查询可传 |
|
||||
| `isHideInventory` | integer | `0` 保留零库存,`1` 隐藏;正式全量必须为 0 |
|
||||
| `barcode`、`barcodeAccurate`、`barcodeList` | string、string、string[] | 模糊/精确检索;列表最多 500。官方名称 Barcode 与列表说明“SKU”不一致,未经单 SKU 实测不得用于生产过滤;全量不传 |
|
||||
| `productName`、`categoryIdList` | string、string[] | 商品名、品类过滤;品类最多 500;全量不传 |
|
||||
| `stockValueType`、`startValue`、`endValue` | string | 数量过滤;类型为 `stkQty/freezeQty/useStkQty`,边界开闭未说明;全量不传 |
|
||||
| `sortName`、`sortOrder` | string | 数量排序,方向 `asc/desc`;无稳定快照或唯一排序保证,不能靠排序解决翻页期间变动 |
|
||||
| `stockStatus` | integer | `0` 无预警、`1` 预警;全量不传 |
|
||||
|
||||
返回是 `data.records[]`,分页元数据是 `data.current/size/total/pages`。主体字段都在每条记录的第一层:
|
||||
|
||||
| 字段 | 类型与映射 |
|
||||
| --- | --- |
|
||||
| `customerCode`、`whCode`、`productSku` | string;与来源账号、品质一起构成候选业务键 |
|
||||
| `productName` | string;展示信息,不作为唯一键 |
|
||||
| `productQuality` | integer;分别保存正品、次品 |
|
||||
| `stkQty` | number;实物库存 |
|
||||
| `freezeQty` | number;冻结库存 |
|
||||
| `useStkQty` | number;可用库存,正品该值用作可售量,不再次扣冻结 |
|
||||
| `transitQty` | number;在途,单独保存,不计入当前可售量 |
|
||||
| `innerBatchNo`、`outBatchNo` | string;批次线索,空字符串保留为空;不能未经核验据其拆分库存粒度 |
|
||||
| `uniqueKey4tenant` | string;只作来源核对,不拆解它替代明确维度 |
|
||||
| `stockCompare` | object;代理仓对比信息,不与本行数量相加;其中 `refreshTime` 不是主体库存采集时间 |
|
||||
|
||||
数量使用 BigDecimal/数据库 DECIMAL;不能强转 int、截断小数或将 `""`、null、缺字段自动转换为 0。官方统一空值规则可能把数值 null 输出成空串或 0,API 数值 0 仅能证明“接口报告零”,首次正式验收仍须与领星页面核对。接口缺行不证明库存为零。
|
||||
|
||||
## 后续库龄数据入口
|
||||
|
||||
[官方批次库存分页](https://apidoc-omp.xlwms.com/reference/post_openapi-v2-stock-batch-page-1.md)公开 `POST /openapi/v2/stock/batch/page`,对应 SKU 批次库存,不是整箱库存。可作为后续真实库龄核验入口,已核对的公开字段如下:
|
||||
|
||||
| 字段 | 官方含义与类型 |
|
||||
| --- | --- |
|
||||
| `stockAge` | integer,库龄天数 |
|
||||
| `putawayDate` | string,上架日期 |
|
||||
| `stkQty` | number,在库数量 |
|
||||
| `customerCode`、`whCode`、`productSku`、`productQuality` | 货主、仓库、SKU 与品质;前三者为 string,品质为 integer |
|
||||
| `sysBatchNo`、`batchNo`、`innerBatchNo`、`outBatchNo`、`relateOrderNo` | string,系统批次、上架批次、内部/外部批次及关联入库单号 |
|
||||
|
||||
该接口尚未实测账号权限、字段非空覆盖和分页完整性;还需确认库龄起算、移仓/退货是否重置、不同视图及库位是否重复汇总,并按同一货主、仓库、SKU、品质与产品库存对账。现有产品库存样本的批次字段为空,不能代替此接口验证,也不能用首次同步日补造真实库龄。领星 `stockAgeStatus` 的规则尚未核准,不直接作为本平台的滞销判断或评级。
|
||||
|
||||
本节仅登记后续待核验能力,不是本轮一期必交代码,不默认接入生产;一期仍使用现有出库与产品库存链路,本次不新增真实请求。后续核验沿用账号独占、同一会话共享请求预算及遇限流即停规则,不另开预算或自动全量补采。用途仍为自营业务内部评估与仓储成本分摊,不用于对外客户收费。
|
||||
|
||||
## 成功、失败和契约差异
|
||||
|
||||
2026-10-12 出库分页、详情和产品库存已观察到成功包络为数值 `code=200`、`data` 和 `msg`,没有 `success`,与官方 BaseResponse 的 required 声明不同。解析规则为:
|
||||
|
||||
1. HTTP 200 只是传输成功;仍检查 JSON `code` 为数值 200。
|
||||
2. `success` 缺失时继续校验数据结构;存在时必须是布尔 true,false、null 或字符串均拒绝。
|
||||
3. 分页必须有有效 `records` 数组和可核验分页元数据;详情必须是对象并核验主体身份与 SKU 明细。当前 Java `mappedPage` 已要求 `total/current/size/pages` 并校验页数和本页行数;完整批次仍须由 Lastleg 跨页检查唯一业务键、页间总数变化及应有页数,不能由单页适配成功推定全量成功。
|
||||
4. 官方认证错误可使用字符串错误码;保留数值错误码和固定错误分类,原始 `msg` 不直接输出日志或用户界面。认证失败不当作空页。
|
||||
5. 测试验证遇 HTTP 429/明确限流码立即停止整轮会话,不自动重试;正式任务交回账号协调器统一冷却后有限退避,不由各接口独立重试。超时等失败也消耗原预算;权限与验签错误停止盲目重试。没有验证的配额与历史限制保留为待确认项。
|
||||
|
||||
**出库分页空结果的已验证例外**:请求 `current=1,size=100`、时间窗口明确不包含目标单时,成功响应为 `records=[]、total=0、pages=0、current=1、size=10`。它把空页条数恢复为默认 10。可仅在这组完整空结果条件同时成立、且本次请求为第一页时归一化内部 `size` 为请求值,保留源分页元数据作为诊断;不能因此判失败。非空页、总数缺失、后续页异常或其他结构错误仍严格拒绝;未经验证不能把例外推广到库存或仓库接口。首次探针因严格回显检查中止,针对空结果核验后完成后续测试,这不是供应商业务请求失败。
|
||||
|
||||
成功响应示例为合成数据,展示的不是实际业务记录:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "操作成功",
|
||||
"data": {
|
||||
"current": 1, "size": 1000, "total": 1, "pages": 1,
|
||||
"records": [{
|
||||
"customerCode": "CUSTOMER-DEMO", "whCode": "WH-DEMO",
|
||||
"productSku": "SKU-DEMO", "productQuality": 0,
|
||||
"stkQty": 120.0, "freezeQty": 20.0,
|
||||
"useStkQty": 100.0, "transitQty": 30.0
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
这里的 `total` 是供应商 JSON number;经过现有平台 Long 序列化后,本地内部 API 的 `total` 为字符串,这是平台响应格式,不能据此要求供应商返回字符串。
|
||||
|
||||
## 联调证据与复现验收
|
||||
|
||||
截至 2026-10-12,出库分页通过本地 Java 服务验证;详情、仓库发现和库存使用同一组凭据及 OMP 签名直接执行只读 HTTPS 请求。临时探针与脱敏报告放在被 Git 忽略的 `integration-service/target/lingxing-local/`,只保留字段类型、数量、分页计数和核验结论,不保存密钥、签名或完整原始响应。这些临时文件可被构建清理,开发依据以本手册记录为准。
|
||||
|
||||
| 项目 | 已验证内容 | 不能由此推定 |
|
||||
| --- | --- | --- |
|
||||
| 一件代发分页 | 本地 Java 已取得一条状态 100 的摘要;使用出库时间最近一个月窗口 | 整月已完成采集、时间区间完整 |
|
||||
| 一件代发详情 | 对同一单传齐仓库、货主、出库单号,HTTP 200、业务码 200;`skuVOList` 返回一行,实出和预报数量均为数值 1 | 所有单都单 SKU、预报永远等于实出;北京时间口径来自后续用户确认,不由 HTTP 成功推定 |
|
||||
| 产品库存样本 | 不传货主、仓库、品质,`current=1,size=2,isHideInventory=0` 返回两行;四种数量是 JSON number,零库存能返回 | 所有空值语义、同一时刻快照;自营范围由用户另外确认 |
|
||||
| 产品库存两轮全集核验 | 北京时间 15:30:32—15:32:24,每轮 7 页、6,635 条;两轮业务键与四种数量一致 | 永久稳定排序、跨页原子快照、已持久化业务库存 |
|
||||
| 正常仓库发现 | 返回 2 个仓库;分页元数据为 `page/pageSize`,仓库资料有 `timeZone` | 接口时间必定使用仓库时区、未来停用仓可直接清零 |
|
||||
| 定向库存筛选 | 用样本货主+仓库查询,返回记录均属于所请求的货主与仓库 | 同仓全量只需该货主,或其他货主不属于自营 |
|
||||
| 按仓全分页 | 分别带两个实际 `whCode` 查询,每页 1000,合计 7 页、6,635 条;每行都属于所请求仓库,分别通过总数与业务键核验 | 跨仓为同一原子时刻、时区已完成业务对账 |
|
||||
|
||||
全集核验的 6,635 是“货主+仓库+SKU+品质”库存记录数,不是商品件数,也不等于去重后的 SKU 数。两轮均为正品 6,293 行、次品 342 行;实物为零 3,278 行、实物大于零 3,357 行。未观察到重复业务键、缺失主体身份、四种数量类型异常或负数;样本全集的批次字段均为空,`stockCompare` 均为空对象,因此非空批次和代理仓对比仍待专项样本。用户随后确认全部 70 个货主、2 个仓库纳入自营,并要求正式采集按仓执行。
|
||||
|
||||
2026-10-12 北京时间 15:43:18—15:44:09 的按仓结果如下。仓库 A/B 是文档脱敏别名,不可作为请求中的 `whCode`;实际编码必须从仓库目录或受控配置读取。
|
||||
|
||||
| 仓库 | 仓库资料时区 | 页数 | 库存记录 | 正品/次品记录 | 零实物记录 | 涉及货主 |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| A | `America/New_York` | 1 | 894 | 892/2 | 280 | 15 |
|
||||
| B | `America/Los_Angeles` | 6 | 5,741 | 5,401/340 | 2,998 | 69 |
|
||||
|
||||
表中美国时区为接口实际返回的仓库资料,保留原值作为证据;两仓的出库返回时间和本期统计口径仍统一为用户确认的北京时间,不按这两个资料值分别转换。
|
||||
|
||||
两仓合计与先前账号全集相符;货主可跨仓出现,15+69 不能作为去重货主数。首次分仓尝试遇到临时网络错误,未视为成功;随后重跑完整分仓读取成功。正式同步必须同样区分失败尝试和已发布完整批次。以上核验只读入内存并保存脱敏统计,没有导入业务表,也没有新增 Java 库存 API。
|
||||
|
||||
### 2026-10-12 追加前置验证
|
||||
|
||||
用户要求继续验证后,本轮继续直接串行请求 OMP,最小请求起始间隔 1.1 秒,不制造业务变更、不做限流压测。以下 API 验证发生时尚未取得用户的时区确认,也未完成页面对账;用户随后确认领星返回值已是北京时间,当前按本手册开头的 `Asia/Shanghai` 口径执行。该用户确认与下列只读实测证据分别记录。
|
||||
|
||||
| 验证项 | 本次结果 | 保留的限制 |
|
||||
| --- | --- | --- |
|
||||
| 正常单按号定位 | 省略时间与状态,返回唯一同货主、同单号的状态 100 记录;三标识详情一致 | 不保证模糊输入或同号跨货主也唯一,仍须逐条核验 |
|
||||
| 出库不同页大小 | 源字符串窗口 `2026-10-10 01:00:00` 至 `02:00:00`,size=124/125 均 3 页、372 个唯一单据;两轮单号集合及仓库/状态/出库时间摘要相同 | 不是 UTC 区间证明,也不是原子快照或永久稳定分页承诺;没有页面导出对账 |
|
||||
| 秒级边界 | 一个已出库样本:宽窗前后复读均命中;以该时刻为起点、终点均命中;严格前一秒与后一秒窗口均不命中。六次结果均全量、唯一且单号准确 | 仅观察到该样本两端包含;尚未覆盖另一仓、其他时间类型或北京时间午夜边界 |
|
||||
| 空结果分页 | 两个不相交窗口都返回 `records=[]、total=0、pages=0、current=1、size=10`,请求 size=100 | 仅按前述严格条件归一化;不能放宽非空页、库存页或后续页 |
|
||||
| 多 SKU 详情 | 另取 5 条已出库单,分别有 4、4、3、3、2 个 SKU;身份、数量类型与列表出库时间一致,实际量均等于预报量 | 未观察到同 SKU 多行、实出少于预报或部分出库,不把缺少样本标为通过;单位仍需业务核对 |
|
||||
| 当前取消单 | 近月创建时间查询的取消目录报告 163 条;抽查列表的 20 行均状态99,读取其中1条详情也为99,按号无时间/状态定位仍唯一命中 | 该样本实际数量1、出库时间为空,不能证明过去已出库;改仓及“出库后再撤销”仍无前后证据 |
|
||||
| 详情耗时 | 7 次详情耗时约 1.09—2.63 秒,平均约 1.57 秒 | 只是小样本观测,不是配额、容量或首采完成时间承诺 |
|
||||
| 实际限流与退避 | 串行、最小起始间隔1.1秒下,仍观察到1次出库分页 HTTP429;有限退避后的第二次请求为 HTTP200、业务码200 | 未刻意压测;不能由一次429反推准确阈值,也不能将1.1秒间隔视为已确认的安全持续速率 |
|
||||
| A 仓库存分页 | size=298/299 各3页、各894个唯一业务键,集合和四种数量一致 | 仍为采集区间观测 |
|
||||
| B 仓库存反例 | size=999 时6页、5,741个唯一键;随后 size=1000 返回5,741行,但只有5,740个唯一键,发现1个重复键,两轮集合不同 | **该次尝试完整性失败,不能发布。** 原因尚不能区分业务变化与非稳定排序,不删除异常证据 |
|
||||
| B 仓完整重试 | 再从第一页以 size=1000 完整读取两轮,各6页、5,741个唯一键;无重复、集合和四种数量一致 | 证明本次可恢复,不证明供应商分页永久稳定;不是将前后数据拼起来凑齐 |
|
||||
|
||||
出库与详情验证于北京时间 16:25:37—16:26:31 完成;两仓不同页大小核验于 16:27:57—16:29:22 完成;B 仓完整重读于 16:32:40 完成。脱敏报告分别为忽略目录中的 `prerequisites-20261012T082631Z.json`、`prerequisites-20261012T082922Z.json`、`prerequisites-20261012T083240Z.json`;前一次空页严格校验中止记录另保留,不能混记为成功。
|
||||
|
||||
验收必须覆盖两个实际用例:出库合法空页不误报失败;库存总数与返回行数相同、但唯一键少 1 时仍整批拒绝并重试。当前 `LingxingWmsClient` 已包含限定的出库空页例外:请求首分页 `size=100`,来源 `current=1,size=10,total=0,pages=0,records=[]` 时允许通过,其余页大小不匹配仍拒绝。此处仅更新源码事实,未重新运行 Java 或批次验收;既有直接 HTTP 联调证据与当前适配器验证应分别记录。
|
||||
|
||||
公开官方资料专项核对未找到账号 QPS/每日配额、时间戳容许误差、源出库时区、历史保留或最大更正期限的明确值。官方 `requestDeliveryTime` 的北京时间说明不能单独外推给 `outboundTime`;本期出库北京时间口径采用用户的明确确认,不再列为待选时区。供应商仍需补充列表/详情保留期限、已出库后撤销与改仓是否允许及查询方式、账号请求配额,以及稳定分页能力。当前低频调用成功不能代替这些确认。
|
||||
|
||||
后续复验先检查账号独占和整轮预算;不直接开启当前会自动规划正式首采的执行开关:
|
||||
|
||||
1. 先完成离线签名、异常脱敏、预算耗尽及用途隔离测试,确认原采集环境已停止且在途请求排空。在独占验证窗口内只读读取配置、不回显值,用 `size=1` 的出库分页和 `size=2` 的产品库存开始,足够即停。保存业务参数模板、时间、HTTP/业务码、字段类型和已用预算。
|
||||
2. 用分页同一行的三个业务标识查详情,核对实际 SKU 数量和创建/出库时间字段;与领星页面同单对账。禁止把包裹数量重复累加。
|
||||
3. 以已确认的当前账号全部 70 个货主、2 个仓库建立范围版本;按仓库目录取得实际编码,核验带 `whCode` 返回的每行仓库一致。仓库目录或业务范围变化要重新验证覆盖,不将 70/2 固定在代码中。
|
||||
4. 测试只在原会话预算内翻少量页、读取有限详情,并记录 `total/pages`、实际行数、唯一键与停止原因;达到预算或遇到限流即停止,不为凑齐某种样本继续搜索。不完整库存不得发布、补零或触发缺行占位。
|
||||
5. 重复键、缺页、总量变化、断点恢复、事实归并和版本发布先用离线合成数据验证。2026-10-13 用户确认库存按每仓一轮完整分页观测,取消两轮数量完全一致的发布前提;正式受控任务保存每仓真实采集区间和完整性证据。所有页、唯一业务键、总量、范围及数量校验仍须通过,不拼接失败批次,不承诺跨页原子快照。历史两轮核验仅证明当次观测结果,出库目录规则不变。
|
||||
6. 对本次预算内已有的正品、零库存、次品、冻结、在途样本进行相同筛选的页面核对;未取到的场景留待合成用例或正式生产验收,不追加无上限查询。结束验证后关闭该环境真实出口,再交还账号给正式采集。
|
||||
|
||||
来源与统计时区已确认采用北京时间;实现仍需验证北京时间午夜边界与内部 UTC 存储不改变业务日期,订单历史修正期限、稳定分页和实际账号限流仍需供应商或人工对账确认。库存 API 没有历史时点参数,不能用当前查询补造昨日库存。开发可以从适配、暂存及分仓任务开始;正式启用标准统一见[一期方案的开发准入与正式启用门槛](领星一件代发数据统计一期方案.md#开发准入与正式启用门槛),本手册的成功样本不替代这些门槛。
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,278 @@
|
||||
# 领星统计查询性能优化方案
|
||||
|
||||
面向平台销售开发总控,当前先完成功能、真实数据正确性及人工页面确认,并发优化后置。本文维护后续性能专项规划,不触发代码修改、真实采集或压测,不把新增诊断任务变成功能联调的前置条件;页面不可用、请求超时或数据错误仍按功能问题处理。
|
||||
|
||||
性能专项恢复时,按“复用完整基线与诊断 → 验证有证据的新候选 → 全场景验收”推进。窄投影、profile 归并和延后商品名称均已试验,未显示稳定收益,移出默认实施顺序;只有新的执行计划证据表明问题或条件发生实质变化时才考虑重测。每次只验证一项主要改动,保留结果一致性与执行计划证据。
|
||||
|
||||
本文为 2026-10-13 的查询优化执行方案,只交付文档,不修改代码或操作环境。业务口径、版本保护及验收目标继续以[一期主方案](领星一件代发数据统计一期方案.md)和[经营总览图表设计](经营总览图表设计.md)为准;本文不另建部署状态或验收进度台账。开发安排由[平台销售总控](codex://threads/01a12feb-0474-77f1-afe0-a3b491733dca)统一收口。
|
||||
|
||||
用户本轮追加的领星获取速度、重复请求与等待开销只读梳理,统一维护在[采集速度优化顺序](#采集速度优化顺序)。它与前述经营查询 SQL 优化分开,不因本次梳理调整正在运行的采集任务或提高账号出口并发。
|
||||
|
||||
## 对照基线与问题判断
|
||||
|
||||
以[库存索引倒序优化后的完整压测](../../baiyue-firstleg/reports/selfop-test-20261013/selfop-perf-read-r5-inventory-seek-r2-result.json)为本次核对取得的较新基线。该轮于北京时间 2026-10-13 10:29 结束,合成数据共 11,968,200 条 SKU 日行,包含多个版本;不能把这个总量当作单仓单版本行数。10 个并发用户持续约 301 秒,总览和销量各完成 664 次、默认库存完成 663 次,共 1,991 次,无请求错误。
|
||||
|
||||
| 查询路径 | P50 | P95 | P99 | 现行 P95 目标 |
|
||||
| --- | ---: | ---: | ---: | ---: |
|
||||
| 经营总览近 15 天 | 2,732 ms | 3,107 ms | 3,275 ms | ≤1,500 ms,未达标 |
|
||||
| SKU 销量近 15 天 | 1,150 ms | 1,382 ms | 1,489 ms | ≤1,000 ms,未达标 |
|
||||
| 默认库存列表 | 613 ms | 774 ms | 849 ms | ≤1,000 ms,该场景达标 |
|
||||
|
||||
[此前仓库日汇总后的报告](../../baiyue-firstleg/reports/selfop-test-20261013/selfop-perf-read-r5-warehouse-daily-r1-result.json)中,三个路径的 P95 分别为 3,169、1,412、1,092 ms。保留它作为前后对照,不能继续将默认库存写成尚未达到 1 秒,也不能把默认列表通过扩大为所有关注筛选、排序和下钻均已通过。
|
||||
|
||||
常用路径稳定性通过不代表完整性能验收通过。该压测报告仍列有未验证项;后续[分段诊断摘要](../../baiyue-firstleg/reports/selfop-test-20261013/selfop-query-timing-r4-summary.json)补充了 SQL 次数与阶段耗时采样,不能再把这项写成完全未开始。后台候选构建并行、构建增长成本、复杂筛选及原单增长不影响查询等仍需专项证据。旧销量版本的 366 天 SKU 清单在较早报告中有约 7.30/7.39 秒的单次抽样,后续需复核;单次结果不能当作 P95。
|
||||
|
||||
已完成且输入条件一致的基线与诊断直接复用,中途停止的压测不算完整基线。恢复性能专项后,先核对期间功能修复是否改变查询 SQL、索引、数据集、版本和资源条件,再决定是否需要更新基线,不因本文更新原样重跑。以上为固定证据快照,后续实际部署和验收状态仍由现行主契约维护。
|
||||
|
||||
## 保留已有优化
|
||||
|
||||
当前代码已具备以下能力,不再作为待从零实现的任务:
|
||||
|
||||
| 已有能力 | 代码入口 | 本轮处理 |
|
||||
| --- | --- | --- |
|
||||
| 趋势读取已发布仓库日汇总,进入查询前验证就绪证据 | [DashboardReadMapper](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/query/DashboardReadMapper.java)、[DashboardQueryService](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/query/DashboardQueryService.java) | 保留,不再让趋势扫描所有 SKU 日行 |
|
||||
| 一次 report 返回统计和三个 Top 10,共享 SKU 计算结果 | [DashboardReadSql](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/query/DashboardReadSql.java) 的 `report` | 保留共享计算,不拆成每张图独立扫描;窄投影按下文已试验结论处理 |
|
||||
| 默认库存按库存量先选页,再补该页销量;普通 ALL 计数只读候选身份 | [AnalyticsInventorySql](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/query/AnalyticsInventorySql.java) 的 `stockFirst`、`inventoryCount` | 保留轻量路径,不能被复杂筛选的通用方案拖慢 |
|
||||
| 默认库存最后出库日按现有索引倒序取首条 | 同上 `inventoryPage` | 复用上文已完成的并发结果;仅默认 ALL+AVAILABLE_DESC 且无分桶/selection 的路径已采用,复杂筛选不能视作同时完成 |
|
||||
| SKU 销量清单先选分页键,再计算本页完整/部分/未知日数 | [AnalyticsReadSql](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/query/AnalyticsReadSql.java) 的 SUMMARY 分支 | 保留,不重新引入所有 SKU × 所有日期的展开 |
|
||||
| 库存过期或 30 日不完整时,总览跳过相应无用事实聚合 | `AnalyticsInventorySql.dashboardCte` | 保留,不能以资格不足场景的快速结果代替完整场景验收 |
|
||||
|
||||
查询已经有日表覆盖索引,不能仅凭慢就继续叠加相近索引。最多 366 个趋势点、30 条榜单记录的 Java 处理暂不列为优化重点。
|
||||
|
||||
## 复用分段诊断并限定剩余测量
|
||||
|
||||
分段诊断共 39 个请求,包含三个接口各 3 个单用户样本和各 10 个并发样本;它明确标为诊断用途、非 P95 验收。并发组的已观测结果如下,均为平均值:
|
||||
|
||||
| 路径 | 主要 SQL 阶段耗时 | 其他阶段与结论 |
|
||||
| --- | ---: | --- |
|
||||
| 总览 | report 约 3,028 ms | context 约 4 ms、daily 约 2 ms;优先研究全仓 SKU 聚合、分桶及榜单成本 |
|
||||
| SKU 销量 | page 约 1,166 ms | count 约 54 ms、context 约 4 ms;优先研究区间聚合与分页排序 |
|
||||
| 默认库存 | page 约 498 ms | count 约 48 ms、context 约 5 ms;保留已达标路径,后续做回归 |
|
||||
|
||||
三个接口在这组样本中均固定为 6 条统计读 SQL。诊断范围为 `ONLY_ANALYTICS_READ_MAPPERS`,不能将 6 条说成包含 IAM/鉴权等全部应用 SQL,也不能由小样本推断全部场景都不存在额外调用。采样已指出主要 SQL 成本;连接池等待、数据库资源竞争、写入重叠等仍按需要补证据,不再从头重复同一诊断。
|
||||
|
||||
固定同一数据集、代码版本、仓库、双统计版本、业务日期、覆盖证据和库存时效,分别记录以下阶段。跨午夜、库存过期、版本切换或测试数据重建后,需要重建可比基线。
|
||||
|
||||
| 请求 | 需要分开的耗时 |
|
||||
| --- | --- |
|
||||
| 总览 | 权限与 context 校验、仓库 daily、report、DTO 组装、序列化与 HTTP 总耗时 |
|
||||
| SKU 销量 | context、候选 count、分页及日量聚合、DTO/HTTP |
|
||||
| 库存 | context 与下钻资格、count、分页与最后出库日、DTO/HTTP |
|
||||
|
||||
每个代表 SQL 保存绑定参数范围、执行计划、实际行数/循环数/耗时、排序和临时表证据。对比 profile、snapshot、daily 各访问节点,确认共享 CTE 是否确实只构建一次。同一请求关联各阶段耗时,不能用两个阶段各自的 P95 相减估算成本。数据库总耗时还应与连接池等待、CPU、磁盘及同机负载对照,不能把 HTTP 与数据库耗时之差全部归给 Java 计算。
|
||||
|
||||
只采集当前测试需要的只读诊断;`EXPLAIN ANALYZE` 会真正执行查询,沿总控既有环境窗口安排,不和另一轮压测或构建竞争。诊断参数采用合成账号和业务编码,不在文档、日志或证据中写凭据及真实客户载荷。
|
||||
|
||||
候选方案先做相同输入的响应对照,再做单请求 SQL 对照;有一致且可解释的收益,才进入整轮 HTTP 压测。首次应用请求、预热和业务结果缓存命中分别标注,不把“首次应用请求”称为数据库磁盘冷启动;不为制造冷启动清理共享数据库缓存。
|
||||
|
||||
## 已试验方案与重试条件
|
||||
|
||||
依据[开发总控 2026-10-13 的后续性能反馈](codex://threads/01a12feb-0474-77f1-afe0-a3b491733dca),以下三项已经测试,均未显示稳定收益。此处记录试验结论与选题边界,不把“尚无稳定收益”扩大成所有数据规模下永久无收益,也不编造提升比例。
|
||||
|
||||
| 方案 | 已有结论 | 默认处理 | 重新验证的前提 |
|
||||
| --- | --- | --- | --- |
|
||||
| 总览共享结果窄投影 | 已试验,未显示稳定收益 | 不再列为首选任务,不重复原样 A/B | 新执行计划显示宽字段确实造成主要临时表/去重成本,且能说明新方案与已测方案的实质差异 |
|
||||
| 两版 profile 归并以减少重复访问 | 已试验,未显示稳定收益 | 不再安排同一归并方案 | 新执行计划显示 profile 访问成为主要成本,并能指出访问路径、规模或归并方法相对既有试验发生的变化 |
|
||||
| 榜单确定后延后读取商品名称 | 后续已试验,未显示稳定收益 | 从待试新候选中移除,不再单独派工 | 新证据表明名称访问或携带名称的中间结果成为主要成本,且处理方式与已测方案存在实质差异 |
|
||||
|
||||
重试前先复用总控保留的代码版本、输入及计划证据,写清旧结论、新证据和本次差异。重新发布文档、换一个试验名称或重新出现同一静态代码建议,都不构成重试理由;已有试验详细证据需要核对时先核对记录,不直接重跑。
|
||||
|
||||
若满足上述前提,正确性边界仍保留:窄投影不能删除身份、分类、资格或排序所需字段,观察证据即使不展示也须参与上游计算;profile 归并须保留来源存在标记,区分“无该版记录”和“该版字段无效”,不能因 MAX/MIN 忽略空值而将未知改成有效。单位资格、编码比较、名称优先级及有效观察依据均不变,库存过期也不意味着其 profile 身份可删除。
|
||||
|
||||
## 后续集中处理两条主要慢查询
|
||||
|
||||
### 总览聚合与销量分页
|
||||
|
||||
总览以 report、销量以 page 为下一阶段的主要优化对象。对照已有计划核实日行扫描、聚合、排序及物化的实际工作量,先说明新方案具体减少哪一部分,而不是继续围绕已无收益的字段/名称调整。默认库存保留回归覆盖,不继续作为主要提速目标。
|
||||
|
||||
总览固定 30 日的重复计算与销量清单任意日期区间是两种需求,不能用只覆盖固定 30 日的结果替代今日、近 3 天、本周、近 15 天、本月及历史自定义区间。若要评估把重复计算移到版本构建阶段,按后文条件分支测算读取收益和构建成本,另行形成具体设计,不直接追加统计表。
|
||||
|
||||
连接池或线程数只有在等待和资源证据支持时才评估,不以增加请求并行度代替减少数据库工作量。每项候选均保留固定版本、全候选资格、未知值及排序语义,不提前裁掉 SKU 获得表面速度。
|
||||
|
||||
### 按实际成本审视物化方式
|
||||
|
||||
`DashboardReadSql.report` 的 DISTINCT 有阻止四个消费者重复展开计算的用途,不能直接删除。如果新的分段与执行计划证据显示共享结果的去重仍是主要成本,再核对既有试验,决定是否有值得验证的物化替代方案;不把 `NO_MERGE` 等提示自动当作尚未尝试的新方向,也不要求先重做窄投影。
|
||||
|
||||
任何替代方案都要证明统计与三个榜单仍共用一次聚合,没有将 daily/snapshot/profile 展开四次。计划不稳定或未显示可重复收益时,保留当前实现;不能仅凭提示写进 SQL 就认定生效。已试验方案若无实质变化,直接沿用既有结论。
|
||||
|
||||
## 减少复杂库存筛选的重复聚合
|
||||
|
||||
`AnalyticsQueryService.inventoryCoverage` 先调用 `inventoryCount`,再读取 `inventoryPage`。当条件依赖销量资格,例如无销量、可售天数、分桶或无法评估时,两次查询都会执行相近的完整候选计算。
|
||||
|
||||
分段测量若证实这两次聚合是相关路径的主要成本,再尝试一次共享候选:先在全候选上计算、筛选和排序,再从同一结果取得计数与当前页。执行计划须证明公共聚合只执行一次,仅抽取相同 SQL 字符串再调用两次不算共享。统计行应独立产生,即使结果为空或 offset 超出末页也返回真实 total,并且不能把统计占位行映射成伪 SKU 记录;不能仅依赖附在页记录上的 `COUNT(*) OVER()`,否则空页会丢失总数。响应 DTO 继续使用现有分页合同,不对前端引入第二套格式。
|
||||
|
||||
必须保留普通 ALL 的身份计数、冻结/次品关注的库存专用计数,以及默认库存先分页方案。**本项主要优化图表下钻和复杂筛选,不承诺降低基线中的 inventory-ALL 耗时。**
|
||||
|
||||
复杂筛选最后出库日仍可单独评估同一 SQL 内的页内索引倒序探测;它只补充展示,不参与筛选资格。保持固定销量版本、账号/仓库/货主/SKU、`business_date<=anchor`、PCS 正出库量及无匹配返回空值。对无销量或大量无效日行的 SKU 仍可能扫描较多行,不能承诺每个 SKU 必定只读取一行。
|
||||
|
||||
热销/滞销计数与分页也有类似重复计算,但只有定向测量证实不达标时再扩展,避免把本轮收敛变成全查询重写。
|
||||
|
||||
## 实测后再启用的方案
|
||||
|
||||
### 不完整或过期状态的快速路径
|
||||
|
||||
总览已跳过部分无用事实扫描。若“30 日不完整且库存过期”的场景仍耗时,可进一步评估只从固定 profile 身份生成候选数和未知统计,跳过空榜单计算。四种 `complete30 × stockFresh` 组合分别对照,零候选、未发布版本、未知原因优先级和七桶计数均须一致。
|
||||
|
||||
该项改善诊断状态响应,不能代替“30 日完整且库存新鲜”的正常经营查询优化,也不优先于总览正常路径。
|
||||
|
||||
### 固定版本结果的有界缓存
|
||||
|
||||
如果前述查询调整后仍未达标,再依据测量结果评估进程内有界缓存及同键并发请求合并,不默认新增 Redis 或缓存平台。总览 report 固定计算 30 日,切换趋势范围时存在复用机会;首先评估该稳定数据块,不缓存整页响应。
|
||||
|
||||
缓存键必须覆盖账号、仓库、全部实际访问范围、销量与库存版本、范围/修订摘要、固定日期窗、完整性和时效资格、规则版本。容量受条目数及内存预算限制,失败结果不作为正常数据缓存;发布、跨午夜、库存过期、修订屏障及旧版本不可读均须使相关复用失效。
|
||||
|
||||
每次请求仍在受控只读快照中完成权限、范围、版本可读性、覆盖和时效校验,重算实时状态。携带固定上下文的请求保留原 `queryAsOf`、业务日期锚点和 `queryExpiresAt`;下钻截止时间依据实际库存时效重算,并受原上下文有效期上限约束,不因缓存命中或翻页续期。一个旧缓存命中不能绕过被删除版本、待重建状态或过期库存的处理;同键请求合并不能把一个请求的上下文直接发给另一请求。
|
||||
|
||||
主方案明确要求无业务结果缓存的性能验收,本方案不修改该标准。缓存关闭、首次未命中、同键首次并发和命中分别报告;缓存收益只能作为额外体验改善。若无缓存始终不能达标,总控应提交剩余成本与方案取舍,不能自行以命中数据宣布通过。
|
||||
|
||||
本轮不新增固定 30 日 SKU 表、周月表或搜索引擎。若执行计划证明正常请求的全仓 SKU 聚合已是主要且无法继续压缩的成本,再单独评估发布时预计算的读取收益、构建增量成本、跨日期重算和原子发布规则;不能仅为省一次查询把可变结果写回已发布版本。
|
||||
|
||||
## 分开规划采集速度与查询并发
|
||||
|
||||
| 链路 | 记录的时间与吞吐 | 与其他链路的边界 |
|
||||
| --- | --- | --- |
|
||||
| 领星目录与逐单详情采集 | 配置间隔、实际请求起始间隔、请求耗时、成功明细数/分钟、429/冷却、剩余目录与详情请求量 | 统一账号级限流及环境独占;不能因有两个仓库就给每仓单独一份额度 |
|
||||
| 本地归并与统计候选构建 | 输入行量、批次量、构建阶段耗时、写入量、发布耗时及磁盘增长 | 使用已落库的事实;统计发布完成与详情下载完成分开记录 |
|
||||
| 页面查询 | 请求并发数、请求组合、实际完成请求数/秒、P50/P95/P99、错误率及各 SQL 耗时 | 读取已发布本地版本,10 个并发用户不等于固定 10 QPS,也不对应领星请求并发 |
|
||||
|
||||
总控在 2026-10-13 报告的账号串行小样本中,3/2/1 秒配置档各完成 20 次成功请求,对应平均详情请求间隔约 3.77/2.79/1.86 秒;0.5 秒配置档在约 735 ms 的两次详情请求间隔处出现 429 并停止。这证明配置等待和实际吞吐要分开测量,不能据此推导领星固定配额,也不能由 20 次成功认定可长期稳定维持该速率。总控选择的 1 秒配置不作为本方案的永久安全速率或新默认配额。
|
||||
|
||||
这些实测仅用于容量推算与解释来源等待。后续仍遵循[主方案的生产首采与测试请求边界](领星一件代发数据统计一期方案.md#生产首采与测试请求边界)及[接口联调手册](领星WMS接口联调手册.md)的账号预算、冷却和终止规则;本方案不发起新的限流探测,不增加真实采集并发,也不放宽原有请求预算。页面性能验证使用本地合成事实与统计数据。
|
||||
|
||||
采集预计完成时间应分为“剩余目录/详情获取、归并、构建、发布”四段。获取阶段根据实际成功吞吐及剩余请求量滚动估算,冷却和失败另计;不能仅用配置间隔乘单数给出整轮完成承诺,也不能因目录页拉完就显示销量已可用。页面分别展示已获取详情、已归并数量、构建阶段、最近完整发布版本及停止原因,沿用既有采集进度合同。
|
||||
|
||||
### 采集速度优化顺序
|
||||
|
||||
依据[接口专项的只读反馈](codex://threads/01a12f3f-c57a-79e1-9efa-9401f594544c),本轮复核了当前工作区的获取、路由、等待和预算链路。结论是:**先减少每条详情之后重复执行的本地工作,再减少短间隔等待造成的恢复开销;扩大目录分页作为后续新任务的次要节省项。** 已定位的是源码中的工作量放大,还没有整轮分段耗时证据,不能宣称它已占总耗时的某个比例或承诺若干倍提速。
|
||||
|
||||
接口调用单位也要分清:一个出库单详情请求可以带回多个 SKU,当前不是每个 SKU 都发一次详情请求。出库目录由账号共享获取,再分仓处理;产品库存独立按仓全量分页,两条链路不混用过滤能力。
|
||||
|
||||
| 顺序 | 已核对的情况 | 候选改进与预期影响 |
|
||||
| --- | --- | --- |
|
||||
| 先保留基线 | 1 秒配置不等于 1 秒实际请求间隔;短样本约 1.86 秒还没有完整分段 | 用现有观测与本地合成回放拆分耗时,不增加领星限流探测;记录生效配置、代码快照及阶段规模 |
|
||||
| 优先 1 | 每拿到一条新详情即执行全量 `route(false)`;按仓逐个检查整批目录 | 保留首次等待任务登记与最终完整路由,中间不再每单重建全量子任务;减少本地查询与子任务写回,不改变必要详情 HTTP 数量 |
|
||||
| 优先 2 | 每次间隔不足可能退出任务、释放租约,随后恢复重新扫描 | 若分段证据确认短间隔让出频繁,评估事务外有界等待或准确的到点调度;减少额外恢复成本,不降低账号最小间隔 |
|
||||
| 随后核对 | 父 manifest 每次整批序列化、重新统计完成量并写回;恢复检查也从开头进行 | 先测累计 JSON 字节、检查点和恢复扫描成本;用可靠的增量计数、变更集合/有界批量减少重复工作,保持可恢复证据。取消全量路由不代表这部分自动消失 |
|
||||
| 后续新窗口 | 官方目录上限 1000,本地出库 Query DTO 与校验上限为 100 | 统一 DTO、适配校验、配置和冻结参数后再验证较大分页;只节省目录请求,不能中途改变已运行任务的分页参数 |
|
||||
| 条件分支 | 批量实际出库明细、可靠修改游标或变更推送尚无已确认合同 | 向供应商核实能力及字段等价性后再设计;这是可能显著减少详情 HTTP 的方向,不能现在直接替换现有来源 |
|
||||
|
||||
#### 已确认的本地放大点
|
||||
|
||||
[SelfopDiscoveryService](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/sync/SelfopDiscoveryService.java) 在详情处理前、每条新详情提交后和全部完成后调用 `route`。其中按配置仓库遍历完整 manifest,对每个对象点查旧订单;相关对象有有效详情时,再读取和解析 stage,并重建子任务 manifest。中途 `detailsResolved=false`,子任务仍等待来源,不会因为这些完整重算提前进入 READY。
|
||||
|
||||
设目录对象数为 N、仓库数为 W、本轮实际新增抓取详情数为 K,在不计恢复和修订的基础路径上,旧订单查询方法调用量约为 `W × N × (K + 2)`。代入 N=K=2,787、W=2,约 1,554.6 万次调用。**这是代码循环的条件推算,不是已测 SQL 次数或数据库全表扫描次数**;MyBatis 缓存、事务边界、恢复和分支都会影响实际 SQL 与耗时。首采 K 接近 N 时,这部分工作量近似平方增长。
|
||||
|
||||
`saveManifest` 还会序列化父任务整批对象、遍历完成数并更新 task/run;检查点读取包含 manifest 的 task 行,路由又为各仓写回完整 manifest。该成本需要单列。优化不能简单把持久检查点全部改成内存缓存,也不能不落库直到最后;可复用的 VALID stage、对应关联及提交边界必须可靠保留,进程中断不能丢失已取得的详情或错误复用旧版本。
|
||||
|
||||
首个最小改动可先减少路由频次,不急于换表或调度平台。最终路由再评估有界批量读取旧归属和有效 stage、每对象解析一次后按仓分组。保留旧仓+新仓联合归属、取消/跨日期修订、`belongsToSlice`、租约栅栏及半归并屏障;全部详情确认前不能让空仓提前发布零量,已经 APPLYING/APPLIED/BLOCKED 的子任务不能被覆盖。页面等待关联和进度继续使用轻量投影,不靠重复全量路由维持可见性。
|
||||
|
||||
#### 额外等待不等于供应商请求时间
|
||||
|
||||
[SelfopEgressService](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/request/SelfopEgressService.java) 的 `ACCOUNT_INTERVAL_WAIT` 在发出领星 HTTP 前产生;[SelfopExecutionService](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/sync/SelfopExecutionService.java) 将执行让出并释放租约。调度器 `fixedDelay=1000` 表示当前 tick 的同步任务处理结束后再等 1 秒,不是保证每秒准时启动。出库任务恢复还包含重新获取租约、建立尝试和读取/扫描 manifest。
|
||||
|
||||
[LingxingEgressGate](../../baiyue-firstleg/integration-service/src/main/java/com/baiyue/integration/provider/lingxing/LingxingEgressGate.java) 在实际 HTTP 开始前另有账号保护,只等待尚未满足的剩余间隔。HTTP、落库和路由也消耗时间,不能把两处配置间隔简单相加。Lastleg 的持久 `minIntervalMs` 采用旧值与配置值的较大者,配置改成 1000 也不能直接证明实际已按 1000 生效;应只读核对实际许可和 HTTP 时间,不为本次梳理清空保护状态。
|
||||
|
||||
短间隔优化仅针对可恢复的普通间隔等待:事务外有界等待后重新校验租约、截止时间、账号保护及预约资格。等待超界、限流冷却、会话预算耗尽和结果不确定仍走原有让出/暂停路径;不能持有数据库事务或行锁睡眠,不能无限占用唯一调度线程,不能为了减少尝试数跳过重新授权。是否使用短等待还是到点调度,由实测等待分布和调度公平性决定。
|
||||
|
||||
| 事件 | 领星真实 HTTP 与预算 |
|
||||
| --- | --- |
|
||||
| 预约前因最小间隔/冷却/在途被拒绝 | 不发领星 HTTP、不增加持久 HTTP 预留;此前本轮内存工作额度可能已消耗,需与请求预算分开统计 |
|
||||
| 成功预留后、发送前失败 | 可能没有真实 HTTP,但预留与根会话额度不自动退还;不能据 reserved 数认定已调用领星 |
|
||||
| 已开始的超时、429 或业务失败 | 消耗一次真实请求;有回执时按实际调用数确认,未知结果保持保守预留 |
|
||||
| 重试/重新定位/再取详情 | 每次均重新授权计额;当前 Integration 没有隐藏的供应商 HTTP 重试循环 |
|
||||
|
||||
内部 reserve/authorize/complete 通信也有成本,但不是领星请求。下一轮性能证据分别记录内部调用数、真实 HTTP 数、预留额度和确认额度,不用 run 次数或重试次数代替外部调用次数。
|
||||
|
||||
#### 哪些请求可以减少,哪些还不能省
|
||||
|
||||
官方[出库分页](https://apidoc-omp.xlwms.com/reference/post_openapi-v2-order-delivery-page-1.md)目前公开的请求字段没有仓库过滤,最大页大小为 1000;返回仓库编码不代表请求支持按仓筛选。按两个仓库重复扫同一账号目录不节省请求,当前账号共享采集设计应保留。
|
||||
|
||||
以 2,787 单、两个稳定目录扫描轮次、所有订单均需一次详情、无异常重试为例:每页 100 需要 56 次目录请求,每页 1000 需要 6 次;加上 2,787 次详情,总量约从 2,843 降到 2,793,少 50 次,约 1.8%。这里只是基础请求量推算,不含重新定位、修订、库存等;真实收益还受响应大小和分页稳定性影响。已经完成目录的当前任务,不会因扩大未来分页而加快剩余详情。
|
||||
|
||||
列表虽然有 `productList[].qty`,官方未明确它在部分出库、差异出库及后续修订中等同实际出库量;[详情](https://apidoc-omp.xlwms.com/reference/post_openapi-v2-order-delivery-detail-1.md)明确区分 `deliveryQty` 与 `actualDeliveryQty`。当前统计需要后者,不能仅因列表包含 SKU 和数量就删掉详情请求。列表的批量单号筛选也不等于批量实际明细。
|
||||
|
||||
已有有效详情且没有更新观测时,当前代码会跳过 HTTP;这项应保留,不再作为从零开发的优化。新的观测代次、身份失配或修订要求重新核实时,仍需读取或重新定位。当前公开时间筛选未确认可靠的修改时间游标,不能永久以“列表字段没变”判断详情无需复查,也不能删除第二轮目录稳定性核验来制造提速。
|
||||
|
||||
需要供应商确认的高价值问题是:已出库列表 qty 的完整语义、批量实际明细能力、带稳定游标的修改时间增量/变更推送、历史修订与取消范围,以及账号级/接口级速率、突发和在途限制。当前未找到已确认能力不等于供应商没有这些能力;取得契约与针对性对账证据后,才能评估替换详情链路的收益。本轮不联系供应商、不增加试探调用。
|
||||
|
||||
#### 最小测量与验收
|
||||
|
||||
先复用已有日志和只读统计。缺少的分段埋点留给后续开发工作包,不为测量新增真实采集、加大并发或反复重跑已完成日期。每轮证据关联同一任务、尝试和出站许可,保留代码版本、N/W/K、复用比例、生效间隔、已发布覆盖、同机负载及预算边界。
|
||||
|
||||
| 测量组 | 必须区分的指标 |
|
||||
| --- | --- |
|
||||
| 外部调用 | 各接口 HTTP 数、实际起始间隔、HTTP 耗时、成功新增详情/分钟、429/超时;复用完成量不算新增下载速度 |
|
||||
| 调度与保护 | 最小间隔拒绝数、可再次尝试时刻、到点至实际恢复的延迟、租约获取/begin 耗时、内部授权/完成回执耗时 |
|
||||
| 本地处理 | 详情检查点、route、最终路由、归并/构建/发布分别计时;订单/stage 方法调用与实际 SQL 次数分别记录 |
|
||||
| 序列化与恢复 | manifest 大小、累计编码/解码字节、子任务写回次数、恢复重扫对象数、峰值内存和数据库连接等待 |
|
||||
|
||||
实际 HTTP 起始间隔、详情提交间隔和整阶段耗时分别报告;用同一请求链中不重叠的时间段解释墙钟耗时,不将互相覆盖的保护等待重复相加。先回答本地重复工作、外部等待各占多少,再决定线程数、连接池或并发调整;短样本不能证明长期限额。
|
||||
|
||||
离线对照建议固定 N=100/1,000/3,000、W=1/2,使用假领星 Client 和计数 Mapper,比较优化前后的必要 HTTP 数、route 次数、查询调用、JSON 字节、子任务写回和最终结果。覆盖部分恢复、全部复用、新观测强制复查、跨仓、取消、时间切片、零单、提交回滚、租约失效、等待超界及冷却。证明减少工作量且结果/恢复语义等价后,再按总控有效授权验证实际数据库耗时与整阶段吞吐;离线替身耗时不能冒充数据库提速。
|
||||
|
||||
本轮不承诺减少必需详情数量,不修改正在运行任务的分页、租约和会话预算,不为赶速度增加账号并发。采集页改版仍按已确认设计推进;这些采集性能候选由总控另行安排,不能把未经测量的优化变成当前页面交付的前置条件。
|
||||
|
||||
## 真实数据覆盖与容量样本用途
|
||||
|
||||
此前几分钟的真实销量样本只能验证局部链路。总控为功能验证补采的两仓单日 2,014 单,也必须完成目录核对、详情获取、归并与覆盖/发布校验后,才能用于判断对应日期的结果;目录数量相同或 HTTP 全部成功本身不证明业务日完整。
|
||||
|
||||
一个日期的数据完整不代表最近 30 日完整,也不自动补足每个 SKU 的观察期。相应平均销量、可售天数、无销量结论及榜单资格仍按主方案判定;不能为让页面出现数字把未覆盖日补零。真实功能样本与合成容量数据分别标注账号范围、仓库、统计版本、覆盖区间、观察依据及库存新鲜度。
|
||||
|
||||
功能核验可先使用真实单日结果,并用已有合成数据检查完整 30 日榜单、边界和下钻。容量验收必须包含“30 日完整且库存新鲜”的正常经营路径;观察不足或库存过期导致跳过聚合的快速响应仅代表该状态,不用于替代正常路径性能结果。
|
||||
|
||||
## 正确性与性能验收
|
||||
|
||||
所有 SQL 调整保留当前 API、权限、六位小数数量口径、统计版本、北京时间业务日及未知值规则。不会因为优化改变页面字段、图表范围、榜单资格或库存新鲜度。
|
||||
|
||||
| 对照组 | 必须验证的结果 |
|
||||
| --- | --- |
|
||||
| 两仓、同 SKU 不同货主、仅单版存在的 SKU | 身份不串仓/不串货主,候选并集不丢失;名称优先级不变 |
|
||||
| 完整/部分/未知销量、真实零量、单位冲突 | 正式量、已采集量、未知数量及原因一致,未知不能变成零 |
|
||||
| 新鲜/过期库存与完整/不足 30 日的四种组合 | KPI、榜单、七桶和下钻资格一致;正常完整场景单独计时 |
|
||||
| 边界 30/60/90 天、零可售、次品/冻结、短观察期 | 分桶用原精度比较;有限天数、无销量和未知不混算,库存品质不放大销量 |
|
||||
| 首末页、越界页、空结果及并列销量/天数 | total、顺序及业务键一致;不先取 Top 10 再算全仓分布 |
|
||||
| 发布切换、旧版、修订屏障、跨午夜、库存到期 | 同请求读一致快照;严格下钻拒绝规则及独立销量读取不变 |
|
||||
| 小数与最后出库日 | 小数汇总不提前取整;最近日期条件不放宽,无匹配仍为空 |
|
||||
|
||||
响应对照使用同一逻辑时钟与固定输入,逐字段比较;真实 HTTP 中必须变化的请求时间/诊断标识单独核对,不以整段忽略 context 的方式让对照通过。
|
||||
|
||||
每项候选先完成直接回归和 SQL 对照,再串行复测同档 HTTP,记录 P50/P95/P99、样本数、错误数、每请求 SQL 数、数据库耗时、扫描及临时结果、响应大小。相同资源下重复比较以排除波动;不能靠提高超时、减少候选、缩短统计范围或跳过资格校验获得收益。
|
||||
|
||||
最终验收沿用主方案:单仓 1 万货主+SKU、单销量版最多 366 万条稀疏日行、当前及至少两个旧版,并验证两仓隔离。无业务结果缓存,10 并发稳定至少 5 分钟;各类用例需要分别有足够样本,低于 100 个成功样本的路径只作抽测,不用其 P95 宣布通过。缺失阶段或失败请求不能从汇总中静默排除。
|
||||
|
||||
| 性能场景 | P95 目标及边界 |
|
||||
| --- | --- |
|
||||
| 经营总览 | ≤1.5 秒 |
|
||||
| 五种常用范围的 SKU 清单、7/30 日榜单、库存各关注筛选/排序、货主概览 | ≤1 秒 |
|
||||
| 366 天自定义 SKU 清单 | ≤2 秒,覆盖当前及仍可读旧版 |
|
||||
| 单 SKU 日趋势、货主选项、采集运行元数据查询 | ≤500 ms |
|
||||
| 全部正常合法请求 | 无超时/错误;首次与预热、单用户与并发、深分页分别报告 |
|
||||
|
||||
同档后台候选构建期间也要满足查询目标,并验证只读完整旧版;构建耗时、扫描、写入及磁盘增长单独报告。增加原单和旧统计版本后,当前固定版本查询不能扩大成原单/全部版本扫描。查询不访问 order/item/stage,不调用领星;合成容量验证不能通过开启真实采集获得数据。
|
||||
|
||||
### 并发与后台构建的对照矩阵
|
||||
|
||||
| 场景 | 固定条件与增加的负载 | 应取得的证据 |
|
||||
| --- | --- | --- |
|
||||
| 查询单独运行 | 单用户与 10 并发分别记录;请求组合、分页深度、日期范围、双版本、资格状态及资源不变 | 每条路径分别统计样本量和时延;默认库存作为已达标回归项,总览与销量作为主要改善对象 |
|
||||
| 查询与候选构建重叠 | 相同查询读取原固定版本,同时启动规模明确的本地候选构建 | 记录真正重叠的起止时间、构建阶段、输入/输出行量、批次及进度,关联查询时延、连接等待、CPU/磁盘;不能仅以后台曾启动证明已覆盖竞争 |
|
||||
| 查询与采集落库重叠 | 如需验证,采用受控合成输入,并单列写入速率与持续时间 | 与前两组分别比较,保留归并/写入的干扰证据;不调用领星制造压力 |
|
||||
| 版本发布边界 | 新旧版切换前后的请求分别标记,固定上下文仍读取原版 | 版本一致、无半份数据、到期拒绝正确;不把发布后更换数据范围的请求混入同一 A/B 结果 |
|
||||
|
||||
请求组合先覆盖既有近 15 日总览、销量和默认库存,再增加常用范围、长窗口、复杂筛选及深分页;记录每类占比,不能改变组合后直接比较整体平均值。主读阶段仍要求稳定至少 5 分钟;短构建或短采样仅标明覆盖到的阶段,其余阶段保留未验证。是否单独追加容量档位由实际使用需求决定,不自行把 10 并发目标扩展为新的大规模压测要求。
|
||||
|
||||
## 交给开发总控的工作包
|
||||
|
||||
以下工作包在功能与人工页面验收安排后启动;当前仅更新规划和证据,不向总控追加立即执行的性能任务。
|
||||
|
||||
| 顺序 | 工作包 | 完成条件 |
|
||||
| --- | --- | --- |
|
||||
| 1 | 复用完整基线与诊断 | 复用 1,991 次请求的完整基线及 39 次分段诊断,核对功能修复后的可比性;仅补缺失或已变化的证据 |
|
||||
| 2 | 对准总览 report 与销量 page | 现有采样已明确主要 SQL 成本;补查计划及资源竞争中的剩余问题,默认库存保持回归,不重做无收益实验 |
|
||||
| 3 | 验证有证据的新候选 | 用具体减少的扫描/聚合/排序工作量说明收益来源;复杂筛选共享聚合按其自身瓶颈选题,窄投影、profile 归并和延后名称无新证据不重做 |
|
||||
| 4 | 全场景验收 | 按主方案完成无缓存、长窗口/旧版、下钻及上述混合负载矩阵;无稳定收益候选不进入最终实现 |
|
||||
| 条件分支 | 退化状态快路/固定版有界缓存/发布时预计算评估 | 仅在前述证据支持时展开,不自动增加本轮表结构或平台依赖 |
|
||||
|
||||
总控指定查询实现的唯一写入者;只读评审、回归设计可以内部并行,Maven、部署和共享环境压测窗口继续串行协调。现有查询、Mapper、SQL 基线由其当前写入者维护,本次文档交接不另行移交文件写权,不创建独立对话。
|
||||
|
||||
每个候选交付“修改点与版本、固定输入、响应对照、前后执行计划、同档性能结果、是否保留及理由”。已试验未显示稳定收益的方案保留结论,新派工先查重;有实质差异才重新验证。测量完整后再决定下一项,不以预计收益百分比代替结果。本文不授权部署、SQL 执行、环境写入或真实领星调用;这些操作继续沿总控已有有效授权和工程约束安排。
|
||||
Reference in New Issue
Block a user