feat(device-header-card): probe button

This commit is contained in:
yangsy
2025-11-19 16:31:54 +08:00
parent fa9b435a0f
commit 4ab33d2021
18 changed files with 296 additions and 32 deletions

View File

@@ -16,3 +16,5 @@ export * from './video/ndm-decoder';
export * from './video/ndm-keyboard';
export * from './video/ndm-media-server';
export * from './video/ndm-video-server';
export * from './ndm-probe';

View File

@@ -0,0 +1,121 @@
import { ndmClient } from '@/apis/client';
import type { NdmDeviceResultVO } from '@/apis/models';
import { getNdmDecoderDetail, getNdmKeyboardDetail, getNdmMediaServerDetail, getNdmNvrDetail, getNdmSecurityBoxDetail, getNdmSwitchDetail, getNdmVideoServerDetail } from '@/apis/requests';
import { DeviceType, tryGetDeviceTypeVal } from '@/enums/device-type';
export const probeNdmDecoderByIds = async (stationCode: string, ids: string[]) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.post<void>(`${prefix}/api/ndm/ndmDecoder/probeByIds`, ids);
const [err] = resp;
if (err) {
throw err;
}
};
export const probeNdmNvrByIds = async (stationCode: string, ids: string[]) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.post<void>(`${prefix}/api/ndm/ndmNvr/probeByIds`, ids);
const [err] = resp;
if (err) {
throw err;
}
};
export const probeNdmSecurityBoxByIds = async (stationCode: string, ids: string[]) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.post<void>(`${prefix}/api/ndm/ndmSecurityBox/probeByIds`, ids);
const [err] = resp;
if (err) {
throw err;
}
};
export const probeNdmMediaServerByIds = async (stationCode: string, ids: string[]) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.post<void>(`${prefix}/api/ndm/ndmMediaServer/probeByIds`, ids);
const [err] = resp;
if (err) {
throw err;
}
};
export const probeNdmSwitchByIds = async (stationCode: string, ids: string[]) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.post<void>(`${prefix}/api/ndm/ndmSwitch/probeByIds`, ids);
const [err] = resp;
if (err) {
throw err;
}
};
export const probeNdmVideoServerByIds = async (stationCode: string, ids: string[]) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.post<void>(`${prefix}/api/ndm/ndmVideoServer/probeByIds`, ids);
const [err] = resp;
if (err) {
throw err;
}
};
export const probeDeviceApi = async (stationCode: string, device: NdmDeviceResultVO) => {
const deviceType = tryGetDeviceTypeVal(device.deviceType);
const deviceDbId = device.id;
if (!deviceType || !deviceDbId) {
throw new Error('未知的设备');
}
if (deviceType === DeviceType.Decoder) {
await probeNdmDecoderByIds(stationCode, [deviceDbId]);
return;
}
if (deviceType === DeviceType.Nvr) {
await probeNdmNvrByIds(stationCode, [deviceDbId]);
return;
}
if (deviceType === DeviceType.SecurityBox) {
await probeNdmSecurityBoxByIds(stationCode, [deviceDbId]);
return;
}
if (deviceType === DeviceType.MediaServer) {
await probeNdmMediaServerByIds(stationCode, [deviceDbId]);
return;
}
if (deviceType === DeviceType.Switch) {
await probeNdmSwitchByIds(stationCode, [deviceDbId]);
return;
}
if (deviceType === DeviceType.VideoServer) {
await probeNdmVideoServerByIds(stationCode, [deviceDbId]);
return;
}
};
export const getDeviceDetailApi = async (stationCode: string, id?: string, deviceType?: string): Promise<NdmDeviceResultVO | undefined> => {
if (!id || !deviceType) {
throw new Error('未知的设备');
}
if (deviceType === DeviceType.Camera) {
return await getNdmVideoServerDetail(stationCode, id);
}
if (deviceType === DeviceType.Decoder) {
return await getNdmDecoderDetail(stationCode, id);
}
if (deviceType === DeviceType.Keyboard) {
return await getNdmKeyboardDetail(stationCode, id);
}
if (deviceType === DeviceType.MediaServer) {
return await getNdmMediaServerDetail(stationCode, id);
}
if (deviceType === DeviceType.Nvr) {
return await getNdmNvrDetail(stationCode, id);
}
if (deviceType === DeviceType.SecurityBox) {
return await getNdmSecurityBoxDetail(stationCode, id);
}
if (deviceType === DeviceType.Switch) {
return await getNdmSwitchDetail(stationCode, id);
}
if (deviceType === DeviceType.VideoServer) {
return await getNdmVideoServerDetail(stationCode, id);
}
return undefined;
};

