feat: 国标级联新增/编辑

This commit is contained in:
JiangQiming 2023-02-28 21:13:10 +08:00
parent e233e9f55f
commit fbff5146bd
2 changed files with 216 additions and 164 deletions

View File

@ -11,7 +11,8 @@ export default {
// 新增 // 新增
save: (data: any) => server.post(`/media/gb28181-cascade`, data), save: (data: any) => server.post(`/media/gb28181-cascade`, data),
// 修改 // 修改
update: (id: string, data: any) => server.put(`/media/gb28181-cascade/${id}`, data), // update: (id: string, data: any) => server.put(`/media/gb28181-cascade/${id}`, data),
update: (data: any) => server.patch(`/media/gb28181-cascade`, data),
// 删除 // 删除
del: (id: string) => server.remove(`media/gb28181-cascade/${id}`), del: (id: string) => server.remove(`media/gb28181-cascade/${id}`),
// 禁用 // 禁用
@ -21,8 +22,8 @@ export default {
// 新增/编辑 // 新增/编辑
// 获取集群节点 // 获取集群节点
clusters: () => server.get(`/network/resources/alive/clusters`), clusters: () => server.get<any>(`/network/resources/clusters`),
// SIP本地地址 // SIP本地地址
all: () => server.get(`/network/resources/alive/_all`), all: () => server.get<any>(`/network/resources/alive/_all`),
} }

View File

