feat(RealTimeInventory): 添加转移概率数据展示功能

- 新增转移概率API调用方法fetchTransitionProbabilities
- 添加单元格单击事件处理handleCellClick获取概率数据
- 实现概率数据存储和颜色映射功能
- 扩展单元格提示信息显示转移概率详情
- 根据概率值动态计算单元格背景颜色
master
huangjinysf 2 months ago
parent ebe0cda336
commit c1a1c894e3

@ -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) : '')"
>
<span v-if="!showDifference">
{{ 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;
}
// modelwire_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];

Loading…
Cancel
Save