diff --git a/frontend/src/components/StatisticsView.jsx b/frontend/src/components/StatisticsView.jsx
index e3f8b77..038aa66 100644
--- a/frontend/src/components/StatisticsView.jsx
+++ b/frontend/src/components/StatisticsView.jsx
@@ -360,7 +360,7 @@ export default function StatisticsView({ trades, holdings, stats, baseline_vw, e
{/* Ticker Weights - Compact */}
- {stats.tickerWeights && Object.keys(stats.tickerWeights).length > 0 && (
+ {effectiveStats?.tickerWeights && Object.keys(effectiveStats.tickerWeights).length > 0 && (
- {Object.entries(stats.tickerWeights).map(([ticker, weight]) => {
+ {Object.entries(effectiveStats.tickerWeights).map(([ticker, weight]) => {
const weightValue = Number(weight);
const isNegative = weightValue < 0;
const displayWeight = (weightValue * 100).toFixed(1);
diff --git a/frontend/src/services/websocket.js b/frontend/src/services/websocket.js
index 014fe02..0557b79 100644
--- a/frontend/src/services/websocket.js
+++ b/frontend/src/services/websocket.js
@@ -24,13 +24,13 @@ export async function fetchGatewayPort() {
if (data.is_running && data.port) {
cachedGatewayPort = data.port;
cachedWsUrl = data.ws_url;
- return { port: data.port, wsUrl: data.ws_url };
+ return { status: "running", port: data.port, wsUrl: data.ws_url };
}
- return null;
+ return { status: "stopped", port: data.port || null, wsUrl: data.ws_url || null };
} catch (error) {
console.warn('[Gateway] Failed to fetch port:', error);
- return null;
+ return { status: "unavailable", port: null, wsUrl: null };
}
}
@@ -86,15 +86,29 @@ export class ReadOnlyClient {
// Resolve WebSocket URL if not set
let targetUrl = this.wsUrl;
if (!targetUrl) {
- // Try to fetch from API first
const gatewayInfo = await fetchGatewayPort();
- if (gatewayInfo) {
+ if (gatewayInfo?.status === "running" && gatewayInfo.wsUrl) {
targetUrl = gatewayInfo.wsUrl;
console.log(`[WebSocket] Resolved Gateway port: ${gatewayInfo.port}`);
- } else {
- // Fallback to default
+ } else if (gatewayInfo?.status === "unavailable") {
targetUrl = WS_URL;
console.log(`[WebSocket] Using default URL: ${targetUrl}`);
+ } else {
+ this.isConnecting = false;
+ this._safeEmit({
+ type: "system",
+ content: "运行任务尚未启动,等待数据服务上线..."
+ });
+
+ if (this.shouldReconnect) {
+ if (this.reconnectTimer) {
+ clearTimeout(this.reconnectTimer);
+ }
+ this.reconnectTimer = setTimeout(() => {
+ this._connect();
+ }, this.reconnectDelay);
+ }
+ return;
}
}