feat(scan): 出库/借库扫码增加未扫清单弹窗
- 扫码进度条旁新增「未扫清单 (N)」按钮(有未扫满物料时显示) - 弹窗列出计划中未扫满的物料:名称/规格/计划数量/已扫数量/待扫数量 - 提供「去扫码」快捷跳转,方便补扫漏掉的物料 - 未扫满 = 计划数量 > 已扫数量(含完全未扫和扫了一部分的情况)
This commit is contained in:
@ -80,6 +80,13 @@
|
|||||||
<span>扫码进度</span>
|
<span>扫码进度</span>
|
||||||
<el-tag type="success" size="small">{{ scanScannedTypes }}/{{ scanTotalTypes }} 种</el-tag>
|
<el-tag type="success" size="small">{{ scanScannedTypes }}/{{ scanTotalTypes }} 种</el-tag>
|
||||||
<el-tag type="primary" size="small">{{ scanScannedQty }}/{{ scanTotalQty }} 件</el-tag>
|
<el-tag type="primary" size="small">{{ scanScannedQty }}/{{ scanTotalQty }} 件</el-tag>
|
||||||
|
<el-button
|
||||||
|
v-if="unscannedCount > 0"
|
||||||
|
type="warning" plain size="small" style="margin-left: auto;"
|
||||||
|
@click="showUnscannedDialog = true"
|
||||||
|
>
|
||||||
|
未扫清单 ({{ unscannedCount }})
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-progress
|
<el-progress
|
||||||
:percentage="scanTotalQty > 0 ? Math.min(100, Math.round(scanScannedQty / scanTotalQty * 100)) : 0"
|
:percentage="scanTotalQty > 0 ? Math.min(100, Math.round(scanScannedQty / scanTotalQty * 100)) : 0"
|
||||||
@ -255,6 +262,37 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- ★ 未扫清单弹窗 -->
|
||||||
|
<el-dialog v-model="showUnscannedDialog" title="未扫清单" width="600px" destroy-on-close>
|
||||||
|
<el-alert
|
||||||
|
v-if="unscannedList.length > 0"
|
||||||
|
:title="`以下 ${unscannedList.length} 种物料还未扫满,请补扫:`"
|
||||||
|
type="warning" :closable="false" show-icon style="margin-bottom: 12px;"
|
||||||
|
/>
|
||||||
|
<el-table :data="unscannedList" border size="small" max-height="400">
|
||||||
|
<el-table-column type="index" label="#" width="40" align="center" />
|
||||||
|
<el-table-column prop="name" label="物料名称" min-width="140" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="spec" label="规格型号" min-width="120" show-overflow-tooltip />
|
||||||
|
<el-table-column label="计划" width="70" align="center">
|
||||||
|
<template #default="{ row }">{{ row.planQty }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="已扫" width="70" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span style="color: #67C23A;">{{ row.scannedQty }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="待扫" width="70" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span style="color: #F56C6C; font-weight: bold;">{{ row.remaining }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="showUnscannedDialog = false">关闭</el-button>
|
||||||
|
<el-button type="primary" @click="showUnscannedDialog = false; showCamera = true">去扫码</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog
|
<el-dialog
|
||||||
v-model="showSignatureDialog"
|
v-model="showSignatureDialog"
|
||||||
fullscreen
|
fullscreen
|
||||||
@ -375,6 +413,31 @@ const scanScannedQty = computed(() =>
|
|||||||
const scanScannedTypes = computed(() => cartItems.value.length)
|
const scanScannedTypes = computed(() => cartItems.value.length)
|
||||||
const scanTotalTypes = computed(() => plannedItems.value.length)
|
const scanTotalTypes = computed(() => plannedItems.value.length)
|
||||||
|
|
||||||
|
// ★ 未扫清单:计划中还没扫满的物料
|
||||||
|
const unscannedList = computed(() => {
|
||||||
|
return plannedItems.value.map(plan => {
|
||||||
|
const planQty = Number(plan.quantity) || 0
|
||||||
|
// 已扫数量(按名称+规格匹配)
|
||||||
|
const scannedQty = cartItems.value
|
||||||
|
.filter(ci => {
|
||||||
|
const ciName = (ci.name || '').trim()
|
||||||
|
const ciSpec = (ci.spec_model || ci.standard || '').trim()
|
||||||
|
return ciName === (plan.name || '').trim() &&
|
||||||
|
ciSpec === (plan.spec_model || '').trim()
|
||||||
|
})
|
||||||
|
.reduce((sum, ci) => sum + (Number(ci.out_quantity) || 0), 0)
|
||||||
|
return {
|
||||||
|
name: plan.name || '',
|
||||||
|
spec: plan.spec_model || '',
|
||||||
|
planQty,
|
||||||
|
scannedQty,
|
||||||
|
remaining: Math.max(0, planQty - scannedQty)
|
||||||
|
}
|
||||||
|
}).filter(item => item.remaining > 0) // 只保留未扫满的
|
||||||
|
})
|
||||||
|
const unscannedCount = computed(() => unscannedList.value.length)
|
||||||
|
const showUnscannedDialog = ref(false)
|
||||||
|
|
||||||
// ★ 加载已审批通过的申请单
|
// ★ 加载已审批通过的申请单
|
||||||
const loadApprovalRequests = async () => {
|
const loadApprovalRequests = async () => {
|
||||||
requestsLoading.value = true
|
requestsLoading.value = true
|
||||||
|
|||||||
@ -71,6 +71,13 @@
|
|||||||
<span>扫码进度</span>
|
<span>扫码进度</span>
|
||||||
<el-tag type="success" size="small">{{ scanScannedTypes }}/{{ scanTotalTypes }} 种</el-tag>
|
<el-tag type="success" size="small">{{ scanScannedTypes }}/{{ scanTotalTypes }} 种</el-tag>
|
||||||
<el-tag type="primary" size="small">{{ scanScannedQty }}/{{ scanTotalQty }} 件</el-tag>
|
<el-tag type="primary" size="small">{{ scanScannedQty }}/{{ scanTotalQty }} 件</el-tag>
|
||||||
|
<el-button
|
||||||
|
v-if="unscannedCount > 0"
|
||||||
|
type="warning" plain size="small" style="margin-left: auto;"
|
||||||
|
@click="showUnscannedDialog = true"
|
||||||
|
>
|
||||||
|
未扫清单 ({{ unscannedCount }})
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-progress
|
<el-progress
|
||||||
:percentage="scanTotalQty > 0 ? Math.min(100, Math.round(scanScannedQty / scanTotalQty * 100)) : 0"
|
:percentage="scanTotalQty > 0 ? Math.min(100, Math.round(scanScannedQty / scanTotalQty * 100)) : 0"
|
||||||
@ -239,6 +246,37 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- ★ 未扫清单弹窗 -->
|
||||||
|
<el-dialog v-model="showUnscannedDialog" title="未扫清单" width="600px" destroy-on-close>
|
||||||
|
<el-alert
|
||||||
|
v-if="unscannedList.length > 0"
|
||||||
|
:title="`以下 ${unscannedList.length} 种物料还未扫满,请补扫:`"
|
||||||
|
type="warning" :closable="false" show-icon style="margin-bottom: 12px;"
|
||||||
|
/>
|
||||||
|
<el-table :data="unscannedList" border size="small" max-height="400">
|
||||||
|
<el-table-column type="index" label="#" width="40" align="center" />
|
||||||
|
<el-table-column prop="name" label="物料名称" min-width="140" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="spec" label="规格型号" min-width="120" show-overflow-tooltip />
|
||||||
|
<el-table-column label="计划" width="70" align="center">
|
||||||
|
<template #default="{ row }">{{ row.planQty }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="已扫" width="70" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span style="color: #67C23A;">{{ row.scannedQty }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="待扫" width="70" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span style="color: #F56C6C; font-weight: bold;">{{ row.remaining }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="showUnscannedDialog = false">关闭</el-button>
|
||||||
|
<el-button type="primary" @click="showUnscannedDialog = false; showCamera = true">去扫码</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog
|
<el-dialog
|
||||||
v-model="showSignatureDialog"
|
v-model="showSignatureDialog"
|
||||||
fullscreen
|
fullscreen
|
||||||
@ -340,6 +378,31 @@ const scanScannedQty = computed(() =>
|
|||||||
const scanScannedTypes = computed(() => cartItems.value.length)
|
const scanScannedTypes = computed(() => cartItems.value.length)
|
||||||
const scanTotalTypes = computed(() => plannedItems.value.length)
|
const scanTotalTypes = computed(() => plannedItems.value.length)
|
||||||
|
|
||||||
|
// ★ 未扫清单:计划中还没扫满的物料
|
||||||
|
const unscannedList = computed(() => {
|
||||||
|
return plannedItems.value.map(plan => {
|
||||||
|
const planQty = Number(plan.quantity) || 0
|
||||||
|
// 已扫数量(按名称+规格匹配)
|
||||||
|
const scannedQty = cartItems.value
|
||||||
|
.filter(ci => {
|
||||||
|
const ciName = (ci.name || '').trim()
|
||||||
|
const ciSpec = (ci.spec_model || ci.standard || '').trim()
|
||||||
|
return ciName === (plan.name || '').trim() &&
|
||||||
|
ciSpec === (plan.spec_model || '').trim()
|
||||||
|
})
|
||||||
|
.reduce((sum, ci) => sum + (Number(ci.out_quantity) || 0), 0)
|
||||||
|
return {
|
||||||
|
name: plan.name || '',
|
||||||
|
spec: plan.spec_model || '',
|
||||||
|
planQty,
|
||||||
|
scannedQty,
|
||||||
|
remaining: Math.max(0, planQty - scannedQty)
|
||||||
|
}
|
||||||
|
}).filter(item => item.remaining > 0) // 只保留未扫满的
|
||||||
|
})
|
||||||
|
const unscannedCount = computed(() => unscannedList.value.length)
|
||||||
|
const showUnscannedDialog = ref(false)
|
||||||
|
|
||||||
// ★ 加载已通过审批的借库申请单列表
|
// ★ 加载已通过审批的借库申请单列表
|
||||||
const loadApprovalRequests = async () => {
|
const loadApprovalRequests = async () => {
|
||||||
requestsLoading.value = true
|
requestsLoading.value = true
|
||||||
|
|||||||
Reference in New Issue
Block a user