You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
304 lines
8.6 KiB
Vue
304 lines
8.6 KiB
Vue
<template>
|
|
<div class="item-analysis-container">
|
|
<div class="item-select-section">
|
|
<el-form :model="analysisForm" label-width="100px">
|
|
<el-form-item label="项目名称">
|
|
<el-select
|
|
v-model="analysisForm.selectedItem"
|
|
placeholder="请选择要分析的项目"
|
|
style="width: 300px"
|
|
clearable
|
|
>
|
|
<el-option
|
|
v-for="item in itemList"
|
|
:key="item"
|
|
:label="item"
|
|
:value="item"
|
|
/>
|
|
</el-select>
|
|
<el-button
|
|
type="primary"
|
|
style="margin-left: 10px"
|
|
:disabled="!analysisForm.selectedItem"
|
|
@click="handleFetchData"
|
|
>
|
|
查询
|
|
</el-button>
|
|
<el-button
|
|
type="success"
|
|
style="margin-left: 10px"
|
|
:disabled="!analysisForm.selectedItem || workbenchData.length === 0"
|
|
@click="handleAnalyzeItem"
|
|
>
|
|
AI分析
|
|
</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
</div>
|
|
|
|
<!-- 机台不良分布数据表格 -->
|
|
<div v-if="workbenchData.length > 0" class="workbench-data">
|
|
<h3>机台不良分布 - {{ analysisForm.selectedItem }}</h3>
|
|
<el-table
|
|
:data="workbenchData"
|
|
border
|
|
style="width: 100%"
|
|
stripe
|
|
:default-sort="{ prop: 'bad_count', order: 'descending' }"
|
|
>
|
|
<el-table-column prop="workbench" label="机台号" width="100" sortable />
|
|
<el-table-column prop="bad_count" label="不良数量" width="120" sortable />
|
|
<el-table-column prop="bad_percentage" label="不良占比" width="120" sortable>
|
|
<template #default="scope">
|
|
{{ scope.row.bad_percentage }}%
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="不良占比可视化">
|
|
<template #default="scope">
|
|
<el-progress
|
|
:percentage="scope.row.bad_percentage"
|
|
:show-text="false"
|
|
:color="getProgressColor(scope.row.bad_percentage)"
|
|
/>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
<div class="statistics-info">
|
|
<p>数据范围: {{ currentStartDate }} 至 {{ currentEndDate }}</p>
|
|
<p>总计机台数: {{ workbenchData.length }}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 分析结果显示区域 -->
|
|
<div v-if="analysisResult" class="analysis-result">
|
|
<h3>{{ analysisForm.selectedItem }} - 分析结果</h3>
|
|
<el-input
|
|
v-model="analysisResult"
|
|
type="textarea"
|
|
:rows="10"
|
|
readonly
|
|
/>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, reactive } from 'vue'
|
|
import { getDateRangeByTimeRange } from "@/utils/dateFormat"
|
|
import { AI_CONFIG, CURRENT_AI_MODEL } from "@/config/ai"
|
|
import { API_CONFIG } from "@/config/api"
|
|
|
|
const props = defineProps({
|
|
paretoData: {
|
|
type: Array,
|
|
default: () => []
|
|
},
|
|
selectedTimeRange: {
|
|
type: String,
|
|
default: '近1年'
|
|
}
|
|
})
|
|
|
|
const emit = defineEmits(['ai-analysis-complete'])
|
|
|
|
// 分析表单数据
|
|
const analysisForm = reactive({
|
|
selectedItem: ''
|
|
})
|
|
|
|
// 分析结果
|
|
const analysisResult = ref('')
|
|
|
|
// 机台不良数据
|
|
const workbenchData = ref([])
|
|
|
|
// 当前查询的日期范围
|
|
const currentStartDate = ref('')
|
|
const currentEndDate = ref('')
|
|
|
|
// 项目名称列表
|
|
const itemList = ref([
|
|
'漆膜厚度',
|
|
'击穿电压2(kv)',
|
|
'击穿电压5(kv)',
|
|
'击穿电压4(kv)',
|
|
'击穿电压3(kv)',
|
|
'回弹角(°)1',
|
|
'回弹角(°)2',
|
|
'击穿电压1(kv)',
|
|
'漆膜连续性(个)',
|
|
'最大外径',
|
|
'伸长率(%)1',
|
|
'导体f值',
|
|
'电阻值',
|
|
'预置伸长率',
|
|
'伸长率(%)2',
|
|
'平均单刮(N)',
|
|
'单向刮漆min(N)'
|
|
])
|
|
|
|
// 根据缺陷百分比设置进度条颜色
|
|
function getProgressColor(percentage) {
|
|
if (percentage >= 10) return '#f56c6c'; // 红色 - 高缺陷率
|
|
if (percentage >= 5) return '#e6a23c'; // 橙色 - 中等缺陷率
|
|
if (percentage >= 2) return '#409eff'; // 蓝色 - 低缺陷率
|
|
return '#67c23a'; // 绿色 - 很低缺陷率
|
|
}
|
|
|
|
// 获取机台不良分布数据
|
|
async function handleFetchData() {
|
|
if (!analysisForm.selectedItem) {
|
|
emit('ai-analysis-complete', '请先选择要分析的项目')
|
|
return
|
|
}
|
|
|
|
// 根据选择的时间范围计算开始和结束日期
|
|
const dateRange = getDateRangeByTimeRange(props.selectedTimeRange);
|
|
const { start_date: startDateStr, end_date: endDateStr } = dateRange;
|
|
|
|
// 保存当前查询的日期范围
|
|
currentStartDate.value = startDateStr;
|
|
currentEndDate.value = endDateStr;
|
|
|
|
// 调用机台不良分布API
|
|
try {
|
|
const response = await fetch(`${API_CONFIG.BASE_URL}${API_CONFIG.ENDPOINTS.WORKBENCH_BADNESS}?item_name=${encodeURIComponent(analysisForm.selectedItem)}&start_date=${startDateStr}&end_date=${endDateStr}`);
|
|
const data = await response.json();
|
|
|
|
if (data.code === 200 && data.data) {
|
|
workbenchData.value = data.data;
|
|
emit('ai-analysis-complete', `成功获取${analysisForm.selectedItem}的机台不良分布数据`);
|
|
} else {
|
|
workbenchData.value = [];
|
|
emit('ai-analysis-complete', data.message || '获取机台不良分布数据失败');
|
|
}
|
|
} catch (error) {
|
|
console.error('获取机台不良分布数据失败:', error);
|
|
workbenchData.value = [];
|
|
emit('ai-analysis-complete', '获取机台不良分布数据失败');
|
|
}
|
|
}
|
|
|
|
// AI分析功能
|
|
async function handleAnalyzeItem() {
|
|
if (!analysisForm.selectedItem || workbenchData.value.length === 0) {
|
|
emit('ai-analysis-complete', '请先选择项目并查询数据')
|
|
return
|
|
}
|
|
|
|
// 在帕累托数据中查找选中项目的数据
|
|
const selectedItemData = props.paretoData.find(item => item.item_name === analysisForm.selectedItem)
|
|
|
|
// 准备分析提示词
|
|
const prompt = `请对以下质检项目和机台不良分布进行详细分析:
|
|
|
|
项目名称: ${analysisForm.selectedItem}
|
|
数据范围: ${currentStartDate.value} 至 ${currentEndDate.value}
|
|
|
|
帕累托分析数据:
|
|
${selectedItemData ?
|
|
`- 缺陷数量: ${selectedItemData.defect_count}\n- 缺陷占比: ${selectedItemData.defect_percentage}%\n- 累计占比: ${selectedItemData.cumulative_percentage}%` :
|
|
'该项目在当前帕累托分析数据中不存在'}
|
|
|
|
机台不良分布数据:
|
|
${workbenchData.value.slice(0, 5).map(item =>
|
|
`- 机台${item.workbench}: 不良数量${item.bad_count}, 不良占比${item.bad_percentage}%`
|
|
).join('\n')}
|
|
|
|
请从以下角度进行分析:
|
|
1. 该项目缺陷对整体质量的影响
|
|
2. 产生缺陷的可能原因分析
|
|
3. 针对该项目的改进建议
|
|
4. 机台不良分布的规律分析
|
|
5. 该项目与其他项目的关联性分析`
|
|
|
|
try {
|
|
// 获取当前AI模型配置
|
|
const currentAIConfig = AI_CONFIG[CURRENT_AI_MODEL]
|
|
|
|
// 调用AI模型API进行分析
|
|
const response = await fetch(`${currentAIConfig.BASE_URL}/chat/completions`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Bearer ${currentAIConfig.API_KEY}`
|
|
},
|
|
body: JSON.stringify({
|
|
model: currentAIConfig.MODEL,
|
|
messages: [
|
|
{
|
|
role: 'system',
|
|
content: '你是一位专业的质量控制专家,擅长分析具体质检项目并提供针对性的改进建议。'
|
|
},
|
|
{
|
|
role: 'user',
|
|
content: prompt
|
|
}
|
|
],
|
|
temperature: 0.3,
|
|
max_tokens: 1500
|
|
})
|
|
})
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`API调用失败: ${response.status}`)
|
|
}
|
|
|
|
const data = await response.json()
|
|
const result = data.choices[0].message.content
|
|
analysisResult.value = result
|
|
// 发送分析结果完成事件
|
|
emit('ai-analysis-complete', result)
|
|
} catch (error) {
|
|
console.error('项目分析失败:', error)
|
|
const errorMessage = `项目分析失败: ${error.message}\n\n请检查网络连接或稍后再试。`
|
|
analysisResult.value = errorMessage
|
|
// 发送分析结果失败事件
|
|
emit('ai-analysis-complete', errorMessage)
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.item-analysis-container {
|
|
width: 100%;
|
|
padding: 20px;
|
|
}
|
|
|
|
.item-select-section {
|
|
margin-bottom: 20px;
|
|
padding: 15px;
|
|
background-color: #f5f7fa;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.analysis-result {
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.analysis-result h3 {
|
|
margin-bottom: 15px;
|
|
color: #409eff;
|
|
}
|
|
|
|
.workbench-data {
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.workbench-data h3 {
|
|
margin-bottom: 15px;
|
|
color: #409eff;
|
|
}
|
|
|
|
.statistics-info {
|
|
margin-top: 10px;
|
|
padding: 10px;
|
|
background-color: #f5f7fa;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.statistics-info p {
|
|
margin: 5px 0;
|
|
font-size: 14px;
|
|
}
|
|
</style> |