diff --git a/backend/app/__pycache__/main.cpython-313.pyc b/backend/app/__pycache__/main.cpython-313.pyc index ff55f88e..2b3959a4 100644 Binary files a/backend/app/__pycache__/main.cpython-313.pyc and b/backend/app/__pycache__/main.cpython-313.pyc differ diff --git a/backend/app/main.py b/backend/app/main.py index b5ef1d75..6b71e061 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -13,11 +13,28 @@ from app.db.database import init_db from app.engine.scheduler import start_scheduler, stop_scheduler from app.api import market, sectors, recommendations, stocks, watchlists, websocket, chat, auth, debug -logging.basicConfig( - level=logging.DEBUG if settings.debug else logging.INFO, - format="%(asctime)s [%(levelname)s] %(name)s: %(message)s", - datefmt="%Y-%m-%d %H:%M:%S", -) +def configure_logging() -> None: + logging.basicConfig( + level=logging.DEBUG if settings.debug else logging.INFO, + format="%(asctime)s [%(levelname)s] %(name)s: %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + ) + + # 保留应用日志的调试能力,但压制基础设施层的噪音。 + noisy_loggers = { + "aiosqlite": logging.WARNING, + "sqlalchemy": logging.WARNING, + "sqlalchemy.engine": logging.WARNING, + "sqlalchemy.pool": logging.WARNING, + "httpx": logging.INFO, + "httpcore": logging.WARNING, + "uvicorn.access": logging.INFO, + } + for name, level in noisy_loggers.items(): + logging.getLogger(name).setLevel(level) + + +configure_logging() logger = logging.getLogger(__name__) diff --git a/frontend/src/app/(auth)/dashboard/page.tsx b/frontend/src/app/(auth)/dashboard/page.tsx index 6a4569d4..4b39885b 100644 --- a/frontend/src/app/(auth)/dashboard/page.tsx +++ b/frontend/src/app/(auth)/dashboard/page.tsx @@ -11,8 +11,6 @@ import type { SectorData, StrategyBoard, } from "@/lib/api"; -import MarketTemp from "@/components/market-temp"; -import SectorHeatmap from "@/components/sector-heatmap"; import { ThemeToggle } from "@/components/theme-toggle"; import { useAuth } from "@/hooks/use-auth"; import { useWebSocket } from "@/hooks/use-websocket"; @@ -209,9 +207,7 @@ export default function DashboardPage() { )} -

- 先看今天能不能做,再看该做什么,最后进入执行。 -

+

先看结论,再看动作,再看焦点标的。

@@ -242,17 +238,27 @@ export default function DashboardPage() { observeCount={observe.length} /> -
+
- +
+ +
+ +
- -
- - -
); } @@ -321,63 +322,147 @@ function DecisionHero({ function ActionPanel({ actions, - focusQueue, - fallbackTitle, + summary, }: { actions: ReturnType; - focusQueue: RecommendationData[]; - fallbackTitle: string; + summary: ReturnType; }) { return ( -
-
-
-
-

今天该做什么

-

把市场结论拆成可执行动作,而不是只给情绪描述。

-
- - 系统校准 - -
- -
- - - -
+
+
+ + +
-
-
-
-

{fallbackTitle}

-

只展示最该盯的少量标的,避免首页无限拉长。

-
- - 全部推荐 - -
- -
- {focusQueue.length ? ( - focusQueue.map((rec) => ) - ) : ( -
- 暂无标的,等待新一轮扫描输出。 -
- )} -
+
+ + +
); } -function ExecutionPanel({ - recommendations, +function FocusPanel({ + focusQueue, actionableCount, watchCount, observeCount, +}: { + focusQueue: RecommendationData[]; + actionableCount: number; + watchCount: number; + observeCount: number; +}) { + return ( +
+
+
+

焦点标的

+

首页只保留最该处理的少量标的。

+
+
+ + + +
+
+ +
+ {focusQueue.length ? ( + focusQueue.map((rec) => ) + ) : ( +
+ 今天没有需要处理的焦点标的。 +
+ )} +
+
+ ); +} + +function MarketSnapshot({ + marketTemperature, + indices, + sectors, + summary, +}: { + marketTemperature: MarketTemperatureData | null; + indices: IndexOverview[]; + sectors: SectorData[]; + summary: ReturnType; +}) { + const leadingSectors = sectors.slice(0, 4); + const majorIndices = indices.slice(0, 3); + + return ( +
+
+
+

市场证据

+

只保留对今天决策有用的信息。

+
+ + 温度 {Math.round(marketTemperature?.temperature ?? 0)} + +
+ +
+ + + + +
+ + {majorIndices.length ? ( +
+ {majorIndices.map((item) => ( +
+
{item.name}
+
+ {item.close.toFixed(2)} + = 0 ? "text-red-400" : "text-emerald-400"}`}> + {item.pct_chg >= 0 ? "+" : ""}{item.pct_chg.toFixed(2)}% + +
+
+ ))} +
+ ) : null} + + {leadingSectors.length ? ( +
+
今日盯住的板块
+
+ {leadingSectors.map((sector) => { + const pct = sector.realtime_pct_change ?? sector.pct_change; + return ( +
+
+
{sector.sector_name}
+
+ {sector.limit_up_count > 0 ? `${sector.limit_up_count} 涨停` : "无涨停"} · {sector.stage || "mid"} +
+
+ = 0 ? "text-red-400" : "text-emerald-400"}`}> + {pct >= 0 ? "+" : ""}{pct.toFixed(2)}% + +
+ ); + })} +
+
+ ) : null} + +
+ 结论:{summary.headline} +
+
+ ); +} + +function AdminPanel({ isAdmin, opsStatus, refreshing, @@ -385,10 +470,6 @@ function ExecutionPanel({ onRefresh, onAction, }: { - recommendations: RecommendationData[]; - actionableCount: number; - watchCount: number; - observeCount: number; isAdmin?: boolean; opsStatus: OpsStatusResponse | null; refreshing: boolean; @@ -396,92 +477,43 @@ function ExecutionPanel({ onRefresh: () => void; onAction: (action: "update_tracking" | "generate_strategy_board" | "generate_strategy_iteration") => void; }) { + if (!isAdmin || !opsStatus) return null; + return ( -
-
-

执行入口

-

不同任务进入不同页面,首页只保留关键入口和现状摘要。

- -
- - - - -
- -
-
- 推荐池状态 - {recommendations.length} 只 -
-
- - - -
+
+
+
+

管理员

+

{opsStatus.data_freshness.message}

+ + {opsStatus.scan_running ? "扫描中" : "空闲"} +
- {isAdmin && opsStatus ? ( -
-
-
-

管理员任务中心

-

{opsStatus.data_freshness.message}

-
- - {opsStatus.scan_running ? "扫描中" : "空闲"} - -
+
+ + + + +
-
- - - - -
- -
- - - -
-
- ) : null} +
+ + +
); } @@ -530,6 +562,15 @@ function HeroFact({ label, value }: { label: string; value: string }) { ); } +function CompactBadge({ label, value }: { label: string; value: string }) { + return ( + + {label} + {value} + + ); +} + function ActionBucket({ title, items, @@ -602,12 +643,12 @@ function FocusStockCard({ rec }: { rec: RecommendationData }) { ); } -function NavCard({ href, title, description }: { href: string; title: string; description: string }) { +function EvidenceStat({ label, value, tone }: { label: string; value: number; tone: string }) { return ( - -
{title}
-
{description}
-
+
+
{label}
+
{value}
+
); } @@ -677,6 +718,7 @@ function buildMarketSummary( cannotDo, modeLabel: strategyProfile?.market_stance || board?.recommended_mode || "等待更新", positionLabel: board?.position_suggestion || (strategyProfile?.max_position_pct ? `${strategyProfile.max_position_pct}% 以内` : "等待更新"), + riskLabel: board?.risk_level || "等待更新", }; }