fix(stocktake): 拉开主副按钮层级防误触,明细增加库位列

【按钮层级】场景 A(已有进行中的盘点)
原实现主按钮是「加入当前盘点」,次入口是个不起眼的文字链接
「开启新一轮盘点」—— 二者视觉权重接近,而后者会终结本司其他 PDA
正在使用的会话,误触代价高。

现改为:
- 主按钮:绿色「继续当前盘点」,高度放到 66px、字号 19px
  (新增 .action-btn-hero),平板大屏上一眼可辨、一按即中
- 次按钮:红色镂空「结束当前并开启新盘点」,点击走 10 秒倒计时强确认
- 确认弹窗措辞由「原有数据将保留」改为明确告知**会话将被终结**:
  「该会话将标记为已结束,其他设备不能再加入」
- 倒计时确认通过后展开配置表单(而非直接开会话),让用户仍能选模式/范围;
  表单提交不再二次弹窗,避免重复确认

【库位列】明细抽屉新增「库位」列,紧跟规格之后 —— 找货刚需。
后端 merged-list 已下发该字段,实测单行返回含 warehouse_location='Y2/4/3/4',
无需改动。
This commit is contained in:
yueli
2026-09-11 13:53:53 +08:00
parent eabe70b00a
commit 325cc44469

View File

