diff --git a/src/views/plan/RealTimeInventory.vue b/src/views/plan/RealTimeInventory.vue index e956479..a143fcf 100644 --- a/src/views/plan/RealTimeInventory.vue +++ b/src/views/plan/RealTimeInventory.vue @@ -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 = `
${echarts.format.formatTime('yyyy-MM-dd hh:mm', params[0].value[0])}
`; - - params.forEach(param => { - const seriesName = param.seriesName; - const value = param.value[1]; - const unit = chartUnit.value === 'box' ? '箱' : 'kg'; - - result += `
- - ${seriesName}: ${value}${unit} -
`; - }); - - 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 = `
${echarts.format.formatTime('yyyy-MM-dd hh:mm', params[0].value[0])}
`; + + params.forEach(param => { + const seriesName = param.seriesName; + const value = param.value[1]; + const unit = chartUnit.value === 'box' ? '箱' : 'kg'; + + result += `
+ + ${seriesName}: ${value}${unit} +
`; + }); + + 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);