2
0

feat:组网配置

This commit is contained in:
zhongzm
2025-06-10 19:10:31 +08:00
parent 83a8fb9a98
commit bc89546ec6

View File

@@ -8,9 +8,9 @@ import {
EditOutlined,
DeleteOutlined
} from '@ant-design/icons-vue';
import { getDashboardSiteList, addSite, deleteSite, getSiteConfig, updateSite } from '@/service/api/auth';
import { getDashboardSiteList, addSite, deleteSite, getSiteConfig, updateSite, getMeshConfig, updateMeshConfig, getRoamingConfig, updateRoamingConfig } from '@/service/api/auth';
import { useI18n } from 'vue-i18n';
import { Form, Modal } from 'ant-design-vue';
import { Form, Modal, Divider, Checkbox, Select, Input, Button } from 'ant-design-vue';
import { message } from 'ant-design-vue';
import { regionOptions, timeZoneOptions } from '@/constants/site-options';
const { t } = useI18n();
@@ -250,6 +250,13 @@ const editFormData = ref({
region: '',
timeZone: '',
scenario: '',
meshEnable: false,
autoFailoverEnable: false,
defGatewayEnable: true,
gateway: '',
fastRoamingEnable: false,
nonStickRoamingEnable: false,
aiRoamingEnable: false
});
// 当前编辑的站点ID
@@ -269,18 +276,53 @@ const { validate: validateEdit, validateInfos: validateEditInfos } = useForm(edi
scenario: [{ required: true, message: t('page.carddata.scenarioRequired') }]
});
// IP分段输入
const gatewayIpParts = ref(['', '', '', '']);
// 拆分IP到4段
function splitGatewayIp(ip: string) {
if (!ip) return ['', '', '', ''];
const parts = ip.split('.');
return [parts[0] || '', parts[1] || '', parts[2] || '', parts[3] || ''];
}
// 拼接4段为IP
function joinGatewayIp(parts: string[]) {
return parts.map(p => p.trim()).join('.');
}
// 弹窗打开时同步分段
watch(() => editFormData.value.gateway, (val) => {
gatewayIpParts.value = splitGatewayIp(val);
}, { immediate: true });
// 分段输入时同步到gateway
watch(gatewayIpParts, (val) => {
editFormData.value.gateway = joinGatewayIp(val);
}, { deep: true });
// 处理编辑按钮点击
const handleEdit = async (record: Api.DashboardSite) => {
try {
currentEditSiteId.value = record.siteId;
const response = await getSiteConfig(record.siteId);
if (response.data) {
const [siteRes, meshRes, roamingRes] = await Promise.all([
getSiteConfig(record.siteId),
getMeshConfig(record.siteId),
getRoamingConfig(record.siteId)
]);
if (siteRes.data) {
editFormData.value = {
name: response.data.name,
region: response.data.region,
timeZone: response.data.timeZone,
scenario: response.data.scenario
name: siteRes.data.name,
region: siteRes.data.region,
timeZone: siteRes.data.timeZone,
scenario: siteRes.data.scenario,
meshEnable: meshRes.data?.mesh?.meshEnable ?? false,
autoFailoverEnable: meshRes.data?.mesh?.autoFailoverEnable ?? false,
defGatewayEnable: meshRes.data?.mesh?.defGatewayEnable ?? true,
gateway: meshRes.data?.mesh?.gateway ?? '',
fastRoamingEnable: roamingRes.data?.roaming?.fastRoamingEnable ?? false,
nonStickRoamingEnable: roamingRes.data?.roaming?.nonStickRoamingEnable ?? false,
aiRoamingEnable: roamingRes.data?.roaming?.aiRoamingEnable ?? false
};
gatewayIpParts.value = splitGatewayIp(editFormData.value.gateway);
showEditDialog.value = true;
}
} catch (error) {
@@ -293,7 +335,32 @@ const handleEdit = async (record: Api.DashboardSite) => {
const handleUpdateSite = async () => {
try {
await validateEdit();
await updateSite(currentEditSiteId.value, editFormData.value);
// 先保存基础配置
await updateSite(currentEditSiteId.value, {
name: editFormData.value.name,
region: editFormData.value.region,
timeZone: editFormData.value.timeZone,
scenario: editFormData.value.scenario
});
// mesh 配置为嵌套结构meshEnable为true时才携带defGatewayEnable和gateway
const meshData: any = { mesh: { meshEnable: editFormData.value.meshEnable } };
if (editFormData.value.meshEnable) {
meshData.mesh.autoFailoverEnable = editFormData.value.autoFailoverEnable;
meshData.mesh.defGatewayEnable = editFormData.value.defGatewayEnable;
if (editFormData.value.defGatewayEnable === false) {
meshData.mesh.gateway = editFormData.value.gateway;
}
}
// roaming 配置为嵌套结构
const roamingData: any = { roaming: { fastRoamingEnable: editFormData.value.fastRoamingEnable } };
if (editFormData.value.fastRoamingEnable) {
roamingData.roaming.nonStickRoamingEnable = editFormData.value.nonStickRoamingEnable;
roamingData.roaming.aiRoamingEnable = editFormData.value.aiRoamingEnable;
}
await Promise.all([
updateMeshConfig(currentEditSiteId.value, meshData),
updateRoamingConfig(currentEditSiteId.value, roamingData)
]);
message.success(t('page.carddata.updateSuccess'));
showEditDialog.value = false;
fetchSiteList(); // 刷新列表
@@ -478,6 +545,7 @@ const handleUpdateSite = async () => {
@ok="handleUpdateSite"
@cancel="showEditDialog = false"
:maskClosable="false"
:width="700"
>
<AForm
:model="editFormData"
@@ -530,6 +598,36 @@ const handleUpdateSite = async () => {
:options="scenarioOptions"
/>
</AFormItem>
<a-divider />
<div style="margin-bottom: 8px; font-weight: bold;">组网配置</div>
<AFormItem>
<a-checkbox v-model:checked="editFormData.meshEnable">Mesh</a-checkbox>
</AFormItem>
<AFormItem v-if="editFormData.meshEnable" style="margin-left: 24px;">
<ASelect v-model:value="editFormData.defGatewayEnable" style="width: 200px;">
<ASelectOption :value="true">AutoRecommended</ASelectOption>
<ASelectOption :value="false">Custom</ASelectOption>
</ASelect>
<template v-if="editFormData.defGatewayEnable === false">
<div style="display: inline-flex; align-items: center; margin-left: 12px;">
<AInput v-for="(part, idx) in gatewayIpParts" :key="idx" v-model:value="gatewayIpParts[idx]" maxlength="3" style="width: 48px; text-align: center; margin-right: 4px;" />
<span v-if="idx < 3" v-for="idx in 3" :key="'dot'+idx">.</span>
</div>
</template>
</AFormItem>
<AFormItem v-if="editFormData.meshEnable" style="margin-left: 24px;">
<a-checkbox v-model:checked="editFormData.autoFailoverEnable">Auto Failover</a-checkbox>
</AFormItem>
<AFormItem>
<a-checkbox v-model:checked="editFormData.fastRoamingEnable">Fast Roaming</a-checkbox>
</AFormItem>
<AFormItem v-if="editFormData.fastRoamingEnable" style="margin-left: 24px;">
<a-checkbox v-model:checked="editFormData.nonStickRoamingEnable">Non-Stick Roaming</a-checkbox>
</AFormItem>
<AFormItem v-if="editFormData.fastRoamingEnable" style="margin-left: 24px;">
<a-checkbox v-model:checked="editFormData.aiRoamingEnable">AI Roaming</a-checkbox>
</AFormItem>
</AForm>
</AModal>
</ACard>