Initial MVP for QA asset backend
This commit is contained in:
93
hy_qa_asset_backend/frontend/app/dashboard/page.tsx
Normal file
93
hy_qa_asset_backend/frontend/app/dashboard/page.tsx
Normal file
@@ -0,0 +1,93 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { useEffect, useState } from "react";
|
||||
import { AlertTriangle, CheckCircle2, Database, FileQuestion, Library, Play, Rows3, Timer } from "lucide-react";
|
||||
import { api, formatDateTime } from "@/lib/api";
|
||||
import type { DashboardSummary, TaskRun } from "@/lib/types";
|
||||
import StatCard from "@/components/StatCard";
|
||||
import StatusBadge from "@/components/StatusBadge";
|
||||
|
||||
export default function DashboardPage() {
|
||||
const [summary, setSummary] = useState<DashboardSummary | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [running, setRunning] = useState(false);
|
||||
|
||||
async function load() {
|
||||
setLoading(true);
|
||||
const data = await api.get<DashboardSummary>("/dashboard/summary");
|
||||
setSummary(data);
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
async function runTask() {
|
||||
setRunning(true);
|
||||
await api.post<TaskRun>("/tasks/run-now", {});
|
||||
await load();
|
||||
setRunning(false);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
load().catch(() => setLoading(false));
|
||||
}, []);
|
||||
|
||||
if (loading || !summary) {
|
||||
return <div className="text-sm text-slate-500">加载中...</div>;
|
||||
}
|
||||
|
||||
const actions = [
|
||||
{ href: "/review", label: "去审核" },
|
||||
{ href: "/high-risk", label: "查看高风险" },
|
||||
{ href: "/standard-qa", label: "查看标准问答库" },
|
||||
{ href: "/logs", label: "查看运行日志" }
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="flex flex-wrap items-center justify-between gap-3">
|
||||
<div>
|
||||
<h1 className="text-2xl font-semibold text-ink">仪表盘</h1>
|
||||
<p className="mt-1 text-sm text-slate-500">最近任务:{summary.last_task_time ? formatDateTime(summary.last_task_time) : "-"}</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={runTask}
|
||||
disabled={running}
|
||||
className="inline-flex h-10 items-center gap-2 rounded-md bg-jade px-4 text-sm font-medium text-white hover:bg-teal-800 disabled:opacity-60"
|
||||
>
|
||||
<Play className="h-4 w-4" aria-hidden />
|
||||
{running ? "处理中" : "手动触发处理任务"}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
|
||||
<StatCard title="昨晚处理答疑场次数" value={summary.processed_sessions} icon={<Timer className="h-5 w-5" />} />
|
||||
<StatCard title="已拆解问答总数" value={summary.pending_review_count + summary.approved_qa_count} icon={<Rows3 className="h-5 w-5" />} tone="indigo" />
|
||||
<StatCard title="待审核问答数" value={summary.pending_review_count} icon={<FileQuestion className="h-5 w-5" />} tone="amber" />
|
||||
<StatCard title="高风险问答数" value={summary.high_risk_count} icon={<AlertTriangle className="h-5 w-5" />} tone="rose" />
|
||||
<StatCard title="已审核问答数" value={summary.approved_qa_count} icon={<CheckCircle2 className="h-5 w-5" />} />
|
||||
<StatCard title="标准问答数" value={summary.standard_qa_count} icon={<Library className="h-5 w-5" />} tone="indigo" />
|
||||
<StatCard title="可被智能体调用问答数" value={summary.callable_qa_count} icon={<Database className="h-5 w-5" />} />
|
||||
<div className="rounded-md border border-line bg-white p-4">
|
||||
<div className="text-sm text-slate-500">最近一次任务状态</div>
|
||||
<div className="mt-3">
|
||||
{summary.last_task_status ? <StatusBadge status={summary.last_task_status} /> : <span className="text-sm text-slate-400">暂无任务</span>}
|
||||
</div>
|
||||
{summary.last_task_error ? <p className="mt-3 text-sm text-rose-700">{summary.last_task_error}</p> : null}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{actions.map((action) => (
|
||||
<Link
|
||||
key={action.href}
|
||||
href={action.href}
|
||||
className="inline-flex h-10 items-center rounded-md border border-line bg-white px-4 text-sm font-medium text-ink hover:bg-slate-50"
|
||||
>
|
||||
{action.label}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user