172 lines
5.1 KiB
TypeScript
172 lines
5.1 KiB
TypeScript
import { ResearchList, ResearchDetail } from "./ResearchList";
|
|
import { useEffect, useState } from "react";
|
|
import { Banner, Button, Pagination, Table } from "@douyinfe/semi-ui-19";
|
|
import { api, formatTime } from "../api";
|
|
import type { PageContext, UIAction } from "../ai/types";
|
|
import { FlowLaunchForm } from "./FlowLaunchForm";
|
|
import { FlowRunView } from "./FlowRunView";
|
|
import type { FlowRun } from "./flowTypes";
|
|
import { flowStatus } from "./flowTypes";
|
|
import "./workspace.css";
|
|
export function PipelinePage({
|
|
active,
|
|
onAction,
|
|
onContext,
|
|
}: {
|
|
active: boolean;
|
|
onAction: (a: UIAction) => void;
|
|
onContext: (c: PageContext) => void;
|
|
}) {
|
|
const [items, setItems] = useState<FlowRun[]>([]);
|
|
const [total, setTotal] = useState(0);
|
|
const [page, setPage] = useState(1);
|
|
const [selected, setSelected] = useState<string | null>(() =>
|
|
localStorage.getItem("research-selected-flow"),
|
|
);
|
|
const [run, setRun] = useState<FlowRun | null>(null);
|
|
const [creating, setCreating] = useState(false);
|
|
const [detailOpen, setDetailOpen] = useState(false);
|
|
const [revision, setRevision] = useState(0);
|
|
const [error, setError] = useState("");
|
|
useEffect(() => {
|
|
if (active) onContext({ page: "pipeline", research_run_id: selected });
|
|
}, [active, selected, onContext]);
|
|
useEffect(() => {
|
|
if (!active) return;
|
|
const c = new AbortController();
|
|
let timer: ReturnType<typeof setTimeout>;
|
|
async function refresh() {
|
|
try {
|
|
const list = await api<{ items: FlowRun[]; total: number }>(
|
|
`/research/flows/runs?kind=pipeline&offset=${(page - 1) * 25}`,
|
|
{ signal: c.signal },
|
|
);
|
|
setItems(list.items);
|
|
setTotal(list.total);
|
|
if (selected)
|
|
setRun(
|
|
await api(`/research/flows/runs/${selected}`, { signal: c.signal }),
|
|
);
|
|
setError("");
|
|
} catch (e) {
|
|
if (!c.signal.aborted) setError((e as Error).message);
|
|
} finally {
|
|
if (!c.signal.aborted) timer = setTimeout(() => void refresh(), 1500);
|
|
}
|
|
}
|
|
void refresh();
|
|
return () => {
|
|
c.abort();
|
|
clearTimeout(timer);
|
|
};
|
|
}, [active, page, selected, revision]);
|
|
function select(id: string) {
|
|
setRun(null);
|
|
setDetailOpen(true);
|
|
setSelected(id);
|
|
localStorage.setItem("research-selected-flow", id);
|
|
setCreating(false);
|
|
}
|
|
return (
|
|
<section className="research-workspace research-list-page">
|
|
{error && !detailOpen && <Banner type="danger" description={error} />}
|
|
<ResearchList
|
|
resetKey={JSON.stringify([page])}
|
|
label="研究流水线"
|
|
actions={
|
|
<Button
|
|
theme="solid"
|
|
onClick={() => {
|
|
setCreating(true);
|
|
setDetailOpen(true);
|
|
}}
|
|
>
|
|
新建自动研究
|
|
</Button>
|
|
}
|
|
pagination={
|
|
<>
|
|
<span>共 {total} 次运行</span>
|
|
{total > 0 && (
|
|
<Pagination
|
|
size="small"
|
|
total={total}
|
|
currentPage={page}
|
|
pageSize={25}
|
|
onPageChange={setPage}
|
|
/>
|
|
)}
|
|
</>
|
|
}
|
|
>
|
|
<Table<FlowRun>
|
|
className="research-table"
|
|
dataSource={items}
|
|
rowKey="id"
|
|
pagination={false}
|
|
size="small"
|
|
sticky
|
|
style={{ minWidth: 640 }}
|
|
empty="暂无研究运行,请新建自动研究。"
|
|
columns={[
|
|
{
|
|
title: "研究名称",
|
|
key: "name",
|
|
render: (_, item) => (
|
|
<Button theme="borderless" onClick={() => select(item.id)}>
|
|
{item.name}
|
|
</Button>
|
|
),
|
|
},
|
|
{
|
|
title: "状态",
|
|
key: "status",
|
|
width: 140,
|
|
render: (_, item) => flowStatus[item.status],
|
|
},
|
|
{
|
|
title: "轮次",
|
|
key: "round",
|
|
width: 80,
|
|
render: (_, item) => item.round,
|
|
},
|
|
{
|
|
title: "创建时间",
|
|
key: "created_at",
|
|
width: 190,
|
|
render: (_, item) => formatTime(item.created_at),
|
|
},
|
|
]}
|
|
/>
|
|
</ResearchList>
|
|
<ResearchDetail
|
|
title={creating ? "新建自动研究" : "研究运行详情"}
|
|
visible={active && detailOpen}
|
|
onClose={() => setDetailOpen(false)}
|
|
>
|
|
{error && <Banner type="danger" description={error} />}
|
|
<div className="research-main">
|
|
{creating ? (
|
|
<FlowLaunchForm
|
|
key="new-flow"
|
|
onStarted={(r) => {
|
|
select(r.id);
|
|
setRun(r);
|
|
setRevision((v) => v + 1);
|
|
}}
|
|
/>
|
|
) : (
|
|
run && (
|
|
<FlowRunView
|
|
run={run}
|
|
onRefresh={() => setRevision((v) => v + 1)}
|
|
onAction={onAction}
|
|
/>
|
|
)
|
|
)}
|
|
</div>
|
|
</ResearchDetail>
|
|
</section>
|
|
);
|
|
}
|