style: 插件行控件两行布局——已启动/已关闭+启动开关、入口+入口开关;面板描述精简为「扩展插件」
This commit is contained in:
@@ -59,7 +59,7 @@ const TAB_META: Record<Exclude<Tab, PluginSettingsTab>, { title: string; desc: s
|
||||
general: { title: '常规', desc: '主题色等外观偏好。' },
|
||||
model: { title: '模型设置', desc: '' },
|
||||
prompt: { title: '系统提示词', desc: '' },
|
||||
plugins: { title: '插件', desc: '扩展插件(内置 / 全局 / 项目),按需启停。' },
|
||||
plugins: { title: '插件', desc: '扩展插件' },
|
||||
skills: { title: '技能', desc: 'SKILL.md 技能包,Agent 自动按需加载。' },
|
||||
commands: { title: '命令', desc: '聊天中 / 触发的自定义命令模板。' }
|
||||
}
|
||||
@@ -635,7 +635,6 @@ function PluginsPanel({
|
||||
onToggle,
|
||||
devBuild,
|
||||
onOpenDir,
|
||||
onOpenSettings,
|
||||
onNavToggle
|
||||
}: {
|
||||
/** 正在切换中的插件 id(切换期间全部开关禁用,避免并发重建运行时) */
|
||||
@@ -644,8 +643,6 @@ function PluginsPanel({
|
||||
/** 开发版构建(第三方装载开关开启);用户版展示关闭提示 */
|
||||
devBuild: boolean
|
||||
onOpenDir: (path: string) => void
|
||||
/** 打开插件自己的二级配置页(仅已声明设置表单的插件出现) */
|
||||
onOpenSettings: (pluginId: string) => void
|
||||
/** 把设置入口固定/移出到设置页一级导航 */
|
||||
onNavToggle: (pluginId: string, on: boolean) => void
|
||||
}): ReactNode {
|
||||
@@ -729,31 +726,41 @@ function PluginsPanel({
|
||||
(a.manifest.order ?? 100) - (b.manifest.order ?? 100) || a.manifest.id.localeCompare(b.manifest.id)
|
||||
)
|
||||
.map((p) => (
|
||||
<div key={p.manifest.id} className="rounded-card border border-line px-3 py-2.5">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-[12.5px] font-medium text-ink">{p.manifest.name}</span>
|
||||
<span className="rounded-control bg-hover px-1.5 py-0.5 text-[10px] text-ink-3">
|
||||
{scope === 'builtin' ? '内置' : scope === 'user' ? '全局' : '项目'} v{p.manifest.version}
|
||||
</span>
|
||||
<span className="ml-auto text-[11px] text-ink-3">{p.enabled ? '已启用' : '已停用'}</span>
|
||||
{p.hasSettings && p.enabled && (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
title="打开配置页"
|
||||
aria-label={`打开${p.manifest.name}配置页`}
|
||||
onClick={() => onOpenSettings(p.manifest.id)}
|
||||
className="shrink-0 rounded-control p-1 text-ink-3 transition-colors hover:bg-hover hover:text-ink"
|
||||
>
|
||||
<LuSettings2 size={13} />
|
||||
</button>
|
||||
<div key={p.manifest.id} className="flex items-center gap-3 rounded-card border border-line px-3 py-2.5">
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-[12.5px] font-medium text-ink">{p.manifest.name}</span>
|
||||
<span className="rounded-control bg-hover px-1.5 py-0.5 text-[10px] text-ink-3">
|
||||
{scope === 'builtin' ? '内置' : scope === 'user' ? '全局' : '项目'} v{p.manifest.version}
|
||||
</span>
|
||||
</div>
|
||||
{p.manifest.description && (
|
||||
<div className="mt-1 text-[12px] leading-5 text-ink-3">{p.manifest.description}</div>
|
||||
)}
|
||||
{p.error && <div className="mt-1 text-[12px] text-red">装载失败:{p.error}</div>}
|
||||
</div>
|
||||
<div className="flex shrink-0 flex-col items-end gap-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-[11px] text-ink-3">{p.enabled ? '已启动' : '已关闭'}</span>
|
||||
<button
|
||||
type="button"
|
||||
role="switch"
|
||||
aria-checked={p.enabled}
|
||||
aria-label={`启用${p.manifest.name}`}
|
||||
disabled={togglingId !== null}
|
||||
onClick={() => onToggle(p, !p.enabled)}
|
||||
className={`relative h-6 w-10 shrink-0 rounded-full transition-colors disabled:cursor-not-allowed disabled:opacity-50 ${
|
||||
p.enabled ? 'bg-accent' : 'bg-line-strong'
|
||||
}`}
|
||||
>
|
||||
<span
|
||||
className={`shrink-0 rounded-control px-1.5 py-0.5 text-[10px] transition-colors ${
|
||||
p.settingsNav ? 'bg-accent/10 text-accent' : 'bg-hover text-ink-3'
|
||||
}`}
|
||||
>
|
||||
一级入口
|
||||
</span>
|
||||
className={`absolute top-0.5 size-5 rounded-full bg-white shadow transition-[left] ${p.enabled ? 'left-[18px]' : 'left-0.5'}`}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
{p.hasSettings && p.enabled && (
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-[11px] text-ink-3">入口</span>
|
||||
<button
|
||||
type="button"
|
||||
role="switch"
|
||||
@@ -769,26 +776,9 @@ function PluginsPanel({
|
||||
className={`absolute top-0.5 size-4 rounded-full bg-white shadow transition-[left] ${p.settingsNav ? 'left-[18px]' : 'left-0.5'}`}
|
||||
/>
|
||||
</button>
|
||||
</>
|
||||
</div>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
role="switch"
|
||||
aria-checked={p.enabled}
|
||||
aria-label={`启用${p.manifest.name}`}
|
||||
disabled={togglingId !== null}
|
||||
onClick={() => onToggle(p, !p.enabled)}
|
||||
className={`relative h-6 w-10 shrink-0 rounded-full transition-colors disabled:cursor-not-allowed disabled:opacity-50 ${
|
||||
p.enabled ? 'bg-accent' : 'bg-line-strong'
|
||||
}`}
|
||||
>
|
||||
<span
|
||||
className={`absolute top-0.5 size-5 rounded-full bg-white shadow transition-[left] ${p.enabled ? 'left-[18px]' : 'left-0.5'}`}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
{p.manifest.description && <div className="mt-1 text-[12px] leading-5 text-ink-3">{p.manifest.description}</div>}
|
||||
{p.error && <div className="mt-1 text-[12px] text-red">装载失败:{p.error}</div>}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -1444,7 +1434,6 @@ export function SettingsModal({
|
||||
onToggle={togglePlugin}
|
||||
devBuild={import.meta.env.DEV}
|
||||
onOpenDir={(path) => void window.api.openPath(path)}
|
||||
onOpenSettings={(pluginId) => setTab(`plugin:${pluginId}`)}
|
||||
onNavToggle={handleSetSettingsNav}
|
||||
/>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user