|
@@ -44,7 +44,7 @@
|
|
<ZoomInOutlined @click="zoomIn" />
|
|
<ZoomInOutlined @click="zoomIn" />
|
|
</a-space>
|
|
</a-space>
|
|
</div>
|
|
</div>
|
|
- <div class="block custom-scroll">
|
|
|
|
|
|
+ <div class="block custom-scroll" style="padding: 10px">
|
|
<div class="data-row">
|
|
<div class="data-row">
|
|
<DeviceAgeCard :ageList="todayData.ageList"></DeviceAgeCard>
|
|
<DeviceAgeCard :ageList="todayData.ageList"></DeviceAgeCard>
|
|
<ElderActivityCard :activity-rate="todayData.activeRate"></ElderActivityCard>
|
|
<ElderActivityCard :activity-rate="todayData.activeRate"></ElderActivityCard>
|
|
@@ -53,47 +53,53 @@
|
|
<div class="data-line">
|
|
<div class="data-line">
|
|
<HistoryChartCard
|
|
<HistoryChartCard
|
|
title="历史告警统计"
|
|
title="历史告警统计"
|
|
- :dayStatInfo="[
|
|
|
|
- { date: '2024-07-01', fallingCount: 5 },
|
|
|
|
- { date: '2024-07-02', fallingCount: 8 },
|
|
|
|
- { date: '2024-07-03', fallingCount: 6 },
|
|
|
|
- { date: '2024-07-04', fallingCount: 10 },
|
|
|
|
- { date: '2024-07-05', fallingCount: 7 },
|
|
|
|
- ]"
|
|
|
|
- :monthStatInfo="[
|
|
|
|
- { month: '2024-06', fallingCount: 32 },
|
|
|
|
- { month: '2024-07', fallingCount: 41 },
|
|
|
|
- { month: '2024-08', fallingCount: 45 },
|
|
|
|
- { month: '2024-09', fallingCount: 30 },
|
|
|
|
- { month: '2024-10', fallingCount: 60 },
|
|
|
|
- { month: '2024-11', fallingCount: 35 },
|
|
|
|
- { month: '2024-12', fallingCount: 50 },
|
|
|
|
- ]"
|
|
|
|
|
|
+ :dayStatInfo="historyData.alarmHistoryData.dayStatInfo"
|
|
|
|
+ :monthStatInfo="historyData.alarmHistoryData.monthStatInfo"
|
|
|
|
+ :mode="alarmMode"
|
|
|
|
+ :loading="alarmLoading"
|
|
color="#f39c12"
|
|
color="#f39c12"
|
|
seriesName="告警次数"
|
|
seriesName="告警次数"
|
|
- />
|
|
|
|
|
|
+ >
|
|
|
|
+ <template #extra>
|
|
|
|
+ <div class="toggle-group">
|
|
|
|
+ <button
|
|
|
|
+ :class="['alarm-button', { active: alarmMode === 'day' }]"
|
|
|
|
+ @click="changeAlarmMode('day')"
|
|
|
|
+ >最近7天</button
|
|
|
|
+ >
|
|
|
|
+ <button
|
|
|
|
+ :class="['alarm-button', { active: alarmMode === 'month' }]"
|
|
|
|
+ @click="changeAlarmMode('month')"
|
|
|
|
+ >最近180天</button
|
|
|
|
+ >
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
|
|
+ </HistoryChartCard>
|
|
|
|
|
|
<HistoryChartCard
|
|
<HistoryChartCard
|
|
title="历史跌倒统计"
|
|
title="历史跌倒统计"
|
|
- :dayStatInfo="[
|
|
|
|
- { date: '2024-07-01', fallingCount: 5 },
|
|
|
|
- { date: '2024-07-02', fallingCount: 8 },
|
|
|
|
- { date: '2024-07-03', fallingCount: 6 },
|
|
|
|
- { date: '2024-07-04', fallingCount: 10 },
|
|
|
|
- { date: '2024-07-05', fallingCount: 7 },
|
|
|
|
- ]"
|
|
|
|
- :monthStatInfo="[
|
|
|
|
- { month: '2024-06', fallingCount: 32 },
|
|
|
|
- { month: '2024-07', fallingCount: 41 },
|
|
|
|
- { month: '2024-08', fallingCount: 60 },
|
|
|
|
- { month: '2024-09', fallingCount: 30 },
|
|
|
|
- { month: '2024-10', fallingCount: 35 },
|
|
|
|
- { month: '2024-11', fallingCount: 45 },
|
|
|
|
- { month: '2024-12', fallingCount: 70 },
|
|
|
|
- ]"
|
|
|
|
|
|
+ :dayStatInfo="historyData.fallHistoryData.dayStatInfo"
|
|
|
|
+ :monthStatInfo="historyData.fallHistoryData.monthStatInfo"
|
|
|
|
+ :mode="fallMode"
|
|
|
|
+ :loading="fallLoading"
|
|
color="#e74c3c"
|
|
color="#e74c3c"
|
|
seriesName="跌倒次数"
|
|
seriesName="跌倒次数"
|
|
- />
|
|
|
|
|
|
+ >
|
|
|
|
+ <template #extra>
|
|
|
|
+ <div class="toggle-group">
|
|
|
|
+ <button
|
|
|
|
+ :class="['fall-button', { active: fallMode === 'day' }]"
|
|
|
|
+ @click="changeFallMode('day')"
|
|
|
|
+ >最近7天</button
|
|
|
|
+ >
|
|
|
|
+ <button
|
|
|
|
+ :class="['fall-button', { active: fallMode === 'month' }]"
|
|
|
|
+ @click="changeFallMode('month')"
|
|
|
|
+ >最近180天</button
|
|
|
|
+ >
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
|
|
+ </HistoryChartCard>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@@ -161,10 +167,13 @@ const todayData = ref<TodayData>({
|
|
|
|
|
|
useResponsiveLayout()
|
|
useResponsiveLayout()
|
|
|
|
|
|
-const { todayScreenData, fallHistoryData, alarmHistoryData } = useDashboardPolling({
|
|
|
|
- tenantId: userStore.userInfo.tenantId || '',
|
|
|
|
- queryType: 'day',
|
|
|
|
-})
|
|
|
|
|
|
+const {
|
|
|
|
+ todayScreenData,
|
|
|
|
+ fallHistoryData,
|
|
|
|
+ alarmHistoryData,
|
|
|
|
+ updateFallQueryType,
|
|
|
|
+ updateAlarmQueryType,
|
|
|
|
+} = useDashboardPolling({ tenantId: userStore.userInfo.tenantId || '' })
|
|
|
|
|
|
const { fetchDict: fetchDictGuardianship, dictNameMap: guardTypeNameMap } =
|
|
const { fetchDict: fetchDictGuardianship, dictNameMap: guardTypeNameMap } =
|
|
useDict('guardianship_type')
|
|
useDict('guardianship_type')
|
|
@@ -202,22 +211,101 @@ watch(
|
|
{ immediate: true }
|
|
{ immediate: true }
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+type RawDayItem = { date: string; fallingCount?: number; alarmCount?: number }
|
|
|
|
+type RawMonthItem = { month: string; fallingCount?: number; alarmCount?: number }
|
|
|
|
+
|
|
|
|
+type StatInfo = { lable: string; count: number }
|
|
|
|
+type HistoryData = { monthStatInfo: StatInfo[]; dayStatInfo: StatInfo[] }
|
|
|
|
+
|
|
|
|
+const historyData = ref<{
|
|
|
|
+ fallHistoryData: HistoryData
|
|
|
|
+ alarmHistoryData: HistoryData
|
|
|
|
+}>({
|
|
|
|
+ fallHistoryData: { monthStatInfo: [], dayStatInfo: [] },
|
|
|
|
+ alarmHistoryData: { monthStatInfo: [], dayStatInfo: [] },
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+// 通用转换函数
|
|
|
|
+const transformStatInfo = (
|
|
|
|
+ source: RawDayItem[] | RawMonthItem[],
|
|
|
|
+ labelKey: 'date' | 'month',
|
|
|
|
+ countKey: 'fallingCount' | 'alarmCount'
|
|
|
|
+): StatInfo[] => {
|
|
|
|
+ if (labelKey === 'date') {
|
|
|
|
+ return (source as RawDayItem[]).map((item) => ({
|
|
|
|
+ lable: item.date,
|
|
|
|
+ count: item[countKey] ?? 0,
|
|
|
|
+ }))
|
|
|
|
+ } else {
|
|
|
|
+ return (source as RawMonthItem[]).map((item) => ({
|
|
|
|
+ lable: item.month,
|
|
|
|
+ count: item[countKey] ?? 0,
|
|
|
|
+ }))
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 监听跌倒数据
|
|
watch(
|
|
watch(
|
|
() => fallHistoryData.value,
|
|
() => fallHistoryData.value,
|
|
(val) => {
|
|
(val) => {
|
|
console.log('🚀🚀🚀 fallHistoryData 更新了', val)
|
|
console.log('🚀🚀🚀 fallHistoryData 更新了', val)
|
|
|
|
+ historyData.value.fallHistoryData.dayStatInfo = transformStatInfo(
|
|
|
|
+ val?.dayStatInfo ?? [],
|
|
|
|
+ 'date',
|
|
|
|
+ 'fallingCount'
|
|
|
|
+ )
|
|
|
|
+ historyData.value.fallHistoryData.monthStatInfo = transformStatInfo(
|
|
|
|
+ val?.monthStatInfo ?? [],
|
|
|
|
+ 'month',
|
|
|
|
+ 'fallingCount'
|
|
|
|
+ )
|
|
},
|
|
},
|
|
{ immediate: true }
|
|
{ immediate: true }
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+// 监听告警数据
|
|
watch(
|
|
watch(
|
|
() => alarmHistoryData.value,
|
|
() => alarmHistoryData.value,
|
|
(val) => {
|
|
(val) => {
|
|
console.log('🚀🚀🚀 alarmHistoryData 更新了', val)
|
|
console.log('🚀🚀🚀 alarmHistoryData 更新了', val)
|
|
|
|
+ historyData.value.alarmHistoryData.dayStatInfo = transformStatInfo(
|
|
|
|
+ val?.dayStatInfo ?? [],
|
|
|
|
+ 'date',
|
|
|
|
+ 'alarmCount'
|
|
|
|
+ )
|
|
|
|
+ historyData.value.alarmHistoryData.monthStatInfo = transformStatInfo(
|
|
|
|
+ val?.monthStatInfo ?? [],
|
|
|
|
+ 'month',
|
|
|
|
+ 'alarmCount'
|
|
|
|
+ )
|
|
},
|
|
},
|
|
{ immediate: true }
|
|
{ immediate: true }
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+const alarmMode = ref<'day' | 'month'>('day')
|
|
|
|
+const fallMode = ref<'day' | 'month'>('day')
|
|
|
|
+
|
|
|
|
+const alarmLoading = ref(false)
|
|
|
|
+const fallLoading = ref(false)
|
|
|
|
+
|
|
|
|
+const changeAlarmMode = async (mode: 'day' | 'month') => {
|
|
|
|
+ if (alarmMode.value !== mode) {
|
|
|
|
+ alarmMode.value = mode
|
|
|
|
+ alarmLoading.value = true
|
|
|
|
+ await updateAlarmQueryType(mode)
|
|
|
|
+ alarmLoading.value = false
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const changeFallMode = async (mode: 'day' | 'month') => {
|
|
|
|
+ if (fallMode.value !== mode) {
|
|
|
|
+ fallMode.value = mode
|
|
|
|
+ fallLoading.value = true
|
|
|
|
+ await updateFallQueryType(mode)
|
|
|
|
+ fallLoading.value = false
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
const toDeviceList = () => {
|
|
const toDeviceList = () => {
|
|
window.open('/device/list', '_blank')
|
|
window.open('/device/list', '_blank')
|
|
}
|
|
}
|
|
@@ -363,7 +451,7 @@ const handleResize = () => {
|
|
display: flex;
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex-direction: column;
|
|
position: relative;
|
|
position: relative;
|
|
- overflow: auto;
|
|
|
|
|
|
+ overflow-y: auto;
|
|
}
|
|
}
|
|
|
|
|
|
.block-center {
|
|
.block-center {
|
|
@@ -558,6 +646,45 @@ const handleResize = () => {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+.toggle-group {
|
|
|
|
+ display: flex;
|
|
|
|
+ gap: 8px;
|
|
|
|
+ justify-content: flex-end;
|
|
|
|
+
|
|
|
|
+ button {
|
|
|
|
+ background: none;
|
|
|
|
+ border: 1px solid;
|
|
|
|
+ padding: 4px 10px;
|
|
|
|
+ border-radius: 4px;
|
|
|
|
+ font-size: 12px;
|
|
|
|
+ cursor: pointer;
|
|
|
|
+
|
|
|
|
+ &.active {
|
|
|
|
+ color: #fff;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .alarm-button {
|
|
|
|
+ border-color: #f39c12;
|
|
|
|
+ color: #f39c12;
|
|
|
|
+
|
|
|
|
+ &.active {
|
|
|
|
+ background-color: #f39c12;
|
|
|
|
+ color: #fff;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .fall-button {
|
|
|
|
+ border-color: #e74c3c;
|
|
|
|
+ color: #e74c3c;
|
|
|
|
+
|
|
|
|
+ &.active {
|
|
|
|
+ background-color: #e74c3c;
|
|
|
|
+ color: #fff;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
</style>
|
|
</style>
|
|
|
|
|
|
<style lang="less">
|
|
<style lang="less">
|