feat: AI市场分析功能

- 后端:AI分析服务、工具调用、定时任务
- 前端:报告列表、详情页、Mermaid图表支持
- 支持OpenAI API兼容模型
- 收盘后自动分析生成报告
This commit is contained in:
Sakurasan
2026-09-01 04:21:29 +08:00
parent d7d019c2c4
commit 912a224b6b
17 changed files with 2525 additions and 4 deletions
+59
View File
@@ -0,0 +1,59 @@
// AI 分析报告 API 客户端
import { getApiBaseUrl } from "./api-client";
const API_BASE = getApiBaseUrl();
export interface AiReport {
id: number;
trade_date: string;
report_type: string;
title: string;
content: string;
summary: string | null;
toolsUsed: string[];
model: string;
tokens_used: number;
created_at: string;
}
export async function fetchAiReports(): Promise<AiReport[]> {
const resp = await fetch(`${API_BASE}/api/ai-analysis`);
if (!resp.ok) throw new Error(`请求失败 (${resp.status})`);
const result = await resp.json();
return result.data || [];
}
export async function fetchAiReport(id: number): Promise<AiReport> {
const resp = await fetch(`${API_BASE}/api/ai-analysis/${id}`);
if (!resp.ok) throw new Error(`请求失败 (${resp.status})`);
const result = await resp.json();
return result.data;
}
export async function checkAiReport(tradeDate: string): Promise<boolean> {
const resp = await fetch(`${API_BASE}/api/ai-analysis/check/${tradeDate}`);
if (!resp.ok) return false;
const result = await resp.json();
return result.data?.hasReport || false;
}
export async function triggerAiAnalysis(): Promise<{ id: number; tokens_used: number }> {
const resp = await fetch(`${API_BASE}/api/ai-analysis/trigger`, { method: "POST" });
if (!resp.ok) {
const err = await resp.json().catch(() => ({}));
throw new Error(err.detail || "触发失败");
}
const result = await resp.json();
return result.data;
}
export async function regenerateAiReport(id: number): Promise<{ id: number; tokens_used: number }> {
const resp = await fetch(`${API_BASE}/api/ai-analysis/${id}/regenerate`, { method: "POST" });
if (!resp.ok) {
const err = await resp.json().catch(() => ({}));
throw new Error(err.detail || "重新生成失败");
}
const result = await resp.json();
return result.data;
}