112 lines
3.4 KiB
Vue
112 lines
3.4 KiB
Vue
<script setup lang="ts">
|
||
import { NInput } from 'naive-ui'
|
||
|
||
import AppInputNumber from '@/components/AppInputNumber.vue'
|
||
import { computed, reactive, ref, watch } from 'vue'
|
||
|
||
import { updateBootVolume } from '@/api/bootVolumes'
|
||
import FormField from '@/components/FormField.vue'
|
||
import FormModal from '@/components/FormModal.vue'
|
||
import type { BootVolume, UpdateBootVolumeRequest } from '@/types/api'
|
||
import { useToast } from '@/composables/useToast'
|
||
|
||
const props = defineProps<{
|
||
show: boolean
|
||
cfgId: number | null
|
||
volume: BootVolume | null
|
||
region?: string
|
||
}>()
|
||
const emit = defineEmits<{ 'update:show': [boolean]; updated: [] }>()
|
||
|
||
const message = useToast()
|
||
const submitting = ref(false)
|
||
|
||
const form = reactive({ displayName: '', sizeInGBs: 50, vpusPerGB: 10 })
|
||
|
||
watch(
|
||
() => props.show,
|
||
(v) => {
|
||
if (v && props.volume)
|
||
Object.assign(form, {
|
||
displayName: props.volume.displayName,
|
||
sizeInGBs: props.volume.sizeInGBs,
|
||
vpusPerGB: props.volume.vpusPerGB,
|
||
})
|
||
},
|
||
)
|
||
|
||
const sizeError = computed(() =>
|
||
props.volume && form.sizeInGBs < props.volume.sizeInGBs ? '仅支持扩容,不能缩小' : '',
|
||
)
|
||
const canSubmit = computed(() => Boolean(form.displayName.trim()) && !sizeError.value)
|
||
|
||
/** 零值字段不更新:只提交与当前值不同的字段 */
|
||
function buildBody(v: BootVolume): UpdateBootVolumeRequest {
|
||
const body: UpdateBootVolumeRequest = {}
|
||
if (form.displayName.trim() !== v.displayName) body.displayName = form.displayName.trim()
|
||
if (form.sizeInGBs !== v.sizeInGBs) body.sizeInGBs = form.sizeInGBs
|
||
if (form.vpusPerGB !== v.vpusPerGB) body.vpusPerGB = form.vpusPerGB
|
||
return body
|
||
}
|
||
|
||
async function submit() {
|
||
if (props.cfgId === null || !props.volume) return
|
||
const body = buildBody(props.volume)
|
||
if (!Object.keys(body).length) {
|
||
emit('update:show', false)
|
||
return
|
||
}
|
||
submitting.value = true
|
||
try {
|
||
await updateBootVolume(props.cfgId, props.volume.id, body, props.region)
|
||
message.success(body.sizeInGBs ? '修改已提交;扩容后需在实例 OS 内扩展文件系统' : '修改已提交')
|
||
emit('update:show', false)
|
||
emit('updated')
|
||
} catch (e) {
|
||
message.error(e instanceof Error ? e.message : '保存失败')
|
||
} finally {
|
||
submitting.value = false
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<FormModal
|
||
:show="show"
|
||
title="编辑引导卷"
|
||
:width="440"
|
||
:submitting="submitting"
|
||
:submit-disabled="!canSubmit"
|
||
submit-text="保存修改"
|
||
@update:show="emit('update:show', $event)"
|
||
@submit="submit"
|
||
>
|
||
<FormField label="显示名" required>
|
||
<NInput v-model:value="form.displayName" placeholder="引导卷显示名" />
|
||
</FormField>
|
||
<div class="grid grid-cols-2 gap-3 max-md:grid-cols-1">
|
||
<FormField
|
||
label="大小(GB)"
|
||
hint="仅支持扩容,不能缩小;扩容后需在实例 OS 内扩展文件系统"
|
||
:error="sizeError"
|
||
>
|
||
<AppInputNumber
|
||
v-model:value="form.sizeInGBs"
|
||
:min="volume?.sizeInGBs ?? 47"
|
||
:max="32768"
|
||
class="w-full"
|
||
/>
|
||
</FormField>
|
||
<FormField label="性能(VPU/GB)" hint="10 均衡 / 20 高性能 / 30–120 超高性能,步进 10">
|
||
<AppInputNumber
|
||
v-model:value="form.vpusPerGB"
|
||
:min="10"
|
||
:max="120"
|
||
:step="10"
|
||
class="w-full"
|
||
/>
|
||
</FormField>
|
||
</div>
|
||
</FormModal>
|
||
</template>
|