Update application UI and functionality
This commit is contained in:
@@ -66,6 +66,7 @@ const route = useRoute();
|
||||
const router = useRouter();
|
||||
const currentPath = computed(() => normalizeAdminPath(route.path));
|
||||
const loading = ref(false);
|
||||
const loginPending = ref(false);
|
||||
const toast = ref<ToastState | null>(null);
|
||||
const autoRefreshPaused = ref(false);
|
||||
const databaseFormEditing = ref(false);
|
||||
@@ -490,7 +491,7 @@ function isAuthError(raw: string, message: string) {
|
||||
}
|
||||
|
||||
async function loadCaptcha() {
|
||||
captcha.value = await api<Captcha>("/api/admin/auth/captcha");
|
||||
captcha.value = await adminFetch<Captcha>("/api/admin/auth/captcha", {}, { timeoutMs: 5000 });
|
||||
}
|
||||
|
||||
async function loadAuthBootstrap() {
|
||||
@@ -498,17 +499,35 @@ async function loadAuthBootstrap() {
|
||||
}
|
||||
|
||||
async function login() {
|
||||
await guarded(async () => {
|
||||
const data = await api<{ csrfToken: string }>("/api/admin/auth/login", {
|
||||
if (loginPending.value) return;
|
||||
if (!loginForm.password || !loginForm.captcha || !captcha.value?.captchaId) {
|
||||
setToast("请填写密码和验证码", "warn");
|
||||
return;
|
||||
}
|
||||
|
||||
loginPending.value = true;
|
||||
loading.value = true;
|
||||
try {
|
||||
const data = await adminFetch<{ csrfToken: string }>("/api/admin/auth/login", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ ...loginForm, captchaId: captcha.value?.captchaId }),
|
||||
});
|
||||
}, { timeoutMs: 8000 });
|
||||
csrf.value = data.csrfToken;
|
||||
sessionStorage.setItem("ymhut.csrf", csrf.value);
|
||||
localStorage.removeItem("ymhut.csrf");
|
||||
connectAdminEvents();
|
||||
navigate("/admin/dashboard");
|
||||
});
|
||||
} catch (error) {
|
||||
const message = toChineseError(error instanceof Error ? error.message : String(error));
|
||||
setToast(message, "error");
|
||||
loginForm.captcha = "";
|
||||
void loadCaptcha().catch(() => {
|
||||
captcha.value = null;
|
||||
});
|
||||
} finally {
|
||||
loading.value = false;
|
||||
loginPending.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function logout() {
|
||||
@@ -747,6 +766,7 @@ async function uploadPackage() {
|
||||
setToast("请选择要上传的发布包", "warn");
|
||||
return;
|
||||
}
|
||||
let completed = false;
|
||||
await guarded(async () => {
|
||||
const form = new FormData();
|
||||
form.append("file", uploadDraft.file as File);
|
||||
@@ -771,6 +791,7 @@ async function uploadPackage() {
|
||||
uploadDraft.status = "上传完成";
|
||||
uploadDraft.file = null;
|
||||
uploadDraft.notes = "";
|
||||
completed = true;
|
||||
setToast("发布包已上传并放入下载目录");
|
||||
await loadReleases();
|
||||
window.setTimeout(() => {
|
||||
@@ -783,6 +804,12 @@ async function uploadPackage() {
|
||||
}, 1200);
|
||||
}).finally(() => {
|
||||
uploadDraft.uploading = false;
|
||||
if (!completed) {
|
||||
uploadDraft.progress = 0;
|
||||
uploadDraft.loadedBytes = 0;
|
||||
uploadDraft.totalBytes = uploadDraft.file?.size || 0;
|
||||
uploadDraft.status = "上传失败,可直接重试";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1709,19 +1736,19 @@ function connectAdminEvents() {
|
||||
当前使用默认账号:{{ authBootstrap.defaultUsername || "admin" }} / {{ authBootstrap.defaultPassword || "admin" }}
|
||||
</p>
|
||||
<form class="form-stack" @submit.prevent="login">
|
||||
<label>账号<input v-model="loginForm.username" autocomplete="username" /></label>
|
||||
<label>密码<input v-model="loginForm.password" type="password" autocomplete="current-password" /></label>
|
||||
<label>账号<input v-model="loginForm.username" autocomplete="username" :disabled="loginPending" /></label>
|
||||
<label>密码<input v-model="loginForm.password" type="password" autocomplete="current-password" :disabled="loginPending" /></label>
|
||||
<label>
|
||||
验证码
|
||||
<div class="captcha-row">
|
||||
<input v-model="loginForm.captcha" />
|
||||
<button class="captcha-button" type="button" title="刷新验证码" @click="loadCaptcha">
|
||||
<input v-model="loginForm.captcha" :disabled="loginPending" autocomplete="off" />
|
||||
<button class="captcha-button" type="button" title="刷新验证码" :disabled="loginPending" @click="loadCaptcha">
|
||||
<img v-if="captcha?.image" :src="captcha.image" alt="验证码" />
|
||||
<span v-else>刷新</span>
|
||||
</button>
|
||||
</div>
|
||||
</label>
|
||||
<Button class="full" type="submit" label="登录" />
|
||||
<Button class="full" type="submit" :label="loginPending ? '正在登录…' : '登录'" :loading="loginPending" :disabled="loginPending" />
|
||||
</form>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
Reference in New Issue
Block a user