Files
oci-portal-dash/src/components/instance/AttachVnicModal.vue
T
Wang Defa 5464d2dfea
CI / test (push) Successful in 27s
Release / release (push) Successful in 26s
发布 0.1.0:通知渠道、告警规则与多项体验修复
2026-07-10 17:31:19 +08:00

148 lines
4.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { NInput, NSelect, type SelectOption } from 'naive-ui'
import { computed, ref, watch } from 'vue'
import { attachVnic } from '@/api/instances'
import { listSubnets } from '@/api/networks'
import FormField from '@/components/FormField.vue'
import FormModal from '@/components/FormModal.vue'
import ToggleCard from '@/components/ToggleCard.vue'
import { useAsync } from '@/composables/useAsync'
import { shortAd } from '@/composables/useFormat'
import { useToast } from '@/composables/useToast'
const props = defineProps<{
show: boolean
cfgId: number
instanceId: string
region?: string
/** 已附加网卡数,仅用于配额提示文案 */
attachedCount: number
}>()
const emit = defineEmits<{ 'update:show': [boolean]; attached: [] }>()
const message = useToast()
const submitting = ref(false)
const subnetId = ref<string | null>(null)
const displayName = ref('')
const privateIp = ref('')
const assignPublicIp = ref(false)
const assignIpv6 = ref(false)
/** vcnId 传空列全部子网:次要网卡允许跨 VCN */
const subnets = useAsync(() => listSubnets(props.cfgId, '', props.region), false)
watch(
() => props.show,
(v) => {
if (v) {
subnetId.value = null
displayName.value = ''
privateIp.value = ''
assignPublicIp.value = false
assignIpv6.value = false
void subnets.run()
}
},
)
const options = computed<SelectOption[]>(() =>
(subnets.data.value ?? [])
.filter((s) => s.lifecycleState === 'AVAILABLE')
.map((s) => ({
label: `${s.displayName}${s.cidrBlock}${s.availabilityDomain ? ` · ${shortAd(s.availabilityDomain)}` : ''}`,
value: s.id,
})),
)
const selected = computed(() => (subnets.data.value ?? []).find((s) => s.id === subnetId.value))
/** 私有子网禁分公网 IP;未启用 IPv6 的子网禁自动分配 */
const publicIpBlocked = computed(() => !!selected.value?.prohibitPublicIp)
const ipv6Blocked = computed(() => !!selected.value && !selected.value.ipv6CidrBlock)
watch(selected, (s) => {
if (s?.prohibitPublicIp) assignPublicIp.value = false
if (s && !s.ipv6CidrBlock) assignIpv6.value = false
})
async function submit() {
if (!subnetId.value) return
submitting.value = true
try {
await attachVnic(props.cfgId, props.instanceId, {
region: props.region,
subnetId: subnetId.value,
displayName: displayName.value.trim(),
privateIp: privateIp.value.trim(),
assignPublicIp: assignPublicIp.value,
assignIpv6: assignIpv6.value,
})
message.success('附加请求已提交,OS 内需自行配置新网卡 IP')
emit('update:show', false)
emit('attached')
} catch (e) {
message.error(e instanceof Error ? e.message : '附加失败')
} finally {
submitting.value = false
}
}
</script>
<template>
<FormModal
:show="show"
title="附加 VNIC"
:submitting="submitting"
:submit-disabled="!subnetId"
submit-text="附加"
@update:show="emit('update:show', $event)"
@submit="submit"
>
<FormField
label="子网"
required
hint="与实例同 AD 的子网;跨 VCN 子网亦可选"
:error="
!subnets.loading.value && !options.length ? '该区域没有可用子网,请先创建' : undefined
"
>
<NSelect
v-model:value="subnetId"
:options="options"
:loading="subnets.loading.value"
filterable
placeholder="选择子网"
/>
</FormField>
<FormField label="显示名称">
<NInput v-model:value="displayName" placeholder="留空自动生成" />
</FormField>
<FormField label="私网 IP">
<NInput v-model:value="privateIp" placeholder="留空自动分配(推荐)" />
</FormField>
<div class="flex flex-col gap-2.5">
<ToggleCard
v-model="assignPublicIp"
title="分配公网 IP"
:desc="publicIpBlocked ? '所选子网为私有子网,不可分配公网 IP' : '仅公有子网可用;临时地址,分离即释放'"
:disabled="publicIpBlocked"
/>
<ToggleCard
v-model="assignIpv6"
title="自动分配 IPv6"
:desc="
ipv6Blocked
? '所选子网未启用 IPv6(可在 VCN 详情一键启用)'
: '附加时同时分一个 IPv6;后续可在网卡列表继续添加'
"
:disabled="ipv6Blocked"
/>
</div>
<div class="mt-2 rounded-md bg-wash px-3 py-2 text-xs leading-relaxed text-ink-3">
当前已附加 {{ attachedCount }} 张网卡可附加数量由 shape 决定 A1.Flex OCPU 1
),超出配额时 OCI 会拒绝请求
</div>
</FormModal>
</template>