vdi-cloud/console/src/components/PveConnectionDialog.vue

39 lines
4.2 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 { computed, reactive, ref, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { api, errorMessage, type PveConnectionInput } from '../api'
import { usePlatform } from '../stores/platform'
const visible = defineModel<boolean>({ required: true })
const form = reactive<PveConnectionInput>({ url: '', tokenId: '', tokenSecret: '', caPem: '', revision: '' })
const busy = ref(false), loaded = ref(false), error = ref(''), checked = ref(''), configured = ref(false), source = ref('')
watch(visible, async open => {
if (!open) return
busy.value = true; loaded.value = false; error.value = ''; checked.value = ''
try { const value = await api.pveConnection(); Object.assign(form, { url: value.url, tokenId: value.tokenId, caPem: value.caPem, tokenSecret: '', revision: value.revision }); configured.value = value.tokenConfigured; source.value = value.source; loaded.value = true }
catch (e) { error.value = errorMessage(e) } finally { busy.value = false }
})
const canSubmit = computed(() => loaded.value && !busy.value && !!form.url && !!form.tokenId)
watch(form, () => { checked.value = '' })
async function check() {
busy.value = true; error.value = ''; checked.value = ''
try { const result = await api.checkPveConnection({ ...form }); checked.value = `${result.message}:${result.nodes} 个节点、${result.vms} 台 VM` } catch (e) { error.value = errorMessage(e) } finally { busy.value = false }
}
async function save() {
busy.value = true; error.value = ''
try {
await ElMessageBox.confirm('保存时会再次检查连接,通过后立即生效。首次接入后仅允许维护同一接入地址。', '保存计算平台接入', { confirmButtonText: '确认保存', cancelButtonText: '取消', type: 'warning' })
await api.savePveConnection({ ...form }); ElMessage.success('接入配置已保存并生效'); visible.value = false; await usePlatform().refresh()
} catch (e) { if (e !== 'cancel' && e !== 'close') error.value = errorMessage(e) } finally { busy.value = false }
}
function close(done: () => void) { if (!busy.value) done() }
</script>
<template>
<el-dialog v-model="visible" title="Proxmox 接入配置" width="660px" :close-on-click-modal="false" :show-close="!busy" :before-close="close" @closed="form.tokenSecret = ''; form.caPem = ''; loaded = false">
<el-alert v-if="error" type="error" :title="error" :closable="false" class="notice" /><el-alert v-if="checked" type="success" :title="checked" :closable="false" class="notice" />
<el-skeleton v-if="busy && !loaded" :rows="6" animated />
<el-form v-if="loaded" label-position="top" :disabled="busy"><p class="subtext">当前来源:{{ source === 'database' ? '控制台配置' : '服务端环境' }}。密钥只接收输入,留空可保留同一地址和 Token ID 的原密钥。</p><el-form-item label="HTTPS 接入地址"><el-input v-model="form.url" aria-label="PVE 接入地址" placeholder="https://pve.example.com:8006" maxlength="250" /></el-form-item><el-form-item label="API Token ID"><el-input v-model="form.tokenId" aria-label="PVE Token ID" placeholder="user@pve!token-name" maxlength="200" autocomplete="off" /></el-form-item><el-form-item label="API Token 密钥"><el-input v-model="form.tokenSecret" aria-label="PVE Token 密钥" type="password" :placeholder="configured ? '已配置,留空保留原密钥' : '请输入 Token 密钥'" autocomplete="new-password" maxlength="200" /></el-form-item><el-form-item label="CA 证书(PEM,可留空使用系统信任)"><el-input v-model="form.caPem" aria-label="PVE CA 证书" type="textarea" :rows="5" maxlength="32768" placeholder="-----BEGIN CERTIFICATE-----" /></el-form-item><p class="subtext">始终验证 TLS 证书。保存失败时原配置继续使用;本期更换集群地址需离线迁移。</p></el-form>
<template #footer><el-button :disabled="busy" @click="visible = false">取消</el-button><el-button :disabled="!canSubmit" :loading="busy" @click="check">检查连接</el-button><el-button type="primary" :disabled="!canSubmit" :loading="busy" @click="save">保存并生效</el-button></template>
</el-dialog>
</template>
<style scoped>.subtext{line-height:1.8;margin:8px 0 18px}.el-form-item{margin-top:20px}</style>