From ba4cc41a5a53e8d71dd79b7d86bcb8905848dd05 Mon Sep 17 00:00:00 2001 From: MarkLo Date: Sat, 29 Nov 2025 00:19:17 +0800 Subject: [PATCH] --- README.md | 16 ++ clean_cache.sh | 206 +++++++++++++++++------ frontend/app/analysis/results/page.tsx | 12 +- frontend/app/globals.css | 132 +++++++++++++++ frontend/app/page.tsx | 50 ++++-- frontend/components/layout/Footer.tsx | 30 +--- frontend/public/logos/claude-color.svg | 1 + frontend/public/logos/deepseek-color.svg | 1 + frontend/public/logos/gemini-color.svg | 1 + frontend/public/logos/grok.svg | 1 + frontend/public/logos/openai.svg | 1 + frontend/public/logos/qwen-color.svg | 1 + llm_logo/claude-color.svg | 1 + llm_logo/deepseek-color.svg | 1 + llm_logo/gemini-color.svg | 1 + llm_logo/grok.svg | 1 + llm_logo/openai.svg | 1 + llm_logo/qwen-color.svg | 1 + 18 files changed, 352 insertions(+), 106 deletions(-) create mode 100644 frontend/public/logos/claude-color.svg create mode 100644 frontend/public/logos/deepseek-color.svg create mode 100644 frontend/public/logos/gemini-color.svg create mode 100644 frontend/public/logos/grok.svg create mode 100644 frontend/public/logos/openai.svg create mode 100644 frontend/public/logos/qwen-color.svg create mode 100644 llm_logo/claude-color.svg create mode 100644 llm_logo/deepseek-color.svg create mode 100644 llm_logo/gemini-color.svg create mode 100644 llm_logo/grok.svg create mode 100644 llm_logo/openai.svg create mode 100644 llm_logo/qwen-color.svg diff --git a/README.md b/README.md index 8690a60c..d680e837 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,21 @@ TradingAgentsX 支援業界領先的多家 LLM 提供商,並為每個模型配置**獨立的 API Key 和 Base URL**,實現最大靈活性。 +
+ +### 支援的 LLM 提供商 + +

+ OpenAI + Anthropic Claude + Google Gemini + xAI Grok + DeepSeek + Alibaba Qwen +

