楼宇能效监测控制系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

371 lines
10 KiB

<template>
<div class="app-container">
<div class="btn-condition">
<div class="condition-left">
<el-form
:model="queryParams"
ref="queryForm"
size="small"
:inline="true"
label-width="68px"
>
<el-form-item label="房间" prop="gwName">
<el-cascader
class="elCascader"
:options="options"
:props="props"
collapse-tags
clearable
v-model="selectedValue"
@change="handleCascaderChange"
filterable
></el-cascader>
</el-form-item>
<el-form-item label="时间范围" prop="gwName">
<el-date-picker
v-model="timeDate"
:default-time="['00:00:00', '23:59:59']"
type="datetimerange"
value-format="yyyy-MM-dd HH:mm:ss"
range-separator="至"
placeholder="选择日期"
start-placeholder="开始日期"
end-placeholder="结束日期"
>
</el-date-picker>
</el-form-item>
</el-form>
<div class="primary-btn">
<el-button
type="primary"
icon="el-icon-search"
size="mini"
@click="handleQuery"
>搜索</el-button
>
</div>
</div>
</div>
<div class="history" v-loading="loading">
<div
class="history-li"
:class="{
oneClass: tableData.length === 1,
twoClass: tableData.length === 2,
}"
v-for="(item, index) in tableData"
:key="index"
>
<div class="history-top">
<div class="room">{{ item.houseName }}</div>
<div class="change" @click="toggleComponent(index)">
<svg-icon
slot="prefix"
icon-class="chartsSvg"
class="chartsSvg"
v-if="item.showCharts"
/>
<svg-icon
slot="prefix"
icon-class="tableSvg"
class="tableSvg"
v-else
/>
</div>
</div>
<div class="title">{{ dayDate[0] }}{{ dayDate[1] }}温湿度数据</div>
<!-- 图表和表格可以自由切换 -->
<history-charts
v-if="item.showCharts"
:chartsData="item.dataList"
:isShowOne="showOneClass"
></history-charts>
<history-tables
v-else
:tableData="item.dataList"
:isShowOne="showOneClass"
></history-tables>
</div>
</div>
</div>
</template>
<script>
import { format2, formatDay } from "@/utils/datetime";
import { spaceTree } from "@/api/region";
import { temHistory } from "@/api/temSys/temMonitor";
import historyCharts from "./components/historyCharts.vue";
import HistoryTables from "./components/historyTables.vue";
export default {
components: { historyCharts, HistoryTables },
data() {
return {
loading: false,
timeDate: [],
dayDate: [],
// 查询参数
queryParams: {
systemType: "4",
houseIds: [], //多选房间的id数组
startTime: "",
endTime: "",
},
selectedValue: [], //选中的数组(里面也是数组)
props: {
value: "id", // 指定使用 id 作为值的标识
label: "label",
children: "children",
multiple: true,
},
options: [],
tableData: [],
showOneClass: true,
};
},
mounted() {
this.initializeTimeDate();
this.getSysBuild();
},
methods: {
// 初始化时间
initializeTimeDate() {
const start = new Date(new Date().setHours(0, 0, 0, 0));
const end = new Date(new Date().setHours(23, 59, 59, 59));
this.timeDate = [format2(start), format2(end)]; // 更新
this.dayDate = [formatDay(start), formatDay(end)];
},
getSysBuild() {
spaceTree().then((res) => {
if (res.code == 200) {
// 只需要保留热水的系统
console.log("楼栋返回值", res);
let newRes = { ...res };
if (newRes.data && newRes.data[0] && newRes.data[0].children) {
newRes.data[0].children = newRes.data[0].children.filter((item) => {
// 假设子项有一个 label属性,用于检查是否包含 "热水"
return item.label && item.label.includes("温度监测");
});
}
this.options = newRes.data[0].children[0].children;
console.log("温度监测的数组", this.options);
// 提取路径
if (this.options.length > 0) {
// 找到最后一层的第一个子节点
const lastLevelFirstChild = this.findLastLevelFirstChild(
this.options[0]
);
console.log("最后一个节点的id", lastLevelFirstChild);
// 查找完整路径
const path = this.findPath(this.options, lastLevelFirstChild.id);
if (path) {
this.selectedValue = [path];
}
console.log("反推三个id", path);
this.queryParams.houseIds = path;
}
this.getList();
}
});
},
// 递归函数,找到最后一层的第一个子节点
findLastLevelFirstChild(node, level = 1) {
if (!node.children || node.children.length === 0) {
return {
id: node.id,
};
}
return this.findLastLevelFirstChild(node.children[0], level + 1);
},
// 最后id反推前三id数组
findPath(options, targetId, currentPath = []) {
for (let i = 0; i < options.length; i++) {
const item = options[i];
// 检查 item 是否有 id 属性
if (!item.id) continue;
const newPath = [...currentPath, item.id];
if (item.id === targetId) {
return newPath;
}
if (item.children && item.children.length > 0) {
const result = this.findPath(item.children, targetId, newPath);
if (result) {
return result;
}
}
}
return null;
},
handleQuery() {
this.getList();
},
getList() {
this.queryParams.startTime = this.timeDate[0];
this.queryParams.endTime = this.timeDate[1];
this.dayDate = [
formatDay(this.queryParams.startTime),
formatDay(this.queryParams.endTime),
];
let data = this.queryParams;
console.log("参数", data);
// 开启 loading 效果
this.loading = true;
temHistory(data)
.then((res) => {
console.log("历史数据返回", res);
if (res.code == 200) {
// 过滤掉 dataList 为空的对象
const filteredRows = res.rows.filter(
(item) => item.dataList && item.dataList.length > 0
);
// 为过滤后的每个对象添加 showCharts: true 属性
const newRows = filteredRows.map((item) => ({
...item,
showCharts: true,
}));
this.tableData = newRows;
if (this.tableData.length > 2) {
this.showOneClass = false;
} else {
this.showOneClass = true;
}
console.log("处理后的历史数据", newRows);
console.log("动态class布尔值", this.showOneClass);
}
})
.catch((error) => {
console.error("查询表格数据时发生错误:", error);
this.loading = false;
})
.finally(() => {
setTimeout(() => {
this.loading = false;
}, 1000);
});
},
handleCascaderChange(selectedOptions) {
console.log("选中的完全路径", selectedOptions);
// 提取所有选中项的最后一级 id 值
const selectedIds = selectedOptions.map(
(option) => option[option.length - 1]
);
console.log("选中的 id 数组:", selectedIds);
this.queryParams.houseIds = selectedIds;
},
toggleComponent(index) {
// 切换显示状态
this.tableData[index].showCharts = !this.tableData[index].showCharts;
},
},
};
</script>
<style lang="scss" scoped>
.elCascader {
width: 350px;
}
.history {
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
flex-wrap: wrap;
.history-li {
background-color: rgb(38, 64, 99);
width: calc(49% - 20px);
height: 350px;
margin: 0 10px;
padding: 20px;
border-radius: 20px;
margin-bottom: 20px;
.history-top {
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.room {
font-family: Arial, sans-serif;
font-size: 20px;
font-weight: bold;
color: #00aaff;
text-shadow: 0 0 5px rgba(0, 170, 255, 0.5);
}
.change {
cursor: pointer;
width: 30px;
height: 30px;
border-radius: 50%;
background-color: #00aaff;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
}
.title {
width: 100%;
font-size: 15px;
color: #fff;
font-weight: bold;
margin: 10px 0;
text-align: center;
}
}
.oneClass {
width: 100% !important;
height: 750px !important;
}
.twoClass {
height: 750px !important;
}
}
// 媒体查询,适配大于2000px分辨率的大屏样式
@media (min-width: 2000px) {
.elCascader {
width: 3.5rem !important;
}
.history {
.history-li {
width: calc(49% - 0.2rem) !important;
height: 3.4rem !important;
margin: 0 0.1rem !important;
padding: 0.2rem !important;
border-radius: 0.2rem !important;
margin-bottom: 0.2rem !important;
.history-top {
.room {
font-size: 0.2rem !important;
}
.change {
width: 0.3rem !important;
height: 0.3rem !important;
}
}
.title {
font-size: 0.15rem !important;
margin: 0.1rem 0 !important;
}
}
.oneClass {
width: 100% !important;
height: 7.5rem !important;
}
.twoClass {
height: 7.5rem !important;
}
}
}
</style>
<style scoped>
.elCascader >>> .el-input__inner::placeholder {
color: transparent !important;
}
/* // 媒体查询,适配大于2000px分辨率的大屏样式 */
@media (min-width: 2000px) {
.condition-left >>> .el-form-item__label {
width: 0.68rem !important;
}
}
</style>