@ -46,23 +46,31 @@
</el-button> </el-button>
</template> </template>
<!-- 场景 A已有进行中的盘点且未主动选择开启新一轮 绿色加入 --> <!-- 场景 A已有进行中的盘点
主按钮 = 继续当前盘点绿加大次按钮 = 结束当前并开启新盘点镂空
两者视觉层级必须拉开 次按钮会终结本司其他人正在用的会话误触代价高 -->
<template v-else-if="activeSession && !creatingNew"> <template v-else-if="activeSession && !creatingNew">
<el-button <el-button
type="success" type="success"
size="large" size="large"
class="action-btn-full" class="action-btn-full action-btn-hero"
@click="joinActiveSession" @click="joinActiveSession"
:loading="btnLoading" :loading="btnLoading"
> >
加入当前盘点 继续当前盘点
</el-button> </el-button>
<div class="active-session-tip"> <div class="active-session-tip">
{{ modeLabel(activeSession.mode) }} · {{ scopeLabel(activeSession.scope_type) }}已扫 {{ activeSession.scanned }} <template v-if="activeSession.initiator">发起人{{ activeSession.initiator }}</template> {{ modeLabel(activeSession.mode) }} · {{ scopeLabel(activeSession.scope_type) }}已扫 {{ activeSession.scanned }} <template v-if="activeSession.initiator">发起人{{ activeSession.initiator }}</template>
</div> </div>
<!-- 次要入口缺了它本司一旦有过会话就永远开不了新一轮 --> <el-button
<el-button link type="primary" class="secondary-entry" @click="creatingNew = true"> type="danger"
开启新一轮盘点 plain
size="large"
class="action-btn-full"
@click="endCurrentAndCreate"
:loading="btnLoading"
>
结束当前并开启新盘点
</el-button> </el-button>
</template> </template>
@ -90,7 +98,7 @@
抽盘仅盘点近 30 天有出入库/借还记录的前 50 个活跃库位 抽盘仅盘点近 30 天有出入库/借还记录的前 50 个活跃库位
</div> </div>
<div v-if="creatingNew" class="task-form-warn"> <div v-if="creatingNew" class="task-form-warn">
开启新一轮会把当前进行中的盘点置为已结束历史数据仍保留 开启新一轮将<strong>终结当前会话</strong>已扫数据完整保留但其他设备不能再加入该会话
</div> </div>
</div> </div>
@ -215,7 +223,7 @@
<!-- 新增: 防呆确认弹窗 --> <!-- 新增: 防呆确认弹窗 -->
<el-dialog <el-dialog
v-model="showConfirmDialog" v-model="showConfirmDialog"
title="⚠️ 确认开启新一轮盘点" title="⚠️ 结束当前盘点"
width="400" width="400"
destroy-on-close destroy-on-close
:close-on-click-modal="false" :close-on-click-modal="false"
@ -225,16 +233,20 @@
> >
<div class="confirm-content"> <div class="confirm-content">
<el-icon :size="48" color="#E6A23C"><WarningFilled /></el-icon> <el-icon :size="48" color="#E6A23C"><WarningFilled /></el-icon>
<p class="confirm-text">当前公司已有盘点在进行中开启新一轮会生成新的会话<strong>原有数据将保留</strong>但之后加入当前盘点只会进入最新的这个会话确定开始吗</p> <p class="confirm-text">
即将<strong>结束当前进行中的盘点</strong><br />
已扫数据会完整保留但该会话将标记为已结束<strong>其他设备不能再加入</strong><br />
随后你可以配置并开启新一轮确定继续吗
</p>
</div> </div>
<template #footer> <template #footer>
<el-button @click="cancelConfirm">取消</el-button> <el-button @click="cancelConfirm">取消</el-button>
<el-button <el-button
type="primary" type="danger"
:disabled="countdown > 0" :disabled="countdown > 0"
@click="confirmStartNew" @click="confirmStartNew"
> >
{{ countdown > 0 ? `确认开启 (${countdown}s)` : '确认开启' }} {{ countdown > 0 ? `确认结束 (${countdown}s)` : '确认结束' }}
</el-button> </el-button>
</template> </template>
</el-dialog> </el-dialog>
@ -344,6 +356,9 @@
<el-table-column prop="sku" label="SKU" width="140" show-overflow-tooltip /> <el-table-column prop="sku" label="SKU" width="140" show-overflow-tooltip />
<el-table-column prop="material_name" label="名称" min-width="120" show-overflow-tooltip /> <el-table-column prop="material_name" label="名称" min-width="120" show-overflow-tooltip />
<el-table-column prop="spec_model" label="规格" width="120" show-overflow-tooltip /> <el-table-column prop="spec_model" label="规格" width="120" show-overflow-tooltip />
<!-- ★ 库位:找货刚需,放在名称/规格后面。
后端 merged-list 已下发SELECT cs.warehouse_location → 组装进 JSON -->
<el-table-column prop="warehouse_location" label="库位" min-width="120" show-overflow-tooltip />
<!-- ★ 账面数与差异由**后端**按会话 mode 决定是否下发: <!-- ★ 账面数与差异由**后端**按会话 mode 决定是否下发:
盲盘时这两个字段返回 null前端不再做任何屏蔽。 盲盘时这两个字段返回 null前端不再做任何屏蔽。
注意 null 必须显示为「—」而不是 0 —— 用 `|| 0` 会把「未下发」 注意 null 必须显示为「—」而不是 0 —— 用 `|| 0` 会把「未下发」
@ -890,26 +905,39 @@ const enterScanning = async (message: string) => {
ElMessage.success(message) ElMessage.success(message)
} }
// 点击「开始新盘点」或次要入口「开启新一轮盘点」 // ★ 场景 A 次按钮「结束当前并开启新盘点」
// 它会终结本司其他 PDA 正在使用的会话,代价高,必须走 10 秒倒计时强确认。
const endCurrentAndCreate = () => {
if (!activeSession.value) {
// 没有活跃会话(理论到不了这里),直接展开表单
creatingNew.value = true
return
}
showConfirmDialog.value = true
countdown.value = 10
if (countdownTimer) clearInterval(countdownTimer)
countdownTimer = setInterval(() => {
countdown.value--
if (countdown.value <= 0) {
clearInterval(countdownTimer!)
countdownTimer = null
}
}, 1000)
}
// 倒计时确认通过:先展开配置表单选模式/范围,不直接开会话
const confirmStartNew = () => {
if (countdown.value > 0) return
showConfirmDialog.value = false
creatingNew.value = true
}
// 创建表单提交。是否终结当前会话已在 endCurrentAndCreate 处确认过,这里不再二次弹窗
const startNewSession = async () => { const startNewSession = async () => {
if (!selectedCompany.value) { if (!selectedCompany.value) {
ElMessage.warning('请先选择公司') ElMessage.warning('请先选择公司')
return return
} }
// ★ 该公司已有进行中的盘点 → 二次确认(不删数据,只签发新会话)
if (activeSession.value) {
showConfirmDialog.value = true
countdown.value = 10
if (countdownTimer) clearInterval(countdownTimer)
countdownTimer = setInterval(() => {
countdown.value--
if (countdown.value <= 0) {
clearInterval(countdownTimer!)
countdownTimer = null
}
}, 1000)
return
}
await doStartNewSession() await doStartNewSession()
} }
@ -950,12 +978,6 @@ const joinActiveSession = async () => {
} finally { btnLoading.value = false } } finally { btnLoading.value = false }
} }
// 弹窗确认后开启新一轮盘点(不再删除任何数据,故不叫 confirmClear
const confirmStartNew = () => {
if (countdown.value > 0) return
doStartNewSession()
}
const cancelConfirm = () => { const cancelConfirm = () => {
showConfirmDialog.value = false showConfirmDialog.value = false
if (countdownTimer) { if (countdownTimer) {
@ -1560,6 +1582,12 @@ const goToVarianceReview = () => {
font-weight: bold; font-weight: bold;
margin: 0 !important; margin: 0 !important;
} }
/* 主按钮:平板大屏上要一眼可辨、一按即中,故比常规按钮再放大一档 */
.action-btn-hero {
height: 66px;
font-size: 19px;
letter-spacing: 1px;
}
.sub-text { font-size: 12px; opacity: 0.8; margin-left: 5px; } .sub-text { font-size: 12px; opacity: 0.8; margin-left: 5px; }
/* ★ 公司选择器:多人协同的隔离维度 */ /* ★ 公司选择器:多人协同的隔离维度 */