Phase 4 completion: - Add ApprovalQueue component for managing pending approvals - Add ExecutionResult component for displaying hand/workflow results - Update Sidebar navigation to use unified AutomationPanel - Replace separate 'hands' and 'workflow' tabs with single 'automation' tab - Fix TypeScript type safety issues with unknown types in JSX expressions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
537 lines
29 KiB
HTML
537 lines
29 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>WorkBuddy - 技能</title>
|
||
<script src="https://cdn.tailwindcss.com"></script>
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||
<style>
|
||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
|
||
|
||
body {
|
||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||
overflow: hidden;
|
||
}
|
||
|
||
/* Custom scrollbar */
|
||
::-webkit-scrollbar { width: 6px; height: 6px; }
|
||
::-webkit-scrollbar-track { background: transparent; }
|
||
::-webkit-scrollbar-thumb { background: #d1d5db; border-radius: 3px; }
|
||
::-webkit-scrollbar-thumb:hover { background: #9ca3af; }
|
||
|
||
/* Skill card animations */
|
||
.skill-card {
|
||
transition: all 0.2s ease;
|
||
border: 1px solid #e5e7eb;
|
||
}
|
||
.skill-card:hover {
|
||
border-color: #d1d5db;
|
||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.03);
|
||
transform: translateY(-1px);
|
||
}
|
||
|
||
/* Add button animation */
|
||
.add-btn {
|
||
transition: all 0.2s ease;
|
||
border: 1px solid #e5e7eb;
|
||
}
|
||
.add-btn:hover {
|
||
border-color: #10b981;
|
||
color: #10b981;
|
||
background-color: #ecfdf5;
|
||
transform: scale(1.05);
|
||
}
|
||
.add-btn:active {
|
||
transform: scale(0.95);
|
||
}
|
||
.add-btn.added {
|
||
background-color: #10b981;
|
||
border-color: #10b981;
|
||
color: white;
|
||
}
|
||
|
||
/* Icon container */
|
||
.skill-icon {
|
||
background: linear-gradient(135deg, #f3f4f6 0%, #e5e7eb 100%);
|
||
transition: all 0.2s ease;
|
||
}
|
||
.skill-card:hover .skill-icon {
|
||
background: linear-gradient(135deg, #e5e7eb 0%, #d1d5db 100%);
|
||
}
|
||
|
||
/* Sidebar active state */
|
||
.sidebar-item.active {
|
||
background-color: #f3f4f6;
|
||
font-weight: 500;
|
||
}
|
||
|
||
/* Search input focus */
|
||
.search-input:focus {
|
||
border-color: #10b981;
|
||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);
|
||
}
|
||
|
||
/* Import button hover */
|
||
.import-btn {
|
||
transition: all 0.2s ease;
|
||
}
|
||
.import-btn:hover {
|
||
background-color: #f3f4f6;
|
||
border-color: #d1d5db;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body class="bg-white h-screen flex text-gray-800">
|
||
|
||
<!-- Left Sidebar -->
|
||
<aside class="w-64 bg-white border-r border-gray-200 flex flex-col h-full flex-shrink-0">
|
||
<!-- App Header -->
|
||
<div class="h-14 flex items-center px-4 border-b border-gray-100 flex-shrink-0">
|
||
<div class="flex items-center gap-2">
|
||
<div class="w-8 h-8 bg-gradient-to-br from-emerald-400 to-teal-500 rounded-lg flex items-center justify-center text-white font-bold text-lg shadow-sm">
|
||
<i class="fas fa-code text-sm"></i>
|
||
</div>
|
||
<span class="font-bold text-lg text-gray-800 tracking-tight">WorkBuddy</span>
|
||
</div>
|
||
<button class="ml-auto p-1.5 hover:bg-gray-100 rounded-lg text-gray-400 transition-colors">
|
||
<i class="far fa-clone text-sm"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Menu Items -->
|
||
<nav class="flex-1 py-3 px-3 space-y-0.5 overflow-y-auto">
|
||
<!-- Search -->
|
||
<div class="px-1 mb-3">
|
||
<div class="relative">
|
||
<i class="fas fa-search absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 text-sm"></i>
|
||
<input type="text" placeholder="搜索任务"
|
||
class="w-full pl-9 pr-8 py-2 bg-gray-50 border border-gray-200 rounded-lg text-sm focus:outline-none focus:border-emerald-500 focus:ring-1 focus:ring-emerald-500 transition-all">
|
||
<button class="absolute right-2 top-1/2 -translate-y-1/2 p-1 hover:bg-gray-200 rounded text-gray-400 transition-colors">
|
||
<i class="fas fa-sliders-h text-xs"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- New Task Button -->
|
||
<button class="w-full flex items-center gap-3 px-3 py-2 hover:bg-gray-100 rounded-lg text-gray-700 transition-colors mb-1">
|
||
<i class="far fa-check-square text-emerald-600 w-5"></i>
|
||
<span class="font-medium">新建任务</span>
|
||
</button>
|
||
|
||
<!-- Nav Items -->
|
||
<a href="#" class="sidebar-item flex items-center gap-3 px-3 py-2 text-gray-600 rounded-lg transition-colors">
|
||
<i class="fas fa-robot text-gray-400 w-5"></i>
|
||
<span>Claw</span>
|
||
</a>
|
||
|
||
<a href="#" class="sidebar-item flex items-center gap-3 px-3 py-2 text-gray-600 rounded-lg transition-colors">
|
||
<i class="fas fa-user-tie text-gray-400 w-5"></i>
|
||
<span>专家</span>
|
||
</a>
|
||
|
||
<a href="#" class="sidebar-item active flex items-center gap-3 px-3 py-2 text-gray-900 rounded-lg transition-colors">
|
||
<i class="fas fa-wand-magic-sparkles text-gray-700 w-5"></i>
|
||
<span>技能</span>
|
||
</a>
|
||
|
||
<a href="#" class="sidebar-item flex items-center gap-3 px-3 py-2 text-gray-600 rounded-lg transition-colors">
|
||
<i class="fas fa-puzzle-piece text-gray-400 w-5"></i>
|
||
<span>插件</span>
|
||
</a>
|
||
|
||
<a href="#" class="sidebar-item flex items-center gap-3 px-3 py-2 text-gray-600 rounded-lg transition-colors">
|
||
<i class="far fa-clock text-gray-400 w-5"></i>
|
||
<span>自动化</span>
|
||
</a>
|
||
|
||
<!-- Empty State -->
|
||
<div class="mt-8 px-4 text-center">
|
||
<p class="text-gray-900 font-medium mb-1">暂无任务</p>
|
||
<p class="text-gray-400 text-sm">点击上方按钮开始新任务</p>
|
||
</div>
|
||
</nav>
|
||
|
||
<!-- User Profile -->
|
||
<div class="p-3 border-t border-gray-200 flex-shrink-0">
|
||
<button class="flex items-center gap-3 w-full hover:bg-gray-50 p-2 rounded-lg transition-colors">
|
||
<div class="w-8 h-8 bg-gradient-to-br from-emerald-400 to-cyan-500 rounded-full flex items-center justify-center text-white font-bold shadow-sm">
|
||
<i class="fas fa-robot text-xs"></i>
|
||
</div>
|
||
<span class="flex-1 text-left text-sm font-medium text-gray-700">iven</span>
|
||
<i class="fas fa-chevron-right text-gray-400 text-xs"></i>
|
||
</button>
|
||
</div>
|
||
</aside>
|
||
|
||
<!-- Main Content -->
|
||
<main class="flex-1 flex flex-col h-full bg-white overflow-hidden">
|
||
<!-- Top Bar -->
|
||
<header class="h-14 bg-white border-b border-gray-200 flex items-center justify-between px-6 flex-shrink-0">
|
||
<div class="flex items-center gap-2">
|
||
<div class="w-8 h-8 bg-gradient-to-br from-emerald-400 to-teal-500 rounded-lg flex items-center justify-center text-white font-bold">
|
||
<i class="fas fa-code text-sm"></i>
|
||
</div>
|
||
<span class="font-bold text-lg">WorkBuddy</span>
|
||
</div>
|
||
<div class="text-sm text-gray-600 font-medium">Agents</div>
|
||
<div class="flex items-center gap-2">
|
||
<button class="p-2 hover:bg-gray-100 rounded-lg text-gray-500">
|
||
<i class="fas fa-minus text-xs"></i>
|
||
</button>
|
||
<button class="p-2 hover:bg-gray-100 rounded-lg text-gray-500">
|
||
<i class="far fa-square text-xs"></i>
|
||
</button>
|
||
<button class="p-2 hover:bg-red-50 rounded-lg text-gray-500 hover:text-red-500">
|
||
<i class="fas fa-times text-xs"></i>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- Content Area -->
|
||
<div class="flex-1 overflow-y-auto bg-white">
|
||
<div class="max-w-6xl mx-auto px-8 py-8">
|
||
|
||
<!-- Header Section -->
|
||
<div class="flex items-start justify-between mb-8">
|
||
<div>
|
||
<h1 class="text-2xl font-bold text-gray-900 mb-1">技能</h1>
|
||
<p class="text-gray-500 text-base">赋予 WorkBuddy 更强大的能力</p>
|
||
</div>
|
||
|
||
<div class="flex items-center gap-3">
|
||
<!-- Search -->
|
||
<div class="relative">
|
||
<i class="fas fa-search absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 text-sm"></i>
|
||
<input type="text" id="skillSearch" placeholder="搜索技能"
|
||
class="search-input w-64 pl-9 pr-4 py-2 bg-white border border-gray-300 rounded-lg text-sm outline-none transition-all">
|
||
</div>
|
||
|
||
<!-- Import Button -->
|
||
<button class="import-btn flex items-center gap-2 px-4 py-2 border border-gray-300 rounded-lg text-sm font-medium text-gray-700 bg-white hover:bg-gray-50" onclick="importSkill()">
|
||
<i class="fas fa-plus text-xs"></i>
|
||
导入技能
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Installed Count -->
|
||
<div class="mb-6">
|
||
<span class="text-gray-900 font-medium">已安装</span>
|
||
<span class="ml-2 px-2 py-0.5 bg-gray-100 text-gray-600 text-xs rounded-full" id="installedCount">0</span>
|
||
</div>
|
||
|
||
<!-- Recommended Section -->
|
||
<div>
|
||
<h2 class="text-base font-semibold text-gray-900 mb-4">推荐</h2>
|
||
|
||
<!-- Skills Grid -->
|
||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4" id="skillsGrid">
|
||
|
||
<!-- Skill Card 1 -->
|
||
<div class="skill-card bg-white rounded-xl p-4 flex items-center gap-4 group cursor-pointer" data-name="find-skills">
|
||
<div class="skill-icon w-12 h-12 rounded-xl flex items-center justify-center flex-shrink-0">
|
||
<i class="fas fa-hammer text-gray-600 text-lg"></i>
|
||
</div>
|
||
<div class="flex-1 min-w-0">
|
||
<h3 class="font-semibold text-gray-900 text-sm mb-0.5">find-skills</h3>
|
||
<p class="text-gray-500 text-sm truncate">Helps users discover and install agent skills whe...</p>
|
||
</div>
|
||
<button class="add-btn w-8 h-8 rounded-full flex items-center justify-center text-gray-400 hover:text-emerald-600 flex-shrink-0" onclick="toggleSkill(this, 'find-skills')">
|
||
<i class="fas fa-plus text-sm"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Skill Card 2 -->
|
||
<div class="skill-card bg-white rounded-xl p-4 flex items-center gap-4 group cursor-pointer" data-name="workbuddy-channel-setup">
|
||
<div class="skill-icon w-12 h-12 rounded-xl flex items-center justify-center flex-shrink-0">
|
||
<i class="fas fa-hammer text-gray-600 text-lg"></i>
|
||
</div>
|
||
<div class="flex-1 min-w-0">
|
||
<h3 class="font-semibold text-gray-900 text-sm mb-0.5">workbuddy-channel-setup</h3>
|
||
<p class="text-gray-500 text-sm truncate">Automate WorkBuddy channel integration setu...</p>
|
||
</div>
|
||
<button class="add-btn w-8 h-8 rounded-full flex items-center justify-center text-gray-400 hover:text-emerald-600 flex-shrink-0" onclick="toggleSkill(this, 'workbuddy-channel-setup')">
|
||
<i class="fas fa-plus text-sm"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Skill Card 3 -->
|
||
<div class="skill-card bg-white rounded-xl p-4 flex items-center gap-4 group cursor-pointer" data-name="FBS-BookWriter">
|
||
<div class="skill-icon w-12 h-12 rounded-xl flex items-center justify-center flex-shrink-0">
|
||
<i class="fas fa-hammer text-gray-600 text-lg"></i>
|
||
</div>
|
||
<div class="flex-1 min-w-0">
|
||
<h3 class="font-semibold text-gray-900 text-sm mb-0.5">FBS-BookWriter</h3>
|
||
<p class="text-gray-500 text-sm truncate">福帮手出品 | 人机协同写书。联网校验-千书千面...</p>
|
||
</div>
|
||
<button class="add-btn w-8 h-8 rounded-full flex items-center justify-center text-gray-400 hover:text-emerald-600 flex-shrink-0" onclick="toggleSkill(this, 'FBS-BookWriter')">
|
||
<i class="fas fa-plus text-sm"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Skill Card 4 -->
|
||
<div class="skill-card bg-white rounded-xl p-4 flex items-center gap-4 group cursor-pointer" data-name="xiaohongshu">
|
||
<div class="skill-icon w-12 h-12 rounded-xl flex items-center justify-center flex-shrink-0">
|
||
<i class="fas fa-hammer text-gray-600 text-lg"></i>
|
||
</div>
|
||
<div class="flex-1 min-w-0">
|
||
<h3 class="font-semibold text-gray-900 text-sm mb-0.5">xiaohongshu</h3>
|
||
<p class="text-gray-500 text-sm truncate">小红书(RedNote)内容工具。使用场景:搜索...</p>
|
||
</div>
|
||
<button class="add-btn w-8 h-8 rounded-full flex items-center justify-center text-gray-400 hover:text-emerald-600 flex-shrink-0" onclick="toggleSkill(this, 'xiaohongshu')">
|
||
<i class="fas fa-plus text-sm"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Skill Card 5 -->
|
||
<div class="skill-card bg-white rounded-xl p-4 flex items-center gap-4 group cursor-pointer" data-name="agentmail">
|
||
<div class="skill-icon w-12 h-12 rounded-xl flex items-center justify-center flex-shrink-0">
|
||
<i class="fas fa-hammer text-gray-600 text-lg"></i>
|
||
</div>
|
||
<div class="flex-1 min-w-0">
|
||
<h3 class="font-semibold text-gray-900 text-sm mb-0.5">agentmail</h3>
|
||
<p class="text-gray-500 text-sm truncate">Email inbox for AI agents. Check messages, sen...</p>
|
||
</div>
|
||
<button class="add-btn w-8 h-8 rounded-full flex items-center justify-center text-gray-400 hover:text-emerald-600 flex-shrink-0" onclick="toggleSkill(this, 'agentmail')">
|
||
<i class="fas fa-plus text-sm"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Skill Card 6 -->
|
||
<div class="skill-card bg-white rounded-xl p-4 flex items-center gap-4 group cursor-pointer" data-name="apple-notes">
|
||
<div class="skill-icon w-12 h-12 rounded-xl flex items-center justify-center flex-shrink-0">
|
||
<i class="fas fa-hammer text-gray-600 text-lg"></i>
|
||
</div>
|
||
<div class="flex-1 min-w-0">
|
||
<h3 class="font-semibold text-gray-900 text-sm mb-0.5">apple-notes</h3>
|
||
<p class="text-gray-500 text-sm truncate">Manage Apple Notes via the `memo` CLI on ma...</p>
|
||
</div>
|
||
<button class="add-btn w-8 h-8 rounded-full flex items-center justify-center text-gray-400 hover:text-emerald-600 flex-shrink-0" onclick="toggleSkill(this, 'apple-notes')">
|
||
<i class="fas fa-plus text-sm"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Skill Card 7 -->
|
||
<div class="skill-card bg-white rounded-xl p-4 flex items-center gap-4 group cursor-pointer" data-name="apple-reminders">
|
||
<div class="skill-icon w-12 h-12 rounded-xl flex items-center justify-center flex-shrink-0">
|
||
<i class="fas fa-hammer text-gray-600 text-lg"></i>
|
||
</div>
|
||
<div class="flex-1 min-w-0">
|
||
<h3 class="font-semibold text-gray-900 text-sm mb-0.5">apple-reminders</h3>
|
||
<p class="text-gray-500 text-sm truncate">Manage Apple Reminders via the `remindctl` CL...</p>
|
||
</div>
|
||
<button class="add-btn w-8 h-8 rounded-full flex items-center justify-center text-gray-400 hover:text-emerald-600 flex-shrink-0" onclick="toggleSkill(this, 'apple-reminders')">
|
||
<i class="fas fa-plus text-sm"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Skill Card 8 -->
|
||
<div class="skill-card bg-white rounded-xl p-4 flex items-center gap-4 group cursor-pointer" data-name="blogwatcher">
|
||
<div class="skill-icon w-12 h-12 rounded-xl flex items-center justify-center flex-shrink-0">
|
||
<i class="fas fa-hammer text-gray-600 text-lg"></i>
|
||
</div>
|
||
<div class="flex-1 min-w-0">
|
||
<h3 class="font-semibold text-gray-900 text-sm mb-0.5">blogwatcher</h3>
|
||
<p class="text-gray-500 text-sm truncate">Monitor blogs and RSS/Atom feeds for updates...</p>
|
||
</div>
|
||
<button class="add-btn w-8 h-8 rounded-full flex items-center justify-center text-gray-400 hover:text-emerald-600 flex-shrink-0" onclick="toggleSkill(this, 'blogwatcher')">
|
||
<i class="fas fa-plus text-sm"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Skill Card 9 -->
|
||
<div class="skill-card bg-white rounded-xl p-4 flex items-center gap-4 group cursor-pointer" data-name="cos-vectors">
|
||
<div class="skill-icon w-12 h-12 rounded-xl flex items-center justify-center flex-shrink-0">
|
||
<i class="fas fa-hammer text-gray-600 text-lg"></i>
|
||
</div>
|
||
<div class="flex-1 min-w-0">
|
||
<h3 class="font-semibold text-gray-900 text-sm mb-0.5">cos-vectors</h3>
|
||
<p class="text-gray-500 text-sm truncate">Manage Tencent Cloud COS vector buckets via ...</p>
|
||
</div>
|
||
<button class="add-btn w-8 h-8 rounded-full flex items-center justify-center text-gray-400 hover:text-emerald-600 flex-shrink-0" onclick="toggleSkill(this, 'cos-vectors')">
|
||
<i class="fas fa-plus text-sm"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Skill Card 10 -->
|
||
<div class="skill-card bg-white rounded-xl p-4 flex items-center gap-4 group cursor-pointer" data-name="gifgrep">
|
||
<div class="skill-icon w-12 h-12 rounded-xl flex items-center justify-center flex-shrink-0">
|
||
<i class="fas fa-hammer text-gray-600 text-lg"></i>
|
||
</div>
|
||
<div class="flex-1 min-w-0">
|
||
<h3 class="font-semibold text-gray-900 text-sm mb-0.5">gifgrep</h3>
|
||
<p class="text-gray-500 text-sm truncate">Search GIF providers with CLI/TUI, download re...</p>
|
||
</div>
|
||
<button class="add-btn w-8 h-8 rounded-full flex items-center justify-center text-gray-400 hover:text-emerald-600 flex-shrink-0" onclick="toggleSkill(this, 'gifgrep')">
|
||
<i class="fas fa-plus text-sm"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Skill Card 11 -->
|
||
<div class="skill-card bg-white rounded-xl p-4 flex items-center gap-4 group cursor-pointer" data-name="github">
|
||
<div class="skill-icon w-12 h-12 rounded-xl flex items-center justify-center flex-shrink-0">
|
||
<i class="fas fa-hammer text-gray-600 text-lg"></i>
|
||
</div>
|
||
<div class="flex-1 min-w-0">
|
||
<h3 class="font-semibold text-gray-900 text-sm mb-0.5">github</h3>
|
||
<p class="text-gray-500 text-sm truncate">Interact with GitHub using the `gh` CLI. Use `gh ...</p>
|
||
</div>
|
||
<button class="add-btn w-8 h-8 rounded-full flex items-center justify-center text-gray-400 hover:text-emerald-600 flex-shrink-0" onclick="toggleSkill(this, 'github')">
|
||
<i class="fas fa-plus text-sm"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Skill Card 12 -->
|
||
<div class="skill-card bg-white rounded-xl p-4 flex items-center gap-4 group cursor-pointer" data-name="gog">
|
||
<div class="skill-icon w-12 h-12 rounded-xl flex items-center justify-center flex-shrink-0">
|
||
<i class="fas fa-hammer text-gray-600 text-lg"></i>
|
||
</div>
|
||
<div class="flex-1 min-w-0">
|
||
<h3 class="font-semibold text-gray-900 text-sm mb-0.5">gog</h3>
|
||
<p class="text-gray-500 text-sm truncate">Google Workspace CLI for Gmail, Calendar, Driv...</p>
|
||
</div>
|
||
<button class="add-btn w-8 h-8 rounded-full flex items-center justify-center text-gray-400 hover:text-emerald-600 flex-shrink-0" onclick="toggleSkill(this, 'gog')">
|
||
<i class="fas fa-plus text-sm"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Skill Card 13 -->
|
||
<div class="skill-card bg-white rounded-xl p-4 flex items-center gap-4 group cursor-pointer" data-name="healthcheck">
|
||
<div class="skill-icon w-12 h-12 rounded-xl flex items-center justify-center flex-shrink-0">
|
||
<i class="fas fa-hammer text-gray-600 text-lg"></i>
|
||
</div>
|
||
<div class="flex-1 min-w-0">
|
||
<h3 class="font-semibold text-gray-900 text-sm mb-0.5">healthcheck</h3>
|
||
<p class="text-gray-500 text-sm truncate">Track water and sleep with JSON file storage.</p>
|
||
</div>
|
||
<button class="add-btn w-8 h-8 rounded-full flex items-center justify-center text-gray-400 hover:text-emerald-600 flex-shrink-0" onclick="toggleSkill(this, 'healthcheck')">
|
||
<i class="fas fa-plus text-sm"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Skill Card 14 -->
|
||
<div class="skill-card bg-white rounded-xl p-4 flex items-center gap-4 group cursor-pointer" data-name="himalaya">
|
||
<div class="skill-icon w-12 h-12 rounded-xl flex items-center justify-center flex-shrink-0">
|
||
<i class="fas fa-hammer text-gray-600 text-lg"></i>
|
||
</div>
|
||
<div class="flex-1 min-w-0">
|
||
<h3 class="font-semibold text-gray-900 text-sm mb-0.5">himalaya</h3>
|
||
<p class="text-gray-500 text-sm truncate">CLI to manage emails via IMAP/SMTP. Use `him...</p>
|
||
</div>
|
||
<button class="add-btn w-8 h-8 rounded-full flex items-center justify-center text-gray-400 hover:text-emerald-600 flex-shrink-0" onclick="toggleSkill(this, 'himalaya')">
|
||
<i class="fas fa-plus text-sm"></i>
|
||
</button>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Empty State (Hidden by default) -->
|
||
<div id="emptyState" class="hidden mt-12 text-center py-12">
|
||
<div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
||
<i class="fas fa-search text-gray-400 text-2xl"></i>
|
||
</div>
|
||
<p class="text-gray-500">未找到相关技能</p>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
<!-- Toast Notification -->
|
||
<div id="toast" class="fixed bottom-8 right-8 bg-gray-900 text-white px-6 py-3 rounded-xl shadow-2xl transform translate-y-20 opacity-0 transition-all duration-300 flex items-center gap-3 z-50">
|
||
<i class="fas fa-check-circle text-emerald-400"></i>
|
||
<span id="toastMessage">操作成功</span>
|
||
</div>
|
||
|
||
<script>
|
||
let installedCount = 0;
|
||
const installedSkills = new Set();
|
||
|
||
// Toggle skill installation
|
||
function toggleSkill(btn, skillName) {
|
||
const icon = btn.querySelector('i');
|
||
|
||
if (installedSkills.has(skillName)) {
|
||
// Uninstall
|
||
installedSkills.delete(skillName);
|
||
btn.classList.remove('added');
|
||
icon.classList.remove('fa-check');
|
||
icon.classList.add('fa-plus');
|
||
installedCount--;
|
||
showToast(`已卸载 ${skillName}`);
|
||
} else {
|
||
// Install
|
||
installedSkills.add(skillName);
|
||
btn.classList.add('added');
|
||
icon.classList.remove('fa-plus');
|
||
icon.classList.add('fa-check');
|
||
installedCount++;
|
||
showToast(`已安装 ${skillName}`);
|
||
}
|
||
|
||
document.getElementById('installedCount').textContent = installedCount;
|
||
}
|
||
|
||
// Import skill action
|
||
function importSkill() {
|
||
showToast('请选择要导入的技能文件');
|
||
}
|
||
|
||
// Show toast notification
|
||
function showToast(message) {
|
||
const toast = document.getElementById('toast');
|
||
const toastMessage = document.getElementById('toastMessage');
|
||
|
||
toastMessage.textContent = message;
|
||
toast.classList.remove('translate-y-20', 'opacity-0');
|
||
|
||
setTimeout(() => {
|
||
toast.classList.add('translate-y-20', 'opacity-0');
|
||
}, 2500);
|
||
}
|
||
|
||
// Search functionality
|
||
document.getElementById('skillSearch').addEventListener('input', function(e) {
|
||
const searchTerm = e.target.value.toLowerCase();
|
||
const cards = document.querySelectorAll('.skill-card');
|
||
let visibleCount = 0;
|
||
|
||
cards.forEach(card => {
|
||
const name = card.getAttribute('data-name').toLowerCase();
|
||
const desc = card.querySelector('p').textContent.toLowerCase();
|
||
|
||
if (name.includes(searchTerm) || desc.includes(searchTerm)) {
|
||
card.style.display = 'flex';
|
||
visibleCount++;
|
||
} else {
|
||
card.style.display = 'none';
|
||
}
|
||
});
|
||
|
||
// Show/hide empty state
|
||
const emptyState = document.getElementById('emptyState');
|
||
if (visibleCount === 0) {
|
||
emptyState.classList.remove('hidden');
|
||
} else {
|
||
emptyState.classList.add('hidden');
|
||
}
|
||
});
|
||
|
||
// Add stagger animation on load
|
||
window.addEventListener('load', () => {
|
||
const cards = document.querySelectorAll('.skill-card');
|
||
cards.forEach((card, index) => {
|
||
card.style.opacity = '0';
|
||
card.style.transform = 'translateY(10px)';
|
||
setTimeout(() => {
|
||
card.style.transition = 'all 0.3s ease';
|
||
card.style.opacity = '1';
|
||
card.style.transform = 'translateY(0)';
|
||
}, index * 30);
|
||
});
|
||
});
|
||
</script>
|
||
</body>
|
||
</html> |