|
|
|
@ -80,15 +80,15 @@
|
|
|
|
width="120"
|
|
|
|
width="120"
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
<el-table-column
|
|
|
|
<!-- <el-table-column
|
|
|
|
prop="wire_disc"
|
|
|
|
prop="wire_disc"
|
|
|
|
label="线盘"
|
|
|
|
label="线盘"
|
|
|
|
width="100"
|
|
|
|
width="100"
|
|
|
|
/>
|
|
|
|
/> -->
|
|
|
|
|
|
|
|
|
|
|
|
<el-table-column
|
|
|
|
<el-table-column
|
|
|
|
prop="wight_completion"
|
|
|
|
prop="wight_completion"
|
|
|
|
label="重量完成(kg)"
|
|
|
|
label="完成重量(kg)"
|
|
|
|
width="120"
|
|
|
|
width="120"
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<template #default="scope">
|
|
|
|
<template #default="scope">
|
|
|
|
@ -106,6 +106,36 @@
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-table-column
|
|
|
|
|
|
|
|
prop="total_number"
|
|
|
|
|
|
|
|
label="总箱数"
|
|
|
|
|
|
|
|
width="100"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
|
|
{{ scope.row.total_number || '-' }}
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-table-column
|
|
|
|
|
|
|
|
prop="total_net_weight"
|
|
|
|
|
|
|
|
label="总净重(kg)"
|
|
|
|
|
|
|
|
width="110"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
|
|
{{ scope.row.total_net_weight || '-' }}
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-table-column
|
|
|
|
|
|
|
|
prop="total_gross_weight"
|
|
|
|
|
|
|
|
label="总毛重(kg)"
|
|
|
|
|
|
|
|
width="110"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
|
|
{{ scope.row.total_gross_weight || '-' }}
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
|
|
|
|
<el-table-column
|
|
|
|
<el-table-column
|
|
|
|
prop="update_time"
|
|
|
|
prop="update_time"
|
|
|
|
label="更新时间"
|
|
|
|
label="更新时间"
|
|
|
|
@ -128,14 +158,54 @@
|
|
|
|
</el-tag>
|
|
|
|
</el-tag>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-table-column
|
|
|
|
|
|
|
|
label="销售历史"
|
|
|
|
|
|
|
|
width="100"
|
|
|
|
|
|
|
|
fixed="right"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
|
|
<el-button
|
|
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
|
|
@click="showSalesHistory(scope.row)"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
查看
|
|
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-table-column>
|
|
|
|
</el-table>
|
|
|
|
</el-table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 销售历史图表 -->
|
|
|
|
|
|
|
|
<div v-if="showChart" class="sales-chart-container">
|
|
|
|
|
|
|
|
<div class="chart-header">
|
|
|
|
|
|
|
|
<h4>销售历史 - {{ salesChartTitle }}</h4>
|
|
|
|
|
|
|
|
<el-button size="small" @click="closeChart">关闭</el-button>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="chart-controls">
|
|
|
|
|
|
|
|
<span class="filter-label">时间范围:</span>
|
|
|
|
|
|
|
|
<el-select v-model="selectedTimeRange" @change="onChartTimeRangeChange" style="width: 120px">
|
|
|
|
|
|
|
|
<el-option label="近1天" value="近1天" />
|
|
|
|
|
|
|
|
<el-option label="近3天" value="近3天" />
|
|
|
|
|
|
|
|
<el-option label="近1周" value="近1周" />
|
|
|
|
|
|
|
|
<el-option label="近1月" value="近1月" />
|
|
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div v-if="salesChartLoading" v-loading="true" class="chart-loading"></div>
|
|
|
|
|
|
|
|
<div v-else-if="!hasSalesData" class="no-data-message">
|
|
|
|
|
|
|
|
暂无销售数据
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div v-else ref="salesChartRef" class="chart"></div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
<script setup>
|
|
|
|
import { ref, computed, onMounted } from 'vue'
|
|
|
|
import { ref, computed, onMounted, nextTick, watch } from 'vue'
|
|
|
|
import { API_CONFIG } from "@/config/api"
|
|
|
|
import { API_CONFIG } from "@/config/api"
|
|
|
|
|
|
|
|
import { getDateRangeByTimeRange } from '@/utils/dateFormat';
|
|
|
|
|
|
|
|
import * as echarts from 'echarts';
|
|
|
|
|
|
|
|
|
|
|
|
// 接收从父组件传递的数据
|
|
|
|
// 接收从父组件传递的数据
|
|
|
|
const props = defineProps({
|
|
|
|
const props = defineProps({
|
|
|
|
@ -155,6 +225,17 @@ const selectedEquipment = ref('all')
|
|
|
|
// 完成度筛选相关状态
|
|
|
|
// 完成度筛选相关状态
|
|
|
|
const selectedCompletionLevel = ref('all') // 默认显示全部
|
|
|
|
const selectedCompletionLevel = ref('all') // 默认显示全部
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 销售图表相关状态
|
|
|
|
|
|
|
|
const showChart = ref(false)
|
|
|
|
|
|
|
|
const salesChartLoading = ref(false)
|
|
|
|
|
|
|
|
const salesData = ref([])
|
|
|
|
|
|
|
|
const hasSalesData = ref(false)
|
|
|
|
|
|
|
|
const selectedTimeRange = ref('近1周')
|
|
|
|
|
|
|
|
const salesChartTitle = ref('')
|
|
|
|
|
|
|
|
const currentSalesAxle = ref(null)
|
|
|
|
|
|
|
|
const salesChartRef = ref(null)
|
|
|
|
|
|
|
|
let salesChart = null
|
|
|
|
|
|
|
|
|
|
|
|
// 当组件加载时,使用父组件传递的数据
|
|
|
|
// 当组件加载时,使用父组件传递的数据
|
|
|
|
equipmentData.value = props.equipmentData
|
|
|
|
equipmentData.value = props.equipmentData
|
|
|
|
|
|
|
|
|
|
|
|
@ -327,6 +408,193 @@ const onCompletionLevelChange = () => {
|
|
|
|
console.log('选择的完成度:', selectedCompletionLevel.value);
|
|
|
|
console.log('选择的完成度:', selectedCompletionLevel.value);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 方法:显示销售历史图表
|
|
|
|
|
|
|
|
const showSalesHistory = (row) => {
|
|
|
|
|
|
|
|
if (!row.update_time || !row.model || !row.specification) {
|
|
|
|
|
|
|
|
console.error('缺少必要的数据参数');
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
currentSalesAxle.value = { ...row };
|
|
|
|
|
|
|
|
salesChartTitle.value = `${row.equipment_code} - ${row.axle_number} - ${row.specification} - ${row.model}`;
|
|
|
|
|
|
|
|
showChart.value = true;
|
|
|
|
|
|
|
|
fetchSalesData(row.model, row.specification);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 方法:关闭图表
|
|
|
|
|
|
|
|
const closeChart = () => {
|
|
|
|
|
|
|
|
showChart.value = false;
|
|
|
|
|
|
|
|
if (salesChart) {
|
|
|
|
|
|
|
|
salesChart.dispose();
|
|
|
|
|
|
|
|
salesChart = null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 方法:图表时间范围变化
|
|
|
|
|
|
|
|
const onChartTimeRangeChange = () => {
|
|
|
|
|
|
|
|
if (currentSalesAxle.value) {
|
|
|
|
|
|
|
|
fetchSalesData(currentSalesAxle.value.model, currentSalesAxle.value.specification);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 获取销量数据
|
|
|
|
|
|
|
|
const fetchSalesData = (model, specification) => {
|
|
|
|
|
|
|
|
salesChartLoading.value = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const dateRange = getDateRangeByTimeRange(selectedTimeRange.value);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let apiUrl = `${API_CONFIG.BASE_URL}/api/sale/records?model=${model}&specification=${specification}&start_date=${dateRange.start_date}&end_date=${dateRange.end_date}`;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
console.log('获取销量数据 URL:', apiUrl);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fetch(apiUrl)
|
|
|
|
|
|
|
|
.then(response => response.json())
|
|
|
|
|
|
|
|
.then(data => {
|
|
|
|
|
|
|
|
console.log('销量数据响应:', data);
|
|
|
|
|
|
|
|
if (data.code === 200 && data.data) {
|
|
|
|
|
|
|
|
salesData.value = data.data;
|
|
|
|
|
|
|
|
hasSalesData.value = salesData.value.length > 0;
|
|
|
|
|
|
|
|
console.log('销量数据:', salesData.value, 'hasSalesData:', hasSalesData.value);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (hasSalesData.value) {
|
|
|
|
|
|
|
|
nextTick(() => {
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
|
|
console.log('初始化图表,salesChartRef:', salesChartRef.value);
|
|
|
|
|
|
|
|
initSalesChart();
|
|
|
|
|
|
|
|
}, 100);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
salesData.value = [];
|
|
|
|
|
|
|
|
hasSalesData.value = false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.catch(error => {
|
|
|
|
|
|
|
|
console.error('销量数据API调用失败:', error);
|
|
|
|
|
|
|
|
salesData.value = [];
|
|
|
|
|
|
|
|
hasSalesData.value = false;
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.finally(() => {
|
|
|
|
|
|
|
|
salesChartLoading.value = false;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化销售图表
|
|
|
|
|
|
|
|
const initSalesChart = () => {
|
|
|
|
|
|
|
|
console.log('initSalesChart called, hasSalesData:', hasSalesData.value, 'data length:', salesData.value.length);
|
|
|
|
|
|
|
|
console.log('salesChartRef.value:', salesChartRef.value);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!hasSalesData.value || !salesData.value.length) {
|
|
|
|
|
|
|
|
console.log('没有销量数据,跳过图表初始化');
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!salesChartRef.value) {
|
|
|
|
|
|
|
|
console.warn('图表容器未渲染,尝试重新初始化');
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
|
|
initSalesChart();
|
|
|
|
|
|
|
|
}, 200);
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
console.log('开始初始化图表');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (salesChart) {
|
|
|
|
|
|
|
|
salesChart.dispose();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
salesChart = echarts.init(salesChartRef.value);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const dates = salesData.value.map(item => {
|
|
|
|
|
|
|
|
const date = new Date(item.date);
|
|
|
|
|
|
|
|
return `${date.getMonth() + 1}/${date.getDate()}`;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const boxCountData = salesData.value.map(item => item.box_count);
|
|
|
|
|
|
|
|
const weightData = salesData.value.map(item => item.weight);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
console.log('图表数据:', { dates, boxCountData, weightData });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const option = {
|
|
|
|
|
|
|
|
tooltip: {
|
|
|
|
|
|
|
|
trigger: 'axis',
|
|
|
|
|
|
|
|
axisPointer: {
|
|
|
|
|
|
|
|
type: 'cross'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
legend: {
|
|
|
|
|
|
|
|
data: ['箱数', '重量(kg)'],
|
|
|
|
|
|
|
|
top: 10
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
grid: {
|
|
|
|
|
|
|
|
left: '3%',
|
|
|
|
|
|
|
|
right: '4%',
|
|
|
|
|
|
|
|
bottom: '3%',
|
|
|
|
|
|
|
|
containLabel: true
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
xAxis: {
|
|
|
|
|
|
|
|
type: 'category',
|
|
|
|
|
|
|
|
data: dates,
|
|
|
|
|
|
|
|
axisLabel: {
|
|
|
|
|
|
|
|
interval: 0,
|
|
|
|
|
|
|
|
rotate: 30
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
yAxis: [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
type: 'value',
|
|
|
|
|
|
|
|
name: '箱数',
|
|
|
|
|
|
|
|
position: 'left',
|
|
|
|
|
|
|
|
axisLine: {
|
|
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
|
|
color: '#5470C6'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
type: 'value',
|
|
|
|
|
|
|
|
name: '重量(kg)',
|
|
|
|
|
|
|
|
position: 'right',
|
|
|
|
|
|
|
|
axisLine: {
|
|
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
|
|
color: '#91CC75'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
series: [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
name: '箱数',
|
|
|
|
|
|
|
|
type: 'bar',
|
|
|
|
|
|
|
|
data: boxCountData,
|
|
|
|
|
|
|
|
itemStyle: {
|
|
|
|
|
|
|
|
color: '#5470C6'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
name: '重量(kg)',
|
|
|
|
|
|
|
|
type: 'line',
|
|
|
|
|
|
|
|
yAxisIndex: 1,
|
|
|
|
|
|
|
|
data: weightData,
|
|
|
|
|
|
|
|
itemStyle: {
|
|
|
|
|
|
|
|
color: '#91CC75'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
salesChart.setOption(option);
|
|
|
|
|
|
|
|
console.log('图表已渲染');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
window.addEventListener('resize', () => {
|
|
|
|
|
|
|
|
if (salesChart) {
|
|
|
|
|
|
|
|
salesChart.resize();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 方法:格式化日期时间
|
|
|
|
// 方法:格式化日期时间
|
|
|
|
const formatDateTime = (dateTimeStr) => {
|
|
|
|
const formatDateTime = (dateTimeStr) => {
|
|
|
|
if (!dateTimeStr) return '';
|
|
|
|
if (!dateTimeStr) return '';
|
|
|
|
@ -377,6 +645,17 @@ onMounted(() => {
|
|
|
|
// 如果组件是通过按钮点击加载的,则不需要在挂载时获取数据
|
|
|
|
// 如果组件是通过按钮点击加载的,则不需要在挂载时获取数据
|
|
|
|
// 因为数据已经通过父组件的 handleEnamellingMachineStatus 方法获取了
|
|
|
|
// 因为数据已经通过父组件的 handleEnamellingMachineStatus 方法获取了
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 监听图表显示状态,初始化图表
|
|
|
|
|
|
|
|
watch(showChart, (newValue) => {
|
|
|
|
|
|
|
|
if (newValue && hasSalesData.value) {
|
|
|
|
|
|
|
|
nextTick(() => {
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
|
|
initSalesChart();
|
|
|
|
|
|
|
|
}, 100);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
<style scoped>
|
|
|
|
@ -446,4 +725,51 @@ onMounted(() => {
|
|
|
|
padding: 8px 0;
|
|
|
|
padding: 8px 0;
|
|
|
|
white-space: nowrap;
|
|
|
|
white-space: nowrap;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.sales-chart-container {
|
|
|
|
|
|
|
|
margin-top: 20px;
|
|
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
|
|
background-color: #f5f7fa;
|
|
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.chart-header {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.chart-header h4 {
|
|
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.chart-controls {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.chart-loading {
|
|
|
|
|
|
|
|
height: 300px;
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.no-data-message {
|
|
|
|
|
|
|
|
height: 300px;
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
|
|
color: #909399;
|
|
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.chart {
|
|
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
height: 350px;
|
|
|
|
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
</style>
|