fix: 功能优化,新增数据查询、设备属性、报警设置3个按钮及对应功能修改。
This commit is contained in:
1
components.d.ts
vendored
1
components.d.ts
vendored
@@ -9,6 +9,7 @@ declare module 'vue' {
|
|||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
ChartFullscreen: typeof import('./src/components/other/chartFullscreen.vue')['default']
|
ChartFullscreen: typeof import('./src/components/other/chartFullscreen.vue')['default']
|
||||||
CustomNavigationBar: typeof import('./src/components/custom-navigation-bar/index.vue')['default']
|
CustomNavigationBar: typeof import('./src/components/custom-navigation-bar/index.vue')['default']
|
||||||
|
DataQuery: typeof import('./src/components/other/dataQuery.vue')['default']
|
||||||
Fish: typeof import('./src/components/other/fish.vue')['default']
|
Fish: typeof import('./src/components/other/fish.vue')['default']
|
||||||
NutBadge: typeof import('@nutui/nutui-taro')['Badge']
|
NutBadge: typeof import('@nutui/nutui-taro')['Badge']
|
||||||
NutButton: typeof import('@nutui/nutui-taro')['Button']
|
NutButton: typeof import('@nutui/nutui-taro')['Button']
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ export default defineAppConfig({
|
|||||||
'pages/msg/index',
|
'pages/msg/index',
|
||||||
'pages/main/my',
|
'pages/main/my',
|
||||||
'components/other/chartFullscreen',
|
'components/other/chartFullscreen',
|
||||||
|
'components/other/dataQuery',
|
||||||
],
|
],
|
||||||
requiredPrivateInfos: [
|
requiredPrivateInfos: [
|
||||||
"getLocation", "chooseLocation"
|
"getLocation", "chooseLocation"
|
||||||
|
|||||||
5
src/components/other/dataQuery.config.ts
Normal file
5
src/components/other/dataQuery.config.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export default definePageConfig({
|
||||||
|
navigationStyle: 'custom',
|
||||||
|
pageOrientation: 'landscape',
|
||||||
|
disableScroll: true,
|
||||||
|
})
|
||||||
617
src/components/other/dataQuery.vue
Normal file
617
src/components/other/dataQuery.vue
Normal file
@@ -0,0 +1,617 @@
|
|||||||
|
<template>
|
||||||
|
<view class="data-query-page" :style="pageStyle">
|
||||||
|
<!-- 顶部标题栏 -->
|
||||||
|
<view class="header">
|
||||||
|
<view class="back-btn" @click="goBack">
|
||||||
|
<text class="icon">←</text>
|
||||||
|
</view>
|
||||||
|
<view class="title">{{ chartTitle }}</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 查询条件区域 -->
|
||||||
|
<view class="query-section">
|
||||||
|
<view class="query-container">
|
||||||
|
<view class="query-item">
|
||||||
|
<view class="query-label">开始时间</view>
|
||||||
|
<view class="query-value" @click="showStartPicker = true">
|
||||||
|
{{ startDate || '请选择' }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="query-item">
|
||||||
|
<view class="query-label">结束时间</view>
|
||||||
|
<view class="query-value" @click="showEndPicker = true">
|
||||||
|
{{ endDate || '请选择' }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<nut-button
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
class="query-btn"
|
||||||
|
@click="queryData"
|
||||||
|
>
|
||||||
|
查询
|
||||||
|
</nut-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 图表容器 -->
|
||||||
|
<view class="chart-container" :style="chartContainerStyle">
|
||||||
|
<view class="loading-container" v-show="loading">
|
||||||
|
<text>加载中...</text>
|
||||||
|
</view>
|
||||||
|
<canvas
|
||||||
|
v-if="!loading"
|
||||||
|
class="chart-canvas"
|
||||||
|
type="2d"
|
||||||
|
id="data-query-chart"
|
||||||
|
:style="canvasStyle"
|
||||||
|
></canvas>
|
||||||
|
<view v-if="!loading && (!chartData || chartData.length === 0)" class="empty-data">
|
||||||
|
<text>暂无数据</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 开始时间选择器 -->
|
||||||
|
<nut-popup v-model:visible="showStartPicker" position="bottom">
|
||||||
|
<nut-date-picker
|
||||||
|
v-model="startDateTime"
|
||||||
|
type="datetime"
|
||||||
|
title="选择开始时间"
|
||||||
|
:min-date="minDate"
|
||||||
|
:max-date="maxDate"
|
||||||
|
@confirm="confirmStartDate"
|
||||||
|
@cancel="showStartPicker = false"
|
||||||
|
/>
|
||||||
|
</nut-popup>
|
||||||
|
|
||||||
|
<!-- 结束时间选择器 -->
|
||||||
|
<nut-popup v-model:visible="showEndPicker" position="bottom">
|
||||||
|
<nut-date-picker
|
||||||
|
v-model="endDateTime"
|
||||||
|
type="datetime"
|
||||||
|
title="选择结束时间"
|
||||||
|
:min-date="minDate"
|
||||||
|
:max-date="maxDate"
|
||||||
|
@confirm="confirmEndDate"
|
||||||
|
@cancel="showEndPicker = false"
|
||||||
|
/>
|
||||||
|
</nut-popup>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed, onMounted, onUnmounted } from 'vue';
|
||||||
|
import Taro from '@tarojs/taro';
|
||||||
|
import { deviceHistory } from '@/api/device';
|
||||||
|
import { formatDateMin } from '@/utils/tools';
|
||||||
|
import uCharts from '@/utils/js-sdk/u-charts/u-charts.js';
|
||||||
|
|
||||||
|
const chartTitle = ref('数据查询');
|
||||||
|
const chartData = ref<any[]>([]);
|
||||||
|
const loading = ref(false);
|
||||||
|
let chartInstance: any = null;
|
||||||
|
|
||||||
|
// 接收的参数
|
||||||
|
const serialNum = ref('');
|
||||||
|
const dataType = ref(1); // 1-溶解氧, 2-水温, 3-饱和度, 4-PH, 5-盐度
|
||||||
|
const deviceName = ref('');
|
||||||
|
const oxyWarnLower = ref<number | null>(null);
|
||||||
|
const tempWarnUpper = ref<number | null>(null);
|
||||||
|
const tempWarnLower = ref<number | null>(null);
|
||||||
|
|
||||||
|
// 时间选择
|
||||||
|
const showStartPicker = ref(false);
|
||||||
|
const showEndPicker = ref(false);
|
||||||
|
const startDate = ref('');
|
||||||
|
const endDate = ref('');
|
||||||
|
const startDateTime = ref(new Date(new Date().getTime() - 30 * 24 * 60 * 60 * 1000));
|
||||||
|
const endDateTime = ref(new Date());
|
||||||
|
|
||||||
|
// 日期范围限制(最近90天到当前)
|
||||||
|
const minDate = computed(() => new Date(new Date().getTime() - 90 * 24 * 60 * 60 * 1000));
|
||||||
|
const maxDate = computed(() => new Date());
|
||||||
|
|
||||||
|
// 屏幕尺寸
|
||||||
|
const screenWidth = ref(375);
|
||||||
|
const screenHeight = ref(667);
|
||||||
|
|
||||||
|
// 页面样式
|
||||||
|
const pageStyle = computed(() => {
|
||||||
|
return {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
background: '#fff',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column' as const,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const chartContainerStyle = computed(() => {
|
||||||
|
return {
|
||||||
|
flex: '1',
|
||||||
|
padding: '10px 15px',
|
||||||
|
background: '#fff',
|
||||||
|
overflow: 'hidden',
|
||||||
|
position: 'relative' as const,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const canvasStyle = computed(() => {
|
||||||
|
return {
|
||||||
|
width: chartWidth.value + 'px',
|
||||||
|
height: chartHeight.value + 'px',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// 获取屏幕尺寸
|
||||||
|
const sysInfo = Taro.getSystemInfoSync();
|
||||||
|
screenWidth.value = sysInfo.windowWidth;
|
||||||
|
screenHeight.value = sysInfo.windowHeight;
|
||||||
|
|
||||||
|
// 获取页面参数
|
||||||
|
const instance = Taro.getCurrentInstance();
|
||||||
|
const params = instance.router?.params || {};
|
||||||
|
|
||||||
|
serialNum.value = params.serialNum || '';
|
||||||
|
dataType.value = Number(params.dataType) || 1;
|
||||||
|
deviceName.value = params.deviceName || '';
|
||||||
|
oxyWarnLower.value = params.oxyWarnLower ? Number(params.oxyWarnLower) : null;
|
||||||
|
tempWarnUpper.value = params.tempWarnUpper ? Number(params.tempWarnUpper) : null;
|
||||||
|
tempWarnLower.value = params.tempWarnLower ? Number(params.tempWarnLower) : null;
|
||||||
|
|
||||||
|
// 设置标题
|
||||||
|
const titles = ['', '溶解氧数据查询', '水温数据查询', '饱和度数据查询', 'PH数据查询', '盐度数据查询'];
|
||||||
|
chartTitle.value = titles[dataType.value] || '数据查询';
|
||||||
|
|
||||||
|
// 初始化默认时间(最近30天)
|
||||||
|
const now = new Date();
|
||||||
|
const monthAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
|
||||||
|
startDate.value = formatDateMin(monthAgo);
|
||||||
|
endDate.value = formatDateMin(now);
|
||||||
|
|
||||||
|
// 初始化图表尺寸
|
||||||
|
setTimeout(() => {
|
||||||
|
initChart();
|
||||||
|
}, 500);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (chartInstance) {
|
||||||
|
chartInstance = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 图表尺寸
|
||||||
|
const chartWidth = ref(0);
|
||||||
|
const chartHeight = ref(0);
|
||||||
|
const chartPixelRatio = ref(1);
|
||||||
|
|
||||||
|
// 初始化图表
|
||||||
|
function initChart() {
|
||||||
|
const sysInfo = Taro.getSystemInfoSync();
|
||||||
|
// 横屏模式,header(44px) + query-section(约50px) = 94px
|
||||||
|
chartWidth.value = sysInfo.windowWidth - 30;
|
||||||
|
chartHeight.value = sysInfo.windowHeight - 110;
|
||||||
|
chartPixelRatio.value = sysInfo.pixelRatio || 1;
|
||||||
|
|
||||||
|
// 自动加载默认数据(最近30天)
|
||||||
|
queryData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回上一页
|
||||||
|
function goBack() {
|
||||||
|
Taro.navigateBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认开始时间
|
||||||
|
function confirmStartDate({ selectedValue }) {
|
||||||
|
startDateTime.value = selectedValue[0];
|
||||||
|
startDate.value = formatDateMin(selectedValue[0]);
|
||||||
|
showStartPicker.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认结束时间
|
||||||
|
function confirmEndDate({ selectedValue }) {
|
||||||
|
endDateTime.value = selectedValue[0];
|
||||||
|
endDate.value = formatDateMin(selectedValue[0]);
|
||||||
|
showEndPicker.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询数据
|
||||||
|
function queryData() {
|
||||||
|
if (!serialNum.value) {
|
||||||
|
Taro.showToast({ title: '设备序列号不存在', icon: 'none' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!startDate.value || !endDate.value) {
|
||||||
|
Taro.showToast({ title: '请选择查询时间范围', icon: 'none' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证时间范围
|
||||||
|
const start = new Date(startDate.value);
|
||||||
|
const end = new Date(endDate.value);
|
||||||
|
|
||||||
|
if (start >= end) {
|
||||||
|
Taro.showToast({ title: '开始时间必须小于结束时间', icon: 'none' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算天数差
|
||||||
|
const dayDiff = Math.ceil((end.getTime() - start.getTime()) / (24 * 60 * 60 * 1000));
|
||||||
|
|
||||||
|
if (dayDiff > 90) {
|
||||||
|
Taro.showToast({ title: '查询范围不能超过3个月(90天)', icon: 'none' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据天数差确定 intervalType
|
||||||
|
// ≤3天: intervalType = 1
|
||||||
|
// 3-7天: intervalType = 2
|
||||||
|
// 7-14天: intervalType = 3
|
||||||
|
// 14-30天: intervalType = 4
|
||||||
|
// 30-60天: intervalType = 5
|
||||||
|
// >60天: intervalType = 6
|
||||||
|
|
||||||
|
let intervalType = 1;
|
||||||
|
if (dayDiff > 3 && dayDiff <= 7) {
|
||||||
|
intervalType = 2;
|
||||||
|
} else if (dayDiff > 7 && dayDiff <= 14) {
|
||||||
|
intervalType = 3;
|
||||||
|
} else if (dayDiff > 14 && dayDiff <= 30) {
|
||||||
|
intervalType = 4;
|
||||||
|
} else if (dayDiff > 30 && dayDiff <= 60) {
|
||||||
|
intervalType = 5;
|
||||||
|
} else if (dayDiff > 60) {
|
||||||
|
intervalType = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
serialNum: serialNum.value,
|
||||||
|
startTime: startDate.value,
|
||||||
|
endTime: endDate.value,
|
||||||
|
intervalType: intervalType,
|
||||||
|
};
|
||||||
|
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
deviceHistory(params).then((res: any) => {
|
||||||
|
loading.value = false;
|
||||||
|
|
||||||
|
if (Array.isArray(res)) {
|
||||||
|
chartData.value = res;
|
||||||
|
} else if (res.code == 200) {
|
||||||
|
chartData.value = res.data || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chartData.value.length === 0) {
|
||||||
|
Taro.showToast({ title: '该时间段暂无数据', icon: 'none' });
|
||||||
|
} else {
|
||||||
|
// 绘制图表
|
||||||
|
drawChart();
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
Taro.showToast({ title: '查询失败,请重试', icon: 'none' });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 绘制图表
|
||||||
|
function drawChart() {
|
||||||
|
if (!chartData.value || chartData.value.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cWidth = chartWidth.value;
|
||||||
|
const cHeight = chartHeight.value;
|
||||||
|
const pixelRatio = chartPixelRatio.value;
|
||||||
|
|
||||||
|
const fieldMap: any = {
|
||||||
|
1: 'dissolvedOxygen',
|
||||||
|
2: 'temperature',
|
||||||
|
3: 'saturability',
|
||||||
|
4: 'ph',
|
||||||
|
5: 'salinity',
|
||||||
|
};
|
||||||
|
|
||||||
|
const nameMap: any = {
|
||||||
|
1: '溶解氧',
|
||||||
|
2: '水温',
|
||||||
|
3: '饱和度',
|
||||||
|
4: 'PH',
|
||||||
|
5: '盐度',
|
||||||
|
};
|
||||||
|
|
||||||
|
const fieldName = fieldMap[dataType.value] || 'dissolvedOxygen';
|
||||||
|
const seriesName = nameMap[dataType.value] || '溶解氧';
|
||||||
|
|
||||||
|
const xAxisData: string[] = [];
|
||||||
|
const seriesData: number[] = [];
|
||||||
|
let series: any[] = [];
|
||||||
|
|
||||||
|
// 根据数据类型添加告警线
|
||||||
|
if (dataType.value === 1 && oxyWarnLower.value) {
|
||||||
|
series.push({
|
||||||
|
name: '告警下限',
|
||||||
|
data: [],
|
||||||
|
color: '#c12e34',
|
||||||
|
lineType: 'dash',
|
||||||
|
});
|
||||||
|
} else if (dataType.value === 2) {
|
||||||
|
if (tempWarnLower.value) {
|
||||||
|
series.push({
|
||||||
|
name: '告警下限',
|
||||||
|
data: [],
|
||||||
|
color: '#c12e34',
|
||||||
|
lineType: 'dash',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (tempWarnUpper.value) {
|
||||||
|
series.push({
|
||||||
|
name: '告警上限',
|
||||||
|
data: [],
|
||||||
|
color: '#e098c7',
|
||||||
|
lineType: 'dash',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chartData.value.forEach((item: any) => {
|
||||||
|
const timeStr = item.time || item.createTime || '';
|
||||||
|
const timeParts = timeStr.split(' ');
|
||||||
|
if (timeParts.length > 1) {
|
||||||
|
const datePart = timeParts[0];
|
||||||
|
const timePart = timeParts[1];
|
||||||
|
|
||||||
|
const dateMatch = datePart.match(/\d{4}-(\d{2})-(\d{2})/);
|
||||||
|
const monthDay = dateMatch ? `${dateMatch[1]}-${dateMatch[2]}` : '';
|
||||||
|
const hourMin = timePart.substring(0, 5);
|
||||||
|
|
||||||
|
const formattedTime = `${monthDay} ${hourMin}`;
|
||||||
|
xAxisData.push(formattedTime);
|
||||||
|
}
|
||||||
|
const value = item[fieldName];
|
||||||
|
seriesData.push(value !== null && value !== undefined ? Number(value) : 0);
|
||||||
|
|
||||||
|
// 填充告警线数据
|
||||||
|
if (dataType.value === 1 && oxyWarnLower.value) {
|
||||||
|
series[0].data.push(oxyWarnLower.value);
|
||||||
|
} else if (dataType.value === 2) {
|
||||||
|
let idx = 0;
|
||||||
|
if (tempWarnLower.value) {
|
||||||
|
series[idx].data.push(tempWarnLower.value);
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
if (tempWarnUpper.value) {
|
||||||
|
series[idx].data.push(tempWarnUpper.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加主数据系列
|
||||||
|
series.unshift({ name: seriesName, data: seriesData });
|
||||||
|
|
||||||
|
Taro.nextTick(() => {
|
||||||
|
const env = Taro.getEnv();
|
||||||
|
|
||||||
|
if (env === Taro.ENV_TYPE.WEB) {
|
||||||
|
// H5 环境
|
||||||
|
setTimeout(() => {
|
||||||
|
const canvasElement = document.querySelector('#data-query-chart canvas') as HTMLCanvasElement;
|
||||||
|
if (!canvasElement) return;
|
||||||
|
|
||||||
|
const ctx = canvasElement.getContext('2d');
|
||||||
|
if (!ctx) return;
|
||||||
|
|
||||||
|
chartInstance = new uCharts({
|
||||||
|
type: 'line',
|
||||||
|
context: ctx,
|
||||||
|
width: cWidth,
|
||||||
|
height: cHeight,
|
||||||
|
categories: xAxisData,
|
||||||
|
series: series,
|
||||||
|
pixelRatio: 1,
|
||||||
|
dataPointShape: false,
|
||||||
|
animation: true,
|
||||||
|
background: '#FFFFFF',
|
||||||
|
color: ['#17B4B2'],
|
||||||
|
padding: [15, 15, 30, 40],
|
||||||
|
enableScroll: false,
|
||||||
|
boundaryGap: 'justify',
|
||||||
|
legend: { show: false },
|
||||||
|
dataLabel: false,
|
||||||
|
xAxis: {
|
||||||
|
disableGrid: true,
|
||||||
|
axisLine: true,
|
||||||
|
type: 'grid',
|
||||||
|
gridType: 'dash',
|
||||||
|
scrollShow: false,
|
||||||
|
labelCount: 8,
|
||||||
|
rotateLabel: true,
|
||||||
|
rotateAngle: 30,
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
disableGrid: false,
|
||||||
|
gridType: 'dash',
|
||||||
|
tofix: 2,
|
||||||
|
},
|
||||||
|
extra: {
|
||||||
|
line: { type: 'curve', width: 2, activeType: 'hollow' },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}, 300);
|
||||||
|
} else {
|
||||||
|
// 小程序环境
|
||||||
|
const query = Taro.createSelectorQuery();
|
||||||
|
query.select('#data-query-chart')
|
||||||
|
.fields({ node: true, size: true })
|
||||||
|
.exec((res) => {
|
||||||
|
if (!res || !res[0] || !res[0].node) return;
|
||||||
|
|
||||||
|
const canvas = res[0].node;
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
if (!ctx) return;
|
||||||
|
|
||||||
|
canvas.width = cWidth * pixelRatio;
|
||||||
|
canvas.height = cHeight * pixelRatio;
|
||||||
|
|
||||||
|
chartInstance = new uCharts({
|
||||||
|
type: 'line',
|
||||||
|
context: ctx,
|
||||||
|
width: cWidth * pixelRatio,
|
||||||
|
height: cHeight * pixelRatio,
|
||||||
|
categories: xAxisData,
|
||||||
|
series: series,
|
||||||
|
pixelRatio: pixelRatio,
|
||||||
|
dataPointShape: false,
|
||||||
|
animation: true,
|
||||||
|
background: '#FFFFFF',
|
||||||
|
color: ['#17B4B2'],
|
||||||
|
padding: [15, 15, 30, 40],
|
||||||
|
enableScroll: false,
|
||||||
|
boundaryGap: 'justify',
|
||||||
|
legend: { show: false },
|
||||||
|
dataLabel: false,
|
||||||
|
xAxis: {
|
||||||
|
disableGrid: true,
|
||||||
|
axisLine: true,
|
||||||
|
type: 'grid',
|
||||||
|
gridType: 'dash',
|
||||||
|
scrollShow: false,
|
||||||
|
labelCount: 6,
|
||||||
|
rotateLabel: true,
|
||||||
|
rotateAngle: 20,
|
||||||
|
marginTop: 5,
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
disableGrid: false,
|
||||||
|
gridType: 'dash',
|
||||||
|
tofix: 2,
|
||||||
|
},
|
||||||
|
extra: {
|
||||||
|
line: { type: 'curve', width: 2, activeType: 'hollow' },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.data-query-page {
|
||||||
|
background: #fff;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
height: 44px;
|
||||||
|
background: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 15px;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-btn {
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-btn .icon {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
margin-right: 44px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.query-section {
|
||||||
|
background: #fff;
|
||||||
|
padding: 6px 15px;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.query-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.query-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.query-label {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #666;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.query-value {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #333;
|
||||||
|
padding: 4px 12px;
|
||||||
|
background: #f5f5f5;
|
||||||
|
border-radius: 4px;
|
||||||
|
white-space: nowrap;
|
||||||
|
min-width: 150px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.query-btn {
|
||||||
|
height: 28px;
|
||||||
|
padding: 0 20px;
|
||||||
|
background: linear-gradient(135deg, #09b8c2 0%, #06a0a9 100%);
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-container {
|
||||||
|
background: #fff;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-canvas {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-container {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 10;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-data {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -335,6 +335,37 @@
|
|||||||
</template>
|
</template>
|
||||||
</nut-empty>
|
</nut-empty>
|
||||||
</view>
|
</view>
|
||||||
|
<!-- 功能按钮区域 -->
|
||||||
|
<nut-row class="action-buttons" v-if="doList.length > 0">
|
||||||
|
<nut-col :span="24">
|
||||||
|
<view class="button-wrapper">
|
||||||
|
<nut-button
|
||||||
|
type="primary"
|
||||||
|
class="action-btn"
|
||||||
|
size="small"
|
||||||
|
@click="goDeviceInfo"
|
||||||
|
>
|
||||||
|
设备属性
|
||||||
|
</nut-button>
|
||||||
|
<nut-button
|
||||||
|
type="primary"
|
||||||
|
class="action-btn"
|
||||||
|
size="small"
|
||||||
|
@click="goAlarmSettings"
|
||||||
|
>
|
||||||
|
报警设置
|
||||||
|
</nut-button>
|
||||||
|
<nut-button
|
||||||
|
type="primary"
|
||||||
|
class="action-btn"
|
||||||
|
size="small"
|
||||||
|
@click="goDataQuery"
|
||||||
|
>
|
||||||
|
数据查询
|
||||||
|
</nut-button>
|
||||||
|
</view>
|
||||||
|
</nut-col>
|
||||||
|
</nut-row>
|
||||||
</nut-col>
|
</nut-col>
|
||||||
</nut-row>
|
</nut-row>
|
||||||
</nut-row>
|
</nut-row>
|
||||||
@@ -1850,6 +1881,72 @@ function submit() {
|
|||||||
state.show = true;
|
state.show = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// 跳转到设备信息页面(设备属性)
|
||||||
|
function goDeviceInfo() {
|
||||||
|
const currentDevice = doList.value.find(
|
||||||
|
(item: any) => item.id === doDev.value
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!currentDevice) {
|
||||||
|
state.show = true;
|
||||||
|
state.msg = '设备信息不存在';
|
||||||
|
state.type = 'fail';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转到 wqm 页面,带上 deviceInfo 参数表示跳到设备信息区域
|
||||||
|
Taro.navigateTo({
|
||||||
|
url: `/home/wqm?id=${currentDevice.id}&name=${currentDevice.deviceName}&page=home§ion=deviceInfo`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转到报警设置页面(溶解氧配置)
|
||||||
|
function goAlarmSettings() {
|
||||||
|
const currentDevice = doList.value.find(
|
||||||
|
(item: any) => item.id === doDev.value
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!currentDevice) {
|
||||||
|
state.show = true;
|
||||||
|
state.msg = '设备信息不存在';
|
||||||
|
state.type = 'fail';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转到 wqm 页面,带上 alarmSettings 参数表示跳到溶解氧配置区域
|
||||||
|
Taro.navigateTo({
|
||||||
|
url: `/home/wqm?id=${currentDevice.id}&name=${currentDevice.deviceName}&page=home§ion=alarmSettings`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转到数据查询页面
|
||||||
|
function goDataQuery() {
|
||||||
|
const currentDevice = doList.value.find(
|
||||||
|
(item: any) => item.id === doDev.value
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!currentDevice) {
|
||||||
|
state.show = true;
|
||||||
|
state.msg = '设备信息不存在';
|
||||||
|
state.type = 'fail';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取设备序列号
|
||||||
|
const serialNum = currentDevice.serialNum || currentDevice.serialNumber || currentDevice.deviceSerialNum || currentDevice.sn;
|
||||||
|
|
||||||
|
if (!serialNum) {
|
||||||
|
state.show = true;
|
||||||
|
state.msg = '设备序列号不存在';
|
||||||
|
state.type = 'fail';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转到数据查询页面(横屏显示)
|
||||||
|
Taro.navigateTo({
|
||||||
|
url: `/components/other/dataQuery?serialNum=${serialNum}&dataType=${prDev.value}&deviceName=${currentDevice.deviceName}&oxyWarnLower=${oxyWarnLower.value || ''}&tempWarnUpper=${tempWarnUpper.value || ''}&tempWarnLower=${tempWarnLower.value || ''}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
/** -----------------method end------------------- */
|
/** -----------------method end------------------- */
|
||||||
defineExpose({
|
defineExpose({
|
||||||
getDeviceList,
|
getDeviceList,
|
||||||
@@ -2050,4 +2147,42 @@ defineExpose({
|
|||||||
.nut-grid-item__content {
|
.nut-grid-item__content {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 功能按钮区域样式
|
||||||
|
.action-buttons {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.nut-col {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20rpx;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 180rpx;
|
||||||
|
height: 70rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
background: linear-gradient(135deg, #09b8c2 0%, #06a0a9 100%);
|
||||||
|
border: none;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 500;
|
||||||
|
box-shadow: 0 4rpx 12rpx rgba(9, 184, 194, 0.3);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
box-shadow: 0 2rpx 8rpx rgba(9, 184, 194, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
<nut-config-provider :theme-vars="themeVars">
|
<nut-config-provider :theme-vars="themeVars">
|
||||||
<view class="body">
|
<view class="body">
|
||||||
<nut-row>
|
<nut-row>
|
||||||
<nut-col :span="24">
|
<!-- 设备信息区域 -->
|
||||||
|
<nut-col :span="24" v-if="!section || section === 'deviceInfo'">
|
||||||
<nut-cell class="wqm_body">
|
<nut-cell class="wqm_body">
|
||||||
<nut-row>
|
<nut-row>
|
||||||
<nut-col :span="24" class="title"> 设备信息 </nut-col>
|
<nut-col :span="24" class="title"> 设备信息 </nut-col>
|
||||||
@@ -63,10 +64,29 @@
|
|||||||
</nut-cell>
|
</nut-cell>
|
||||||
</nut-cell-group>
|
</nut-cell-group>
|
||||||
</nut-col>
|
</nut-col>
|
||||||
|
<!-- 将解除绑定按钮移到设备信息区域内 -->
|
||||||
|
<nut-col :span="24" :style="{ marginTop: '20rpx' }">
|
||||||
|
<nut-button
|
||||||
|
block
|
||||||
|
shape="square"
|
||||||
|
size="large"
|
||||||
|
color="#E22323"
|
||||||
|
:style="{
|
||||||
|
fontWeight: 'bold',
|
||||||
|
fontSize: '14px !important',
|
||||||
|
borderRadius: '10px',
|
||||||
|
}"
|
||||||
|
@click="unbind"
|
||||||
|
:loading="b_isLoading"
|
||||||
|
v-if="Uid==rootuserid"
|
||||||
|
>解除绑定</nut-button
|
||||||
|
>
|
||||||
|
</nut-col>
|
||||||
</nut-row>
|
</nut-row>
|
||||||
</nut-cell>
|
</nut-cell>
|
||||||
</nut-col>
|
</nut-col>
|
||||||
<nut-col :span="24">
|
<!-- 溶解氧配置区域 -->
|
||||||
|
<nut-col :span="24" v-if="!section || section === 'alarmSettings'">
|
||||||
<nut-cell class="wqm_body">
|
<nut-cell class="wqm_body">
|
||||||
<nut-row>
|
<nut-row>
|
||||||
<nut-col :span="24" class="title"> 溶解氧配置 </nut-col>
|
<nut-col :span="24" class="title"> 溶解氧配置 </nut-col>
|
||||||
@@ -336,40 +356,6 @@
|
|||||||
</nut-row>
|
</nut-row>
|
||||||
</nut-cell>
|
</nut-cell>
|
||||||
</nut-col>
|
</nut-col>
|
||||||
<!-- <nut-col :span="24" :style="{ marginBottom: '20rpx' }">
|
|
||||||
<nut-button
|
|
||||||
block
|
|
||||||
shape="square"
|
|
||||||
size="large"
|
|
||||||
color="#E22323"
|
|
||||||
plain
|
|
||||||
:style="{
|
|
||||||
fontWeight: 'bold',
|
|
||||||
fontSize: '14px !important',
|
|
||||||
borderRadius: '10px',
|
|
||||||
}"
|
|
||||||
@click="removeDev"
|
|
||||||
:loading="r_isLoading"
|
|
||||||
>移除设备</nut-button
|
|
||||||
>
|
|
||||||
</nut-col> -->
|
|
||||||
<nut-col :span="24">
|
|
||||||
<nut-button
|
|
||||||
block
|
|
||||||
shape="square"
|
|
||||||
size="large"
|
|
||||||
color="#E22323"
|
|
||||||
:style="{
|
|
||||||
fontWeight: 'bold',
|
|
||||||
fontSize: '14px !important',
|
|
||||||
borderRadius: '10px',
|
|
||||||
}"
|
|
||||||
@click="unbind"
|
|
||||||
:loading="b_isLoading"
|
|
||||||
v-if="Uid==rootuserid"
|
|
||||||
>解除绑定</nut-button
|
|
||||||
>
|
|
||||||
</nut-col>
|
|
||||||
</nut-row>
|
</nut-row>
|
||||||
</view>
|
</view>
|
||||||
</nut-config-provider>
|
</nut-config-provider>
|
||||||
@@ -687,6 +673,7 @@ const instance = Taro.getCurrentInstance();
|
|||||||
const id = instance.router.params.id;
|
const id = instance.router.params.id;
|
||||||
const name = instance.router.params.name;
|
const name = instance.router.params.name;
|
||||||
const page = instance.router.params.page;
|
const page = instance.router.params.page;
|
||||||
|
const section = instance.router.params.section; // 获取区域参数
|
||||||
// const name = undefined
|
// const name = undefined
|
||||||
Taro.setNavigationBarTitle({
|
Taro.setNavigationBarTitle({
|
||||||
title: "水质检测仪设置",
|
title: "水质检测仪设置",
|
||||||
|
|||||||
Reference in New Issue
Block a user