refactor: 重构项目结构

- 优化 `车站-设备-告警`  轮询机制
- 改进设备卡片的布局
- 支持修改设备
- 告警轮询中获取完整告警数据
- 车站告警详情支持导出完整的 `今日告警列表`
- 支持将状态持久化到 `IndexedDB`
- 新增轮询控制 (调试模式)
- 新增离线开发模式 (调试模式)
- 新增 `IndexedDB` 数据控制 (调试模式)
This commit is contained in:
yangsy
2025-12-11 13:42:22 +08:00
commit 37781216b2
278 changed files with 17988 additions and 0 deletions

View File

@@ -0,0 +1,88 @@
<script setup lang="ts">
import { watchDebounced } from '@vueuse/core';
import { NFlex, NIcon, NList, NListItem, NModal, NScrollbar, NStatistic, NText, NThing } from 'naive-ui';
import { computed, ref, toRefs } from 'vue';
import { useStationStore } from '@/stores';
import { storeToRefs } from 'pinia';
import type { Station, SyncCameraResult } from '@/apis';
import { DeleteFilled, EditFilled, PlusCircleFilled } from '@vicons/antd';
const props = defineProps<{
syncCameraResult: Record<Station['code'], SyncCameraResult>;
}>();
const emit = defineEmits<{
afterLeave: [];
}>();
const stationStore = useStationStore();
const { stations } = storeToRefs(stationStore);
const { syncCameraResult } = toRefs(props);
const show = ref(false);
watchDebounced(
[syncCameraResult],
([result]) => {
show.value = Object.keys(result).length > 0;
},
{
debounce: 500,
deep: true,
},
);
const onAfterLeave = () => {
emit('afterLeave');
};
const syncList = computed(() => {
return Object.values(syncCameraResult.value).map((sync) => {
const { stationCode, startTime, endTime, insertList, updateList, deleteList } = sync;
const stationName = stations.value.find((station) => station.code === stationCode)?.name;
return { stationName, startTime, endTime, insertList, updateList, deleteList };
});
});
</script>
<template>
<NModal v-model:show="show" preset="card" title="摄像机同步结果" style="width: 600px" @after-leave="onAfterLeave">
<NScrollbar style="max-height: 400px">
<NList hoverable clickable>
<NListItem v-for="{ stationName, endTime, insertList, updateList, deleteList } in syncList" :key="stationName">
<NThing title-independent>
<template #header>
<NText strong>{{ stationName }}</NText>
</template>
<template #header-extra>
<NText depth="3"> {{ endTime }} 完成 </NText>
</template>
<NFlex justify="space-around" :size="24" style="margin-top: 8px">
<NStatistic label="新增">
<template #prefix>
<NIcon :component="PlusCircleFilled" />
</template>
{{ insertList.length }}
</NStatistic>
<NStatistic label="更新">
<template #prefix>
<NIcon :component="EditFilled" />
</template>
{{ updateList.length }}
</NStatistic>
<NStatistic label="删除">
<template #prefix>
<NIcon :component="DeleteFilled" />
</template>
{{ deleteList.length }}
</NStatistic>
</NFlex>
</NThing>
</NListItem>
</NList>
</NScrollbar>
</NModal>
</template>
<style scoped lang="scss"></style>