楼宇能效监测控制系统
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.
 
 
 
 
 

1021 lines
31 KiB

<template>
<div class="app-container">
<div class="left-tree">
<!-- el-tree 设置一个固定的高度和滚动条 -->
<div style="height: 7rem; overflow-y: auto">
<el-tree
ref="tree"
:data="treeData"
node-key="id"
:default-expand-all="false"
:default-expanded-keys="expandedKeys"
:auto-expand-parent="true"
icon-class="none"
@node-expand="handleNodeExpand"
@node-collapse="handleNodeCollapse"
:highlight-current="true"
@node-click="handleNodeClick"
>
<template #default="{ node }">
<span class="custom-tree-node">
<!-- 根据节点状态动态设置图标类名 -->
<div class="tree-left">
<i :class="getIconClass(node)" class="custom-tree-icon"></i>
<span class="tree-label">{{ node.label }}</span>
</div>
</span>
</template>
</el-tree>
</div>
</div>
<div class="right-monitor">
<div class="buildingDiv">
<div class="buildingDiv-left">
<img
class="title-bg"
src="../../../assets/images/title-bg.png"
alt=""
/>
<div class="title-word">位置{{ currentName }}</div>
</div>
<div class="buildingDiv-right">
<div class="wanrn-li">
<i class="el-icon-message-solid" style="color: #fe9805"></i>
<span>高温报警:</span>
<span class="red-text">{{ warningData }}</span>
</div>
<div class="wanrn-li">
<i class="el-icon-message-solid" style="color: #fa260a"></i>
<span>离线设备:</span>
<span class="gray-text">{{ offlineData / 2 }}</span>
</div>
</div>
</div>
<div class="tem-data">
<div class="tem-li" v-for="(item, index) in tableData" :key="index">
<div class="temli-top">
<div>
<div class="temli-title">{{ item.houseName }}</div>
</div>
<div class="top-right">
<!-- 可能有高温报警的img -->
<img
v-if="getDeviceWarning(item.deviceList, '12')"
src="../../../assets/images/warning.png"
class="warning-img"
alt=""
/>
<!-- 在线状态 -->
<img
src="../../../assets/images/online.png"
class="online"
alt=""
v-if="getDevicStatus(item.deviceList, '12')"
/>
<img
src="../../../assets/images/offline.png"
class="online"
alt=""
v-else
/>
<!-- 详情 -->
<div
class="details"
@click="getHistory(item)"
title="查看历史记录"
>
<i class="el-icon-s-data"></i>
</div>
</div>
</div>
<!-- 显示温度 -->
<div
class="tem"
v-if="getDeviceByParamType(item.deviceList, '12')"
:class="{ warningClass: getDeviceWarning(item.deviceList, '12') }"
>
<div class="tem-word">
<img
v-if="getDeviceWarning(item.deviceList, '12')"
class="tem-img"
src="../../../assets/images/tem-warning.png"
alt=""
/>
<img
v-else
class="tem-img"
src="../../../assets/images/tem-normal.png"
alt=""
/>
<div class="tem-middle">
<div>
{{ getDeviceByParamType(item.deviceList, "12").otherName }}
</div>
<div class="en-text">Temperature</div>
</div>
</div>
<div class="tem-right">
<span class="tem-num">{{
getDeviceByParamType(item.deviceList, "12").curValue
}}</span>
<span>℃</span>
</div>
</div>
<!-- 显示湿度 -->
<div class="tem" v-if="getDeviceByParamType(item.deviceList, '32')">
<div class="tem-word">
<img
class="tem-img"
src="../../../assets/images/hum-normal.png"
alt=""
/>
<div class="tem-middle">
<div>
{{ getDeviceByParamType(item.deviceList, "32").otherName }}
</div>
<div class="en-text">Humidity</div>
</div>
</div>
<div class="tem-right">
<span class="tem-num">{{
getDeviceByParamType(item.deviceList, "32").curValue
}}</span>
<span>%</span>
</div>
</div>
</div>
</div>
</div>
<!-- 历史数据弹框 -->
<el-dialog title="当日数据" :visible.sync="openDialog" append-to-body>
<div class="charts" ref="chart_ref"></div>
</el-dialog>
<!-- <div class="charts" ref="chart_ref"></div> -->
</div>
</template>
<script>
import { spaceTree } from "@/api/region";
import { format } from "@/utils/datetime";
import { temList, temHistory } from "@/api/temSys/temMonitor";
import * as echarts from "echarts";
export default {
data() {
return {
loading: false,
treeData: [],
defaultProps: {
children: "children",
label: "label",
},
deviceList: [],
expandedKeys: [],
currentId: "", //当前选中高亮的id
currentName: "", //当前选中的名称
currentLevel: "", //当前节点的层级
currentParentId: "", //当前节点的上级的id
tableData: [], //系统状态表格数据
openDialog: false,
chartInstance: null,
option: {},
chartData1: [],
chartData2: [],
bottomData: [],
warningData: 0,
offlineData: 0,
};
},
mounted() {
this.getSysBuild();
},
destroyed() {
//取消监听器
window.removeEventListener("resize", this.screenAdapter);
},
methods: {
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("温度监测");
});
}
console.log("newRes.data[0]", newRes.data[0]);
// 指定要保留的最大层级(从 1 开始计数),这里假设指定为第 4 级
const targetLevel = 4;
// 从 data[0] 开始处理,当前层级为 1
if (newRes.data[0]) {
this.removeChildrenAfterLevel(newRes.data[0], 1, targetLevel);
}
console.log("筛选后的新结果", newRes);
this.treeData = newRes.data;
this.$nextTick(() => {
// 默认展开节点
this.getExpandedKeys(this.treeData, 1);
if (this.treeData.length > 0) {
// 找到最后一层的第一个子节点
const lastLevelFirstChild = this.findLastLevelFirstChild(
this.treeData[0]
);
// this.$refs.tree.setCurrentKey(
// this.treeData[0].children[0].children[0].children[0].id
// );
// 设置当前选中的节点,默认高亮
this.$refs.tree.setCurrentKey(lastLevelFirstChild.id);
// 更新当前节点的信息
this.currentId = lastLevelFirstChild.id;
this.currentLevel = lastLevelFirstChild.level;
this.currentName = lastLevelFirstChild.label;
console.log("当前选中节点ID", this.currentId);
console.log("当前选中节点层级", this.currentLevel);
console.log("当前选中节点名称", this.currentName);
this.getTemList();
}
});
}
});
},
// 递归函数,用于去除指定层级往后的 children 数据
removeChildrenAfterLevel(obj, currentLevel, targetLevel) {
if (currentLevel >= targetLevel) {
// 当达到指定层级时,将 children 属性置为空数组
obj.children = [];
return;
}
if (obj.children && obj.children.length > 0) {
// 若存在 children 数组,则递归处理每个子项
for (let i = 0; i < obj.children.length; i++) {
this.removeChildrenAfterLevel(
obj.children[i],
currentLevel + 1,
targetLevel
);
}
}
},
// 递归函数,找到最后一层的第一个子节点
findLastLevelFirstChild(node, level = 1) {
if (!node.children || node.children.length === 0) {
return {
id: node.id,
level,
label: node.label,
};
}
return this.findLastLevelFirstChild(node.children[0], level + 1);
},
// 默认只展示一二级菜单
getExpandedKeys(nodes, level) {
nodes.forEach((node) => {
if (level <= this.currentId + 4) {
this.expandedKeys.push(node.id);
}
if (node.children) {
this.getExpandedKeys(node.children, level + 1);
}
});
},
// 更换图标
getIconClass(node) {
// console.log("当前图标的节点内容", node);
if (node.level === 4) {
// 4级菜单时的图标
if (node.expanded) {
return "el-icon-document"; // 4级菜单展开时的图标类名
}
return "el-icon-document"; // 4级菜单收缩时的图标类名
}
if (node.expanded) {
return "el-icon-folder-opened"; // 4三级菜单展开时的图标类名
}
return "el-icon-folder-add"; // 4三级菜单收缩时的图标类名
},
handleNodeExpand(node) {
// 节点展开时触发
},
handleNodeCollapse(node) {
// 节点收缩时触发
},
// 点击当前节点,保存节点内容
handleNodeClick(node, data) {
console.log("点击的当前节点", node, data);
if (data.level !== 4) {
console.log("不是第4层000");
// 设置当前选中的节点,默认高亮
this.$refs.tree.setCurrentKey(this.currentId);
console.log("当前选中节点ID", this.currentId);
console.log("当前选中节点层级", this.currentLevel);
console.log("当前选中节点名称", this.currentName);
} else {
console.log("第5层111");
this.currentId = node.id;
this.currentLevel = data.level;
this.currentName = node.label;
// 设置当前选中的节点,默认高亮
this.$refs.tree.setCurrentKey(this.currentId);
console.log("当前选中节点ID", this.currentId);
console.log("当前选中节点层级", this.currentLevel);
console.log("当前选中节点名称", this.currentName);
this.getTemList();
}
},
getTemList() {
let data = {
systemType: "4",
floorId: this.currentId,
};
temList(data).then((res) => {
console.log("温度返回", res);
this.warningData = 0;
this.offlineData = 0;
if (res.code == 200) {
this.tableData = res.rows;
// 统计高温报警和离线的数据
this.tableData.forEach((item) => {
item.deviceList.forEach((device) => {
if (device.alarmStatus === 1) {
this.warningData++;
}
if (device.status !== 0) {
this.offlineData++;
}
});
});
} else {
this.tableData = [];
this.warningData = 0;
this.offlineData = 0;
}
});
},
getDeviceByParamType(deviceList, paramType) {
let obj = deviceList.find((device) => device.paramType === paramType);
return obj;
},
// 高温报警
getDeviceWarning(deviceList, paramType) {
// console.log("deviceList", deviceList);
return deviceList.some((item) => {
// console.log("item.paramType", item.paramType);
// console.log("item.alarmStatus", item.alarmStatus);
if (item.paramType === paramType && item.alarmStatus === 1) {
// console.log("返回true了呀");
return true;
}
return false;
});
},
// 设备在线状态
getDevicStatus(deviceList, paramType) {
// console.log("在线状态deviceList", deviceList);
return deviceList.some((item) => {
if (item.paramType === paramType && item.status === 0) {
// console.log("返回true了呀");
return true;
}
return false;
});
},
getHistory(item) {
console.log("item", item);
// 打开当前房间的历史记录的内容
this.openDialog = true;
this.$nextTick(() => {
this.echartsData(item.houseId);
});
},
echartsData(id) {
const start = new Date(new Date().setHours(0, 0, 0, 0));
const end = new Date(new Date().setHours(23, 59, 59, 59));
let data = {
systemType: "4",
houseIds: [id],
startTime: format(start),
endTime: format(end),
};
temHistory(data).then((res) => {
console.log("历史数据返回", res);
if (res.code == 200) {
let data = res.rows[0].dataList;
this.chartData1 = [];
this.chartData2 = [];
this.bottomData = [];
console.log("data", data);
data.forEach((item) => {
// 处理 chartData1
const value1 =
item.indoorTemp === null || item.indoorTemp === ""
? 0
: item.indoorTemp;
this.chartData1.push(value1);
// 假设 item 中对应 chartData2 的字段是 indoorHumidity
const value2 =
item.indoorHumidity === null || item.indoorHumidity === ""
? 0
: item.indoorHumidity;
this.chartData2.push(value2);
// 假设 item 中对应 bottomData 的字段是 curTime
const value3 =
item.curTime === null || item.curTime === "" ? 0 : item.curTime;
this.bottomData.push(value3);
});
this.initChart();
window.addEventListener("resize", this.screenAdapter);
this.screenAdapter();
}
});
// // chartData1是实线部分, chartData2是虚线代表预测部分
// // chartData2的值 为 [ chartData1的长度-1个" "空值,chartData1最后一个值, xxx,xxx,xxx ]
// const adapterOption = {
// xAxis: {
// data: this.bottomData,
// },
// series: [
// {
// yAxisIndex: 0,
// data: this.chartData1,
// },
// {
// yAxisIndex: 0,
// data: this.chartData2,
// },
// ],
// };
// this.chartInstance.setOption(adapterOption);
// //手动的调用图标对象的resize才能产生效果
// this.chartInstance.resize();
},
// 折线图自适应+ 根据按钮切换图例仅限一条且不可点击+ 折线图数据
screenAdapter() {
//自己定义的比较合适的适配大小,2.6 mes_ref是图表盒子
const titleFontSize = this.$refs.chart_ref.offsetWidth / 130;
//因为option可以多次配置的,所以这里的option只需要写 需要配置大小的相关数据
const adapterOption = {};
//记得重新给配置项给实例对象。只要实例对象.chartInstance不变,option就可以多次配置不同的条件。也可以配置一个dataoption只写需要从后台请求的数据相关
this.chartInstance.setOption(adapterOption);
//手动的调用图标对象的resize才能产生效果
this.chartInstance.resize();
},
//初始化chartInstance对象
initChart() {
const chartRef = this.$refs.chart_ref;
if (chartRef) {
// 初始化图表的代码
this.chartInstance = echarts.init(this.$refs.chart_ref);
const titleFontSize = this.$refs.chart_ref.offsetWidth / 70;
this.option = {
tooltip: {
trigger: "axis",
textStyle: {
// 设置提示框内文字的大小
fontSize: titleFontSize,
},
},
legend: {
show: true,
top: 10,
textStyle: {
color: "white",
fontSize: titleFontSize,
},
},
grid: {
top: "10%",
left: "4%",
right: "6%",
bottom: "3%",
containLabel: true,
},
xAxis: {
type: "category",
//设置为true代表离零刻度间隔一段距离
boundaryGap: true,
// 修饰刻度标签的颜色即x坐标数据
axisLabel: {
// interval: 0, //强制显示所有x轴数据
// rotate: 30, //x轴坐标字体倾斜30度
color: "rgba(255, 255, 255, 1)",
fontSize: titleFontSize, //x轴文字大小
},
axisTick: {
show: false, // 不显示坐标轴刻度线
},
// x坐标轴的颜色
axisLine: {
show: true,
lineStyle: {
color: "#365576",
},
},
splitLine: {
lineStyle: {
color: "#e2e6f0",
},
}, //x轴分割线
data: this.bottomData,
},
yAxis: {
min: 0,
// max:20,
// // // min:'dataMin',
// // // max:'dataMax',
// name: "kwh", // 第一个 y 轴的单位描述
// 设置 name 的样式
nameTextStyle: {
color: "rgba(255, 255, 255, 1)",
fontSize: 12,
},
miniInterval: 5,
type: "value",
// 修饰刻度标签的颜色即y坐标数据
axisLabel: {
color: "rgba(255, 255, 255, 1)",
fontSize: titleFontSize, //x轴文字大小
},
// 显示y坐标轴
axisLine: {
show: true,
lineStyle: {
color: "#365576", // 设置 y 轴线的颜色
},
},
//y轴分割线段数
// splitNumber: 10,
// 修改y轴分割线的颜色
splitLine: {
lineStyle: {
color: "#1a3d62", // 设置分割线的颜色
type: "dashed", // 设置分割线为虚线
},
},
},
series: [
{
type: "line",
// 拐点大小
// 拐点大小
symbolSize: titleFontSize * 0.5,
lineStyle: {
// 设置折线的厚度
width: titleFontSize * 0.1,
},
data: this.chartData2,
name: "湿度",
//折线颜色
itemStyle: {
color: "#00CED1", //折线的颜色
},
smooth: false,
// 不显示折线点
showSymbol: true,
areaStyle: {
color: {
type: "linear",
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: "rgba(0, 206, 209, 0.5)", // 渐变起始颜色
},
{
offset: 1,
color: "rgba(0, 206, 209, 0)", // 渐变结束颜色
},
],
global: false, // 缺省为 false
},
},
},
{
type: "line",
// 拐点大小
symbolSize: titleFontSize * 0.5,
lineStyle: {
// 设置折线的厚度
width: titleFontSize * 0.1,
},
data: this.chartData1,
name: "温度",
//折线颜色
itemStyle: {
color: "#1a69f1", //折线点的颜色
},
lineStyle: {
color: "#1a69f1", //折线点的颜色
},
smooth: false,
// 不显示折线点
showSymbol: true,
// 区域填充样式,添加渐变背景
areaStyle: {
color: {
type: "linear",
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: "rgba(26, 105, 241, 0.5)", // 渐变起始颜色
},
{
offset: 1,
color: "rgba(26, 105, 241, 0)", // 渐变结束颜色
},
],
global: false, // 缺省为 false
},
},
},
],
};
//把配置项给实例对象
this.chartInstance.setOption(this.option, true);
} else {
console.error("未找到有效的 DOM 元素");
}
},
},
};
</script>
<style lang="scss" scoped>
.app-container {
display: flex;
flex-direction: row;
justify-content: space-between;
flex-wrap: nowrap;
align-items: stretch;
height: 100%;
.left-tree {
width: 256px;
padding: 15px 10px 10px 10px;
border: 1px solid #004b8c;
}
.right-monitor {
width: calc(100% - 280px);
display: flex;
flex-direction: column;
justify-content: flex-start;
.buildingDiv {
padding-left: 54px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
position: relative;
.title-bg {
width: 208px;
height: 38px;
position: absolute;
left: 0;
z-index: 0;
}
.title-word {
z-index: 10;
font-family: YouSheBiaoTiHei;
font-size: 24px;
color: #ffffff;
white-space: nowrap;
}
.buildingDiv-right {
display: flex;
flex-direction: row;
align-items: center;
margin-right: 20px;
color: #c7dbe6;
font-size: 18px;
.wanrn-li {
display: flex;
flex-direction: row;
align-items: center;
margin-right: 50px;
.el-icon-message-solid {
margin-right: 3px;
}
.red-text {
color: #fe9805;
font-size: 20px;
font-weight: bold;
margin-left: 5px;
}
.gray-text {
color: #fa260a;
font-size: 20px;
font-weight: bold;
margin-left: 5px;
}
}
}
}
.tem-data {
width: 100%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-content: flex-start;
height: 800px;
overflow-y: auto;
.tem-li {
display: flex;
flex-direction: column;
width: calc(33.33% - 20px);
height: 255px;
background-image: url(../../././../assets/images/border-7.png);
background-size: 100% 100%;
background-repeat: no-repeat;
padding: 20px;
margin: 0 10px 20px 10px;
transition: filter 0.3s ease;
.temli-top {
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
color: #ffffff;
font-size: 18px;
margin-bottom: 15px;
.top-right {
display: flex;
flex-direction: row;
align-items: center;
.online {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
margin: 0 15px 0 0;
width: 25px;
height: 18px;
}
}
}
.temli-title {
height: 40px;
font-family: Arial, sans-serif;
font-size: 20px;
font-weight: bold;
color: #00aaff;
text-shadow: 0 0 5px rgba(0, 170, 255, 0.5);
margin-left: 7px;
}
.warning-img {
width: 35px;
height: 35px;
margin-right: 10px;
/* 添加闪烁动画 */
animation: blink 1s infinite;
}
@keyframes blink {
100% {
opacity: 1;
}
50% {
opacity: 0;
}
}
.tem {
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
color: #ffffff;
font-size: 18px;
.tem-word {
display: flex;
flex-direction: row;
align-items: center;
.tem-img {
width: 80px;
height: 80px;
margin-right: 15px;
}
.tem-middle {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: flex-start;
.en-text {
font-size: 13px;
margin-top: 10px;
}
}
}
.tem-right {
font-size: 16px;
margin-top: 15px;
.tem-num {
font-size: 30px;
font-weight: bold;
margin-right: 10px;
}
}
}
.warningClass {
color: #fe9805 !important;
}
.details {
background-color: #3c8dd4;
width: 40px;
height: 40px;
border-radius: 50%;
text-align: center;
line-height: 40px;
cursor: pointer;
}
}
.details:hover .tem-li {
filter: brightness(
1.2
); /* 降低亮度,使背景图片颜色更深,可根据需求调整数值 */
transform: scale(1.02);
}
.tem-li:hover {
}
}
}
}
.charts {
width: 870px;
height: 300px;
}
.tree-container {
height: 330px; /* 设置固定高度 */
overflow-y: auto; /* 启用垂直滚动条 */
}
// 滚动条
:-webkit-scrollbar {
width: 10px; /* 滚动条宽度 */
}
::-webkit-scrollbar-track {
background: transparent !important; /* 滚动条轨道背景色 */
}
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
.tree-left {
.custom-tree-icon {
margin-right: 5px;
}
}
}
@media (min-width: 1200px) and (max-width: 1540px) {
.tem-li {
width: calc(49% - 20px) !important;
}
}
@media (max-width: 1200px) {
.tem-li {
width: calc(100% - 40px) !important;
}
}
// 媒体查询,适配大于2000px分辨率的大屏样式
@media (min-width: 2000px) {
.app-container {
.left-tree {
width: 2.56rem !important;
padding: 0.15rem 0.1rem 0.1rem 0.1rem !important;
}
.right-monitor {
width: calc(100% - 2.8rem) !important;
.buildingDiv {
padding-left: 0.54rem !important;
margin-bottom: 0.2rem !important;
.title-bg {
width: 2.08rem !important;
height: 0.38rem !important;
}
.title-word {
font-size: 0.24rem !important;
}
.buildingDiv-right {
margin-right: 0.2rem !important;
font-size: 0.18rem !important;
.wanrn-li {
margin-right: 0.5rem !important;
.el-icon-message-solid {
margin-right: 0.03rem !important;
}
.red-text {
font-size: 0.2rem !important;
margin-left: 0.05rem !important;
}
.gray-text {
font-size: 0.2rem !important;
margin-left: 0.05rem !important;
}
}
}
}
.tem-data {
height: 8rem !important;
.tem-li {
width: calc(33.33% - 0.2rem) !important;
height: 2.55rem !important;
padding: 0.2rem !important;
margin: 0 0.1rem 0.2rem 0.1rem !important;
.temli-top {
font-size: 0.18rem !important;
margin-bottom: 0.15rem !important;
.top-right {
.online {
margin: 0 0.15rem 0 0 !important;
width: 0.25rem !important;
height: 0.18rem !important;
}
}
}
.temli-title {
height: 0.4rem !important;
font-size: 0.2rem !important;
margin-left: 0.07rem !important;
}
.warning-img {
width: 0.35rem !important;
height: 0.35rem !important;
margin-right: 0.1rem !important;
}
.tem {
font-size: 0.18rem !important;
.tem-word {
.tem-img {
width: 0.8rem !important;
height: 0.8rem !important;
margin-right: 0.15rem !important;
}
.tem-middle {
.en-text {
font-size: 0.13rem !important;
margin-top: 0.1rem !important;
}
}
}
.tem-right {
font-size: 0.16rem !important;
margin-top: 0.15rem !important;
.tem-num {
font-size: 0.3rem !important;
margin-right: 0.1rem !important;
}
}
}
.details {
width: 0.4rem !important;
height: 0.4rem !important;
line-height: 0.4rem !important;
}
}
}
}
}
.charts {
width: 8.7rem !important;
height: 3rem !important;
}
}
</style>
<style scoped>
/* 自定义高亮颜色 */
.left-tree
>>> .el-tree--highlight-current
.el-tree-node.is-current
> .el-tree-node__content {
background-color: #285b9e !important;
/* color: #f56c6c; */
color: #25f1f8;
}
</style>
<style scoped lang="scss">
/* 媒体查询适配大于2000px分辨率的大屏样式 - element样式 */
@media (max-width: 2000px) {
::v-deep .el-dialog {
width: 900px !important;
}
}
@media (min-width: 2000px) {
::v-deep .el-dialog {
width: 9rem !important;
}
}
</style>