diff --git a/src/views/plan/RealTimeInventory.vue b/src/views/plan/RealTimeInventory.vue index 8bccaaf..e88861e 100644 --- a/src/views/plan/RealTimeInventory.vue +++ b/src/views/plan/RealTimeInventory.vue @@ -27,6 +27,7 @@ :header-cell-style="{ backgroundColor: '#f5f7fa', color: '#606266' }" empty-text="暂无数据" :scrollbar-always-on="true" + @cell-click="handleCellClick" @cell-dblclick="handleCellDblClick" > @@ -53,7 +54,7 @@ padding: '8px 0', transition: 'background-color 0.3s ease' }" - :title="getCellTooltip(scope.row.specification, column.prop)" + :title="getCellTooltip(scope.row.specification, column.prop) + (getTransitionProbabilityTooltip(scope.row.specification, column.prop) ? '\n\n' + getTransitionProbabilityTooltip(scope.row.specification, column.prop) : '')" > {{ scope.row[column.prop] || '-' }} @@ -175,6 +176,10 @@ const uidProductionStatus = ref([]) const uidProductionStatusMap = ref(new Map()) const equipmentCodeColors = ref(new Map()) // equipment_code到颜色的映射 +// 转移概率数据 +const transitionProbabilitiesMap = ref(new Map()) // 存储转移概率数据 +const transitionColorsMap = ref(new Map()) // 存储概率颜色映射 + // WMS对话框相关状态 const wmsDialogVisible = ref(false) const currentWmsModel = ref('') @@ -408,6 +413,84 @@ const fetchUIDProductionStatus = async () => { } }; +// 方法:获取转移概率数据 +const fetchTransitionProbabilities = async (equipmentCode, axleNumber, model, specification, wireDisc) => { + try { + // 构建查询参数 + const params = new URLSearchParams({ + equipment_code: equipmentCode, + axle_number: axleNumber, + model: model, + specification: specification, + wire_disc: wireDisc + }); + + const url = `${API_CONFIG.BASE_URL}/api/plan/analysis/transition/probabilities?${params}`; + + console.log('正在请求转移概率API:', url); + console.log('API_CONFIG.BASE_URL:', API_CONFIG.BASE_URL); + + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }); + + console.log('API响应状态:', response.status, response.statusText); + console.log('API响应头:', Object.fromEntries(response.headers.entries())); + + if (!response.ok) { + console.error('API响应错误:', response.status, response.statusText); + const errorText = await response.text(); + console.error('错误响应内容:', errorText); + ElMessage.error(`API调用失败: ${response.status} ${response.statusText}`); + return null; + } + + const result = await response.json(); + + console.log('转移概率API返回结果:', result); + console.log('result.code:', result.code); + console.log('result.data:', result.data); + console.log('result.message:', result.message); + + // 检查响应结构 + if (result.code === 200) { + if (result.data) { + console.log('API调用成功,返回数据:', result.data); + return result.data; + } else { + console.error('API返回code=200但没有data字段'); + ElMessage.warning('API返回成功但没有数据'); + return null; + } + } else { + console.error('获取转移概率数据失败:', result.code, result.message); + ElMessage.error(`获取转移概率数据失败: ${result.message || '未知错误'}`); + return null; + } + } catch (error) { + console.error('转移概率API调用失败:', error); + console.error('错误详情:', { + name: error.name, + message: error.message, + stack: error.stack + }); + + // 判断错误类型 + if (error.name === 'TypeError' && error.message.includes('fetch')) { + ElMessage.error('网络连接失败,请检查API服务器是否运行'); + } else if (error.message.includes('CORS')) { + ElMessage.error('跨域请求被阻止,请检查API配置'); + } else { + ElMessage.error(`API调用异常: ${error.message}`); + } + + return null; + } +}; + // 方法:格式化wire_disc const formatWireDisc = (wireDisc) => { if (!wireDisc) return ''; @@ -446,6 +529,16 @@ const generateLowSaturationColor = (index) => { return lowSaturationColors[index % lowSaturationColors.length]; }; +// 方法:根据概率值获取颜色 +const getProbabilityColor = (intensity) => { + // intensity 是 0-1 之间的值,表示概率的相对强度 + const hue = 220; // 蓝色色调 + const saturation = Math.round(30 + intensity * 70); // 30% 到 100% 饱和度 + const lightness = Math.round(85 - intensity * 30); // 85% 到 55% 亮度 + + return `hsl(${hue}, ${saturation}%, ${lightness}%)`; +}; + // 方法:根据wight_completion获取完成度状态 const getCompletionStatus = (wight_completion) => { if (wight_completion <= 0) { @@ -501,6 +594,24 @@ const getEquipmentCodeColor = (specification, columnProp) => { // 构建包含规格的key const keyWithSpec = `${columnProp}::${specification}`; + // 首先检查是否有转移概率数据 + if (transitionProbabilitiesMap.value.has(keyWithSpec)) { + const transitionData = transitionProbabilitiesMap.value.get(keyWithSpec); + if (transitionData && transitionData.prediction && transitionData.prediction.most_likely_next_spec) { + const mostLikelySpec = transitionData.prediction.most_likely_next_spec; + const probability = transitionData.prediction.probability; + + // 构建颜色键来查找概率颜色 + const colorKey = `${keyWithSpec}::${mostLikelySpec}`; + if (transitionColorsMap.value.has(colorKey)) { + const baseColor = transitionColorsMap.value.get(colorKey); + console.log(`为单元格 ${keyWithSpec} 应用转移概率颜色: ${baseColor}, 概率: ${(probability * 100).toFixed(1)}%`); + return baseColor; + } + } + } + + // 如果没有转移概率数据,回退到设备代码颜色 if (!uidProductionStatusMap.value.has(keyWithSpec)) { return null; } @@ -509,6 +620,35 @@ const getEquipmentCodeColor = (specification, columnProp) => { return status.equipment_color; }; +// 方法:获取转移概率提示信息 +const getTransitionProbabilityTooltip = (specification, columnProp) => { + const keyWithSpec = `${columnProp}::${specification}`; + + if (!transitionProbabilitiesMap.value.has(keyWithSpec)) { + return ''; + } + + const transitionData = transitionProbabilitiesMap.value.get(keyWithSpec); + if (!transitionData || !transitionData.prediction) { + return ''; + } + + const { prediction, current_specification_transitions } = transitionData; + let tooltip = `最可能转移: ${prediction.most_likely_next_spec}\n概率: ${(prediction.probability * 100).toFixed(1)}%\n`; + + // 添加其他可能的转移选项 + if (current_specification_transitions) { + tooltip += '\n其他可能转移:\n'; + Object.entries(current_specification_transitions).forEach(([spec, data]) => { + if (spec !== prediction.most_likely_next_spec) { + tooltip += `${spec}: ${(data.probability * 100).toFixed(1)}% (${data.count}次)\n`; + } + }); + } + + return tooltip.trim(); +}; + // 方法:获取单元格悬停提示 const getCellTooltip = (specification, columnProp) => { // 构建包含规格的key @@ -555,7 +695,97 @@ const getDifferenceClass = (difference) => { return 'difference-zero'; // 黑色,无变化 }; -// 方法:处理单元格双击事件 +// 方法:处理单元格单击事件 - 获取转移概率数据 +const handleCellClick = async (row, column, cell, event) => { + const cellValue = row[column.property]; + + // 检查单元格是否有值 + if (!cellValue || cellValue === '-' || cellValue === null || cellValue === undefined) { + return; + } + + // 检查是否是规格列或总计列,这些列不需要获取转移概率 + if (column.property === 'specification' || column.property === 'total') { + return; + } + + // 从列属性中提取model和wire_disc + const columnKey = column.property; + const hasWireDisc = columnKey.includes('::'); + let model, wire_disc; + + if (hasWireDisc) { + [model, wire_disc] = columnKey.split('::'); + } else { + model = columnKey; + wire_disc = null; + } + + console.log('单击事件参数:', { + columnKey, + model, + wire_disc, + specification: row.specification + }); + + // 获取对应的机台信息和轴数 + const keyWithSpec = `${columnKey}::${row.specification}`; + let equipmentCode = 'QB002'; // 默认值 + let axleNumber = '左边'; // 默认值 + + if (uidProductionStatusMap.value.has(keyWithSpec)) { + const status = uidProductionStatusMap.value.get(keyWithSpec); + equipmentCode = status.equipment_code || 'QB002'; + axleNumber = status.axle_number || '左边'; + } + + console.log('获取转移概率参数:', { + equipmentCode, + axleNumber, + model, + specification: row.specification, + wireDisc: formatWireDisc(wire_disc || '') + }); + + // 检查是否已经获取过该单元格的转移概率数据 + if (transitionProbabilitiesMap.value.has(keyWithSpec)) { + console.log('该单元格的转移概率数据已存在,跳过API调用'); + return; + } + + // 获取转移概率数据 + const transitionData = await fetchTransitionProbabilities( + equipmentCode, + axleNumber, + model, + row.specification, + formatWireDisc(wire_disc || '') + ); + + if (transitionData && transitionData.current_specification_transitions) { + // 存储转移概率数据 + const transitionsKey = `${columnKey}::${row.specification}`; + transitionProbabilitiesMap.value.set(transitionsKey, transitionData); + + // 计算概率颜色 + const probabilities = transitionData.current_specification_transitions; + const maxProbability = Math.max(...Object.values(probabilities).map(p => p.probability)); + + Object.entries(probabilities).forEach(([targetSpec, data]) => { + const colorKey = `${transitionsKey}::${targetSpec}`; + const intensity = data.probability / maxProbability; // 0-1之间的强度值 + const color = getProbabilityColor(intensity); + transitionColorsMap.value.set(colorKey, color); + }); + + console.log('转移概率数据已存储:', transitionProbabilitiesMap.value); + console.log('概率颜色映射:', transitionColorsMap.value); + + ElMessage.success('转移概率数据已加载'); + } +}; + +// 方法:处理单元格双击事件 - 显示WMS详情 const handleCellDblClick = (row, column, cell, event) => { const cellValue = row[column.property];