From c47bb15d8cd29c80c724de236f02f2dfacc43bfb Mon Sep 17 00:00:00 2001 From: cheney Date: Wed, 26 Aug 2026 16:01:19 +0800 Subject: [PATCH] =?UTF-8?q?feat(design):=20Riso=20=E9=A3=8E=E6=A0=BC?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E8=AE=BE=E8=AE=A1=E4=B8=8E=E9=9D=99=E6=80=81?= =?UTF-8?q?=E5=8E=9F=E5=9E=8B=EF=BC=88=E9=A6=96=E9=A1=B5/=E5=88=97?= =?UTF-8?q?=E8=A1=A8/=E8=AF=A6=E6=83=85/=E7=AE=A1=E7=90=86=E5=8F=B0/?= =?UTF-8?q?=E7=99=BB=E5=BD=95=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- design/DESIGN.md | 98 ++ design/prototype/admin.html | 245 ++++ design/prototype/assets/css/main.css | 1839 ++++++++++++++++++++++++++ design/prototype/assets/js/main.js | 151 +++ design/prototype/detail.html | 181 +++ design/prototype/index.html | 240 ++++ design/prototype/list.html | 217 +++ design/prototype/login.html | 76 ++ 8 files changed, 3047 insertions(+) create mode 100644 design/DESIGN.md create mode 100644 design/prototype/admin.html create mode 100644 design/prototype/assets/css/main.css create mode 100644 design/prototype/assets/js/main.js create mode 100644 design/prototype/detail.html create mode 100644 design/prototype/index.html create mode 100644 design/prototype/list.html create mode 100644 design/prototype/login.html diff --git a/design/DESIGN.md b/design/DESIGN.md new file mode 100644 index 0000000..cb4e6cf --- /dev/null +++ b/design/DESIGN.md @@ -0,0 +1,98 @@ +# Awesome Index · 页面设计方案 + +> 把网上牛逼的东西收进一个库:给人用,也给 AI 用。 +> 本文档是视觉方向的唯一事实来源;实现时所有颜色与字体决策从这里派生。 + +## 1. 主题定位 + +- **主体**:一个人工精选的「牛逼东西」数据库——开源软件、微服务、SaaS、网站、工具、应用、脚本、插件。 +- **受众**:开发者(人类读者)+ AI Agent(MCP 机器读者)。**双读者**是本站与普通导航站的本质区别。 +- **首页的唯一职责**:让两类读者都最快拿到想要的东西——人用搜索框,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 800(CJK 回退 Noto Sans SC 900) | 仅 H1/H2 与词标,克制使用 | +| 正文/UI | Hanken Grotesk(CJK 回退 Noto Sans SC) | 400/500/700 | +| 数据/注释 | IBM Plex Mono 400–600 | 编目注释、代码、标签、表格数字 | + +字号阶(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。 diff --git a/design/prototype/admin.html b/design/prototype/admin.html new file mode 100644 index 0000000..34f58fe --- /dev/null +++ b/design/prototype/admin.html @@ -0,0 +1,245 @@ + + + + + +管理台 · Awesome Index + + + + + + + + +
+ +
+ +
+ + + +
+ +
+

// table: accounts · role: admin | editor | viewer

+

账号管理

+

管理可以登录管理台的账号与角色。

+
+ +
+ +
+ + + + + + + + + + +
用户名角色状态最后登录操作
adminadminactive2026-08-26 09:14
editor.lineditoractive2026-08-25 21:40
ai-ingesteditor(AI 接口)受限2026-08-26 07:02
+
+ + +
+

// tree: tags · 支持 嵌套 / 移动 / 删除(删除前需确认子标签归属)

+

标签管理

+

拖拽调整层级与顺序;删除父标签时其子标签自动上移一级。

+
+
+

标签树 (点击 ▶ 展开)

+
    +
  • + +
      +
    • +
        +
      • +
      • +
      +
    • +
    • +
    • +
    +
  • +
  • + +
      +
    • +
    • +
    • +
    +
  • +
  • +
+
+
+

编辑标签:JavaScript / TS

+
+

名称

+ +

上级标签

+ +

排序权重

