新增打印多张标签纸的功能

This commit is contained in:
dxc
2026-02-24 14:33:43 +08:00
parent 853374de5d
commit d1ab5f1100

View File

@ -1,3 +1,4 @@
inventory-web/src/views/stock/inbound/buy.vue
<template> <template>
<div class="buy-module"> <div class="buy-module">
<div class="header-container"> <div class="header-container">
@ -315,6 +316,13 @@
<el-input-number v-model="form.in_quantity" :min="1" controls-position="right" style="width:100%" class="strong-input"/> <el-input-number v-model="form.in_quantity" :min="1" controls-position="right" style="width:100%" class="strong-input"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6" v-if="dialogStatus === 'create'">
<el-form-item label="打印份数" prop="print_copies">
<el-input-number v-model="form.print_copies" :min="1" :max="999" controls-position="right" style="width:100%"/>
</el-form-item>
</el-col>
<template v-if="dialogStatus === 'update'"> <template v-if="dialogStatus === 'update'">
<el-col :span="6"><el-form-item label="当前库存" prop="stock_quantity"><el-input-number v-model="form.stock_quantity" disabled style="width:100%" :controls="false"/></el-form-item></el-col> <el-col :span="6"><el-form-item label="当前库存" prop="stock_quantity"><el-input-number v-model="form.stock_quantity" disabled style="width:100%" :controls="false"/></el-form-item></el-col>
<el-col :span="6"><el-form-item label="当前可用" prop="available_quantity"><el-input-number v-model="form.available_quantity" disabled style="width:100%" :controls="false"/></el-form-item></el-col> <el-col :span="6"><el-form-item label="当前可用" prop="available_quantity"><el-input-number v-model="form.available_quantity" disabled style="width:100%" :controls="false"/></el-form-item></el-col>
@ -495,7 +503,16 @@
<img v-if="previewUrl" :src="previewUrl" alt="Label Preview" style="width: 100%; border: 1px solid #ccc;"/> <img v-if="previewUrl" :src="previewUrl" alt="Label Preview" style="width: 100%; border: 1px solid #ccc;"/>
<div v-else class="empty-preview">正在生成预览...</div> <div v-else class="empty-preview">正在生成预览...</div>
</div> </div>
<div style="margin-top: 20px; font-size: 14px; color: #666;"><p>打印机 IP: 192.168.9.205</p><p>尺寸: 40mm x 30mm</p></div> <div style="margin-top: 20px; font-size: 14px; color: #666;">
<p>打印机 IP: 192.168.9.205</p>
<p>尺寸: 40mm x 30mm</p>
<div style="margin-top: 15px; display: flex; align-items: center; justify-content: center; gap: 10px;">
<span style="font-weight: bold; color: #303133;">打印份数:</span>
<el-input-number v-model="printCopies" :min="1" :max="100" size="default" style="width: 120px;" />
</div>
</div>
</div> </div>
<template #footer> <template #footer>
<div class="dialog-footer"><el-button @click="printVisible = false">取消</el-button><el-button type="primary" :loading="printing" @click="confirmPrint"><el-icon><Printer/></el-icon>确认打印</el-button></div> <div class="dialog-footer"><el-button @click="printVisible = false">取消</el-button><el-button type="primary" :loading="printing" @click="confirmPrint"><el-icon><Printer/></el-icon>确认打印</el-button></div>
@ -521,7 +538,7 @@ import {
getUserSuggestions, getUserSuggestions,
getLinkSuggestions, getLinkSuggestions,
getLocationSuggestions, getLocationSuggestions,
getFilterOptions // 新增引入 getFilterOptions
} from '@/api/inbound/buy' } from '@/api/inbound/buy'
import {getLabelPreview, executePrint} from '@/api/common/print' import {getLabelPreview, executePrint} from '@/api/common/print'
import WebRtcCamera from '@/components/Camera/WebRtcCamera.vue' import WebRtcCamera from '@/components/Camera/WebRtcCamera.vue'
@ -582,6 +599,8 @@ const printLoading = ref(false)
const printing = ref(false) const printing = ref(false)
const previewUrl = ref('') const previewUrl = ref('')
const currentPrintData = ref<any>({}) const currentPrintData = ref<any>({})
const printCopies = ref(1) // [新增] 打印份数状态
const entryMode = ref('batch') const entryMode = ref('batch')
const modeLocked = ref(false) const modeLocked = ref(false)
const dialogImageUrl = ref('') const dialogImageUrl = ref('')
@ -645,7 +664,8 @@ const form = reactive({
in_quantity: 1, stock_quantity: 1, available_quantity: 1, warehouse_location: '', in_quantity: 1, stock_quantity: 1, available_quantity: 1, warehouse_location: '',
unit_price: 0, total_price: 0, currency: 'CNY', exchange_rate: 1.00, unit_price: 0, total_price: 0, currency: 'CNY', exchange_rate: 1.00,
supplier_name: '', purchaser: '', purchaser_email: '', source_link: '', detail_link: '', supplier_name: '', purchaser: '', purchaser_email: '', source_link: '', detail_link: '',
arrival_photo: [] as string[], inspection_report: [] as string[] arrival_photo: [] as string[], inspection_report: [] as string[],
print_copies: 1 // [新增] 入库时的打印份数
}) })
@ -917,6 +937,7 @@ const submitForm = async () => {
if (inspection_report_url.value && !finalReportList.includes(inspection_report_url.value)) finalReportList.push(inspection_report_url.value) if (inspection_report_url.value && !finalReportList.includes(inspection_report_url.value)) finalReportList.push(inspection_report_url.value)
const onlyImages = finalReportList.filter(item => !isExternalLink(item)) const onlyImages = finalReportList.filter(item => !isExternalLink(item))
if (inspection_report_url.value) onlyImages.push(inspection_report_url.value) if (inspection_report_url.value) onlyImages.push(inspection_report_url.value)
// 注意:这里不要把 print_copies 发送到后端,除非后端有接收字段。通常打印是前端行为。
const payload = { ...form, inspection_report: onlyImages, in_quantity: Number(form.in_quantity), unit_price: Number(form.unit_price) } const payload = { ...form, inspection_report: onlyImages, in_quantity: Number(form.in_quantity), unit_price: Number(form.unit_price) }
try { try {
if (dialogStatus.value === 'create') { if (dialogStatus.value === 'create') {
@ -924,7 +945,11 @@ const submitForm = async () => {
ElMessage.success('入库成功') ElMessage.success('入库成功')
if (res.data) { if (res.data) {
ElMessage.info('发送打印指令...') ElMessage.info('发送打印指令...')
try { await executePrint(res.data); ElMessage.success('打印指令已发送') } try {
// [修改] 传递用户选择的打印份数而不是默认的1份
await executePrint({ ...res.data, copies: form.print_copies });
ElMessage.success(`打印指令已发送 (x${form.print_copies})`)
}
catch (printErr: any) { ElMessage.warning('打印失败:' + (printErr.msg || '未知错误')) } catch (printErr: any) { ElMessage.warning('打印失败:' + (printErr.msg || '未知错误')) }
} }
} else { await updateBuyInbound(form.id!, payload); ElMessage.success('更新成功') } } else { await updateBuyInbound(form.id!, payload); ElMessage.success('更新成功') }
@ -1044,17 +1069,42 @@ const handleCameraConfirm = async (file: File) => {
} }
const handleDelete = async (row: any) => { try { await deleteBuyInbound(row.id); ElMessage.success('删除成功'); fetchData() } catch (e) { ElMessage.error('删除失败') } } const handleDelete = async (row: any) => { try { await deleteBuyInbound(row.id); ElMessage.success('删除成功'); fetchData() } catch (e) { ElMessage.error('删除失败') } }
// ------------------------------------
// 打印逻辑
// ------------------------------------
const handlePrint = async (row: any) => { const handlePrint = async (row: any) => {
printVisible.value = true; printLoading.value = true; previewUrl.value = '' printVisible.value = true;
printLoading.value = true;
previewUrl.value = '';
printCopies.value = 1; // [新增] 每次打开打印弹窗重置为1份
currentPrintData.value = { global_print_id: row.global_print_id, material_name: row.material_name, spec_model: row.spec_model, category: row.category, material_type: row.material_type, warehouse_loc: row.warehouse_loc, serial_number: row.serial_number, batch_number: row.batch_number, sku: row.sku } currentPrintData.value = { global_print_id: row.global_print_id, material_name: row.material_name, spec_model: row.spec_model, category: row.category, material_type: row.material_type, warehouse_loc: row.warehouse_loc, serial_number: row.serial_number, batch_number: row.batch_number, sku: row.sku }
try { const res: any = await getLabelPreview(currentPrintData.value); previewUrl.value = res.data } try { const res: any = await getLabelPreview(currentPrintData.value); previewUrl.value = res.data }
catch (e) { ElMessage.error('预览失败') } finally { printLoading.value = false } catch (e) { ElMessage.error('预览失败') } finally { printLoading.value = false }
} }
const confirmPrint = async () => { printing.value = true; try { await executePrint(currentPrintData.value); ElMessage.success('指令已发送'); printVisible.value = false } catch (e: any) { ElMessage.error(e.msg || '打印失败') } finally { printing.value = false } }
const confirmPrint = async () => {
printing.value = true;
try {
// [修改] 将份数合并到打印数据中发送
await executePrint({ ...currentPrintData.value, copies: printCopies.value });
ElMessage.success('指令已发送');
printVisible.value = false
} catch (e: any) {
ElMessage.error(e.msg || '打印失败')
} finally {
printing.value = false
}
}
const resetForm = () => { const resetForm = () => {
materialOptions.value = []; arrivalFileList.value = []; reportFileList.value = []; inspection_report_url.value = '' materialOptions.value = []; arrivalFileList.value = []; reportFileList.value = []; inspection_report_url.value = ''
searchPage.value = 1; hasNextPage.value = true; searchKeyword.value = ''; searchPage.value = 1; hasNextPage.value = true; searchKeyword.value = '';
Object.assign(form, { id: undefined, base_id: undefined, material_name: '', spec_model: '', category: '', unit: '', material_type: '', sku: '', barcode: '', in_date: '', serial_number: '', batch_number: '', status: '在库', inspection_status: '未检', in_quantity: 1, stock_quantity: 1, available_quantity: 1, warehouse_location: '', unit_price: 0, total_price: 0, currency: 'CNY', exchange_rate: 1.00, supplier_name: '', purchaser: '', purchaser_email: '', source_link: '', detail_link: '', arrival_photo: [], inspection_report: [] }) Object.assign(form, {
id: undefined, base_id: undefined, material_name: '', spec_model: '', category: '', unit: '', material_type: '', sku: '', barcode: '', in_date: '', serial_number: '', batch_number: '', status: '在库', inspection_status: '未检', in_quantity: 1, stock_quantity: 1, available_quantity: 1, warehouse_location: '', unit_price: 0, total_price: 0, currency: 'CNY', exchange_rate: 1.00, supplier_name: '', purchaser: '', purchaser_email: '', source_link: '', detail_link: '', arrival_photo: [], inspection_report: [],
print_copies: 1 // [新增] 重置时恢复为1
})
} }
const getStatusType = (status: string) => { const map: any = {'在库': 'success', '出库': 'info', '损耗': 'danger'}; return map[status] || 'warning' } const getStatusType = (status: string) => { const map: any = {'在库': 'success', '出库': 'info', '损耗': 'danger'}; return map[status] || 'warning' }
const formatMoney = (val: any, currency = '¥') => { const num = Number(val); return isNaN(num) ? '-' : `${currency} ${num.toFixed(2)}` } const formatMoney = (val: any, currency = '¥') => { const num = Number(val); return isNaN(num) ? '-' : `${currency} ${num.toFixed(2)}` }