"use client"; /** * 研究资料查询:自然语言问题 → 生成检索式 → 在选定来源检索 → 总结 / 生成引用。 */ import { useState } from "react"; import { Search } from "lucide-react"; import { CredibilityBadge, InfoRow, RawDetails } from "@/components/display"; import { ErrorBanner, Loading, PageHeading } from "@/components/feedback"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Textarea } from "@/components/ui/textarea"; import { UsageGuide } from "@/components/usage-guide"; import { ApiError } from "@/lib/api"; import { researchApi } from "@/lib/services"; import type { Citation, SearchQuery, Summary } from "@/lib/types"; import { cn } from "@/lib/utils"; /* eslint-disable @typescript-eslint/no-explicit-any */ const SOURCES: { value: string; label: string }[] = [ { value: "PUBMED", label: "PubMed" }, { value: "CNKI", label: "中国知网" }, { value: "WANFANG", label: "万方数据" }, { value: "UPTODATE", label: "UpToDate" }, { value: "COCHRANE", label: "Cochrane" }, ]; /** 证据分级 → 配色(越强越绿)。 */ function evidenceVariant( level: string, ): "success" | "info" | "warning" | "muted" { if (level.startsWith("1")) return "success"; if (level.startsWith("2")) return "info"; if (level.startsWith("3") || level === "4") return "warning"; return "muted"; } export default function ResearchPage() { const [question, setQuestion] = useState(""); const [searchQuery, setSearchQuery] = useState(null); const [selectedSources, setSelectedSources] = useState(["PUBMED"]); const [results, setResults] = useState(null); const [summary, setSummary] = useState(null); const [citations, setCitations] = useState(null); const [busy, setBusy] = useState(false); const [error, setError] = useState(null); async function run(fn: () => Promise, after?: (v: T) => void) { setError(null); setBusy(true); try { after?.(await fn()); } catch (err) { setError(err instanceof ApiError ? err.message : "操作失败"); } finally { setBusy(false); } } const items: any[] = results?.page?.items ?? results?.items ?? []; function toggleSource(val: string) { setSelectedSources((prev) => prev.includes(val) ? prev.filter((x) => x !== val) : [...prev, val], ); } return (
} title="循证检索" description="按 PICO 框架将临床问题转为专业检索式,检索医学数据库、总结证据并生成规范引用。" /> ① 生成检索式