<script lang="ts" setup>
|
import { computed, ref } from 'vue';
|
|
import { DICT_TYPE } from '@vben/constants';
|
|
import {
|
Button,
|
Descriptions,
|
Divider,
|
Empty,
|
Image,
|
Input,
|
message,
|
Modal,
|
Tag,
|
} from 'ant-design-vue';
|
|
import {
|
parseBarcodeContent,
|
renderBarcodeImage,
|
} from '#/api/mes/wm/barcode';
|
import { DictTag } from '#/components/dict-tag';
|
|
defineOptions({ name: 'WlsBarcodeScanModal' });
|
|
const open = ref(false);
|
const content = ref('');
|
const parseResult = ref<Record<string, any>>();
|
const imageBase64 = ref('');
|
const parsing = ref(false);
|
const rendering = ref(false);
|
|
function openModal() {
|
open.value = true;
|
content.value = '';
|
parseResult.value = undefined;
|
imageBase64.value = '';
|
}
|
|
/** 解析条码内容 */
|
async function handleParse() {
|
if (!content.value?.trim()) {
|
message.warning('请先扫码枪扫入或手动输入条码内容');
|
return;
|
}
|
parsing.value = true;
|
try {
|
parseResult.value = await parseBarcodeContent(content.value.trim());
|
} finally {
|
parsing.value = false;
|
}
|
}
|
|
/** 服务端成图预览(PNG Base64,不落库) */
|
async function handleRender() {
|
if (!content.value?.trim()) {
|
message.warning('请先扫码枪扫入或手动输入条码内容');
|
return;
|
}
|
rendering.value = true;
|
try {
|
const base64 = await renderBarcodeImage(
|
content.value.trim(),
|
parseResult.value?.format,
|
);
|
imageBase64.value = base64 ? `data:image/png;base64,${base64}` : '';
|
if (!base64) {
|
message.warning('成图失败,请检查条码内容是否符合所选格式');
|
}
|
} finally {
|
rendering.value = false;
|
}
|
}
|
|
/** 匹配方式文案 */
|
const matchedLabel = computed(() => {
|
if (parseResult.value?.matched) {
|
return '精确命中';
|
}
|
if (parseResult.value?.fields) {
|
return '模板反解';
|
}
|
return '未匹配';
|
});
|
const matchedColor = computed(() => {
|
if (parseResult.value?.matched) {
|
return 'green';
|
}
|
if (parseResult.value?.fields) {
|
return 'blue';
|
}
|
return 'orange';
|
});
|
|
defineExpose({ open: openModal });
|
</script>
|
|
<template>
|
<Modal v-model:open="open" title="扫码解析 / 条码预览" width="720px">
|
<div class="space-y-4">
|
<div class="flex gap-2">
|
<Input
|
v-model:value="content"
|
placeholder="扫码枪扫入或手动输入条码内容,回车解析"
|
@press-enter="handleParse"
|
/>
|
<Button type="primary" :loading="parsing" @click="handleParse">
|
解析
|
</Button>
|
<Button :loading="rendering" @click="handleRender">成图预览</Button>
|
</div>
|
|
<div v-if="parseResult">
|
<Divider orientation="left">解析结果</Divider>
|
<Descriptions
|
v-if="parseResult.bizType != null || parseResult.bizCode != null"
|
bordered
|
:column="2"
|
size="small"
|
>
|
<Descriptions.Item label="匹配方式">
|
<Tag :color="matchedColor">{{ matchedLabel }}</Tag>
|
</Descriptions.Item>
|
<Descriptions.Item v-if="parseResult.format != null" label="条码格式">
|
<DictTag
|
:type="DICT_TYPE.MES_WM_BARCODE_FORMAT"
|
:value="parseResult.format"
|
/>
|
</Descriptions.Item>
|
<Descriptions.Item v-if="parseResult.bizType != null" label="业务类型">
|
<DictTag
|
:type="DICT_TYPE.MES_WM_BARCODE_BIZ_TYPE"
|
:value="parseResult.bizType"
|
/>
|
</Descriptions.Item>
|
<Descriptions.Item v-if="parseResult.barcodeId != null" label="条码编号">
|
{{ parseResult.barcodeId }}
|
</Descriptions.Item>
|
<Descriptions.Item label="业务编码">
|
{{ parseResult.bizCode || '-' }}
|
</Descriptions.Item>
|
<Descriptions.Item label="业务名称">
|
{{ parseResult.bizName || '-' }}
|
</Descriptions.Item>
|
<Descriptions.Item v-if="parseResult.bizId != null" label="业务编号">
|
{{ parseResult.bizId }}
|
</Descriptions.Item>
|
</Descriptions>
|
|
<div v-if="parseResult.fields" class="mt-2">
|
<div class="mb-1 text-sm font-medium">模板字段</div>
|
<div
|
v-for="(value, key) in parseResult.fields"
|
:key="key"
|
class="mb-1 flex items-center gap-2"
|
>
|
<Tag>{{ key }}</Tag>
|
<span>{{ value }}</span>
|
</div>
|
</div>
|
<Empty
|
v-else-if="parseResult.bizType == null && parseResult.bizCode == null"
|
description="未匹配到条码记录或条码配置模板"
|
/>
|
</div>
|
|
<div v-if="imageBase64">
|
<Divider orientation="left">成图预览</Divider>
|
<div class="flex justify-center rounded bg-gray-100 p-4">
|
<Image :src="imageBase64" :width="220" />
|
</div>
|
</div>
|
</div>
|
<template #footer>
|
<Button @click="open = false">关闭</Button>
|
</template>
|
</Modal>
|
</template>
|