This commit is contained in:
@@ -162,6 +162,10 @@
|
||||
</t-form-item>
|
||||
</div>
|
||||
|
||||
<t-alert v-if="completing" class="setup-progress" theme="info" :close-btn="false">
|
||||
{{ completionProgressMessage }}
|
||||
</t-alert>
|
||||
|
||||
<div class="setup-actions">
|
||||
<t-button variant="outline" :disabled="completing" @click="currentStep = 0">
|
||||
<template #icon><t-icon name="chevron-left" /></template>
|
||||
@@ -223,8 +227,13 @@ const errorMessage = ref('');
|
||||
const connectionResult = ref<SetupConnection | null>(null);
|
||||
const verifiedFingerprint = ref('');
|
||||
const completionMessage = ref('系统正在重启,请稍候。');
|
||||
const completionProgressMessage = ref('正在初始化数据库结构并创建管理员,请稍候。');
|
||||
const countdown = ref(10);
|
||||
let countdownTimer: number | undefined;
|
||||
let unmounted = false;
|
||||
|
||||
const SETUP_CONFIRMATION_TIMEOUT_MS = 60_000;
|
||||
const SETUP_CONFIRMATION_INTERVAL_MS = 2_000;
|
||||
|
||||
const databaseForm = reactive<SetupDatabaseRequest>({
|
||||
setupCode: '',
|
||||
@@ -317,21 +326,51 @@ async function finishSetup(context?: SubmitContext) {
|
||||
return;
|
||||
}
|
||||
completing.value = true;
|
||||
completionProgressMessage.value = '正在初始化数据库结构并创建管理员,请稍候。';
|
||||
errorMessage.value = '';
|
||||
try {
|
||||
const result = await completeSetup({ ...databaseForm, ...adminForm });
|
||||
if (!result.completed) throw new Error('安装服务未确认完成,请稍后重试');
|
||||
completionMessage.value = result.message;
|
||||
countdown.value = Math.max(1, result.restartAfterSeconds || 10);
|
||||
currentStep.value = 2;
|
||||
startCountdown();
|
||||
showCompleted(result.message, result.restartAfterSeconds);
|
||||
} catch (error) {
|
||||
errorMessage.value = (error as Error).message || '安装初始化失败';
|
||||
const requestError = error as Error & { status?: number };
|
||||
if (requestError.status === undefined || requestError.status >= 500) {
|
||||
completionProgressMessage.value = '连接暂时中断,正在确认安装结果。';
|
||||
if (await waitForSetupCompletion()) {
|
||||
showCompleted('安装已完成,系统正在切换到正式模式', 10);
|
||||
return;
|
||||
}
|
||||
errorMessage.value = '安装结果暂未确认,请稍后重新打开安装页面;若问题持续,请检查服务日志。';
|
||||
} else {
|
||||
errorMessage.value = requestError.message || '安装初始化失败';
|
||||
}
|
||||
} finally {
|
||||
completing.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function waitForSetupCompletion() {
|
||||
const deadline = Date.now() + SETUP_CONFIRMATION_TIMEOUT_MS;
|
||||
while (Date.now() < deadline) {
|
||||
if (unmounted) return false;
|
||||
try {
|
||||
const status = await getSetupStatus();
|
||||
if (status.ready) return true;
|
||||
} catch {
|
||||
// A short connection failure is expected while systemd restarts the service.
|
||||
}
|
||||
await new Promise((resolve) => window.setTimeout(resolve, SETUP_CONFIRMATION_INTERVAL_MS));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function showCompleted(message: string, restartAfterSeconds: number) {
|
||||
completionMessage.value = message;
|
||||
countdown.value = Math.max(1, restartAfterSeconds || 10);
|
||||
currentStep.value = 2;
|
||||
startCountdown();
|
||||
}
|
||||
|
||||
function confirmSetup() {
|
||||
void finishSetup();
|
||||
}
|
||||
@@ -340,13 +379,18 @@ function startCountdown() {
|
||||
window.clearInterval(countdownTimer);
|
||||
countdownTimer = window.setInterval(() => {
|
||||
countdown.value -= 1;
|
||||
if (countdown.value <= 0) openLogin();
|
||||
if (countdown.value <= 0) void openLogin();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function openLogin() {
|
||||
async function openLogin() {
|
||||
window.clearInterval(countdownTimer);
|
||||
window.location.assign('/login');
|
||||
completionMessage.value = '系统正在启动,请稍候。';
|
||||
if (await waitForSetupCompletion()) {
|
||||
window.location.assign('/login');
|
||||
return;
|
||||
}
|
||||
completionMessage.value = '系统启动时间较长,请稍后刷新页面。';
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
@@ -364,7 +408,10 @@ onMounted(async () => {
|
||||
}
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => window.clearInterval(countdownTimer));
|
||||
onBeforeUnmount(() => {
|
||||
unmounted = true;
|
||||
window.clearInterval(countdownTimer);
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
.setup-page {
|
||||
@@ -382,8 +429,7 @@ onBeforeUnmount(() => window.clearInterval(countdownTimer));
|
||||
}
|
||||
|
||||
.setup-panel {
|
||||
align-self: center;
|
||||
justify-self: center;
|
||||
place-self: center;
|
||||
width: min(760px, 100%);
|
||||
min-width: 0;
|
||||
padding: 32px;
|
||||
@@ -445,6 +491,10 @@ h1 {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.setup-progress {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.setup-complete {
|
||||
min-height: 280px;
|
||||
display: flex;
|
||||
|
||||
Reference in New Issue
Block a user