Files
admin-web/src/modules/loading-lists/components/PalletLabelPrintDialog.vue
T

66 lines
4.8 KiB
Vue
Raw Normal View History

2026-09-09 17:27:00 +08:00
<script setup lang="ts">
import { computed, ref } from 'vue'
import { Printer } from '@lucide/vue'
import { ElMessage } from 'element-plus'
import AppDialog from '@/shared/components/AppDialog.vue'
import LoadErrorState from '@/shared/components/LoadErrorState.vue'
import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
import { preparePalletLabels, printPalletLabels, type PalletLabelManifest } from '../api/platformLoadingLists'
const props = defineProps<{ planId: string; warehouseId: string; disabled?: boolean }>()
const open = ref(false)
const loading = ref(false)
const printing = ref(false)
const error = ref<ApiErrorDetails | null>(null)
const manifest = ref<PalletLabelManifest | null>(null)
const scope = ref<'ALL' | 'WAREHOUSE'>('ALL')
const warehouseCode = ref('')
const count = ref(1)
const selectedGroup = computed(() => manifest.value?.groups.find((group) => group.destinationWarehouseCode === warehouseCode.value) || null)
const disabledConfirm = computed(() => !manifest.value?.totalCount || (scope.value === 'WAREHOUSE' && (!selectedGroup.value || count.value < 1 || count.value > selectedGroup.value.totalCount)))
async function show() {
open.value = true; loading.value = true; error.value = null; manifest.value = null
try {
manifest.value = await preparePalletLabels(props.planId, props.warehouseId)
warehouseCode.value = manifest.value.groups[0]?.destinationWarehouseCode || ''
count.value = manifest.value.groups[0]?.totalCount || 1
} catch (cause) { error.value = getApiErrorDetails(cause, '托盘码清单加载失败') }
finally { loading.value = false }
}
function onWarehouseChange() { count.value = selectedGroup.value?.totalCount || 1 }
async function print() {
if (!manifest.value) return
printing.value = true; error.value = null
try {
const blob = await printPalletLabels(props.planId, props.warehouseId,
scope.value === 'WAREHOUSE' ? warehouseCode.value : undefined,
scope.value === 'WAREHOUSE' ? count.value : undefined)
const url = URL.createObjectURL(blob); const anchor = document.createElement('a')
anchor.href = url; anchor.download = `${manifest.value.containerNo}-托盘码.pdf`; anchor.click(); URL.revokeObjectURL(url)
ElMessage.success(`已生成 ${scope.value === 'ALL' ? manifest.value.totalCount : count.value} 张托盘码`)
} catch (cause) { error.value = getApiErrorDetails(cause, '托盘码打印失败') }
finally { printing.value = false }
}
</script>
<template>
<el-button :disabled="disabled" @click="show"><Printer :size="16" />打印托盘码</el-button>
<AppDialog v-model="open" title="散货托盘码" width="min(760px, calc(100vw - 28px))" confirm-text="生成 PDF" :loading="loading" :confirm-loading="printing" :confirm-disabled="disabledConfirm" @confirm="print">
<LoadErrorState v-if="error" compact title="托盘码操作失败" :message="error.message" :show-retry="false" />
<template v-if="manifest">
<el-alert type="info" :closable="false" :title="`编号规则:${manifest.containerNo}-FBA地址内部编号-三位序号;一件代发托盘不在此清单。`" />
2026-09-09 17:27:00 +08:00
<el-radio-group v-model="scope" class="print-scope"><el-radio value="ALL">全部打印({{ manifest.totalCount }} 张)</el-radio><el-radio value="WAREHOUSE">按 FBA 仓补打</el-radio></el-radio-group>
<div v-if="scope === 'WAREHOUSE'" class="print-options"><el-select v-model="warehouseCode" placeholder="选择 FBA 仓" @change="onWarehouseChange"><el-option v-for="group in manifest.groups" :key="group.destinationWarehouseCode" :label="`${group.destinationWarehouseCode} · ${group.totalCount} 张`" :value="group.destinationWarehouseCode" /></el-select><el-input-number v-model="count" placeholder="打印张数" :min="1" :max="selectedGroup?.totalCount || 1" /><span>张(从该仓第 1 张起)</span></div>
<el-table :data="manifest.groups" border max-height="300"><el-table-column label="FBA 仓编码" prop="destinationWarehouseCode" width="140" /><el-table-column label="内部编号" prop="destinationWarehouseInternalCode" width="120" /><el-table-column label="FBA 仓名称" prop="destinationWarehouseName" min-width="160"><template #default="{ row }">{{ row.destinationWarehouseName || '—' }}</template></el-table-column><el-table-column label="托盘数" prop="totalCount" width="90" align="right" /><el-table-column label="编号范围" min-width="230"><template #default="{ row }">{{ row.labels[0]?.palletCode || '—' }}<template v-if="row.labels.length > 1"> ~ {{ row.labels[row.labels.length - 1]?.palletCode }}</template></template></el-table-column></el-table>
2026-09-09 17:27:00 +08:00
</template>
</AppDialog>
</template>
<style scoped>
.print-scope { display:flex; margin:18px 0 12px; }
.print-options { display:flex; align-items:center; gap:12px; margin-bottom:16px; }
.print-options .el-select { width:240px; }
</style>