feat(web): 任务中心全局 Provider / 设置·布局·路由调整 / 视频解析页适配

- tasks.tsx:顶栏任务中心全局 Provider(SSE 任务进度,供各插件页共享)
- 设置页与 AppLayout / client / router 调整,BF2042 插件页路由注册
- web_hub:dashboard / bot_settings 同步更新
- 视频解析页配合后端(缓存 tab / 任务槽进度)

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
sansenhoshiandClaude Code committed 2026-10-13 17:53:27 +08:00
1 parent 6af60a7d55
commit 968b3d1cfe
10 files changed
+804 -9

No files matched your search

+26 -2
View File
@@ -18,6 +18,7 @@ from __future__ import annotations
import asyncio
import os
import platform
import socket
import time
import psutil
@@ -216,8 +217,26 @@ def _is_private_ip(ip: str) -> bool:
return a == 10 or (a == 192 and b == 168) or (a == 172 and 16 <= b <= 31)
def _route_ip() -> str | None:
"""默认路由出口 IP —— 连外网时内核会挑的那张网卡。
VPN / 虚拟机 / WSL / EasyTier 的地址同样是私有段,纯按字符串排序会让
虚拟网卡赢(10.0.0.129 < 192.168.2.186),首页「协议端配对」就会展示一个
协议端连不上的地址(2026-10-08 实测)。逻辑与 hexi.core.outbound_media
的 `_route_ip` 同源,改这里记得同步那边;无网络时返回 None。
"""
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
sock.connect(("8.8.8.8", 80))
return str(sock.getsockname()[0])
except OSError:
return None
finally:
sock.close()
def _local_ips() -> list[str]:
"""本机可被协议端访问的 IPv4 列表(私有网段优先,排除环回/链路本地)。"""
"""本机可被协议端访问的 IPv4 列表(默认路由网卡最前,其次私有网段优先)。"""
ips: list[str] = []
try:
addrs = psutil.net_if_addrs()
@@ -237,7 +256,12 @@ def _local_ips() -> list[str]:
continue
if ip not in ips:
ips.append(ip)
return sorted(ips, key=lambda ip: (not _is_private_ip(ip), ip))
ips.sort(key=lambda ip: (not _is_private_ip(ip), ip))
route = _route_ip()
if route in ips:
ips.remove(route)
ips.insert(0, route)
return ips
def _ws_path() -> str: