From a27f80b043bb9651fd0032dcd28b2fee6cf820b9 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期一, 03 八月 2026 13:42:34 +0800
Subject: [PATCH] feat(ai): 集成AI智能分析功能到MPS表单和仪表板
---
src/views/mes/pro/workorder/modules/ai/predict-material.vue | 87 +++++++++++++++++++++++++++++++++++++++----
1 files changed, 79 insertions(+), 8 deletions(-)
diff --git a/src/views/mes/pro/workorder/modules/ai/predict-material.vue b/src/views/mes/pro/workorder/modules/ai/predict-material.vue
index 919fc43..c6c5673 100644
--- a/src/views/mes/pro/workorder/modules/ai/predict-material.vue
+++ b/src/views/mes/pro/workorder/modules/ai/predict-material.vue
@@ -1,21 +1,25 @@
<script lang="ts" setup>
import type { MesProAiApi } from '#/api/mes/pro/ai';
-import { ref } from 'vue';
+import { onUnmounted, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { IconifyIcon } from '@vben/icons';
-import { Button, message, Table, Tag } from 'ant-design-vue';
+import { Button, Progress, Table, Tag } from 'ant-design-vue';
import { predictMaterial } from '#/api/mes/pro/ai';
defineOptions({ name: 'MesProAiPredictMaterial' });
-const props = defineProps<{ workOrderId: number }>();
+const props = defineProps<{ workOrderId?: number; mpsId?: number }>();
const loading = ref(false);
+const progress = ref(0);
const result = ref<MesProAiApi.PredictMaterialRespVO>();
+const errorMsg = ref('');
+
+let progressTimer: ReturnType<typeof setInterval> | null = null;
const riskLevelColor: Record<number, string> = { 1: 'green', 2: 'orange', 3: 'red' };
const riskLevelText: Record<number, string> = { 1: '浣庨闄�', 2: '涓闄�', 3: '楂橀闄�' };
@@ -31,20 +35,58 @@
{ title: '寤鸿鎺柦', dataIndex: 'suggestion' },
];
+function startProgress() {
+ progress.value = 0;
+ progressTimer = setInterval(() => {
+ if (progress.value < 30) {
+ progress.value += 3;
+ } else if (progress.value < 70) {
+ progress.value += 2;
+ } else if (progress.value < 88) {
+ progress.value += 0.5;
+ }
+ }, 100);
+}
+
+function stopProgress() {
+ if (progressTimer) {
+ clearInterval(progressTimer);
+ progressTimer = null;
+ }
+}
+
+function finishProgress() {
+ stopProgress();
+ progress.value = 100;
+}
+
+onUnmounted(() => stopProgress());
+
async function handlePredict() {
loading.value = true;
result.value = undefined;
+ errorMsg.value = '';
+ modalApi.open();
+ startProgress();
try {
- result.value = await predictMaterial(props.workOrderId);
- modalApi.open();
+ result.value = await predictMaterial(props.workOrderId, props.mpsId);
+ finishProgress();
} catch {
- message.error('AI 鍒嗘瀽鏆傛椂涓嶅彲鐢紝璇风◢鍚庨噸璇�');
+ errorMsg.value = 'AI 鍒嗘瀽鏆傛椂涓嶅彲鐢紝璇风◢鍚庨噸璇�';
+ stopProgress();
} finally {
loading.value = false;
}
}
-const [ResultModal, modalApi] = useVbenModal({ footer: false });
+const [ResultModal, modalApi] = useVbenModal({
+ footer: false,
+ onOpenChange(isOpen: boolean) {
+ if (!isOpen) {
+ stopProgress();
+ }
+ },
+});
</script>
<template>
@@ -54,7 +96,36 @@
</Button>
<ResultModal title="AI 鐗╂枡鐭己棰勬祴" class="w-3/5">
- <template v-if="result">
+ <!-- 鍔犺浇涓� -->
+ <div v-if="loading" class="flex flex-col items-center py-10">
+ <div class="relative mb-6">
+ <div class="absolute inset-0 animate-ping rounded-full bg-blue-400 opacity-20" style="width: 80px; height: 80px" />
+ <div class="relative flex h-20 w-20 items-center justify-center rounded-full bg-blue-50">
+ <IconifyIcon icon="ant-design:alert-outlined" class="text-3xl text-blue-500" />
+ </div>
+ </div>
+ <div class="mb-3 text-base font-medium text-gray-700">
+ AI 姝e湪鍒嗘瀽鐗╂枡搴撳瓨涓庨渶姹�...
+ </div>
+ <div class="w-2/3">
+ <Progress
+ :percent="Math.round(progress)"
+ :stroke-color="{ '0%': '#1677ff', '100%': '#69b1ff' }"
+ :show-info="true"
+ status="active"
+ />
+ </div>
+ <div class="mt-2 text-sm text-gray-400">姝e湪鏌ヨ搴撳瓨鏁版嵁銆佽瘎浼扮墿鏂欑煭缂洪闄�</div>
+ </div>
+
+ <!-- 閿欒 -->
+ <div v-else-if="errorMsg" class="flex flex-col items-center py-10">
+ <IconifyIcon icon="ant-design:close-circle-filled" class="mb-4 text-5xl text-red-400" />
+ <span class="text-base text-gray-500">{{ errorMsg }}</span>
+ </div>
+
+ <!-- 缁撴灉 -->
+ <template v-else-if="result">
<div class="mb-4 flex items-center gap-2">
<span class="text-base font-medium">鏁翠綋椋庨櫓绛夌骇锛�</span>
<Tag :color="riskLevelColor[result.riskLevel]">
--
Gitblit v1.9.3