+ +
+ ### 📋 支援的 LLM 提供商矩陣 | 提供商 | 支援模型 | Base URL | 是否支援自訂端點 | @@ -54,6 +69,7 @@ TradingAgentsX 支援業界領先的多家 LLM 提供商,並為每個模型配 | **Qwen (Alibaba)** | Qwen3-Max, Qwen-Plus, Qwen Flash | `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` | ✅ 是 | | **自訂端點** | 上述列表中的模型 | 使用者自訂 | ✅ 完全支援 | + ### 🔧 三層獨立配置 系統支援**三個獨立的 LLM 配置點**,每個都可使用不同的提供商和 API Key: diff --git a/clean_cache.sh b/clean_cache.sh index f0619d0a..6b5a2154 100755 --- a/clean_cache.sh +++ b/clean_cache.sh @@ -1,14 +1,14 @@ #!/bin/bash # ======================================== -# 清理開發與構建緩存腳本 -# 此腳本會清理 pnpm 和開發過程中產生的緩存文件 -# 不會影響項目的源代碼和依賴包 +# 清理所有緩存腳本(全域版本) +# 此腳本會清理整個專案中所有類型的緩存文件 +# 不限定特定目錄,徹底清理所有緩存 # ======================================== set -e # 遇到錯誤立即停止 -echo "🧹 開始清理緩存..." +echo "🧹 開始全域清理所有緩存..." echo "================================" # 記錄腳本執行位置 @@ -16,121 +16,217 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$SCRIPT_DIR" # ======================================== -# 前端緩存清理 +# Next.js / React 緩存清理 # ======================================== echo "" -echo "📦 清理前端緩存..." +echo "⚛️ 清理 Next.js / React 緩存..." -if [ -d "frontend/.next" ]; then - echo " ✓ 刪除 frontend/.next (Next.js 構建輸出)" - rm -rf frontend/.next +# 清理 .next 目錄(整個專案) +NEXT_COUNT=$(find . -type d -name ".next" 2>/dev/null | wc -l | tr -d ' ') +if [ "$NEXT_COUNT" -gt 0 ]; then + echo " ✓ 刪除 $NEXT_COUNT 個 .next 目錄" + find . -type d -name ".next" -exec rm -rf {} + 2>/dev/null || true else - echo " - frontend/.next 不存在,跳過" + echo " - 沒有 .next 目錄,跳過" fi -if [ -d "frontend/.turbo" ]; then - echo " ✓ 刪除 frontend/.turbo (Turbopack 緩存)" - rm -rf frontend/.turbo +# 清理 .turbo 目錄 +TURBO_COUNT=$(find . -type d -name ".turbo" 2>/dev/null | wc -l | tr -d ' ') +if [ "$TURBO_COUNT" -gt 0 ]; then + echo " ✓ 刪除 $TURBO_COUNT 個 .turbo 目錄" + find . -type d -name ".turbo" -exec rm -rf {} + 2>/dev/null || true else - echo " - frontend/.turbo 不存在,跳過" + echo " - 沒有 .turbo 目錄,跳過" fi -if [ -d "frontend/out" ]; then - echo " ✓ 刪除 frontend/out (靜態導出輸出)" - rm -rf frontend/out +# 清理 out 目錄 +OUT_COUNT=$(find . -type d -name "out" 2>/dev/null | wc -l | tr -d ' ') +if [ "$OUT_COUNT" -gt 0 ]; then + echo " ✓ 刪除 $OUT_COUNT 個 out 目錄" + find . -type d -name "out" -exec rm -rf {} + 2>/dev/null || true else - echo " - frontend/out 不存在,跳過" + echo " - 沒有 out 目錄,跳過" fi -# 清理 TypeScript 增量編譯緩存 -if [ -f "frontend/tsconfig.tsbuildinfo" ]; then - echo " ✓ 刪除 frontend/tsconfig.tsbuildinfo (TS 增量緩存)" - rm -f frontend/tsconfig.tsbuildinfo +# 清理 build 目錄 +BUILD_COUNT=$(find . -type d -name "build" 2>/dev/null | wc -l | tr -d ' ') +if [ "$BUILD_COUNT" -gt 0 ]; then + echo " ✓ 刪除 $BUILD_COUNT 個 build 目錄" + find . -type d -name "build" -exec rm -rf {} + 2>/dev/null || true else - echo " - TypeScript 緩存不存在,跳過" + echo " - 沒有 build 目錄,跳過" +fi + +# 清理 dist 目錄 +DIST_COUNT=$(find . -type d -name "dist" 2>/dev/null | wc -l | tr -d ' ') +if [ "$DIST_COUNT" -gt 0 ]; then + echo " ✓ 刪除 $DIST_COUNT 個 dist 目錄" + find . -type d -name "dist" -exec rm -rf {} + 2>/dev/null || true +else + echo " - 沒有 dist 目錄,跳過" fi # ======================================== -# 後端緩存清理 +# TypeScript 緩存清理 # ======================================== echo "" -echo "🐍 清理後端緩存..." +echo "📘 清理 TypeScript 緩存..." -# 清理 Python 緩存 -PYCACHE_COUNT=$(find backend -type d -name "__pycache__" 2>/dev/null | wc -l | tr -d ' ') +# 清理 tsconfig.tsbuildinfo +TSBUILDINFO_COUNT=$(find . -name "tsconfig.tsbuildinfo" -o -name "*.tsbuildinfo" 2>/dev/null | wc -l | tr -d ' ') +if [ "$TSBUILDINFO_COUNT" -gt 0 ]; then + echo " ✓ 刪除 $TSBUILDINFO_COUNT 個 TypeScript 緩存文件" + find . \( -name "tsconfig.tsbuildinfo" -o -name "*.tsbuildinfo" \) -delete 2>/dev/null || true +else + echo " - 沒有 TypeScript 緩存,跳過" +fi + +# ======================================== +# Python 緩存清理 +# ======================================== +echo "" +echo "🐍 清理 Python 緩存..." + +# 清理 __pycache__ +PYCACHE_COUNT=$(find . -type d -name "__pycache__" 2>/dev/null | wc -l | tr -d ' ') if [ "$PYCACHE_COUNT" -gt 0 ]; then echo " ✓ 刪除 $PYCACHE_COUNT 個 __pycache__ 目錄" - find backend -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true + find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true else echo " - 沒有 __pycache__ 目錄,跳過" fi # 清理 .pyc 文件 -PYC_COUNT=$(find backend -type f -name "*.pyc" 2>/dev/null | wc -l | tr -d ' ') +PYC_COUNT=$(find . -type f -name "*.pyc" 2>/dev/null | wc -l | tr -d ' ') if [ "$PYC_COUNT" -gt 0 ]; then echo " ✓ 刪除 $PYC_COUNT 個 .pyc 文件" - find backend -type f -name "*.pyc" -delete 2>/dev/null || true + find . -type f -name "*.pyc" -delete 2>/dev/null || true else echo " - 沒有 .pyc 文件,跳過" fi # 清理 .pyo 文件 -PYO_COUNT=$(find backend -type f -name "*.pyo" 2>/dev/null | wc -l | tr -d ' ') +PYO_COUNT=$(find . -type f -name "*.pyo" 2>/dev/null | wc -l | tr -d ' ') if [ "$PYO_COUNT" -gt 0 ]; then echo " ✓ 刪除 $PYO_COUNT 個 .pyo 文件" - find backend -type f -name "*.pyo" -delete 2>/dev/null || true + find . -type f -name "*.pyo" -delete 2>/dev/null || true else echo " - 沒有 .pyo 文件,跳過" fi -# 清理 pytest 緩存 -if [ -d "backend/.pytest_cache" ]; then - echo " ✓ 刪除 backend/.pytest_cache (Pytest 緩存)" - rm -rf backend/.pytest_cache +# 清理 .pytest_cache +PYTEST_COUNT=$(find . -type d -name ".pytest_cache" 2>/dev/null | wc -l | tr -d ' ') +if [ "$PYTEST_COUNT" -gt 0 ]; then + echo " ✓ 刪除 $PYTEST_COUNT 個 .pytest_cache 目錄" + find . -type d -name ".pytest_cache" -exec rm -rf {} + 2>/dev/null || true else - echo " - Pytest 緩存不存在,跳過" + echo " - 沒有 .pytest_cache 目錄,跳過" +fi + +# 清理 *.egg-info +EGGINFO_COUNT=$(find . -type d -name "*.egg-info" 2>/dev/null | wc -l | tr -d ' ') +if [ "$EGGINFO_COUNT" -gt 0 ]; then + echo " ✓ 刪除 $EGGINFO_COUNT 個 .egg-info 目錄" + find . -type d -name "*.egg-info" -exec rm -rf {} + 2>/dev/null || true +else + echo " - 沒有 .egg-info 目錄,跳過" fi # ======================================== -# 通用緩存清理 +# 通用緩存目錄清理 # ======================================== echo "" -echo "🔧 清理通用緩存..." +echo "📦 清理通用緩存目錄..." -# 清理 macOS 系統文件 +# 清理 .cache 目錄 +CACHE_COUNT=$(find . -type d -name ".cache" 2>/dev/null | wc -l | tr -d ' ') +if [ "$CACHE_COUNT" -gt 0 ]; then + echo " ✓ 刪除 $CACHE_COUNT 個 .cache 目錄" + find . -type d -name ".cache" -exec rm -rf {} + 2>/dev/null || true +else + echo " - 沒有 .cache 目錄,跳過" +fi + +# 清理 .parcel-cache +PARCEL_COUNT=$(find . -type d -name ".parcel-cache" 2>/dev/null | wc -l | tr -d ' ') +if [ "$PARCEL_COUNT" -gt 0 ]; then + echo " ✓ 刪除 $PARCEL_COUNT 個 .parcel-cache 目錄" + find . -type d -name ".parcel-cache" -exec rm -rf {} + 2>/dev/null || true +else + echo " - 沒有 .parcel-cache 目錄,跳過" +fi + +# 清理 .vite 目錄 +VITE_COUNT=$(find . -type d -name ".vite" 2>/dev/null | wc -l | tr -d ' ') +if [ "$VITE_COUNT" -gt 0 ]; then + echo " ✓ 刪除 $VITE_COUNT 個 .vite 目錄" + find . -type d -name ".vite" -exec rm -rf {} + 2>/dev/null || true +else + echo " - 沒有 .vite 目錄,跳過" +fi + +# ======================================== +# 系統緩存清理 +# ======================================== +echo "" +echo "🔧 清理系統緩存..." + +# 清理 .DS_Store (macOS) DS_STORE_COUNT=$(find . -name ".DS_Store" 2>/dev/null | wc -l | tr -d ' ') if [ "$DS_STORE_COUNT" -gt 0 ]; then - echo " ✓ 刪除 $DS_STORE_COUNT 個 .DS_Store 文件 (macOS 緩存)" + echo " ✓ 刪除 $DS_STORE_COUNT 個 .DS_Store 文件" find . -name ".DS_Store" -delete 2>/dev/null || true else echo " - 沒有 .DS_Store 文件,跳過" fi -# 清理日誌文件 -if [ -f "npm-debug.log" ]; then - echo " ✓ 刪除 npm-debug.log" - rm -f npm-debug.log -fi - -if [ -f "yarn-error.log" ]; then - echo " ✓ 刪除 yarn-error.log" - rm -f yarn-error.log +# 清理 Thumbs.db (Windows) +THUMBS_COUNT=$(find . -name "Thumbs.db" 2>/dev/null | wc -l | tr -d ' ') +if [ "$THUMBS_COUNT" -gt 0 ]; then + echo " ✓ 刪除 $THUMBS_COUNT 個 Thumbs.db 文件" + find . -name "Thumbs.db" -delete 2>/dev/null || true +else + echo " - 沒有 Thumbs.db 文件,跳過" fi # ======================================== -# 計算清理的空間 +# 日誌文件清理 +# ======================================== +echo "" +echo "📝 清理日誌文件..." + +# 清理 npm/yarn 日誌 +LOG_COUNT=$(find . \( -name "npm-debug.log" -o -name "yarn-error.log" -o -name "yarn-debug.log" -o -name "pnpm-debug.log" \) 2>/dev/null | wc -l | tr -d ' ') +if [ "$LOG_COUNT" -gt 0 ]; then + echo " ✓ 刪除 $LOG_COUNT 個日誌文件" + find . \( -name "npm-debug.log" -o -name "yarn-error.log" -o -name "yarn-debug.log" -o -name "pnpm-debug.log" \) -delete 2>/dev/null || true +else + echo " - 沒有日誌文件,跳過" +fi + +# ======================================== +# 完成 # ======================================== echo "" echo "================================" -echo "✅ 清理完成!" +echo "✅ 全域緩存清理完成!" echo "" -echo "📋 保留的重要文件:" +echo "📋 保留的重要文件/目錄:" echo " ✓ node_modules (依賴包)" -echo " ✓ pnpm-lock.yaml (鎖定文件)" +echo " ✓ pnpm-lock.yaml / package-lock.json (鎖定文件)" echo " ✓ package.json (包配置)" +echo " ✓ .git (版本控制)" echo " ✓ 所有源代碼文件" echo "" +echo "�️ 已清理的緩存類型:" +echo " • Next.js/React: .next, .turbo, out, build, dist" +echo " • TypeScript: *.tsbuildinfo" +echo " • Python: __pycache__, *.pyc, *.pyo, .pytest_cache, *.egg-info" +echo " • 通用緩存: .cache, .parcel-cache, .vite" +echo " • 系統文件: .DS_Store, Thumbs.db" +echo " • 日誌文件: npm-debug.log, yarn-error.log 等" +echo "" echo "💡 提示:" -echo " - 下次運行 'pnpm dev' 時,緩存會自動重新生成" +echo " - 下次運行開發服務器時,緩存會自動重新生成" echo " - 如果需要重新安裝依賴,請運行 'pnpm install'" echo "" diff --git a/frontend/app/analysis/results/page.tsx b/frontend/app/analysis/results/page.tsx index 21f8a712..addd3de4 100644 --- a/frontend/app/analysis/results/page.tsx +++ b/frontend/app/analysis/results/page.tsx @@ -132,7 +132,7 @@ export default function AnalysisResultsPage() {
{/* Header */} -
+

