fix: 统一管理后台 401 与加载失败处理

This commit is contained in:
Nixevol
2026-09-30 16:22:48 +08:00
parent 1cb562fb71
commit ed788fbb74
17 changed files with 473 additions and 47 deletions
+35 -11
View File
@@ -2,6 +2,7 @@
import { computed, h, onMounted, reactive, ref } from "vue";
import type { DataTableColumns, DataTableRowKey } from "naive-ui";
import {
NAlert,
NButton,
NDataTable,
NForm,
@@ -21,6 +22,7 @@ import type { UploadCustomRequestOptions } from "naive-ui";
import PageHeader from "@/components/PageHeader.vue";
import HelpTip from "@/components/HelpTip.vue";
import SecretOnceAlert from "@/components/SecretOnceAlert.vue";
import LoadFailed from "@/components/LoadFailed.vue";
import {
batchEndpoints,
createEndpoint,
@@ -41,6 +43,7 @@ import { message } from "@/utils/notify";
const dialog = useDialog();
const loading = ref(false);
const loadError = ref("");
const rows = ref<Endpoint[]>([]);
const total = ref(0);
const checkedKeys = ref<DataTableRowKey[]>([]);
@@ -77,6 +80,7 @@ const createForm = reactive({
default_delay_seconds: 0,
});
const createLoading = ref(false);
const createError = ref("");
const editOpen = ref(false);
const editId = ref("");
@@ -94,6 +98,7 @@ const talkPassword = ref("");
async function load() {
loading.value = true;
loadError.value = "";
try {
const cursor = page.value > 1 ? String((page.value - 1) * pageSize.value) : "";
const res = await listEndpoints({
@@ -105,6 +110,8 @@ async function load() {
});
rows.value = res.items;
total.value = res.total;
} catch (e) {
loadError.value = e instanceof Error ? e.message : "加载失败";
} finally {
loading.value = false;
}
@@ -187,14 +194,12 @@ function openCreate() {
talk_password: "",
default_delay_seconds: 0,
});
createError.value = "";
createOpen.value = true;
}
async function submitCreate() {
if (!createForm.name.trim()) {
message.error("名称不能为空");
return;
}
createError.value = "";
createLoading.value = true;
try {
const res = await createEndpoint({
@@ -212,6 +217,8 @@ async function submitCreate() {
filename: `${res.id}-password.txt`,
};
await load();
} catch (e) {
createError.value = e instanceof ApiError ? e.message : e instanceof Error ? e.message : "开通失败";
} finally {
createLoading.value = false;
}
@@ -252,10 +259,23 @@ function openTalk(r: Endpoint) {
}
async function submitTalk() {
await setTalkPassword(talkId.value, talkPassword.value);
talkOpen.value = false;
message.success(talkPassword.value ? "已设置对话密码" : "已清除对话密码");
await load();
const save = async () => {
await setTalkPassword(talkId.value, talkPassword.value);
talkOpen.value = false;
message.success(talkPassword.value ? "已设置对话密码" : "已清除对话密码");
await load();
};
if (!talkPassword.value) {
dialog.warning({
title: "清除对话密码",
content: "留空保存将清除该端的对话密码,确定继续?",
positiveText: "清除",
negativeText: "取消",
onPositiveClick: () => save(),
});
return;
}
await save();
}
async function onResetPwd(r: Endpoint) {
@@ -360,6 +380,8 @@ function onPageSizeChange(s: number) {
</template>
</PageHeader>
<div class="page-body">
<LoadFailed v-if="loadError" :description="loadError" @retry="load" />
<template v-else>
<SecretOnceAlert
v-if="onceSecret"
:title="onceSecret.title"
@@ -403,16 +425,18 @@ function onPageSizeChange(s: number) {
}"
@update:checked-row-keys="(k) => (checkedKeys = k)"
/>
</template>
</div>
<n-modal v-model:show="createOpen" preset="card" title="开通端" style="width: 520px" :mask-closable="false">
<n-scrollbar style="max-height: 360px">
<n-form label-placement="left" label-width="110" :show-feedback="false">
<n-alert v-if="createError" type="error" :title="createError" style="margin-bottom: 8px" />
<n-form label-placement="left" label-width="110">
<n-form-item label="编号">
<n-input v-model:value="createForm.id" placeholder="留空则生成" data-testid="create-id" />
</n-form-item>
<n-form-item label="名称">
<n-input v-model:value="createForm.name" data-testid="create-name" />
<n-input v-model:value="createForm.name" data-testid="create-name" placeholder="可选" />
</n-form-item>
<n-form-item label="登录密码">
<n-input v-model:value="createForm.login_password" placeholder="留空则生成" type="password" show-password-on="click" />
@@ -464,7 +488,7 @@ function onPageSizeChange(s: number) {
<n-modal v-model:show="talkOpen" preset="card" title="设置对话密码" style="width: 420px">
<n-form label-placement="left" label-width="90" :show-feedback="false">
<n-form-item label="对话密码">
<n-input v-model:value="talkPassword" type="password" show-password-on="click" placeholder="留空表示清除" />
<n-input v-model:value="talkPassword" type="password" show-password-on="click" placeholder="4–64 字符,留空表示清除" />
</n-form-item>
</n-form>
<template #footer>