---

## 路径：`recruiter_navigator\web\templates\index.html`

```html
{% extends "base.html" %}

{% block title %}Recruiter Tool Navigator{% endblock %}

{% block head %}
<link rel="stylesheet" href="/static/css/common.css">
{% endblock %}

{% block content %}
<div x-data="toolNavigator()" class="min-h-screen">
    <!-- 顶部导航 -->
    <header class="bg-white/80 backdrop-blur-xl border-b border-slate-200/80 sticky top-0 z-40">
        <div class="max-w-7xl mx-auto px-6 py-4 flex items-center justify-between">
            <div class="flex items-center gap-4">
                <div class="w-10 h-10 rounded-xl bg-gradient-to-br from-blue-500 to-indigo-600 flex items-center justify-center shadow-lg shadow-blue-500/20">
                    <span class="text-white text-lg font-bold">R</span>
                </div>
                <div>
                    <h1 class="text-lg font-bold text-slate-900 tracking-tight">Recruiter Tool Navigator</h1>
                    <p class="text-xs text-slate-400 font-medium">{{ tools|length }} tools · 一键查阅 · 终端启动</p>
                </div>
            </div>
            <div class="flex items-center gap-3">
                <a href="/home" class="btn-secondary flex items-center gap-2">
                    <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/>
                    </svg>
                    流程图
                </a>
                <div class="relative">
                    <svg class="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
                    </svg>
                    <input
                        type="text"
                        x-model="searchQuery"
                        placeholder="搜索工具..."
                        class="search-input"
                    />
                </div>
            </div>
        </div>
    </header>

    <!-- 分类标签 -->
    <div class="bg-white border-b border-slate-200/80">
        <div class="max-w-7xl mx-auto px-6">
            <div class="flex gap-2 py-3 overflow-x-auto">
                <button
                    @click="activeCategory = 'all'"
                    :class="activeCategory === 'all' ? 'active' : ''"
                    class="category-btn"
                >
                    全部 ({{ tools|length }})
                </button>
                {% for cat, count in categories.items() %}
                <button
                    @click="activeCategory = '{{ cat.value }}'"
                    :class="activeCategory === '{{ cat.value }}' ? 'active' : ''"
                    class="category-btn"
                >
                    {{ cat_labels[cat.value] }} ({{ count }})
                </button>
                {% endfor %}
            </div>
        </div>
    </div>

    <!-- 工具卡片网格 -->
    <div class="max-w-7xl mx-auto px-6 py-6">
        <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
            <template x-for="tool in filteredTools" :key="tool.name">
                <div
                    @click="openDetail(tool.name)"
                    class="tool-card group"
                >
                    <div class="flex items-start justify-between mb-3">
                        <span class="text-2xl" x-text="getCategoryIcon(tool.category)"></span>
                        <span
                            class="mode-badge"
                            :class="getModeBadgeClass(tool.launch_mode)"
                            x-text="tool.launch_mode.toUpperCase()"
                        ></span>
                    </div>
                    <h3 class="font-semibold text-slate-900 mb-1 group-hover:text-blue-600 transition-colors" x-text="tool.display_name"></h3>
                    <p class="text-sm text-slate-500 mb-1 font-mono" x-text="tool.name"></p>
                    <p class="text-sm text-slate-600 line-clamp-2 mb-3" x-text="tool.description"></p>
                    <div class="flex flex-wrap gap-1 mb-3">
                        <template x-for="tag in tool.tags.slice(0, 3)" :key="tag">
                            <span class="tag" x-text="tag"></span>
                        </template>
                    </div>
                    <button class="btn-primary w-full">
                        查看详情 →
                    </button>
                </div>
            </template>
        </div>

        <!-- 空状态 -->
        <div x-show="filteredTools.length === 0" class="text-center py-20">
            <div class="text-6xl mb-4 opacity-20">🔍</div>
            <p class="text-slate-400 text-lg font-medium">没有找到匹配的工具</p>
            <p class="text-slate-300 text-sm mt-2">尝试其他搜索关键词</p>
        </div>
    </div>

    <!-- 详情抽屉 -->
    <div
        x-show="showDetail"
        x-cloak
        class="fixed inset-0 z-50 flex justify-end"
        @keydown.escape.window="showDetail = false"
    >
        <!-- 遮罩 -->
        <div class="absolute inset-0 bg-black/40" @click="showDetail = false"></div>
        <!-- 抽屉面板 -->
        <div class="relative w-full max-w-4xl bg-white shadow-2xl overflow-y-auto">
            <template x-if="activeTool">
                <div class="p-6">
                    <!-- 头部 -->
                    <div class="flex items-start justify-between mb-6">
                        <div>
                            <div class="flex items-center gap-2 mb-2">
                                <span class="text-3xl" x-text="getCategoryIcon(activeTool.category)"></span>
                                <h2 class="text-2xl font-bold text-gray-900" x-text="activeTool.display_name"></h2>
                            </div>
                            <p class="text-gray-500 font-mono text-sm" x-text="activeTool.name"></p>
                        </div>
                        <button @click="showDetail = false" class="text-gray-400 hover:text-gray-600 p-2">
                            <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
                            </svg>
                        </button>
                    </div>

                    <!-- 终端命令指引区域 -->
                    <div class="bg-gray-900 rounded-xl p-5 mb-6">
                        <div class="flex items-center gap-2 mb-3">
                            <span class="text-green-400 text-sm font-semibold">⌨ 终端命令</span>
                            <span class="text-gray-500 text-xs">— 请在本地终端中执行以下命令</span>
                        </div>
                        <!-- 安装命令 -->
                        <div class="mb-2">
                            <span class="text-gray-500 text-xs block mb-1">安装</span>
                            <div class="flex items-center justify-between bg-gray-800 rounded-lg px-4 py-2">
                                <code class="text-green-400 font-mono text-sm" x-text="activeTool.launch_commands?.install || ('pip install ' + activeTool.name)"></code>
                                <button
                                    @click="copyToClipboard(activeTool.launch_commands?.install || ('pip install ' + activeTool.name))"
                                    class="text-gray-400 hover:text-white ml-4 text-sm"
                                    title="复制"
                                >📋 复制</button>
                            </div>
                        </div>
                        <!-- 运行命令 -->
                        <div>
                            <span class="text-gray-500 text-xs block mb-1">运行</span>
                            <div class="flex items-center justify-between bg-gray-800 rounded-lg px-4 py-2">
                                <code class="text-yellow-400 font-mono text-sm" x-text="activeTool.launch_commands?.run || activeTool.launch?.command"></code>
                                <button
                                    @click="copyToClipboard(activeTool.launch_commands?.run || activeTool.launch?.command)"
                                    class="text-gray-400 hover:text-white ml-4 text-sm"
                                    title="复制"
                                >📋 复制</button>
                            </div>
                        </div>
                        <!-- Web 模式提示 -->
                        <template x-if="activeTool.launch?.mode === 'web' && activeTool.launch?.web_port">
                            <div class="mt-2 text-blue-400 text-xs">
                                💡 启动后在浏览器中访问 http://localhost:<span x-text="activeTool.launch.web_port"></span>
                            </div>
                        </template>
                    </div>

                    <!-- Tab 切换 -->
                    <div class="border-b border-gray-200 mb-6">
                        <nav class="flex gap-6 overflow-x-auto">
                            <button
                                @click="activeTab = 'readme'"
                                :class="activeTab === 'readme' ? 'border-blue-600 text-blue-600' : 'border-transparent text-gray-500 hover:text-gray-700'"
                                class="pb-3 border-b-2 font-medium text-sm transition-colors whitespace-nowrap"
                            >📖 项目介绍</button>
                            <button
                                @click="activeTab = 'usecases'"
                                :class="activeTab === 'usecases' ? 'border-blue-600 text-blue-600' : 'border-transparent text-gray-500 hover:text-gray-700'"
                                class="pb-3 border-b-2 font-medium text-sm transition-colors whitespace-nowrap"
                            >🎯 使用场景</button>
                            <button
                                @click="activeTab = 'workflow'"
                                :class="activeTab === 'workflow' ? 'border-blue-600 text-blue-600' : 'border-transparent text-gray-500 hover:text-gray-700'"
                                class="pb-3 border-b-2 font-medium text-sm transition-colors whitespace-nowrap"
                            >🔗 工作流</button>
                            <button
                                @click="activeTab = 'quickstart'"
                                :class="activeTab === 'quickstart' ? 'border-blue-600 text-blue-600' : 'border-transparent text-gray-500 hover:text-gray-700'"
                                class="pb-3 border-b-2 font-medium text-sm transition-colors whitespace-nowrap"
                            >🚀 新手上路</button>
                        </nav>
                    </div>

                    <!-- Tab 内容: 项目介绍 (PyPI README) -->
                    <div x-show="activeTab === 'readme'" class="markdown-body" x-html="renderMarkdown(activeTool.docs?.readme || '暂无项目介绍')"></div>

                    <!-- Tab 内容: 使用场景 -->
                    <div x-show="activeTab === 'usecases'">
                        <template x-if="activeTool.docs?.use_cases?.length">
                            <div class="space-y-3">
                                <template x-for="(uc, i) in activeTool.docs.use_cases" :key="i">
                                    <div class="flex gap-3 p-4 bg-blue-50 rounded-lg">
                                        <span class="text-blue-600 font-bold text-lg shrink-0">🎯</span>
                                        <p class="text-gray-700 text-sm leading-relaxed" x-text="uc"></p>
                                    </div>
                                </template>
                            </div>
                        </template>
                        <template x-if="!activeTool.docs?.use_cases?.length">
                            <p class="text-gray-400">暂无使用场景</p>
                        </template>
                    </div>

                    <!-- Tab 内容: 工作流 -->
                    <div x-show="activeTab === 'workflow'">
                        <div class="space-y-4">
                            <!-- 上游工具 -->
                            <template x-if="activeTool.docs?.workflow?.prev_tools?.length">
                                <div>
                                    <h4 class="text-sm font-semibold text-gray-500 mb-2">上游工具（前置步骤）</h4>
                                    <div class="flex flex-wrap gap-2">
                                        <template x-for="pt in activeTool.docs.workflow.prev_tools" :key="pt">
                                            <button
                                                @click="openDetail(pt)"
                                                class="px-3 py-1.5 bg-green-100 text-green-700 rounded-lg text-sm font-medium hover:bg-green-200 transition-colors"
                                                x-text="pt"
                                            ></button>
                                        </template>
                                    </div>
                                </div>
                            </template>

                            <!-- 当前工具 -->
                            <div class="flex items-center gap-2">
                                <template x-if="activeTool.docs?.workflow?.prev_tools?.length">
                                    <span class="text-gray-400 text-lg">→</span>
                                </template>
                                <div class="px-4 py-2 bg-blue-600 text-white rounded-lg font-semibold text-sm">
                                    ⭐ <span x-text="activeTool.name"></span>
                                </div>
                                <template x-if="activeTool.docs?.workflow?.next_tools?.length">
                                    <span class="text-gray-400 text-lg">→</span>
                                </template>
                            </div>

                            <!-- 下游工具 -->
                            <template x-if="activeTool.docs?.workflow?.next_tools?.length">
                                <div>
                                    <h4 class="text-sm font-semibold text-gray-500 mb-2">下游工具（后续步骤）</h4>
                                    <div class="flex flex-wrap gap-2">
                                        <template x-for="nt in activeTool.docs.workflow.next_tools" :key="nt">
                                            <button
                                                @click="openDetail(nt)"
                                                class="px-3 py-1.5 bg-purple-100 text-purple-700 rounded-lg text-sm font-medium hover:bg-purple-200 transition-colors"
                                                x-text="nt"
                                            ></button>
                                        </template>
                                    </div>
                                </div>
                            </template>

                            <template x-if="!activeTool.docs?.workflow?.prev_tools?.length && !activeTool.docs?.workflow?.next_tools?.length">
                                <p class="text-gray-400">暂无工作流推荐</p>
                            </template>
                        </div>
                    </div>

                    <!-- Tab 内容: 新手上路 -->
                    <div x-show="activeTab === 'quickstart'">
                        <template x-if="activeTool.docs?.quick_start">
                            <div class="space-y-4">
                                <!-- 安装 -->
                                <div>
                                    <h4 class="text-sm font-semibold text-gray-500 mb-2">1. 安装</h4>
                                    <div class="bg-gray-900 text-green-400 p-4 rounded-lg font-mono text-sm flex items-center justify-between">
                                        <code x-text="activeTool.docs.quick_start.install"></code>
                                        <button
                                            @click="copyToClipboard(activeTool.docs.quick_start.install)"
                                            class="text-gray-400 hover:text-white ml-4 text-sm"
                                            title="复制"
                                        >📋 复制</button>
                                    </div>
                                </div>
                                <!-- 运行示例 -->
                                <div>
                                    <h4 class="text-sm font-semibold text-gray-500 mb-2">2. 运行示例</h4>
                                    <div class="bg-gray-900 text-green-400 p-4 rounded-lg font-mono text-sm flex items-center justify-between">
                                        <code x-text="activeTool.docs.quick_start.command_example"></code>
                                        <button
                                            @click="copyToClipboard(activeTool.docs.quick_start.command_example)"
                                            class="text-gray-400 hover:text-white ml-4 text-sm"
                                            title="复制"
                                        >📋 复制</button>
                                    </div>
                                </div>
                                <!-- 预期输出 -->
                                <div>
                                    <h4 class="text-sm font-semibold text-gray-500 mb-2">3. 预期输出</h4>
                                    <p class="text-gray-700 text-sm bg-gray-50 p-4 rounded-lg leading-relaxed" x-text="activeTool.docs.quick_start.expected_output"></p>
                                </div>
                            </div>
                        </template>
                        <template x-if="!activeTool.docs?.quick_start">
                            <p class="text-gray-400">暂无新手指引</p>
                        </template>
                    </div>

                    <!-- 底部信息 -->
                    <div class="mt-8 pt-6 border-t border-gray-200">
                        <div class="flex items-center justify-between">
                            <div class="flex flex-wrap gap-2">
                                <template x-for="tag in activeTool.docs?.tags || []" :key="tag">
                                    <span class="text-xs bg-gray-100 text-gray-600 px-2 py-1 rounded" x-text="tag"></span>
                                </template>
                            </div>
                            <a
                                :href="activeTool.pypi_url"
                                target="_blank"
                                class="text-sm text-blue-600 hover:underline"
                            >PyPI 页面 →</a>
                        </div>
                    </div>
                </div>
            </template>
        </div>
    </div>
</div>

<script>
function toolNavigator() {
    return {
        searchQuery: '',
        activeCategory: 'all',
        showDetail: false,
        activeTool: null,
        activeTab: 'readme',
        allTools: {{ tools_json | safe }},

        get filteredTools() {
            let result = this.allTools;
            if (this.activeCategory !== 'all') {
                result = result.filter(t => t.category === this.activeCategory);
            }
            if (this.searchQuery.trim()) {
                const q = this.searchQuery.toLowerCase();
                result = result.filter(t =>
                    t.name.toLowerCase().includes(q) ||
                    t.display_name.toLowerCase().includes(q) ||
                    t.description.toLowerCase().includes(q) ||
                    t.tags.some(tag => tag.toLowerCase().includes(q))
                );
            }
            return result;
        },

        async openDetail(toolName) {
            try {
                const resp = await fetch(`/api/tool/${toolName}`);
                if (resp.ok) {
                    this.activeTool = await resp.json();
                    this.activeTab = 'readme';
                    this.showDetail = true;
                }
            } catch (e) {
                console.error('Failed to load tool detail:', e);
            }
        },

        getCategoryIcon(category) {
            const icons = {
                search: '🔍',
                resume: '📄',
                outreach: '✉️',
                data: '📊',
                infra: '🔧'
            };
            return icons[category] || '📦';
        },

        getModeBadgeClass(mode) {
            const classes = {
                cli: 'cli',
                web: 'web',
                interactive: 'interactive'
            };
            return classes[mode] || '';
        },

        renderMarkdown(text) {
            if (!text) return '';
            return marked.parse(text);
        },

        copyToClipboard(text) {
            navigator.clipboard.writeText(text).then(() => {
                // 简单反馈
                const btn = event.currentTarget;
                const original = btn.textContent;
                btn.textContent = '✅ 已复制';
                setTimeout(() => { btn.textContent = original; }, 1500);
            });
        }
    };
}
</script>
{% endblock %}

```

---