修正首页的内容
This commit is contained in:
parent
a6f2895dad
commit
4ea47541e9
@ -309,10 +309,13 @@ async def get_available_sources(market: str):
|
||||
|
||||
@router.get("/recent", response_model=List[dict])
|
||||
async def get_recent_companies(
|
||||
data_source: str = "Bloomberg",
|
||||
data_source: str = None,
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
"""获取最近更新的公司列表"""
|
||||
"""获取最近更新的公司列表
|
||||
|
||||
如果不指定 data_source,将返回所有数据源的最近更新。
|
||||
"""
|
||||
return await data_fetcher_service.get_recent_companies(
|
||||
data_source=data_source,
|
||||
db=db,
|
||||
|
||||
@ -492,24 +492,28 @@ def get_available_data_sources(market: str) -> List[Dict]:
|
||||
return sources
|
||||
|
||||
async def get_recent_companies(
|
||||
data_source: str,
|
||||
data_source: Optional[str],
|
||||
db: AsyncSession,
|
||||
limit: int = 20
|
||||
) -> List[Dict]:
|
||||
"""获取指定数据源下最近更新的公司"""
|
||||
"""获取最近更新的公司列表
|
||||
|
||||
Args:
|
||||
data_source: 可选的数据源过滤。如果为None,则返回所有数据源的最近更新。
|
||||
db: 数据库会话
|
||||
limit: 返回数量限制
|
||||
"""
|
||||
query = (
|
||||
select(Company, DataUpdate.completed_at)
|
||||
select(Company, DataUpdate.completed_at, DataUpdate.data_source)
|
||||
.join(DataUpdate, Company.id == DataUpdate.company_id)
|
||||
.where(
|
||||
and_(
|
||||
DataUpdate.data_source == data_source,
|
||||
DataUpdate.status == 'completed'
|
||||
)
|
||||
)
|
||||
.where(DataUpdate.status == 'completed')
|
||||
.order_by(DataUpdate.completed_at.desc())
|
||||
.limit(limit * 3) # Fetch more to handle duplicates
|
||||
.limit(limit * 5) # Fetch more to handle duplicates
|
||||
)
|
||||
|
||||
if data_source:
|
||||
query = query.where(DataUpdate.data_source == data_source)
|
||||
|
||||
result = await db.execute(query)
|
||||
rows = result.all()
|
||||
|
||||
@ -517,13 +521,14 @@ async def get_recent_companies(
|
||||
companies = []
|
||||
|
||||
for row in rows:
|
||||
company, completed_at = row
|
||||
company, completed_at, source = row
|
||||
if company.id not in seen_ids:
|
||||
seen_ids.add(company.id)
|
||||
companies.append({
|
||||
"market": company.market,
|
||||
"symbol": company.symbol,
|
||||
"company_name": company.company_name,
|
||||
"data_source": source,
|
||||
"last_update": completed_at.strftime('%Y-%m-%d %H:%M') if completed_at else ""
|
||||
})
|
||||
if len(companies) >= limit:
|
||||
|
||||
@ -116,7 +116,7 @@ export default function Home() {
|
||||
</div>
|
||||
|
||||
{/* 历史记录 */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div className="w-full">
|
||||
<HistoryList onSelect={handleCompanySelect} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
"use client"
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
import { getReports } from "@/lib/api"
|
||||
import { getRecentCompanies } from "@/lib/api"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"
|
||||
import { Loader2 } from "lucide-react"
|
||||
import { Loader2, Database } from "lucide-react"
|
||||
import type { SearchResult } from "@/lib/types"
|
||||
|
||||
interface HistoryListProps {
|
||||
@ -12,59 +10,50 @@ interface HistoryListProps {
|
||||
}
|
||||
|
||||
export function HistoryList({ onSelect }: HistoryListProps) {
|
||||
const [reports, setReports] = useState<any[]>([])
|
||||
const [companies, setCompanies] = useState<any[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
getReports().then(setReports).catch(console.error).finally(() => setLoading(false))
|
||||
getRecentCompanies().then(setCompanies).catch(console.error).finally(() => setLoading(false))
|
||||
}, [])
|
||||
|
||||
if (loading) return <Loader2 className="animate-spin text-muted-foreground" />
|
||||
|
||||
if (reports.length === 0) return <div className="text-muted-foreground">没有找到历史记录。</div>
|
||||
if (companies.length === 0) return <div className="text-muted-foreground">没有找到最近的数据记录。</div>
|
||||
|
||||
return (
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
{reports.map((report: any) => (
|
||||
<div className="grid gap-4 grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5">
|
||||
{companies.map((company: any, index: number) => (
|
||||
<Card
|
||||
key={report.id}
|
||||
key={`${company.symbol}-${index}`}
|
||||
className="hover:shadow-lg transition-shadow cursor-pointer"
|
||||
onClick={() => {
|
||||
if (onSelect) {
|
||||
onSelect({
|
||||
symbol: report.symbol,
|
||||
market: report.market,
|
||||
company_name: report.company_name
|
||||
}, report.data_source)
|
||||
symbol: company.symbol,
|
||||
market: company.market,
|
||||
company_name: company.company_name
|
||||
}, company.data_source)
|
||||
}
|
||||
}}
|
||||
>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg">{report.company_name}</CardTitle>
|
||||
<CardHeader className="pb-2">
|
||||
<div className="flex justify-between items-start">
|
||||
<CardTitle className="text-lg">{company.company_name}</CardTitle>
|
||||
<Badge variant="outline">{company.market}</Badge>
|
||||
</div>
|
||||
<CardDescription>
|
||||
{report.market} {report.symbol}
|
||||
{company.symbol}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{new Date(report.created_at).toLocaleString('zh-CN')}
|
||||
</span>
|
||||
<Badge variant={
|
||||
report.status === "completed" ? "default" :
|
||||
report.status === "in_progress" ? "secondary" :
|
||||
report.status === "failed" ? "destructive" : "outline"
|
||||
}>
|
||||
{report.status === "completed" ? "已完成" :
|
||||
report.status === "in_progress" ? "进行中" :
|
||||
report.status === "failed" ? "失败" : "待处理"}
|
||||
</Badge>
|
||||
<div className="flex items-center justify-between text-sm text-muted-foreground">
|
||||
<span>{company.last_update}</span>
|
||||
<div className="flex items-center gap-1">
|
||||
<Database className="w-3 h-3" />
|
||||
<span>{company.data_source}</span>
|
||||
</div>
|
||||
{report.ai_model && (
|
||||
<div className="mt-2 text-xs text-muted-foreground">
|
||||
模型: {report.ai_model}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
|
||||
@ -163,6 +163,19 @@ export async function getAnalysisHistory(
|
||||
return res.json()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最近更新的公司列表
|
||||
*/
|
||||
export async function getRecentCompanies(dataSource?: string): Promise<any[]> {
|
||||
let url = `${API_BASE}/data/recent`
|
||||
if (dataSource) {
|
||||
url += `?data_source=${dataSource}`
|
||||
}
|
||||
const res = await fetch(url)
|
||||
if (!res.ok) throw new Error("Failed to fetch recent companies")
|
||||
return res.json()
|
||||
}
|
||||
|
||||
// ========== 兼容性函数 ==========
|
||||
/**
|
||||
* 获取所有分析报告(兼容旧API)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user