532 lines
14 KiB
Vue
Raw Permalink Normal View History

2024-12-09 14:16:57 +08:00
<template>
<view class="device-history">
<view class="tools-wrap">
<view class="time-shortcut">
<uni-data-select v-model="queryParams.timeShortcut" :localdata="timeShortcuts"
@change="handleTimeShortcutChange" :clear="false"></uni-data-select>
</view>
<view class="date-wrap" @click="handleDateTimeClick">
<u--input
customStyle="height: 68rpx; padding: 0 18rpx; background-color:transparent; pointer-events:none;"
:placeholder="$tt('deviceHistory.inputDate')" :value="formatDate(queryParams.strTime)" disabled>
</u--input>
</view>
<view class="filter-btn">
<u-icon :label="$tt('deviceHistory.filtrate')" labelPos="left" name="hourglass" size="18"
@click="handleFilterClick"></u-icon>
</view>
</view>
<!-- 折线图 -->
<view class="charts-box" v-if="historys.length !== 0">
<qiun-data-charts type="line" :opts="chartOpts" :chartData="chartData" canvasId="multiLineChart" />
</view>
<!-- 表格 -->
<view class="table-box" v-if="historys.length !== 0">
<uni-table :border="false" :show="devTotal === 0" stripe :emptyText="$tt('deviceHistory.emptyTable')">
<uni-tr>
<uni-td align="center">{{ $tt('deviceHistory.updateTime') }}</uni-td>
<uni-td align="center" v-for="item in tableHeaders" :key="item.value">{{item.name}}</uni-td>
</uni-tr>
<uni-tr v-for="item in tableCom" :key="item.value">
<uni-td align="center">{{item.time}}</uni-td>
<uni-td align="center" v-for="chil in tableHeaders" :key="chil.value">{{item[chil.value]}}</uni-td>
</uni-tr>
</uni-table>
<view class="pagination-box">
<uni-pagination show-icon :page-size="devPageSize" :current="devPageNum" :total="devTotal"
@change="getTableComsList" />
</view>
</view>
<u-empty mode="data" :show="historys.length === 0" :text="$tt('deviceHistory.emptyData')"
marginTop="30"></u-empty>
<view class="other-wrap">
<!-- 日期选择器 -->
<u-datetime-picker ref="datetimePicker" :show="isDateTime" mode="datetime" :closeOnClickOverlay="true"
:confirmText="dateTimeIndex > 1 ? $tt('deviceHistory.confirm') : $tt('deviceHistory.nextStep')"
:cancelText="$tt('deviceHistory.cancel')" @confirm="handleConfirmDateTime"
@cancel="handleCancelDateTime" @close="handleCloseDateTime">
</u-datetime-picker>
<u-popup :show="isFilter" mode="top" :safeAreaInsetBottom="false" @close="isFilter = false">
<view class="filter-pop">
<view class="content-wrap">
<!-- <view class="title-wrap" v-if="deviceInfo.deviceType === 2">子设备</view>
<view class="check-box-wrap" v-if="deviceInfo.deviceType === 2">
<uni-data-checkbox mode="tag" v-model="queryParams.slaveId"
:localdata="slaveList"></uni-data-checkbox>
</view> -->
<view class="title-wrap">{{ $tt('deviceHistory.variable')}}</view>
<view class="check-box-wrap">
<uni-data-checkbox mode="tag" multiple v-model="queryParams.identifiers"
:localdata="identifierList" @change="handleIdentifierCheck"></uni-data-checkbox>
</view>
</view>
<u-line direction='row'></u-line>
<view class="bottom-wrap">
<u-button customStyle="border: none;" plain :text="$tt('deviceHistory.cancel')"
@click="isFilter = false"></u-button>
<u-line direction='col' length="40"></u-line>
<u-button customStyle="border: none;" type="primary" plain :text="$tt('deviceHistory.confirm')"
@click="handleConfirmFilter"></u-button>
</view>
</view>
</u-popup>
</view>
</view>
</template>
<script>
import moment from 'moment';
import uniDataCheckbox from '@/pagesA/components/uni-data-checkbox/index.vue';
import uniPagination from '@/pagesA/components/uni-pagination/index.vue';
2025-03-27 14:23:27 +08:00
import {
getSubGatewayList
} from '@/apis/modules/gateway.js';
import {
listThingsModel
} from '@/apis/modules/device.js';
import {
getHistoryList
} from '@/apis/modules/deviceLog.js';
2024-12-09 14:16:57 +08:00
export default {
name: 'deviceHistory',
components: {
uniDataCheckbox,
uniPagination
},
props: {
device: {
type: Object,
default: null,
require: true,
},
type: Number
},
watch: {
2025-03-27 14:23:27 +08:00
device: function(newVal, oldVal) {
2024-12-09 14:16:57 +08:00
this.deviceInfo = newVal;
},
2025-03-27 14:23:27 +08:00
type(val) {
2024-12-09 14:16:57 +08:00
if (val === 3) {
// const { deviceType } = this.deviceInfo || {};
// if (deviceType === 2) {
// this.getSlaveDatas();
// }
this.getData();
}
}
},
2025-03-27 14:23:27 +08:00
data() {
2024-12-09 14:16:57 +08:00
const beginTime = new Date().getTime() - 3600 * 1000 * 24;
const endTime = new Date().getTime();
return {
deviceInfo: {}, // 设备信息
deviceId: null,
// 时间快捷数据列表
timeShortcuts: [{
value: 0,
text: this.$tt('deviceHistory.lastTwoHours')
},
{
value: 1,
text: this.$tt('deviceHistory.lastOneDay')
},
{
value: 2,
text: this.$tt('deviceHistory.lastThirtyDay')
},
{
value: 3,
text: this.$tt('deviceHistory.custom')
},
],
// 查询参数
queryParams: {
timeShortcut: 1,
strTime: `${beginTime}-${endTime}`,
beginTime: beginTime,
endTime: endTime,
slaveId: '',
identifiers: [],
},
isDateTime: false, // 是否开启日期选择器
dateTimeIndex: 1, // 次数
isFilter: false, // 是否开启筛选
slaveList: [], // 子设备列表
identifierList: [], // 变量列表
// chart option
chartOpts: {
color: ['#1890FF', '#91CB74', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4',
'#ea7ccc'
], // 三组数据的颜色
padding: [15, 10, 0, 15], // 图表的内边距
dataLabel: false, // 不显示数据标签
dataPointShape: false, // 显示数据点形状
enableScroll: false, // 禁用图表滚动
legend: {}, // 启用图例
xAxis: {
disableGrid: true, // 禁用X轴网格线
disabled: true, // 禁用x轴的显示
},
yAxis: {
disableGrid: false, // 禁用Y轴网格线
data: [{
// min: 0,
// max: 100 // 设置Y轴的最小值和最大值
}],
},
extra: {
line: {
type: "step", // 直线类型的折线图
width: 1, // 线条宽度
activeType: "hollow", // 激活状态下的线条样式
linearType: "custom" // 自定义线条渐变颜色
},
},
},
// 存储图表数据
chartData: {
categories: [],
series: []
},
historys: [], // 历史数据
tableHeaders: [], // 设备列表table数据
tableComTemp: [],
devPageSize: 10,
devPageNum: 1,
devTotal: 0, // 数据总量
};
},
computed: {
2025-03-27 14:23:27 +08:00
tableCom() {
2024-12-09 14:16:57 +08:00
const start = (this.devPageNum - 1) * this.devPageSize;
const end = start + this.devPageSize;
return this.tableComTemp.slice(start, end);
},
},
methods: {
// 快捷时间选择
2025-03-27 14:23:27 +08:00
handleTimeShortcutChange(val) {
2024-12-09 14:16:57 +08:00
if (val === 3) {
return;
}
const endTime = new Date().getTime();
let beginTime = null;
if (val === 0) {
beginTime = endTime - 3600 * 1000 * 2;
} else if (val === 1) {
beginTime = endTime - 3600 * 1000 * 24;
} else if (val === 2) {
beginTime = endTime - 3600 * 1000 * 24 * 30;
};
this.queryParams.beginTime = beginTime;
this.queryParams.endTime = endTime;
this.queryParams.strTime = beginTime + '-' + endTime;
this.getHistory();
},
// 格式化时间
2025-03-27 14:23:27 +08:00
formatDate(strTime) {
2024-12-09 14:16:57 +08:00
const times = strTime.split('-');
const beginTime = new Date(Number(times[0]));
const endTime = new Date(Number(times[1]));
const beginMonth = (beginTime.getMonth() + 1).toString().padStart(2, '0');
const beginDay = beginTime.getDate().toString().padStart(2, '0');
const beginHours = beginTime.getHours().toString().padStart(2, '0');
const beginMinutes = beginTime.getMinutes().toString().padStart(2, '0');
const endMonth = (endTime.getMonth() + 1).toString().padStart(2, '0');
const endDay = endTime.getDate().toString().padStart(2, '0');
const endHours = endTime.getHours().toString().padStart(2, '0');
const endMinutes = endTime.getMinutes().toString().padStart(2, '0');
return `${beginMonth}-${beginDay} ${beginHours}:${beginMinutes} - ${endMonth}-${endDay} ${endHours}:${endMinutes}`;
},
// 日期选择
2025-03-27 14:23:27 +08:00
handleDateTimeClick() {
const {
beginTime,
endTime
} = this.queryParams;
2024-12-09 14:16:57 +08:00
if (this.dateTimeIndex === 1) {
this.$refs.datetimePicker.innerValue = beginTime;
} else {
this.$refs.datetimePicker.innerValue = endTime;
}
this.isDateTime = true;
},
// 时间选择下一步/确定
2025-03-27 14:23:27 +08:00
handleConfirmDateTime(e) {
const {
beginTime,
endTime
} = this.queryParams;
2024-12-09 14:16:57 +08:00
if (this.dateTimeIndex === 1) {
this.queryParams.beginTime = e.value;
this.dateTimeIndex = this.dateTimeIndex + 1;
this.queryParams.strTime = e.value + '-' + endTime;
this.$refs.datetimePicker.innerValue = endTime;
this.isDateTime = false;
setTimeout(() => {
this.isDateTime = true;
}, 1);
} else {
this.queryParams.endTime = e.value;
this.dateTimeIndex = 1;
this.queryParams.strTime = beginTime + '-' + e.value;
this.getHistory();
this.isDateTime = false;
this.queryParams.timeShortcut = 3;
}
},
// 取消日期选择
2025-03-27 14:23:27 +08:00
handleCancelDateTime() {
2024-12-09 14:16:57 +08:00
this.isDateTime = false;
},
// 点击遮取消日期选择
2025-03-27 14:23:27 +08:00
handleCloseDateTime() {
2024-12-09 14:16:57 +08:00
this.isDateTime = false;
},
// 筛选
2025-03-27 14:23:27 +08:00
handleFilterClick() {
2024-12-09 14:16:57 +08:00
this.isFilter = true;
},
// 变量选择
2025-03-27 14:23:27 +08:00
handleIdentifierCheck(e) {
2024-12-09 14:16:57 +08:00
const value = e.detail.value;
const length = value.length;
if (length > 9) {
uni.showToast({
icon: 'none',
title: '变量数不能超过9个'
});
this.queryParams.identifiers = value.slice(0, 9);
}
},
// 筛选确认
2025-03-27 14:23:27 +08:00
handleConfirmFilter() {
const {
identifiers
} = this.queryParams;
2024-12-09 14:16:57 +08:00
if (identifiers.length === 0) {
uni.showToast({
icon: 'none',
title: '请选择变量!'
});
} else {
this.getHistory();
this.isFilter = false;
}
},
// 获取子设备列表数据
2025-03-27 14:23:27 +08:00
getSlaveDatas() {
const {
deviceId
} = this.deviceInfo;
2024-12-09 14:16:57 +08:00
const params = {
gwDeviceId: deviceId,
pageNum: 1,
pageSize: 9999,
};
getSubGatewayList(params).then(res => {
2025-03-27 14:23:27 +08:00
const {
code,
rows
} = res;
2024-12-09 14:16:57 +08:00
if (code === 200) {
this.slaveList = rows.map(item => ({
text: item.subDeviceName,
value: item.slaveId
}));
this.queryParams.slaveId = this.slaveList[0].value;
}
});
},
// 获取物模型
2025-03-27 14:23:27 +08:00
getIdentifierList() {
const {
deviceId
} = this.deviceInfo;
2024-12-09 14:16:57 +08:00
const params = {
deviceId: deviceId,
pageNum: 1,
pageSize: 9999,
};
listThingsModel(params).then((res) => {
2025-03-27 14:23:27 +08:00
const {
code,
rows
} = res;
2024-12-09 14:16:57 +08:00
if (code === 200) {
this.identifierList = rows.map(item => ({
text: item.modelName,
value: item.identifier,
type: item.type,
}));
this.queryParams.identifiers = [this.identifierList[0].value];
}
});
},
// 获取统计数据
2025-03-27 14:23:27 +08:00
getData() {
2024-12-09 14:16:57 +08:00
this.getIdentifierList();
this.getHistory(); // 获取统计数据
},
// 获取统计数据
2025-03-27 14:23:27 +08:00
getHistory() {
const {
identifiers,
beginTime,
endTime,
slaveId
} = this.queryParams;
const {
deviceId,
serialNumber
} = this.deviceInfo;
2024-12-09 14:16:57 +08:00
if (identifiers.length !== 0) {
const idenList = identifiers.map((item) => {
const iden = this.identifierList.find((chil) => chil.value === item);
return {
identifier: iden.value,
type: iden.type
};
});
const params = {
identifierList: idenList,
beginTime: moment(beginTime).format('YYYY-MM-DD HH:mm:ss'),
endTime: moment(endTime).format('YYYY-MM-DD HH:mm:ss'),
deviceId: deviceId,
// slaveId: slaveId,
serialNumber: serialNumber,
};
getHistoryList(params).then(res => {
this.historys = res.data;
this.chartData = this.getChartDatas();
this.getTableDatas();
})
}
},
// 获取折线图数据
2025-03-27 14:23:27 +08:00
getChartDatas() {
2024-12-09 14:16:57 +08:00
const categories = this.historys.map((item) => Object.keys(item)[0]);
const series = this.queryParams.identifiers.map((item) => {
return {
name: this.identifierList.find((chil) => chil.value === item).text,
data: this.historys.map((d) => {
const ide = Object.values(d)[0].find((f) => Object.keys(f)[0] === item);
return Object.values(ide)[0];
}),
};
});
return {
categories,
series
}
},
// 获取表格数据
2025-03-27 14:23:27 +08:00
getTableDatas() {
2024-12-09 14:16:57 +08:00
this.tableHeaders = this.queryParams.identifiers.map((item) => ({
name: this.identifierList.find((chil) => chil.value === item).text,
value: item,
}));
this.tableComTemp = this.historys.map((item) => {
const time = Object.keys(item)[0];
let obj = {};
Object.values(item)[0].forEach((chil) => {
obj[Object.keys(chil)[0]] = Object.values(chil)[0];
});
return {
time,
...obj
};
});
this.devTotal = this.historys.length;
},
// 获取设备列表数据
2025-03-27 14:23:27 +08:00
getTableComsList(e) {
2024-12-09 14:16:57 +08:00
this.devPageNum = e.current;
},
},
options: {
styleIsolation: 'shared'
}
};
</script>
<style lang="scss" scoped>
.device-history {
width: 100%;
.tools-wrap {
display: flex;
flex-direction: row;
align-items: center;
padding: 20rpx 14rpx;
background: #fff;
.time-shortcut {
width: 190rpx;
2025-03-27 14:23:27 +08:00
::v-deep .uni-select {
2024-12-09 14:16:57 +08:00
height: 70rpx;
}
}
.date-wrap {
flex: 1;
margin-left: 10rpx;
}
.filter-btn {
font-size: 28rpx;
margin-left: 14rpx;
height: 70rpx;
display: flex;
align-items: center;
}
}
.charts-box {
width: 100%;
background-color: #fff;
padding: 20rpx 0;
margin-top: 20rpx;
}
.table-box {
width: 100%;
background-color: #fff;
padding: 10px 0;
margin-top: 10px;
.pagination-box {
margin: 10px 10px 0 0;
}
}
.other-wrap {
.filter-pop {
.content-wrap {
padding: 10px;
.title-wrap {
font-size: 28rpx;
font-weight: bold;
margin-top: 10rpx;
}
.check-box-wrap {
margin: 10rpx 0 30rpx 0;
max-height: 200px;
overflow-y: auto;
}
}
.bottom-wrap {
display: flex;
flex-direction: row;
align-items: center;
}
}
}
}
</style>