初始提交:OCI 面板前端(含 GenAI 网关一期)
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
<script setup lang="ts">
|
||||
import { NInput, NSelect, useMessage, 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'
|
||||
|
||||
const props = defineProps<{
|
||||
show: boolean
|
||||
cfgId: number
|
||||
instanceId: string
|
||||
region?: string
|
||||
/** 已附加网卡数,仅用于配额提示文案 */
|
||||
attachedCount: number
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{ 'update:show': [boolean]; attached: [] }>()
|
||||
|
||||
const message = useMessage()
|
||||
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>
|
||||
Reference in New Issue
Block a user