@ -4,13 +4,13 @@
<a-card> <a-card>
<a-row :gutter="24"> <a-row :gutter="24">
<a-col :span="12"> <a-col :span="12">
<a-form layout="vertical" :model="formData"> <a-form ref="formRef" layout="vertical" :model="formData">
<a-row :gutter="24"> <a-row :gutter="24">
<TitleComponent data="基本信息" /> <TitleComponent data="基本信息" />
<a-col :span="12"> <a-col :span="12">
<a-form-item <a-form-item
label="名称" label="名称"
name="name" name="cascadeName"
:rules="[ :rules="[
{ {
required: true, required: true,
@ -23,7 +23,7 @@
]" ]"
> >
<a-input <a-input
v-model:value="formData.name" v-model:value="formData.cascadeName"
placeholder="请输入名称" placeholder="请输入名称"
/> />
</a-form-item> </a-form-item>
@ -31,7 +31,7 @@
<a-col :span="12"> <a-col :span="12">
<a-form-item <a-form-item
label="代理视频流" label="代理视频流"
name="name" name="proxyStream"
:rules="[ :rules="[
{ {
required: true, required: true,
@ -41,12 +41,12 @@
> >
<a-radio-group <a-radio-group
button-style="solid" button-style="solid"
v-model:value="formData.name" v-model:value="formData.proxyStream"
> >
<a-radio-button value="enabled"> <a-radio-button :value="true">
启用 启用
</a-radio-button> </a-radio-button>
<a-radio-button value="disabled"> <a-radio-button :value="false">
禁用 禁用
</a-radio-button> </a-radio-button>
</a-radio-group> </a-radio-group>
@ -56,8 +56,7 @@
<TitleComponent data="信令服务配置" /> <TitleComponent data="信令服务配置" />
<a-col :span="12"> <a-col :span="12">
<a-form-item <a-form-item
label="集群节点" name="clusterNodeId"
name="name"
:rules="[ :rules="[
{ {
required: true, required: true,
@ -65,9 +64,23 @@
}, },
]" ]"
> >
<a-input <template #label>
v-model:value="formData.name" <span>
集群节点
<a-tooltip
title="使用此集群节点级联到上级平台"
>
<AIcon
type="QuestionCircleOutlined"
style="margin-left: 2px"
/>
</a-tooltip>
</span>
</template>
<a-select
v-model:value="formData.clusterNodeId"
placeholder="请选择集群节点" placeholder="请选择集群节点"
:options="clustersList"
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
@ -95,7 +108,7 @@
<a-col :span="24"> <a-col :span="24">
<a-form-item <a-form-item
label="上级SIP ID" label="上级SIP ID"
name="name" name="sipId"
:rules="[ :rules="[
{ {
required: true, required: true,
@ -108,7 +121,7 @@
]" ]"
> >
<a-input <a-input
v-model:value="formData.name" v-model:value="formData.sipId"
placeholder="请输入上级SIP ID" placeholder="请输入上级SIP ID"
/> />
</a-form-item> </a-form-item>
@ -116,7 +129,7 @@
<a-col :span="12"> <a-col :span="12">
<a-form-item <a-form-item
label="上级SIP域" label="上级SIP域"
name="name" name="domain"
:rules="[ :rules="[
{ {
required: true, required: true,
@ -129,7 +142,7 @@
]" ]"
> >
<a-input <a-input
v-model:value="formData.name" v-model:value="formData.domain"
placeholder="请输入上级平台SIP域" placeholder="请输入上级平台SIP域"
/> />
</a-form-item> </a-form-item>
@ -137,7 +150,7 @@
<a-col :span="12"> <a-col :span="12">
<a-form-item <a-form-item
label="上级SIP 地址" label="上级SIP 地址"
name="name" name="remoteAddress"
:rules="[ :rules="[
{ {
required: true, required: true,
@ -152,14 +165,21 @@
<a-row :gutter="10"> <a-row :gutter="10">
<a-col :span="14"> <a-col :span="14">
<a-input <a-input
v-model:value="formData.name" v-model:value="
formData.remoteAddress
"
placeholder="请输入IP地址" placeholder="请输入IP地址"
/> />
</a-col> </a-col>
<a-col :span="10"> <a-col :span="10">
<a-input <a-input-number
v-model:value="formData.name" :min="1"
:max="65535"
v-model:value="
formData.remotePort
"
placeholder="请输入端口" placeholder="请输入端口"
style="width: 100%"
/> />
</a-col> </a-col>
</a-row> </a-row>
@ -169,7 +189,7 @@
<a-col :span="24"> <a-col :span="24">
<a-form-item <a-form-item
label="本地SIP ID" label="本地SIP ID"
name="name" name="localSipId"
:rules="[ :rules="[
{ {
required: true, required: true,
@ -182,15 +202,14 @@
]" ]"
> >
<a-input <a-input
v-model:value="formData.name" v-model:value="formData.localSipId"
placeholder="网关侧的SIP ID" placeholder="网关侧的SIP ID"
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="12"> <a-col :span="12">
<a-form-item <a-form-item
label="SIP本地地址" name="host"
name="name"
:rules="[ :rules="[
{ {
required: true, required: true,
@ -198,20 +217,30 @@
}, },
]" ]"
> >
<template #label>
<span>
SIP本地地址
<a-tooltip
title="使用指定的网卡和端口进行请求"
>
<AIcon
type="QuestionCircleOutlined"
style="margin-left: 2px"
/>
</a-tooltip>
</span>
</template>
<a-row :gutter="10"> <a-row :gutter="10">
<a-col :span="14"> <a-col :span="14">
<a-select <a-select
v-model:value="formData.name" v-model:value="formData.host"
placeholder="请选择IP地址" placeholder="请选择IP地址"
> :options="allList"
<a-select-option value="1"> />
1
</a-select-option>
</a-select>
</a-col> </a-col>
<a-col :span="10"> <a-col :span="10">
<a-select <a-select
v-model:value="formData.name" v-model:value="formData.port"
placeholder="请选择端口" placeholder="请选择端口"
> >
<a-select-option value="1"> <a-select-option value="1">
@ -225,7 +254,7 @@
<a-col :span="12"> <a-col :span="12">
<a-form-item <a-form-item
label="SIP远程地址" label="SIP远程地址"
name="name" name="publicHost"
:rules="[ :rules="[
{ {
required: true, required: true,
@ -240,14 +269,21 @@
<a-row :gutter="10"> <a-row :gutter="10">
<a-col :span="14"> <a-col :span="14">
<a-input <a-input
v-model:value="formData.name" v-model:value="
formData.publicHost
"
placeholder="请输入IP地址" placeholder="请输入IP地址"
/> />
</a-col> </a-col>
<a-col :span="10"> <a-col :span="10">
<a-input <a-input-number
v-model:value="formData.name" :min="1"
:max="65535"
v-model:value="
formData.publicPort
"
placeholder="请输入端口" placeholder="请输入端口"
style="width: 100%"
/> />
</a-col> </a-col>
</a-row> </a-row>
@ -256,7 +292,7 @@
<a-col :span="24"> <a-col :span="24">
<a-form-item <a-form-item
label="传输协议" label="传输协议"
name="name" name="transport"
:rules="[ :rules="[
{ {
required: true, required: true,
@ -266,12 +302,12 @@
> >
<a-radio-group <a-radio-group
button-style="solid" button-style="solid"
v-model:value="formData.name" v-model:value="formData.transport"
> >
<a-radio-button value="UDP"> <a-radio-button value="UDP">
UDP UDP
</a-radio-button> </a-radio-button>
<a-radio-button value="TCP_PASSIVE"> <a-radio-button value="TCP">
TCP TCP
</a-radio-button> </a-radio-button>
</a-radio-group> </a-radio-group>
@ -280,7 +316,7 @@
<a-col :span="12"> <a-col :span="12">
<a-form-item <a-form-item
label="用户" label="用户"
name="name" name="user"
:rules="[ :rules="[
{ {
required: true, required: true,
@ -293,7 +329,7 @@
]" ]"
> >
<a-input <a-input
v-model:value="formData.name" v-model:value="formData.user"
placeholder="请输入用户" placeholder="请输入用户"
/> />
</a-form-item> </a-form-item>
@ -301,7 +337,7 @@
<a-col :span="12"> <a-col :span="12">
<a-form-item <a-form-item
label="接入密码" label="接入密码"
name="name" name="password"
:rules="[ :rules="[
{ {
required: true, required: true,
@ -313,8 +349,8 @@
}, },
]" ]"
> >
<a-input <a-input-password
v-model:value="formData.name" v-model:value="formData.password"
placeholder="请输入接入密码" placeholder="请输入接入密码"
/> />
</a-form-item> </a-form-item>
@ -322,7 +358,7 @@
<a-col :span="12"> <a-col :span="12">
<a-form-item <a-form-item
label="厂商" label="厂商"
name="name" name="manufacturer"
:rules="[ :rules="[
{ {
required: true, required: true,
@ -335,7 +371,7 @@
]" ]"
> >
<a-input <a-input
v-model:value="formData.name" v-model:value="formData.manufacturer"
placeholder="请输入厂商" placeholder="请输入厂商"
/> />
</a-form-item> </a-form-item>
@ -343,7 +379,7 @@
<a-col :span="12"> <a-col :span="12">
<a-form-item <a-form-item
label="型号" label="型号"
name="name" name="model"
:rules="[ :rules="[
{ {
required: true, required: true,
@ -356,7 +392,7 @@
]" ]"
> >
<a-input <a-input
v-model:value="formData.name" v-model:value="formData.model"
placeholder="请输入型号" placeholder="请输入型号"
/> />
</a-form-item> </a-form-item>
@ -364,7 +400,7 @@
<a-col :span="12"> <a-col :span="12">
<a-form-item <a-form-item
label="版本号" label="版本号"
name="name" name="firmware"
:rules="[ :rules="[
{ {
required: true, required: true,
@ -377,7 +413,7 @@
]" ]"
> >
<a-input <a-input
v-model:value="formData.name" v-model:value="formData.firmware"
placeholder="请输入版本号" placeholder="请输入版本号"
/> />
</a-form-item> </a-form-item>
@ -385,42 +421,44 @@
<a-col :span="12"> <a-col :span="12">
<a-form-item <a-form-item
label="心跳周期(秒)" label="心跳周期(秒)"
name="name" name="keepaliveInterval"
:rules="[ :rules="[
{ {
required: true, required: true,
message: '请输入心跳周期(秒)', message: '请输入心跳周期',
},
{
max: 64,
message: '最多可输入64个字符',
}, },
]" ]"
> >
<a-input-number <a-input-number
v-model:value="formData.name" :min="1"
placeholder="请输入心跳周期(秒)" :max="10000"
v-model:value="
formData.keepaliveInterval
"
placeholder="请输入心跳周期"
style="width: 100%"
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="12"> <a-col :span="12">
<a-form-item <a-form-item
label="注册间隔(秒)" label="注册间隔(秒)"
name="name" name="registerInterval"
:rules="[ :rules="[
{ {
required: true, required: true,
message: '请输入注册间隔(秒)', message: '请输入注册间隔',
},
{
max: 64,
message: '最多可输入64个字符',
}, },
]" ]"
> >
<a-input-number <a-input-number
v-model:value="formData.name" :min="1"
placeholder="请输入注册间隔(秒)" :max="10000"
v-model:value="
formData.registerInterval
"
placeholder="请输入注册间隔"
style="width: 100%"
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
@ -523,10 +561,7 @@ import { getImage } from '@/utils/comm';
import { Form } from 'ant-design-vue'; import { Form } from 'ant-design-vue';
import { message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import DeviceApi from '@/api/media/device'; import CascadeApi from '@/api/media/cascade';
import { PROVIDER_OPTIONS } from '@/views/media/Device/const';
import type { ProductType } from '@/views/media/Device/typings';
const router = useRouter(); const router = useRouter();
const route = useRoute(); const route = useRoute();
@ -534,101 +569,96 @@ const useForm = Form.useForm;
// //
const formData = ref({ const formData = ref({
id: '', id: route.query.id || undefined,
// name: '',
cascadeName: '',
proxyStream: false,
// , sipConfigs[{}]
clusterNodeId: '',
name: '', name: '',
channel: 'gb28181-2016', sipId: '',
photoUrl: getImage('/device-media.png'), domain: '',
productId: '', remoteAddress: '',
others: { remotePort: undefined,
access_pwd: '', localSipId: '',
}, host: '',
description: '', port: undefined,
// // remotePublic: {
streamMode: 'UDP', // host: '',
// port: undefined,
// },
publicHost: '',
publicPort: undefined,
transport: 'UDP',
user: '',
password: '',
manufacturer: '', manufacturer: '',
model: '', model: '',
firmware: '', firmware: '',
keepaliveInterval: '60',
registerInterval: '3600',
}); });
//
const formRules = ref({
id: [
{
required: true,
message: '请输入ID',
},
{ max: 64, message: '最多输入64个字符' },
{
pattern: /^[a-zA-Z0-9_\-]+$/,
message: '请输入英文或者数字或者-或者_',
},
],
name: [
{ required: true, message: '请输入名称' },
{ max: 64, message: '最多可输入64个字符' },
],
productId: [{ required: true, message: '请选择所属产品' }],
channel: [{ required: true, message: '请选择接入方式' }],
'others.access_pwd': [{ required: true, message: '请输入接入密码' }],
description: [{ max: 200, message: '最多可输入200个字符' }],
streamMode: [{ required: true, message: '请选择流传输模式' }],
});
watch(
() => formData.value.channel,
(val) => {
formRules.value['id'][0].required = val === 'gb28181-2016';
formRules.value['others.access_pwd'][0].required =
val === 'gb28181-2016';
validate();
getProductList();
},
);
const { resetFields, validate, validateInfos, clearValidate } = useForm(
formData.value,
formRules.value,
);
const clearValid = () => {
setTimeout(() => {
clearValidate();
}, 200);
};
/** /**
* 获取所属产品 * 获取集群节点
*/ */
const productList = ref<ProductType[]>([]); const clustersList = ref([]);
const getProductList = async () => { const getClustersList = async () => {
// console.log('formData.productId: ', formData.value.productId); const { result } = await CascadeApi.clusters();
const params = { clustersList.value = result.map((m: any) => ({
paging: false, label: m.name,
sorts: [{ name: 'createTime', order: 'desc' }], value: m.id,
terms: [ }));
{ column: 'accessProvider', value: formData.value.channel },
{ column: 'state', value: 1 },
],
};
const { result } = await DeviceApi.queryProductList(params);
productList.value = result;
}; };
getProductList(); getClustersList();
/** /**
* 新增产品 * SIP本地地址
*/ */
const saveProductVis = ref(false); const allList = ref([]);
const getAllList = async () => {
const { result } = await CascadeApi.all();
allList.value = result.map((m: any) => ({
label: m.host,
value: m.host,
}));
};
getAllList();
/** /**
* 获取详情 * 获取详情
*/ */
const getDetail = async () => { const getDetail = async () => {
const res = await DeviceApi.detail(route.query.id as string); if (!route.query.id) return;
const res = await CascadeApi.detail(route.query.id as string);
// console.log('res: ', res); // console.log('res: ', res);
// formData.value = res.result; // formData.value = res.result;
Object.assign(formData.value, res.result); // Object.assign(formData.value, res.result);
formData.value.channel = res.result.provider;
const { id, name, proxyStream, sipConfigs } = res.result;
formData.value = {
id,
cascadeName: name,
proxyStream,
clusterNodeId: sipConfigs[0]?.clusterNodeId,
name: sipConfigs[0]?.name,
sipId: sipConfigs[0]?.sipId,
domain: sipConfigs[0]?.domain,
remoteAddress: sipConfigs[0]?.remoteAddress,
remotePort: sipConfigs[0]?.remotePort,
localSipId: sipConfigs[0]?.localSipId,
host: sipConfigs[0]?.host,
port: sipConfigs[0]?.port,
publicHost: sipConfigs[0]?.publicHost,
publicPort: sipConfigs[0]?.publicPort,
transport: sipConfigs[0]?.transport,
user: sipConfigs[0]?.user,
password: sipConfigs[0]?.password,
manufacturer: sipConfigs[0]?.manufacturer,
model: sipConfigs[0]?.model,
firmware: sipConfigs[0]?.firmware,
keepaliveInterval: sipConfigs[0]?.keepaliveInterval,
registerInterval: sipConfigs[0]?.registerInterval,
};
console.log('formData.value: ', formData.value); console.log('formData.value: ', formData.value);
}; };
@ -640,28 +670,49 @@ onMounted(() => {
/** /**
* 表单提交 * 表单提交
*/ */
const formRef = ref();
const btnLoading = ref<boolean>(false); const btnLoading = ref<boolean>(false);
const handleSubmit = () => { const handleSubmit = () => {
// console.log('formData.value: ', formData.value); // console.log('formData.value: ', formData.value);
validate() formRef.value
.validate()
.then(async () => { .then(async () => {
const {
id,
cascadeName,
proxyStream,
publicHost,
publicPort,
...extraFormData
} = formData.value;
const params = {
id,
name: cascadeName,
proxyStream,
sipConfigs: [
{
...extraFormData,
remotePublic: {
host: publicHost,
port: publicPort,
},
},
],
};
btnLoading.value = true; btnLoading.value = true;
let res; const res = formData.value.id
if (!route.query.id) { ? await CascadeApi.update(params)
res = await DeviceApi.save(formData.value); : await CascadeApi.save(params);
} else {
res = await DeviceApi.update(formData.value);
}
if (res?.success) {
message.success('保存成功');
router.back();
}
})
.catch((err) => {
console.log('err: ', err);
})
.finally(() => {
btnLoading.value = false; btnLoading.value = false;
if (res.success) {
message.success('操作成功');
router.back();
} else {
message.error('操作失败');
}
})
.catch((err: any) => {
console.log('err: ', err);
}); });
}; };
</script> </script>