feat(tls): manage ACME domain and add desktop client settings

This commit is contained in:
opsx committed 2026-10-21 10:25:55 +08:00
1 parent 003f755b37
commit 00f6c876cf
85 files changed
+7276 -1

No files matched your search

+52
View File
@@ -43,6 +43,32 @@
</el-card>
</el-col>
<el-col :xs="24" :lg="14" v-if="auth.isAdmin()">
<el-card class="page-card" shadow="never" style="margin-bottom:16px">
<template #header><b>{{ $t('tls.title') }}</b></template>
<el-alert type="info" :closable="false" :title="$t('tls.description')" style="margin-bottom:16px" />
<el-form @submit.prevent="saveTLSDomain" label-position="top">
<el-form-item :label="$t('tls.domain')">
<el-input v-model.trim="tlsDomain" placeholder="test-link.appx365.com" maxlength="253" />
</el-form-item>
<el-button type="primary" :loading="tlsSaving" @click="saveTLSDomain">{{ $t('tls.saveDomain') }}</el-button>
</el-form>
<el-alert v-if="tlsStatus?.restart_required" type="warning" :closable="false" :title="$t('tls.restartRequired')" style="margin:12px 0" />
<el-descriptions :column="1" size="small" border v-if="tlsStatus">
<el-descriptions-item :label="$t('tls.domain')">{{ tlsStatus.configured_domain || $t('tls.notConfigured') }}</el-descriptions-item>
<el-descriptions-item :label="$t('tls.activeDomain')">{{ tlsStatus.domain || $t('tls.notConfigured') }}</el-descriptions-item>
<el-descriptions-item :label="$t('tls.dns')">{{ tlsStatus.dns?.join(', ') || '—' }}</el-descriptions-item>
<el-descriptions-item :label="$t('tls.certificate')">
<el-tag :type="tlsStatus.certificate_valid ? 'success' : 'warning'">{{ tlsStatus.certificate_valid ? $t('tls.valid') : tlsStatus.enabled ? $t('tls.pending') : $t('tls.notConfigured') }}</el-tag>
</el-descriptions-item>
<el-descriptions-item v-if="tlsStatus.certificate_cached" :label="$t('tls.issuer')">{{ tlsStatus.issuer || '—' }}</el-descriptions-item>
<el-descriptions-item v-if="tlsStatus.certificate_cached" :label="$t('tls.expires')">{{ new Date(tlsStatus.not_after).toLocaleString() }}</el-descriptions-item>
<el-descriptions-item :label="$t('tls.renewal')">{{ tlsStatus.enabled ? $t('tls.automatic') : '—' }}</el-descriptions-item>
<el-descriptions-item :label="$t('tls.ports')">{{ tlsStatus.http_address || ':80' }} / {{ tlsStatus.https_address || ':443' }}</el-descriptions-item>
</el-descriptions>
<p class="tls-hint">{{ $t('tls.setupHint') }}</p>
<el-button :loading="tlsLoading" @click="loadTLS">{{ $t('tls.refresh') }}</el-button>
<el-button v-if="tlsStatus?.enabled" type="primary" tag="a" :href="`https://${tlsStatus.domain}/api/health`" target="_blank" rel="noopener noreferrer">{{ $t('tls.openHttps') }}</el-button>
</el-card>
<el-card class="page-card" shadow="never">
<template #header><b>{{ $t('settings.auditTitle') }}</b></template>
<el-empty :description="$t('settings.auditMigrated')">
@@ -82,6 +108,30 @@ const mfaCanvas = ref(null)
const mfaLoading = ref(false)
const backupVisible = ref(false)
const backupCodes = ref([])
const tlsStatus = ref(null)
const tlsLoading = ref(false)
const tlsSaving = ref(false)
const tlsDomain = ref('')
async function loadTLS() {
tlsLoading.value = true
try {
const { data } = await api.get('/system/tls')
tlsStatus.value = data
tlsDomain.value = data.configured_domain || data.domain || ''
} catch (e) { ElMessage.error(e.response?.data?.error || t('tls.loadFailed')) }
finally { tlsLoading.value = false }
}
async function saveTLSDomain() {
tlsSaving.value = true
try {
const { data } = await api.put('/system/tls/domain', { domain: tlsDomain.value })
tlsStatus.value = data.status
ElMessage.success(data.restart_required ? t('tls.restartRequired') : t('tls.saved'))
} catch (e) { ElMessage.error(e.response?.data?.error || t('tls.saveFailed')) }
finally { tlsSaving.value = false }
}
async function changePwd() {
if (pwd.value.new_password !== pwd.value.confirm) return ElMessage.warning(t('settings.passwordMismatch'))
@@ -98,6 +148,7 @@ async function changePwd() {
}
onMounted(async () => {
if (auth.isAdmin() && !auth.mustChange) loadTLS()
try {
const status = await api.get('/mfa/status')
mfa.value.enabled = status.data.enabled
@@ -148,4 +199,5 @@ function copyBackup() {
color: var(--text-primary); text-align: center; padding: 6px;
background: var(--bg-card); border-radius: 4px;
}
.tls-hint { color: var(--text-secondary); line-height: 1.6; font-size: 13px; }
</style>