<script lang="ts" setup>
|
import type { MesTraceBatchApi } from '#/api/mes/trace/batch';
|
|
import { computed, ref } from 'vue';
|
|
import { useVbenModal } from '@vben/common-ui';
|
|
import { Descriptions, Spin, Tabs, Tag, message } from 'ant-design-vue';
|
|
import { getBatchTraceDetail } from '#/api/mes/trace/batch';
|
|
import TraceDecision from './TraceDecision.vue';
|
import TraceGraph from './TraceGraph.vue';
|
import TraceStageOverview from './TraceStageOverview.vue';
|
import TraceTimeline from './TraceTimeline.vue';
|
|
const detailData = ref<MesTraceBatchApi.Detail>();
|
const loading = ref(false);
|
const activeTab = ref('overview');
|
const formatDate = (value?: string) => value ? new Date(value).toLocaleString() : '未记录';
|
const riskLevel = computed(() => {
|
if (!detailData.value) return 'NORMAL';
|
return detailData.value.decision?.riskLevel || (detailData.value.quality?.result === 2 ? 'HIGH' : 'NORMAL');
|
});
|
const riskLabel = computed(() => riskLevel.value === 'HIGH' ? '高风险' : riskLevel.value === 'NORMAL' ? '正常' : '需关注');
|
const riskColor = computed(() => riskLevel.value === 'HIGH' ? 'red' : riskLevel.value === 'NORMAL' ? 'green' : 'orange');
|
|
const [Modal, modalApi] = useVbenModal({
|
onOpenChange(isOpen) {
|
if (!isOpen) {
|
detailData.value = undefined;
|
return;
|
}
|
const row = modalApi.getData<{ code?: string }>();
|
if (row?.code) {
|
void loadDetail(row.code);
|
}
|
activeTab.value = 'overview';
|
},
|
});
|
|
async function loadDetail(code: string) {
|
loading.value = true;
|
try {
|
detailData.value = await getBatchTraceDetail(code);
|
} catch {
|
message.error('批次追溯详情加载失败');
|
} finally {
|
loading.value = false;
|
}
|
}
|
</script>
|
|
<template>
|
<Modal
|
title="全链路批次追溯"
|
class="w-11/12"
|
:show-cancel-button="false"
|
:show-confirm-button="false"
|
>
|
<Spin :spinning="loading">
|
<div v-if="detailData" class="px-2">
|
<div class="mb-4 grid grid-cols-2 gap-3 lg:grid-cols-5">
|
<div class="rounded border bg-blue-50 px-4 py-3"><div class="text-muted-foreground text-xs">袋码数量</div><div class="mt-1 text-lg font-semibold text-blue-700">{{ detailData.bagTotal ?? 0 }}</div></div>
|
<div class="rounded border bg-violet-50 px-4 py-3"><div class="text-muted-foreground text-xs">托盘数量</div><div class="mt-1 text-lg font-semibold text-violet-700">{{ detailData.palletCount ?? 0 }}</div></div>
|
<div class="rounded border bg-green-50 px-4 py-3"><div class="text-muted-foreground text-xs">入库数量</div><div class="mt-1 text-lg font-semibold text-green-700">{{ detailData.decision?.inboundQuantity ?? detailData.inbound?.quantity ?? 0 }}</div></div>
|
<div class="rounded border bg-orange-50 px-4 py-3"><div class="text-muted-foreground text-xs">销售去向</div><div class="mt-1 text-lg font-semibold text-orange-700">{{ detailData.decision?.salesTargetCount ?? detailData.salesTargets?.length ?? 0 }}</div></div>
|
<div class="col-span-2 rounded border px-4 py-3 lg:col-span-1" :class="riskLevel === 'HIGH' ? 'border-red-200 bg-red-50' : riskLevel === 'NORMAL' ? 'border-green-200 bg-green-50' : 'border-orange-200 bg-orange-50'"><div class="text-muted-foreground text-xs">综合风险</div><div class="mt-1"><Tag :color="riskColor">{{ riskLabel }}</Tag></div></div>
|
</div>
|
<Descriptions bordered :column="{ xs: 1, sm: 2, md: 3 }" size="small">
|
<Descriptions.Item label="追溯入口">{{ detailData.requestCode || '未记录' }}</Descriptions.Item>
|
<Descriptions.Item label="入口类型"><Tag color="blue">{{ detailData.sourceType || 'BATCH' }}</Tag></Descriptions.Item>
|
<Descriptions.Item label="批次状态">{{ detailData.batchStatusName || '未知' }}</Descriptions.Item>
|
<Descriptions.Item label="品种">{{ detailData.itemName || detailData.itemCode || '未记录' }}</Descriptions.Item>
|
<Descriptions.Item label="批次号">{{ detailData.batchCode || '未记录' }}</Descriptions.Item>
|
<Descriptions.Item label="责任人">{{ detailData.ownerUserName || '未记录' }}</Descriptions.Item>
|
<Descriptions.Item label="生产线">{{ detailData.lineName || detailData.lineCode || '未记录' }}</Descriptions.Item>
|
<Descriptions.Item label="计划数量">{{ detailData.planQuantity ?? 0 }}</Descriptions.Item>
|
<Descriptions.Item label="生产日期">{{ formatDate(detailData.produceDate) }}</Descriptions.Item>
|
<Descriptions.Item label="入库时间">{{ formatDate(detailData.inboundTime || detailData.inbound?.eventTime) }}</Descriptions.Item>
|
</Descriptions>
|
|
<Tabs v-model:active-key="activeTab" class="mt-4" type="card">
|
<Tabs.TabPane key="overview" tab="阶段总览">
|
<TraceStageOverview :detail="detailData" />
|
</Tabs.TabPane>
|
<Tabs.TabPane key="timeline" tab="全链路时间线">
|
<TraceTimeline :detail="detailData" />
|
</Tabs.TabPane>
|
<Tabs.TabPane key="graph" tab="流动图谱">
|
<TraceGraph :detail="detailData" />
|
</Tabs.TabPane>
|
<Tabs.TabPane key="decision" tab="决策分析">
|
<TraceDecision :detail="detailData" />
|
</Tabs.TabPane>
|
</Tabs>
|
</div>
|
<div v-else-if="!loading" class="py-12 text-center text-muted-foreground">暂无追溯数据</div>
|
</Spin>
|
</Modal>
|
</template>
|