结构调整

视频解析多图/多媒体结构 消息体适配
This commit is contained in:
2026-09-08 14:25:32 +08:00
parent 30899688a7
commit 131b92b319
72 changed files with 433 additions and 186 deletions
-4
View File
@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-54 -44.52999973297119 216.1999969482422 143.78999710083008" data-asc="0.9052734375" width="216.1999969482422" height="143.78999710083008"><defs><filter id="toxic-glow-filter" x="-54" y="-44.52999973297119" width="216.1999969482422" height="143.78999710083008" filterUnits="userSpaceOnUse">
<feDropShadow dx="0" dy="0" stdDeviation="6" flood-color="#acdba4" flood-opacity="0.9"/>
<feDropShadow dx="0" dy="0" stdDeviation="18" flood-color="#a294b8" flood-opacity="0.6"/>
</filter></defs><g fill="#0f0f0f" stroke="#686a68" stroke-width="1.5" filter="url(#toxic-glow-filter)"><g transform="translate(0, 0)"><path d="M0 45.26L0 9.47L4.74 9.47L4.74 24.17L23.34 24.17L23.34 9.47L28.08 9.47L28.08 45.26L23.34 45.26L23.34 28.39L4.74 28.39L4.74 45.26L0 45.26ZM36.06 45.26L36.06 9.47L61.94 9.47L61.94 13.70L40.80 13.70L40.80 24.66L60.60 24.66L60.60 28.86L40.80 28.86L40.80 41.04L62.77 41.04L62.77 45.26L36.06 45.26ZM65.67 45.26L79.52 26.61L67.31 9.47L72.95 9.47L79.44 18.65Q81.47 21.51 82.32 23.05Q83.52 21.09 85.16 18.97L92.36 9.47L97.51 9.47L84.94 26.34L98.49 45.26L92.63 45.26L83.62 32.50Q82.86 31.40 82.06 30.10Q80.86 32.06 80.35 32.79L71.36 45.26L65.67 45.26ZM103.47 45.26L103.47 9.47L108.20 9.47L108.20 45.26L103.47 45.26Z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

+1 -1
View File
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" type="image/svg+xml" href="/hub/favicon.svg" />
<link rel="icon" type="image/svg+xml" href="/hub/favicon.png" />
<title>HeXi · 统一管理台</title>
</head>
<body>
Binary file not shown.

After

Width:  |  Height:  |  Size: 810 KiB

