diff --git a/README.md b/README.md
index 89f9707..6089f30 100644
--- a/README.md
+++ b/README.md
@@ -47,6 +47,7 @@ pnpm run build:antdv-next
## 业务页面
- 系统管理 / 站内信是日志级通知列表,只展示 API 错误、QQBot 下线、NapCat 离线等后端自动捕获事件;页面提供筛选、处理/重新打开、置顶和删除,不提供人工新增或编辑。
+- QQBot / 账号连接页拆分 OneBot 连接、QQ 登录、NapCat 运行和运行说明列;更新登录通过 SSE 展示 quick / password / qrcode 每步进度。
## 部署说明
diff --git a/apps/web-antdv-next/src/api/qqbot/index.ts b/apps/web-antdv-next/src/api/qqbot/index.ts
index 9fc2f9d..9096423 100644
--- a/apps/web-antdv-next/src/api/qqbot/index.ts
+++ b/apps/web-antdv-next/src/api/qqbot/index.ts
@@ -53,11 +53,21 @@ export namespace QqbotApi {
bindStatus?: 'bound' | 'disabled' | 'pending';
containerId?: string;
containerName?: string;
+ containerOnline?: boolean;
containerStatus?: 'creating' | 'error' | 'running' | 'stopped';
lastCheckedAt?: string;
lastError?: string;
lastLoginAt?: string;
lastStartedAt?: string;
+ oneBotOnline?: boolean;
+ qqLoginMessage?: null | string;
+ qqLoginStatus?:
+ | 'offline'
+ | 'online'
+ | 'qrcode_expired'
+ | 'qrcode_pending'
+ | 'unknown';
+ webuiOnline?: boolean | null;
webuiPort?: null | number;
}
diff --git a/apps/web-antdv-next/src/views/qqbot/account/list.tsx b/apps/web-antdv-next/src/views/qqbot/account/list.tsx
index c206647..63e0303 100644
--- a/apps/web-antdv-next/src/views/qqbot/account/list.tsx
+++ b/apps/web-antdv-next/src/views/qqbot/account/list.tsx
@@ -184,14 +184,20 @@ export default defineComponent({
{
dataIndex: 'connectStatus',
key: 'accountOnlineStatus',
- title: '账号在线',
- width: 130,
+ title: 'OneBot 连接',
+ width: 140,
+ },
+ {
+ dataIndex: 'napcat',
+ key: 'qqLoginStatus',
+ title: 'QQ 登录',
+ width: 150,
},
{
dataIndex: 'napcat',
key: 'napcatRuntime',
- title: 'NapCat 容器',
- width: 220,
+ title: 'NapCat 运行',
+ width: 240,
},
{
dataIndex: 'lastHeartbeatAt',
@@ -302,7 +308,7 @@ export default defineComponent({
],
},
fieldName: 'connectStatus',
- label: '账号在线',
+ label: 'OneBot',
},
],
},
@@ -626,19 +632,38 @@ export default defineComponent({
if (!row.enabled) {
return 已停用;
}
+ const online = row.napcat?.oneBotOnline ?? row.connectStatus === 'online';
return (
-
- {row.connectStatus === 'online' ? 'OneBot 在线' : 'OneBot 离线'}
+
+ {online ? 'OneBot 在线' : 'OneBot 离线'}
);
};
+ const renderQqLoginStatus = (row: QqbotApi.Account) => {
+ const meta = getQqLoginStatusMeta(row.napcat);
+ return (
+
+ {meta.label}
+ {row.napcat?.qqLoginMessage ? (
+
+ {row.napcat.qqLoginMessage}
+
+ ) : null}
+
+ );
+ };
+
const renderNapcatRuntime = (row: QqbotApi.Account) => {
const napcat = row.napcat;
const meta = getNapcatStatusMeta(napcat);
+ const webuiMeta = getNapcatWebuiMeta(napcat);
return (
- {meta.label}
+
+ {meta.label}
+ {webuiMeta.label}
+
{napcat?.containerName ? (
{napcat.containerName}
@@ -694,6 +719,34 @@ export default defineComponent({
return statusMap[napcat.containerStatus];
}
+ function getNapcatWebuiMeta(napcat?: null | QqbotApi.AccountNapcatRuntime) {
+ if (!napcat) return { color: 'default', label: 'WebUI 未绑定' };
+ if (napcat.webuiOnline === true) {
+ return { color: 'success', label: 'WebUI 可用' };
+ }
+ if (napcat.webuiOnline === false) {
+ return { color: 'error', label: 'WebUI 不可用' };
+ }
+ return { color: 'default', label: 'WebUI 未检查' };
+ }
+
+ function getQqLoginStatusMeta(
+ napcat?: null | QqbotApi.AccountNapcatRuntime,
+ ) {
+ if (!napcat) return { color: 'default', label: '未绑定容器' };
+ const statusMap: Record<
+ NonNullable,
+ { color: string; label: string }
+ > = {
+ offline: { color: 'error', label: 'QQ 离线' },
+ online: { color: 'success', label: 'QQ 在线' },
+ qrcode_expired: { color: 'warning', label: '二维码过期' },
+ qrcode_pending: { color: 'processing', label: '等待扫码' },
+ unknown: { color: 'default', label: '状态未知' },
+ };
+ return statusMap[napcat.qqLoginStatus || 'unknown'];
+ }
+
function getRecentActivity(row: QqbotApi.Account) {
const candidates = [
{ label: '最近心跳', value: row.lastHeartbeatAt },
@@ -719,14 +772,26 @@ export default defineComponent({
if (row.lastError) {
return { level: 'warning', text: `账号异常:${row.lastError}` };
}
+ if (row.napcat?.qqLoginMessage) {
+ return {
+ level: 'warning',
+ text: `QQ 登录:${row.napcat.qqLoginMessage}`,
+ };
+ }
if (row.napcat?.lastError) {
- return { level: 'warning', text: `容器异常:${row.napcat.lastError}` };
+ return { level: 'warning', text: `NapCat:${row.napcat.lastError}` };
+ }
+ if (row.napcat?.qqLoginStatus === 'qrcode_expired') {
+ return { level: 'warning', text: '二维码已过期,点击更新登录' };
}
if (row.connectStatus === 'online') {
return { level: 'normal', text: '消息链路可用' };
}
+ if (row.napcat?.qqLoginStatus === 'online') {
+ return { level: 'warning', text: 'QQ 在线,等待 OneBot 连接' };
+ }
if (row.napcat?.containerStatus === 'running') {
- return { level: 'warning', text: '等待反向 WS' };
+ return { level: 'warning', text: 'NapCat 运行中,等待 OneBot 连接' };
}
if (row.napcat?.containerStatus === 'creating') {
return { level: 'warning', text: '容器创建中' };
@@ -840,6 +905,9 @@ export default defineComponent({
if (column.key === 'accountOnlineStatus') {
return renderAccountOnlineStatus(row);
}
+ if (column.key === 'qqLoginStatus') {
+ return renderQqLoginStatus(row);
+ }
if (column.key === 'napcatRuntime') {
return renderNapcatRuntime(row);
}