feat(characters): use local character catalog

This commit is contained in:
2026-07-17 16:03:18 +08:00
parent a210a98d98
commit b3ebd5cf3b
96 changed files with 1023 additions and 522 deletions
@@ -1,45 +0,0 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
const httpClientMock = vi.hoisted(() => vi.fn());
vi.mock("../http_client", () => ({
httpClient: httpClientMock,
}));
import { CharacterApi } from "../character_api";
describe("CharacterApi", () => {
beforeEach(() => {
httpClientMock.mockReset();
});
it("loads characters and preserves the backend order", async () => {
httpClientMock.mockResolvedValue({
success: true,
data: {
items: [
{
id: "character_aria",
slug: "aria",
displayName: "Aria",
avatarUrl: "https://cdn.example.com/aria.jpg",
},
{
id: "character_elio",
slug: "elio",
displayName: "Elio Silvestri",
avatarUrl: "https://cdn.example.com/elio.jpg",
},
],
},
});
const response = await new CharacterApi().getCharacters();
expect(httpClientMock).toHaveBeenCalledWith("/api/characters");
expect(response.items.map((character) => character.id)).toEqual([
"character_aria",
"character_elio",
]);
});
});
+1 -2
View File
@@ -24,6 +24,5 @@
"privateRoomAlbumUnlock": { "method": "post", "path": "/api/private-room/albums/{albumId}/unlock" },
"metricsPwaEvent": { "method": "post", "path": "/api/metrics/pwa/event" },
"reportUserInfo": { "method": "post", "path": "/api/data/report-user-info" },
"feedback": { "method": "post", "path": "/api/feedback" },
"characters": { "method": "get", "path": "/api/characters" }
"feedback": { "method": "post", "path": "/api/feedback" }
}
-2
View File
@@ -99,6 +99,4 @@ export class ApiPath {
// ============ 用户反馈相关 ============
static readonly feedback = apiContract.feedback.path;
// ============ 角色相关 ============
static readonly characters = apiContract.characters.path;
}
-17
View File
@@ -1,17 +0,0 @@
import {
CharactersResponse,
CharactersResponseSchema,
} from "@/data/schemas/character";
import { ApiPath } from "./api_path";
import { httpClient } from "./http_client";
import { type ApiEnvelope, unwrap } from "./response_helper";
export class CharacterApi {
async getCharacters(): Promise<CharactersResponse> {
const envelope = await httpClient<ApiEnvelope<unknown>>(ApiPath.characters);
return CharactersResponseSchema.parse(unwrap(envelope));
}
}
export const characterApi = new CharacterApi();
-1
View File
@@ -6,7 +6,6 @@ export * from "./api_path";
export * from "./api_result";
export * from "./auth_api";
export * from "./chat_api";
export * from "./character_api";
export * from "./feedback_api";
export * from "./http_client";
export * from "./metrics_api";