56 lines
2.9 KiB
Vue
56 lines
2.9 KiB
Vue
<script setup lang="ts">
|
||
import { onBeforeUnmount, ref, watch } from 'vue'
|
||
import { ElMessage } from 'element-plus'
|
||
import { getChargeableWeights, confirmChargeableWeight, type ChargeableWeight } from '../api/chargeableWeights'
|
||
const props = defineProps<{ orderId: string; canConfirm: boolean }>()
|
||
const emit = defineEmits<{ close: []; confirmed: [] }>()
|
||
const rows = ref<ChargeableWeight[]>([])
|
||
const loading = ref(false)
|
||
const saving = ref('')
|
||
const error = ref('')
|
||
const commands = new Map<string, string>()
|
||
let sequence = 0
|
||
let confirmationSequence = 0
|
||
async function load() {
|
||
const ticket = ++sequence
|
||
loading.value = true; error.value = ''; rows.value = []
|
||
try { const data = await getChargeableWeights(props.orderId); if (ticket === sequence) rows.value = data }
|
||
catch (e) { if (ticket === sequence) error.value = e instanceof Error ? e.message : '计费重加载失败' }
|
||
finally { if (ticket === sequence) loading.value = false }
|
||
}
|
||
async function confirm(row: ChargeableWeight) {
|
||
if (saving.value || !props.canConfirm) return
|
||
const ticket = sequence
|
||
const attempt = ++confirmationSequence
|
||
const fingerprint = `${row.inboundId}:${row.fingerprint}`
|
||
const key = commands.get(fingerprint) ?? `weight-${crypto.randomUUID()}`
|
||
commands.set(fingerprint, key); saving.value = row.inboundId; error.value = ''
|
||
try {
|
||
await confirmChargeableWeight(row, key)
|
||
if (ticket !== sequence) return
|
||
ElMessage.success('计费重已确认'); emit('confirmed'); await load()
|
||
} catch (e) { if (ticket === sequence) error.value = e instanceof Error ? e.message : '确认失败,请刷新后重试' }
|
||
finally { if (attempt === confirmationSequence) saving.value = '' }
|
||
}
|
||
watch(() => props.orderId, () => { confirmationSequence++; saving.value = ''; commands.clear(); void load() }, { immediate: true })
|
||
onBeforeUnmount(() => { sequence++; confirmationSequence++ })
|
||
</script>
|
||
<template>
|
||
<el-dialog :model-value="true" title="确认计费重" width="560px" :close-on-click-modal="false" @close="emit('close')">
|
||
<el-alert v-if="error" :title="error" type="error" :closable="false" />
|
||
<el-button v-if="error" :disabled="!!saving" @click="load">重新加载</el-button>
|
||
<div v-loading="loading">
|
||
<el-empty v-if="!loading && !error && !rows.length" description="暂无已审核的计费重" />
|
||
<div v-for="row in rows" :key="row.inboundId" class="weight-row">
|
||
<span>来源入仓单:{{ row.inboundId }}<br>计费重:{{ row.chargeableWeightKg }} kg</span>
|
||
<el-tag v-if="row.confirmed" type="success">已确认</el-tag>
|
||
<el-button v-else-if="canConfirm" type="primary" :disabled="!!saving" :loading="saving === row.inboundId" @click="confirm(row)">确认计费重</el-button>
|
||
<span v-else>待确认</span>
|
||
</div>
|
||
</div>
|
||
</el-dialog>
|
||
</template>
|
||
<style scoped>
|
||
.weight-row { display: flex; justify-content: space-between; align-items: center; gap: 16px; padding: 12px 0; }
|
||
</style>
|