fix: 校正一次性密码展示与 CSV 下载

This commit is contained in:
Nixevol
2026-09-30 16:22:49 +08:00
parent ed788fbb74
commit 15802bf706
9 changed files with 270 additions and 35 deletions
+34 -13
View File
@@ -38,6 +38,7 @@ import {
} from "@/api/admin";
import { ApiError } from "@/api/http";
import { formatLocalMs } from "@/utils/time";
import { buildPasswordCsv, downloadText } from "@/utils/csv";
import { message } from "@/utils/notify";
const dialog = useDialog();
@@ -67,7 +68,7 @@ const onlineOptions = [
{ label: "离线", value: "false" },
];
const onceSecret = ref<{ title: string; secret: string; filename: string } | null>(null);
const onceSecret = ref<{ title: string; secret: string; filename: string; mime?: string } | null>(null);
const importResult = ref<ImportItem[] | null>(null);
const createOpen = ref(false);
@@ -211,11 +212,15 @@ async function submitCreate() {
default_delay_seconds: createForm.default_delay_seconds,
});
createOpen.value = false;
onceSecret.value = {
title: "开通成功,登录密码只显示一次",
secret: `${res.id}\t${res.login_password}`,
filename: `${res.id}-password.txt`,
};
if (res.login_password) {
onceSecret.value = {
title: "开通成功,登录密码只显示一次",
secret: `${res.id}\t${res.login_password}`,
filename: `${res.id}-password.txt`,
};
} else {
message.success(`已开通 ${res.id}`);
}
await load();
} catch (e) {
createError.value = e instanceof ApiError ? e.message : e instanceof Error ? e.message : "开通失败";
@@ -337,11 +342,15 @@ async function onImport(options: UploadCustomRequestOptions) {
const text = await raw.text();
const res = await importEndpoints(text);
importResult.value = res.items;
onceSecret.value = {
title: "CSV 导入成功,密码只显示一次",
secret: res.items.map((i) => `${i.id},${i.name},${i.login_password}`).join("\n"),
filename: "import-passwords.csv",
};
const pwdRows = res.items.filter((i): i is ImportItem & { login_password: string } => Boolean(i.login_password));
if (pwdRows.length) {
onceSecret.value = {
title: "CSV 导入成功,密码只显示一次",
secret: buildPasswordCsv(pwdRows),
filename: "import-passwords.csv",
mime: "text/csv;charset=utf-8",
};
}
options.onFinish();
await load();
} catch (e) {
@@ -355,6 +364,16 @@ async function onImport(options: UploadCustomRequestOptions) {
}
}
function downloadImportCsv() {
if (!importResult.value?.length) {
return;
}
const pwdRows = importResult.value.filter((i): i is ImportItem & { login_password: string } =>
Boolean(i.login_password),
);
downloadText("import-passwords.csv", buildPasswordCsv(pwdRows), "text/csv;charset=utf-8");
}
function onPageChange(p: number) {
page.value = p;
void load();
@@ -387,6 +406,7 @@ function onPageSizeChange(s: number) {
:title="onceSecret.title"
:secret="onceSecret.secret"
:filename="onceSecret.filename"
:mime="onceSecret.mime"
@dismiss="onceSecret = null"
/>
<n-space style="margin-bottom: 12px" align="center">
@@ -439,7 +459,7 @@ function onPageSizeChange(s: number) {
<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" />
<n-input v-model:value="createForm.login_password" placeholder="留空则生成" type="password" show-password-on="click" data-testid="create-login-password" />
</n-form-item>
<n-form-item label="对话密码">
<n-input v-model:value="createForm.talk_password" placeholder="可选" type="password" show-password-on="click" />
@@ -502,10 +522,11 @@ function onPageSizeChange(s: number) {
<n-modal v-if="importResult" :show="true" preset="card" title="导入结果" style="width: 560px" @update:show="(v) => !v && (importResult = null)">
<n-scrollbar style="max-height: 280px">
<n-text depth="3">以下密码仅本次可见,请下载保存。</n-text>
<pre style="font-size: 12px; white-space: pre-wrap">{{ importResult.map((i) => `${i.id}\t${i.name}\t${i.login_password}`).join("\n") }}</pre>
<pre style="font-size: 12px; white-space: pre-wrap">{{ importResult.map((i) => `${i.id}\t${i.name}\t${i.login_password ?? ""}`).join("\n") }}</pre>
</n-scrollbar>
<template #footer>
<n-space justify="end">
<n-button @click="downloadImportCsv">下载</n-button>
<n-button @click="importResult = null">关闭</n-button>
</n-space>
</template>