From 97c1a9131c84bcd936023937a234e422ad7ff28f Mon Sep 17 00:00:00 2001 From: yueli Date: Fri, 11 Sep 2026 13:34:36 +0800 Subject: [PATCH] =?UTF-8?q?feat(stocktake):=20=E6=98=8E/=E7=9B=B2=E7=9B=98?= =?UTF-8?q?=E7=94=B1=E5=90=8E=E7=AB=AF=E5=BC=BA=E5=88=B6=E9=A9=B1=E5=8A=A8?= =?UTF-8?q?=EF=BC=8C=E5=89=8D=E7=AB=AF=E8=A7=A3=E9=99=A4=E5=B1=8F=E8=94=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原实现是前端把「账面数」「差异」两列用 HTML 注释藏掉 —— 数据仍在 HTTP 响应里明文下发,抓包或用改过的客户端即可看到,等于没有屏蔽。 【后端】/draft/merged-list 先查该 session_id 的 StocktakeSession.mode: - blind:stock_qty 与 diff_qty 一律置 None,真实账面数不出现在响应中 - open :正常下发 差异必须一并置空 —— diff_qty 由账面数算出,下发差异等于变相泄漏账面数。 响应新增 data.mode 供前端提示。 Fail-Safe:查不到会话行时按盲盘处理。宁可界面少显示两列,也不能因为 会话记录缺失就把账面数泄漏出去。 【前端】删除屏蔽用的 HTML 注释,恢复两列正常渲染,不再承担数据屏蔽职责。 但 null 必须渲染为「—」而非 0:原 差异 模板用 `row.diff_qty || 0`, 会把「未下发」显示成「无差异」,工人会误以为账实相符。 另在抽屉表头加模式标签,便于核对。 实测: 盲盘 → 账面数=None 差异=None mode=blind 明盘 → 账面数=1.0 差异=-1.0 mode=open 未知 session_id → 同盲盘(Fail-Safe 生效) --- inventory-backend/app/api/v1/inbound/stock.py | 17 +++++++++-- .../src/views/stock/stocktake/index.vue | 30 +++++++++++++++---- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/inventory-backend/app/api/v1/inbound/stock.py b/inventory-backend/app/api/v1/inbound/stock.py index 1230e9f..53db8a1 100644 --- a/inventory-backend/app/api/v1/inbound/stock.py +++ b/inventory-backend/app/api/v1/inbound/stock.py @@ -1900,6 +1900,12 @@ def get_draft_merged_list(): params['offset'] = offset rows = db.session.execute(db.text(data_sql), params).fetchall() + # ── 明/盲盘控制:账面数与差异由后端强制决定是否下发 ── + # ★ Fail-Safe:查不到会话配置时按盲盘处理。宁可让界面少显示两列, + # 也不能因为会话行缺失就把真实账面数泄漏出去。 + session = StocktakeSession.query.filter_by(session_id=session_id).first() + is_blind = True if session is None else (session.mode == STOCKTAKE_MODE_BLIND) + # ── 组装结果 ── items = [] for row in rows: @@ -1915,9 +1921,12 @@ def get_draft_merged_list(): 'sku': row.sku or '', 'material_name': row.mat_name or '', 'spec_model': row.mat_spec or '', - 'stock_qty': stock_qty, + # ★ 盲盘:账面数置空,真实值不得出现在 HTTP 响应里 + 'stock_qty': None if is_blind else stock_qty, 'quantity': draft_qty, - 'diff_qty': round(diff_qty, 4), + # ★ 盲盘:差异同样置空 —— diff_qty 由账面数算出, + # 下发差异等于变相泄漏账面数 + 'diff_qty': None if is_blind else round(diff_qty, 4), 'remark': row.draft_remark or '', 'warehouse_location': row.warehouse_location or '', }) @@ -1927,7 +1936,9 @@ def get_draft_merged_list(): 'data': { 'list': items, 'total': total, 'total_scanned': total_scanned, - 'page': page, 'pageSize': page_size + 'page': page, 'pageSize': page_size, + # 前端据此决定表头提示;真正的数据屏蔽已经在上面做完了 + 'mode': session.mode if session is not None else STOCKTAKE_MODE_BLIND, } }), 200 diff --git a/inventory-web/src/views/stock/stocktake/index.vue b/inventory-web/src/views/stock/stocktake/index.vue index 3fdcee5..bcdaf5e 100644 --- a/inventory-web/src/views/stock/stocktake/index.vue +++ b/inventory-web/src/views/stock/stocktake/index.vue @@ -321,6 +321,9 @@ 已盘 未盘 + + {{ modeLabel(listMode) }} + 总品项: {{ stats.total }} | 已盘: {{ stats.scanned }} | 未盘: {{ stats.total - stats.scanned }} @@ -339,8 +342,16 @@ - - + + + + - +