feat: integrate chatbox research with datasets and backtests

This commit is contained in:
yuxuanhui
2026-09-08 12:43:00 +08:00
parent 43336ad960
commit aef8e1d310
37 changed files with 1421 additions and 42 deletions
+83 -2
View File
@@ -26,6 +26,7 @@ import {
queryString,
} from "../api";
import type { Account, Job } from "../types";
import type { PageContext, UIAction } from "../ai/types";
import "./dataset.css";
type Scope = {
@@ -66,6 +67,7 @@ type Draft = {
dataset_id: string;
scope: Scope;
field_ids: string[];
field_types: Record<string, string | null>;
collection_version: string;
selection: string;
created_at: string;
@@ -114,6 +116,8 @@ export function DatasetPage({
onTask,
onModal,
onChat,
onContext,
action,
}: {
account: Account | null;
version: string;
@@ -123,6 +127,8 @@ export function DatasetPage({
onTask: () => void;
onModal: (value: boolean) => void;
onChat: () => void;
onContext: (context: PageContext) => void;
action: UIAction | null;
}) {
const [scope, setScope] = useState<Scope>({
instrument_type: "EQUITY",
@@ -185,6 +191,61 @@ export function DatasetPage({
);
const total = selected?.complete_count ?? 0;
const chosen = Math.max(0, total - excluded.size);
const contextDraft = inputOpen ? draft : null;
useEffect(() => {
if (!active) return;
onContext({
page: "datasets",
catalog_scope: contextDraft?.scope ?? scope,
dataset_id: contextDraft?.dataset_id ?? selected?.id,
field_id: contextDraft ? undefined : detail?.field,
collection_version:
contextDraft?.collection_version ??
selected?.collection_version ??
undefined,
template_input_id: contextDraft?.id,
unsaved_field_selection: !contextDraft && excluded.size > 0,
});
}, [
active,
scopeQuery,
contextDraft,
selected?.id,
selected?.collection_version,
detail?.field,
excluded.size,
onContext,
]);
useEffect(() => {
if (action?.type !== "open_research_input") return;
let live = true;
void api<Draft>(`/catalog/inputs/${encode(action.input_id)}`)
.then((saved) => {
if (!live) return;
changeScope(saved.scope);
setDraft(saved);
setInputOpen(true);
})
.catch((e) => {
if (live) setError(e.message);
});
return () => {
live = false;
};
}, [action]);
const researchInput = (saved: Draft) => {
setDraft(saved);
setHistoryOpen(false);
setInputOpen(true);
onContext({
page: "datasets",
catalog_scope: saved.scope,
dataset_id: saved.dataset_id,
collection_version: saved.collection_version,
template_input_id: saved.id,
});
onChat();
};
const top = historyOpen
? "history"
: inputOpen
@@ -1131,6 +1192,11 @@ export function DatasetPage({
保存输入草稿
</Button>
)}
{draft && (
<Button theme="solid" onClick={() => researchInput(draft)}>
用此输入研究
</Button>
)}
</div>
<div className="catalog-details-body">
<h2>{draft ? "输入草稿已保存" : selected?.name}</h2>
@@ -1140,10 +1206,24 @@ export function DatasetPage({
: `${preparation.current?.count} 个字段`}
</p>
<p>
{scope.region} · {scope.universe} · Delay {scope.delay}
{(draft?.scope ?? scope).region} ·{" "}
{(draft?.scope ?? scope).universe} · Delay{" "}
{(draft?.scope ?? scope).delay}
</p>
<p>模板消费方尚未接入</p>
<p>保存后可交给 Chatbox 研究,构建候选并预览回测。</p>
{draft && <p>草稿 ID:{draft.id}</p>}
{draft && (
<details>
<summary>查看固定字段集合</summary>
<p>
{draft.field_ids
.map(
(id) => `${id} (${draft.field_types[id] ?? "类型未知"})`,
)
.join(", ")}
</p>
</details>
)}
<p>
集合版本:
{draft?.collection_version ?? preparation.current?.version}
@@ -1177,6 +1257,7 @@ export function DatasetPage({
{d.scope.delay}
</p>
<p>{formatTime(d.created_at, account?.timezone)}</p>
<Button onClick={() => researchInput(d)}>用此输入研究</Button>
<details>
<summary>查看固定字段集合</summary>
<p>{d.field_ids.join(", ")}</p>