refactor: 统一管理页面布局 — FilterToolbar + usePageSearchParams + parseListParams

This commit is contained in:
2026-06-04 17:25:36 +08:00
parent 61b479e2be
commit 6f547560d1
40 changed files with 1805 additions and 628 deletions

View File

@@ -130,6 +130,48 @@ describe("models API routes", () => {
});
});
test("GET /api/models sortBy + sortOrder", async () => {
await withRouteDb(async (db) => {
const p = seedProvider(db, "SortP");
createTestModel(db, "Beta", p);
createTestModel(db, "Alpha", p);
const req = new Request("http://localhost/api/models?page=1&pageSize=20&sortBy=name&sortOrder=asc");
const res = await listModelsViaHandler(req, db);
expect(res.status).toBe(200);
const body = (await res.json()) as { items: Model[] };
expect(body.items[0]!.name).toBe("Alpha");
expect(body.items[1]!.name).toBe("Beta");
});
});
test("GET /api/models filter by capabilities", async () => {
await withRouteDb(async (db) => {
const p = seedProvider(db, "CapP");
createModel(db, { capabilities: ["text"], modelId: "text-1", name: "TextModel", providerId: p }, LOG);
createModel(
db,
{ capabilities: ["reasoning"], modelId: "reasoning-1", name: "ReasoningModel", providerId: p },
LOG,
);
const req = new Request("http://localhost/api/models?page=1&pageSize=20&capabilities=text");
const res = await listModelsViaHandler(req, db);
expect(res.status).toBe(200);
const body = (await res.json()) as { items: Model[]; total: number };
expect(body.total).toBe(1);
expect(body.items[0]!.name).toBe("TextModel");
});
});
test("GET /api/models rejects invalid sortBy", async () => {
await withRouteDb(async (db) => {
const req = new Request("http://localhost/api/models?page=1&pageSize=20&sortBy=evil");
const res = await listModelsViaHandler(req, db);
expect(res.status).toBe(400);
});
});
test("GET /api/models filter by providerId", async () => {
await withRouteDb(async (db) => {
const p1 = seedProvider(db, "P1");