168 lines
6.0 KiB
Vue
168 lines
6.0 KiB
Vue
<script setup lang="ts">
|
||
import {
|
||
detailMediaServerApi,
|
||
detailVideoServerApi,
|
||
icmpEntityByDeviceId,
|
||
updateMediaServerApi,
|
||
updateVideoServerApi,
|
||
type NdmMediaServerUpdateVO,
|
||
type NdmServerResultVO,
|
||
type NdmServerUpdateVO,
|
||
type NdmVideoServerUpdateVO,
|
||
type Station,
|
||
} from '@/apis';
|
||
import { DEVICE_TYPE_LITERALS, tryGetDeviceType } from '@/enums';
|
||
import { useDeviceStore } from '@/stores';
|
||
import { parseErrorFeedback } from '@/utils';
|
||
import { useMutation } from '@tanstack/vue-query';
|
||
import { isCancel } from 'axios';
|
||
import destr from 'destr';
|
||
import { isString } from 'es-toolkit';
|
||
import { NButton, NCard, NFlex, NForm, NFormItem, NFormItemGi, NGrid, NInput, NSwitch, type FormInst, type FormRules } from 'naive-ui';
|
||
import { computed, onBeforeUnmount, ref, toRefs, useTemplateRef, watch } from 'vue';
|
||
|
||
const props = defineProps<{
|
||
ndmDevice: NdmServerResultVO;
|
||
station: Station;
|
||
}>();
|
||
|
||
const deviceStore = useDeviceStore();
|
||
|
||
const { ndmDevice, station } = toRefs(props);
|
||
|
||
const localDevice = ref<NdmServerUpdateVO>({ ...ndmDevice.value });
|
||
watch(ndmDevice, (newDevice) => {
|
||
localDevice.value = { ...newDevice };
|
||
});
|
||
|
||
const canEditDeviceId = computed(() => {
|
||
const { deviceId } = ndmDevice.value;
|
||
if (!isString(deviceId)) return true;
|
||
if (deviceId.length === 0) return true;
|
||
return false;
|
||
});
|
||
|
||
const validatorAbortController = ref<AbortController>(new AbortController());
|
||
const abortController = ref<AbortController>(new AbortController());
|
||
|
||
const formInst = useTemplateRef<FormInst>('formInst');
|
||
const formRules: FormRules = {
|
||
deviceId: {
|
||
trigger: ['input'],
|
||
asyncValidator: async (rule, value: string) => {
|
||
await validateDeviceIdDuplicated({ deviceId: value }).catch((error) => {
|
||
if (isCancel(error)) return;
|
||
throw error;
|
||
});
|
||
},
|
||
},
|
||
};
|
||
|
||
const { mutateAsync: validateDeviceIdDuplicated } = useMutation({
|
||
mutationFn: async (params: { deviceId?: string }) => {
|
||
const { deviceId } = params;
|
||
if (!deviceId) throw new Error('请输入设备ID');
|
||
|
||
const deviceIdPattern = /^\d{4}(09|11)\d{4}$/;
|
||
if (!deviceIdPattern.test(deviceId)) throw new Error('设备ID不符合规范');
|
||
|
||
// 如果没有修改设备ID,则不做ID唯一性校验
|
||
if (deviceId === ndmDevice.value.deviceId) return;
|
||
|
||
validatorAbortController.value.abort();
|
||
validatorAbortController.value = new AbortController();
|
||
|
||
const icmpEntities = await icmpEntityByDeviceId(deviceId, {
|
||
stationCode: station.value.code,
|
||
signal: validatorAbortController.value.signal,
|
||
});
|
||
if (icmpEntities.length > 0) throw new Error('该设备ID已存在');
|
||
},
|
||
});
|
||
|
||
const { mutate: updateDevice, isPending } = useMutation({
|
||
mutationFn: async () => {
|
||
await formInst.value?.validate().catch(() => {
|
||
throw new Error('表单校验失败');
|
||
});
|
||
|
||
abortController.value.abort();
|
||
abortController.value = new AbortController();
|
||
|
||
const deviceType = tryGetDeviceType(localDevice.value.deviceType);
|
||
const stationCode = station.value.code;
|
||
const signal = abortController.value.signal;
|
||
if (deviceType === DEVICE_TYPE_LITERALS.ndmMediaServer) {
|
||
await updateMediaServerApi(localDevice.value as NdmMediaServerUpdateVO, { stationCode, signal });
|
||
return await detailMediaServerApi(`${localDevice.value.id}`, { stationCode, signal });
|
||
} else if (deviceType === DEVICE_TYPE_LITERALS.ndmVideoServer) {
|
||
await updateVideoServerApi(`${localDevice.value.id}`, localDevice.value as NdmVideoServerUpdateVO, { stationCode, signal });
|
||
return await detailVideoServerApi(`${localDevice.value.id}`, { stationCode, signal });
|
||
} else {
|
||
throw new Error('不是服务器设备');
|
||
}
|
||
},
|
||
onSuccess: (newDevice) => {
|
||
localDevice.value = { ...newDevice };
|
||
deviceStore.patchDevice(station.value.code, { ...newDevice });
|
||
window.$message.success('更新成功');
|
||
},
|
||
onError: (error) => {
|
||
if (isCancel(error)) return;
|
||
console.error(error);
|
||
const errorFeedback = parseErrorFeedback(error);
|
||
window.$message.error(errorFeedback);
|
||
},
|
||
});
|
||
|
||
onBeforeUnmount(() => {
|
||
validatorAbortController.value.abort();
|
||
abortController.value.abort();
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<NCard hoverable size="small">
|
||
<template #default>
|
||
<NForm size="small" ref="formInst" :model="localDevice" :rules="formRules">
|
||
<NGrid>
|
||
<NFormItemGi span="8" label-placement="left" label="ICMP启用">
|
||
<NSwitch :value="destr(localDevice.icmpEnabled)" @update:value="(enabled: boolean) => (localDevice.icmpEnabled = enabled)" />
|
||
</NFormItemGi>
|
||
<NFormItemGi span="8" label-placement="left" label="SNMP启用">
|
||
<NSwitch :value="destr(localDevice.snmpEnabled)" @update:value="(enabled: boolean) => (localDevice.snmpEnabled = enabled)" />
|
||
</NFormItemGi>
|
||
</NGrid>
|
||
<NFormItem label-placement="left" label="设备ID" path="deviceId">
|
||
<NInput v-model:value="localDevice.deviceId" :disabled="!canEditDeviceId" />
|
||
</NFormItem>
|
||
<NFormItem label-placement="left" label="设备名称">
|
||
<NInput v-model:value="localDevice.name" />
|
||
</NFormItem>
|
||
<NFormItem label-placement="left" label="设备厂商">
|
||
<NInput v-model:value="localDevice.manufacturer" />
|
||
</NFormItem>
|
||
<NFormItem label-placement="left" label="型号">
|
||
<NInput v-model:value="localDevice.model" />
|
||
</NFormItem>
|
||
<NFormItem label-placement="left" label="团体字符串">
|
||
<NInput v-model:value="localDevice.community" />
|
||
</NFormItem>
|
||
<NFormItem label-placement="left" label="设备描述">
|
||
<NInput v-model:value="localDevice.description" />
|
||
</NFormItem>
|
||
<NFormItem label-placement="left" label="上游设备">
|
||
<NInput v-model:value="localDevice.linkDescription" />
|
||
</NFormItem>
|
||
</NForm>
|
||
</template>
|
||
<template #action>
|
||
<NFlex justify="end">
|
||
<NButton secondary size="small" :loading="isPending" @click="() => updateDevice()">更新</NButton>
|
||
</NFlex>
|
||
</template>
|
||
</NCard>
|
||
</template>
|
||
|
||
<style scoped lang="scss"></style>
|