diff --git a/src/views/StockOverview/components/FlexScreen/hooks/useRealtimeQuote.ts b/src/views/StockOverview/components/FlexScreen/hooks/useRealtimeQuote.ts
index dfb69bfc..1167614a 100644
--- a/src/views/StockOverview/components/FlexScreen/hooks/useRealtimeQuote.ts
+++ b/src/views/StockOverview/components/FlexScreen/hooks/useRealtimeQuote.ts
@@ -402,59 +402,77 @@ export const useRealtimeQuote = (codes: string[] = []): UseRealtimeQuoteReturn =
}, []);
const createConnection = useCallback((exchange: Exchange) => {
+ // 检查是否是 HTTPS 页面尝试连接 ws://(Mixed Content)
+ const isHttps = typeof window !== 'undefined' && window.location.protocol === 'https:';
+ const wsUrl = WS_CONFIG[exchange];
+ const isInsecureWs = wsUrl.startsWith('ws://');
+
+ if (isHttps && isInsecureWs) {
+ logger.warn(
+ 'FlexScreen',
+ `${exchange} WebSocket 连接被跳过:HTTPS 页面无法连接不安全的 ws:// 端点`
+ );
+ return;
+ }
+
if (wsRefs.current[exchange]) {
wsRefs.current[exchange]!.close();
}
- const ws = new WebSocket(WS_CONFIG[exchange]);
- wsRefs.current[exchange] = ws;
+ try {
+ const ws = new WebSocket(wsUrl);
+ wsRefs.current[exchange] = ws;
- ws.onopen = () => {
- logger.info('FlexScreen', `${exchange} WebSocket 已连接`);
- setConnected(prev => ({ ...prev, [exchange]: true }));
+ ws.onopen = () => {
+ logger.info('FlexScreen', `${exchange} WebSocket 已连接`);
+ setConnected(prev => ({ ...prev, [exchange]: true }));
- if (exchange === 'SSE') {
- const codes = Array.from(subscribedCodes.current.SSE);
- if (codes.length > 0) {
- ws.send(JSON.stringify({
- action: 'subscribe',
- channels: ['stock', 'index'],
- codes,
- }));
- }
- }
-
- startHeartbeat(exchange);
- };
-
- ws.onmessage = (event: MessageEvent) => {
- try {
- const msg = JSON.parse(event.data);
- handleMessage(exchange, msg);
- } catch (e) {
- logger.warn('FlexScreen', `${exchange} 消息解析失败`, e);
- }
- };
-
- ws.onerror = (error: Event) => {
- logger.error('FlexScreen', `${exchange} WebSocket 错误`, error);
- };
-
- ws.onclose = () => {
- logger.info('FlexScreen', `${exchange} WebSocket 断开`);
- setConnected(prev => ({ ...prev, [exchange]: false }));
- stopHeartbeat(exchange);
-
- // 自动重连
- if (!reconnectRefs.current[exchange] && subscribedCodes.current[exchange].size > 0) {
- reconnectRefs.current[exchange] = setTimeout(() => {
- reconnectRefs.current[exchange] = null;
- if (subscribedCodes.current[exchange].size > 0) {
- createConnection(exchange);
+ if (exchange === 'SSE') {
+ const codes = Array.from(subscribedCodes.current.SSE);
+ if (codes.length > 0) {
+ ws.send(JSON.stringify({
+ action: 'subscribe',
+ channels: ['stock', 'index'],
+ codes,
+ }));
}
- }, RECONNECT_INTERVAL);
- }
- };
+ }
+
+ startHeartbeat(exchange);
+ };
+
+ ws.onmessage = (event: MessageEvent) => {
+ try {
+ const msg = JSON.parse(event.data);
+ handleMessage(exchange, msg);
+ } catch (e) {
+ logger.warn('FlexScreen', `${exchange} 消息解析失败`, e);
+ }
+ };
+
+ ws.onerror = (error: Event) => {
+ logger.error('FlexScreen', `${exchange} WebSocket 错误`, error);
+ };
+
+ ws.onclose = () => {
+ logger.info('FlexScreen', `${exchange} WebSocket 断开`);
+ setConnected(prev => ({ ...prev, [exchange]: false }));
+ stopHeartbeat(exchange);
+
+ // 自动重连(仅在非 HTTPS + ws:// 场景下)
+ if (!reconnectRefs.current[exchange] && subscribedCodes.current[exchange].size > 0) {
+ reconnectRefs.current[exchange] = setTimeout(() => {
+ reconnectRefs.current[exchange] = null;
+ if (subscribedCodes.current[exchange].size > 0) {
+ createConnection(exchange);
+ }
+ }, RECONNECT_INTERVAL);
+ }
+ };
+ } catch (e) {
+ logger.error('FlexScreen', `${exchange} WebSocket 连接失败`, e);
+ setConnected(prev => ({ ...prev, [exchange]: false }));
+ }
}, [startHeartbeat, stopHeartbeat, handleMessage]);
const subscribe = useCallback((code: string) => {
diff --git a/sse_html.html b/sse_html.html
new file mode 100644
index 00000000..8723bda7
--- /dev/null
+++ b/sse_html.html
@@ -0,0 +1,378 @@
+
+
+
+
+
+ VDE 实时行情 - WebSocket 测试
+
+
+
+
+
VDE 实时行情
+
+
+
+
未连接
+
+
+
+
+
+
+
+
+
+
+
+
📊 指数行情
+
+
+
+ | 代码/名称 |
+ 最新 |
+ 涨跌 |
+ 涨跌幅 |
+ 成交额(亿) |
+
+
+
+
+
+
+
+
+
📈 股票行情 (前20)
+
+
+
+ | 代码/名称 |
+ 最新 |
+ 涨跌幅 |
+ 买一 |
+ 卖一 |
+ 成交额(万) |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/szse_html.html b/szse_html.html
new file mode 100644
index 00000000..baf8e8f0
--- /dev/null
+++ b/szse_html.html
@@ -0,0 +1,289 @@
+
+
+
+
+
+ 深交所行情 WebSocket 测试
+
+
+
+
+
深交所行情 WebSocket 测试
+
+
+
+
+
+
+
+ 未连接
+
+
+
+
+
+
+
+
+
+
+
+ | 代码 |
+ 类型 |
+ 最新价 |
+ 涨跌幅 |
+ 成交量 |
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/valuefrontier.conf b/valuefrontier.conf
index 9f4e2992..76fac284 100644
--- a/valuefrontier.conf
+++ b/valuefrontier.conf
@@ -112,6 +112,42 @@ server {
proxy_buffering off;
}
+ # ============================================
+ # 实时行情 WebSocket 代理(灵活屏功能)
+ # ============================================
+
+ # 上交所实时行情 WebSocket
+ location /ws/sse {
+ proxy_pass http://49.232.185.254:8765;
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection $connection_upgrade;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_connect_timeout 7d;
+ proxy_send_timeout 7d;
+ proxy_read_timeout 7d;
+ proxy_buffering off;
+ }
+
+ # 深交所实时行情 WebSocket
+ location /ws/szse {
+ proxy_pass http://222.128.1.157:8765;
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection $connection_upgrade;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_connect_timeout 7d;
+ proxy_send_timeout 7d;
+ proxy_read_timeout 7d;
+ proxy_buffering off;
+ }
+
location /mcp/ {
proxy_pass http://127.0.0.1:8900/;
proxy_http_version 1.1;
@@ -142,7 +178,6 @@ server {
}
}
-
# 概念板块API代理
location /concept-api/ {
proxy_pass http://222.128.1.157:16801/;
@@ -158,6 +193,7 @@ server {
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
+
# Elasticsearch API代理(价值论坛)
location /es-api/ {
proxy_pass http://222.128.1.157:19200/;
@@ -223,36 +259,7 @@ server {
proxy_send_timeout 86400s;
proxy_read_timeout 86400s;
}
- # AI Chat 应用 (Next.js) - MCP 集成
- # AI Chat 静态资源(图片、CSS、JS)
- location ~ ^/ai-chat/(images|_next/static|_next/image|favicon.ico) {
- proxy_pass http://127.0.0.1:3000;
- proxy_http_version 1.1;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
- # 缓存设置
- expires 30d;
- add_header Cache-Control "public, immutable";
- }
-
- # AI Chat 主应用
- location /ai-chat {
- proxy_pass http://127.0.0.1:3000;
- proxy_http_version 1.1;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
- proxy_set_header Cookie $http_cookie;
- proxy_pass_request_headers on;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "upgrade";
- proxy_buffering off;
- proxy_cache off;
- }
# iframe 内部资源代理(Bytedesk 聊天窗口的 CSS/JS)
location /chat/ {
proxy_pass http://43.143.189.195/chat/;
@@ -326,6 +333,22 @@ server {
add_header Cache-Control "public, max-age=86400";
}
+ # Bytedesk 文件访问代理(仅 2025 年文件)
+ location ^~ /file/2025/ {
+ proxy_pass http://43.143.189.195/file/2025/;
+ proxy_http_version 1.1;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ # 缓存配置
+ proxy_cache_valid 200 1d;
+ expires 1d;
+ add_header Cache-Control "public, max-age=86400";
+ add_header Access-Control-Allow-Origin *;
+ }
+
# Visitor API 代理(Bytedesk 初始化接口)
location /visitor/ {