diff --git a/.gitignore b/.gitignore
index 3369bad9..118bc9ce 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,11 +1,12 @@
.venv
-results
-env/
-__pycache__/
-.DS_Store
+# Project specific
+/results
*.csv
-src/
+*.json
+*.log
+*.db
+
+# Evaluation results
eval_results/
-eval_data/
*.egg-info/
.env
diff --git a/frontend/app/analysis/page.tsx b/frontend/app/analysis/page.tsx
index 32f6e80b..6c5f06d2 100644
--- a/frontend/app/analysis/page.tsx
+++ b/frontend/app/analysis/page.tsx
@@ -4,15 +4,20 @@
"use client";
import { useState } from "react";
+import { useRouter } from "next/navigation";
import { AnalysisForm } from "@/components/analysis/AnalysisForm";
import { TradingDecision } from "@/components/analysis/TradingDecision";
import { AnalystReport } from "@/components/analysis/AnalystReport";
import { PriceChart } from "@/components/analysis/PriceChart";
import { LoadingSpinner } from "@/components/shared/LoadingSpinner";
+import { Button } from "@/components/ui/button";
import { useAnalysis } from "@/hooks/useAnalysis";
+import { useAnalysisContext } from "@/context/AnalysisContext";
import type { AnalysisRequest } from "@/lib/types";
export default function AnalysisPage() {
+ const router = useRouter();
+ const { setAnalysisResult } = useAnalysisContext();
const { runAnalysis, loading, error, result } = useAnalysis();
const handleSubmit = async (request: AnalysisRequest) => {
@@ -24,6 +29,13 @@ export default function AnalysisPage() {
}
};
+ const handleViewResults = () => {
+ if (result) {
+ setAnalysisResult(result);
+ router.push("/analysis/results");
+ }
+ };
+
return (
@@ -49,6 +61,13 @@ export default function AnalysisPage() {
{result && !loading && (
+ {/* 查看詳細結果按鈕 */}
+
+
+
+
{/* 價格圖表 */}
{result.price_data && result.price_stats && (
{
+ if (!analysisResult) {
+ router.push("/analysis");
+ }
+ }, [analysisResult, router]);
+
+ if (!analysisResult) {
+ return (
+
+
+
沒有分析結果
+
請先執行分析
+
+
+
+ );
+ }
+
+ const currentAnalyst = ANALYSTS.find(a => a.key === selectedAnalyst);
+ const currentReport = analysisResult.reports?.[currentAnalyst?.reportKey || ""];
+
+ return (
+
+
+ {/* Header */}
+
+
+
+ {analysisResult.ticker} 詳細分析結果
+
+
+ 分析日期:{analysisResult.analysis_date}
+
+
+
+
+
+ {/* 分析師選擇 Tabs */}
+
+
+ {ANALYSTS.map(analyst => (
+
+ {analyst.label}
+
+ ))}
+
+
+ {ANALYSTS.map(analyst => (
+
+
+ {/* 價格圖表 - 每個分析師都有 */}
+ {analysisResult.price_data && analysisResult.price_stats && (
+
+ )}
+
+ {/* 分析師報告 */}
+
+
+ {analyst.label} 報告
+
+ {analyst.key === "market" && "技術分析與市場趨勢評估"}
+ {analyst.key === "social" && "社群情緒與市場氛圍分析"}
+ {analyst.key === "news" && "新聞事件與影響分析"}
+ {analyst.key === "fundamentals" && "財務數據與基本面分析"}
+
+
+
+ {currentReport ? (
+
+ ) : (
+
+
+ 此分析師沒有生成報告
+
+
+ 可能此分析師未被選擇或分析過程中未產生報告
+
+
+ )}
+
+
+
+
+ ))}
+
+
+
+ );
+}
diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx
index 68ebb866..5de855d1 100644
--- a/frontend/app/layout.tsx
+++ b/frontend/app/layout.tsx
@@ -3,6 +3,7 @@ import { Inter } from "next/font/google";
import "./globals.css";
import { Header } from "@/components/layout/Header";
import { Footer } from "@/components/layout/Footer";
+import { AnalysisProvider } from "@/context/AnalysisContext";
const inter = Inter({ subsets: ["latin"] });
@@ -19,13 +20,15 @@ export default function RootLayout({
return (
-
-
-
- {children}
-
-
-
+
+
+
+
+ {children}
+
+
+
+
);
diff --git a/frontend/context/AnalysisContext.tsx b/frontend/context/AnalysisContext.tsx
new file mode 100644
index 00000000..9d1492db
--- /dev/null
+++ b/frontend/context/AnalysisContext.tsx
@@ -0,0 +1,33 @@
+"use client";
+
+import { createContext, useContext, useState, ReactNode } from "react";
+import type { AnalysisResponse } from "@/lib/types";
+
+interface AnalysisContextType {
+ analysisResult: AnalysisResponse | null;
+ setAnalysisResult: (result: AnalysisResponse | null) => void;
+}
+
+const AnalysisContext = createContext(
+ undefined
+);
+
+export function AnalysisProvider({ children }: { children: ReactNode }) {
+ const [analysisResult, setAnalysisResult] = useState(
+ null
+ );
+
+ return (
+
+ {children}
+
+ );
+}
+
+export function useAnalysisContext() {
+ const context = useContext(AnalysisContext);
+ if (!context) {
+ throw new Error("useAnalysisContext must be used within AnalysisProvider");
+ }
+ return context;
+}