feat(admin): 补全平台任务观测 + 空间管理 + 基建加 MinIO/实时探针
对照已实现系统功能补 admin 缺失模块(feat/site): - 全平台任务/运行观测:GET /admin/tasks(跨租户查 sundynix_task,join 租户名/提交人邮箱/评测, 按状态/租户筛 + 状态计数;含 HITL 待审批=筛 waiting)+ TasksPage(状态卡+筛+表)。 - 空间(Space)管理:GET /admin/spaces(跨租户列 Space + 成员数子查询 + kind/归档态)+ SpacesPage。 - 基建观测:infra 加 MinIO(126 对象存储);postgres/redis/minio 从启动标志升级为实时 ping (blob.Ping/Postgres.Ping/Redis.Ping),能反映中途掉线。StatusPage 加 minio 标签、6 个依赖。 - 模型健康/熔断:确认 DashboardPage 已有「运行时链路态」渲染 m.health,无需重做。 验证:admin tsc + vitest 41 过、gateway build/vet/test 过;两新页浏览器实测渲染+优雅错误处理; 两新端点起临时 gateway 打真 PG 实测——tasks(counts+3路join)、spaces(成员数子查询)均返真数据。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -314,6 +314,58 @@ export async function adminRefundOrder(id: string, memo: string): Promise<{ stat
|
||||
return { status: d.status ?? "", detail: d.detail };
|
||||
}
|
||||
|
||||
// ---- 全平台任务/运行观测(管理端,来自 sundynix_task 跨租户)----
|
||||
export interface AdminTask {
|
||||
task_id: string;
|
||||
tenant_id: string;
|
||||
tenant_name: string;
|
||||
owner: string;
|
||||
owner_email: string;
|
||||
status: string;
|
||||
detail: string;
|
||||
topic: string;
|
||||
at: string; // RFC3339
|
||||
eval_level: string;
|
||||
eval_overall: number;
|
||||
}
|
||||
|
||||
// adminTasks 全平台任务流 + 状态计数。status 空=全部;tenant 空=全租户;含 HITL 待审批(status=waiting)。
|
||||
export async function adminTasks(
|
||||
status = "",
|
||||
tenant = "",
|
||||
limit = 50,
|
||||
): Promise<{ tasks: AdminTask[]; counts: Record<string, number> }> {
|
||||
const q = new URLSearchParams();
|
||||
if (status) q.set("status", status);
|
||||
if (tenant) q.set("tenant", tenant);
|
||||
q.set("limit", String(limit));
|
||||
const res = guard(await fetch(`${ADMIN}/tasks?${q.toString()}`, { headers: authHeaders() }));
|
||||
const d = (await res.json().catch(() => ({}))) as { tasks?: AdminTask[]; counts?: Record<string, number>; error?: string };
|
||||
if (!res.ok) throw new Error(d.error ?? `tasks failed: ${res.status}`);
|
||||
return { tasks: d.tasks ?? [], counts: d.counts ?? {} };
|
||||
}
|
||||
|
||||
// ---- 全平台空间(Space)观测(管理端,跨租户 sundynix_space)----
|
||||
export interface AdminSpace {
|
||||
id: string;
|
||||
tenant_id: string;
|
||||
tenant_name: string;
|
||||
name: string;
|
||||
kind: string; // personal / project / tenant
|
||||
creator: string;
|
||||
creator_email: string;
|
||||
archived: boolean;
|
||||
members: number;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export async function adminSpaces(limit = 200): Promise<AdminSpace[]> {
|
||||
const res = guard(await fetch(`${ADMIN}/spaces?limit=${limit}`, { headers: authHeaders() }));
|
||||
const d = (await res.json().catch(() => ({}))) as { spaces?: AdminSpace[]; error?: string };
|
||||
if (!res.ok) throw new Error(d.error ?? `spaces failed: ${res.status}`);
|
||||
return d.spaces ?? [];
|
||||
}
|
||||
|
||||
// ---- 自动评测观测(真数据,来自 sundynix_eval)----
|
||||
export interface EvalDay {
|
||||
day: string; // YYYYMMDD
|
||||
|
||||
Reference in New Issue
Block a user