feat(design): Riso 风格页面设计与静态原型(首页/列表/详情/管理台/登录)

This commit is contained in:
cheney 2026-08-26 16:01:19 +08:00
commit c47bb15d8c
8 changed files with 3047 additions and 0 deletions

98
design/DESIGN.md Normal file
View File

@ -0,0 +1,98 @@
# Awesome Index · 页面设计方案
> 把网上牛逼的东西收进一个库:给人用,也给 AI 用。
> 本文档是视觉方向的唯一事实来源;实现时所有颜色与字体决策从这里派生。
## 1. 主题定位
- **主体**一个人工精选的「牛逼东西」数据库——开源软件、微服务、SaaS、网站、工具、应用、脚本、插件。
- **受众**:开发者(人类读者)+ AI AgentMCP 机器读者)。**双读者**是本站与普通导航站的本质区别。
- **首页的唯一职责**让两类读者都最快拿到想要的东西——人用搜索框AI 用 MCP。
## 2. 设计方向Riso 孔版印刷 × 数据档案
从「收藏/编目/印刷目录册」的世界取材:孔版印刷的双色错位、档案卡片的厚描边、
等宽字的编目批注。明确避开三种 AI 默认脸:
①暖奶油底+衬线大字+赤陶色;②近黑底+荧光绿/朱红单色;③报纸细线+直角密排。
### 色彩 token
| Token | 值 | 用途 |
|---|---|---|
| `--paper` | `#F0F1EC` | 页面底色:冷灰绿纸面(非暖奶油) |
| `--paper-raised` | `#FBFBF7` | 卡片/输入器具 |
| `--ink` | `#171A21` | 蓝黑油墨:正文、主按钮、描边 |
| `--ink-dim` | `rgba(23,26,33,.62)` | 次级文字 |
| `--riso-blue` | `#2436E8` | 电光群青:唯一强调色(平面色块,禁止渐变) |
| `--riso-coral` | `#FF4D2E` | 错版珊瑚红极少量标记logo 错位、必填星号、在线点) |
| `--panel` | `#10131A` | MCP 面板、页脚的深墨底 |
规则:蓝色只以「实心色块 / 错位阴影 / 记号笔划线」出现;珊瑚红全页不超过 5 处。
### 字体
| 角色 | 字体 | 说明 |
|---|---|---|
| 展示 | Bricolage Grotesque 800CJK 回退 Noto Sans SC 900 | 仅 H1/H2 与词标,克制使用 |
| 正文/UI | Hanken GroteskCJK 回退 Noto Sans SC | 400/500/700 |
| 数据/注释 | IBM Plex Mono 400600 | 编目注释、代码、标签、表格数字 |
字号阶clamp 流式):`12 / 13 / 14 / 16 / 18 / 22 / clamp(30→64) 展示级`。
### 布局概念
```
首屏 ~/awesome-index ← 编目注释行 ┐ 左栏
把网上牛逼的东西, │
收进一个好用的库。 ← 记号笔划线强调 │
[ 🔍 输入需求关键字…… ] [搜索] ← 首屏主对象 │
→ mcp: search_entries({ q: "…" }) ← 实时回显(签名元素) │
[● 给 AI 用?本站提供 MCP 接口 ↓] ← 锚点滚到第二屏 │
收录 1,284 · 标签 96 … ← 元信息一行 ┘
机读 JSON 面板 ⇄ ┐ 右栏
人读标本卡(叠放) │ 数据标本
[随机游览] ┘
第二屏 // 同一个库,两种读者
「复制给 Agent」一句话指令条
┌─────────── 深墨面板 ───────────┐
│ MCP 端点卡 │ 01 加配置 │
│ honor3.com/mcp │ 02 看工具表 │
│ [复制] ● 在线 │ 03 直接调用 │
└────────────────────────────────┘
第三屏 最近收录:[卡片][卡片][卡片][卡片]
页脚 深墨高页脚:品牌栏 / 快速反馈表单 / 导航(含管理入口) / 版权条
```
### 签名元素:双读者注释系统
每个主要区块左上角有一条 IBM Plex Mono 小字「机器等价物」批注
(如 `// mcp.tools: search_entries, get_entry, random_entry, list_tags`
详情页提供 人读 ⇄ 机读(JSON) 视角切换。结构本身在陈述事实:这个站服务两种读者。
### 动效(一处编排,其余安静)
- 首屏加载:标题两行依次上浮 → 搜索框浮现 → 回显行打字一次。
- 卡片 hover向左上位移 + 蓝色错位硬阴影(印刷套色感)。
- 全局尊重 `prefers-reduced-motion`;焦点态为 3px 群青外描边。
## 3. 文案原则
主动词、句式一致:「搜索」「复制→已复制」「发送→已收到」;
错误不道歉、直接给办法;空状态是行动邀请。
联系admin@honor3.com。
## 4. 原型文件
```
design/prototype/
├── index.html 首页(首屏 / MCP 第二屏 / 最近收录第三屏)
├── login.html 管理台登录人工通道Agent 走 MCP
├── list.html 列表页(左侧嵌套标签树过滤)
├── detail.html 详情页(元数据 + 评论 + 机读视图)
├── admin.html 管理台(账号/标签/内容/评论/内容源 五个分区)
└── assets/{css/main.css, js/main.js}
```
原型为纯静态演示数据;正式实现按技术选型接入 DuckDB + JS 后端 + Docker。

245
design/prototype/admin.html Normal file
View File

@ -0,0 +1,245 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>管理台 · Awesome Index</title>
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='4' y='4' width='20' height='20' rx='5' fill='%232436E8'/%3E%3Crect x='10' y='10' width='18' height='18' rx='5' fill='none' stroke='%23FF4D2E' stroke-width='2.5'/%3E%3C/svg%3E" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,800&family=Hanken+Grotesk:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600&family=Noto+Sans+SC:wght@400;500;700;900&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="assets/css/main.css" />
</head>
<body>
<header class="topbar">
<div class="container topbar-inner">
<a class="brand" href="index.html">
<span class="brand-mark"><i></i><i></i></span>
AWESOME·INDEX
</a>
<nav class="topnav" aria-label="主导航">
<a href="index.html">首页</a>
<a href="list.html">浏览全部</a>
<a href="admin.html" aria-current="page">管理入口</a>
</nav>
<button class="btn btn-sm nav-toggle" aria-expanded="false">菜单</button>
</div>
</header>
<div class="admin-shell">
<!-- 侧栏 -->
<nav class="admin-nav" aria-label="管理分区">
<h4>管理台</h4>
<button type="button" data-section="sec-accounts" aria-current="true">账号管理</button>
<button type="button" data-section="sec-tags" aria-current="false">标签管理</button>
<button type="button" data-section="sec-content" aria-current="false">内容管理</button>
<button type="button" data-section="sec-comments" aria-current="false">评论管理</button>
<button type="button" data-section="sec-sources" aria-current="false">内容源</button>
</nav>
<main class="admin-main">
<!-- 账号管理 -->
<section id="sec-accounts">
<p class="anno">// table: accounts · role: admin | editor | viewer</p>
<h1>账号管理</h1>
<p class="admin-desc">管理可以登录管理台的账号与角色。</p>
<div class="admin-toolbar">
<input class="input" type="search" placeholder="搜索用户名…" />
<div class="spacer"></div>
<button class="btn btn-primary btn-sm" type="button">新增账号</button>
</div>
<table class="data-table">
<thead><tr><th>用户名</th><th>角色</th><th>状态</th><th>最后登录</th><th style="text-align:right">操作</th></tr></thead>
<tbody>
<tr><td><b>admin</b></td><td>admin</td><td><span class="status-pill status-ok">active</span></td><td class="mono">2026-08-26 09:14</td>
<td><div class="row-actions"><button class="btn btn-sm" type="button">编辑</button><button class="btn btn-sm btn-danger" type="button" data-demo-danger="原型演示:未删除账号">删除</button></div></td></tr>
<tr><td><b>editor.lin</b></td><td>editor</td><td><span class="status-pill status-ok">active</span></td><td class="mono">2026-08-25 21:40</td>
<td><div class="row-actions"><button class="btn btn-sm" type="button">编辑</button><button class="btn btn-sm btn-danger" type="button" data-demo-danger="原型演示:未删除账号">删除</button></div></td></tr>
<tr><td><b>ai-ingest</b></td><td>editorAI 接口)</td><td><span class="status-pill status-warn">受限</span></td><td class="mono">2026-08-26 07:02</td>
<td><div class="row-actions"><button class="btn btn-sm" type="button">编辑</button><button class="btn btn-sm btn-danger" type="button" data-demo-danger="原型演示:未删除账号">删除</button></div></td></tr>
</tbody>
</table>
</section>
<!-- 标签管理 -->
<section id="sec-tags" class="active">
<p class="anno">// tree: tags · 支持 嵌套 / 移动 / 删除(删除前需确认子标签归属)</p>
<h1>标签管理</h1>
<p class="admin-desc">拖拽调整层级与顺序;删除父标签时其子标签自动上移一级。</p>
<div class="tagmgr">
<div class="panel-box">
<h3>标签树 <span class="mono" style="font-weight:400;font-size:12px;color:var(--ink-dim)">(点击 ▶ 展开)</span></h3>
<ul class="tag-tree">
<li>
<button class="tree-row" type="button" data-tree="t-lang" aria-expanded="true"><span class="tw"></span> 编程语言 <span class="cnt">96</span></button>
<ul class="tag-children open" id="t-lang">
<li><button class="tree-row" type="button" data-tree="t-js" aria-expanded="true"><span class="tw"></span> JavaScript / TS <span class="cnt">41</span></button>
<ul class="tag-children open" id="t-js">
<li><button class="tree-row" type="button"><span class="tw"></span> Node.js <span class="cnt">22</span></button></li>
<li><button class="tree-row" type="button"><span class="tw"></span> Deno <span class="cnt">5</span></button></li>
</ul>
</li>
<li><button class="tree-row" type="button"><span class="tw"></span> Rust <span class="cnt">28</span></button></li>
<li><button class="tree-row" type="button"><span class="tw"></span> Go <span class="cnt">19</span></button></li>
</ul>
</li>
<li>
<button class="tree-row" type="button" data-tree="t-form" aria-expanded="false"><span class="tw"></span> 形态 <span class="cnt">58</span></button>
<ul class="tag-children" id="t-form">
<li><button class="tree-row" type="button"><span class="tw"></span> CLI <span class="cnt">31</span></button></li>
<li><button class="tree-row" type="button"><span class="tw"></span> 自托管 <span class="cnt">18</span></button></li>
<li><button class="tree-row" type="button"><span class="tw"></span> Docker 就绪 <span class="cnt">9</span></button></li>
</ul>
</li>
<li><button class="tree-row" type="button"><span class="tw"></span> AI 相关 <span class="cnt">34</span></button></li>
</ul>
</div>
<div class="panel-box">
<h3>编辑标签:<span class="mono" style="font-size:13px">JavaScript / TS</span></h3>
<form data-demo-submit="标签已保存">
<p style="font-size:13px;color:var(--ink-dim);margin-bottom:6px">名称</p>
<input class="input" value="JavaScript / TS" style="margin-bottom:14px" />
<p style="font-size:13px;color:var(--ink-dim);margin-bottom:6px">上级标签</p>
<select class="select" style="width:100%;margin-bottom:14px">
<option>编程语言</option>
<option>— 移到顶层 —</option>
</select>
<p style="font-size:13px;color:var(--ink-dim);margin-bottom:6px">排序权重</p>
<input class="input" value="10" type="number" style="margin-bottom:18px;width:120px" />
<div style="display:flex;gap:10px">
<button class="btn btn-primary btn-sm" type="submit">保存修改</button>
<button class="btn btn-sm btn-danger" type="button" data-demo-danger="原型演示:未删除标签">删除此标签</button>
</div>
</form>
<hr style="border:0;border-top:1.5px solid var(--ink-faint);margin:20px 0" />
<form style="display:flex;gap:10px" data-demo-submit="新标签已创建">
<input class="input" placeholder="新增子标签…" required />
<button class="btn btn-sm" type="submit">新增到该组</button>
</form>
</div>
</div>
</section>
<!-- 内容管理 -->
<section id="sec-content" hidden>
<p class="anno">// table: entries · 状态 active | greyed | pending</p>
<h1>内容管理</h1>
<p class="admin-desc">全部收录条目。灰掉 = 暂不可见但保留数据;删除为物理删除,需二次确认。</p>
<div class="stat-strip">
<div class="stat-cell"><b>1,284</b><span>总条目</span></div>
<div class="stat-cell"><b>1,241</b><span>active</span></div>
<div class="stat-cell"><b>31</b><span>greyed已灰掉</span></div>
<div class="stat-cell"><b>12</b><span>pending 待核验</span></div>
</div>
<div class="admin-toolbar">
<input class="input" type="search" placeholder="搜索标题 / 描述…" value="" />
<select class="select"><option>全部类型</option><option>工具</option><option>微服务</option><option>SaaS</option><option>网站</option><option>应用</option><option>脚本</option><option>插件</option></select>
<select class="select"><option>全部状态</option><option>active</option><option>greyed</option><option>pending</option></select>
<div class="spacer"></div>
<button class="btn btn-primary btn-sm" type="button">新增条目</button>
</div>
<table class="data-table">
<thead><tr><th>标题</th><th>类型</th><th>来源</th><th>状态</th><th>更新时间</th><th style="text-align:right">操作</th></tr></thead>
<tbody>
<tr>
<td><b>ripgrep</b><br /><span class="mono" style="font-size:11px;color:var(--ink-dim)">Rust · CLI</span></td>
<td>工具</td><td>人工</td><td><span class="status-pill status-ok">active</span></td><td class="mono">2026-08-23</td>
<td><div class="row-actions"><button class="btn btn-sm" type="button">编辑</button><button class="btn btn-sm" type="button" data-demo-danger="原型演示:未灰掉条目">灰掉</button><button class="btn btn-sm btn-danger" type="button" data-demo-danger="原型演示:未删除条目">删除</button></div></td>
</tr>
<tr>
<td><b>Uptime Kuma</b><br /><span class="mono" style="font-size:11px;color:var(--ink-dim)">JavaScript · 自托管</span></td>
<td>应用</td><td>人工</td><td><span class="status-pill status-ok">active</span></td><td class="mono">2026-08-19</td>
<td><div class="row-actions"><button class="btn btn-sm" type="button">编辑</button><button class="btn btn-sm" type="button" data-demo-danger="原型演示:未灰掉条目">灰掉</button><button class="btn btn-sm btn-danger" type="button" data-demo-danger="原型演示:未删除条目">删除</button></div></td>
</tr>
<tr>
<td><b>free-stock-cdn</b><br /><span class="mono" style="font-size:11px;color:var(--ink-dim)">AI 录入 · 待核验</span></td>
<td>网站</td><td>AI 接口</td><td><span class="status-pill status-warn">pending</span></td><td class="mono">2026-08-25</td>
<td><div class="row-actions"><button class="btn btn-sm" type="button">编辑</button><button class="btn btn-sm" type="button">通过</button><button class="btn btn-sm btn-danger" type="button" data-demo-danger="原型演示:未删除条目">删除</button></div></td>
</tr>
<tr>
<td><b>old-torrent-helper</b><br /><span class="mono" style="font-size:11px;color:var(--ink-dim)">Shell · 脚本</span></td>
<td>脚本</td><td>人工</td><td><span class="status-pill status-dim">greyed</span></td><td class="mono">2026-06-30</td>
<td><div class="row-actions"><button class="btn btn-sm" type="button">编辑</button><button class="btn btn-sm" type="button">恢复</button><button class="btn btn-sm btn-danger" type="button" data-demo-danger="原型演示:未删除条目">删除</button></div></td>
</tr>
</tbody>
</table>
</section>
<!-- 评论管理 -->
<section id="sec-comments" hidden>
<p class="anno">// table: comments · 先审后删</p>
<h1>评论管理</h1>
<p class="admin-desc">处理举报与垃圾评论;删除会同时从 DuckDB 中移除记录。</p>
<div class="admin-toolbar">
<select class="select"><option>全部评论</option><option>待处理举报</option><option>最新发布</option></select>
<div class="spacer"></div>
<input class="input" type="search" placeholder="搜索评论内容…" />
</div>
<table class="data-table">
<thead><tr><th>评论者</th><th>内容</th><th>所属条目</th><th>时间</th><th style="text-align:right">操作</th></tr></thead>
<tbody>
<tr><td><b>kentang</b></td><td style="max-width:280px">配合 fzf 之后基本回不去原生 grep 了…</td><td class="mono">ripgrep</td><td class="mono">2026-08-20</td>
<td><div class="row-actions"><button class="btn btn-sm btn-danger" type="button" data-demo-danger="原型演示:未删除评论">删除</button></div></td></tr>
<tr><td><b>spam-bot-7</b></td><td style="max-width:280px">免费领取!!!点我主页……</td><td class="mono">Uptime Kuma</td><td class="mono">2026-08-24</td>
<td><div class="row-actions"><button class="btn btn-sm btn-danger" type="button" data-demo-danger="原型演示:未删除评论">删除</button></div></td></tr>
<tr><td><b>moss</b></td><td style="max-width:280px">Windows 下也稳……</td><td class="mono">ripgrep</td><td class="mono">2026-08-14</td>
<td><div class="row-actions"><button class="btn btn-sm btn-danger" type="button" data-demo-danger="原型演示:未删除评论">删除</button></div></td></tr>
</tbody>
</table>
</section>
<!-- 内容源 -->
<section id="sec-sources" hidden>
<p class="anno">// sources: human editor + ai endpoint · 灰掉策略可按来源配置</p>
<h1>内容源管理</h1>
<p class="admin-desc">控制数据从哪里进来。人工录入始终可用AI 接口录入可随时关闭或限制为「仅待审核」。</p>
<div style="display:grid;gap:16px;margin-top:24px;max-width:720px">
<div class="panel-box">
<h3 style="display:flex;align-items:center;gap:10px"><span class="dot"></span> 人工录入</h3>
<p style="font-size:13.5px;color:var(--ink-dim)">管理员与编辑在管理台直接 新增 / 修改 / 灰掉 / 删除 条目。所有改动写入审计日志。</p>
<div class="switchline" style="border-bottom:0">
本月人工改动
<span class="mono">47 次 · 最近 2026-08-26 09:14</span>
</div>
</div>
<div class="panel-box">
<h3 style="display:flex;align-items:center;gap:10px"><span class="dot dot-off"></span> AI 接口录入</h3>
<div class="switchline">
启用 AI 录入接口
<label class="toggle"><input type="checkbox" checked aria-label="启用 AI 录入接口" /><i></i></label>
</div>
<div class="switchline">
新条目先进入待审核(不直接可见)
<label class="toggle"><input type="checkbox" checked aria-label="待审核开关" /><i></i></label>
</div>
<div class="switchline">
自动灰掉:仓库 404 / 半年无核验通过
<label class="toggle"><input type="checkbox" aria-label="自动灰掉开关" /><i></i></label>
</div>
<div class="switchline" style="border-bottom:0">
接口密钥
<span class="mono">ak_live_••••••••4f2a <button class="copy-btn" style="color:var(--ink);border-color:var(--ink)" type="button" data-copy="ak_live_demo_key">复制</button></span>
</div>
</div>
</div>
</section>
</main>
</div>
<footer class="footer on-panel">
<div class="container">
<div class="footer-bar" style="border-top:0;padding-top:26px">
<span>© 2026 honor3.com · Awesome Index Admin</span>
<span style="display:flex;gap:22px">
<a href="login.html" style="color:inherit;text-decoration:none">退出登录 →</a>
<span class="mono">db: duckdb · env: local</span>
</span>
</div>
</div>
</footer>
<div class="toast" role="status"></div>
<script src="assets/js/main.js"></script>
</body>
</html>

