This commit is contained in:
ljx
2025-11-03 18:56:57 +08:00
parent fd4e05a802
commit 7b4cdd2b3c
3 changed files with 197 additions and 43 deletions

View File

@ -5,10 +5,6 @@
"ComputedRef": true,
"DirectiveBinding": true,
"EffectScope": true,
"ElLoading": true,
"ElMessage": true,
"ElMessageBox": true,
"ElNotification": true,
"ExtractDefaultPropTypes": true,
"ExtractPropTypes": true,
"ExtractPublicPropTypes": true,
@ -318,6 +314,10 @@
"watchThrottled": true,
"watchTriggerable": true,
"watchWithFilter": true,
"whenever": true
"whenever": true,
"ElMessage": true,
"ElLoading": true,
"ElMessageBox": true,
"ElNotification": true
}
}

View File

@ -56,7 +56,7 @@ export const getOption = (xData: any, yData: any) => {
{
// show: true,
start: 0,
end: 30,
end: 100,
bottom: 2, // 下滑块距离x轴底部的距离
height: 23
},
@ -177,7 +177,7 @@ export const getOption2 = (data: any) => {
// show: true,
start: 0,
end: 30,
end: 100,
bottom: 2, // 下滑块距离x轴底部的距离
height: 23
},
@ -322,7 +322,7 @@ export const getLineOption = (lineData: any) => {
{
// show: true,
start: 0,
end: 30,
end: 100,
bottom: 2, // 下滑块距离x轴底部的距离
height: 23
},
@ -674,7 +674,7 @@ export const getBarOptions = (data: any) => {
{
// show: true,
start: 0,
end: 30,
end: 100,
bottom: 2, // 下滑块距离x轴底部的距离
height: 23
},

View File

@ -5,28 +5,38 @@
<div class="header">
<img src="@/assets/large/right1.png" style="width: 17px; height: 18px" alt="" />
<span class="title">告警信息中心</span>
<!-- <el-badge :value="unhandledCount" class="unhandled-badge" type="danger"> {{ unhandledCount }}条未处理 </el-badge> -->
<span class="jgao">{{ alarmData.length }}条信息未处理</span>
</div>
<!-- 告警卡片列表可循环渲染这里演示单条 -->
<!-- 告警卡片列表 -->
<div class="alarm_list">
<el-card class="alarm-card" shadow="hover" v-for="(item, index) in alarmData" :key="index">
<div class="alarm-card" v-for="(item, index) in alarmData" :key="index">
<div class="card-header">
<img src="@/assets/large/right2.png" style="width: 15px; height: 15px" alt="" />
<span class="card-title">{{ item.alarmMsg }}</span>
<span class="time">{{ formatDate(item.alarmBeginTime) }}</span>
</div>
<div class="card-content">
{{ item.advice }}
</div>
<div class="card-footer">
<el-tag type="danger" size="small">紧急</el-tag>
<el-tag type="danger" size="small">处理</el-tag>
</div>
</el-card>
<div class="card-content">
<!-- 文本容器控制3行溢出 -->
<div class="text-container">
{{ item.advice }}
</div>
<!-- 查看更多按钮右侧显示 -->
<div class="read-more" @click="open(item)">查看更多</div>
</div>
</div>
</div>
</div>
<div class="detailBox" :class="{ 'show': newDetail }">
<div class="boxContent" v-html="newDetail?.advice"></div>
<!-- 假设 item content 字段根据实际调整 -->
<div class="close" @click="newDetail = null">
<CircleClose style="width: 1.2em; height: 1.2em" />
</div>
</div>
<div class="overview">
<div class="left_title">
<div style="display: flex; align-items: center">
@ -73,7 +83,7 @@
<span
class="progress-percent"
:class="{
green1: item.rate >= 99, // 可根据需求调整颜色规则
green1: item.rate >= 99,
orange1: item.rate < 99 && item.rate >= 90
}"
>{{ item.rate }}%</span
@ -84,7 +94,7 @@
class="progress-fg"
:style="{ width: item.rate + '%' }"
:class="{
green: item.rate >= 99, // 可根据需求调整颜色规则
green: item.rate >= 99,
orange: item.rate < 99 && item.rate >= 90
}"
></div>
@ -93,7 +103,6 @@
</div>
<div class="container_item_two">
<div>正常{{ item.normal }}</div>
<div>异常{{ item.abnormal }}</div>
</div>
</div>
@ -103,15 +112,15 @@
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { ref, nextTick, onUnmounted } from 'vue';
import { getAlarmListOverview } from '@/api/large';
import { formatDate } from '@/utils/index';
const alarmData: any = ref({});
const alarmData = ref<any[]>([]);
const deviceStats = ref([
{
name: '光伏组件',
icon: '../../../assets/large/right5.png', // 示例图标
icon: '../../../assets/large/right5.png',
total: '25,680',
unit: '块',
rate: 99.2,
@ -155,13 +164,85 @@ const deviceStats = ref([
abnormal: 12
}
]);
// 存储所有绑定的事件处理函数,用于卸载时解绑
const eventHandlers: Array<() => void> = [];
// 处理“查看更多/收起”逻辑
const handleReadMore = async () => {
await nextTick();
const textContainers: any = document.querySelectorAll('.alarm-card .text-container');
const readMoreBtns: any = document.querySelectorAll('.alarm-card .read-more');
// 清空之前的事件绑定(避免重复绑定)
eventHandlers.forEach((handler) => handler());
eventHandlers.length = 0;
textContainers.forEach((textContainer, index) => {
const btn = readMoreBtns[index] as HTMLDivElement;
if (!btn) return;
// 关键修改判断文本是否超过3行scrollHeight > clientHeight 表示溢出)
const isOverflow = textContainer.scrollHeight > textContainer.clientHeight;
btn.style.display = isOverflow ? 'inline-block' : 'none';
// 定义点击事件处理函数
// const toggleExpand = () => {
// const isExpanded = textContainer.style.webkitLineClamp === 'none';
// if (isExpanded) {
// // 收起恢复3行限制
// textContainer.style.webkitLineClamp = '3';
// btn.textContent = '查看更多';
// } else {
// // 展开:取消行数限制
// textContainer.style.webkitLineClamp = 'none';
// btn.textContent = '收起';
// }
// };
// 绑定点击事件并存储,用于后续解绑
// btn.addEventListener('click', toggleExpand);
// eventHandlers.push(() => {
// btn.removeEventListener('click', toggleExpand);
// });
});
};
// 接口请求:获取告警数据后执行处理逻辑
const getAlarm = () => {
getAlarmListOverview().then((res) => {
console.log(res);
alarmData.value = res.data;
handleReadMore(); // 数据渲染后执行文本溢出处理
});
};
// 初始化调用接口
getAlarm();
// 定义 item 类型(替换 any提升类型安全性
interface ItemType {
id: string | number;
advice: string; // 存储富文本内容的字段,根据实际数据结构调整
// 其他字段...
}
const newDetail = ref(null);
// 假设 item 是当前列表项(实际可能来自 v-for 循环)
const item = ref<ItemType>({
id: 1,
advice: '<p>这是要显示的详情内容...</p>' // 示例富文本内容
});
// 切换展开/隐藏逻辑
const open = (targetItem: ItemType) => {
// 如果当前展开的就是目标项 → 隐藏;否则 → 展开目标项
newDetail.value = newDetail.value === targetItem ? null : targetItem;
console.log(newDetail.value);
};
// 组件卸载时解绑所有事件(避免内存泄漏)
onUnmounted(() => {
eventHandlers.forEach((handler) => handler());
});
</script>
<style scoped lang="scss">
@ -171,10 +252,9 @@ getAlarm();
}
.alarm-container {
border: 1px solid #1e2b3d; /* 深色背景模拟,可替换成项目背景 */
border: 1px solid #1e2b3d;
border-radius: 8px;
color: #fff;
// box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
padding: 10px;
}
@ -203,8 +283,8 @@ getAlarm();
.alarm_list {
width: 100%;
padding: 5px 0;
height: 14vh;
overflow-y: auto; /* 垂直方向超出时显示滚动条 */
height: 17vh;
// overflow-y: auto; /* 垂直方向超出时显示滚动条 */
}
// 滚动条优化
.alarm_list::-webkit-scrollbar {
@ -220,18 +300,19 @@ getAlarm();
}
/* 告警卡片 */
.alarm-card {
height: 100%;
background: rgba(12, 30, 53, 0.3);
color: #fff;
border: none;
border-radius: 8px;
border: 1px solid #f56c6c;
margin-top: 10px;
padding: 5px;
margin-bottom: 8px; /* 增加卡片间距,避免重叠 */
}
.card-header {
display: flex;
align-items: center;
// justify-content: space-between;
margin-bottom: 12px;
margin-bottom: 8px;
}
.card-title {
font-size: 16px;
@ -244,16 +325,49 @@ getAlarm();
color: #909399;
margin-left: auto; /* 右对齐 */
}
/* 关键修改:卡片内容容器(承载文本和按钮) */
.card-content {
font-size: 13px;
color: #dcdfe6;
margin-bottom: 12px;
// margin-bottom: 12px;
line-height: 1.6;
position: relative;
width: 100%;
line-height: 1.5;
// padding-right: 70px; /* 给右侧按钮预留空间,避免超出卡片 */
min-height: 4.5em; /* 3行文本高度1.5line-height * 3确保按钮位置稳定 */
}
/* 关键修改文本容器限制3行 */
.text-container {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3; /* 限制显示3行 */
overflow: hidden;
word-break: break-all;
padding-bottom: 2px; /* 避免文本底部被按钮遮挡 */
}
/* 关键修改:查看更多按钮(右侧显示+深色适配) */
.read-more {
display: none;
position: absolute;
right: 0;
bottom: -20px;
/* 渐变遮罩改为卡片背景色,避免白色块 */
background: linear-gradient(to right, transparent, rgba(12, 30, 53, 0.3) 60%);
padding-left: 15px; /* 增加遮罩宽度,避免文字与按钮重叠 */
color: #1677ff;
cursor: pointer;
z-index: 1; /* 确保按钮在文本上方 */
white-space: nowrap; /* 按钮文字不换行 */
font-size: 13px; /* 与文本字号一致 */
}
.card-footer {
display: flex;
align-items: center;
justify-content: space-between;
padding-bottom: 5px;
}
.left_title {
width: 100%;
@ -290,7 +404,7 @@ img {
}
.overview {
width: 100%;
height: 28vh;
height: 25vh;
padding: 10px;
border-radius: 10px;
border: 1px solid #1e2b3d;
@ -301,7 +415,7 @@ img {
width: 100%;
font-size: 14px;
line-height: 30px;
overflow-y: auto; /* 垂直方向超出时显示滚动条 */
overflow-y: auto;
}
// 滚动条优化
.overview_content::-webkit-scrollbar {
@ -325,15 +439,14 @@ img {
border-radius: 10px;
.stats-container {
width: 100%; /* 可根据实际场景调整宽度 */
width: 100%;
height: 87%;
padding: 10px;
border-radius: 8px;
box-sizing: border-box;
overflow-y: auto; /* 垂直方向超出时显示滚动条 */
overflow-y: auto;
.container_item {
width: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
@ -359,13 +472,10 @@ img {
flex-direction: column;
justify-content: space-between;
padding-left: 10px;
// align-items: center;
}
}
/* 右侧区域:进度条 + 数据 */
.card-right {
display: flex;
margin-left: 10px;
justify-content: space-between;
align-items: center;
@ -381,7 +491,7 @@ img {
font-weight: bold;
}
.abnormal {
color: #ff9900; /* 异常数据颜色 */
color: #ff9900;
}
.progress-bg {
height: 6px;
@ -397,7 +507,6 @@ img {
width: 100px;
transition: width 0.3s;
}
/* 进度条颜色区分(可扩展更多规则) */
.green {
background-color: #28a745;
}
@ -429,14 +538,59 @@ img {
width: 5px;
height: 5px;
}
.stats-container::-webkit-scrollbar-thumb {
background-color: #0ff;
border-radius: 5px;
}
.stats-container::-webkit-scrollbar-track {
background-color: rgba(0, 255, 255, 0.2);
}
}
.detailBox {
display: flex;
position: absolute;
right: 0;
top: 10vh;
width: 300px;
padding: 20px 15px;
box-sizing: border-box;
/* background: rgba(138, 157, 161, 0.5); */
background: #040c1c;
// border: 2px dashed rgba(29, 214, 255, 0.3);
border-right: none;
border-radius: 4px;
transition: all 0.3s ease;
opacity: 0;
z-index: -1;
& > .boxContent {
flex: 1;
height: 300px;
max-height: 500px;
overflow-y: auto;
&::-webkit-scrollbar-track {
background: rgba(204, 204, 204, 0.1);
border-radius: 10px;
}
&::-webkit-scrollbar-thumb {
background: rgba(29, 214, 255, 0.78);
border-radius: 10px;
}
}
&.show {
right: 25vw;
opacity: 1;
z-index: 1;
}
.close {
position: absolute;
top: 3px;
right: 7px;
cursor: pointer;
}
}
</style>