fix(webui,plugin): 内核控制按钮晚绑定 + 按钮布局;plugin_start 报错给候选名

1. 内核控制通道晚绑定(真机 503 实测)
   POST /api/v1/kernel/restart 一直返回 503:webui 由 plugin-host 在装配期
   拉起,而 main() 里 SetKernelControl 还没执行 ⇒ 插件 Start 拿到 nil。
   依赖图保证不了 main 里的语句顺序,所以改成让插件拿**解析器**
   (lazyKernelControl),调用那一刻再取真实通道;授权仍在每次调用时
   按 kernelControlAllowed/kernelRestartAllowed 复核,不因晚绑定放宽。

2. WebUI 重启/关机按钮布局
   原先用 .theme-btn(顶栏图标样式:pill + margin-right + 无文字)混在
   侧栏底部的文字按钮里 ⇒ 大小不一、挤在一起、关机看不出是危险操作。
   改为与「退出登录」同族的 btn-sm,带图标+文字,关机用 danger 悬停。

3. plugin_start 失败报错
   原来只说加载出错,或插件不存在,一个可用名字都不给,模型只能盲猜
   (实测把 files 写成 file)。现在给:失败原因分类(目录不存在/没清单/
   自身加载失败)、最接近的名字(Levenshtein ≤2)、已安装清单(最多 12)。

4. scripts/migrate-plugins-to-org.sh:插件迁到 GitHub 组织独立仓的脚本收口

测试:go build ./... 通过;go test ./internal/plugin ./internal/plugins/webui 全绿。
This commit is contained in:
JianFeeeee
2026-10-27 01:43:19 +08:00
parent 55fa2685ae
commit c33199cc5a
5 changed files with 386 additions and 113 deletions

View File

@ -598,6 +598,28 @@
all var(--dur-micro) var(--ease-out),
transform var(--dur-micro) var(--ease-out);
}
/* 内核控制按钮组(侧栏底部):与"退出登录"同族,带文字与图标。
两枚按钮等宽、同一行、间距一致;关机用红色悬停提示危险操作。 */
.nav-kernel {
display: flex;
gap: 8px;
margin: 8px 0 4px;
}
.nav-kernel .btn {
flex: 1 1 0;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
padding: 6px 10px;
font-size: 13px;
line-height: 1.2;
}
.nav-kernel .nav-danger:hover {
color: #e5484d;
border-color: rgba(229, 72, 77, 0.5);
background: rgba(229, 72, 77, 0.08);
}
.theme-btn:hover {
color: var(--accent);
border-color: rgba(var(--accent-rgb), 0.5);

View File

@ -142,33 +142,43 @@
</button>
<!-- 内核控制:重启 / 关机。
放在导航底部而不是页面里,是因为它们作用于**整个服务**,
不属于任何一个标签页。 -->
<button
class="theme-btn"
id="kernel-restart-btn"
onclick="kernelRestart()"
title="重启内核(服务约断线数秒后自动重连)"
aria-label="重启内核"
>
<svg viewBox="0 0 24 24" width="15" height="15" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round">
<path d="M21 12a9 9 0 1 1-2.6-6.4" />
<path d="M21 3v6h-6" />
</svg>
</button>
<button
class="theme-btn"
id="kernel-shutdown-btn"
onclick="kernelShutdown()"
title="关闭内核(需人工 systemctl start 才能再启动)"
aria-label="关闭内核"
>
<svg viewBox="0 0 24 24" width="15" height="15" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round">
<path d="M12 3v9" />
<path d="M6.3 6.3a8 8 0 1 0 11.4 0" />
</svg>
</button>
不属于任何一个标签页。
★ 2026-10-26:原先是两个只有图标的 .theme-btn(那是**顶栏**的样式:
有 margin-right、pill 圆角、无文字),混在侧栏底部的文字按钮里
⇒ 大小不一、挤在一起、且用户看不出哪个是关机。
现在改成与"退出登录"同族的 btn-sm,带图标 + 文字,
关机额外用 danger 样式(红色悬停)区别于重启。 -->
<div class="nav-kernel">
<button
class="btn btn-ghost btn-sm"
id="kernel-restart-btn"
onclick="kernelRestart()"
title="重启内核(服务断线数秒后自动重连;进行中的对话可能中断)"
>
<svg viewBox="0 0 24 24" width="14" height="14" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round"
aria-hidden="true">
<path d="M21 12a9 9 0 1 1-2.6-6.4" />
<path d="M21 3v6h-6" />
</svg>
重启
</button>
<button
class="btn btn-ghost btn-sm nav-danger"
id="kernel-shutdown-btn"
onclick="kernelShutdown()"
title="关闭内核(不会自动重启,需人工 systemctl start)"
>
<svg viewBox="0 0 24 24" width="14" height="14" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round"
aria-hidden="true">
<path d="M12 3v9" />
<path d="M6.3 6.3a8 8 0 1 0 11.4 0" />
</svg>
关机
</button>
</div>
<button
class="btn btn-ghost btn-sm"
onclick="logout()"