File diff suppressed because it is too large Load Diff

151
design/prototype/assets/js/main.js vendored Normal file
View File

@ -0,0 +1,151 @@
/* Awesome Index · 原型交互(演示数据,正式版接入后端) */
(function () {
"use strict";
/* Toast */
var toastEl = document.querySelector(".toast");
var toastTimer = null;
function toast(msg) {
if (!toastEl) return;
toastEl.textContent = msg;
toastEl.classList.add("show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.classList.remove("show");
}, 2200);
}
window.awToast = toast;
/* 复制按钮 */
document.querySelectorAll("[data-copy]").forEach(function (btn) {
btn.addEventListener("click", function () {
var text = btn.getAttribute("data-copy");
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(text).then(
function () { toast("已复制"); },
function () { toast("复制失败,请手动选择文本"); }
);
} else {
toast("当前环境不支持自动复制");
}
});
});
/* 首屏:查询回显为 MCP 调用 */
var searchInput = document.getElementById("q");
var echo = document.getElementById("query-echo");
if (searchInput && echo) {
var paint = function () {
var q = searchInput.value.trim();
echo.textContent = q
? '→ mcp: search_entries({ "q": "' + q + '", "limit": 20 })'
: "→ mcp: search_entries({ \"q\": \"…\" })";
};
searchInput.addEventListener("input", paint);
paint();
}
/* 随机游览 */
var randomBtn = document.getElementById("random-btn");
if (randomBtn) {
randomBtn.addEventListener("click", function () {
location.href = "detail.html";
});
}
/* 首页搜索提交 → 列表页(原型) */
var searchForm = document.getElementById("search-form");
if (searchForm) {
searchForm.addEventListener("submit", function (e) {
e.preventDefault();
location.href = "list.html";
});
}
/* 移动端导航 */
var navToggle = document.querySelector(".nav-toggle");
if (navToggle) {
navToggle.addEventListener("click", function () {
var bar = document.querySelector(".topbar");
var open = bar.classList.toggle("menu-open");
navToggle.setAttribute("aria-expanded", open ? "true" : "false");
});
}
/* 列表页:过滤栏抽屉 */
var railToggle = document.getElementById("rail-toggle");
if (railToggle) {
railToggle.addEventListener("click", function () {
var rail = document.getElementById("filter-rail");
rail.classList.toggle("open");
});
}
/* 标签树折叠 */
document.querySelectorAll(".tree-row[data-tree]").forEach(function (row) {
row.addEventListener("click", function () {
var target = document.getElementById(row.getAttribute("data-tree"));
if (!target) return;
var open = target.classList.toggle("open");
row.setAttribute("aria-expanded", open ? "true" : "false");
});
});
/* 详情页:人读 / 机读切换 */
document.querySelectorAll(".view-tabs button").forEach(function (tab) {
tab.addEventListener("click", function () {
document.querySelectorAll(".view-tabs button").forEach(function (t) {
t.setAttribute("aria-selected", "false");
});
tab.setAttribute("aria-selected", "true");
var view = tab.getAttribute("data-view");
document.querySelectorAll("[data-view-panel]").forEach(function (p) {
p.hidden = p.getAttribute("data-view-panel") !== view;
});
});
});
/* 管理台分区切换 */
document.querySelectorAll(".admin-nav button[data-section]").forEach(function (btn) {
btn.addEventListener("click", function () {
document.querySelectorAll(".admin-nav button").forEach(function (b) {
b.setAttribute("aria-current", "false");
});
btn.setAttribute("aria-current", "true");
var id = btn.getAttribute("data-section");
document.querySelectorAll(".admin-main > section").forEach(function (s) {
s.classList.toggle("active", s.id === id);
});
});
});
/* 登录(原型:任意输入均可进入) */
var loginForm = document.getElementById("login-form");
if (loginForm) {
loginForm.addEventListener("submit", function (e) {
e.preventDefault();
if (!loginForm.reportValidity()) return;
toast("登录成功,正在进入管理台…");
setTimeout(function () {
location.href = "admin.html";
}, 600);
});
}
/* 演示表单:只弹提示,不真正提交 */
document.querySelectorAll("[data-demo-submit]").forEach(function (form) {
form.addEventListener("submit", function (e) {
e.preventDefault();
toast(form.getAttribute("data-demo-submit") || "已提交");
form.reset();
});
});
/* 危险操作演示拦截 */
document.querySelectorAll("[data-demo-danger]").forEach(function (el) {
el.addEventListener("click", function (e) {
e.preventDefault();
toast(el.getAttribute("data-demo-danger") || "原型演示:该操作未执行");
});
});
})();

