39 lines
4.2 KiB
Vue
39 lines
4.2 KiB
Vue
<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>
|