|
|
@@ -36,12 +36,21 @@
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
|
|
|
-<!-- <el-form-item>-->
|
|
|
-<!-- <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>-->
|
|
|
-<!-- <el-button icon="Refresh" @click="resetQuery">重置</el-button>-->
|
|
|
-<!-- </el-form-item>-->
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="success" @click="viewTrend">查看近5日织造米数</el-button>
|
|
|
+ </el-form-item>
|
|
|
</el-form>
|
|
|
|
|
|
+ <!-- 图表弹窗 -->
|
|
|
+ <el-dialog title="近5日织造米数趋势图" v-model="chartDialogVisible" width="800px" append-to-body>
|
|
|
+ <div ref="chartRef" style="width: 100%; height: 400px;"></div>
|
|
|
+ <template #footer>
|
|
|
+ <div class="dialog-footer">
|
|
|
+ <el-button @click="closeChartDialog">关闭</el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
<el-table v-loading="loading" :data="calcSpecList" show-summary :summary-method="getSummaries"
|
|
|
@selection-change="handleSelectionChange">
|
|
|
<el-table-column label="日期" align="center" prop="dataDate" width="180">
|
|
|
@@ -107,8 +116,10 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup name="CalcSpec">
|
|
|
-import {addCalcSpec, delCalcSpec, getCalcSpec, listCalcSpec, updateCalcSpec} from "@/api/calc/calcSpec";
|
|
|
+import {addCalcSpec, delCalcSpec, getCalcSpec, listCalcSpec, updateCalcSpec,trend} from "@/api/calc/calcSpec";
|
|
|
import {listDevice} from "@/api/biz/device"
|
|
|
+import * as echarts from 'echarts';
|
|
|
+import { nextTick } from 'vue';
|
|
|
|
|
|
const {proxy} = getCurrentInstance();
|
|
|
const {in_out_time} = proxy.useDict('in_out_time');
|
|
|
@@ -122,6 +133,10 @@ const multiple = ref(true);
|
|
|
const total = ref(0);
|
|
|
const title = ref("");
|
|
|
const deviceOptions = ref([]);
|
|
|
+const chartRef = ref(null);
|
|
|
+let chartInstance = null;
|
|
|
+const chartDialogVisible = ref(false);
|
|
|
+const trendData = ref({});
|
|
|
|
|
|
const data = reactive({
|
|
|
form: {},
|
|
|
@@ -202,6 +217,241 @@ function getList() {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+/**查询趋势*/
|
|
|
+function viewTrend(){
|
|
|
+ trend(queryParams.value).then(response => {
|
|
|
+ // 保存数据并显示图表弹窗
|
|
|
+ trendData.value = response;
|
|
|
+ chartDialogVisible.value = true;
|
|
|
+ // 等待DOM更新后初始化图表
|
|
|
+ nextTick(() => {
|
|
|
+ initChart(response);
|
|
|
+ });
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+// 关闭图表弹窗
|
|
|
+function closeChartDialog() {
|
|
|
+ chartDialogVisible.value = false;
|
|
|
+ // 销毁图表实例
|
|
|
+ if (chartInstance) {
|
|
|
+ chartInstance.dispose();
|
|
|
+ chartInstance = null;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 初始化图表
|
|
|
+function initChart(data) {
|
|
|
+ // 销毁之前的图表实例
|
|
|
+ if (chartInstance) {
|
|
|
+ chartInstance.dispose();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 初始化新的图表实例
|
|
|
+ chartInstance = echarts.init(chartRef.value);
|
|
|
+
|
|
|
+ console.log('传入initChart的数据:', data); // 调试信息
|
|
|
+
|
|
|
+ // 处理数据 - 修正数据访问路径
|
|
|
+ let responseData = data.data.data;
|
|
|
+
|
|
|
+ const timestamps = responseData.timestamps || [];
|
|
|
+ const values = responseData.values || [];
|
|
|
+
|
|
|
+ console.log('提取的原始数据:', { timestamps, values }); // 调试信息
|
|
|
+
|
|
|
+ // 将时间戳转换为日期字符串 (mm-dd hh:mm格式)
|
|
|
+ const dates = timestamps.map(timestamp => {
|
|
|
+ const date = new Date(timestamp);
|
|
|
+ const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
|
|
+ const day = date.getDate().toString().padStart(2, '0');
|
|
|
+ const hours = date.getHours().toString().padStart(2, '0');
|
|
|
+ const minutes = date.getMinutes().toString().padStart(2, '0');
|
|
|
+ return `${month}-${day} ${hours}:${minutes}`;
|
|
|
+ });
|
|
|
+
|
|
|
+ // 提取数值(处理嵌套数组)
|
|
|
+ const chartValues = [];
|
|
|
+ const validDates = [];
|
|
|
+
|
|
|
+ values.forEach((item, index) => {
|
|
|
+ // 检查是否有足够的数据点
|
|
|
+ if (Array.isArray(item) && item.length > 0) {
|
|
|
+ // 获取第一个元素并尝试转为数字
|
|
|
+ const rawValue = item[0];
|
|
|
+ const numericValue = parseFloat(rawValue);
|
|
|
+
|
|
|
+ // 检查转换后的值是否有效
|
|
|
+ if (!isNaN(numericValue)) {
|
|
|
+ chartValues.push(numericValue);
|
|
|
+ validDates.push(dates[index]);
|
|
|
+ } else if (typeof rawValue === 'number' && !isNaN(rawValue)) {
|
|
|
+ // 如果本身就是数字
|
|
|
+ chartValues.push(rawValue);
|
|
|
+ validDates.push(dates[index]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ console.log('处理后的图表数据:', { validDates, chartValues }); // 调试信息
|
|
|
+
|
|
|
+ // 如果没有有效数据,显示提示
|
|
|
+ if (validDates.length === 0 && chartValues.length === 0) {
|
|
|
+ chartInstance.setOption({
|
|
|
+ title: {
|
|
|
+ text: '暂无有效数据',
|
|
|
+ left: 'center',
|
|
|
+ top: 'center'
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算默认显示的时间范围(根据选择的日期和时段)
|
|
|
+ let startIndex = 0;
|
|
|
+ let endIndex = validDates.length - 1;
|
|
|
+
|
|
|
+ if (queryParams.value.dataDate && queryParams.value.remark) {
|
|
|
+ // 解析时段,例如 "7-19" 或 "23-7"
|
|
|
+ const timeRange = queryParams.value.remark.split('-');
|
|
|
+ if (timeRange.length === 2) {
|
|
|
+ const startTime = parseInt(timeRange[0]);
|
|
|
+ const endTime = parseInt(timeRange[1]);
|
|
|
+
|
|
|
+ // 构造选择的日期
|
|
|
+ const selectedDate = new Date(queryParams.value.dataDate);
|
|
|
+ const month = (selectedDate.getMonth() + 1).toString().padStart(2, '0');
|
|
|
+ const day = selectedDate.getDate().toString().padStart(2, '0');
|
|
|
+
|
|
|
+ // 判断是否是跨天时段(如23-7)
|
|
|
+ if (startTime > endTime) {
|
|
|
+ // 跨天时段处理,例如 23-7 表示当天23点到次日7点
|
|
|
+ // 查找当天23点开始的数据
|
|
|
+ const startDateTime = `${month}-${day} ${startTime.toString().padStart(2, '0')}:00`;
|
|
|
+ const startTimeIndex = validDates.findIndex(date => date.startsWith(startDateTime));
|
|
|
+ if (startTimeIndex !== -1) {
|
|
|
+ startIndex = startTimeIndex;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查找次日7点的数据
|
|
|
+ const nextDay = new Date(selectedDate);
|
|
|
+ nextDay.setDate(nextDay.getDate() + 1);
|
|
|
+ const nextMonth = (nextDay.getMonth() + 1).toString().padStart(2, '0');
|
|
|
+ const nextDayStr = nextDay.getDate().toString().padStart(2, '0');
|
|
|
+ const endDateTime = `${nextMonth}-${nextDayStr} ${endTime.toString().padStart(2, '0')}:00`;
|
|
|
+ const endTimeIndex = validDates.findIndex(date => date.startsWith(endDateTime));
|
|
|
+ if (endTimeIndex !== -1) {
|
|
|
+ endIndex = endTimeIndex;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 正常时段处理,例如 7-19 表示当天7点到19点
|
|
|
+ // 查找开始时间索引
|
|
|
+ const startDateTime = `${month}-${day} ${startTime.toString().padStart(2, '0')}:00`;
|
|
|
+ const startTimeIndex = validDates.findIndex(date => date.startsWith(startDateTime));
|
|
|
+ if (startTimeIndex !== -1) {
|
|
|
+ startIndex = startTimeIndex;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查找结束时间索引
|
|
|
+ const endDateTime = `${month}-${day} ${endTime.toString().padStart(2, '0')}:00`;
|
|
|
+ const endTimeIndex = validDates.findIndex(date => date.startsWith(endDateTime));
|
|
|
+ if (endTimeIndex !== -1) {
|
|
|
+ endIndex = endTimeIndex;
|
|
|
+ } else {
|
|
|
+ // 如果找不到确切的结束时间,尝试查找最接近的时间点
|
|
|
+ for (let i = validDates.length - 1; i >= 0; i--) {
|
|
|
+ if (validDates[i].startsWith(`${month}-${day}`)) {
|
|
|
+ endIndex = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 确保索引范围合理
|
|
|
+ if (startIndex >= endIndex) {
|
|
|
+ endIndex = Math.min(startIndex + 10, validDates.length - 1); // 默认显示10个点
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 配置图表选项 - 遵循项目规范
|
|
|
+ const option = {
|
|
|
+ title: {
|
|
|
+ text: '近5日织造米数趋势图',
|
|
|
+ left: 'center'
|
|
|
+ },
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'axis',
|
|
|
+ formatter: function (params) {
|
|
|
+ const date = params[0].axisValue;
|
|
|
+ const value = params[0].data;
|
|
|
+ return `${date}<br/>织造米数: ${value}`;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ dataZoom: [
|
|
|
+ {
|
|
|
+ type: 'inside',
|
|
|
+ startValue: startIndex,
|
|
|
+ endValue: endIndex
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'slider',
|
|
|
+ startValue: startIndex,
|
|
|
+ endValue: endIndex,
|
|
|
+ bottom: 10
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ data: validDates.length > 0 ? validDates : dates, // 如果有有效日期则使用,否则使用全部日期
|
|
|
+ name: '时间',
|
|
|
+ axisLabel: {
|
|
|
+ formatter: '{value}',
|
|
|
+ rotate: 45 // 旋转标签以避免重叠
|
|
|
+ },
|
|
|
+ splitLine: {
|
|
|
+ show: false // 遵循规范:不显示网格线
|
|
|
+ }
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: 'value',
|
|
|
+ name: '织造米数',
|
|
|
+ splitLine: {
|
|
|
+ show: false // 遵循规范:不显示网格线
|
|
|
+ }
|
|
|
+ },
|
|
|
+ series: [{
|
|
|
+ data: chartValues.length > 0 ? chartValues : values, // 如果有处理后的数据则使用,否则使用原始数据
|
|
|
+ type: 'line',
|
|
|
+ smooth: true,
|
|
|
+ showSymbol: false, // 遵循规范:不显示数据点小圆圈
|
|
|
+ itemStyle: {
|
|
|
+ color: '#409EFF'
|
|
|
+ },
|
|
|
+ markPoint: {
|
|
|
+ data: [
|
|
|
+ {type: 'max', name: '最大值', itemStyle: {color: '#F56C6C'}},
|
|
|
+ {type: 'min', name: '最小值', itemStyle: {color: '#67C23A'}}
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ markLine: {
|
|
|
+ data: [
|
|
|
+ {type: 'average', name: '平均值'}
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ }]
|
|
|
+ };
|
|
|
+
|
|
|
+ // 设置图表配置
|
|
|
+ chartInstance.setOption(option);
|
|
|
+
|
|
|
+ // 监听窗口大小变化,自适应图表
|
|
|
+ window.addEventListener('resize', () => {
|
|
|
+ chartInstance.resize();
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
//自定义方法
|
|
|
function getSummaries(param) {
|
|
|
const {columns, data} = param;
|