View File

@ -0,0 +1,181 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ripgrep · Awesome Index</title>
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='4' y='4' width='20' height='20' rx='5' fill='%232436E8'/%3E%3Crect x='10' y='10' width='18' height='18' rx='5' fill='none' stroke='%23FF4D2E' stroke-width='2.5'/%3E%3C/svg%3E" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,800&family=Hanken+Grotesk:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600&family=Noto+Sans+SC:wght@400;500;700;900&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="assets/css/main.css" />
</head>
<body>
<header class="topbar">
<div class="container topbar-inner">
<a class="brand" href="index.html">
<span class="brand-mark"><i></i><i></i></span>
AWESOME·INDEX
</a>
<nav class="topnav" aria-label="主导航">
<a href="index.html">首页</a>
<a href="list.html" aria-current="page">浏览全部</a>
<a href="admin.html">管理入口</a>
</nav>
<button class="btn btn-sm nav-toggle" aria-expanded="false">菜单</button>
</div>
</header>
<main class="container">
<p class="crumbs"><a href="index.html">~/awesome-index</a> / <a href="list.html">工具</a> / ripgrep</p>
<div class="detail-head">
<div class="detail-title">
<h1>ripgrep</h1>
<span class="chip chip-type">工具</span>
<div class="detail-actions">
<a class="btn btn-sm" href="#" onclick="return false">访问仓库 ↗</a>
<button class="btn btn-sm" type="button" data-copy='https://honor3.com/mcp → get_entry("ripgrep")'>复制给 AI</button>
</div>
</div>
<p style="margin-top:12px;color:var(--ink-dim);max-width:56ch">如果你在终端里找过东西,就值得认识 ripgrep它把「递归 + 正则 + 快」做成了一件不需要思考的事。</p>
</div>
<div class="detail-layout">
<!-- 正文 -->
<article class="detail-body">
<section>
<p class="anno">// entry.body · markdown source</p>
<h2>这是什么</h2>
<p>ripgrep命令名 rg是一个面向目录的递归搜索工具。它默认遵循 .gitignore 规则跳过无关文件,自动跳过二进制内容,并利用 Rust 的并行与 SIMD 能力,在大代码库里的搜索速度常年第一梯队。</p>
<p>对日常使用来说,它意味着把 grep -r 那串参数彻底忘掉:<code class="mono" style="font-size:.9em">rg TODO</code> 就是全部。</p>
</section>
<section>
<h2>为什么牛逼</h2>
<ul class="feat-list">
<li>默认尊重 .gitignore搜索结果天然干净</li>
<li>并行遍历 + 字面量优化,速度在同类工具中长期领先;</li>
<li>输出对人和管道都友好,可无缝接进 fzf 等工作流;</li>
<li>单文件跨平台分发Windows / macOS / Linux 开箱即用。</li>
</ul>
</section>
<section>
<h2>截图</h2>
<div class="shot">screenshot placeholder · 16:9 建议尺寸 1280×640</div>
</section>
<section>
<p class="anno">// dual reader view · 人读 ⇄ 机读</p>
<div class="view-tabs" role="tablist" aria-label="视图切换">
<button type="button" data-view="human" aria-selected="true">人读</button>
<button type="button" data-view="machine" aria-selected="false">机读 JSON</button>
</div>
<div data-view-panel="human">
<p style="color:var(--ink-dim)">这一页就是人读视图。切换到「机读 JSON」可以看到 AI 通过 MCP 的 get_entry 拿到的同一条数据——两种读者,同一份事实。</p>
</div>
<div data-view-panel="machine" hidden>
<div class="code-block">{
"id": "ripgrep",
"type": "tool",
"name": "ripgrep",
"description": "以正则递归搜索目录,默认尊重 .gitignore。",
"url": "https://github.com/BurntSushi/ripgrep",
"tags": ["Rust", "CLI", "跨平台"],
"license": "MIT",
"stars": 52300,
"updated_at": "2026-08-23",
"source": { "kind": "human", "editor": "admin" },
"status": "active"
}</div>
</div>
</section>
<section>
<p class="anno">// comments · 3 条</p>
<h2>评论</h2>
<div class="comment">
<span class="avatar">K</span>
<div>
<div class="comment-head"><b>kentang</b><time>2026-08-20</time></div>
<p>配合 fzf 之后基本回不去原生 grep 了rg --files | fzf 是我每天用得最多的组合键。</p>
</div>
</div>
<div class="comment">
<span class="avatar">M</span>
<div>
<div class="comment-head"><b>moss</b><time>2026-08-14</time></div>
<p>Windows 下也稳,公司那台老机器上搜几十万文件的 monorepo 依然秒出。</p>
</div>
</div>
<div class="comment">
<span class="avatar">A</span>
<div>
<div class="comment-head"><b>anon-42</b><time>2026-08-02</time></div>
<p>建议补一条标签可以加到「AI 编码代理常用工具」组里agent 检索代码很依赖它。</p>
</div>
</div>
<form class="comment-form" data-demo-submit="评论已发布">
<div class="form-row">
<input class="input" type="text" placeholder="昵称" required />
</div>
<textarea class="textarea" placeholder="说点有用的:使用场景、坑、搭配推荐…" required></textarea>
<div>
<button class="btn btn-primary" type="submit">发布评论</button>
</div>
</form>
</section>
</article>
<!-- 侧栏 -->
<aside>
<div class="side-card">
<h3>元数据</h3>
<table class="meta-table">
<tr><td>类型</td><td>工具 / CLI</td></tr>
<tr><td>语言</td><td>Rust</td></tr>
<tr><td>License</td><td>MIT</td></tr>
<tr><td>Stars</td><td>52,300</td></tr>
<tr><td>收录时间</td><td>2025-11-03</td></tr>
<tr><td>最近核验</td><td>2026-08-23 ✓</td></tr>
<tr><td>来源</td><td>人工录入</td></tr>
<tr><td>状态</td><td><span class="status-pill status-ok">active</span></td></tr>
</table>
</div>
<div class="side-card">
<h3>标签</h3>
<div class="card-tags" style="margin-top:0">
<span class="chip">Rust</span>
<span class="chip">CLI</span>
<span class="chip">跨平台</span>
<span class="chip">终端工具</span>
</div>
</div>
<div class="side-card">
<h3>相关条目</h3>
<a class="related-item" href="#"><b>fd</b><span>find 的现代替代品,和 rg 同门师兄弟</span></a>
<a class="related-item" href="#"><b>fzf</b><span>模糊筛选器rg 结果的下一站</span></a>
<a class="related-item" href="#"><b>silversearcher-ag</b><span>前一代经典,如今多被 rg 取代</span></a>
</div>
</aside>
</div>
</main>
<footer class="footer on-panel">
<div class="container">
<div class="footer-bar" style="border-top:0;padding-top:26px">
<span>© 2026 honor3.com · Awesome Index</span>
<span><a href="mailto:admin@honor3.com" style="color:inherit">admin@honor3.com</a></span>
</div>
</div>
</footer>
<div class="toast" role="status"></div>
<script src="assets/js/main.js"></script>
</body>
</html>

