feat(web): 顶栏账号菜单接入 bot 启停 / 插件页分区 / 首页协议端配对信息

- 重启/关闭 bot 从设置页提到顶栏账号下拉(破坏性操作弹确认框),等待回连逻辑抽成
  lib/botAction.ts 供两处共用:先等旧进程让出端口,再以 dashboard SSE 真收到一帧为准,
  只看 HTTP 200 会在"端口起来但插件未挂接"时误判就绪
- 插件管理页按 带 Web 页面 / 带配置项 / 都没有 分区,卡片加类型与 Web/配置 徽章
- 首页「BOT 协议端信息」分两半:左半登录账号,右半 NoneBot 接入信息
  (IP / 运行端口 / WS 路径 / 访问令牌,均可一键复制,另给整条反向 WS 地址),
  监听地址非 0.0.0.0 时提示仅本机可连;「BOT 后端信息」移到自己一行
- dashboard.py 新增 endpoint 段:读 driver.config 的 host/port、驱动实际注册的
  反向 WS 路由(自动跳过根路径与尾斜杠别名)、适配器令牌与本机网卡 IP

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
2026-09-22 14:23:52 +08:00
co-authored by Claude Code
parent 814c1994b6
commit 4b5e8b8b2e
7 changed files with 546 additions and 194 deletions
+52
View File
@@ -0,0 +1,52 @@
import { hubDashboardStream } from '../api/client'
/** 请求停止/重启 bot 后,等它回连的那段等待逻辑(设置页与顶栏账号菜单共用)。
*
* 重启分两步回来:旧进程先退出(让出端口),新进程才起来,所以先干等一会儿
* 再开始探活;探活以 dashboard SSE **真正收到一帧**为准 —— 只看 HTTP 200 会在
* 「端口起来了但插件还没挂接」时就放行,紧接着的请求全 404。
*
* 返回 dispose:重复触发或组件卸载时调用,内部会撤掉 SSE 与超时定时器。
*/
export function watchBotReconnect(opts: {
onReady: () => void
onTimeout: () => void
/** 等旧进程退出的时间 */
startupDelayMs?: number
/** 探活总超时 */
timeoutMs?: number
}): () => void {
const { onReady, onTimeout, startupDelayMs = 4000, timeoutMs = 60000 } = opts
let stopped = false
let timer: number | null = null
let disposeStream: (() => void) | null = null
const finish = () => {
stopped = true
if (timer != null) { window.clearTimeout(timer); timer = null }
if (disposeStream) { disposeStream(); disposeStream = null }
}
timer = window.setTimeout(() => {
if (stopped) return
disposeStream = hubDashboardStream({
onData: (d) => {
if (stopped) return
if (d && d.ok !== false) { finish(); onReady() }
},
})
timer = window.setTimeout(() => {
if (stopped) return
finish()
onTimeout()
}, timeoutMs)
}, startupDelayMs)
return finish
}
/** 菜单/按钮上共用的文案,避免两处写法漂移 */
export const BOT_ACTION_TEXT = {
restart: { title: '重启 bot', confirm: '确定重启 bot 进程吗?将先拉起新进程再退出旧进程,期间 Web 与 QQ 连接会短暂断开。' },
stop: { title: '关闭 bot', confirm: '确定关闭当前 bot 进程吗?Web 管理台与 QQ 连接都会断开,需要在服务器上手动重新启动。' },
} as const