feat: revamp web hub — global connection status, array config editor, log streaming

- Global connection badge in app header (persistent dashboard SSE via ConnectionProvider)
- LogProvider keeps log data and SSE stream alive across page switches (no reload spinner)
- Config drawer: password reveal toggle, array-type row editor for list fields
- Plugin management: optimistic updates, race-free loading, reset all group overrides
- Logs: load-earlier pagination; backend tail-read optimization (before/end offsets)
- web_auth: Web password changes persist (sync_admin seeding only when .env has explicit key)
- Dashboard: collect in thread pool + 1s result cache
- ErrorBoundary + local Suspense: plugin chunk loading stays inside content area
- UI polish: table row hover, mobile header/breadcrumb fixes, wider config drawer
- config_standard: array type inference for list fields; array env skip
- random_jm_code / steam_info: array schema migration; README web frontend note

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
2026-09-03 15:39:10 +08:00
co-authored by Claude Code
parent 9371a28e35
commit c53b210413
45 changed files with 1312 additions and 576 deletions
@@ -0,0 +1,20 @@
"""业务逻辑层:一个业务动作一个方法;不依赖 nonebot(可单测)。"""
from __future__ import annotations
from hexi.web_config import get_effective_value
from ..repository import get_record, save_record
_PLUGIN_ID = __package__.rsplit(".", 1)[0]
async def do_something(text: str) -> str:
"""示例业务:记录输入并返回带配置的回复。"""
save_record("last_input", text)
prefix = get_effective_value(_PLUGIN_ID, "reply", "你好,我是模板插件!")
record = get_record("last_input")
if record:
return f"{prefix} 已记录:{record}"
return prefix