Compare commits

...

3 Commits

Author SHA1 Message Date
yangsy
f0ab42613b refactor(enums): Tab order of DeviceTree 2025-11-28 15:03:22 +08:00
yangsy
4272cd90de fix: wait for 5s after syncCamera then refetch polling 2025-11-28 14:41:48 +08:00
yangsy
fb7657f99c feat: fold/expand menu 2025-11-28 00:13:05 +08:00
5 changed files with 44 additions and 11 deletions

View File

@@ -7,7 +7,7 @@ import { getAppEnvConfig } from '@/utils';
import { useQueryClient } from '@tanstack/vue-query';
import { useEventListener } from '@vueuse/core';
import axios from 'axios';
import { NButton, NDivider, NDrawer, NDrawerContent, NFlex, NFormItem, NInput, NInputNumber, NModal, NRadio, NRadioGroup, NText } from 'naive-ui';
import { NButton, NDivider, NDrawer, NDrawerContent, NFlex, NFormItem, NInput, NInputNumber, NModal, NRadio, NRadioGroup, NSwitch, NText } from 'naive-ui';
import { storeToRefs } from 'pinia';
import { onMounted, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
@@ -17,7 +17,7 @@ const route = useRoute();
const show = defineModel<boolean>('show');
const settingStore = useSettingStore();
const { stationGridColumns, debugModeEnabled } = storeToRefs(settingStore);
const { stationGridColumns, debugModeEnabled, menuCollpased } = storeToRefs(settingStore);
const pollingStore = usePollingStore();
const { stationVerifyMode } = storeToRefs(pollingStore);
@@ -68,8 +68,11 @@ useEventListener('keydown', (event) => {
<NFormItem label="深色模式" label-placement="left">
<ThemeSwitch />
</NFormItem>
<NDivider>布局</NDivider>
<NFormItem label="折叠菜单" label-placement="left">
<NSwitch v-model:value="menuCollpased" />
</NFormItem>
<template v-if="route.path === '/station'">
<NDivider>布局</NDivider>
<NFormItem label="车站列数" label-placement="left">
<NInputNumber v-model:value="stationGridColumns" :min="1" :max="10" />
</NFormItem>

View File

@@ -1,5 +1,4 @@
export const DeviceType = {
AlarmHost: 'ndmAlarmHost',
Camera: 'ndmCamera',
Nvr: 'ndmNvr',
Switch: 'ndmSwitch',
@@ -8,13 +7,13 @@ export const DeviceType = {
MediaServer: 'ndmMediaServer',
VideoServer: 'ndmVideoServer',
Keyboard: 'ndmKeyboard',
AlarmHost: 'ndmAlarmHost',
} as const;
export type DeviceTypeKey = keyof typeof DeviceType;
export type DeviceTypeVal = (typeof DeviceType)[DeviceTypeKey];
export const DeviceTypeCode: Record<DeviceTypeVal, string[]> = {
[DeviceType.AlarmHost]: ['117'],
[DeviceType.Camera]: ['131', '132'],
[DeviceType.Nvr]: ['111', '118'],
[DeviceType.Switch]: ['220'],
@@ -23,10 +22,10 @@ export const DeviceTypeCode: Record<DeviceTypeVal, string[]> = {
[DeviceType.MediaServer]: ['403'],
[DeviceType.VideoServer]: ['401'],
[DeviceType.Keyboard]: ['141'],
[DeviceType.AlarmHost]: ['117'],
};
export const DeviceTypeName: Record<DeviceTypeVal, string> = {
[DeviceType.AlarmHost]: '报警主机',
[DeviceType.Camera]: '摄像机',
[DeviceType.Nvr]: '网络录像机',
[DeviceType.Switch]: '交换机',
@@ -35,6 +34,7 @@ export const DeviceTypeName: Record<DeviceTypeVal, string> = {
[DeviceType.MediaServer]: '媒体服务器',
[DeviceType.VideoServer]: '视频服务器',
[DeviceType.Keyboard]: '网络键盘',
[DeviceType.AlarmHost]: '报警主机',
};
/**

View File

@@ -9,9 +9,20 @@ import { SettingsDrawer } from '@/components';
import { useStompClient } from '@/composables';
import { useLineStationsQuery } from '@/composables';
import { LINE_STATIONS_QUERY_KEY, LINE_DEVICES_QUERY_KEY, LINE_ALARMS_QUERY_KEY } from '@/constants';
import { useAlarmStore, useUserStore } from '@/stores';
import { useAlarmStore, useSettingStore, useUserStore } from '@/stores';
import { useIsFetching } from '@tanstack/vue-query';
import { AlertFilled, BugFilled, CaretDownFilled, EnvironmentFilled, /* AreaChartOutlined, */ FileTextFilled, HddFilled, LogoutOutlined, SettingOutlined } from '@vicons/antd';
import {
AlertFilled,
BugFilled,
CaretDownFilled,
DoubleLeftOutlined,
DoubleRightOutlined,
EnvironmentFilled,
/* AreaChartOutlined, */ FileTextFilled,
HddFilled,
LogoutOutlined,
SettingOutlined,
} from '@vicons/antd';
import type { AxiosError } from 'axios';
import { NBadge, NButton, NDropdown, NFlex, NIcon, NLayout, NLayoutContent, NLayoutFooter, NLayoutHeader, NLayoutSider, NMenu, NScrollbar, type DropdownOption, type MenuOption } from 'naive-ui';
import { storeToRefs } from 'pinia';
@@ -26,6 +37,13 @@ const { userInfo } = storeToRefs(userStore);
const alarmStore = useAlarmStore();
const { unreadAlarmCount } = storeToRefs(alarmStore);
const settingStore = useSettingStore();
const { menuCollpased } = storeToRefs(settingStore);
const onToggleMenuCollapsed = () => {
menuCollpased.value = !menuCollpased.value;
};
const { error: stationListQueryError } = useLineStationsQuery();
watch(stationListQueryError, (newStationListQueryError) => {
@@ -134,8 +152,15 @@ const openSettingsDrawer = () => {
<template>
<NScrollbar x-scrollable style="width: 100vw; height: 100vh">
<NLayout has-sider :content-style="{ 'min-width': '1400px' }">
<NLayoutSider bordered collapsed collapse-mode="width" :collapsed-width="64">
<NMenu collapsed :collapsed-width="64" :collapsed-icon-size="20" :value="route.path" :options="menuOptions" />
<NLayoutSider bordered :collapsed="menuCollpased" collapse-mode="width" :collapsed-width="64" @update:collapsed="onToggleMenuCollapsed">
<NFlex vertical justify="space-between" :size="0" style="height: 100%">
<NMenu :collapsed="menuCollpased" :collapsed-width="64" :collapsed-icon-size="20" :value="route.path" :options="menuOptions" />
<NButton block quaternary :focusable="false" @click="onToggleMenuCollapsed">
<template #icon>
<NIcon :component="menuCollpased ? DoubleRightOutlined : DoubleLeftOutlined" />
</template>
</NButton>
</NFlex>
</NLayoutSider>
<NLayout :native-scrollbar="false">
<NLayoutHeader bordered class="app-layout-header">
@@ -145,7 +170,6 @@ const openSettingsDrawer = () => {
<NButton text size="tiny" :loading="fetchingCount > 0" />
</NFlex>
<NFlex align="center" :size="0" style="height: 100%">
<!-- <ThemeSwitch /> -->
<NDropdown trigger="hover" show-arrow :options="dropdownOptions" @select="selectDropdownOption">
<NButton :focusable="false" quaternary icon-placement="right" style="height: 100%">
<template #default>

View File

@@ -3,6 +3,7 @@ import { syncCameraApi, syncNvrChannelsApi, type Station } from '@/apis';
import { DeviceAlarmDetailModal, DeviceExportModal, DeviceParamsConfigModal, OfflineDeviceDetailModal, RecordCheckExportModal, StationCard } from '@/components';
import { useLineAlarmsQuery, useLineDevicesQuery } from '@/composables';
import { useAlarmStore, useDeviceStore, usePollingStore, useSettingStore, useStationStore } from '@/stores';
import { sleep } from '@/utils';
import { useMutation } from '@tanstack/vue-query';
import { NGrid, NGi, NScrollbar, NFlex, NButtonGroup, NButton, NCheckbox } from 'naive-ui';
import { storeToRefs } from 'pinia';
@@ -71,6 +72,7 @@ const { mutate: syncCamera, isPending: cameraSyncing } = useMutation({
.map(([code]) => code);
for (const stationCode of stationCodes) {
await syncCameraApi({ stationCode });
await sleep(5000);
}
},
onSuccess: () => {

View File

@@ -10,6 +10,8 @@ export const useSettingStore = defineStore(
return darkThemeEnabled.value ? darkTheme : lightTheme;
});
const menuCollpased = ref(false);
const stationGridColumns = ref(6);
const debugModeEnabled = ref(false);
@@ -24,6 +26,8 @@ export const useSettingStore = defineStore(
darkThemeEnabled,
themeMode,
menuCollpased,
stationGridColumns,
debugModeEnabled,