240
design/prototype/index.html Normal file
View File

@ -0,0 +1,240 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Awesome Index · 把网上牛逼的东西收进一个库</title>
<meta name="description" content="精选开源软件、服务与网站的数据库。给人用,也给 AI 用——直接提供 MCP 接口。" />
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='4' y='4' width='20' height='20' rx='5' fill='%232436E8'/%3E%3Crect x='10' y='10' width='18' height='18' rx='5' fill='none' stroke='%23FF4D2E' stroke-width='2.5'/%3E%3C/svg%3E" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,800&family=Hanken+Grotesk:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600&family=Noto+Sans+SC:wght@400;500;700;900&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="assets/css/main.css" />
</head>
<body>
<header class="topbar">
<div class="container topbar-inner">
<a class="brand" href="index.html">
<span class="brand-mark"><i></i><i></i></span>
AWESOME·INDEX
</a>
<nav class="topnav" aria-label="主导航">
<a href="index.html" aria-current="page">首页</a>
<a href="list.html">浏览全部</a>
<a href="admin.html">管理入口</a>
</nav>
<button class="btn btn-sm nav-toggle" aria-expanded="false">菜单</button>
</div>
</header>
<main>
<!-- 首屏 -->
<section class="hero container">
<div class="hero-grid">
<div class="hero-copy">
<p class="anno rise">~/awesome-index — 给人用,也给 AI 用</p>
<h1 class="rise d1">把网上<span class="hl">牛逼的东西</span><br />收进一个好用的库。</h1>
<p class="hero-sub rise d2">人工精选的开源软件、微服务、SaaS、网站、工具、脚本与插件。每一条都是结构化数据人在页面上搜AI 通过 MCP 直接调用。</p>
<form class="search-instrument rise d3" id="search-form" role="search">
<svg width="19" height="19" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.8-3.8"/></svg>
<input id="q" type="search" placeholder="输入需求关键字,如:自托管相册 / 终端文件管理器…" aria-label="搜索收录内容" />
<button class="btn btn-primary" type="submit">搜索</button>
</form>
<p class="query-echo rise d3" id="query-echo" aria-live="polite"></p>
<a class="mcp-jump rise d4" href="#mcp">
<span class="dot"></span>
给 AI 用?本站提供 MCP 接口
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M12 4v16m0 0 6-6m-6 6-6-6"/></svg>
</a>
<p class="hero-meta rise d4">
<span>收录 <b>1,284</b></span>
<span>标签组 <b>96</b></span>
<span>本周新增 <b>+23</b></span>
<span>存储 <b>DuckDB</b></span>
<span>MCP <b>就绪</b></span>
</p>
</div>
<!-- 右侧视觉:同一条数据的两种读者形态 -->
<div class="hero-visual rise d3" role="presentation">
<p class="spec-label mono">// get_entry("ripgrep") · 同一条数据,两种读者</p>
<div class="spec-machine mono" aria-hidden="true">{
"id": "ripgrep",
"type": "tool",
"name": "ripgrep",
"tags": ["Rust", "CLI"],
"stars": 52300,
"status": "active"
}</div>
<div class="spec-human" aria-hidden="true">
<span class="chip chip-type">工具</span>
<h3>ripgrep</h3>
<p>以正则递归搜索目录,默认尊重 .gitignore是代码库里最快的找东西方式。</p>
<div class="card-tags"><span class="chip">Rust</span><span class="chip">CLI</span></div>
<p class="card-meta">★ 52.3k · 更新于 3 天前</p>
</div>
<button class="btn btn-random" id="random-btn" type="button" title="随机打开一条收录,没有头绪时让库替你挑一个">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" aria-hidden="true"><path d="M3 7h4l10 10h4M17 3l4 4-4 4M3 17h4l2.5-2.5M21 17l-4 4"/></svg>
随机游览
</button>
</div>
</div>
</section>
<!-- 第二屏MCP -->
<section class="mcp on-panel" id="mcp">
<div class="container">
<p class="anno">// mcp.transport: streamable-http · auth: none</p>
<h2 class="rise">同一个库,两种读者。<br />AI 走这边。</h2>
<p class="mcp-sub rise d1">本站所有条目同时暴露为 MCPModel Context Protocol接口。把下面的地址加进你的 AI 客户端Claude、Cursor 或任何支持 MCP 的 Agent 就能直接搜索与读取这个库。</p>
<!-- 一句话交给 Agent 自己完成配置 -->
<div class="agent-prompt rise d1">
<div>
<h3>不想手动改配置?</h3>
<p class="mono">复制下面这句话发给你的 Agent它会自己完成接入</p>
<blockquote class="mono" id="agent-sentence">「请把 URL 为 https://honor3.com/mcp 的 MCP 服务器添加到你的客户端配置中,名称用 awesome-index完成后告诉我现在可以调用哪些工具。」</blockquote>
</div>
<button class="copy-btn" type="button" data-copy="请把 URL 为 https://honor3.com/mcp 的 MCP 服务器添加到你的客户端配置中,名称用 awesome-index完成后告诉我现在可以调用哪些工具。">复制给 Agent</button>
</div>
<div class="mcp-grid">
<aside class="endpoint-card rise d2">
<h3>MCP Server URL</h3>
<div class="endpoint-url">
<code id="mcp-url">https://honor3.com/mcp</code>
<button class="copy-btn" type="button" data-copy="https://honor3.com/mcp">复制</button>
</div>
<p class="endpoint-status"><span class="dot"></span>在线 · 协议 2025-06-18</p>
<p class="endpoint-note">只读访问,无需密钥。写入类操作仅限管理台与白名单来源。</p>
</aside>
<div class="steps">
<div class="step rise d2">
<div class="step-head"><span class="step-no">01</span><h3>把服务器加进客户端配置</h3></div>
<pre>{
<span class="k">"mcpServers"</span>: {
<span class="k">"awesome-index"</span>: {
<span class="k">"url"</span>: <span class="s">"https://honor3.com/mcp"</span>
}
}
}</pre>
</div>
<div class="step rise d3">
<div class="step-head"><span class="step-no">02</span><h3>可用的工具</h3></div>
<table class="tools-table">
<thead><tr><th>tool</th><th>说明</th></tr></thead>
<tbody>
<tr><td>search_entries</td><td>按关键字、类型、标签搜索收录内容</td></tr>
<tr><td>get_entry</td><td>获取单条的完整详情与元数据</td></tr>
<tr><td>random_entry</td><td>随机返回一条,用于探索发现</td></tr>
<tr><td>list_tags</td><td>列出全部标签组及其嵌套结构</td></tr>
</tbody>
</table>
</div>
<div class="step rise d4">
<div class="step-head"><span class="step-no">03</span><h3>直接问你的 AI</h3></div>
<pre>「用 awesome-index 找三个能自托管的相册方案,
按 star 数排序,给我 repo 链接。」</pre>
</div>
</div>
</div>
</div>
</section>
<!-- 第三屏:最近收录 -->
<section class="recent container">
<div class="section-head">
<div>
<p class="anno">// resource: recent_entries · limit 4</p>
<h2>最近收录</h2>
</div>
<a href="list.html">查看全部 →</a>
</div>
<div class="card-grid">
<a class="card" href="detail.html">
<span class="chip chip-type">工具</span>
<h3>ripgrep</h3>
<p>以正则递归搜索目录,默认尊重 .gitignore是代码库里最快的找东西方式。</p>
<div class="card-tags"><span class="chip">Rust</span><span class="chip">CLI</span></div>
<p class="card-meta">★ 52.3k · 更新于 3 天前</p>
</a>
<a class="card" href="detail.html">
<span class="chip chip-type">应用</span>
<h3>Uptime Kuma</h3>
<p>自托管的服务可用性监控,漂亮的状态页、通知渠道齐全,五分钟部署完事。</p>
<div class="card-tags"><span class="chip">JavaScript</span><span class="chip">自托管</span></div>
<p class="card-meta">★ 71.9k · 更新于 1 周前</p>
</a>
<a class="card" href="detail.html">
<span class="chip chip-type">网站</span>
<h3>Excalidraw</h3>
<p>手绘风格的白板画图工具,架构图和示意草图的好搭档,支持实时协作。</p>
<div class="card-tags"><span class="chip">TypeScript</span><span class="chip">在线服务</span></div>
<p class="card-meta">★ 96.1k · 更新于 2 天前</p>
</a>
<a class="card" href="detail.html">
<span class="chip chip-type">微服务</span>
<h3>minio</h3>
<p>兼容 S3 API 的对象存储,单二进制即可跑起来,自建存储事实上的标准答案。</p>
<div class="card-tags"><span class="chip">Go</span><span class="chip">存储</span></div>
<p class="card-meta">★ 54.6k · 更新于 5 小时前</p>
</a>
</div>
</section>
</main>
<!-- 页脚 -->
<footer class="footer on-panel">
<div class="container">
<div class="footer-grid">
<div class="footer-brand">
<a class="brand" href="index.html" style="color:var(--paper-on-panel)">
<span class="brand-mark"><i style="border-color:#5b6cff"></i><i></i></span>
AWESOME·INDEX
</a>
<p>一个人工维护的「牛逼东西」数据库。条目可人工录入,也可经 AI 接口进入;坏数据会被灰掉,好东西值得被检索。</p>
</div>
<div>
<h4>站内</h4>
<ul>
<li><a href="index.html">首页</a></li>
<li><a href="list.html">浏览全部</a></li>
<li><a href="detail.html">随机一条(示例)</a></li>
<li><a href="admin.html">管理入口 →</a></li>
</ul>
</div>
<div>
<h4>给 AI</h4>
<ul>
<li><a href="#mcp-url" class="mono">GET /mcp</a></li>
<li><a href="#">MCP 使用文档</a></li>
<li><a href="#">全量数据导出JSON</a></li>
</ul>
</div>
<form class="feedback" data-demo-submit="已收到,感谢反馈">
<h4><label for="fb-text">快速反馈</label></h4>
<textarea id="fb-text" placeholder="坏链接 / 推荐条目 / 吐槽都行"></textarea>
<button type="submit">发送</button>
<span class="alt">或写信到 <a href="mailto:admin@honor3.com">admin@honor3.com</a></span>
</form>
</div>
<div class="footer-bar">
<span>© 2026 honor3.com · Awesome Index</span>
<span>由 DuckDB 驱动 · MCP 就绪 · 数据每日快照</span>
</div>
</div>
</footer>
<div class="toast" role="status"></div>
<script src="assets/js/main.js"></script>
</body>
</html>