View File

@@ -4,6 +4,16 @@ import type { PageParams, NdmSecurityBoxPageQuery, PageResult, NdmSecurityBoxRes
export const postNdmSecurityBoxPage = async (stationCode: string, pageQuery: PageParams<NdmSecurityBoxPageQuery>, signal?: AbortSignal) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.post<PageResult<NdmSecurityBoxResultVO>>(`${prefix}/api/ndm/ndmSecurityBox/page`, pageQuery, { signal });
const [err, ndmSecurityBox] = resp;
if (err || !ndmSecurityBox) {
throw err;
}
return ndmSecurityBox;
};
export const getNdmSecurityBoxDetail = async (stationCode: string, id: string) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.get<NdmSecurityBoxResultVO>(`${prefix}/api/ndm/ndmSecurityBox/detail`, { params: { id } });
const [err, ndmSecurityBoxData] = resp;
if (err || !ndmSecurityBoxData) {
throw err;
@@ -18,7 +28,7 @@ export const putNdmSecurityBox = async (stationCode: string, updateVO: NdmSecuri
if (err || !ndmSecurityBox) {
throw err;
}
return ndmSecurityBox;
return await getNdmSecurityBoxDetail(stationCode, ndmSecurityBox.id ?? '');
};
export const turnStatus = async (stationCode: string, ipAddress: string, circuitIndex: number, status: number) => {

View File

@@ -4,6 +4,16 @@ import type { PageParams, NdmSwitchPageQuery, PageResult, NdmSwitchResultVO, Ndm
export const postNdmSwitchPage = async (stationCode: string, pageQuery: PageParams<NdmSwitchPageQuery>, signal?: AbortSignal) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.post<PageResult<NdmSwitchResultVO>>(`${prefix}/api/ndm/ndmSwitch/page`, pageQuery, { signal });
const [err, ndmSwitch] = resp;
if (err || !ndmSwitch) {
throw err;
}
return ndmSwitch;
};
export const getNdmSwitchDetail = async (stationCode: string, id: string) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.get<NdmSwitchResultVO>(`${prefix}/api/ndm/ndmSwitch/detail`, { params: { id } });
const [err, ndmSwitchData] = resp;
if (err || !ndmSwitchData) {
throw err;
@@ -18,5 +28,5 @@ export const putNdmSwitch = async (stationCode: string, updateVO: NdmSwitchUpdat
if (err || !ndmSwitch) {
throw err;
}
return ndmSwitch;
return await getNdmSwitchDetail(stationCode, ndmSwitch.id ?? '');
};

View File

@@ -5,11 +5,21 @@ import dayjs from 'dayjs';
export const postNdmNvrPage = async (stationCode: string, pageQuery: PageParams<NdmNvrPageQuery>, signal?: AbortSignal) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.post<PageResult<NdmNvrResultVO>>(`${prefix}/api/ndm/ndmNvr/page`, pageQuery, { signal });
const [err, ndmNvrData] = resp;
if (err || !ndmNvrData) {
const [err, ndmNvr] = resp;
if (err || !ndmNvr) {
throw err;
}
return ndmNvrData;
return ndmNvr;
};
export const getNdmNvrDetail = async (stationCode: string, id: string) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.get<NdmNvrResultVO>(`${prefix}/api/ndm/ndmNvr/detail`, { params: { id } });
const [err, ndmNvr] = resp;
if (err || !ndmNvr) {
throw err;
}
return ndmNvr;
};
export const putNdmNvr = async (stationCode: string, updateVO: NdmNvrUpdateVO) => {
@@ -19,7 +29,7 @@ export const putNdmNvr = async (stationCode: string, updateVO: NdmNvrUpdateVO) =
if (err || !ndmNvr) {
throw err;
}
return ndmNvr;
return await getNdmNvrDetail(stationCode, ndmNvr.id ?? '');
};
export const getChannelList = async (stationCode: string, ndmNvr: NdmNvrResultVO) => {

View File

@@ -4,11 +4,21 @@ import type { PageParams, NdmCameraPageQuery, PageResult, NdmCameraResultVO, Ndm
export const postNdmCameraPage = async (stationCode: string, pageQuery: PageParams<NdmCameraPageQuery>, signal?: AbortSignal) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.post<PageResult<NdmCameraResultVO>>(`${prefix}/api/ndm/ndmCamera/page`, pageQuery, { signal });
const [err, ndmCameraData] = resp;
if (err || !ndmCameraData) {
const [err, ndmCamera] = resp;
if (err || !ndmCamera) {
throw err;
}
return ndmCameraData;
return ndmCamera;
};
export const getNdmCameraDetail = async (stationCode: string, id: string) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.get<NdmCameraResultVO>(`${prefix}/api/ndm/ndmCamera/detail`, { params: { id } });
const [err, ndmCamera] = resp;
if (err || !ndmCamera) {
throw err;
}
return ndmCamera;
};
export const putNdmCamera = async (stationCode: string, updateVO: NdmCameraUpdateVO) => {
@@ -18,5 +28,5 @@ export const putNdmCamera = async (stationCode: string, updateVO: NdmCameraUpdat
if (err || !ndmCamera) {
throw err;
}
return ndmCamera;
return await getNdmCameraDetail(stationCode, ndmCamera.id ?? '');
};

View File

@@ -4,11 +4,21 @@ import type { PageParams, NdmDecoderPageQuery, PageResult, NdmDecoderResultVO, N
export const postNdmDecoderPage = async (stationCode: string, pageQuery: PageParams<NdmDecoderPageQuery>, signal?: AbortSignal) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.post<PageResult<NdmDecoderResultVO>>(`${prefix}/api/ndm/ndmDecoder/page`, pageQuery, { signal });
const [err, ndmDecoderData] = resp;
if (err || !ndmDecoderData) {
const [err, ndmDecoder] = resp;
if (err || !ndmDecoder) {
throw err;
}
return ndmDecoderData;
return ndmDecoder;
};
export const getNdmDecoderDetail = async (stationCode: string, id: string) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.get<NdmDecoderResultVO>(`${prefix}/api/ndm/ndmDecoder/detail`, { params: { id } });
const [err, ndmDecoder] = resp;
if (err || !ndmDecoder) {
throw err;
}
return ndmDecoder;
};
export const putNdmDecoder = async (stationCode: string, updateVO: NdmDecoderUpdateVO) => {
@@ -18,5 +28,5 @@ export const putNdmDecoder = async (stationCode: string, updateVO: NdmDecoderUpd
if (err || !ndmDecoder) {
throw err;
}
return ndmDecoder;
return await getNdmDecoderDetail(stationCode, ndmDecoder.id ?? '');
};

View File

@@ -11,6 +11,16 @@ export const postNdmKeyboardPage = async (stationCode: string, pageQuery: PagePa
return ndmKeyboardData;
};
export const getNdmKeyboardDetail = async (stationCode: string, id: string) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.get<NdmKeyboardResultVO>(`${prefix}/api/ndm/ndmKeyboard/detail`, { params: { id } });
const [err, ndmKeyboardData] = resp;
if (err || !ndmKeyboardData) {
throw err;
}
return ndmKeyboardData;
};
export const putNdmKeyboard = async (stationCode: string, updateVO: NdmKeyboardUpdateVO) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.put<NdmKeyboardResultVO>(`${prefix}/api/ndm/ndmKeyboard`, updateVO);
@@ -18,5 +28,5 @@ export const putNdmKeyboard = async (stationCode: string, updateVO: NdmKeyboardU
if (err || !ndmKeyboard) {
throw err;
}
return ndmKeyboard;
return await getNdmKeyboardDetail(stationCode, ndmKeyboard.id ?? '');
};

View File

@@ -4,11 +4,21 @@ import type { PageParams, NdmMediaServerPageQuery, PageResult, NdmMediaServerRes
export const postNdmMediaServerPage = async (stationCode: string, pageQuery: PageParams<NdmMediaServerPageQuery>, signal?: AbortSignal) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.post<PageResult<NdmMediaServerResultVO>>(`${prefix}/api/ndm/ndmMediaServer/page`, pageQuery, { signal });
const [err, ndmMediaServerData] = resp;
if (err || !ndmMediaServerData) {
const [err, ndmMediaServer] = resp;
if (err || !ndmMediaServer) {
throw err;
}
return ndmMediaServerData;
return ndmMediaServer;
};
export const getNdmMediaServerDetail = async (stationCode: string, id: string) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.get<NdmMediaServerResultVO>(`${prefix}/api/ndm/ndmMediaServer/detail`, { params: { id } });
const [err, ndmMediaServer] = resp;
if (err || !ndmMediaServer) {
throw err;
}
return ndmMediaServer;
};
export const putNdmMediaServer = async (stationCode: string, updateVO: NdmMediaServerUpdateVO) => {
@@ -18,5 +28,5 @@ export const putNdmMediaServer = async (stationCode: string, updateVO: NdmMediaS
if (err || !ndmMediaServer) {
throw err;
}
return ndmMediaServer;
return await getNdmMediaServerDetail(stationCode, ndmMediaServer.id ?? '');
};

View File

@@ -4,11 +4,21 @@ import type { PageParams, NdmVideoServerPageQuery, PageResult, NdmVideoServerRes
export const postNdmVideoServerPage = async (stationCode: string, pageQuery: PageParams<NdmVideoServerPageQuery>, signal?: AbortSignal) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.post<PageResult<NdmVideoServerResultVO>>(`${prefix}/api/ndm/ndmVideoServer/page`, pageQuery, { signal });
const [err, ndmVideoServerData] = resp;
if (err || !ndmVideoServerData) {
const [err, ndmVideoServer] = resp;
if (err || !ndmVideoServer) {
throw err;
}
return ndmVideoServerData;
return ndmVideoServer;
};
export const getNdmVideoServerDetail = async (stationCode: string, id: string) => {
const prefix = stationCode ? `/${stationCode}` : '';
const resp = await ndmClient.get<NdmVideoServerResultVO>(`${prefix}/api/ndm/ndmVideoServer/detail`, { params: { id } });
const [err, ndmVideoServer] = resp;
if (err || !ndmVideoServer) {
throw err;
}
return ndmVideoServer;
};
export const putNdmVideoServer = async (stationCode: string, updateVO: NdmVideoServerUpdateVO) => {
@@ -18,5 +28,5 @@ export const putNdmVideoServer = async (stationCode: string, updateVO: NdmVideoS
if (err || !ndmVideoServer) {
throw err;
}
return ndmVideoServer;
return await getNdmVideoServerDetail(stationCode, ndmVideoServer.id ?? '');
};

View File

@@ -68,7 +68,7 @@ const selectedTab = ref('设备状态');
<NTabs v-model:value="selectedTab" size="small">
<NTabPane name="设备状态" tab="设备状态">
<NFlex vertical>
<DeviceHeaderCard :device="ndmCamera" />
<DeviceHeaderCard :station-code="stationCode" :device="ndmCamera" />
<DeviceCommonCard :common-info="commonInfo" />
</NFlex>
</NTabPane>

View File

@@ -1,16 +1,21 @@
<script setup lang="ts">
import type { NdmDeviceResultVO } from '@/apis/models';
import { getDeviceDetailApi, probeDeviceApi } from '@/apis/requests';
import { DeviceType, DeviceTypeName, tryGetDeviceTypeVal, type DeviceTypeVal } from '@/enums/device-type';
import { NButton, NCard, NFlex, NTag } from 'naive-ui';
import { useLineDevicesStore } from '@/stores/line-devices';
import { useMutation } from '@tanstack/vue-query';
import { ApiOutlined, ReloadOutlined } from '@vicons/antd';
import { NButton, NCard, NFlex, NIcon, NTag, NTooltip } from 'naive-ui';
import { computed, toRefs } from 'vue';
const props = defineProps<{
stationCode: string;
device: NdmDeviceResultVO;
}>();
// const emit = defineEmits<{}>();
const { device } = toRefs(props);
const { stationCode, device } = toRefs(props);
const type = computed(() => {
const deviceTypeVal = tryGetDeviceTypeVal(device.value.deviceType);
@@ -39,6 +44,34 @@ const onClickOpenMgmtPage = () => {
}
}
};
const canProbe = computed(() => device.value.snmpEnabled);
const { mutate: probeDevice, isPending: probing } = useMutation({
mutationFn: async () => {
await probeDeviceApi(stationCode.value, device.value);
},
onError: (error) => {
console.error(error);
window.$message.error(error.message);
},
});
const { mutate: getDeviceDetail, isPending: loading } = useMutation({
mutationFn: async () => {
const { id, deviceType } = device.value;
return await getDeviceDetailApi(stationCode.value, id, tryGetDeviceTypeVal(deviceType));
},
onSuccess: (device) => {
if (device) {
useLineDevicesStore().patch(stationCode.value, device);
}
},
onError: (error) => {
console.error(error);
window.$message.error(error.message);
},
});
</script>
<template>
@@ -51,6 +84,8 @@ const onClickOpenMgmtPage = () => {
<div>{{ name }}</div>
<NButton v-if="canOpenMgmtPage" ghost size="tiny" type="default" :focusable="false" @click="onClickOpenMgmtPage">管理</NButton>
</NFlex>
</template>
<template #default>
<div style="font-size: small; color: #666">
<div>
<span>设备类型</span>
@@ -74,6 +109,32 @@ const onClickOpenMgmtPage = () => {
</div>
</div>
</template>
<template #header-extra>
<NTooltip v-if="canProbe" trigger="hover">
<template #trigger>
<NButton size="small" quaternary circle :loading="probing" @click="() => probeDevice()">
<template #icon>
<NIcon :component="ApiOutlined" />
</template>
</NButton>
</template>
<template #default>
<span>获取最新诊断</span>
</template>
</NTooltip>
<NTooltip trigger="hover">
<template #trigger>
<NButton size="small" quaternary circle :loading="loading" @click="() => getDeviceDetail()">
<template #icon>
<NIcon :component="ReloadOutlined" />
</template>
</NButton>
</template>
<template #default>
<span>刷新设备</span>
</template>
</NTooltip>
</template>
</NCard>
</template>

View File

@@ -48,7 +48,7 @@ const selectedTab = ref('设备状态');
<NTabs v-model:value="selectedTab" size="small">
<NTabPane name="设备状态" tab="设备状态">
<NFlex vertical>
<DeviceHeaderCard :device="ndmDecoder" />
<DeviceHeaderCard :station-code="stationCode" :device="ndmDecoder" />
<DeviceCommonCard :common-info="commonInfo" />
<DeviceHardwareCard :cpu-usage="cpuUsage" :mem-usage="memUsage" />
</NFlex>

View File

@@ -24,7 +24,7 @@ const selectedTab = ref('设备状态');
<NTabs v-model:value="selectedTab" size="small">
<NTabPane name="设备状态" tab="设备状态">
<NFlex vertical>
<DeviceHeaderCard :device="ndmKeyboard" />
<DeviceHeaderCard :station-code="stationCode" :device="ndmKeyboard" />
</NFlex>
</NTabPane>
<NTabPane name="历史诊断" tab="历史诊断">

View File

@@ -58,7 +58,7 @@ const selectedTab = ref('设备状态');
<NTabs v-model:value="selectedTab" size="small">
<NTabPane name="设备状态" tab="设备状态">
<NFlex vertical>
<DeviceHeaderCard :device="ndmNvr" />
<DeviceHeaderCard :station-code="stationCode" :device="ndmNvr" />
<DeviceCommonCard :common-info="commonInfo" />
<DeviceHardwareCard :cpu-usage="cpuUsage" :mem-usage="memUsage" />
<NvrDiskCard :disk-health="diskHealth" :group-info-list="groupInfoList" />

View File

@@ -57,7 +57,7 @@ const selectedTab = ref('设备状态');
<NTabs v-model:value="selectedTab" size="small">
<NTabPane name="设备状态" tab="设备状态">
<NFlex vertical>
<DeviceHeaderCard :device="ndmSecurityBox" />
<DeviceHeaderCard :station-code="stationCode" :device="ndmSecurityBox" />
<DeviceCommonCard :common-info="commonInfo" />
<DeviceHardwareCard :cpu-usage="cpuUsage" :mem-usage="memUsage" />
<SecurityBoxInfoCard :fan-speeds="fanSpeeds" :temperature="temperature" :humidity="humidity" :switches="switches" />

View File

@@ -39,7 +39,7 @@ const selectedTab = ref('设备状态');
<NTabs v-model:value="selectedTab" size="small">
<NTabPane name="设备状态">
<NFlex vertical>
<DeviceHeaderCard :device="ndmServer" />
<DeviceHeaderCard :station-code="stationCode" :device="ndmServer" />
<DeviceHardwareCard :cpu-usage="cpuUsage" :mem-usage="memUsage" :disk-usage="diskUsage" :running-time="runningTime" />
</NFlex>
</NTabPane>

View File

@@ -40,7 +40,7 @@ const selectedTab = ref('设备状态');
<NTabs v-model:value="selectedTab" size="small">
<NTabPane name="设备状态">
<NFlex vertical>
<DeviceHeaderCard :device="ndmSwitch" />
<DeviceHeaderCard :station-code="stationCode" :device="ndmSwitch" />
<DeviceHardwareCard :cpu-usage="cpuUsage" :mem-usage="memUsage" />
<SwitchPortCard :port-info-list="portInfoList" />
</NFlex>