gaoluyang
2026-08-03 75242bbba28ae8902ddf86d33febb497d79e5fc3
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
<script lang="ts" setup>
import type { MesProAiApi } from '#/api/mes/pro/ai';
 
import { ref } from 'vue';
 
import { useVbenModal } from '@vben/common-ui';
import { IconifyIcon } from '@vben/icons';
 
import { Button, message, Table, Tag } from 'ant-design-vue';
 
import { predictMaterial } from '#/api/mes/pro/ai';
 
defineOptions({ name: 'MesProAiPredictMaterial' });
 
const props = defineProps<{ workOrderId: number }>();
 
const loading = ref(false);
const result = ref<MesProAiApi.PredictMaterialRespVO>();
 
const riskLevelColor: Record<number, string> = { 1: 'green', 2: 'orange', 3: 'red' };
const riskLevelText: Record<number, string> = { 1: '低风险', 2: '中风险', 3: '高风险' };
const itemRiskColor: Record<string, string> = { '充足': 'green', '紧张': 'orange', '短缺': 'red' };
 
const columns = [
  { title: '物料编码', dataIndex: 'itemCode', width: 120 },
  { title: '物料名称', dataIndex: 'itemName', width: 150 },
  { title: '需求量', dataIndex: 'requiredQuantity', width: 100 },
  { title: '库存可用量', dataIndex: 'availableQuantity', width: 100 },
  { title: '短缺数量', dataIndex: 'shortageQuantity', width: 100 },
  { title: '风险等级', dataIndex: 'riskLevel', width: 100, key: 'riskLevel' },
  { title: '建议措施', dataIndex: 'suggestion' },
];
 
async function handlePredict() {
  loading.value = true;
  result.value = undefined;
  try {
    result.value = await predictMaterial(props.workOrderId);
    modalApi.open();
  } catch {
    message.error('AI 分析暂时不可用,请稍后重试');
  } finally {
    loading.value = false;
  }
}
 
const [ResultModal, modalApi] = useVbenModal({ footer: false });
</script>
 
<template>
  <Button :loading="loading" @click="handlePredict">
    <template #icon><IconifyIcon icon="ant-design:alert-outlined" /></template>
    AI 物料预测
  </Button>
 
  <ResultModal title="AI 物料短缺预测" class="w-3/5">
    <template v-if="result">
      <div class="mb-4 flex items-center gap-2">
        <span class="text-base font-medium">整体风险等级:</span>
        <Tag :color="riskLevelColor[result.riskLevel]">
          {{ riskLevelText[result.riskLevel] || '-' }}
        </Tag>
      </div>
      <div class="mb-4 rounded bg-gray-50 p-3 text-sm leading-relaxed">
        {{ result.reasoning }}
      </div>
      <Table
        v-if="result.riskItems?.length"
        :columns="columns"
        :data-source="result.riskItems"
        :pagination="false"
        row-key="itemCode"
        size="small"
        bordered
      >
        <template #bodyCell="{ column, text }">
          <template v-if="column.key === 'riskLevel'">
            <Tag :color="itemRiskColor[text] || 'default'">{{ text }}</Tag>
          </template>
        </template>
      </Table>
      <div v-else class="py-4 text-center text-gray-400">无物料风险项</div>
    </template>
  </ResultModal>
</template>