217
design/prototype/list.html Normal file
View File

@ -0,0 +1,217 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>搜索结果 · Awesome Index</title>
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='4' y='4' width='20' height='20' rx='5' fill='%232436E8'/%3E%3Crect x='10' y='10' width='18' height='18' rx='5' fill='none' stroke='%23FF4D2E' stroke-width='2.5'/%3E%3C/svg%3E" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,800&family=Hanken+Grotesk:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600&family=Noto+Sans+SC:wght@400;500;700;900&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="assets/css/main.css" />
</head>
<body>
<header class="topbar">
<div class="container topbar-inner">
<a class="brand" href="index.html">
<span class="brand-mark"><i></i><i></i></span>
AWESOME·INDEX
</a>
<nav class="topnav" aria-label="主导航">
<a href="index.html">首页</a>
<a href="list.html" aria-current="page">浏览全部</a>
<a href="admin.html">管理入口</a>
</nav>
<button class="btn btn-sm nav-toggle" aria-expanded="false">菜单</button>
</div>
</header>
<main class="container">
<div class="page-head">
<p class="anno">// tool: search_entries · filters applied server-side</p>
<h1>「终端工具」的搜索结果</h1>
</div>
<form class="search-instrument" id="search-form" role="search" style="max-width:720px;margin-top:-6px;box-shadow:none">
<svg width="19" height="19" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.8-3.8"/></svg>
<input id="q" type="search" value="终端工具" aria-label="搜索收录内容" />
<button class="btn btn-primary" type="submit">搜索</button>
</form>
<div class="list-toolbar">
<span class="result-count"><b>47</b> 条结果 · 用时 6ms</span>
<div class="toolbar-right">
<label class="mono" for="sort" style="font-size:12px;color:var(--ink-dim)">排序</label>
<select class="select" id="sort">
<option>最相关</option>
<option>Star 最多</option>
<option>最近更新</option>
<option>最近收录</option>
</select>
<button class="btn btn-sm rail-toggle" id="rail-toggle" type="button">筛选标签</button>
</div>
</div>
<div class="list-layout">
<!-- 左侧过滤 -->
<aside class="filter-rail" id="filter-rail" aria-label="标签过滤">
<div class="filter-group">
<h3>类型</h3>
<label class="checkline"><input type="checkbox" checked /> 工具 <span class="cnt">14</span></label>
<label class="checkline"><input type="checkbox" /> 微服务 <span class="cnt">9</span></label>
<label class="checkline"><input type="checkbox" /> 应用 <span class="cnt">8</span></label>
<label class="checkline"><input type="checkbox" /> 脚本 <span class="cnt">7</span></label>
<label class="checkline"><input type="checkbox" /> 网站 <span class="cnt">5</span></label>
<label class="checkline"><input type="checkbox" /> 插件 <span class="cnt">3</span></label>
<label class="checkline"><input type="checkbox" /> SaaS <span class="cnt">1</span></label>
</div>
<div class="filter-group">
<h3>编程语言</h3>
<ul class="tag-tree">
<li>
<button class="tree-row" type="button" data-tree="lang-rust" aria-expanded="false"><span class="tw"></span> Rust <span class="cnt">11</span></button>
<ul class="tag-children" id="lang-rust">
<li><button class="tree-row" type="button"><span class="tw"></span> CLI 框架 <span class="cnt">4</span></button></li>
<li><button class="tree-row" type="button"><span class="tw"></span> WebAssembly <span class="cnt">2</span></button></li>
</ul>
</li>
<li>
<button class="tree-row" type="button" data-tree="lang-js" aria-expanded="true"><span class="tw"></span> JavaScript / TS <span class="cnt">13</span></button>
<ul class="tag-children open" id="lang-js">
<li><button class="tree-row" type="button"><span class="tw"></span> Node.js <span class="cnt">7</span></button></li>
<li><button class="tree-row" type="button"><span class="tw"></span> Deno <span class="cnt">2</span></button></li>
<li><button class="tree-row" type="button"><span class="tw"></span> 浏览器扩展 <span class="cnt">3</span></button></li>
</ul>
</li>
<li>
<button class="tree-row" type="button" data-tree="lang-py" aria-expanded="false"><span class="tw"></span> Python <span class="cnt">9</span></button>
<ul class="tag-children" id="lang-py">
<li><button class="tree-row" type="button"><span class="tw"></span> 自动化 <span class="cnt">5</span></button></li>
<li><button class="tree-row" type="button"><span class="tw"></span> 数据处理 <span class="cnt">3</span></button></li>
</ul>
</li>
<li>
<button class="tree-row" type="button" data-tree="lang-go" aria-expanded="false"><span class="tw"></span> Go <span class="cnt">8</span></button>
<ul class="tag-children" id="lang-go">
<li><button class="tree-row" type="button"><span class="tw"></span> 自托管服务 <span class="cnt">6</span></button></li>
</ul>
</li>
<li><button class="tree-row" type="button"><span class="tw"></span> Shell <span class="cnt">6</span></button></li>
</ul>
</div>
<div class="filter-group">
<h3>平台 / 形态</h3>
<label class="checkline"><input type="checkbox" checked /> CLI <span class="cnt">16</span></label>
<label class="checkline"><input type="checkbox" /> 自托管 <span class="cnt">12</span></label>
<label class="checkline"><input type="checkbox" /> Docker 就绪 <span class="cnt">10</span></label>
<label class="checkline"><input type="checkbox" /> 跨平台 <span class="cnt">18</span></label>
</div>
<button class="clear-filters" type="button">清空全部筛选</button>
</aside>
<!-- 结果列表 -->
<section class="results" aria-label="搜索结果">
<a class="result-row" href="detail.html">
<span class="chip chip-type">工具</span>
<div class="result-main">
<h3>ripgrep (rg)</h3>
<p>正则递归搜索目录,默认尊重 .gitignore。终端里找东西的事实标准。</p>
<div class="card-tags"><span class="chip">Rust</span><span class="chip">CLI</span><span class="chip">跨平台</span></div>
</div>
<div class="result-side">
<span>★ 52.3k</span>
<span>MIT · 更新于 3 天前</span>
</div>
</a>
<a class="result-row" href="detail.html">
<span class="chip chip-type">工具</span>
<div class="result-main">
<h3>fzf</h3>
<p>通用模糊查找器,管道进任何列表都能交互式筛选,终端工作流的粘合剂。</p>
<div class="card-tags"><span class="chip">Go</span><span class="chip">CLI</span><span class="chip">跨平台</span></div>
</div>
<div class="result-side">
<span>★ 68.1k</span>
<span>MIT · 更新于 1 周前</span>
</div>
</a>
<a class="result-row" href="detail.html">
<span class="chip chip-type">工具</span>
<div class="result-main">
<h3>fd</h3>
<p>find 的现代替代品,语法直觉、彩色输出、快得离谱,和 fzf 是天生一对。</p>
<div class="card-tags"><span class="chip">Rust</span><span class="chip">CLI</span></div>
</div>
<div class="result-side">
<span>★ 35.7k</span>
<span>Apache-2.0 · 更新于 4 天前</span>
</div>
</a>
<a class="result-row" href="detail.html">
<span class="chip chip-type">脚本</span>
<div class="result-main">
<h3>zoxide</h3>
<p>记录你的 cd 习惯,之后打 z proj 就能跳到最常去的目录。</p>
<div class="card-tags"><span class="chip">Rust</span><span class="chip">CLI</span><span class="chip">Shell</span></div>
</div>
<div class="result-side">
<span>★ 24.9k</span>
<span>MIT · 更新于 2 周前</span>
</div>
</a>
<a class="result-row" href="detail.html">
<span class="chip chip-type">应用</span>
<div class="result-main">
<h3>Warp Terminal</h3>
<p>以块为单位的现代终端命令输入、输出、报错各自独立AI 补全内建。</p>
<div class="card-tags"><span class="chip">Rust</span><span class="chip">跨平台</span><span class="chip">AI 就绪</span></div>
</div>
<div class="result-side">
<span>★ 22.4k</span>
<span>专有 · 更新于 6 天前</span>
</div>
</a>
<a class="result-row" href="detail.html">
<span class="chip chip-type">微服务</span>
<div class="result-main">
<h3>ttyd</h3>
<p>把任意终端程序共享到浏览器里,一条命令起一个 Web 终端。</p>
<div class="card-tags"><span class="chip">C</span><span class="chip">自托管</span><span class="chip">Docker 就绪</span></div>
</div>
<div class="result-side">
<span>★ 10.2k</span>
<span>MIT · 更新于 1 月前</span>
</div>
</a>
<nav class="pager" aria-label="分页">
<button class="btn btn-sm" type="button" disabled style="opacity:.45">← 上一页</button>
<span>第 1 / 8 页</span>
<a class="btn btn-sm" href="#">下一页 →</a>
</nav>
</section>
</div>
</main>
<footer class="footer on-panel">
<div class="container">
<div class="footer-bar" style="border-top:0;padding-top:26px">
<span>© 2026 honor3.com · Awesome Index</span>
<span><a href="mailto:admin@honor3.com" style="color:inherit">admin@honor3.com</a></span>
</div>
</div>
</footer>
<div class="toast" role="status"></div>
<script src="assets/js/main.js"></script>
</body>
</html>

