# 仓储首页重构实施说明 更新日期:2026-10-16。 首页继续嵌套在 EleAdmin 页面内容区,保留原系统菜单、页头及标签栏。仅移除看板自身重复的顶部品牌/筛选栏和左侧导航,展示用户截图红框内的数据总览。看板主内容使用内容区可用宽度并随内容增长,根节点不得使用视口级 `fixed/inset/z-index` 或强制系统布局全屏。保留首页卡片下钻、明细筛选和返回首页入口;仓库/单位继续从现有路由参数及接口默认值读取。此约定以用户最新确认的“嵌套在页面里面、需要之前系统菜单”为准。 ## 页面与组件 普通及宇信首页通过 `warehouseManagement/index/index.vue`、`common.vue`、`yuxin.vue` 嵌套进入 `dashboard.vue`。三个历史入口都保留原路径,避免新增“点击首页”才能打开的独立看板路由。入口组合首页、9个统计视图、待我审批和4个原业务视图,共15个视图;首页不保留快捷新建按钮,新增单据从出入库列表进入。 | 文件 | 职责 | | --- | --- | | `index/dashboard.vue` | 路由筛选、真实请求、刷新生命周期、报表导出、业务导航及批量收货队列 | | `index/components/HomeOverview.vue` | 待办、指标、图表、预警与动态展示,事件上抛到入口 | | `index/components/DashboardChart.vue` | ECharts绘图、点击下钻、尺寸适配与实例销毁 | | `index/detail.vue`、`dashboard-screens.js` | 真实明细列、筛选、分页、操作和统计口径 | | `index/components/DashboardActions.vue` | 阈值、采购需求、处置、财务登记与逐单结果 | | `api/warehouseManagement/dashboard.js` | 统一鉴权请求和业务响应校验,身份保留字符串 | `dashboardView`取值:`home/ledger/dead/io/todo/age/alerts/turnover/locations/qc/flow/addin/addout/ioapp/inapp`。筛选保存在路由查询中,显式空`unit`表示不自动选默认单位。月份初值使用本地月份完整首末日,接口以服务端规则再次校验。 首页以外的14个配套视图如下: | 视图 | 路由值 | | --- | --- | | 库存台账 | `ledger` | | 呆滞品分析 | `dead` | | 出入库动态 | `io` | | 待办单据 | `todo` | | 批次库龄 | `age` | | 安全库存预警 | `alerts` | | 周转分析 | `turnover` | | 库位地图 | `locations` | | 入库质检 | `qc` | | 待我审批 | `flow` | | 新增入库单 | `addin` | | 新增出库单 | `addout` | | 出入库申请 | `ioapp` | | 入总库申请 | `inapp` | ## 数据口径与刷新 - 使用`/wms/index/home-options`、`home-summary`、`home-detail`及`home-alert-config`,不保留原型示例数字。 - 不同基本单位不相加。库存含待检与锁定;库存总量、分类、库龄、周转等 KPI 的可用量扣锁并排除未放行(`batchRows` 的`available_count_base−锁定量`)。**安全库存预警是唯一例外**:预警可用量=在库量−锁定量、含待检与未放行,走`alertRows` 的独立子查询,与上述 KPI 不同源;`batchRows`/`costRows` 两个共享片段因此不得改动,理由见《仓储首页看板口径.md》A1。金额按可核实入库价估值,缺价不显示为零。 - 呆滞认定要求首次入库及最近实际消耗均超过180天,占比使用呆滞估值与全部库存估值。日期或估值不足时展示原因。 - `summary.capturedAt`显示为“服务端查询时间”;7日前日末实际采集时间由`comparisonReason`说明,不能将本次接口时间当作日结时间。 - 总统计15分钟、预警5分钟、动态30秒刷新;后两类通过`section=alerts/activities`更新对应区块。请求序号及生命周期世代阻止旧响应覆盖新筛选;页面停用、销毁后清理定时器。 - 明细真实分页,导出沿当前筛选逐页读取。空值保留未知语义,缺日期显示“日期待核实”。 ## 原业务链路 - 待入/出库、入总库按本月整单待办打开,默认状态0;清除首页物料、单位筛选,避免与整单计数口径冲突。入总库原API在每次查询时固定`type=1`,重置筛选不会混入出库申请。 - 批量收货从真实WMS申请列表选择,逐单打开原入库表单,完成原校验和包装明细组装后暂存请求,全部核对后调用`/wms/dashboard/action/batch-receive`。来源为`/wms/applystoragedetail/listByAppIds`;`extInfo.dashboardApplyDetailId`保留申请明细ID,采购来源`sourceReceiveProductId`原样保留。 - 批量收货确认期间阻止重复请求;旧表单事件必须与当前`inId`匹配。成功项移除,失败项保留完整请求及原`requestKey`供重试。成功表示保存并提交原审批或质检,库存变动仍取决于原流程。 - 库存盘点入口默认`type=inventory`;待审批使用真实当前任务分页及逐单审批返回值。业务身份禁止转成JavaScript数值。 - 阈值按仓库与物料基本单位配置,要求`0≤最低≤安全≤最高`且精度4位;历史单位不一致时提示核对。采购需求保存为EOM草稿,需在原需求详情核对并提交。 - 呆滞处置依次保存草稿、提交真实审批、执行原调拨或出库、登记独立财务凭证。驳回/撤销可重新提交;审批本身不变动库存。财务附件复用原上传组件。 - 库位用途字段为`allocationPurpose=ordinary/repair/temporary/virtual`,启停字段为`enabled=0/1`;新货位普通且启用,历史空值保留待核实。 ## 跨系统与权限 从当前用户授权菜单解析门户同源入口。WT接收`warehouseScope/warehouseId/month/taskId`后,先按真实任务ID和授权范围查询,再打开原审批容器。WT新增`stagnantDisposal/detailDialog.vue`读取真实处置申请,`submit.vue`复用现有审批意见、通过与驳回处理。EOM通过`requirementId`打开原采购需求详情。 本地没有QMS前端项目,质检操作仅标“打开检验工作台”,传批次参数;未证明目标工作台消费这些参数,不宣称可精确打开质检报告。 WMS/WT/EOM在`dashboard=1`时启用深色Element主题。WMS样式限制在页面内容区及看板专用弹层:`DashboardActions`使用`wms-dashboard-dialog`,其选择框使用`wms-dashboard-popper`;不得直接覆盖整个`body`下的Element组件。系统页头部门、角色输入框及选项面板保持原白色样式。接口仍由服务端校验授权仓库及业务权限,不以隐藏前端按钮代替鉴权。 ## 验证与验收边界 最终定向检查:WMS 22个、WT 5个、EOM 3个改动的Vue/JS/SCSS文件,模板编译、Babel脚本解析及看板Sass编译均无失败;三个前端仓库`git diff --check`通过。WT处置审批另用Vue实际选项合并断言,确认无独立模板的子组件继承原渲染函数、审批方法、任务参数,且后端两个组件路径均指向本地现存文件。 上述重构检查未执行完整前端构建、Maven、浏览器或设备验证,也未调用真实写接口。Sass仅出现现有旧JS API弃用提示。新增文档和断言脚本均未被忽略规则排除,未暂存或提交本次改动。 2026-10-16展示范围修正:实际本地浏览器确认首页位于`.ele-admin-content`内,系统菜单、页头和标签栏可见;部门、角色输入框和展开的选项面板计算背景均为`rgb(255, 255, 255)`。卡片进入库存台账及返回首页已验证。修正后的布局、看板及操作弹层模板和脚本解析、三份看板SCSS编译、现有业务断言和`git diff --check`通过;系统布局文件无最终差异。本次未执行完整构建、设备验证或真实写操作。 运行`node scripts/check-warehouse-dashboard.cjs`可重复验证月份边界、空值/零值、大整数身份、授权菜单路径、整单待办筛选、“其他”分组下钻、重复收货事件与失败项幂等重试;脚本直接加载现有组件方法,使用请求桩,不访问数据库。 部署前须在目标环境联调真实响应、菜单路径、弹层布局、审批模型及权限、采购草稿、批量收货审批/质检、处置执行与财务附件。日末数据需等真实采集积累,缺失历史不能用样例或补造值替代。后端表结构与模型准备参见后端项目`docs/仓储管理首页重构-统计与数据核验.md`及影响地图。 2026-10-16首页入口约定:本次将“白色字典背景”暂按“白色字体”处理,标题“仓储管理总览”和“下午好,xxx”使用白色字体,保留看板深色背景;库存总量、库存金额、库存分类“查看台账”及分类图点击统一跳转原库存台账`/warehouseManagement/stockLedger`,待入库与入库管理使用`/warehouseManagement/stockManagement`,待出库与出库管理使用`/warehouseManagement/outgoingManagement`,不进入首页自建台账或出入库列表。原系统入口不携带`dashboard=1`;`ledger`事件与`stockLedger`事件统一分流,避免其他统计页的“查看库存”再次进入自建台账。前文重构记录中的台账下钻约定以本条为准。原台账未读取首页分类查询参数,本次仅保证进入原页面,不宣称自动选中分类。 2026-10-29下钻页深色主题泄漏修复(蓝色背景问题):现象是从仓储首页下钻打开的页签(出库单详情、入库单详情、盘点工单详情、调拨详情、批次详情)整页呈深蓝底色而不是系统白底。根因不是页面自身样式,而是深色主题的实现方式:`dashboard-element.scss` 以 `body.wms-dashboard-theme .ele-admin-content` 为作用域,`router.afterEach` 又按 `to.query.dashboard === '1'` 在 `body` 上开关该 class,而 `dashboard.vue` 的 `navigate()` 会把 `dashboard=1` 一并推到业务页 URL;`beforeDestroy` 里 `this.$route.query.dashboard !== '1'` 的判断在新路由已切换后才执行,同样留下 class。于是新页签里所有 `.el-card/.el-table/.el-input` 被刷成 `#0A1A30`,白底页面看起来就是「蓝色背景」。修复方式是把主题从「URL 参数驱动的全局 class」改为「看板自身容器作用域」:`dashboard-element.scss` 去掉 `body.wms-dashboard-theme .ele-admin-content`,只保留 `.wms-home`(看板模板根节点)与 `.wms-dashboard-dialog/.wms-dashboard-popper`(append-to-body 的弹层与 popper);`dashboard.vue` 不再在 `mounted/activated/beforeDestroy` 操作 `document.body.classList`;`router.afterEach` 删除 query→class 的切换;`navigate()` 不再向业务页透传 `dashboard=1`(保持「系统原有入口不携带 dashboard=1」的约定),并补上吞 `NavigationDuplicated` 的 catch,重复点同一行不再弹错。`dashboard=1` 保留给看板自身的内部视图(`tgTable` 批量收货勾选、`warehouseApplication` 批量审批),这两处的判断都在看板路由内,不受影响。验证:`npx sass` 编译 `dashboard-element.scss` 通过;`vue-template-compiler` 解析 `dashboard.vue/HomeOverview.vue/DashboardActions.vue` 模板与 Babel 解析脚本、`router/index.js` 均通过;`node scripts/check-warehouse-dashboard.cjs` 原 12 组断言仍全通过,并新增 G1「深色主题作用域」断言(禁止 `body.` 级作用域、禁止 `document.body.classList` 主题开关、禁止 `navigate` 带 `dashboard=1`),该组断言对修复前的文件实测会失败,非空转;`eslint` 对 `router/index.js` 的报错数量由 10 降为 9(改动的第 76 行原本就是 prettier 报错行,余下 9 条为既有问题),`git diff --check` 通过。本次未执行完整构建与浏览器验证,蓝色背景是否消失需在目标环境点开上述五个下钻页确认;WT/EOM 两仓库的看板主题若同样以 body class 实现,需要各自单独排查(本次只改 WMS 前端)。 2026-10-29首页默认基本单位:进入首页时基本单位下拉框默认选中第一个基本单位。原因是多基本单位下不选单位,后端只能按「单位待核实」处理——库存总量、库存金额、周转天数、库龄结构、分类分布等 KPI 整片为空,用户看到的就是「首页没有数据」;下拉框虽然有「全部单位」,但不该是默认值。实现:后端 `GET /wms/index/home-options` 已下发 `defaultUnit`(`unitRows.get(0)`,按授权仓库算好),前端 `dashboard.vue` 新增 `defaultUnit()`(优先 `options.defaultUnit`,缺失回退 `units` 第一个非空单位)与 `applyDefaultUnit(explicit)`,在 `readRoute()`(仅 `view === 'home'`)和 `created()` 拿到筛选项之后再各兜一次——第一次 `readRoute` 时 `options` 还没到,只靠 `readRoute` 会漏掉首屏;默认值同时写进 `filters.unit`,否则请求参数里根本没有 `unit`。判定「用户是否表过态」只看 URL 里有没有 `unit` 键:显式 `unit=` 是用户主动选的「全部单位」,保持不动;已有单位不覆盖。同时修掉两处会退回「全部单位」的入口:`setWarehouse` 不再把单位清空(单位列表是全部授权仓库口径,与单仓无关,清空后切仓立刻没数据),`open('home')` 从出入库申请/入总库申请返回时把被这两个视图清掉的单位补回来(这两个视图按单位过滤会把申请单筛空,所以它们自己不带单位)。验证:`node scripts/check-warehouse-dashboard.cjs` 新增 H1 断言组(默认选中 `defaultUnit`、回退 `units[0]`、空白单位不选、无单位返回空串、显式空单位与已选单位不被覆盖、`setWarehouse` 不再出现 `unit: ''`、返回首页补单位、`created` 后补兜一次);该组断言对修复前文件实测全部失败,非空转。模板/脚本解析、`git diff --check` 通过;未执行完整构建与浏览器验证,首屏是否直接出数需在目标环境确认。 2026-10-29盘点工单详情下钻地址修正:现象是从首页点「盘点任务进行中」/出入库动态里的盘点流水,跳转地址是 `…/stocktaking/work/details?startTime=…&endTime=…&page=1&warehouseId=…&unit=KG&categoryId=…&id=…`,既没有 `planId`,还糊了一串首页筛选参数,详情页报错。两处根因:①`navigate()` 把首页整套 `this.filters` 整包拼进业务页 URL(详情页只认 `id`/`planId`,其余全是噪声);②盘点两个下钻入口只带 `id`,正常地址应是列表页那套 `?id=<工单ID>&planId=<计划ID>`。修复:`navigate()` 只透传显式参数(`cleanQuery({...query})`,不再 `...this.filters`、也不再带 `dashboard=1`);`business('todo')` 与 `business('io')` 的盘点分支改为 `{ id, planId: row.planId }`。`planId` 由后端首页查询列下发:`WmsHomeMapper.xml#todoRows` 三分支各补第 11 列(盘点分支 `CAST(o.plan_id AS CHAR)`,另两分支 `NULL`),`recentActivities` 两分支各补第 12 列(盘点分支真实 `plan_id`,出入库分支 `NULL`),UNION 列数保持一致(11/11/11、12/12)。兼容:旧链接/旧数据没有 `planId` 时 `cleanQuery` 直接丢弃该键,不会拼出 `planId=undefined`;后端 `PlanServiceImpl#getOrderInfoByPlanId` 已能由工单反查 `plan_id` 兜底,所以两种地址都能打开。验证:`node scripts/check-warehouse-dashboard.cjs` 新增 I1 断言组(待办与动态两个入口都带 id+planId、`planId` 缺失不拼 undefined、URL 只剩显式参数、`navigate` 源码不得再出现 `...this.filters`),全通过且对修复前文件实测失败;`xmllint --noout`、UNION 列数一致性脚本、模板/脚本解析、Sass、`git diff --check` 均通过。未执行完整构建、未部署、未连真实库。 2026-10-29「出入库动态 › 查看动态」改落 V13 出入库申请:原链接发 `open('io')`,落到首页自建的 V4 出入库动态列表(已完成流水明细,粒度是快照行)。用户要的是单据本身,改为 `open('ioapp', { status: '' })` → `dashboardView=ioapp`,打开与系统菜单同一个「出入库申请」组件(入库/出库两个页签)。关键点:`open()` 对 ioapp 的默认 `status=0`(未处理)会把已完成单据挡住,所以必须显式传空串,`cleanQuery` 再把它丢掉,等价于申请列表的「全部状态」默认值(`search.vue` 的 `defaultWhere.status=''`);`direction` 由 `open()` 兜底为入库页签;`warehouseId` 随首页筛选带过去,`categoryId`/`unit` 被 ioapp 分支清掉(按单位筛申请单会把单据筛空),时间窗沿用 `monthRange()` 本月。V4 列表仍然可达,入口不删:「最近作业动态 › 全部动态」、趋势柱体/无作业日点击、以及 V4 里调拨行的「查看单据」都还是 `open('io')`,所以 `scripts/check-warehouse-dashboard.cjs` 里「全部动态 › 必须仍发 open('io')」的既有断言保持不动。验证:新增 J1 断言组(模板必须发 `open('ioapp', { status: '' })`;行为断言走真实 `open()`+`route()`,确认 dashboardView=ioapp、direction=in、带 warehouseId、**query 里没有 status**(否则又变回只看未处理)、unit 为空、带本月 startTime/endTime;「全部动态 ›」仍发 open('io')),全通过。模板/脚本解析、`git diff --check` 通过;未起浏览器验证,需在实际环境点一次确认 V13 列表默认是全部状态且入库页签有数据。 2026-10-29「查看动态」落点再修正:上一版改成看板内嵌的 `open('ioapp')`(`dashboardView=ioapp`,仍停在首页路由、只是切换内部视图),用户要的是**菜单真实路由**——跳 `/warehouseManagement/inboundRequests`(出入库申请)这个独立页签。最终实现:`HomeOverview.vue` 的「查看动态 ›」改发 `$emit('navigate', '/warehouseManagement/inboundRequests', { warehouseId })`,`dashboard.vue` 在 `` 上增加 `@navigate="navigate"`,复用已有的 `navigate()`(只透传显式参数、`cleanQuery` 丢空值、吞 `NavigationDuplicated`)。只带当前仓库:状态/时间/页签交给目标页默认值(`search.vue` 的 `defaultWhere.status=''`=全部状态、默认入库页签、无时间窗),不得带 `dashboard=1`(会误开看板批量收货勾选列);未选仓库时 query 为空,`?warehouseId=` 这种空串不落 URL。V4 动态列表入口保持不变(「全部动态 ›」、趋势柱体/无作业日、调拨行「查看单据」仍发 `open('io')`),既有「全部动态 › 必须仍发 open('io')」断言不动。验证:J1 断言组重写为路由断言——模板必须发 `navigate('/warehouseManagement/inboundRequests', { warehouseId: warehouseId })` 且不得出现 `open('ioapp')`/`open('io')`,`dashboard.vue` 必须有 `@navigate="navigate"`;行为断言走真实 `navigate()` 确认 push 的 path 是 `/warehouseManagement/inboundRequests`、query 只有 `warehouseId`、无 `dashboard`、仓库为空时 query 为空对象。全套 11 组断言、模板/脚本解析、`git diff --check` 通过;未起浏览器,需实际点一次确认打开的是菜单「出入库申请」页签而不是首页内嵌视图。 2026-10-29首页首屏遮罩:看板渲染慢,之前是空卡片先渲染、数字分批填充,用户看到的是「首页没有数据」。改为首屏盖一层遮罩,数据(`home-options` + `home-summary`)落定后再显示内容。实现:`dashboard.vue` 增加 `homeLoading`(默认 true),`created()` 里 `await this.refresh()` 之后置 false(**只置一次**,15 分钟定时刷新、筛选项切换、路由 query 变化都不再闪遮罩);模板在 `.wms-home` 内加 `
转圈 + 「正在加载首页数据…」
`,只挡首页视图——明细视图(V2/V4/V5…)有自己的 `v-loading`,不能被这块盖住。加载失败同样撤遮罩,露出 `HomeOverview` 的错误条与「重试」。样式写在 `dashboard-layout.scss`:`.wms-home` 补 `position: relative` 作为遮罩定位上下文(已核对 `.screen-band`/`.card`/`.kpi`/`.todo-item` 这些绝对定位装饰本来就有各自的 relative 父级,不会因为新增定位上下文移位),遮罩 `position: absolute` + `z-index: 20` + 与看板同色的径向渐变 + `min-height: 320px` 下限(首屏内容为空时 `.wms-home` 只靠 `min-height:100%` 撑高,防止极端情况下压成一条线);**不能用 `position: fixed`**,那会连系统页头、菜单、标签栏一起盖掉(与 dashboard-element.scss 的既定约束一致)。转圈用 `@keyframes home-loading-spin`。验证:新增 K1 断言组(`homeLoading` 默认 true;`created` 中 `await refresh()` 之后再置 false 且全文件只出现一次;模板 `v-if` 必须带 `view === 'home'`;样式必须 absolute + z-index + 动画关键帧,且不得出现 `position: fixed`),全套 12 组断言、模板/脚本解析、两份 SCSS 编译、`git diff --check` 通过。未执行完整构建与浏览器验证,实际首屏出数时间与遮罩停留时长需在目标环境确认。