Browse Source

docs:实时数据

master
waibao2 1 month ago
parent
commit
47e8cdca51
  1. 311
      src/views/data/currdata/index.vue

311
src/views/data/currdata/index.vue

@ -0,0 +1,311 @@ @@ -0,0 +1,311 @@
<template>
<div class="app-container app-container-bg">
<el-card class="first-card" ref='firstCard' shadow="always">
<el-form :model="queryParams" ref="queryForm" :inline="true" @submit.native.prevent>
<el-form-item label="测站属性" prop="prop">
<el-select v-model="queryParams.prop" placeholder="请选择测站属性" style="width:100%" @change="propChange">
<el-option v-for="dict in propsList" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="测站名称" prop="stnmId">
<el-select v-model="queryParams.stnmId" placeholder="请选择测站名称" style="width:100%" @change="handleQuery">
<el-option v-for="dict in stationList" :key="dict.stnmId" :label="dict.stnm" :value="dict.stnmId"></el-option>
</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>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['data:currdata:export']">导出</el-button>
</el-col>
</el-row>
</el-card>
<div class="el-card-p card-shadow carder-border mt10 pad10 currdata" v-loading="fullscreenLoading">
<div class="table-container" v-if="processedTables.length > 0" v-infinite-scroll="loadMore" infinite-scroll-disabled="busy" infinite-scroll-distance="30">
<div class="table-grid" :style="{ gridTemplateColumns: `repeat(${itemsPerRow}, 1fr)` }">
<div class="table-item" v-for="(table, index) in processedTables" :key="index">
<el-table :data="table.data" class="double-header-table" :show-header="true" :header-cell-style="{ backgroundColor: '#3F7DEC !important', }" style="width: 100%;" size="mini">
<el-table-column :label="table.stnm" width="120" show-overflow-tooltip>
<template #header #default="scope">
<div class="header-content">
<el-tooltip effect="dark" :content="table.stnm" placement="top-end" :open-delay="300">
<div class="item-station cursor">
<div>
{{ table.stnm }}
</div>
<div>{{ table.stcd }}</div>
</div>
</el-tooltip>
<div class="header-right ">
<span class="item-time">{{ table.tm }}</span>
</div>
</div>
</template>
<el-table-column prop="typeName" label="名称" show-overflow-tooltip />
<el-table-column prop="value" label="值" :class-name="value-name" />
<el-table-column prop="unit" label="单位" width="80" />
</el-table-column>
</el-table>
</div>
</div>
</div>
<el-empty class="table-container " v-else :image-size="200"></el-empty>
</div>
</div>
</template>
<script setup>
import { ref, reactive, onMounted, } from 'vue'
import _ from 'lodash'
const { proxy } = getCurrentInstance()
const alignment = 'center'
const queryParams = reactive({
page: 1,
limit: 10,
stnmId: '',
prop: "",
mainType: "A"
})
const fullscreenLoading = ref(false)
let currdataList = []
let total = 0
const getList = async () => {
fullscreenLoading.value = true;
try {
const res = await proxy.axiosGet('/data/currdata/queryAll', queryParams)
if (res.code == 0) {
currdataList = res.data
total = currdataList.length
formatTableData()
}
} catch (error) {
} finally {
fullscreenLoading.value = false
}
}
let tableList = ref([])
const formatTableData = () => {
const result = _.chain(currdataList)
.groupBy('stnm')
.map((group, stnm) => ({
stnm,
stcd: group[0].stcd,
tm: group[0].latestTm,
data: group.map(item => ({
...item,
value: item.val !== null ? item.val : item.latestValue
}))
}))
.value();
tableList.value = result
}
//
const busy = ref(false)
const loadMore = async () => {
let all = total <= queryParams.page * queryParams.limit
if (busy.value && all) return; //
busy.value = true; //
queryParams.page += 1
let response = await proxy.axiosGet('/data/currdata/queryAll', queryParams);
if (response.code == 0) {
let rawData = response.data
let concatData = currdataList.concat(rawData)
currdataList = concatData
formatTableData()
}
busy.value = false;
}
const itemsPerRow = ref(5)
const processedTables = computed(() => {
let data = tableList.value
const result = [];
const rows = Math.ceil(data.length / itemsPerRow.value);
for (let i = 0; i < rows; i++) {
const startIndex = i * itemsPerRow.value;
const endIndex = Math.min(startIndex + itemsPerRow.value, data.length);
const rowTables = data.slice(startIndex, endIndex);
//
const maxRows = Math.max(...rowTables.map(table => table.data.length));
//
rowTables.forEach(table => {
const newTable = { ...table };
//
if (table.data.length < maxRows) {
const emptyRows = Array(maxRows - table.data.length).fill({});
newTable.data = [...table.data, ...emptyRows];
}
result.push(newTable);
});
}
return result;
})
//
const stationList = ref([])
const propChange = async () => {
try {
let res = await proxy.axiosGet('/basic/station/queryStnmandStnmId', queryParams);
if (res.code == 200) {
stationList.value = res.data;
}
} catch (error) {
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNum = 1
getList()
}
const resetQuery = () => {
proxy.resetForm("queryForm");
handleQuery();
}
//
const handleExport = async () => {
let p = {
page: 1,
limit: 9999,
stnm: queryParams.stnm,
mainType: queryParams.mainType,
}
let res = await proxy.axiosGet('/data/currdata/queryAll', p);
if (res.code === 0) {
let table = [];
table.push({
A: "站点名称",
B: "设备ID",
C: "类型",
D: "最新数值",
E: "最新上传时间",
});
res.data.forEach(d => {
let row = {
A: d.stnm,
B: d.stcd,
C: d.typeName,
D: d.latestValue,
E: d.latestTm
};
table.push(row);
});
let header = ["A", "B", "C", "D", "E"];
let fileName = "站点实时数据";
proxy.exportExcel(header, table, fileName);
}
}
onMounted(() => {
getList()
propChange()
})
const propsList = ref([
{ label: '水文测站', value: 0 },
{ label: '气象站', value: 1 }
])
</script>
<style lang="scss" scoped>
.currdata {
overflow-y: scroll;
}
.table-container {
width: 100%;
.table-grid {
display: grid;
grid-template-columns: repeat(var(--grid-columns), 1fr);
gap: 20px;
width: 100%;
.table-item {
min-width: 240px;
/* 防止表格溢出*/
}
}
.header-content {
display: flex;
justify-content: space-between;
flex-wrap: nowrap;
.item-station {
width: 150px;
white-space: nowrap !important;
text-overflow: ellipsis;
word-break: break-all;
overflow: hidden;
}
.item-station,
.item-icon,
.item-time {
font-size: 12px;
color: #fff;
/* flex-wrap: nowrap; */
}
.item-icon {
cursor: pointer;
margin-left: 2px;
}
}
}
/* 表格样式 */
:deep(.double-header-table) {
border-radius: 12px;
&::before {
display: none;
}
.el-table__fixed-right::before {
display: none;
}
.el-table__body-wrapper::-webkit-scrollbar {
display: none;
}
/* 统一行高 */
.el-table__row {
height: 39.6667px;
}
/* 空行样式 */
.el-table__row--empty {
background-color: #f5f7fa;
}
/* 隐藏子表头 */
.el-table__header tr:nth-child(2) {
display: none;
}
/* 调整主表头样式 */
.el-table__header tr:first-child th {
background: #f5f7fa;
font-weight: bold;
}
}
/** 取消表格滑上的背景色 */
:deep(.el-table--enable-row-hover .el-table__body tr:hover>td.el-table__cell) {
background: #fff !important;
}
</style>
Loading…
Cancel
Save