+ +
+ + +
+
+
+
+ + +
+
+
+
+ + + + + + + + + +
+
+ + + +
+ + + diff --git a/design/prototype/assets/css/main.css b/design/prototype/assets/css/main.css new file mode 100644 index 0000000..08d8af7 --- /dev/null +++ b/design/prototype/assets/css/main.css @@ -0,0 +1,1839 @@ +/* ============================================================ + Awesome Index · 设计系统 + 方向:Riso 孔版印刷 × 数据档案(见 design/DESIGN.md) + ============================================================ */ + +/* ---------- Tokens ---------- */ +:root { + --paper: #f0f1ec; + --paper-raised: #fbfbf7; + --ink: #171a21; + --ink-dim: rgba(23, 26, 33, 0.62); + --ink-faint: rgba(23, 26, 33, 0.14); + --riso-blue: #2436e8; + --riso-blue-soft: rgba(36, 54, 232, 0.14); + --riso-coral: #ff4d2e; + --panel: #10131a; + --panel-raised: #1a1f29; + --paper-on-panel: #e9ebe4; + --dim-on-panel: rgba(233, 235, 228, 0.6); + --ok: #2f9e63; + + --font-display: "Bricolage Grotesque", "Noto Sans SC", sans-serif; + --font-body: "Hanken Grotesk", "Noto Sans SC", -apple-system, "PingFang SC", + "Microsoft YaHei", sans-serif; + --font-mono: "IBM Plex Mono", ui-monospace, Consolas, monospace; + + --r-sm: 8px; + --r-md: 12px; + --r-lg: 16px; + --border: 2px solid var(--ink); + --shadow-rest: 4px 4px 0 rgba(23, 26, 33, 0.08); + --shadow-riso: 7px 7px 0 var(--riso-blue); + + --container: 1160px; +} + +/* ---------- Reset / base ---------- */ +*, +*::before, +*::after { + box-sizing: border-box; +} +html { + scroll-behavior: smooth; +} +body { + margin: 0; + background: var(--paper); + color: var(--ink); + font-family: var(--font-body); + font-size: 16px; + line-height: 1.65; + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; +} +img, +svg { + display: block; +} +a { + color: inherit; +} +button, +input, +textarea, +select { + font: inherit; + color: inherit; +} +h1, +h2, +h3, +p { + margin: 0; +} +::selection { + background: var(--riso-blue); + color: #fff; +} +:focus-visible { + outline: 3px solid var(--riso-blue); + outline-offset: 3px; + border-radius: 4px; +} + +.container { + width: min(var(--container), calc(100% - 48px)); + margin-inline: auto; +} +@media (max-width: 640px) { + .container { + width: calc(100% - 36px); + } +} + +.mono { + font-family: var(--font-mono); +} + +/* 编目注释:签名元素 */ +.anno { + font-family: var(--font-mono); + font-size: 11.5px; + letter-spacing: 0.05em; + color: var(--ink-dim); + display: flex; + align-items: center; + gap: 10px; + margin-bottom: 22px; +} +.anno::before { + content: ""; + width: 22px; + height: 2px; + background: var(--riso-blue); + flex: none; +} +.on-panel .anno { + color: var(--dim-on-panel); +} + +/* ---------- 按钮 ---------- */ +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + padding: 11px 20px; + border-radius: var(--r-sm); + border: var(--border); + background: var(--paper-raised); + font-weight: 700; + font-size: 15px; + cursor: pointer; + text-decoration: none; + transition: + transform 0.16s ease, + box-shadow 0.16s ease, + background 0.16s ease; +} +.btn:hover { + transform: translate(-2px, -2px); + box-shadow: 5px 5px 0 var(--riso-blue); +} +.btn:active { + transform: translate(0, 0); + box-shadow: none; +} +.btn-primary { + background: var(--ink); + color: var(--paper); +} +.btn-ghost { + border-color: transparent; + background: transparent; +} +.btn-ghost:hover { + box-shadow: none; + background: var(--riso-blue-soft); +} +.btn-sm { + padding: 6px 12px; + font-size: 13px; + border-width: 1.5px; +} +.btn-danger:hover { + box-shadow: 5px 5px 0 var(--riso-coral); +} + +/* ---------- 徽章 / 标签 ---------- */ +.chip { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 3px 10px; + border: 1.5px solid var(--ink-faint); + border-radius: 999px; + font-family: var(--font-mono); + font-size: 12px; + text-decoration: none; + color: var(--ink-dim); + background: transparent; + transition: + border-color 0.15s ease, + color 0.15s ease, + background 0.15s ease; +} +a.chip:hover, +button.chip:hover { + border-color: var(--riso-blue); + color: var(--riso-blue); + background: var(--riso-blue-soft); +} +.chip-type { + border-color: var(--ink); + background: var(--ink); + color: var(--paper); + font-weight: 600; +} +.chip.is-active { + border-color: var(--riso-blue); + background: var(--riso-blue); + color: #fff; +} +.dot { + width: 7px; + height: 7px; + border-radius: 50%; + background: var(--ok); + flex: none; +} +.dot-off { + background: var(--riso-coral); +} + +/* ---------- 顶栏 ---------- */ +.topbar { + position: sticky; + top: 0; + z-index: 50; + background: rgba(240, 241, 236, 0.88); + backdrop-filter: blur(10px); + border-bottom: 2px solid var(--ink); +} +.topbar-inner { + display: flex; + align-items: center; + gap: 28px; + height: 64px; +} +.brand { + display: inline-flex; + align-items: center; + gap: 10px; + text-decoration: none; + font-family: var(--font-display); + font-weight: 800; + font-size: 17px; + letter-spacing: 0.02em; +} +.brand-mark { + position: relative; + width: 20px; + height: 20px; + flex: none; +} +.brand-mark i { + position: absolute; + inset: 0; + border: 2.5px solid var(--riso-blue); + border-radius: 5px; +} +.brand-mark i:last-child { + transform: translate(3px, 3px); + border-color: var(--riso-coral); +} +.topnav { + display: flex; + gap: 4px; + margin-left: auto; + align-items: center; +} +.topnav a { + text-decoration: none; + font-weight: 600; + font-size: 14.5px; + padding: 7px 13px; + border-radius: 999px; +} +.topnav a:hover { + background: var(--riso-blue-soft); + color: var(--riso-blue); +} +.topnav a[aria-current="page"] { + background: var(--ink); + color: var(--paper); +} +.nav-toggle { + display: none; + margin-left: auto; +} + +/* ---------- 首屏 ---------- */ +.hero { + padding: clamp(56px, 9vh, 96px) 0 64px; +} +.hero h1 { + font-family: var(--font-display); + font-weight: 800; + font-size: clamp(34px, 6vw, 68px); + line-height: 1.12; + letter-spacing: 0.005em; + max-width: 18em; +} +.hero .hl { + background: linear-gradient( + transparent 58%, + var(--riso-blue-soft) 58%, + rgba(36, 54, 232, 0.32) 92%, + transparent 92% + ); + padding-inline: 2px; +} +.hero-sub { + margin-top: 18px; + font-size: 17px; + color: var(--ink-dim); + max-width: 34em; +} + +/* 搜索仪器 */ +.search-instrument { + margin-top: 34px; + max-width: 720px; + background: var(--paper-raised); + border: var(--border); + border-radius: var(--r-lg); + box-shadow: 8px 8px 0 var(--riso-blue-soft); + display: flex; + align-items: stretch; + overflow: hidden; + transition: + transform 0.2s ease, + box-shadow 0.2s ease; +} +.search-instrument:focus-within { + transform: translate(-2px, -2px); + box-shadow: 10px 10px 0 var(--riso-blue-soft); +} +.search-instrument svg { + align-self: center; + margin-left: 18px; + color: var(--ink-dim); + flex: none; +} +.search-instrument input { + flex: 1; + min-width: 0; + border: 0; + background: transparent; + padding: 18px 14px; + font-size: 16.5px; +} +.search-instrument input::placeholder { + color: var(--ink-dim); +} +.search-instrument input:focus { + outline: none; +} +.search-instrument .btn-primary { + border: 0; + border-left: var(--border); + border-radius: 0; + padding-inline: 30px; + font-size: 16px; +} +.query-echo { + margin-top: 12px; + font-family: var(--font-mono); + font-size: 12.5px; + color: var(--riso-blue); + min-height: 1.4em; + overflow-wrap: anywhere; +} +.hero-meta { + margin-top: 30px; + font-family: var(--font-mono); + font-size: 12.5px; + color: var(--ink-dim); + display: flex; + gap: 8px 22px; + flex-wrap: wrap; +} +.hero-meta b { + color: var(--ink); + font-weight: 600; +} +.btn-random { + position: absolute; + right: 2px; + bottom: 4px; + z-index: 3; + background: var(--paper-raised); +} + +/* 首屏双栏:文案 + 数据标本视觉 */ +.hero-grid { + display: grid; + grid-template-columns: minmax(0, 1.3fr) minmax(0, 0.8fr); + gap: clamp(36px, 5vw, 72px); + align-items: center; +} +.hero-copy { + min-width: 0; +} +.mcp-jump { + display: inline-flex; + align-items: center; + gap: 9px; + margin-top: 18px; + padding: 8px 16px; + border: 1.5px solid var(--ink-faint); + border-radius: 999px; + font-family: var(--font-mono); + font-size: 13px; + text-decoration: none; + color: var(--ink); + transition: + border-color 0.15s ease, + background 0.15s ease, + color 0.15s ease; +} +.mcp-jump svg { + transition: transform 0.2s ease; +} +.mcp-jump:hover { + border-color: var(--riso-blue); + color: var(--riso-blue); + background: var(--riso-blue-soft); +} +.mcp-jump:hover svg { + transform: translateY(2px); +} + +/* 右侧视觉:同一条数据的两种读者形态 */ +.hero-visual { + position: relative; + min-height: 380px; +} +.spec-label { + position: absolute; + top: -6px; + left: 4px; + font-size: 11.5px; + color: var(--ink-dim); + letter-spacing: 0.04em; + max-width: 100%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.spec-machine { + position: absolute; + top: 34px; + right: 0; + width: min(320px, 96%); + background: var(--panel); + color: #cdd3ea; + font-size: 11.5px; + line-height: 1.65; + padding: 18px 20px; + border-radius: var(--r-md); + transform: rotate(2.6deg); + box-shadow: 10px 10px 0 rgba(23, 26, 33, 0.12); + overflow: hidden; +} +.spec-human { + position: absolute; + bottom: 12px; + left: 0; + width: min(300px, 94%); + background: var(--paper-raised); + border: var(--border); + border-radius: var(--r-md); + padding: 18px; + transform: rotate(-3deg); + box-shadow: 9px 9px 0 var(--riso-blue); +} +.spec-human h3 { + font-size: 16.5px; + font-weight: 700; + margin-top: 12px; +} +.spec-human p { + margin-top: 6px; + font-size: 13.5px; + color: var(--ink-dim); + line-height: 1.55; +} +.spec-human .card-tags { + margin-top: 14px; +} + +/* 最近收录(第三屏) */ +.recent { + padding: 84px 0 96px; +} +.card-grid { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 18px; +} +.card { + display: block; + background: var(--paper-raised); + border: var(--border); + border-radius: var(--r-md); + padding: 18px; + text-decoration: none; + box-shadow: var(--shadow-rest); + transition: + transform 0.18s ease, + box-shadow 0.18s ease; +} +.card:hover { + transform: translate(-3px, -3px); + box-shadow: var(--shadow-riso); +} +.card .chip-type { + margin-bottom: 12px; +} +.card h3 { + font-size: 16.5px; + font-weight: 700; + display: flex; + align-items: center; + gap: 6px; +} +.card p { + margin-top: 6px; + font-size: 13.5px; + color: var(--ink-dim); + line-height: 1.55; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} +.card-tags { + margin-top: 14px; + display: flex; + gap: 6px; + flex-wrap: wrap; +} +.card-meta { + margin-top: 12px; + font-family: var(--font-mono); + font-size: 11.5px; + color: var(--ink-dim); +} +.section-head { + display: flex; + align-items: baseline; + justify-content: space-between; + gap: 16px; + margin-bottom: 22px; +} +.section-head h2 { + font-family: var(--font-display); + font-weight: 800; + font-size: 24px; +} +.section-head a { + font-weight: 600; + font-size: 14px; + color: var(--riso-blue); + text-decoration: none; +} +.section-head a:hover { + text-decoration: underline; +} + +/* ---------- MCP 第二屏 ---------- */ +.mcp { + scroll-margin-top: 70px; + background: var(--panel); + color: var(--paper-on-panel); + padding: 76px 0 84px; +} +.mcp h2 { + font-family: var(--font-display); + font-weight: 800; + font-size: clamp(26px, 4vw, 38px); + max-width: 20em; +} +.mcp-sub { + margin-top: 12px; + color: var(--dim-on-panel); + max-width: 40em; +} +.mcp-grid { + margin-top: 40px; + display: grid; + grid-template-columns: 380px 1fr; + gap: 22px; + align-items: start; +} +.agent-prompt { + margin-top: 26px; + display: flex; + align-items: center; + gap: 20px; + background: var(--panel-raised); + border: 1.5px dashed rgba(233, 235, 228, 0.28); + border-radius: var(--r-md); + padding: 18px 22px; +} +.agent-prompt h3 { + font-size: 15px; + font-weight: 700; +} +.agent-prompt .mono { + margin-top: 4px; + font-size: 12.5px; + color: var(--dim-on-panel); +} +.agent-prompt blockquote { + margin: 10px 0 0; + padding: 11px 14px; + background: rgba(0, 0, 0, 0.35); + border-left: 3px solid var(--riso-blue); + border-radius: 0 8px 8px 0; + font-size: 12.5px; + line-height: 1.7; + color: #cdd3ea; + overflow-wrap: anywhere; +} +.agent-prompt .copy-btn { + align-self: flex-start; + flex: none; + white-space: nowrap; +} +.endpoint-card { + background: var(--panel-raised); + border: 1.5px solid rgba(233, 235, 228, 0.16); + border-radius: var(--r-md); + padding: 22px; +} +.endpoint-card h3 { + font-size: 13px; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--dim-on-panel); + font-family: var(--font-mono); + font-weight: 500; +} +.endpoint-url { + margin-top: 14px; + display: flex; + gap: 10px; + align-items: stretch; +} +.endpoint-url code { + flex: 1; + min-width: 0; + font-family: var(--font-mono); + font-size: 13px; + background: rgba(233, 235, 228, 0.07); + border: 1px solid rgba(233, 235, 228, 0.16); + border-radius: 8px; + padding: 11px 13px; + overflow-x: auto; + white-space: nowrap; +} +.copy-btn { + flex: none; + border: 1px solid rgba(233, 235, 228, 0.28); + background: transparent; + color: var(--paper-on-panel); + border-radius: 8px; + padding: 0 14px; + cursor: pointer; + font-family: var(--font-mono); + font-size: 12.5px; + transition: background 0.15s ease; +} +.copy-btn:hover { + background: rgba(233, 235, 228, 0.12); +} +.endpoint-status { + margin-top: 16px; + font-family: var(--font-mono); + font-size: 12px; + color: var(--dim-on-panel); + display: flex; + align-items: center; + gap: 8px; +} +.endpoint-note { + margin-top: 18px; + font-size: 13.5px; + line-height: 1.7; + color: var(--dim-on-panel); +} +.steps { + display: grid; + gap: 14px; +} +.step { + background: var(--panel-raised); + border: 1.5px solid rgba(233, 235, 228, 0.16); + border-radius: var(--r-md); + padding: 18px 20px; +} +.step-head { + display: flex; + align-items: baseline; + gap: 12px; +} +.step-no { + font-family: var(--font-mono); + font-size: 12px; + color: var(--riso-coral); + font-weight: 600; +} +.step h3 { + font-size: 15.5px; + font-weight: 700; +} +.step pre { + margin: 12px 0 0; + background: rgba(0, 0, 0, 0.35); + border: 1px solid rgba(233, 235, 228, 0.12); + border-radius: 8px; + padding: 13px 15px; + font-family: var(--font-mono); + font-size: 12.5px; + line-height: 1.6; + overflow-x: auto; + color: #cdd3ea; +} +.step pre .k { + color: #8fa3ff; +} +.step pre .s { + color: #ffd9a0; +} +.tools-table { + width: 100%; + border-collapse: collapse; + margin-top: 12px; + font-size: 13px; +} +.tools-table th { + text-align: left; + font-family: var(--font-mono); + font-size: 11px; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--dim-on-panel); + font-weight: 500; + padding: 8px 10px; + border-bottom: 1px solid rgba(233, 235, 228, 0.16); +} +.tools-table td { + padding: 9px 10px; + border-bottom: 1px solid rgba(233, 235, 228, 0.09); +} +.tools-table td:first-child { + font-family: var(--font-mono); + color: #8fa3ff; + white-space: nowrap; +} + +/* ---------- 页脚 ---------- */ +.footer { + background: var(--panel); + color: var(--paper-on-panel); + padding: 72px 0 0; + border-top: 6px solid var(--riso-blue); +} +.footer-grid { + display: grid; + grid-template-columns: 1.3fr 1fr 1fr 0.9fr; + gap: 44px; + padding-bottom: 56px; +} +.footer h4 { + font-family: var(--font-mono); + font-size: 11.5px; + font-weight: 500; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--dim-on-panel); + margin: 0 0 18px; +} +.footer-brand p { + margin-top: 14px; + font-size: 14px; + color: var(--dim-on-panel); + max-width: 26em; +} +.footer a { + color: var(--paper-on-panel); + text-decoration: none; + font-size: 14px; +} +.footer ul { + list-style: none; + margin: 0; + padding: 0; + display: grid; + gap: 11px; +} +.footer ul a:hover { + color: #8fa3ff; + text-decoration: underline; +} +.feedback textarea { + width: 100%; + min-height: 86px; + resize: vertical; + background: var(--panel-raised); + border: 1.5px solid rgba(233, 235, 228, 0.2); + border-radius: 8px; + padding: 11px 13px; + font-size: 13.5px; + color: var(--paper-on-panel); +} +.feedback textarea::placeholder { + color: rgba(233, 235, 228, 0.38); +} +.feedback button { + margin-top: 10px; + background: var(--paper-on-panel); + color: var(--ink); + border: 0; + border-radius: 8px; + padding: 9px 18px; + font-weight: 700; + cursor: pointer; +} +.feedback button:hover { + background: #fff; +} +.feedback .alt { + display: block; + margin-top: 10px; + font-size: 12.5px; + color: var(--dim-on-panel); +} +.feedback .alt a { + color: #8fa3ff; +} +.footer-bar { + border-top: 1px solid rgba(233, 235, 228, 0.14); + padding: 22px 0 26px; + display: flex; + justify-content: space-between; + gap: 12px 28px; + flex-wrap: wrap; + font-family: var(--font-mono); + font-size: 12px; + color: var(--dim-on-panel); +} + +/* ---------- 列表页 ---------- */ +.page-head { + padding: 46px 0 26px; +} +.page-head h1 { + font-family: var(--font-display); + font-weight: 800; + font-size: clamp(26px, 4vw, 40px); +} +.list-toolbar { + display: flex; + align-items: center; + gap: 14px; + flex-wrap: wrap; + padding-bottom: 20px; + border-bottom: 2px solid var(--ink); +} +.result-count { + font-family: var(--font-mono); + font-size: 13px; + color: var(--ink-dim); +} +.result-count b { + color: var(--ink); +} +.toolbar-right { + margin-left: auto; + display: flex; + gap: 10px; + align-items: center; +} +.select { + border: 1.5px solid var(--ink); + background: var(--paper-raised); + border-radius: 8px; + padding: 7px 10px; + font-size: 13.5px; + cursor: pointer; +} + +.list-layout { + display: grid; + grid-template-columns: 264px 1fr; + gap: 36px; + align-items: start; + padding: 30px 0 80px; +} +.filter-rail { + position: sticky; + top: 88px; + display: grid; + gap: 26px; +} +.rail-toggle { + display: none; +} +.filter-group h3 { + font-family: var(--font-mono); + font-size: 11.5px; + font-weight: 600; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--ink-dim); + margin-bottom: 12px; +} +.checkline { + display: flex; + align-items: center; + gap: 9px; + padding: 5px 0; + font-size: 14px; + cursor: pointer; + user-select: none; +} +.checkline input { + accent-color: var(--riso-blue); + width: 15px; + height: 15px; + cursor: pointer; +} +.checkline .cnt { + margin-left: auto; + font-family: var(--font-mono); + font-size: 11.5px; + color: var(--ink-dim); +} +.tag-tree { + list-style: none; + margin: 0; + padding: 0; + font-size: 14px; +} +.tag-tree ul { + list-style: none; + margin: 0; + padding-left: 16px; + border-left: 1.5px solid var(--ink-faint); +} +.tag-tree li { + padding: 2px 0; +} +.tree-row { + display: flex; + align-items: center; + gap: 7px; + width: 100%; + background: none; + border: 0; + padding: 4px 6px; + cursor: pointer; + text-align: left; + font-size: 14px; + border-radius: 6px; +} +.tree-row:hover { + background: var(--riso-blue-soft); +} +.tree-row .tw { + color: var(--ink-dim); + font-family: var(--font-mono); + font-size: 10px; + width: 10px; + flex: none; + transition: transform 0.15s ease; +} +.tree-row[aria-expanded="true"] .tw { + transform: rotate(90deg); +} +.tree-row .cnt { + margin-left: auto; + font-family: var(--font-mono); + font-size: 11px; + color: var(--ink-dim); +} +.tag-children { + display: none; +} +.tag-children.open { + display: block; +} +.clear-filters { + background: none; + border: 0; + padding: 0; + color: var(--riso-blue); + font-size: 13px; + font-weight: 600; + cursor: pointer; + text-align: left; +} +.clear-filters:hover { + text-decoration: underline; +} + +.results { + display: grid; + gap: 14px; +} +.result-row { + display: grid; + grid-template-columns: 96px 1fr auto; + gap: 18px; + align-items: start; + background: var(--paper-raised); + border: var(--border); + border-radius: var(--r-md); + padding: 16px 18px; + text-decoration: none; + transition: + transform 0.16s ease, + box-shadow 0.16s ease; +} +.result-row:hover { + transform: translate(-2px, -2px); + box-shadow: 6px 6px 0 var(--riso-blue); +} +.result-main h3 { + font-size: 16.5px; + font-weight: 700; +} +.result-main p { + margin-top: 4px; + font-size: 13.5px; + color: var(--ink-dim); +} +.result-side { + text-align: right; + font-family: var(--font-mono); + font-size: 11.5px; + color: var(--ink-dim); + display: grid; + gap: 6px; + justify-items: end; +} +.pager { + margin-top: 26px; + display: flex; + justify-content: center; + align-items: center; + gap: 14px; + font-family: var(--font-mono); + font-size: 13px; +} + +/* ---------- 详情页 ---------- */ +.crumbs { + font-family: var(--font-mono); + font-size: 12.5px; + color: var(--ink-dim); + padding: 26px 0 8px; +} +.crumbs a { + color: inherit; + text-decoration: none; +} +.crumbs a:hover { + color: var(--riso-blue); +} +.detail-head { + padding: 10px 0 26px; + border-bottom: 2px solid var(--ink); +} +.detail-title { + display: flex; + align-items: center; + gap: 14px; + flex-wrap: wrap; + margin-top: 10px; +} +.detail-title h1 { + font-family: var(--font-display); + font-weight: 800; + font-size: clamp(30px, 5vw, 52px); +} +.detail-actions { + margin-left: auto; + display: flex; + gap: 10px; + flex-wrap: wrap; +} +.detail-layout { + display: grid; + grid-template-columns: 1fr 320px; + gap: 40px; + padding: 34px 0 70px; + align-items: start; +} +.detail-body section { + margin-bottom: 40px; +} +.detail-body h2 { + font-family: var(--font-display); + font-weight: 800; + font-size: 21px; + margin-bottom: 14px; +} +.detail-body p { + margin-bottom: 12px; + max-width: 62ch; +} +.shot { + border: var(--border); + border-radius: var(--r-md); + background: + repeating-linear-gradient( + -45deg, + transparent 0 14px, + rgba(23, 26, 33, 0.03) 14px 15px + ), + var(--paper-raised); + aspect-ratio: 16/8; + display: grid; + place-items: center; + color: var(--ink-dim); + font-family: var(--font-mono); + font-size: 12.5px; +} +.feat-list { + margin: 0; + padding: 0; + list-style: none; + display: grid; + gap: 10px; +} +.feat-list li { + padding-left: 26px; + position: relative; + max-width: 60ch; +} +.feat-list li::before { + content: "✳"; + position: absolute; + left: 0; + top: 0; + color: var(--riso-blue); + font-size: 14px; +} +.view-tabs { + display: inline-flex; + border: 1.5px solid var(--ink); + border-radius: 8px; + overflow: hidden; + margin-bottom: 14px; +} +.view-tabs button { + border: 0; + background: var(--paper-raised); + padding: 7px 16px; + font-family: var(--font-mono); + font-size: 12.5px; + cursor: pointer; +} +.view-tabs button[aria-selected="true"] { + background: var(--ink); + color: var(--paper); +} +.code-block { + background: var(--panel); + color: #cdd3ea; + border-radius: var(--r-md); + padding: 18px 20px; + font-family: var(--font-mono); + font-size: 12.5px; + line-height: 1.65; + overflow-x: auto; + white-space: pre; +} +.side-card { + background: var(--paper-raised); + border: var(--border); + border-radius: var(--r-md); + padding: 20px; + box-shadow: var(--shadow-rest); + margin-bottom: 22px; +} +.side-card h3 { + font-family: var(--font-mono); + font-size: 11.5px; + font-weight: 600; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--ink-dim); + margin-bottom: 14px; +} +.meta-table { + width: 100%; + border-collapse: collapse; + font-size: 13.5px; +} +.meta-table td { + padding: 7px 0; + vertical-align: top; +} +.meta-table td:first-child { + color: var(--ink-dim); + width: 42%; +} +.meta-table td:last-child { + font-family: var(--font-mono); + font-size: 12.5px; +} +.related-item { + display: block; + text-decoration: none; + padding: 9px 0; + border-top: 1.5px solid var(--ink-faint); +} +.related-item:first-of-type { + border-top: 0; +} +.related-item b { + font-size: 14px; +} +.related-item span { + display: block; + font-size: 12.5px; + color: var(--ink-dim); + margin-top: 2px; +} +.related-item:hover b { + color: var(--riso-blue); +} + +/* 评论 */ +.comment { + display: flex; + gap: 14px; + padding: 18px 0; + border-bottom: 1.5px solid var(--ink-faint); +} +.avatar { + width: 38px; + height: 38px; + flex: none; + border-radius: 50%; + border: 2px solid var(--ink); + display: grid; + place-items: center; + font-family: var(--font-display); + font-weight: 800; + font-size: 15px; + background: var(--riso-blue-soft); +} +.comment-head { + display: flex; + gap: 10px; + align-items: baseline; + font-size: 13.5px; +} +.comment-head b { + font-size: 14px; +} +.comment-head time { + font-family: var(--font-mono); + font-size: 11.5px; + color: var(--ink-dim); +} +.comment p { + margin-top: 6px; + font-size: 14px; +} +.comment-form { + margin-top: 24px; + display: grid; + gap: 12px; + max-width: 620px; +} +.input, +.textarea { + border: 1.5px solid var(--ink); + border-radius: 8px; + background: var(--paper-raised); + padding: 11px 14px; + font-size: 14px; + width: 100%; +} +.input:focus, +.textarea:focus { + outline: 3px solid var(--riso-blue); + outline-offset: 0; +} +.textarea { + min-height: 96px; + resize: vertical; +} +.form-row { + display: flex; + gap: 12px; +} +.form-row .input { + flex: 1; +} + +/* ---------- 管理台 ---------- */ +.admin-shell { + display: grid; + grid-template-columns: 230px 1fr; + min-height: calc(100vh - 64px); +} +.admin-nav { + border-right: 2px solid var(--ink); + padding: 28px 18px; + display: grid; + gap: 4px; + align-content: start; + background: var(--paper-raised); +} +.admin-nav h4 { + font-family: var(--font-mono); + font-size: 11px; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--ink-dim); + margin: 0 0 10px 10px; + font-weight: 600; +} +.admin-nav button { + display: flex; + align-items: center; + gap: 10px; + width: 100%; + text-align: left; + background: none; + border: 0; + border-radius: 8px; + padding: 10px 12px; + font-size: 14px; + font-weight: 600; + cursor: pointer; +} +.admin-nav button:hover { + background: var(--riso-blue-soft); +} +.admin-nav button[aria-current="true"] { + background: var(--ink); + color: var(--paper); +} +.admin-main { + padding: 34px 40px 70px; + min-width: 0; +} +.admin-main > section { + display: none; +} +.admin-main > section.active { + display: block; + animation: fadein 0.25s ease; +} +.admin-main h1 { + font-family: var(--font-display); + font-weight: 800; + font-size: 27px; +} +.admin-desc { + color: var(--ink-dim); + font-size: 14px; + margin-top: 6px; +} +.admin-toolbar { + display: flex; + gap: 10px; + flex-wrap: wrap; + align-items: center; + margin: 24px 0 18px; +} +.admin-toolbar .input { + max-width: 260px; +} +.admin-toolbar .spacer { + flex: 1; +} +.data-table { + width: 100%; + border-collapse: collapse; + background: var(--paper-raised); + border: var(--border); + border-radius: var(--r-md); + overflow: hidden; + font-size: 13.5px; +} +.data-table th { + text-align: left; + font-family: var(--font-mono); + font-size: 11px; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--ink-dim); + font-weight: 600; + padding: 11px 14px; + border-bottom: 2px solid var(--ink); + background: var(--paper); +} +.data-table td { + padding: 12px 14px; + border-bottom: 1.5px solid var(--ink-faint); + vertical-align: middle; +} +.data-table tr:last-child td { + border-bottom: 0; +} +.data-table tbody tr { + transition: background 0.12s ease; +} +.data-table tbody tr:hover { + background: rgba(36, 54, 232, 0.05); +} +.row-actions { + display: flex; + gap: 6px; + justify-content: flex-end; +} +.status-pill { + display: inline-block; + font-family: var(--font-mono); + font-size: 11px; + padding: 2px 9px; + border-radius: 999px; + border: 1.5px solid currentColor; +} +.status-ok { + color: var(--ok); +} +.status-warn { + color: var(--riso-coral); +} +.status-dim { + color: var(--ink-dim); +} +.tagmgr { + display: grid; + grid-template-columns: 1.1fr 1fr; + gap: 26px; + margin-top: 24px; + align-items: start; +} +.panel-box { + background: var(--paper-raised); + border: var(--border); + border-radius: var(--r-md); + padding: 22px; +} +.panel-box h3 { + font-size: 15px; + font-weight: 700; + margin-bottom: 14px; +} +.switchline { + display: flex; + align-items: center; + gap: 12px; + padding: 10px 0; + border-bottom: 1.5px solid var(--ink-faint); + font-size: 14px; +} +.switchline:last-child { + border-bottom: 0; +} +.switchline .mono { + font-size: 12px; + color: var(--ink-dim); + margin-left: auto; +} +.toggle { + position: relative; + width: 38px; + height: 21px; + flex: none; +} +.toggle input { + position: absolute; + inset: 0; + opacity: 0; + cursor: pointer; + z-index: 1; +} +.toggle i { + position: absolute; + inset: 0; + border: 1.5px solid var(--ink); + border-radius: 999px; + background: var(--paper); + transition: background 0.15s ease; +} +.toggle i::after { + content: ""; + position: absolute; + top: 2px; + left: 2px; + width: 13px; + height: 13px; + border-radius: 50%; + background: var(--ink); + transition: transform 0.15s ease; +} +.toggle input:checked + i { + background: var(--riso-blue); +} +.toggle input:checked + i::after { + transform: translateX(17px); + background: #fff; +} +.stat-strip { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 16px; + margin: 24px 0 8px; +} +.stat-cell { + background: var(--paper-raised); + border: var(--border); + border-radius: var(--r-md); + padding: 16px 18px; +} +.stat-cell b { + display: block; + font-family: var(--font-mono); + font-size: 22px; + font-weight: 600; +} +.stat-cell span { + font-size: 12.5px; + color: var(--ink-dim); +} + +/* ---------- 登录页 ---------- */ +.auth-wrap { + position: relative; + min-height: calc(100vh - 64px); + display: grid; + place-items: center; + padding: 56px 0 72px; +} +.auth-wrap::before, +.auth-wrap::after { + content: ""; + position: absolute; + width: 230px; + height: 150px; + border: 2px solid var(--ink-faint); + border-radius: var(--r-md); +} +.auth-wrap::before { + top: 14%; + left: 12%; + transform: rotate(-6deg); +} +.auth-wrap::after { + bottom: 9%; + right: 11%; + transform: rotate(4deg); + border-color: rgba(36, 54, 232, 0.25); +} +.auth-card { + width: min(430px, 100%); + background: var(--paper-raised); + border: var(--border); + border-radius: var(--r-lg); + padding: 32px 34px 26px; + box-shadow: 10px 10px 0 var(--riso-blue); +} +.auth-card h1 { + font-family: var(--font-display); + font-weight: 800; + font-size: clamp(24px, 3vw, 30px); +} +.auth-sub { + margin-top: 8px; + font-size: 13.5px; + color: var(--ink-dim); +} +.auth-sub a { + color: var(--riso-blue); + font-weight: 600; + text-decoration: none; +} +.auth-sub a:hover { + text-decoration: underline; +} +.field { + margin-top: 16px; +} +.field label { + display: block; + font-size: 13px; + font-weight: 600; + margin-bottom: 6px; +} +.field .input { + width: 100%; +} +.auth-row { + margin-top: 14px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + font-size: 13px; +} +.auth-row a { + color: var(--riso-blue); + text-decoration: none; +} +.auth-row a:hover { + text-decoration: underline; +} +.btn-block { + width: 100%; + margin-top: 22px; + padding-block: 13px; + font-size: 16px; +} +.auth-note { + margin-top: 20px; + padding-top: 16px; + border-top: 1.5px solid var(--ink-faint); + display: grid; + gap: 6px; + font-size: 11.5px; + letter-spacing: 0.03em; + color: var(--ink-dim); +} + +/* ---------- Toast ---------- */ +.toast { + position: fixed; + left: 50%; + bottom: 30px; + transform: translate(-50%, 16px); + background: var(--ink); + color: var(--paper); + font-size: 14px; + font-weight: 600; + padding: 11px 20px; + border-radius: 999px; + border: 2px solid var(--paper); + box-shadow: 5px 5px 0 var(--riso-blue); + opacity: 0; + pointer-events: none; + transition: + opacity 0.2s ease, + transform 0.2s ease; + z-index: 99; +} +.toast.show { + opacity: 1; + transform: translate(-50%, 0); +} + +/* ---------- 入场动效(一处编排) ---------- */ +@keyframes rise { + from { + opacity: 0; + transform: translateY(16px); + } + to { + opacity: 1; + transform: translateY(0); + } +} +@keyframes fadein { + from { + opacity: 0; + } + to { + opacity: 1; + } +} +.rise { + animation: rise 0.55s cubic-bezier(0.2, 0.7, 0.2, 1) both; +} +.d1 { + animation-delay: 0.06s; +} +.d2 { + animation-delay: 0.14s; +} +.d3 { + animation-delay: 0.22s; +} +.d4 { + animation-delay: 0.3s; +} + +/* ---------- 响应式 ---------- */ +@media (max-width: 1024px) { + .card-grid { + grid-template-columns: repeat(2, 1fr); + } + .mcp-grid { + grid-template-columns: 1fr; + } + .detail-layout { + grid-template-columns: 1fr; + } + .footer-grid { + grid-template-columns: 1fr 1fr; + } + .stat-strip { + grid-template-columns: repeat(2, 1fr); + } +} +@media (max-width: 900px) { + .auth-wrap::before, + .auth-wrap::after { + display: none; + } + .hero-grid { + grid-template-columns: 1fr; + } + .hero-visual { + min-height: 0; + display: flex; + align-items: center; + gap: 14px; + margin-top: 4px; + } + .spec-label { + position: static; + margin: 0; + flex: 1; + min-width: 0; + white-space: normal; + } + .spec-machine, + .spec-human { + display: none; + } + .btn-random { + position: static; + flex: none; + } + .list-layout { + grid-template-columns: 1fr; + } + .filter-rail { + position: static; + display: none; + border: 1.5px dashed var(--ink-faint); + border-radius: var(--r-md); + padding: 20px; + } + .filter-rail.open { + display: grid; + } + .rail-toggle { + display: inline-flex; + } + .admin-shell { + grid-template-columns: 1fr; + } + .admin-nav { + border-right: 0; + border-bottom: 2px solid var(--ink); + display: flex; + overflow-x: auto; + padding: 12px 16px; + } + .admin-nav h4 { + display: none; + } + .admin-nav button { + width: auto; + white-space: nowrap; + } + .tagmgr { + grid-template-columns: 1fr; + } + .result-row { + grid-template-columns: 1fr; + } + .result-side { + text-align: left; + justify-items: start; + grid-auto-flow: column; + } +} +@media (max-width: 640px) { + .agent-prompt { + flex-direction: column; + align-items: stretch; + } + .topnav { + display: none; + } + .topbar.menu-open .topnav { + display: grid; + position: absolute; + top: 64px; + left: 0; + right: 0; + background: var(--paper); + border-bottom: 2px solid var(--ink); + padding: 12px 24px 18px; + } + .nav-toggle { + display: inline-flex; + } + .card-grid { + grid-template-columns: 1fr; + } + .search-instrument { + flex-direction: column; + } + .search-instrument svg { + display: none; + } + .search-instrument input { + padding: 16px 18px 4px; + } + .search-instrument .btn-primary { + border-left: 0; + border-top: var(--border); + padding: 13px; + } + .footer-grid { + grid-template-columns: 1fr; + gap: 34px; + } +} + +/* ---------- 降低动效 ---------- */ +@media (prefers-reduced-motion: reduce) { + html { + scroll-behavior: auto; + } + *, + *::before, + *::after { + animation-duration: 0.001s !important; + animation-delay: 0s !important; + transition-duration: 0.001s !important; + } +} diff --git a/design/prototype/assets/js/main.js b/design/prototype/assets/js/main.js new file mode 100644 index 0000000..e161ad4 --- /dev/null +++ b/design/prototype/assets/js/main.js @@ -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") || "原型演示:该操作未执行"); + }); + }); +})(); diff --git a/design/prototype/detail.html b/design/prototype/detail.html new file mode 100644 index 0000000..a604ba9 --- /dev/null +++ b/design/prototype/detail.html @@ -0,0 +1,181 @@ + + + + + +ripgrep · Awesome Index + + + + + + + + +
+ +
+ +
+

~/awesome-index / 工具 / ripgrep

+ +
+
+

ripgrep

+ 工具 +
+ 访问仓库 ↗ + +
+
+

如果你在终端里找过东西,就值得认识 ripgrep:它把「递归 + 正则 + 快」做成了一件不需要思考的事。

+
+ +
+ +
+
+

// entry.body · markdown source

+

这是什么

+

ripgrep(命令名 rg)是一个面向目录的递归搜索工具。它默认遵循 .gitignore 规则跳过无关文件,自动跳过二进制内容,并利用 Rust 的并行与 SIMD 能力,在大代码库里的搜索速度常年第一梯队。

+

对日常使用来说,它意味着把 grep -r 那串参数彻底忘掉:rg TODO 就是全部。

+
+ +
+

为什么牛逼

+
    +
  • 默认尊重 .gitignore,搜索结果天然干净;
  • +
  • 并行遍历 + 字面量优化,速度在同类工具中长期领先;
  • +
  • 输出对人和管道都友好,可无缝接进 fzf 等工作流;
  • +
  • 单文件跨平台分发,Windows / macOS / Linux 开箱即用。
  • +
+
+ +
+

截图

+
screenshot placeholder · 16:9 建议尺寸 1280×640
+
+ +
+

// dual reader view · 人读 ⇄ 机读

+
+ + +
+
+

这一页就是人读视图。切换到「机读 JSON」可以看到 AI 通过 MCP 的 get_entry 拿到的同一条数据——两种读者,同一份事实。

+
+ +
+ +
+

// comments · 3 条

+

评论

+
+ K +
+
kentang
+

配合 fzf 之后基本回不去原生 grep 了,rg --files | fzf 是我每天用得最多的组合键。

+
+
+
+ M +
+
moss
+

Windows 下也稳,公司那台老机器上搜几十万文件的 monorepo 依然秒出。

+
+
+
+ A +
+
anon-42
+

建议补一条标签:可以加到「AI 编码代理常用工具」组里,agent 检索代码很依赖它。

+
+
+ +
+
+ +
+ +
+ +
+
+
+
+ + + +
+
+ + + +
+ + + diff --git a/design/prototype/index.html b/design/prototype/index.html new file mode 100644 index 0000000..3437b66 --- /dev/null +++ b/design/prototype/index.html @@ -0,0 +1,240 @@ + + + + + +Awesome Index · 把网上牛逼的东西收进一个库 + + + + + + + + + +
+ +
+ +
+ +
+
+
+

~/awesome-index — 给人用,也给 AI 用

+

把网上牛逼的东西
收进一个好用的库。

+

人工精选的开源软件、微服务、SaaS、网站、工具、脚本与插件。每一条都是结构化数据:人在页面上搜,AI 通过 MCP 直接调用。

+ + +

+ + + + 给 AI 用?本站提供 MCP 接口 + + + +

+ 收录 1,284 + 标签组 96 + 本周新增 +23 + 存储 DuckDB + MCP 就绪 +

+
+ + + +
+
+ + +
+
+

// mcp.transport: streamable-http · auth: none

+

同一个库,两种读者。
AI 走这边。

+

本站所有条目同时暴露为 MCP(Model Context Protocol)接口。把下面的地址加进你的 AI 客户端,Claude、Cursor 或任何支持 MCP 的 Agent 就能直接搜索与读取这个库。

+ + +
+
+

不想手动改配置?

+

复制下面这句话发给你的 Agent,它会自己完成接入:

+
「请把 URL 为 https://honor3.com/mcp 的 MCP 服务器添加到你的客户端配置中,名称用 awesome-index,完成后告诉我现在可以调用哪些工具。」
+
+ +
+ +
+ + +
+
+
01

把服务器加进客户端配置

+
{
+  "mcpServers": {
+    "awesome-index": {
+      "url": "https://honor3.com/mcp"
+    }
+  }
+}
+
+
+
02

可用的工具

+ + + + + + + + +
tool说明
search_entries按关键字、类型、标签搜索收录内容
get_entry获取单条的完整详情与元数据
random_entry随机返回一条,用于探索发现
list_tags列出全部标签组及其嵌套结构
+
+
+
03

直接问你的 AI

+
「用 awesome-index 找三个能自托管的相册方案,
+  按 star 数排序,给我 repo 链接。」
+
+
+
+
+
+ + +
+
+
+

// resource: recent_entries · limit 4

+

最近收录

+
+ 查看全部 → +
+ +
+
+ + + + +
+ + + diff --git a/design/prototype/list.html b/design/prototype/list.html new file mode 100644 index 0000000..cef67e8 --- /dev/null +++ b/design/prototype/list.html @@ -0,0 +1,217 @@ + + + + + +搜索结果 · Awesome Index + + + + + + + + +
+ +
+ +
+
+

// tool: search_entries · filters applied server-side

+

「终端工具」的搜索结果

+
+ + + +
+ 47 条结果 · 用时 6ms +
+ + + +
+
+ +
+ + + + +
+ + 工具 +
+

ripgrep (rg)

+

正则递归搜索目录,默认尊重 .gitignore。终端里找东西的事实标准。

+
RustCLI跨平台
+
+
+ ★ 52.3k + MIT · 更新于 3 天前 +
+
+ + + 工具 +
+

fzf

+

通用模糊查找器,管道进任何列表都能交互式筛选,终端工作流的粘合剂。

+
GoCLI跨平台
+
+
+ ★ 68.1k + MIT · 更新于 1 周前 +
+
+ + + 工具 +
+

fd

+

find 的现代替代品,语法直觉、彩色输出、快得离谱,和 fzf 是天生一对。

+
RustCLI
+
+
+ ★ 35.7k + Apache-2.0 · 更新于 4 天前 +
+
+ + + 脚本 +
+

zoxide

+

记录你的 cd 习惯,之后打 z proj 就能跳到最常去的目录。

+
RustCLIShell
+
+
+ ★ 24.9k + MIT · 更新于 2 周前 +
+
+ + + 应用 +
+

Warp Terminal

+

以块为单位的现代终端,命令输入、输出、报错各自独立,AI 补全内建。

+
Rust跨平台AI 就绪
+
+
+ ★ 22.4k + 专有 · 更新于 6 天前 +
+
+ + + 微服务 +
+

ttyd

+

把任意终端程序共享到浏览器里,一条命令起一个 Web 终端。

+
C自托管Docker 就绪
+
+
+ ★ 10.2k + MIT · 更新于 1 月前 +
+
+ + +
+
+
+ + + +
+ + + diff --git a/design/prototype/login.html b/design/prototype/login.html new file mode 100644 index 0000000..0dd5c14 --- /dev/null +++ b/design/prototype/login.html @@ -0,0 +1,76 @@ + + + + + +管理台登录 · Awesome Index + + + + + + + + +
+ +
+ +
+
+
+

// route: /admin/login · auth: session cookie

+ +

管理台登录

+

人工通道。AI Agent 请走 MCP 接口——这扇门不对机器开放。

+ +
+
+ + +
+
+ + +
+
+ + 忘记密码? +
+ +
+ +
+ // demo 账号:admin / admin + // agents: POST /mcp · 此处返回 403 +
+
+
+
+ + + +
+ + +