|
@@ -0,0 +1,471 @@
|
|
|
+<template>
|
|
|
+ <div class="charts-container">
|
|
|
+ <a-select ref="select" v-model:value="chartsType" size="small" style="position: absolute; z-index: 99; top: 2px; left: 2px; width: 98px">
|
|
|
+ <a-select-option value="listMonitor">实时监测</a-select-option>
|
|
|
+ <a-select-option value="detail">详情监测</a-select-option>
|
|
|
+ <a-select-option value="history">历史记录</a-select-option>
|
|
|
+ </a-select>
|
|
|
+
|
|
|
+ <div class="charts-box" v-if="chartsType === 'listMonitor'" style="position: absolute; top: 20px">
|
|
|
+ <div class="echarts-group">
|
|
|
+ <BarAndLine
|
|
|
+ class="echarts-item"
|
|
|
+ :chartsColumnsType="chartsColumnsType"
|
|
|
+ :xAxisPropType="xAxisPropType"
|
|
|
+ :dataSource="dataSource"
|
|
|
+ height="100%"
|
|
|
+ chartsType="listMonitor"
|
|
|
+ :option="echartsOption"
|
|
|
+ :chartsColumns="fan1ChartsColumns"
|
|
|
+ style="border-right: 1px solid #fff"
|
|
|
+ />
|
|
|
+ <BarAndLine
|
|
|
+ class="echarts-item"
|
|
|
+ :chartsColumnsType="chartsColumnsType"
|
|
|
+ :xAxisPropType="xAxisPropType"
|
|
|
+ :dataSource="dataSource"
|
|
|
+ height="100%"
|
|
|
+ chartsType="listMonitor"
|
|
|
+ :option="echartsOption"
|
|
|
+ :chartsColumns="fan2ChartsColumns"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="charts-box" v-else-if="chartsType === 'detail' && deviceListApi">
|
|
|
+ <Select
|
|
|
+ :options="options"
|
|
|
+ :fieldNames="{ label: 'strname', value: 'deviceID' }"
|
|
|
+ v-model:value="deviceId"
|
|
|
+ placeholder="请选择查看的设备"
|
|
|
+ size="small"
|
|
|
+ style="position: absolute; z-index: 99; left: 102px; width: 150px; top: 2px"
|
|
|
+ />
|
|
|
+ <div class="echarts-group">
|
|
|
+ <BarAndLine
|
|
|
+ class="echarts-item"
|
|
|
+ :chartsColumnsType="chartsColumnsType"
|
|
|
+ :xAxisPropType="resultXAxisPropType"
|
|
|
+ :dataSource="detailDataSource"
|
|
|
+ height="100%"
|
|
|
+ :option="echartsOption2"
|
|
|
+ chartsType="detail"
|
|
|
+ :chartsColumns="fan1ChartsColumns"
|
|
|
+ style="border-right: 1px solid #fff"
|
|
|
+ />
|
|
|
+ <BarAndLine
|
|
|
+ class="echarts-item"
|
|
|
+ :chartsColumnsType="chartsColumnsType"
|
|
|
+ :xAxisPropType="resultXAxisPropType"
|
|
|
+ :dataSource="detailDataSource"
|
|
|
+ height="100%"
|
|
|
+ :option="echartsOption2"
|
|
|
+ chartsType="detail"
|
|
|
+ :chartsColumns="fan2ChartsColumns"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="charts-box" v-else-if="chartsType === 'history'">
|
|
|
+ <Select
|
|
|
+ :options="options"
|
|
|
+ :fieldNames="{ label: 'strname', value: 'deviceID' }"
|
|
|
+ v-model:value="deviceId"
|
|
|
+ placeholder="请选择查看的设备"
|
|
|
+ size="small"
|
|
|
+ style="position: absolute; z-index: 99; left: 102px; width: 150px; top: 2px"
|
|
|
+ />
|
|
|
+ <template v-if="globalConfig.History_Type == 'vent'">
|
|
|
+ <a-date-picker
|
|
|
+ v-model:value="historyParams.ttime_begin"
|
|
|
+ valueFormat="YYYY-MM-DD HH:mm:ss"
|
|
|
+ placeholder="请选择开始日期"
|
|
|
+ size="small"
|
|
|
+ :showTime="true"
|
|
|
+ style="position: absolute; z-index: 99; left: 254px; width: 170px; top: 2px"
|
|
|
+ />
|
|
|
+ <a-date-picker
|
|
|
+ v-model:value="historyParams.ttime_end"
|
|
|
+ valueFormat="YYYY-MM-DD HH:mm:ss"
|
|
|
+ placeholder="请选择结束日期"
|
|
|
+ size="small"
|
|
|
+ :showTime="true"
|
|
|
+ style="position: absolute; z-index: 99; left: 426px; width: 170px; top: 2px"
|
|
|
+ />
|
|
|
+ <a-select
|
|
|
+ ref="select"
|
|
|
+ v-model:value="historyParams.skip"
|
|
|
+ placeholder="请选择间隔时间"
|
|
|
+ size="small"
|
|
|
+ style="position: absolute; z-index: 99; top: 2px; left: 598px; width: 150px"
|
|
|
+ >
|
|
|
+ <a-select-option value="1">1秒</a-select-option>
|
|
|
+ <a-select-option value="2">5秒</a-select-option>
|
|
|
+ <a-select-option value="3">10秒</a-select-option>
|
|
|
+ <a-select-option value="4">30分钟</a-select-option>
|
|
|
+ <a-select-option value="5">1分钟</a-select-option>
|
|
|
+ <a-select-option value="6">10分钟</a-select-option>
|
|
|
+ <a-select-option value="7">30分钟</a-select-option>
|
|
|
+ <a-select-option value="8">1小时</a-select-option>
|
|
|
+ </a-select>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <a-date-picker
|
|
|
+ v-model:value="historyParams.startTime"
|
|
|
+ valueFormat="YYYY-MM-DD HH:mm:ss"
|
|
|
+ placeholder="开始时间"
|
|
|
+ size="small"
|
|
|
+ :showTime="true"
|
|
|
+ style="position: absolute; z-index: 99; left: 254px; width: 170px; top: 2px"
|
|
|
+ />
|
|
|
+ <a-date-picker
|
|
|
+ v-model:value="historyParams.endTime"
|
|
|
+ valueFormat="YYYY-MM-DD HH:mm:ss"
|
|
|
+ placeholder="结束时间"
|
|
|
+ size="small"
|
|
|
+ :showTime="true"
|
|
|
+ style="position: absolute; z-index: 99; left: 426px; width: 170px; top: 2px"
|
|
|
+ />
|
|
|
+ <a-select
|
|
|
+ ref="select"
|
|
|
+ v-model:value="historyParams.interval"
|
|
|
+ placeholder="请选择间隔时间"
|
|
|
+ size="small"
|
|
|
+ style="position: absolute; z-index: 99; top: 2px; left: 598px; width: 150px"
|
|
|
+ >
|
|
|
+ <a-select-option value="1s">1秒</a-select-option>
|
|
|
+ <a-select-option value="5s">5秒</a-select-option>
|
|
|
+ <a-select-option value="10s">10秒</a-select-option>
|
|
|
+ <a-select-option value="30s">30秒</a-select-option>
|
|
|
+ <a-select-option value="1m">1分钟</a-select-option>
|
|
|
+ <a-select-option value="10m">5分钟</a-select-option>
|
|
|
+ <a-select-option value="30m">10分钟</a-select-option>
|
|
|
+ <a-select-option value="1h">1小时</a-select-option>
|
|
|
+ </a-select>
|
|
|
+ </template>
|
|
|
+ <Pagination
|
|
|
+ size="small"
|
|
|
+ v-model:current="currentPage"
|
|
|
+ v-model:page-size="pageSize"
|
|
|
+ :total="total"
|
|
|
+ :show-total="(total) => `共 ${total} 条`"
|
|
|
+ style="position: absolute; z-index: 99; top: 2px; right: 30px"
|
|
|
+ />
|
|
|
+ <div class="echarts-group">
|
|
|
+ <BarAndLine
|
|
|
+ class="echarts-item"
|
|
|
+ :chartsColumnsType="chartsColumnsType"
|
|
|
+ :xAxisPropType="resultXAxisPropType"
|
|
|
+ :dataSource="resultDataSource"
|
|
|
+ height="100%"
|
|
|
+ :option="echartsOption1"
|
|
|
+ chartsType="history"
|
|
|
+ style="margin-top: 20px; border-right: 1px solid #fff"
|
|
|
+ :chartsColumns="fan1ChartsColumns"
|
|
|
+ />
|
|
|
+ <BarAndLine
|
|
|
+ class="echarts-item"
|
|
|
+ :chartsColumnsType="chartsColumnsType"
|
|
|
+ :xAxisPropType="resultXAxisPropType"
|
|
|
+ :dataSource="resultDataSource"
|
|
|
+ height="100%"
|
|
|
+ :option="echartsOption1"
|
|
|
+ chartsType="history"
|
|
|
+ style="margin-top: 20px"
|
|
|
+ :chartsColumns="fan2ChartsColumns"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<script lang="ts">
|
|
|
+ import { ref, defineComponent, watch, reactive, onMounted, watchEffect, inject } from 'vue';
|
|
|
+ import BarAndLine from '/@/components/chart/BarAndLine.vue';
|
|
|
+ import dayjs from 'dayjs';
|
|
|
+ import { defHttp } from '/@/utils/http/axios';
|
|
|
+ import { Select, Pagination } from 'ant-design-vue';
|
|
|
+
|
|
|
+ export default defineComponent({
|
|
|
+ name: 'DeviceEcharts',
|
|
|
+ components: { BarAndLine, Select, Pagination },
|
|
|
+ props: {
|
|
|
+ fan1ChartsColumns: {
|
|
|
+ type: Array,
|
|
|
+ default: () => [],
|
|
|
+ },
|
|
|
+ fan2ChartsColumns: {
|
|
|
+ type: Array,
|
|
|
+ default: () => [],
|
|
|
+ },
|
|
|
+ chartsColumnsHistory: {
|
|
|
+ type: Array,
|
|
|
+ default: () => [],
|
|
|
+ },
|
|
|
+ chartsColumnsType: {
|
|
|
+ type: String,
|
|
|
+ required: true,
|
|
|
+ },
|
|
|
+ dataSource: {
|
|
|
+ type: Array,
|
|
|
+ default: () => [],
|
|
|
+ },
|
|
|
+ deviceListApi: {
|
|
|
+ type: Function,
|
|
|
+ required: true,
|
|
|
+ },
|
|
|
+ deviceType: {
|
|
|
+ type: String,
|
|
|
+ required: true,
|
|
|
+ },
|
|
|
+ option: {
|
|
|
+ type: Object,
|
|
|
+ default: () => ({}),
|
|
|
+ },
|
|
|
+ xAxisPropType: {
|
|
|
+ type: String,
|
|
|
+ required: true,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ setup(props) {
|
|
|
+ const globalConfig = inject('globalConfig');
|
|
|
+ let historyList;
|
|
|
+ if (globalConfig.History_Type == 'vent') {
|
|
|
+ historyList = (params) => defHttp.get({ url: '/safety/ventanalyMonitorData/listdays', params });
|
|
|
+ } else {
|
|
|
+ historyList = (params) => defHttp.post({ url: '/monitor/history/getHistoryData', params });
|
|
|
+ }
|
|
|
+ const chartsType = ref('history');
|
|
|
+ const deviceId = ref('');
|
|
|
+ const options = ref([]);
|
|
|
+ const historyParams = reactive({
|
|
|
+ ttime_begin: dayjs().startOf('date').format('YYYY-MM-DD HH:mm:ss'),
|
|
|
+ ttime_end: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
|
|
+ skip: '8',
|
|
|
+ startTime: dayjs().startOf('date').format('YYYY-MM-DD HH:mm:ss'),
|
|
|
+ endTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
|
|
+ interval: '1h',
|
|
|
+ });
|
|
|
+ const resultXAxisPropType = ref('');
|
|
|
+ const resultDataSource = ref<any[]>([]);
|
|
|
+ const detailDataSource = ref<any[]>([]);
|
|
|
+ const currentPage = ref<number>(1);
|
|
|
+ const pageSize = ref<number>(20);
|
|
|
+ const total = ref(0);
|
|
|
+
|
|
|
+ const echartsOption = {
|
|
|
+ grid: {
|
|
|
+ top: '50px',
|
|
|
+ left: '10px',
|
|
|
+ right: props.fan1ChartsColumns.length * 15 + 'px',
|
|
|
+ bottom: '15px',
|
|
|
+ containLabel: true,
|
|
|
+ },
|
|
|
+ toolbox: {
|
|
|
+ feature: {},
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ axisLabel: {
|
|
|
+ interval: 0,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ };
|
|
|
+ const echartsOption1 = {
|
|
|
+ grid: {
|
|
|
+ top: '60px',
|
|
|
+ left: '10px',
|
|
|
+ right: props.fan1ChartsColumns.length * 15 + 'px',
|
|
|
+ bottom: '35px',
|
|
|
+ containLabel: true,
|
|
|
+ },
|
|
|
+ toolbox: {
|
|
|
+ feature: {},
|
|
|
+ },
|
|
|
+ legend: {
|
|
|
+ top: 40,
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ interval: 0,
|
|
|
+ },
|
|
|
+ };
|
|
|
+ const echartsOption2 = {
|
|
|
+ grid: {
|
|
|
+ top: '70px',
|
|
|
+ left: '10px',
|
|
|
+ right: props.fan1ChartsColumns.length * 15 + 'px',
|
|
|
+ bottom: '5px',
|
|
|
+ containLabel: true,
|
|
|
+ },
|
|
|
+ toolbox: {
|
|
|
+ feature: {},
|
|
|
+ },
|
|
|
+ };
|
|
|
+
|
|
|
+ const onChange = (pageNumber: number) => {
|
|
|
+ console.log('Page: ', pageNumber);
|
|
|
+ };
|
|
|
+
|
|
|
+ watch(
|
|
|
+ [chartsType, deviceId, historyParams, pageSize, currentPage],
|
|
|
+ async (
|
|
|
+ [newChartsType, newDeviceId, newHistoryParams, newPageSize, newCurrentPage],
|
|
|
+ [oldChartsType, oldDeviceId, oldHistoryParams, oldPageSize, oldCurrentPage]
|
|
|
+ ) => {
|
|
|
+ console.log('[ historyParams ] >', historyParams.ttime, dayjs(historyParams.ttime).format('HH:mm:ss'));
|
|
|
+ if (newChartsType === 'listMonitor') {
|
|
|
+ // 实时监测所有
|
|
|
+ resultDataSource.value = props.dataSource;
|
|
|
+ } else if (newChartsType === 'history') {
|
|
|
+ resultDataSource.value = [];
|
|
|
+ // 历史
|
|
|
+ if (newChartsType !== oldChartsType || newDeviceId !== oldDeviceId) {
|
|
|
+ currentPage.value = 1;
|
|
|
+ }
|
|
|
+ const device = options.value.find((device) => device['deviceID'] === newDeviceId);
|
|
|
+ if (device) {
|
|
|
+ let res;
|
|
|
+ if (globalConfig.History_Type == 'vent') {
|
|
|
+ resultXAxisPropType.value = 'ttime';
|
|
|
+
|
|
|
+ const datas = await historyList({
|
|
|
+ ttime_begin: newHistoryParams.ttime_begin,
|
|
|
+ ttime_end: newHistoryParams.ttime_end,
|
|
|
+ strtype: device.deviceType,
|
|
|
+ gdeviceid: newDeviceId,
|
|
|
+ skip: historyParams.skip,
|
|
|
+ pageSize: pageSize.value,
|
|
|
+ pageNo: currentPage.value,
|
|
|
+ column: 'createTime',
|
|
|
+ });
|
|
|
+ res = datas['datalist']['records'];
|
|
|
+ if (res && res.length > 0) {
|
|
|
+ resultDataSource.value = res.map((item) => Object.assign(item, item.readData));
|
|
|
+ } else {
|
|
|
+ resultDataSource.value = [];
|
|
|
+ }
|
|
|
+ total.value = datas['datalist'].total;
|
|
|
+ } else {
|
|
|
+ resultXAxisPropType.value = 'time';
|
|
|
+ res = await historyList({
|
|
|
+ pageSize: pageSize.value,
|
|
|
+ pageNum: currentPage.value,
|
|
|
+ startTime: newHistoryParams.ttime_begin,
|
|
|
+ endTime: newHistoryParams.ttime_end,
|
|
|
+ deviceId: newDeviceId,
|
|
|
+ strtype: device.deviceType,
|
|
|
+ interval: historyParams.interval,
|
|
|
+ column: 'createTime',
|
|
|
+ });
|
|
|
+ if (res && res.records && res.records.length > 0) {
|
|
|
+ resultDataSource.value = res.records.map((item) => Object.assign(item, item.readData));
|
|
|
+ } else {
|
|
|
+ resultDataSource.value = [];
|
|
|
+ }
|
|
|
+ total.value = res.total;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (newChartsType === 'detail') {
|
|
|
+ // 设备详情
|
|
|
+ resultXAxisPropType.value = 'readTime';
|
|
|
+ if (newDeviceId !== oldDeviceId) {
|
|
|
+ detailDataSource.value = [];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+ watchEffect(() => {
|
|
|
+ if (chartsType.value === 'detail') {
|
|
|
+ const currentData = props.dataSource.find((item: any) => item.deviceID === deviceId.value);
|
|
|
+ if (currentData) {
|
|
|
+ const isHas = detailDataSource.value.find((item) => item[resultXAxisPropType.value] === currentData[resultXAxisPropType.value]);
|
|
|
+ if (!isHas) {
|
|
|
+ if (detailDataSource.value.length < 15) {
|
|
|
+ detailDataSource.value.push(currentData);
|
|
|
+ } else {
|
|
|
+ detailDataSource.value.shift();
|
|
|
+ detailDataSource.value.push(currentData);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ onMounted(async () => {
|
|
|
+ const res = await props.deviceListApi();
|
|
|
+ // debugger;
|
|
|
+ if (res['msgTxt'] && res['msgTxt'][0] && res['msgTxt'][0]['datalist']) {
|
|
|
+ options.value = res['msgTxt'][0]['datalist'];
|
|
|
+ deviceId.value = options.value[0]['deviceID'];
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return {
|
|
|
+ chartsType,
|
|
|
+ deviceId,
|
|
|
+ resultDataSource,
|
|
|
+ historyParams,
|
|
|
+ options,
|
|
|
+ resultXAxisPropType,
|
|
|
+ detailDataSource,
|
|
|
+ currentPage,
|
|
|
+ pageSize,
|
|
|
+ total,
|
|
|
+ echartsOption,
|
|
|
+ echartsOption1,
|
|
|
+ echartsOption2,
|
|
|
+ onChange,
|
|
|
+ globalConfig,
|
|
|
+ };
|
|
|
+ },
|
|
|
+ });
|
|
|
+</script>
|
|
|
+<style lang="less">
|
|
|
+ :deep(.vent-select-dropdown) {
|
|
|
+ color: #000 !important;
|
|
|
+ .vent-select-item {
|
|
|
+ color: #000 !important;
|
|
|
+ }
|
|
|
+ }
|
|
|
+</style>
|
|
|
+<style lang="less" scoped>
|
|
|
+ @import '/@/design/vent/color.less';
|
|
|
+ .charts-container {
|
|
|
+ position: relative;
|
|
|
+ height: 100%;
|
|
|
+ .charts-box {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ position: absolute;
|
|
|
+ bottom: 0;
|
|
|
+ top: 0px;
|
|
|
+ .echarts-group {
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+ :deep(div) {
|
|
|
+ border-right: 1px solid #ffffff22 !important;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .@{ventSpace}-picker,
|
|
|
+ .@{ventSpace}-select-selector {
|
|
|
+ background: #00000017 !important;
|
|
|
+ border: 1px solid @vent-form-item-boder !important;
|
|
|
+ input,
|
|
|
+ .@{ventSpace}-select-selection-item,
|
|
|
+ .@{ventSpace}-picker-suffix {
|
|
|
+ color: #fff !important;
|
|
|
+ }
|
|
|
+ .@{ventSpace}-select-selection-placeholder {
|
|
|
+ color: #b7b7b7 !important;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .@{ventSpace}-select-arrow,
|
|
|
+ .@{ventSpace}-picker-separator {
|
|
|
+ color: #fff !important;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ :deep(.@{ventSpace}-select-dropdown) {
|
|
|
+ color: #000 !important;
|
|
|
+ .@{ventSpace}-select-item {
|
|
|
+ color: #000 !important;
|
|
|
+ }
|
|
|
+ }
|
|
|
+</style>
|