fix(borrow): 转交弹窗文案纠偏 + 表头一键全选

一、修掉弹窗内的过期文案(与「按件转交」自相矛盾)
----
顶部 Alert 仍写着上一版「整单转交」的描述,而下方的交互早已改为按件勾选。
现按业务方给的文案改为:
  标题:「按件转交,对方确认后责任正式转移」
  描述:「发起后将生成「待接收」记录,对方在系统中确认接收前,物品仍挂在您的名下。」
同时修掉同处一处过期注释(「整单转交 + 双向握手」)。

二、勾选改用 Element Plus 标准 selection 列
----
原先逐行手写 el-checkbox + computed 收集,**没有表头全选**。现改用
<el-table-column type="selection" width="55" :selectable="..." />:
· 表头自带一键全选 / 取消全选;
· selectable 钩子把「已有待接收」的明细排除在可选之外 ——
  表头全选也会自动跳过它们,不会出现「整列勾上却提交失败」;
· 选中状态交由 el-table 内部托管(@selection-change),不再与数据源字段
  两套并存导致不同步。

★ 预选通过表格 API(toggleRowSelection)在 nextTick 后写入,不直接改数据源:
  弹窗是 destroy-on-close,每次打开表格都是新建的,故每次都要重新预选。
This commit is contained in:
yueli
2026-09-17 10:17:48 +08:00
parent 1bb3f59bb7
commit 5f0cdc3adb

View File

@ -362,11 +362,11 @@
</template>
</el-dialog>
<!-- 借库转交弹窗整单转交 + 双向握手 -->
<!-- 借库转交弹窗按件转交 + 双向握手主行/明细行共用 -->
<el-dialog v-model="transferDialogVisible" title="发起借库转交" width="640px" destroy-on-close>
<el-alert
title="整单转交,且需对方确认后责任转移"
description="发起后生成一条「待接收」记录,东西仍在您手上、责任仍归您;对方在其借用列表中确认接收后,本单全部未还物品的持有责任才整体转移给他。"
title="按件转交,对方确认后责任正式转移"
description="发起后生成「待接收」记录,对方在系统中确认接收前,物品仍挂在您的名下。"
type="warning"
:closable="false"
show-icon
@ -379,12 +379,19 @@
转交粒度是<strong>单件物品</strong>可以只转其中一件
</div>
</div>
<el-table :data="transferCandidates" border size="small" max-height="240">
<el-table-column width="46" align="center">
<template #default="{row}">
<el-checkbox v-model="row.selected" :disabled="row.disabled" />
</template>
</el-table-column>
<!-- Element Plus 标准的 selection 自带表头全选 / 取消全选
比逐行 checkbox 多出一键操作能力已有待接收的明细由 selectable
钩子置为不可选表头全选也会自动跳过它们 -->
<el-table
ref="transferTableRef"
:data="transferCandidates"
border
size="small"
max-height="240"
row-key="id"
@selection-change="handleTransferSelectionChange"
>
<el-table-column type="selection" width="55" :selectable="transferSelectable" />
<el-table-column prop="material_name" label="物料名称" min-width="130" show-overflow-tooltip />
<el-table-column prop="sku" label="SKU" width="110" show-overflow-tooltip />
<el-table-column label="状态" width="100" align="center">
@ -481,7 +488,7 @@
</template>
<script setup lang="ts">
import { ref, computed, onMounted, onBeforeUnmount } from 'vue'
import { ref, computed, nextTick, onMounted, onBeforeUnmount } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import request from '@/utils/request'
import dayjs from 'dayjs'
@ -756,10 +763,20 @@ const transferToUserId = ref<number | null>(null)
const transferRemark = ref('')
const transferUsers = ref<Array<{ id: number; name: string }>>([])
// 弹窗内勾选的明细(默认全选可转交项)
const transferSelected = computed(() =>
transferCandidates.value.filter((c: any) => c.selected)
)
// 弹窗内勾选的明细由 el-table 的 selection 机制托管(含表头一键全选)。
// ★ 不用逐行 checkbox + computed那样拿不到「全选」能力且选中状态与
// 表格内部状态两套并存,容易不同步。
const transferTableRef = ref<any>(null)
const transferSelected = ref<any[]>([])
const handleTransferSelectionChange = (rows: any[]) => {
transferSelected.value = rows
}
// 已有待接收的明细不可再发起(后端也会拒)—— 置为不可选,
// 表头「全选」会自动跳过它们,不会出现整列勾上却提交失败的情况。
const transferSelectable = (row: any) => !row.disabled
// 已勾选项的待还合计
const transferTotalQty = computed(() =>
transferSelected.value.reduce((s: number, c: any) => s + (Number(c.pending_quantity) || 0), 0)
@ -792,23 +809,35 @@ const loadTransferUsers = async () => {
* ★ 转交粒度已下沉到明细行:一张单可以只转其中一件(借 2 件转 1 件),
* 故这里用勾选而非「整单」。
*/
const openTransferDialog = (row: any, detail?: any) => {
const openTransferDialog = async (row: any, detail?: any) => {
const candidates = (row.children || []).filter((c: any) => (c.pending_quantity || 0) > 0)
if (!candidates.length) {
ElMessage.warning('该单号下没有未归还的明细,无法转交')
return
}
transferBorrowNo.value = row.borrow_no
// 已有待接收的明细不可再发起(后端也会拒)——直接置灰,避免用户白填一遍
transferCandidates.value = candidates.map((c: any) => ({
...c,
selected: detail ? c.id === detail.id : !c.pending_transfer,
// 预选标记:从明细行进入只预选该件,从主行进入预选全部可转交项
_preselect: detail ? c.id === detail.id : !c.pending_transfer,
disabled: !!c.pending_transfer,
}))
transferToUserId.value = null
transferRemark.value = ''
transferSelected.value = []
transferDialogVisible.value = true
loadTransferUsers()
// ★ 等表格渲染完再落预选selection 状态由 el-table 内部持有,
// 必须通过它的 APItoggleRowSelection不能改数据源字段。
// 弹窗是 destroy-on-close每次打开表格都是新建的故每次都要重新预选。
await nextTick()
const tbl = transferTableRef.value
if (!tbl) return
tbl.clearSelection()
transferCandidates.value.forEach((c: any) => {
if (c._preselect) tbl.toggleRowSelection(c, true)
})
}
const confirmTransfer = async () => {