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}
-
+
);
}
@@ -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 || "等待更新",
};
}