| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- <template>
- <div class="result-analysis">
- <el-card shadow="never">
- <template #header>
- <div class="card-header">
- <span class="title">AI 结果分析</span>
- <el-tag type="info" size="small">Kimi k3 + 多保真度校准</el-tag>
- </div>
- </template>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form label-width="100px" size="small">
- <el-form-item label="保真度等级">
- <el-select v-model="fidelity">
- <el-option label="L0 - 解析预筛选" value="L0" />
- <el-option label="L1 - 磁路等效电路" value="L1" />
- <el-option label="L2 - 2D FEA" value="L2" />
- <el-option label="L3 - 3D FEA (Motor-CAD)" value="L3" />
- <el-option label="L4 - 3D瞬态+热耦合" value="L4" />
- </el-select>
- </el-form-item>
- <el-form-item label="目标转矩">
- <el-input-number v-model="targets.tavg_nm" :min="0" />
- </el-form-item>
- <el-form-item label="目标效率">
- <el-input-number v-model="targets.efficiency_pct" :min="0" :max="100" />
- </el-form-item>
- </el-form>
- </el-col>
- <el-col :span="12">
- <div class="input-area">
- <div class="input-label">仿真结果数据 (JSON数组)</div>
- <el-input
- v-model="resultsJson"
- type="textarea"
- :rows="6"
- placeholder='[{"tavg_nm": 15.2, "efficiency_pct": 92.5, "airgap_mm": 1.0, ...}]'
- />
- <div class="actions">
- <el-button size="small" @click="loadExample">加载示例</el-button>
- <el-button type="primary" :loading="analyzing" @click="doAnalyze">开始分析</el-button>
- </div>
- </div>
- </el-col>
- </el-row>
- </el-card>
- <el-card v-if="analysis" shadow="never" style="margin-top: 20px;">
- <template #header>
- <div class="card-header">
- <span>分析结果</span>
- <ConfidenceBadge v-if="confidence" :grade="confidence.grade" :score="confidence.score" />
- </div>
- </template>
- <el-alert :title="analysis.summary" type="info" :closable="false" show-icon style="margin-bottom: 16px;" />
- <el-row :gutter="16">
- <el-col :span="12">
- <div class="section-title">关键指标统计</div>
- <el-table :data="metricStats" border size="small">
- <el-table-column prop="metric" label="指标" width="140" />
- <el-table-column prop="min" label="最小" />
- <el-table-column prop="max" label="最大" />
- <el-table-column prop="mean" label="均值" />
- </el-table>
- </el-col>
- <el-col :span="12">
- <div class="section-title">收敛性检查</div>
- <el-table :data="convChecks" border size="small">
- <el-table-column prop="name" label="判据" width="160" />
- <el-table-column label="结果" width="80">
- <template #default="{ row }">
- <el-tag :type="row.passed ? 'success' : 'danger'" size="small">{{ row.passed ? 'PASS' : 'FAIL' }}</el-tag>
- </template>
- </el-table-column>
- <el-table-column prop="value" label="数值" />
- </el-table>
- </el-col>
- </el-row>
- <el-divider v-if="aiAnalysis" content-position="left">AI 深度分析</el-divider>
- <el-descriptions v-if="aiAnalysis" :column="1" border size="small">
- <el-descriptions-item v-if="aiAnalysis.trend_analysis" label="趋势分析">{{ aiAnalysis.trend_analysis }}</el-descriptions-item>
- <el-descriptions-item v-if="aiAnalysis.recommendation" label="优化建议">{{ aiAnalysis.recommendation }}</el-descriptions-item>
- </el-descriptions>
- <div v-if="aiAnalysis?.optimization_suggestions?.length" class="suggestions">
- <div class="section-title">优化建议清单</div>
- <el-timeline>
- <el-timeline-item
- v-for="(s, idx) in aiAnalysis.optimization_suggestions"
- :key="idx"
- :type="s.priority === 'high' ? 'danger' : s.priority === 'medium' ? 'warning' : 'primary'"
- >
- <strong>{{ s.suggestion }}</strong>
- <div v-if="s.expected_improvement" style="color: #909399; font-size: 12px;">预期改善: {{ s.expected_improvement }}</div>
- </el-timeline-item>
- </el-timeline>
- </div>
- </el-card>
- </div>
- </template>
- <script setup lang="ts">
- import { ref, reactive, computed } from 'vue'
- import { ElMessage } from 'element-plus'
- import { analysisApi } from '@/api/ai'
- import ConfidenceBadge from '@/components/ai/ConfidenceBadge.vue'
- const fidelity = ref('L3')
- const targets = reactive({ tavg_nm: 10, efficiency_pct: 92 })
- const resultsJson = ref('')
- const analyzing = ref(false)
- const analysis = ref<any>(null)
- const aiAnalysis = ref<any>(null)
- const confidence = computed(() => analysis.value?.confidence)
- const metricStats = computed(() => {
- const stats = analysis.value?.quantitative?.statistics || {}
- return Object.entries(stats).map(([metric, s]: any) => ({
- metric, min: s.min, max: s.max, mean: s.mean,
- }))
- })
- const convChecks = computed(() => {
- const conv = analysis.value?.quantitative?.convergence || {}
- return Object.entries(conv)
- .filter(([k]) => k !== 'summary')
- .map(([name, v]: any) => ({ name, passed: v.passed, value: v.value ?? '-' }))
- })
- const loadExample = () => {
- const data = []
- for (let i = 0; i < 15; i++) {
- const airgap = 0.5 + Math.random() * 1.5
- const current = 10 + Math.random() * 15
- data.push({
- airgap_mm: +airgap.toFixed(2),
- current_a: +current.toFixed(1),
- tavg_nm: +(current * 2.5 / Math.sqrt(airgap) + (Math.random() - 0.5)).toFixed(2),
- efficiency_pct: +(88 + Math.random() * 5).toFixed(1),
- total_losses_w: +(40 + Math.random() * 20).toFixed(1),
- winding_temp_c: +(85 + Math.random() * 25).toFixed(1),
- feasible: Math.random() > 0.15,
- })
- }
- resultsJson.value = JSON.stringify(data, null, 2)
- }
- const doAnalyze = async () => {
- let results: any[]
- try {
- results = JSON.parse(resultsJson.value)
- } catch {
- ElMessage.error('结果数据不是有效的JSON')
- return
- }
- if (!Array.isArray(results) || !results.length) {
- ElMessage.error('请输入至少一条结果数据')
- return
- }
- analyzing.value = true
- try {
- const res: any = await analysisApi.analyze({
- results,
- targets: { ...targets },
- fidelity: fidelity.value,
- })
- analysis.value = res
- aiAnalysis.value = res.ai_analysis
- ElMessage.success('分析完成')
- } catch (e: any) {
- ElMessage.error('分析失败: ' + (e.message || e))
- } finally {
- analyzing.value = false
- }
- }
- </script>
- <style scoped>
- .result-analysis { padding: 20px; }
- .title { font-weight: 600; font-size: 16px; }
- .card-header { display: flex; justify-content: space-between; align-items: center; }
- .input-area { display: flex; flex-direction: column; gap: 8px; }
- .input-label { font-weight: 600; color: #606266; font-size: 13px; }
- .actions { display: flex; gap: 8px; justify-content: flex-end; }
- .section-title { font-weight: 600; margin: 12px 0 8px; color: #303133; }
- .suggestions { margin-top: 16px; }
- </style>
|