cangku/backend/src/constants/sidebarPages.js
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

68 lines
2.3 KiB
JavaScript

const ROLES = ['admin', 'analyst', 'user', 'guest'];
const DEFAULT_PLANNING_ROLES = { admin: true, analyst: true, user: true, guest: false };
const DEFAULT_SYSTEM_ROLES = { admin: true, analyst: false, user: false, guest: false };
const buildPlanningPage = ({ pageKey, pageName, path, allowSubPaths = false }) => ({
pageKey,
pageName,
path,
category: 'planning',
defaultRoles: DEFAULT_PLANNING_ROLES,
departmentDefaultAllowed: false,
...(allowSubPaths ? { allowSubPaths: true } : {}),
});
const SIDEBAR_PAGES = [
buildPlanningPage({ pageKey: 'ops_b_incentive', pageName: '激励看板', path: '/planning/operation/ops-b-incentive' }),
buildPlanningPage({
pageKey: 'dashboard_preview',
pageName: '仪表盘(开发预览)',
path: '/planning/dev-style-preview',
}),
buildPlanningPage({
pageKey: 'marketing_events',
pageName: '营销活动',
path: '/planning/operation/marketing-events',
allowSubPaths: true,
}),
buildPlanningPage({ pageKey: 'promotion_module', pageName: '推广模块', path: '/planning/operation/promotion-module' }),
buildPlanningPage({ pageKey: 'new_product_test', pageName: '新品测款', path: '/planning/operation/new-product-test' }),
buildPlanningPage({ pageKey: 'product_analysis', pageName: '商品分析', path: '/planning/operation/product-analysis' }),
buildPlanningPage({
pageKey: 'modular_stock_monitor',
pageName: '模块化库存监控 · 配件库存监控',
path: '/planning/operation/modular-stock-monitor',
}),
buildPlanningPage({
pageKey: 'mkh_bom',
pageName: '模块化库存监控 · MKH-BOM资料',
path: '/planning/operation/mkh-bom-data',
}),
buildPlanningPage({ pageKey: 'work_orders', pageName: '工单待办', path: '/planning/operation/work-orders' }),
buildPlanningPage({
pageKey: 'stock_sales_analysis',
pageName: '大货库存监控 · 库存动销分析',
path: '/planning/operation/stock-sales-analysis',
}),
{
pageKey: 'settings',
pageName: '系统设置',
path: '/settings',
category: 'system',
defaultRoles: DEFAULT_SYSTEM_ROLES,
departmentDefaultAllowed: false,
},
];
const SIDEBAR_PAGE_MAP = SIDEBAR_PAGES.reduce((acc, page) => {
acc[page.pageKey] = page;
return acc;
}, {});
module.exports = {
ROLES,
SIDEBAR_PAGES,
SIDEBAR_PAGE_MAP,
};