|
|
@@ -82,6 +82,21 @@
|
|
|
}"
|
|
|
@click="selectElderly(elderly)"
|
|
|
>
|
|
|
+ <!-- <el-tag
|
|
|
+ v-if="hasWarning(elderly.id)"
|
|
|
+ class="warning-flag"
|
|
|
+ type="danger"
|
|
|
+ size="small"
|
|
|
+ effect="dark"
|
|
|
+ >警</el-tag
|
|
|
+ > -->
|
|
|
+ <Icon
|
|
|
+ v-if="hasWarning(elderly.id)"
|
|
|
+ icon="mdi:alert"
|
|
|
+ class="warning-flag"
|
|
|
+ color="yellow"
|
|
|
+ :size="50"
|
|
|
+ />
|
|
|
<div class="elderly-avatar-large" :class="getGenderClass(elderly.gender)">
|
|
|
<span class="avatar-initial">{{ getNameInitial(elderly.name) }}</span>
|
|
|
</div>
|
|
|
@@ -434,7 +449,7 @@
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
-import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'
|
|
|
+import { ref, reactive, computed, onMounted, onUnmounted, nextTick, h } from 'vue'
|
|
|
import { ElMessage, ElMessageBox, ElNotification } from 'element-plus'
|
|
|
import fetchHttp from '@/config/axios/fetchHttp'
|
|
|
import { getAccessToken, getLoginForm } from '@/utils/auth'
|
|
|
@@ -725,6 +740,41 @@ const genderMap = {
|
|
|
1: '男'
|
|
|
}
|
|
|
|
|
|
+// 告警标记:点击老人后清除;刷新后仍保留
|
|
|
+const WARNING_STORAGE_KEY = 'elder_warning_flags'
|
|
|
+const warningFlags = ref<number[]>([])
|
|
|
+
|
|
|
+const loadWarningFlags = () => {
|
|
|
+ try {
|
|
|
+ const raw = localStorage.getItem(WARNING_STORAGE_KEY)
|
|
|
+ warningFlags.value = raw ? JSON.parse(raw) : []
|
|
|
+ } catch (e) {
|
|
|
+ warningFlags.value = []
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const saveWarningFlags = () => {
|
|
|
+ localStorage.setItem(WARNING_STORAGE_KEY, JSON.stringify(warningFlags.value))
|
|
|
+}
|
|
|
+
|
|
|
+const addWarningFlag = (elderId: number) => {
|
|
|
+ if (!elderId) return
|
|
|
+ if (!warningFlags.value.includes(elderId)) {
|
|
|
+ warningFlags.value.push(elderId)
|
|
|
+ saveWarningFlags()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const clearWarningFlag = (elderId: number) => {
|
|
|
+ const idx = warningFlags.value.indexOf(elderId)
|
|
|
+ if (idx !== -1) {
|
|
|
+ warningFlags.value.splice(idx, 1)
|
|
|
+ saveWarningFlags()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const hasWarning = (elderId: number) => warningFlags.value.includes(elderId)
|
|
|
+
|
|
|
// 在响应式数据部分添加
|
|
|
const addElderDialogVisible = ref(false)
|
|
|
const elderFormRef = ref()
|
|
|
@@ -1022,6 +1072,8 @@ const getNameInitial = (name?: string) => {
|
|
|
const selectElderly = (elderly: Elderly) => {
|
|
|
selectedElderly.value.id = elderly.id
|
|
|
selectedElderly.value.name = elderly.name
|
|
|
+ // 点击查看后清除该老人的告警标记
|
|
|
+ clearWarningFlag(elderly.id)
|
|
|
getElderDeviceMessage(selectedElderly.value.id)
|
|
|
}
|
|
|
|
|
|
@@ -1099,6 +1151,7 @@ const getElderList = async () => {
|
|
|
if (elderlyList.value.length) {
|
|
|
selectedElderly.value.id = elderlyList.value[0].id
|
|
|
getElderDeviceMessage(selectedElderly.value.id)
|
|
|
+ warningFlags.value = []
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -1184,6 +1237,8 @@ const getAllDevices = async () => {
|
|
|
|
|
|
// 生命周期
|
|
|
onMounted(() => {
|
|
|
+ // 初始化本地持久化的未读告警标记
|
|
|
+ loadWarningFlags()
|
|
|
getTenantName()
|
|
|
// 初始化时间
|
|
|
updateDateTime()
|
|
|
@@ -1631,6 +1686,8 @@ const handleSOSAlert = (alertData) => {
|
|
|
duration: 10000
|
|
|
})
|
|
|
|
|
|
+ // 标记该老人有未读告警
|
|
|
+ if (alert.elderId) addWarningFlag(alert.elderId)
|
|
|
// 找出elderlyList.value里面id和healthAlertData.elderId一致的老人,将这个老人排序到elderlyList.value第一个,并且边框红色闪烁
|
|
|
if (alert.elderId && elderlyList.value.length > 0) {
|
|
|
const elderIndex = elderlyList.value.findIndex((elder) => elder.id === alert.elderId)
|
|
|
@@ -1669,6 +1726,9 @@ const handleHealthAlert = (healthAlert) => {
|
|
|
console.log('healthAlert', healthAlert)
|
|
|
const healthAlertData = healthAlert.data
|
|
|
|
|
|
+ // 标记该老人有未读告警
|
|
|
+ if (healthAlertData.elderId) addWarningFlag(healthAlertData.elderId)
|
|
|
+
|
|
|
ElNotification({
|
|
|
title: `🚨🚨 ${healthAlertData.eventType} 🚨🚨`,
|
|
|
customClass: 'my-warning-notification',
|
|
|
@@ -2080,6 +2140,7 @@ $transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
|
}
|
|
|
|
|
|
.elderly-card-large {
|
|
|
+ position: relative;
|
|
|
display: flex;
|
|
|
padding: 20px;
|
|
|
cursor: pointer;
|
|
|
@@ -2221,6 +2282,16 @@ $transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
|
white-space: nowrap;
|
|
|
}
|
|
|
|
|
|
+/* 未读告警徽标 */
|
|
|
+.warning-flag {
|
|
|
+ position: absolute;
|
|
|
+ top: 10px;
|
|
|
+ left: 160px;
|
|
|
+ z-index: 2;
|
|
|
+ border-radius: 10px;
|
|
|
+ padding: 2px 6px;
|
|
|
+}
|
|
|
+
|
|
|
/* 右侧详情区域 */
|
|
|
.detail-section {
|
|
|
display: flex;
|