云
2 小时以前 7a93a85f75bcfc8001ea1d3b921860806a8209ac
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<script setup lang="ts">
import type { TraceResult } from '#/utils/traceLookup';
 
import { computed, ref } from 'vue';
 
import { Button } from 'ant-design-vue';
 
import { lookupTrace } from '#/utils/traceLookup';
 
import TraceScanInput from './TraceScanInput.vue';
 
/**
 * 追溯二维码扫码核对面板。
 *
 * 扫码后只解析对象并展示核对信息,点击「确认带入」才由页面执行写入。
 */
const props = withDefaults(
  defineProps<{
    disabled?: boolean;
    title?: string;
  }>(),
  {
    disabled: false,
    title: '扫码带出',
  },
);
 
const emit = defineEmits<{ confirm: [trace: TraceResult] }>();
 
const busy = ref(false);
const error = ref('');
const trace = ref<TraceResult>();
 
const typeLabel = computed(() =>
  trace.value
    ? ({ bag: '袋码', batch: '批次码', pallet: '托盘码' } as const)[
        trace.value.type
      ]
    : '',
);
 
const quantity = computed(() => {
  if (!trace.value) return '';
  if (trace.value.type === 'bag') return '1';
  if (trace.value.type === 'pallet') return trace.value.data.bagCount ?? '';
  return trace.value.data.bagQuantity ?? '';
});
 
async function identify(code: string) {
  if (props.disabled || busy.value) return;
  busy.value = true;
  error.value = '';
  trace.value = undefined;
  try {
    trace.value = await lookupTrace(code);
  } catch (e) {
    error.value = e instanceof Error ? e.message : '追溯码识别失败';
  } finally {
    busy.value = false;
  }
}
 
function confirm() {
  if (!trace.value) return;
  emit('confirm', trace.value);
  trace.value = undefined;
}
 
function cancel() {
  trace.value = undefined;
  error.value = '';
}
</script>
 
<template>
  <section class="mb-3 rounded-lg border border-border p-3">
    <h3 class="mb-2 text-sm font-semibold">{{ title }}</h3>
    <TraceScanInput
      v-if="!trace"
      :disabled="disabled || busy"
      @code="identify"
    />
    <div v-else class="space-y-1 text-sm">
      <p>
        <span class="text-muted-foreground">码类型:</span>{{ typeLabel }}
        <span class="ml-4 text-muted-foreground">码值:</span>{{ trace.code }}
      </p>
      <p>
        <span class="text-muted-foreground">品种:</span
        >{{ trace.data.itemName || '未录入' }}
        <span class="ml-4 text-muted-foreground">批次:</span
        >{{ trace.data.batchCode || '未绑定' }}
      </p>
      <p>
        <span class="text-muted-foreground">可带入数量:</span
        >{{ quantity || '—' }}
      </p>
      <div class="flex gap-2 pt-1">
        <Button type="primary" :disabled="disabled || busy" @click="confirm">
          确认带入
        </Button>
        <Button :disabled="busy" @click="cancel">取消本次扫码</Button>
      </div>
    </div>
    <p v-if="error" class="mt-1 text-red-600" role="alert">{{ error }}</p>
  </section>
</template>