+1 -1
View File
@@ -174,7 +174,7 @@ export function AppLayout() {
<Bars className="size-5" />
</Button>
{isPluginSub && (
<Button size="sm" variant="tertiary" className="max-w-24 shrink-0 truncate" onPress={() => navigate('/hub/plugins')}>← 返回</Button>
<Button size="sm" variant="tertiary" className="max-w-24 shrink-0 truncate" onPress={() => navigate('/hub/plugins')}>返回</Button>
)}
{isPluginSub ? (
<div className="flex min-w-0 items-center gap-2">
+6
View File
@@ -33,6 +33,7 @@ interface CatalogPlugin {
name: string
description: string
usage: string
type?: string
enabled: boolean
chat: string[]
groups: Record<string, GroupOverride>
@@ -304,6 +305,11 @@ export default function PluginsPage() {
<div className="min-w-0 flex-1">
<div className="flex flex-wrap items-center gap-2">
<span className="text-sm font-semibold text-slate-800">{p.name}</span>
{p.type && (
<span className={'inline-block rounded-full text-xs px-2 py-0.5 ' + (p.type === 'library' ? 'bg-violet-50 text-violet-600' : 'bg-sky-50 text-sky-600')}>
{p.type === 'library' ? 'lib' : 'app'}
</span>
)}
{p.has_web && <span className="inline-block rounded-full bg-indigo-50 text-indigo-600 text-xs px-2 py-0.5">Web</span>}
{p.has_config && <span className="inline-block rounded-full bg-amber-50 text-amber-600 text-xs px-2 py-0.5">配置</span>}
<span className={'inline-block rounded-full text-xs px-2 py-0.5 ' + (on ? 'bg-emerald-50 text-emerald-600' : 'bg-slate-100 text-slate-400')}>{on ? '启用' : '停用'}</span>
+18 -1
View File
@@ -17,6 +17,8 @@ interface BotConfigData {
debug: boolean
log_level: string
log_level_options: string[]
log_max_mb: number
log_max_mb_default: number
source: string
notice?: string
applied?: string[]
@@ -46,6 +48,7 @@ export default function SettingsPage() {
const [cfgNickname, setCfgNickname] = useState('')
const [cfgDebug, setCfgDebug] = useState(false)
const [cfgLogLevel, setCfgLogLevel] = useState('INFO')
const [cfgLogMaxMb, setCfgLogMaxMb] = useState('20')
const [cfgBusy, setCfgBusy] = useState(false)
const [cfgLoaded, setCfgLoaded] = useState(false)
@@ -64,6 +67,7 @@ export default function SettingsPage() {
setCfgNickname((c.nickname || []).join(', '))
setCfgDebug(!!c.debug)
setCfgLogLevel(c.log_level || 'INFO')
setCfgLogMaxMb(String(c.log_max_mb ?? c.log_max_mb_default ?? 20))
setCfgLoaded(true)
} catch (e: any) {
setCfgLoaded(false)
@@ -95,18 +99,25 @@ export default function SettingsPage() {
const saveBotConfig = async () => {
setCfgBusy(true)
try {
const values = {
const values: Record<string, any> = {
superusers: (cfgSuperusers || '').split(/[,\s]+/).map(s => s.trim()).filter(Boolean),
nickname: (cfgNickname || '').split(/[,\s]+/).map(s => s.trim()).filter(Boolean),
debug: cfgDebug,
log_level: cfgLogLevel,
}
const logMaxMbRaw = cfgLogMaxMb.trim()
if (logMaxMbRaw !== '') {
const logMaxMb = parseInt(logMaxMbRaw, 10)
if (!(logMaxMb > 0)) { toast.warning('日志清理大小需为正整数(MB)'); setCfgBusy(false); return }
values.log_max_mb = logMaxMb
}
const r = await hubBotConfigSave(values)
setBotCfg(r)
setCfgSuperusers((r.superusers || []).join(', '))
setCfgNickname((r.nickname || []).join(', '))
setCfgDebug(!!r.debug)
setCfgLogLevel(r.log_level || 'INFO')
setCfgLogMaxMb(String(r.log_max_mb ?? r.log_max_mb_default ?? 20))
toast.success('BOT 配置已保存')
if (r.notice) toast.info(r.notice)
} catch (e: any) {
@@ -199,6 +210,7 @@ export default function SettingsPage() {
<p className="text-xs text-slate-400 mb-4">
SUPERUSERS / NICKNAME 支持逗号或空格分隔;保存后会写入 .env 并尽量热应用。
部分插件在启动时缓存了这些值,完全生效建议保存后重启 bot。
日志清理大小保存后仅在下一个检查周期(约 1 分钟)内生效,无需重启。
</p>
<div className="grid gap-4 md:grid-cols-2">
<TextField>
@@ -230,6 +242,11 @@ export default function SettingsPage() {
</Select>
<span className="text-xs text-slate-400">日志等级(INFO 为默认)</span>
</div>
<TextField>
<Label>日志清理大小 (MB)</Label>
<Input type="number" min={1} value={cfgLogMaxMb} onChange={e => setCfgLogMaxMb(e.target.value)} placeholder="如: 20" />
<span className="text-xs text-slate-400">_bot_run.log 超过该大小即清空(不归档)</span>
</TextField>
</div>
<div className="mt-4 flex items-center gap-3">
<Button isDisabled={cfgBusy || !cfgLoaded || !!restarting} onPress={saveBotConfig}>{cfgBusy ? '保存中…' : '保存 BOT 配置'}</Button>