View File

@ -0,0 +1,76 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>管理台登录 · Awesome Index</title>
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='4' y='4' width='20' height='20' rx='5' fill='%232436E8'/%3E%3Crect x='10' y='10' width='18' height='18' rx='5' fill='none' stroke='%23FF4D2E' stroke-width='2.5'/%3E%3C/svg%3E" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,800&family=Hanken+Grotesk:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600&family=Noto+Sans+SC:wght@400;500;700;900&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="assets/css/main.css" />
</head>
<body>
<header class="topbar">
<div class="container topbar-inner">
<a class="brand" href="index.html">
<span class="brand-mark"><i></i><i></i></span>
AWESOME·INDEX
</a>
<nav class="topnav" aria-label="主导航">
<a href="index.html">首页</a>
<a href="list.html">浏览全部</a>
<a href="login.html" aria-current="page">管理入口</a>
</nav>
<button class="btn btn-sm nav-toggle" aria-expanded="false">菜单</button>
</div>
</header>
<main>
<div class="auth-wrap container">
<section class="auth-card rise" aria-labelledby="auth-title">
<p class="anno">// route: /admin/login · auth: session cookie</p>
<h1 id="auth-title">管理台登录</h1>
<p class="auth-sub">人工通道。AI Agent 请走 <a href="index.html#mcp">MCP 接口</a>——这扇门不对机器开放。</p>
<form id="login-form" novalidate>
<div class="field">
<label for="login-user">用户名</label>
<input class="input" id="login-user" name="username" type="text"
placeholder="admin" autocomplete="username" required />
</div>
<div class="field">
<label for="login-pass">密码</label>
<input class="input" id="login-pass" name="password" type="password"
placeholder="••••••••" autocomplete="current-password" required />
</div>
<div class="auth-row">
<label class="checkline" style="padding:0">
<input type="checkbox" checked /> 记住这台设备
</label>
<a href="mailto:admin@honor3.com">忘记密码?</a>
</div>
<button class="btn btn-primary btn-block" type="submit">登 录</button>
</form>
<div class="auth-note mono">
<span>// demo 账号admin / admin</span>
<span>// agents: POST /mcp · 此处返回 403</span>
</div>
</section>
</div>
</main>
<footer class="footer-bar" style="background:transparent;border-top:2px solid var(--ink);color:var(--ink-dim)">
<div class="container" style="display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:20px 0 26px;font-family:var(--font-mono);font-size:12px">
<span>© 2026 honor3.com · Awesome Index Admin</span>
<span><a href="index.html" style="color:inherit;text-decoration:none">← 返回首页</a></span>
</div>
</footer>
<div class="toast" role="status"></div>
<script src="assets/js/main.js"></script>
</body>
</html>