feat(RealTimeInventory): 添加销售数据展示并与库存历史趋势对比

- 新增销售数据获取API接口调用
- 在图表中同时展示库存历史趋势和销售数据
- 优化图表配置以支持多系列数据显示
- 添加销售数据相关状态管理
master
huangjinysf 2 months ago
parent f6550cd819
commit 04d29f5aae

@ -155,8 +155,11 @@ const wmsTableRef = ref(null)
//
const inventoryChartRef = ref(null)
const historyChartLoading = ref(false)
const salesChartLoading = ref(false)
const historyData = ref([])
const salesData = ref([])
const hasHistoryData = ref(false)
const hasSalesData = ref(false)
const selectedTimeRange = ref('近1月')
const chartUnit = ref('box')
let inventoryChart = null
@ -401,6 +404,65 @@ const handleCellDblClick = (row, column, cell, event) => {
fetchInventoryHistoryData(model, row.specification, wire_disc);
};
//
const fetchSalesData = (model, specification) => {
salesChartLoading.value = true;
const dateRange = getDateRangeByTimeRange(selectedTimeRange.value);
// API URL
const params = new URLSearchParams({
model: model || '',
specification: specification || '',
start_date: dateRange.start_date,
end_date: dateRange.end_date
});
let apiUrl = `${API_CONFIG.BASE_URL}/api/sale/records?${params.toString()}`;
console.log('销售数据API调用参数:', {
model,
specification,
dateRange,
apiUrl
});
fetch(apiUrl)
.then(response => response.json())
.then(data => {
console.log('销售数据API原始返回数据:', data);
if (data.code === 200 && data.data) {
let records = data.data;
console.log('销售原始数据:', records);
console.log('销售记录数量:', records.length);
//
if (records.length > 0) {
console.log('销售第一条记录结构:', records[0]);
console.log('销售第一条记录的所有键:', Object.keys(records[0]));
}
salesData.value = records;
hasSalesData.value = salesData.value.length > 0;
console.log('设置后的salesData:', salesData.value);
console.log('hasSalesData:', hasSalesData.value);
} else {
console.error('销售数据API返回数据格式错误:', data);
salesData.value = [];
hasSalesData.value = false;
}
})
.catch(error => {
console.error('销量数据API调用失败:', error);
salesData.value = [];
hasSalesData.value = false;
})
.finally(() => {
salesChartLoading.value = false;
});
};
//
const fetchInventoryHistoryData = (model, specification, wireDisc) => {
historyChartLoading.value = true;
@ -418,7 +480,7 @@ const fetchInventoryHistoryData = (model, specification, wireDisc) => {
let apiUrl = `${API_CONFIG.BASE_URL}/api/plan/wms/history?${params.toString()}`;
console.log('API调用参数:', {
console.log('库存历史API调用参数:', {
model,
specification,
wireDisc,
@ -426,21 +488,48 @@ const fetchInventoryHistoryData = (model, specification, wireDisc) => {
apiUrl
});
fetch(apiUrl)
//
Promise.all([
fetchInventoryHistoryAPI(apiUrl),
fetchSalesData(model, specification)
]).then(() => {
nextTick(() => {
setTimeout(() => {
console.log('开始初始化图表');
initInventoryChart();
}, 100);
});
}).catch(error => {
console.error('数据获取失败:', error);
historyData.value = [];
hasHistoryData.value = false;
salesData.value = [];
hasSalesData.value = false;
}).finally(() => {
historyChartLoading.value = false;
});
};
// API
const fetchInventoryHistoryAPI = (apiUrl) => {
return fetch(apiUrl)
.then(response => response.json())
.then(data => {
console.log('API原始返回数据:', data);
console.log('库存历史API原始返回数据:', data);
if (data.code === 200 && data.data && data.data.records) {
let records = data.data.records;
console.log('原始records数据:', records);
console.log('records数量:', records.length);
console.log('库存历史原始records数据:', records);
console.log('库存历史records数量:', records.length);
//
if (records.length > 0) {
console.log('第一条记录结构:', records[0]);
console.log('第一条记录的所有键:', Object.keys(records[0]));
console.log('库存历史第一条记录结构:', records[0]);
console.log('库存历史第一条记录的所有键:', Object.keys(records[0]));
}
//
const dateRange = getDateRangeByTimeRange(selectedTimeRange.value);
// 使
if (isMoreThanOneWeek(dateRange.start_date, dateRange.end_date)) {
records = downsampleHistoryToKeyTimes(records);
@ -452,17 +541,8 @@ const fetchInventoryHistoryData = (model, specification, wireDisc) => {
console.log('设置后的historyData:', historyData.value);
console.log('hasHistoryData:', hasHistoryData.value);
nextTick(() => {
setTimeout(() => {
console.log('开始初始化图表');
initInventoryChart();
}, 100);
});
} else {
console.error('API返回数据格式错误:', data);
console.error('data.code:', data.code);
console.error('data.data:', data.data);
console.error('库存历史API返回数据格式错误:', data);
historyData.value = [];
hasHistoryData.value = false;
}
@ -471,9 +551,6 @@ const fetchInventoryHistoryData = (model, specification, wireDisc) => {
console.error('库存历史数据API调用失败:', error);
historyData.value = [];
hasHistoryData.value = false;
})
.finally(() => {
historyChartLoading.value = false;
});
};
@ -571,46 +648,50 @@ const initInventoryChart = () => {
//
const option = {
title: {
text: '库存历史趋势',
left: 'center',
textStyle: {
fontSize: 16,
fontWeight: 'bold'
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
},
formatter: function(params) {
let result = `<div style="margin-bottom: 5px;"><strong>${echarts.format.formatTime('yyyy-MM-dd hh:mm', params[0].value[0])}</strong></div>`;
params.forEach(param => {
const seriesName = param.seriesName;
const value = param.value[1];
const unit = chartUnit.value === 'box' ? '箱' : 'kg';
result += `<div style="margin: 3px 0;">
<span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${param.color};"></span>
${seriesName}: ${value}${unit}
</div>`;
});
return result;
}
},
legend: {
data: ['库存'],
top: 30
},
title: {
text: '库存历史趋势与销售对比',
left: 'center',
textStyle: {
fontSize: 16,
fontWeight: 'bold'
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
},
formatter: function(params) {
let result = `<div style="margin-bottom: 5px;"><strong>${echarts.format.formatTime('yyyy-MM-dd hh:mm', params[0].value[0])}</strong></div>`;
params.forEach(param => {
const seriesName = param.seriesName;
const value = param.value[1];
const unit = chartUnit.value === 'box' ? '箱' : 'kg';
result += `<div style="margin: 3px 0;">
<span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${param.color};"></span>
${seriesName}: ${value}${unit}
</div>`;
});
return result;
}
},
legend: {
data: chartData.map(s => s.name),
right: 10,
top: 30,
textStyle: {
fontSize: 12
}
},
grid: {
left: '3%',
right: '4%',
right: '15%',
bottom: '3%',
containLabel: true
},
@ -660,29 +741,32 @@ const prepareInventoryChartData = () => {
console.log('prepareInventoryChartData 被调用');
console.log('hasHistoryData.value:', hasHistoryData.value);
console.log('historyData.value.length:', historyData.value ? historyData.value.length : 0);
console.log('hasSalesData.value:', hasSalesData.value);
console.log('salesData.value.length:', salesData.value ? salesData.value.length : 0);
const series = [];
//
if (hasHistoryData.value && historyData.value.length > 0) {
console.log('开始处理历史数据');
console.log('第一条历史数据示例:', historyData.value[0]);
console.log('开始处理库存历史数据');
console.log('第一条库存历史数据示例:', historyData.value[0]);
const historySeriesData = historyData.value.map((item, index) => {
console.log(`处理${index}条数据:`, item);
console.log(`处理库存历史${index}条数据:`, item);
//
const timeField = item.create_time || item.createTime || item.time || item.timestamp;
const boxCountField = item.box_count || item.boxCount || item.box || item.count || item.total_number;
const weightField = item.total_weight || item.totalWeight || item.weight || item.total_net_weight || item.totalGrossWeight;
// console.log(':', {
// timeField,
// boxCountField,
// weightField
// });
console.log('库存字段映射检查:', {
timeField,
boxCountField,
weightField
});
if (!timeField) {
// console.warn(`${index}`);
console.warn(`库存历史第${index}条数据缺少时间字段`);
return null;
}
@ -695,18 +779,18 @@ const prepareInventoryChartData = () => {
value = weightField || 0;
}
console.log(`时间戳: ${time}, 值: ${value}`);
console.log(`库存时间戳: ${time}, 值: ${value}`);
if (isNaN(time) || time <= 0) {
console.warn(`${index}条数据时间格式无效:`, timeField);
console.warn(`库存历史${index}条数据时间格式无效:`, timeField);
return null;
}
return [time, value];
}).filter(item => item !== null); //
// console.log(':', historySeriesData);
// console.log(':', historySeriesData.length);
console.log('库存历史转换后的图表数据:', historySeriesData);
console.log('库存历史有效数据点数量:', historySeriesData.length);
if (historySeriesData.length > 0) {
series.push({
@ -728,12 +812,77 @@ const prepareInventoryChartData = () => {
])
}
});
console.log('成功创建图表序列');
console.log('成功创建库存图表序列');
} else {
console.warn('没有有效的库存图表数据');
}
} else {
console.warn('没有库存历史数据或库存历史数据为空');
}
//
if (hasSalesData.value && salesData.value.length > 0) {
console.log('开始处理销售数据');
console.log('第一条销售数据示例:', salesData.value[0]);
const salesSeriesData = salesData.value.map((item, index) => {
console.log(`处理销售第${index}条数据:`, item);
//
const timeField = item.date || item.create_time || item.createTime || item.time || item.timestamp;
const boxCountField = item.box_count || item.boxCount || item.box || item.count;
const weightField = item.weight || item.total_weight || item.totalWeight;
console.log('销售字段映射检查:', {
timeField,
boxCountField,
weightField
});
if (!timeField) {
console.warn(`销售第${index}条数据缺少时间字段`);
return null;
}
const time = new Date(timeField).getTime();
let value;
if (chartUnit.value === 'box') {
value = boxCountField || 0;
} else {
value = weightField || 0;
}
console.log(`销售时间戳: ${time}, 值: ${value}`);
if (isNaN(time) || time <= 0) {
console.warn(`销售第${index}条数据时间格式无效:`, timeField);
return null;
}
return [time, value];
}).filter(item => item !== null); //
console.log('销售转换后的图表数据:', salesSeriesData);
console.log('销售有效数据点数量:', salesSeriesData.length);
if (salesSeriesData.length > 0) {
series.push({
name: '销售',
type: 'bar',
data: salesSeriesData,
barWidth: 8,
itemStyle: {
color: '#F56C6C',
borderRadius: [2, 2, 0, 0]
}
});
console.log('成功创建销售图表序列');
} else {
console.warn('没有有效的图表数据');
console.warn('没有有效的销售图表数据');
}
} else {
console.warn('没有历史数据或历史数据为空');
console.warn('没有销售数据或销售数据为空');
}
console.log('最终返回的series:', series);

Loading…
Cancel
Save