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 }} - 安装 - - +
@@ -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 @@