fix(resource/api-keys): 编辑后复制当前凭证并清空旧显示状态

This commit is contained in:
lanrtop 2026-09-23 21:16:41 +09:00
parent 47ff656083
commit 6d512fb0ad
2 changed files with 33 additions and 3 deletions

View File

@ -0,0 +1,21 @@
import { describe, expect, it } from "vitest";
import { copyCurrentApiKey } from "./ApiKeysPanel";
describe("copyCurrentApiKey", () => {
it("reads the current credential instead of reusing a previously revealed value", async () => {
let current = "synthetic-old-key";
let copied = "";
const reveal = async (id: string) => {
expect(id).toBe("k1");
return current;
};
const write = async (value: string) => { copied = value; };
await copyCurrentApiKey("k1", reveal, write);
expect(copied).toBe("synthetic-old-key");
current = "synthetic-new-key";
await copyCurrentApiKey("k1", reveal, write);
expect(copied).toBe("synthetic-new-key");
});
});

View File

@ -18,6 +18,14 @@ const PROVIDERS = [
{ value: "custom", label: "自定义", color: "bg-gray-100 text-gray-600 border-gray-200" },
];
export async function copyCurrentApiKey(
id: string,
reveal: (id: string) => Promise<string>,
write: (value: string) => Promise<void>,
): Promise<void> {
await write(await reveal(id));
}
function getProviderStyle(provider: string) {
return PROVIDERS.find((p) => p.value === provider)?.color ?? PROVIDERS[PROVIDERS.length - 1].color;
}
@ -144,7 +152,7 @@ function ApiKeyCard({ item, onEdit, onDelete }: {
};
const copy = async () => {
try {
await navigator.clipboard.writeText(secret ?? await revealApiKey(item.id));
await copyCurrentApiKey(item.id, revealApiKey, (value) => navigator.clipboard.writeText(value));
setError(undefined);
} catch (cause) {
setError(String(cause));
@ -249,6 +257,7 @@ export function ApiKeysPanel() {
const [showModal, setShowModal] = useState(false);
const [editingItem, setEditingItem] = useState<(ApiKey & { api_key: string }) | null>(null);
const [editError, setEditError] = useState<string>();
const [keyRevision, setKeyRevision] = useState(0);
const { data: keys = [] } = useQuery({
queryKey: ["api-keys"],
@ -262,7 +271,7 @@ export function ApiKeysPanel() {
const editMut = useMutation({
mutationFn: ({ id, input }: { id: string; input: SaveApiKeyInput }) => editApiKey(id, input),
onSuccess: () => { qc.invalidateQueries({ queryKey: ["api-keys"] }); setEditingItem(null); },
onSuccess: () => { setKeyRevision((revision) => revision + 1); qc.invalidateQueries({ queryKey: ["api-keys"] }); setEditingItem(null); },
});
const deleteMut = useMutation({
@ -299,7 +308,7 @@ export function ApiKeysPanel() {
{keys.map((k) => (
<ApiKeyCard
key={k.id}
key={`${k.id}:${keyRevision}`}
item={k}
onEdit={() => { void (async () => {
try {