<script lang="ts" setup>
|
import type { EchartsUIType, EChartsOption } from '@vben/plugins/echarts';
|
import type { MesTraceBatchApi } from '#/api/mes/trace/batch';
|
|
import { nextTick, onMounted, ref, watch } from 'vue';
|
|
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
|
|
const props = defineProps<{ detail: MesTraceBatchApi.Detail }>();
|
const chartRef = ref<EchartsUIType>();
|
const { renderEcharts } = useEcharts(chartRef);
|
const render = () => renderEcharts(buildOption());
|
|
// use-echarts 在 onMounted 后才将 isActive 置为 true,
|
// 故渲染必须放到 onMounted(immediate watch 在 setup 阶段会被静默丢弃)
|
onMounted(() => {
|
void nextTick(render);
|
});
|
watch(() => props.detail, () => void render(), { deep: true });
|
|
const buildOption = (): EChartsOption => {
|
const nodes: { id: string; name: string; category: number; symbolSize: number }[] = [];
|
const links: { source: string; target: string }[] = [];
|
const add = (id: string, name: string, category: number, symbolSize = 42) => {
|
if (!nodes.some((node) => node.id === id)) nodes.push({ id, name, category, symbolSize });
|
};
|
const connect = (source: string, target: string) => {
|
if (source !== target && !links.some((link) => link.source === source && link.target === target)) links.push({ source, target });
|
};
|
const root = `batch:${props.detail.batchCode || props.detail.requestCode || 'unknown'}`;
|
add(root, props.detail.batchCode || '生产批次', 1, 58);
|
(props.detail.purchaseSources ?? []).slice(0, 12).forEach((item, index) => { const id = `source:${index}`; add(id, item.vendorName || item.receiptCode || '采购来源', 0); connect(id, root); });
|
if (props.detail.quality) { add('quality', props.detail.quality.resultName || '质量检验', 2); connect(root, 'quality'); }
|
add('warehouse', '扫码入库', 3); connect(root, 'warehouse');
|
(props.detail.salesTargets ?? []).slice(0, 12).forEach((item, index) => { const id = `sales:${index}`; add(id, item.clientName || item.salesCode || '销售去向', 4); connect('warehouse', id); });
|
if (props.detail.antiFake?.scanCount) { add('consumer', `消费者验证\n${props.detail.antiFake.scanCount} 次`, 5); connect('warehouse', 'consumer'); }
|
const series = { type: 'graph' as const, layout: 'force' as const, roam: true, draggable: true, data: nodes, links, categories: ['来源', '生产批次', '质量', '仓储', '销售', '消费'].map((name) => ({ name })), label: { show: true, fontSize: 12 }, force: { repulsion: 260, edgeLength: 110 }, lineStyle: { color: '#94a3b8', curveness: 0.15 } };
|
return { tooltip: { trigger: 'item' }, legend: [{ data: ['来源', '生产批次', '质量', '仓储', '销售', '消费'] }], series: [series] };
|
};
|
</script>
|
|
<template>
|
<div class="p-4">
|
<EchartsUI ref="chartRef" :height="'420px'" class="w-full rounded border bg-muted/20" />
|
<div class="text-muted-foreground mt-2 text-center text-xs">图谱默认展示批次级关系,来源和销售节点各最多 12 条</div>
|
</div>
|
</template>
|