{analysisResult.ticker} 詳細分析結果 @@ -144,7 +144,7 @@ export default function AnalysisResultsPage() {

{/* 分析師選擇 Tabs */} - + {ANALYSTS.map(analyst => ( {analyst.label} @@ -178,7 +178,7 @@ export default function AnalysisResultsPage() { )} {/* 分析師報告 */} - + {analyst.label} 報告 @@ -187,7 +187,7 @@ export default function AnalysisResultsPage() { {currentReport ? ( -
+
{currentReport} diff --git a/frontend/app/globals.css b/frontend/app/globals.css index dc98be74..c78e4888 100644 --- a/frontend/app/globals.css +++ b/frontend/app/globals.css @@ -120,3 +120,135 @@ @apply bg-background text-foreground; } } + +/* Custom animations */ +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes slideUp { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes slideInLeft { + from { + opacity: 0; + transform: translateX(-30px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes slideInRight { + from { + opacity: 0; + transform: translateX(30px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes scaleUp { + from { + opacity: 0; + transform: scale(0.95); + } + to { + opacity: 1; + transform: scale(1); + } +} + +@keyframes shimmer { + 0% { + background-position: -200% center; + } + 100% { + background-position: 200% center; + } +} + +/* Animation utility classes */ +.animate-fade-in { + animation: fadeIn 0.6s ease-out; +} + +.animate-slide-up { + animation: slideUp 0.6s ease-out; +} + +.animate-slide-in-left { + animation: slideInLeft 0.6s ease-out; +} + +.animate-slide-in-right { + animation: slideInRight 0.6s ease-out; +} + +.animate-scale-up { + animation: scaleUp 0.5s ease-out; +} + +/* Stagger delays for sequential animations */ +.animate-delay-100 { + animation-delay: 0.1s; + animation-fill-mode: both; +} + +.animate-delay-200 { + animation-delay: 0.2s; + animation-fill-mode: both; +} + +.animate-delay-300 { + animation-delay: 0.3s; + animation-fill-mode: both; +} + +.animate-delay-400 { + animation-delay: 0.4s; + animation-fill-mode: both; +} + +.animate-delay-500 { + animation-delay: 0.5s; + animation-fill-mode: both; +} + +.animate-delay-600 { + animation-delay: 0.6s; + animation-fill-mode: both; +} + +/* Enhanced hover effects */ +.hover-lift { + transition: transform 0.3s ease, box-shadow 0.3s ease; +} + +.hover-lift:hover { + transform: translateY(-8px); + box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), + 0 8px 10px -6px rgb(0 0 0 / 0.1); +} + +/* Gradient shimmer effect */ +.gradient-shimmer { + background-size: 200% auto; + animation: shimmer 3s linear infinite; +} diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx index 55e26597..dad5636e 100644 --- a/frontend/app/page.tsx +++ b/frontend/app/page.tsx @@ -1,4 +1,5 @@ import Link from "next/link"; +import Image from "next/image"; import { Button } from "@/components/ui/button"; import { Card, @@ -12,7 +13,7 @@ export default function HomePage() { return (
{/* Hero Section */} -
+

TradingAgentsX

@@ -28,20 +29,11 @@ export default function HomePage() { 開始分析 - - -
{/* Core Features Section */} -
+

🎯 核心特色

基於 LangGraph 的智能股票交易分析平台,結合多個 AI 代理進行協作決策 @@ -360,7 +352,7 @@ function FeatureCard({ icon: string; }) { return ( - +

{icon}
{title} @@ -384,7 +376,7 @@ function AgentCard({ responsibilities: string[]; }) { return ( - + {name} {role} @@ -412,11 +404,35 @@ function LLMProviderCard({ models: string[]; icon: string; }) { + // Map provider names to logo filenames + const logoMap: Record = { + "OpenAI": "/logos/openai.svg", + "Anthropic": "/logos/claude-color.svg", + "Google Gemini": "/logos/gemini-color.svg", + "Grok (xAI)": "/logos/grok.svg", + "DeepSeek": "/logos/deepseek-color.svg", + "Qwen (Alibaba)": "/logos/qwen-color.svg", + }; + + const logoSrc = logoMap[name]; + return ( - + -
- {icon} +
+ {logoSrc ? ( +
+ {`${name} +
+ ) : ( + {icon} + )} {name}
@@ -442,7 +458,7 @@ function TechnicalCard({ features: string[]; }) { return ( - + {title} diff --git a/frontend/components/layout/Footer.tsx b/frontend/components/layout/Footer.tsx index a61a70b5..400ba4ff 100644 --- a/frontend/components/layout/Footer.tsx +++ b/frontend/components/layout/Footer.tsx @@ -5,35 +5,9 @@ export function Footer() { return (