diff --git a/docs/develop-guides/roadmap.md b/docs/develop-guides/roadmap.md
index 80b2a64a..2da47409 100644
--- a/docs/develop-guides/roadmap.md
+++ b/docs/develop-guides/roadmap.md
@@ -45,6 +45,7 @@
- 新增内置Skills reporter,并移除内置 Agent reporter,数据库报表将由 Skills 完成
- 重构内置 Skills 安装机制:内置 skill 改为在管理页以“未安装”状态展示,支持按需安装、基于 `version + content_hash` 的更新提示与覆盖确认,并对已安装内置 skill 禁止在线文件编辑
- 新增知识库 PDF、图片的预览功能
+- 优化扩展页工具列表筛选区:将“全部分类”筛选收纳为搜索框右侧的紧凑下拉入口,并复用扩展页侧栏工具条样式,避免影响其他管理组件布局
diff --git a/web/src/assets/css/extensions.less b/web/src/assets/css/extensions.less
index e1b0052b..2e3ad3d7 100644
--- a/web/src/assets/css/extensions.less
+++ b/web/src/assets/css/extensions.less
@@ -30,6 +30,20 @@
flex-direction: column;
flex-shrink: 0;
+ .sidebar-toolbar {
+ padding: 8px 12px;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ border-bottom: 1px solid var(--gray-150);
+
+ .search-box {
+ flex: 1;
+ min-width: 0;
+ padding: 0;
+ }
+ }
+
.search-box {
padding: 8px 12px 0;
@@ -76,6 +90,34 @@
// }
}
+ .sidebar-tool {
+ width: 28px;
+ height: 28px;
+ padding: 0;
+ border-radius: 8px;
+ border-color: var(--gray-150);
+ background-color: var(--gray-0);
+ color: var(--gray-500);
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+ box-shadow: none;
+
+ &:hover,
+ &:focus {
+ color: var(--gray-700);
+ border-color: var(--gray-200);
+ background-color: var(--gray-0);
+ }
+
+ &.active {
+ color: var(--main-color);
+ border-color: var(--main-color);
+ background-color: color-mix(in srgb, var(--main-color) 8%, var(--gray-0));
+ }
+ }
+
.list-container {
flex: 1;
overflow-y: auto;
diff --git a/web/src/components/SkillsManagerComponent.vue b/web/src/components/SkillsManagerComponent.vue
index 90e8aaf2..9d858c6f 100644
--- a/web/src/components/SkillsManagerComponent.vue
+++ b/web/src/components/SkillsManagerComponent.vue
@@ -37,13 +37,14 @@
{{ skill.name }}
-
更新
-
+
{{ skill.name }}
@@ -144,43 +149,40 @@
>
{{ currentSkillStatusLabel }}
-
安装
-
-
+
-
+
-
+
+
{{ isBuiltinInstalledSkill ? '卸载' : '删除' }}
+
@@ -476,6 +478,10 @@ const isBuiltinInstalledSkill = computed(() => {
return !!(isInstalledSkill.value && (currentSkill.value?.is_builtin || currentSkill.value?.installed_record))
})
+const currentSkillDeleteActionText = computed(() => {
+ return isBuiltinInstalledSkill.value ? '卸载' : '删除'
+})
+
const currentSkillStatusLabel = computed(() => {
const skill = currentSkill.value
if (!skill) return ''
@@ -777,22 +783,26 @@ const handleCreateNode = async () => {
const confirmDeleteSkill = () => {
if (!currentSkill.value || !isInstalledSkill.value) return
+ const actionText = currentSkillDeleteActionText.value
+ const detailText = isBuiltinInstalledSkill.value
+ ? '卸载后会移除已安装文件和数据库记录,但仍可从“未安装 Skills”中重新安装。'
+ : '删除后无法恢复,所有文件和配置将永久消失。'
Modal.confirm({
- title: `彻底删除技能「${currentSkill.value.slug}」?`,
- content: '删除后无法恢复,所有文件和配置将永久消失。',
- okText: '确认删除',
+ title: `确认${actionText}技能「${currentSkill.value.slug}」?`,
+ content: detailText,
+ okText: `确认${actionText}`,
okType: 'danger',
cancelText: '取消',
onOk: async () => {
try {
await skillApi.deleteSkill(currentSkill.value.slug)
- message.success('已删除')
+ message.success(`已${actionText}`)
currentSkill.value = null
treeData.value = []
resetFileState()
await fetchSkills()
} catch {
- message.error('删除失败')
+ message.error(`${actionText}失败`)
}
}
})
@@ -975,6 +985,121 @@ defineExpose({
}
}
}
+
+}
+
+.skill-inline-action {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 999px;
+ min-width: 52px;
+ height: 24px;
+ padding: 0 9px;
+ border-style: solid;
+ border-width: 1px;
+ box-shadow: none;
+ font-size: 12px;
+ font-weight: 600;
+ line-height: 1;
+ transition:
+ background-color 0.18s ease,
+ border-color 0.18s ease,
+ color 0.18s ease;
+ cursor: pointer;
+ appearance: none;
+
+ &.skill-inline-action-primary {
+ border-color: transparent;
+ background: var(--main-600);
+ color: var(--main-0);
+ }
+
+ &.skill-inline-action-secondary {
+ border-color: var(--main-100);
+ background: var(--main-30);
+ color: var(--main-700);
+ }
+
+ &:hover,
+ &:focus {
+ outline: none;
+ }
+
+ &.skill-inline-action-primary:hover,
+ &.skill-inline-action-primary:focus {
+ background: var(--main-700);
+ color: var(--main-0);
+ }
+
+ &.skill-inline-action-secondary:hover,
+ &.skill-inline-action-secondary:focus {
+ border-color: var(--main-200);
+ background: var(--main-50);
+ color: var(--main-800);
+ }
+}
+
+.skill-panel-action {
+ min-height: 30px;
+ padding: 0 12px;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 999px;
+ border-style: solid;
+ border-width: 1px;
+ box-shadow: none;
+ font-weight: 500;
+ transition:
+ background-color 0.18s ease,
+ border-color 0.18s ease,
+ color 0.18s ease;
+ cursor: pointer;
+ appearance: none;
+
+ &:hover,
+ &:focus {
+ outline: none;
+ }
+
+ &.skill-panel-action-primary {
+ border-color: transparent;
+ background: var(--main-600);
+ color: var(--main-0);
+ }
+
+ &.skill-panel-action-primary:hover,
+ &.skill-panel-action-primary:focus {
+ background: var(--main-700);
+ color: var(--main-0);
+ }
+
+ &.skill-panel-action-secondary {
+ border-color: var(--gray-200);
+ background: var(--gray-25);
+ color: var(--gray-700);
+
+ &:hover,
+ &:focus {
+ border-color: var(--gray-300);
+ color: var(--gray-900);
+ background: var(--gray-0);
+ }
+ }
+
+ &.skill-panel-action-danger {
+ border-color: var(--color-error-100);
+ background: var(--color-error-50);
+ color: var(--color-error-700);
+
+ &:hover,
+ &:focus {
+ border-color: var(--color-error-100);
+ background: var(--color-error-100);
+ color: var(--color-error-900);
+ }
+ }
}
.panel-status-chip {
diff --git a/web/src/components/ToolsManagerComponent.vue b/web/src/components/ToolsManagerComponent.vue
index 59930bea..541df954 100644
--- a/web/src/components/ToolsManagerComponent.vue
+++ b/web/src/components/ToolsManagerComponent.vue
@@ -6,29 +6,33 @@