youruo f20bd3a487 feat: 侧边栏新增二级「库存动销分析」页面
按《仓库库存动销分析.xlsx》:
- 一级菜单「大货库存监控」下新增二级「库存动销分析」(路由 /planning/operation/stock-sales-analysis)
- 表头与表格结构按需求表:仓库 | 动销等级 | SKU数量 | SKU占比 | 库存数量 | 库存占比 | 销量,
  每仓 6 个动销等级(爆款/热卖款/平销款/滞销款-1/滞销款-2/销售=0)+ 1 行汇总,仓库列跨行合并
- 分档口径:日销 = 统计窗口内已发货件数 ÷ 窗口天数(7/14/30 天可选,默认 30),
  库存取 rpt.jst_inventoryInfo 实时库存,销量取 jst_Orders×jst_OrderItem 按 send_date
  (排除 Delete/Cancelled,与每日进销存发货口径一致),只统计有库存或有销量的 SKU
- 后端 /api/stock-sales-analysis:单条 SQL 一次覆盖全部仓库×等级,5 分钟缓存 + refresh=1 强制重算;
  返回逐仓 + 全仓合计、占比、无数据仓数量
- 前端页面:统计天数/仓库筛选、口径说明弹窗、合计行高亮、无数据仓计数提示
- 页面权限:前后端 sidebarPages 注册 pageKey=stock_sales_analysis,默认 planning 角色可见

验证:后端 syntax + 单测 5/5;前端 eslint、build、npm test 21/21;
本地接口 30 天窗口实测 27 仓(崔桥汇总 2080 SKU / 90822 件 / 54076 件销量),
占比逐仓闭合为 100%;浏览器实测侧边栏入口、表头、197 行渲染与截图均正常
2026-09-27 16:29:58 +08:00

91 lines
1.5 KiB
CSS

.stock-sales-page {
padding: 16px 20px 24px;
display: flex;
flex-direction: column;
gap: 12px;
}
.stock-sales-header {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.stock-sales-header__title {
display: flex;
align-items: center;
gap: 4px;
}
.stock-sales-header__help {
font-size: 13px;
}
.stock-sales-header__meta {
display: flex;
flex-wrap: wrap;
gap: 16px;
font-size: 13px;
color: rgba(0, 0, 0, 0.55);
}
.stock-sales-th-tip {
border-bottom: 1px dashed rgba(0, 0, 0, 0.35);
cursor: help;
white-space: nowrap;
}
.stock-sales-table .ant-table-thead > tr > th {
white-space: nowrap;
font-size: 12px;
padding: 6px 8px;
}
.stock-sales-table .ant-table-tbody > tr > td {
padding: 5px 8px;
font-size: 13px;
vertical-align: middle;
}
.stock-sales-warehouse {
white-space: nowrap;
}
.stock-sales-grade {
white-space: nowrap;
}
.stock-sales-grade.is-total {
font-weight: 600;
}
/* 每个仓库的汇总行 */
.stock-sales-table .stock-sales-row--subtotal > td {
background: rgba(0, 0, 0, 0.03);
font-weight: 600;
}
/* 全仓合计行 */
.stock-sales-table .stock-sales-row--grand > td {
background: rgba(22, 119, 255, 0.06);
font-weight: 600;
}
.stock-sales-footer {
font-size: 12px;
}
.stock-sales-help p {
margin: 0 0 6px;
line-height: 1.7;
font-size: 13px;
white-space: pre-wrap;
}
.stock-sales-help p.is-indent {
padding-left: 16px;
color: rgba(0, 0, 0, 0.65);
}