chore: import zh skill github-dashboard

This commit is contained in:
wehub-skill-sync
2026-07-13 21:35:40 +08:00
commit 51fcfa795f
8 changed files with 1340 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
# WeHub 来源说明
- Skill 名称:`github-dashboard`
- 中文类目:仓库/团队管理仪表盘
- 上游仓库:`nexu-io__open-design`
- 上游路径:`design-templates/github-dashboard/SKILL.md`
- 上游链接:https://github.com/nexu-io/open-design/blob/HEAD/design-templates/github-dashboard/SKILL.md
- 本仓库为 WeHub 中文 Skill 汉化包,基于 skill 市场筛选 Top200 清单整理
- 原作者、版权和许可证信息以上游仓库为准
+130
View File
@@ -0,0 +1,130 @@
---
name: github-dashboard
description: |
GitHub 仓库分析看板 —— 星标、复刻、贡献者、
Issue、Pull Request、近期活动及主要贡献者。当需求中提及
GitHub 仓库看板、开源项目增长报告、仓库健康页面或
GitHub 分析视图时使用。
triggers:
- "github dashboard"
- "repo dashboard"
- "repository dashboard"
- "github analytics"
- "open source dashboard"
- "github growth"
- "仓库看板"
- "GitHub 看板"
od:
mode: prototype
platform: desktop
scenario: operation
preview:
type: html
entry: index.html
design_system:
requires: true
sections: [color, typography, layout, components]
outputs:
primary: index.html
secondary:
- template.html
- data.json
- artifact.json
- provenance.json
capabilities_required:
- shell
- file_write
example_prompt: "Build a GitHub dashboard for nexu-io/open-design — stars, forks, contributors, issues, PRs, recent activity, and top contributors."
---
# GitHub 看板技能
以 FlowAI / Soft Paper Workspace 视觉风格创建单个屏幕的 GitHub 仓库分析看板:暖白画布、白色圆角面板、固定左侧边栏、紧凑的 KPI 卡片、柔和色块、密集表格以及低对比度细线。
## 资源结构
```
github-dashboard/
├── SKILL.md
├── example.html ← 渲染后的参考看板
└── references/
├── template.html ← 兼容 live-artifact 的 HTML 模板
├── example-data.json ← 标准化的公开 GitHub 数据形态
├── artifact-example.json ← 最简 live-artifact 创建输入
└── provenance-example.json ← 安全的数据来源/溯源示例
```
## 何时使用此技能
当用户请求针对单个 GitHub 仓库的看板或报告时使用,例如:
- 仓库增长看板
- 开源项目健康报告
- GitHub 星标 / 复刻 / 贡献者分析
- Issue 与 Pull Request 活动页面
- 维护者 / 贡献者看板
如果用户要求可刷新、来源可审计或定时更新,则生成 live-artifact 源文件集(`template.html``data.json``artifact.json``provenance.json`)并遵循 `live-artifact` 约定。如果仅需可视化产物,则生成独立自包含的 `index.html`
## 工作流程
1. **确认仓库范围**
- 从需求中解析 `owner/repo`
- 本 v1 版技能仅针对单个仓库。如果请求多个仓库,请用户选择主仓库,或为每个仓库分别创建看板。
- 如果仓库缺失,用一句话询问 GitHub URL 或 `owner/repo`
2. **收集公开 GitHub 数据**
- 优先使用 GitHub CLI/API 获取公开仓库数据。
- 当前星标/复刻/关注者/开放 Issue 数量:`GET /repos/{owner}/{repo}``stargazers_count``forks_count``watchers_count``open_issues_count`)。
- 贡献者:分页请求 `GET /repos/{owner}/{repo}/contributors?per_page=100&page=N`,按 `contributions` 降序排列,取看板使用的前 N 名。如果只取到第 1 页,将总数标注为首页估算值。
- Issue:使用 GitHub 搜索 API`repo:{owner}/{repo} is:issue`)获取总数,或分页请求 `GET /repos/{owner}/{repo}/issues?state=all` 并过滤掉含有 `pull_request` 字段的条目。
- Pull Request:使用 GitHub 搜索 API`repo:{owner}/{repo} is:pr`)获取总数,或分页请求 `GET /repos/{owner}/{repo}/pulls?state=all` 并通过 `Link` 头部统计页数。
- 近期活动:合并最新的 Issue 和 Pull Request,将其规范化为可直接展示的行,预览列表控制在 5–10 条。
- 增长/增量指标:GitHub REST 不提供完整的历史星标/复刻增量。可使用 GraphQL、星标事件快照、Events API(可用时),或在 `provenance.json` 中明确标注增量为估算/合成数据。
- 不得存储认证令牌、原始 HTTP 信封、Cookie、速率限制头部或私有元数据。
3. **标准化为看板数据**
- 必填 `repository``name``fullName``url``description``language``license``created``lastUpdated`
- 必填 `metrics`:星标、复刻、贡献者、Issue、Pull Request。存储可直接展示的总数及小幅增量或增长说明。
- 必填 `contributors`:前 58 位贡献者,包含 `login``avatar``contributions`
- 必填 `recentActivity`:可直接展示的行,包含 `title``typeText``typeClass``label``labelClass``author``authorAvatar``updated`。不得依赖模板条件判断来处理 Issue/PR 切换。
- 图表数据仅在 GitHub 未暴露精确历史数据时可为合成数据;在 provenance 中记录转换过程。
4. **应用视觉系统**
- 存在活跃的 `DESIGN.md` 令牌时优先使用。
- 如果未提供设计系统,使用 `references/template.html` 中所反映的 Soft Paper 默认值:`#F2F2F0` 画布、白色卡片、`#ECECEA` 边框、`#0A0A0A` 墨色、Geist/Inter 字体、256px 侧边栏、48px 顶栏、16px 卡片圆角。
- 颜色使用应克制且具有语义:绿色代表健康指标、琥珀色代表警告、蓝色代表功能/PR 标签,红色仅用于缺陷或风险。
5. **布局页面**
- 外壳:256px 侧边栏 + 主面板,均为白色、圆角 16px、1px 细线边框。
- 顶栏:左侧为仓库上下文,右侧为刷新/导出/操作入口。
- 头部:仓库名称、描述及日期/设置/操作行。
- KPI 条:5 张紧凑卡片,分别展示星标、复刻、贡献者、Issue、PR。
- 主网格:2fr/1fr 分割,左侧为增长图表或活动表格,右侧为热门贡献者/健康卡片。
- 页脚:以小号浅色文字显示来源/最后更新时间。
6. **写入产物**
- 对于静态产物,写入一个独立的 `index.html`,内联 CSS,不依赖外部 JS 库。
- 对于 live artifact,写入 `template.html``data.json``artifact.json``provenance.json``index.html` 由守护进程派生。
- 用稳定的 `data-od-id` 值标记主要区域:`sidebar``topbar``repo-header``kpi-strip``growth-chart``contributors``activity``provenance`
## 视觉规则
- 仅限浅色模式。
- 桌面端 256px 固定侧边栏;窄屏幕时堆叠排列。
- 第一行放置 4 或 5 张 KPI 卡片。
- 所有计数使用表格衬线数字。
- 头像为圆形,表格和贡献者列表中为 28–32px。
- 表格正文 13px,列表列标签 11px 大写,行分隔线 1px。
- 卡片使用细线边框,最多使用几乎不可见的阴影:`0 1px 2px rgba(10,10,10,.04), 0 1px 1px rgba(10,10,10,.02)`
- 除小型工作流/仓库图标占位符外,不使用渐变。
- 页面不得看起来像 GitHub 本身。这是一个自定义运营看板,而非 GitHub UI 克隆。
## 自查清单
- 每个指标都有来源或溯源说明。
- 不持久化任何私有数据或凭据。
- 数据标签与具体仓库对应,而非占位符。
- 在 50% 缩放比例下屏幕仍清晰可读。
- 每个区域最多使用一个纯黑色主要操作按钮。
- 状态标签和 Issue/PR 标签为柔和色块,而非高饱和度徽章。
+473
View File
@@ -0,0 +1,473 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>open-design — GitHub 仪表盘</title>
<style>
:root {
--canvas: #f2f2f0;
--surface: #ffffff;
--surface-muted: #fafaf9;
--border: #ececea;
--border-strong: #e2e2df;
--text-primary: #0a0a0a;
--text-secondary: #6b6b6b;
--text-tertiary: #9a9a95;
--active-bg: #e6f4ea;
--active-fg: #1f8a4c;
--pending-bg: #fff6d6;
--pending-fg: #9a7b12;
--feature-bg: #dcebff;
--feature-fg: #2f66c9;
--danger-bg: #fdecec;
--danger-fg: #c0392b;
--green: #34a853;
--amber: #e8a23a;
--red: #d94a3d;
--shadow: 0 1px 2px rgba(10, 10, 10, .04), 0 1px 1px rgba(10, 10, 10, .02);
--radius-card: 16px;
--radius-tile: 12px;
--radius-control: 8px;
font-family: Geist, Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-feature-settings: "tnum", "lnum";
}
* { box-sizing: border-box; }
body { margin: 0; background: var(--canvas); color: var(--text-primary); }
.shell { min-height: 100vh; padding: 16px; display: grid; grid-template-columns: 256px 1fr; gap: 16px; }
.sidebar, .main { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-card); box-shadow: var(--shadow); }
.sidebar { padding: 16px; display: flex; flex-direction: column; gap: 22px; }
.brand { height: 48px; display: flex; align-items: center; gap: 10px; font-weight: 600; font-size: 15px; }
.logo { width: 32px; height: 32px; border-radius: 8px; background: linear-gradient(135deg, #2f66c9, #5a8ded); color: white; display: grid; place-items: center; font-size: 18px; font-weight: 600; }
.group-label { display: flex; align-items: center; gap: 8px; color: var(--text-tertiary); font-size: 11px; font-weight: 500; letter-spacing: .02em; text-transform: uppercase; margin-bottom: 8px; margin-top: 4px; }
.dot-ring { width: 14px; height: 14px; border: 1.5px dashed var(--text-tertiary); border-radius: 999px; flex: none; }
.nav { display: grid; gap: 4px; }
.nav-item { min-height: 36px; display: flex; align-items: center; justify-content: space-between; gap: 10px; border-radius: var(--radius-control); padding: 8px 10px; color: var(--text-secondary); font-size: 13px; text-decoration: none; transition: all .15s; }
.nav-item:hover { background: var(--surface-muted); }
.nav-item.active { background: var(--surface-muted); color: var(--text-primary); font-weight: 500; }
.count { border-radius: 999px; padding: 2px 8px; background: var(--surface-muted); color: var(--text-secondary); font-size: 11px; font-weight: 500; }
.main { overflow: hidden; }
.topbar { height: 48px; border-bottom: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; padding: 0 20px; font-size: 14px; }
.topbar-title { display: flex; align-items: center; gap: 10px; }
.topbar-icon { width: 20px; height: 20px; opacity: .7; }
.content { padding: 24px 28px 32px; display: grid; gap: 24px; }
.page-head { display: flex; align-items: end; justify-content: space-between; gap: 16px; }
h1 { margin: 0; font-size: 22px; line-height: 1.25; font-weight: 600; letter-spacing: -.005em; }
.subtitle { margin-top: 6px; color: var(--text-secondary); font-size: 14px; line-height: 1.4; }
.actions { display: flex; gap: 8px; align-items: center; }
button, .button { border: 1px solid var(--border-strong); background: var(--surface); border-radius: var(--radius-control); padding: 8px 14px; color: var(--text-primary); font: inherit; font-size: 12px; cursor: pointer; transition: all .15s; text-decoration: none; display: inline-flex; align-items: center; justify-content: center; }
button:hover, .button:hover { background: var(--surface-muted); }
button.primary, .button.primary { background: var(--text-primary); color: #fff; border-color: var(--text-primary); }
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-card); box-shadow: var(--shadow); padding: 20px; }
.tabs { display: inline-flex; background: var(--surface-muted); border-radius: 12px; padding: 4px; gap: 4px; }
.tab { padding: 6px 12px; border-radius: var(--radius-control); color: var(--text-secondary); font-size: 12px; cursor: pointer; transition: all .15s; border: 1px solid transparent; text-decoration: none; }
.tab.active { background: var(--surface); color: var(--text-primary); border: 1px solid var(--border); box-shadow: var(--shadow); }
.kpis { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 16px; }
.kpi { min-height: 84px; border: 1px solid var(--border); border-radius: var(--radius-tile); background: var(--surface-muted); padding: 14px; display: flex; flex-direction: column; }
.kpi-top { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.glyph { width: 28px; height: 28px; border-radius: 8px; background: var(--surface); border: 1px solid var(--border); display: inline-grid; place-items: center; box-shadow: var(--shadow); font-size: 14px; flex: none; }
.kpi-label { color: var(--text-secondary); font-size: 13px; }
.kpi-num { font-size: 28px; font-weight: 600; line-height: 1.1; margin-top: auto; }
.kpi-trend { font-size: 12px; color: var(--green); margin-top: 4px; font-weight: 500; }
.kpi-trend.down { color: var(--text-tertiary); }
.grid { display: grid; grid-template-columns: 2fr 1fr; gap: 16px; }
.grid-full { display: grid; grid-template-columns: 1fr; gap: 16px; }
.card-title { display: flex; align-items: center; gap: 8px; font-size: 16px; font-weight: 600; margin-bottom: 16px; }
.tick-rule { height: 24px; margin: 8px 0 16px; background: repeating-linear-gradient(90deg, var(--border) 0 1px, transparent 1px 8px); }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
.table-scroll { overflow-x: auto; }
.table-scroll table { min-width: 760px; }
th { text-align: left; padding: 10px 12px; color: var(--text-tertiary); font-size: 11px; font-weight: 500; letter-spacing: .01em; background: var(--surface-muted); text-transform: uppercase; }
td { padding: 14px 12px; border-top: 1px solid var(--border); color: var(--text-secondary); }
td strong { color: var(--text-primary); font-weight: 500; }
.mono { font-family: "Geist Mono", "JetBrains Mono", ui-monospace, monospace; font-size: 12px; }
.pill { display: inline-flex; align-items: center; gap: 6px; border-radius: 999px; padding: 3px 10px; font-size: 11px; font-weight: 500; }
.pill::before { content: ""; width: 6px; height: 6px; border-radius: 999px; background: currentColor; }
.active-pill { background: var(--active-bg); color: var(--active-fg); }
.pending-pill { background: var(--pending-bg); color: var(--pending-fg); }
.feature-pill { background: var(--feature-bg); color: var(--feature-fg); }
.danger-pill { background: var(--danger-bg); color: var(--danger-fg); }
.avatar { width: 28px; height: 28px; border-radius: 999px; border: 1px solid var(--border); background: linear-gradient(135deg, #dcecff, #f8eadb); display: inline-grid; place-items: center; color: var(--text-secondary); font-size: 11px; font-weight: 500; margin-right: 8px; overflow: hidden; flex: none; }
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.contrib { display: grid; gap: 10px; }
.person { display: flex; align-items: center; justify-content: space-between; gap: 10px; border: 1px solid var(--border); border-radius: 12px; padding: 12px; background: var(--surface-muted); }
.person-info { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; }
.person-name { font-weight: 500; font-size: 13px; color: var(--text-primary); }
.person-role { font-size: 12px; color: var(--text-secondary); margin-top: 2px; }
.chart-container { position: relative; height: 180px; margin-top: 16px; }
.chart { width: 100%; height: 100%; }
.chart-bars { display: flex; align-items: flex-end; justify-content: space-between; height: 100%; gap: 8px; }
.bar { flex: 1; background: linear-gradient(180deg, var(--green) 0%, #2d8a47 100%); border-radius: 4px 4px 0 0; min-height: 4px; position: relative; transition: all .2s; }
.bar:hover { opacity: .85; }
.bar-label { position: absolute; bottom: -22px; left: 50%; transform: translateX(-50%); font-size: 11px; color: var(--text-tertiary); white-space: nowrap; }
.trend-line { display: flex; align-items: flex-end; height: 100%; gap: 2px; }
.trend-point { flex: 1; background: var(--feature-fg); border-radius: 2px 2px 0 0; min-height: 2px; }
.issue-row { display: flex; align-items: start; gap: 12px; padding: 14px 12px; border-top: 1px solid var(--border); }
.issue-row:first-child { border-top: none; }
.issue-icon { width: 20px; height: 20px; border-radius: 999px; background: var(--active-bg); color: var(--active-fg); display: grid; place-items: center; font-size: 11px; flex: none; margin-top: 2px; }
.issue-icon.pr { background: var(--feature-bg); color: var(--feature-fg); }
.issue-content { flex: 1; min-width: 0; }
.issue-title { font-size: 14px; font-weight: 500; color: var(--text-primary); margin-bottom: 4px; }
.issue-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 12px; color: var(--text-tertiary); margin-top: 6px; }
.issue-meta span { display: flex; align-items: center; gap: 4px; }
.provenance-note { color: var(--text-tertiary); font-size: 12px; line-height: 1.5; padding: 4px 2px; }
@media (max-width: 980px) {
.shell { grid-template-columns: 1fr; }
.kpis { grid-template-columns: repeat(2, 1fr); }
.grid { grid-template-columns: 1fr; }
.sidebar { min-height: auto; }
}
</style>
</head>
<body>
<div class="shell">
<aside class="sidebar" data-od-id="sidebar">
<div class="brand">
<div class="logo">OD</div>
<span>open-design</span>
</div>
<section>
<div class="group-label"><span class="dot-ring"></span> 仓库</div>
<div class="nav">
<a href="#overview" class="nav-item active">概览</a>
<a href="#activity" class="nav-item">活动 <span class="count">5</span></a>
<a href="#contributors" class="nav-item">贡献者 <span class="count">87</span></a>
<a href="#community" class="nav-item">社区</a>
</div>
</section>
<section>
<div class="group-label"><span class="dot-ring"></span> 指标</div>
<div class="nav">
<a href="#growth-chart" class="nav-item">Star 增长</a>
<a href="#fork-trend" class="nav-item">Fork 动态</a>
<a href="#activity" class="nav-item">Issue 趋势</a>
<a href="#activity" class="nav-item">PR 速度</a>
</div>
</section>
<section>
<div class="group-label"><span class="dot-ring"></span> 快速链接</div>
<div class="nav">
<a href="https://github.com/nexu-io/open-design" class="nav-item">GitHub 仓库</a>
<a href="https://github.com/nexu-io/open-design#readme" class="nav-item">文档</a>
<a href="https://github.com/nexu-io/open-design/discussions" class="nav-item">讨论</a>
</div>
</section>
</aside>
<main class="main">
<div class="topbar" data-od-id="topbar">
<div class="topbar-title">
<svg class="topbar-icon" fill="currentColor" viewBox="0 0 16 16">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/>
</svg>
<span>open-design 仪表盘</span>
</div>
<div class="actions">
<button>2026 年 5 月 6 日</button>
<button>⟳ 刷新</button>
</div>
</div>
<div class="content">
<header class="page-head" data-od-id="repo-header" id="overview">
<div>
<h1>nexu-io/open-design</h1>
<div class="subtitle">本地优先、开源的 Anthropic Claude Design 替代方案。19 个技能 · 71 个品牌级 Design System · 生成网页/桌面/移动端原型 · 幻灯片 · 图片 · 视频</div>
</div>
<div class="actions">
<a class="button" href="https://github.com/nexu-io/open-design">在 GitHub 上查看 →</a>
</div>
</header>
<section class="card">
<div class="tabs" role="tablist" aria-label="仪表盘分区">
<a href="#overview" class="tab active" role="tab">指标</a>
<a href="#activity" class="tab" role="tab">活动</a>
<a href="#contributors" class="tab" role="tab">贡献者</a>
<a href="#community" class="tab" role="tab">社区</a>
</div>
<div class="kpis" style="margin-top:16px" data-od-id="kpi-strip">
<div class="kpi">
<div class="kpi-top">
<span class="glyph"></span>
<span class="kpi-label">Star</span>
</div>
<div class="kpi-num">29,070</div>
<div class="kpi-trend">本周 +2,847</div>
</div>
<div class="kpi">
<div class="kpi-top">
<span class="glyph"></span>
<span class="kpi-label">Fork</span>
</div>
<div class="kpi-num">3,167</div>
<div class="kpi-trend">本周 +218</div>
</div>
<div class="kpi">
<div class="kpi-top">
<span class="glyph"></span>
<span class="kpi-label">贡献者</span>
</div>
<div class="kpi-num">87</div>
<div class="kpi-trend">12 位活跃</div>
</div>
<div class="kpi">
<div class="kpi-top">
<span class="glyph"></span>
<span class="kpi-label">未关闭 Issue</span>
</div>
<div class="kpi-num">230</div>
<div class="kpi-trend down">共 450 个</div>
</div>
<div class="kpi">
<div class="kpi-top">
<span class="glyph"></span>
<span class="kpi-label">Pull Request</span>
</div>
<div class="kpi-num">5</div>
<div class="kpi-trend down">共 653 个</div>
</div>
</div>
</section>
<section class="grid">
<div class="card" data-od-id="growth-chart" id="growth-chart">
<div class="card-title"><span class="dot-ring"></span> Star 增长(最近 30 天)</div>
<div class="chart-container">
<div class="chart-bars">
<div class="bar" style="height: 45%;">
<span class="bar-label">第 1 周</span>
</div>
<div class="bar" style="height: 62%;">
<span class="bar-label">第 2 周</span>
</div>
<div class="bar" style="height: 78%;">
<span class="bar-label">第 3 周</span>
</div>
<div class="bar" style="height: 100%;">
<span class="bar-label">第 4 周</span>
</div>
</div>
</div>
</div>
<aside class="card" data-od-id="contributors" id="contributors">
<div class="card-title"><span class="dot-ring"></span> 热门贡献者</div>
<div class="tick-rule"></div>
<div class="contrib">
<div class="person">
<div class="person-info">
<div class="avatar">
<img src="https://avatars.githubusercontent.com/u/26423749?v=4" alt="pftom" />
</div>
<div>
<div class="person-name">pftom</div>
<div class="person-role">26 次贡献</div>
</div>
</div>
<span class="pill pending-pill">26</span>
</div>
<div class="person">
<div class="person-info">
<div class="avatar">
<img src="https://avatars.githubusercontent.com/u/20859779?v=4" alt="lefarcen" />
</div>
<div>
<div class="person-name">lefarcen</div>
<div class="person-role">18 次贡献</div>
</div>
</div>
<span class="pill pending-pill">18</span>
</div>
<div class="person">
<div class="person-info">
<div class="avatar">
<img src="https://avatars.githubusercontent.com/u/201593046?v=4" alt="Sid-Qin" />
</div>
<div>
<div class="person-name">Sid-Qin</div>
<div class="person-role">17 次贡献</div>
</div>
</div>
<span class="pill pending-pill">17</span>
</div>
<div class="person">
<div class="person-info">
<div class="avatar">
<img src="https://avatars.githubusercontent.com/u/3953668?v=4" alt="nettee" />
</div>
<div>
<div class="person-name">nettee</div>
<div class="person-role">10 次贡献</div>
</div>
</div>
<span class="pill pending-pill">10</span>
</div>
<div class="person">
<div class="person-info">
<div class="avatar">
<img src="https://avatars.githubusercontent.com/u/56862773?v=4" alt="alchemistklk" />
</div>
<div>
<div class="person-name">alchemistklk</div>
<div class="person-role">9 次贡献</div>
</div>
</div>
<span class="pill pending-pill">9</span>
</div>
</div>
</aside>
</section>
<section class="grid-full">
<div class="card" data-od-id="activity" id="activity">
<div class="card-title"><span class="dot-ring"></span> 最近活动</div>
<div class="table-scroll">
<table>
<thead>
<tr>
<th style="width: 50px;">类型</th>
<th>标题</th>
<th style="width: 120px;">状态</th>
<th style="width: 140px;">作者</th>
<th style="width: 100px;">更新时间</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<span class="issue-icon pr">PR</span>
</td>
<td><strong>添加支付宝商家入驻技能</strong></td>
<td>
<span class="pill feature-pill">feature</span>
</td>
<td>
<div style="display: flex; align-items: center;">
<span class="avatar" style="margin-right: 8px;">
<img src="https://avatars.githubusercontent.com/u/238133142?v=4" alt="leilei926524-tech" />
</span>
<span>leilei926524-tech</span>
</div>
</td>
<td class="mono" style="color: var(--text-tertiary);">2 小时前</td>
</tr>
<tr>
<td><span class="issue-icon issue">ISSUE</span></td>
<td><strong>在设置中保存 API 密钥后添加明确的成功反馈</strong></td>
<td><span class="pill danger-pill">bug</span></td>
<td>
<div style="display: flex; align-items: center;">
<span class="avatar" style="margin-right: 8px;"><img src="https://avatars.githubusercontent.com/u/237175303?v=4" alt="shangxinyu1" /></span>
<span>shangxinyu1</span>
</div>
</td>
<td class="mono" style="color: var(--text-tertiary);">2 小时前</td>
</tr>
<tr>
<td><span class="issue-icon issue">ISSUE</span></td>
<td><strong>hermes json-rpc id 2: Invalid params</strong></td>
<td><span class="pill danger-pill">bug</span></td>
<td>
<div style="display: flex; align-items: center;">
<span class="avatar" style="margin-right: 8px;"><img src="https://avatars.githubusercontent.com/u/42241934?v=4" alt="zlpawn" /></span>
<span>zlpawn</span>
</div>
</td>
<td class="mono" style="color: var(--text-tertiary);">3 小时前</td>
</tr>
<tr>
<td><span class="issue-icon pr">PR</span></td>
<td><strong>fix: 修复0.4.0版本聊天窗口宽度溢出问题</strong></td>
<td><span class="pill active-pill">bug-fix</span></td>
<td>
<div style="display: flex; align-items: center;">
<span class="avatar" style="margin-right: 8px;"><img src="https://avatars.githubusercontent.com/u/12208097?v=4" alt="1119302165" /></span>
<span>1119302165</span>
</div>
</td>
<td class="mono" style="color: var(--text-tertiary);">4 小时前</td>
</tr>
<tr>
<td><span class="issue-icon issue">ISSUE</span></td>
<td><strong>修复 Open Design 未从 Codex CLI 读取最新模型列表的问题</strong></td>
<td><span class="pill danger-pill">bug</span></td>
<td>
<div style="display: flex; align-items: center;">
<span class="avatar" style="margin-right: 8px;"><img src="https://avatars.githubusercontent.com/u/237175303?v=4" alt="shangxinyu1" /></span>
<span>shangxinyu1</span>
</div>
</td>
<td class="mono" style="color: var(--text-tertiary);">5 小时前</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section class="grid">
<div class="card" id="fork-trend">
<div class="card-title"><span class="dot-ring"></span> Fork 趋势(最近 30 天)</div>
<div class="chart-container">
<div class="trend-line">
<div class="trend-point" style="height: 35%;"></div>
<div class="trend-point" style="height: 42%;"></div>
<div class="trend-point" style="height: 48%;"></div>
<div class="trend-point" style="height: 55%;"></div>
<div class="trend-point" style="height: 61%;"></div>
<div class="trend-point" style="height: 68%;"></div>
<div class="trend-point" style="height: 74%;"></div>
<div class="trend-point" style="height: 82%;"></div>
<div class="trend-point" style="height: 88%;"></div>
<div class="trend-point" style="height: 95%;"></div>
<div class="trend-point" style="height: 100%;"></div>
</div>
</div>
</div>
<div class="card">
<div class="card-title"><span class="dot-ring"></span> 仓库统计</div>
<div class="tick-rule"></div>
<table>
<tbody>
<tr>
<td><strong>主要语言</strong></td>
<td style="text-align: right;">TypeScript</td>
</tr>
<tr>
<td><strong>许可证</strong></td>
<td style="text-align: right;">Apache-2.0</td>
</tr>
<tr>
<td><strong>创建时间</strong></td>
<td style="text-align: right;">2026 年 4 月 28 日</td>
</tr>
<tr>
<td><strong>最后更新</strong></td>
<td style="text-align: right;">2026 年 5 月 6 日</td>
</tr>
<tr>
<td><strong>仓库大小</strong></td>
<td style="text-align: right;">112 MB</td>
</tr>
</tbody>
</table>
</div>
</section>
<footer class="provenance-note" data-od-id="provenance">
数据更新于 2026 年 5 月 6 日,来源于公开的 GitHub API 字段。估算的趋势数据记录在 provenance.json 中。
</footer>
</div>
</main>
</div>
</body>
</html>
+10
View File
@@ -0,0 +1,10 @@
# GitHub Dashboard 参考资料
这些文件是从公开的 `nexu-io/open-design` dashboard 产物(artifact)中生成的示例。
- `template.html` —— 一个兼容实时产物(live-artifact)的模板,使用转义的 `{{data.path}}` 绑定。
- `example-data.json` —— 精简且归一化的 GitHub Dashboard 数据。
- `artifact-example.json` —— 用于可刷新的实时产物的最小化守护进程创建输入。
- `provenance-example.json` —— 针对公开 GitHub API 来源及其转换操作的安全溯源说明。
请将这些文件作为实现时的参考,而非强制性输出。该技能(skill)可根据用户对可刷新性的需求,生成静态的 `index.html` 或实时产物源文件集。
+15
View File
@@ -0,0 +1,15 @@
{
"title": "Open Design GitHub Dashboard",
"slug": "open-design-github-dashboard",
"status": "active",
"preview": {
"type": "html",
"entry": "index.html"
},
"document": {
"format": "html_template_v1",
"templatePath": "template.html",
"generatedPreviewPath": "index.html",
"dataPath": "data.json"
}
}
+138
View File
@@ -0,0 +1,138 @@
{
"repository": {
"name": "open-design",
"fullName": "nexu-io/open-design",
"url": "https://github.com/nexu-io/open-design",
"description": "Local-first, open-source alternative to Anthropic's Claude Design. 19 Skills · 71 brand-grade Design Systems · Generate web/desktop/mobile prototypes · slides · images · videos",
"language": "TypeScript",
"license": "Apache-2.0",
"created": "Apr 28, 2026",
"lastUpdated": "May 6, 2026",
"size": "112 MB"
},
"metrics": {
"stars": {
"total": "29,070",
"growth": "2,847"
},
"forks": {
"total": "3,167",
"growth": "218"
},
"contributors": {
"total": "87",
"active": "12"
},
"issues": {
"open": "230",
"total": "450"
},
"pullRequests": {
"open": "5",
"total": "653"
}
},
"charts": {
"starGrowth": [
{ "label": "W1", "height": 45 },
{ "label": "W2", "height": 62 },
{ "label": "W3", "height": 78 },
{ "label": "W4", "height": 100 }
],
"forkTrend": [
{ "height": 35 },
{ "height": 42 },
{ "height": 48 },
{ "height": 55 },
{ "height": 61 },
{ "height": 68 },
{ "height": 74 },
{ "height": 82 },
{ "height": 88 },
{ "height": 95 },
{ "height": 100 }
]
},
"contributors": [
{
"login": "pftom",
"avatar": "https://avatars.githubusercontent.com/u/26423749?v=4",
"contributions": 26
},
{
"login": "lefarcen",
"avatar": "https://avatars.githubusercontent.com/u/20859779?v=4",
"contributions": 18
},
{
"login": "Sid-Qin",
"avatar": "https://avatars.githubusercontent.com/u/201593046?v=4",
"contributions": 17
},
{
"login": "nettee",
"avatar": "https://avatars.githubusercontent.com/u/3953668?v=4",
"contributions": 10
},
{
"login": "alchemistklk",
"avatar": "https://avatars.githubusercontent.com/u/56862773?v=4",
"contributions": 9
}
],
"recentActivity": [
{
"typeText": "PR",
"typeClass": "pr",
"title": "Add Alipay merchant onboarding skill",
"label": "feature",
"labelClass": "feature-pill",
"author": "leilei926524-tech",
"authorAvatar": "https://avatars.githubusercontent.com/u/238133142?v=4",
"updated": "2 hours ago"
},
{
"typeText": "ISSUE",
"typeClass": "issue",
"title": "Add clear success feedback after saving API keys in Settings",
"label": "bug",
"labelClass": "danger-pill",
"author": "shangxinyu1",
"authorAvatar": "https://avatars.githubusercontent.com/u/237175303?v=4",
"updated": "2 hours ago"
},
{
"typeText": "ISSUE",
"typeClass": "issue",
"title": "hermes json-rpc id 2: Invalid params",
"label": "bug",
"labelClass": "danger-pill",
"author": "zlpawn",
"authorAvatar": "https://avatars.githubusercontent.com/u/42241934?v=4",
"updated": "3 hours ago"
},
{
"typeText": "PR",
"typeClass": "pr",
"title": "fix: 修复0.4.0版本聊天窗口宽度溢出问题",
"label": "bug-fix",
"labelClass": "active-pill",
"author": "1119302165",
"authorAvatar": "https://avatars.githubusercontent.com/u/12208097?v=4",
"updated": "4 hours ago"
},
{
"typeText": "ISSUE",
"typeClass": "issue",
"title": "Fix Open Design not reading the latest model list from Codex CLI",
"label": "bug",
"labelClass": "danger-pill",
"author": "shangxinyu1",
"authorAvatar": "https://avatars.githubusercontent.com/u/237175303?v=4",
"updated": "5 hours ago"
}
],
"metadata": {
"lastUpdated": "May 6, 2026"
}
}
+92
View File
@@ -0,0 +1,92 @@
{
"sources": [
{
"type": "github_api",
"description": "GitHub REST API v3",
"endpoints": [
"GET /repos/nexu-io/open-design",
"GET /repos/nexu-io/open-design/contributors?per_page=100&page=1",
"GET /search/issues?q=repo:nexu-io/open-design+is:issue",
"GET /search/issues?q=repo:nexu-io/open-design+is:pr"
],
"fetchedAt": "2026-05-06T09:30:00Z"
}
],
"fields": [
{
"path": "repository.fullName",
"source": "GET /repos/nexu-io/open-design",
"field": "full_name"
},
{
"path": "metrics.stars.total",
"source": "GET /repos/nexu-io/open-design",
"field": "stargazers_count"
},
{
"path": "metrics.forks.total",
"source": "GET /repos/nexu-io/open-design",
"field": "forks_count"
},
{
"path": "metrics.contributors.total",
"source": "GET /repos/nexu-io/open-design/contributors?per_page=100&page=N",
"field": "paginated unique contributor count",
"note": "Display value may be capped or labelled as an estimate when only page 1 is available."
},
{
"path": "metrics.issues.total",
"source": "GET /search/issues?q=repo:nexu-io/open-design+is:issue",
"field": "total_count"
},
{
"path": "metrics.pullRequests.total",
"source": "GET /search/issues?q=repo:nexu-io/open-design+is:pr",
"field": "total_count"
},
{
"path": "charts.starGrowth",
"source": "estimated",
"note": "GitHub REST does not expose full historical star deltas; heights are display-normalized from available recent growth signals."
},
{
"path": "charts.forkTrend",
"source": "synthetic",
"note": "Generated as normalized 0-100% chart heights for visual trend preview."
}
],
"transformations": [
{
"step": "Data normalization",
"description": "Converted GitHub API responses to compact dashboard format",
"operations": [
"Formatted large numbers with comma separators",
"Estimated star and fork growth trends and marked them as non-auditable estimates",
"Extracted top 5 contributors by contribution count",
"Selected most recent 5 issues and pull requests",
"Generated normalized chart-height values for star growth and fork trends"
]
},
{
"step": "Privacy filtering",
"description": "Applied safe data practices",
"operations": [
"Preserved only public GitHub profile information",
"Used public avatar URLs",
"Excluded sensitive or internal repository metadata"
]
}
],
"notes": [
"Current repository totals are sourced from public GitHub API endpoints; growth series are explicitly estimated or synthetic as documented in fields[].",
"No authentication tokens or credentials stored",
"Star growth is estimated from available recent growth signals, not directly auditable from GitHub REST alone",
"Fork growth is synthetic for preview purposes",
"Chart heights are normalized percentages for responsive display"
],
"refreshPolicy": {
"recommended": "hourly",
"minInterval": "15 minutes",
"note": "GitHub API has rate limits; recommend caching for production use"
}
}
+473
View File
@@ -0,0 +1,473 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{{data.repository.name}} — GitHub 仪表盘</title>
<style>
:root {
--canvas: #f2f2f0;
--surface: #ffffff;
--surface-muted: #fafaf9;
--border: #ececea;
--border-strong: #e2e2df;
--text-primary: #0a0a0a;
--text-secondary: #6b6b6b;
--text-tertiary: #9a9a95;
--active-bg: #e6f4ea;
--active-fg: #1f8a4c;
--pending-bg: #fff6d6;
--pending-fg: #9a7b12;
--feature-bg: #dcebff;
--feature-fg: #2f66c9;
--danger-bg: #fdecec;
--danger-fg: #c0392b;
--green: #34a853;
--amber: #e8a23a;
--red: #d94a3d;
--shadow: 0 1px 2px rgba(10, 10, 10, .04), 0 1px 1px rgba(10, 10, 10, .02);
--radius-card: 16px;
--radius-tile: 12px;
--radius-control: 8px;
font-family: Geist, Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-feature-settings: "tnum", "lnum";
}
* { box-sizing: border-box; }
body { margin: 0; background: var(--canvas); color: var(--text-primary); }
.shell { min-height: 100vh; padding: 16px; display: grid; grid-template-columns: 256px 1fr; gap: 16px; }
.sidebar, .main { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-card); box-shadow: var(--shadow); }
.sidebar { padding: 16px; display: flex; flex-direction: column; gap: 22px; }
.brand { height: 48px; display: flex; align-items: center; gap: 10px; font-weight: 600; font-size: 15px; }
.logo { width: 32px; height: 32px; border-radius: 8px; background: linear-gradient(135deg, #2f66c9, #5a8ded); color: white; display: grid; place-items: center; font-size: 18px; font-weight: 600; }
.group-label { display: flex; align-items: center; gap: 8px; color: var(--text-tertiary); font-size: 11px; font-weight: 500; letter-spacing: .02em; text-transform: uppercase; margin-bottom: 8px; margin-top: 4px; }
.dot-ring { width: 14px; height: 14px; border: 1.5px dashed var(--text-tertiary); border-radius: 999px; flex: none; }
.nav { display: grid; gap: 4px; }
.nav-item { min-height: 36px; display: flex; align-items: center; justify-content: space-between; gap: 10px; border-radius: var(--radius-control); padding: 8px 10px; color: var(--text-secondary); font-size: 13px; text-decoration: none; transition: all .15s; }
.nav-item:hover { background: var(--surface-muted); }
.nav-item.active { background: var(--surface-muted); color: var(--text-primary); font-weight: 500; }
.count { border-radius: 999px; padding: 2px 8px; background: var(--surface-muted); color: var(--text-secondary); font-size: 11px; font-weight: 500; }
.main { overflow: hidden; }
.topbar { height: 48px; border-bottom: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; padding: 0 20px; font-size: 14px; }
.topbar-title { display: flex; align-items: center; gap: 10px; }
.topbar-icon { width: 20px; height: 20px; opacity: .7; }
.content { padding: 24px 28px 32px; display: grid; gap: 24px; }
.page-head { display: flex; align-items: end; justify-content: space-between; gap: 16px; }
h1 { margin: 0; font-size: 22px; line-height: 1.25; font-weight: 600; letter-spacing: -.005em; }
.subtitle { margin-top: 6px; color: var(--text-secondary); font-size: 14px; line-height: 1.4; }
.actions { display: flex; gap: 8px; align-items: center; }
button, .button { border: 1px solid var(--border-strong); background: var(--surface); border-radius: var(--radius-control); padding: 8px 14px; color: var(--text-primary); font: inherit; font-size: 12px; cursor: pointer; transition: all .15s; text-decoration: none; display: inline-flex; align-items: center; justify-content: center; }
button:hover, .button:hover { background: var(--surface-muted); }
button.primary, .button.primary { background: var(--text-primary); color: #fff; border-color: var(--text-primary); }
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-card); box-shadow: var(--shadow); padding: 20px; }
.tabs { display: inline-flex; background: var(--surface-muted); border-radius: 12px; padding: 4px; gap: 4px; }
.tab { padding: 6px 12px; border-radius: var(--radius-control); color: var(--text-secondary); font-size: 12px; cursor: pointer; transition: all .15s; border: 1px solid transparent; text-decoration: none; }
.tab.active { background: var(--surface); color: var(--text-primary); border: 1px solid var(--border); box-shadow: var(--shadow); }
.kpis { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 16px; }
.kpi { min-height: 84px; border: 1px solid var(--border); border-radius: var(--radius-tile); background: var(--surface-muted); padding: 14px; display: flex; flex-direction: column; }
.kpi-top { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.glyph { width: 28px; height: 28px; border-radius: 8px; background: var(--surface); border: 1px solid var(--border); display: inline-grid; place-items: center; box-shadow: var(--shadow); font-size: 14px; flex: none; }
.kpi-label { color: var(--text-secondary); font-size: 13px; }
.kpi-num { font-size: 28px; font-weight: 600; line-height: 1.1; margin-top: auto; }
.kpi-trend { font-size: 12px; color: var(--green); margin-top: 4px; font-weight: 500; }
.kpi-trend.down { color: var(--text-tertiary); }
.grid { display: grid; grid-template-columns: 2fr 1fr; gap: 16px; }
.grid-full { display: grid; grid-template-columns: 1fr; gap: 16px; }
.card-title { display: flex; align-items: center; gap: 8px; font-size: 16px; font-weight: 600; margin-bottom: 16px; }
.tick-rule { height: 24px; margin: 8px 0 16px; background: repeating-linear-gradient(90deg, var(--border) 0 1px, transparent 1px 8px); }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
.table-scroll { overflow-x: auto; }
.table-scroll table { min-width: 760px; }
th { text-align: left; padding: 10px 12px; color: var(--text-tertiary); font-size: 11px; font-weight: 500; letter-spacing: .01em; background: var(--surface-muted); text-transform: uppercase; }
td { padding: 14px 12px; border-top: 1px solid var(--border); color: var(--text-secondary); }
td strong { color: var(--text-primary); font-weight: 500; }
.mono { font-family: "Geist Mono", "JetBrains Mono", ui-monospace, monospace; font-size: 12px; }
.pill { display: inline-flex; align-items: center; gap: 6px; border-radius: 999px; padding: 3px 10px; font-size: 11px; font-weight: 500; }
.pill::before { content: ""; width: 6px; height: 6px; border-radius: 999px; background: currentColor; }
.active-pill { background: var(--active-bg); color: var(--active-fg); }
.pending-pill { background: var(--pending-bg); color: var(--pending-fg); }
.feature-pill { background: var(--feature-bg); color: var(--feature-fg); }
.danger-pill { background: var(--danger-bg); color: var(--danger-fg); }
.avatar { width: 28px; height: 28px; border-radius: 999px; border: 1px solid var(--border); background: linear-gradient(135deg, #dcecff, #f8eadb); display: inline-grid; place-items: center; color: var(--text-secondary); font-size: 11px; font-weight: 500; margin-right: 8px; overflow: hidden; flex: none; }
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.contrib { display: grid; gap: 10px; }
.person { display: flex; align-items: center; justify-content: space-between; gap: 10px; border: 1px solid var(--border); border-radius: 12px; padding: 12px; background: var(--surface-muted); }
.person-info { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; }
.person-name { font-weight: 500; font-size: 13px; color: var(--text-primary); }
.person-role { font-size: 12px; color: var(--text-secondary); margin-top: 2px; }
.chart-container { position: relative; height: 180px; margin-top: 16px; }
.chart { width: 100%; height: 100%; }
.chart-bars { display: flex; align-items: flex-end; justify-content: space-between; height: 100%; gap: 8px; }
.bar { flex: 1; background: linear-gradient(180deg, var(--green) 0%, #2d8a47 100%); border-radius: 4px 4px 0 0; min-height: 4px; position: relative; transition: all .2s; }
.bar:hover { opacity: .85; }
.bar-label { position: absolute; bottom: -22px; left: 50%; transform: translateX(-50%); font-size: 11px; color: var(--text-tertiary); white-space: nowrap; }
.trend-line { display: flex; align-items: flex-end; height: 100%; gap: 2px; }
.trend-point { flex: 1; background: var(--feature-fg); border-radius: 2px 2px 0 0; min-height: 2px; }
.issue-row { display: flex; align-items: start; gap: 12px; padding: 14px 12px; border-top: 1px solid var(--border); }
.issue-row:first-child { border-top: none; }
.issue-icon { width: 20px; height: 20px; border-radius: 999px; background: var(--active-bg); color: var(--active-fg); display: grid; place-items: center; font-size: 11px; flex: none; margin-top: 2px; }
.issue-icon.pr { background: var(--feature-bg); color: var(--feature-fg); }
.issue-content { flex: 1; min-width: 0; }
.issue-title { font-size: 14px; font-weight: 500; color: var(--text-primary); margin-bottom: 4px; }
.issue-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 12px; color: var(--text-tertiary); margin-top: 6px; }
.issue-meta span { display: flex; align-items: center; gap: 4px; }
.provenance-note { color: var(--text-tertiary); font-size: 12px; line-height: 1.5; padding: 4px 2px; }
@media (max-width: 980px) {
.shell { grid-template-columns: 1fr; }
.kpis { grid-template-columns: repeat(2, 1fr); }
.grid { grid-template-columns: 1fr; }
.sidebar { min-height: auto; }
}
</style>
</head>
<body>
<div class="shell">
<aside class="sidebar" data-od-id="sidebar">
<div class="brand">
<div class="logo">OD</div>
<span>{{data.repository.name}}</span>
</div>
<section>
<div class="group-label"><span class="dot-ring"></span> 仓库</div>
<div class="nav">
<a href="#overview" class="nav-item active">概览</a>
<a href="#activity" class="nav-item">活动 <span class="count">{{data.metrics.pullRequests.open}}</span></a>
<a href="#contributors" class="nav-item">贡献者 <span class="count">{{data.metrics.contributors.total}}</span></a>
<a href="#community" class="nav-item">社区</a>
</div>
</section>
<section>
<div class="group-label"><span class="dot-ring"></span> 指标</div>
<div class="nav">
<a href="#growth-chart" class="nav-item">Star 增长</a>
<a href="#fork-trend" class="nav-item">Fork 活动</a>
<a href="#activity" class="nav-item">Issue 趋势</a>
<a href="#activity" class="nav-item">PR 速度</a>
</div>
</section>
<section>
<div class="group-label"><span class="dot-ring"></span> 快速链接</div>
<div class="nav">
<a href="{{data.repository.url}}" class="nav-item">GitHub 仓库</a>
<a href="{{data.repository.url}}#readme" class="nav-item">文档</a>
<a href="{{data.repository.url}}/discussions" class="nav-item">讨论</a>
</div>
</section>
</aside>
<main class="main">
<div class="topbar" data-od-id="topbar">
<div class="topbar-title">
<svg class="topbar-icon" fill="currentColor" viewBox="0 0 16 16">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/>
</svg>
<span>{{data.repository.name}} 仪表盘</span>
</div>
<div class="actions">
<button>{{data.metadata.lastUpdated}}</button>
<button>⟳ 刷新</button>
</div>
</div>
<div class="content">
<header class="page-head" data-od-id="repo-header" id="overview">
<div>
<h1>{{data.repository.fullName}}</h1>
<div class="subtitle">{{data.repository.description}}</div>
</div>
<div class="actions">
<a class="button" href="{{data.repository.url}}">在 GitHub 上查看 →</a>
</div>
</header>
<section class="card">
<div class="tabs" role="tablist" aria-label="仪表盘分区">
<a href="#overview" class="tab active" role="tab">指标</a>
<a href="#activity" class="tab" role="tab">活动</a>
<a href="#contributors" class="tab" role="tab">贡献者</a>
<a href="#community" class="tab" role="tab">社区</a>
</div>
<div class="kpis" style="margin-top:16px" data-od-id="kpi-strip">
<div class="kpi">
<div class="kpi-top">
<span class="glyph"></span>
<span class="kpi-label">Stars</span>
</div>
<div class="kpi-num">{{data.metrics.stars.total}}</div>
<div class="kpi-trend">本周 +{{data.metrics.stars.growth}}</div>
</div>
<div class="kpi">
<div class="kpi-top">
<span class="glyph"></span>
<span class="kpi-label">Forks</span>
</div>
<div class="kpi-num">{{data.metrics.forks.total}}</div>
<div class="kpi-trend">本周 +{{data.metrics.forks.growth}}</div>
</div>
<div class="kpi">
<div class="kpi-top">
<span class="glyph"></span>
<span class="kpi-label">贡献者</span>
</div>
<div class="kpi-num">{{data.metrics.contributors.total}}</div>
<div class="kpi-trend">{{data.metrics.contributors.active}} 活跃</div>
</div>
<div class="kpi">
<div class="kpi-top">
<span class="glyph"></span>
<span class="kpi-label">开放的 Issue</span>
</div>
<div class="kpi-num">{{data.metrics.issues.open}}</div>
<div class="kpi-trend down">共 {{data.metrics.issues.total}} 个</div>
</div>
<div class="kpi">
<div class="kpi-top">
<span class="glyph"></span>
<span class="kpi-label">Pull Request</span>
</div>
<div class="kpi-num">{{data.metrics.pullRequests.open}}</div>
<div class="kpi-trend down">共 {{data.metrics.pullRequests.total}} 个</div>
</div>
</div>
</section>
<section class="grid">
<div class="card" data-od-id="growth-chart" id="growth-chart">
<div class="card-title"><span class="dot-ring"></span> Star 增长(近 30 天)</div>
<div class="chart-container">
<div class="chart-bars">
<div class="bar" style="height: {{data.charts.starGrowth.0.height}}%;">
<span class="bar-label">{{data.charts.starGrowth.0.label}}</span>
</div>
<div class="bar" style="height: {{data.charts.starGrowth.1.height}}%;">
<span class="bar-label">{{data.charts.starGrowth.1.label}}</span>
</div>
<div class="bar" style="height: {{data.charts.starGrowth.2.height}}%;">
<span class="bar-label">{{data.charts.starGrowth.2.label}}</span>
</div>
<div class="bar" style="height: {{data.charts.starGrowth.3.height}}%;">
<span class="bar-label">{{data.charts.starGrowth.3.label}}</span>
</div>
</div>
</div>
</div>
<aside class="card" data-od-id="contributors" id="contributors">
<div class="card-title"><span class="dot-ring"></span> 顶尖贡献者</div>
<div class="tick-rule"></div>
<div class="contrib">
<div class="person">
<div class="person-info">
<div class="avatar">
<img src="{{data.contributors.0.avatar}}" alt="{{data.contributors.0.login}}" />
</div>
<div>
<div class="person-name">{{data.contributors.0.login}}</div>
<div class="person-role">{{data.contributors.0.contributions}} 次贡献</div>
</div>
</div>
<span class="pill pending-pill">{{data.contributors.0.contributions}}</span>
</div>
<div class="person">
<div class="person-info">
<div class="avatar">
<img src="{{data.contributors.1.avatar}}" alt="{{data.contributors.1.login}}" />
</div>
<div>
<div class="person-name">{{data.contributors.1.login}}</div>
<div class="person-role">{{data.contributors.1.contributions}} 次贡献</div>
</div>
</div>
<span class="pill pending-pill">{{data.contributors.1.contributions}}</span>
</div>
<div class="person">
<div class="person-info">
<div class="avatar">
<img src="{{data.contributors.2.avatar}}" alt="{{data.contributors.2.login}}" />
</div>
<div>
<div class="person-name">{{data.contributors.2.login}}</div>
<div class="person-role">{{data.contributors.2.contributions}} 次贡献</div>
</div>
</div>
<span class="pill pending-pill">{{data.contributors.2.contributions}}</span>
</div>
<div class="person">
<div class="person-info">
<div class="avatar">
<img src="{{data.contributors.3.avatar}}" alt="{{data.contributors.3.login}}" />
</div>
<div>
<div class="person-name">{{data.contributors.3.login}}</div>
<div class="person-role">{{data.contributors.3.contributions}} 次贡献</div>
</div>
</div>
<span class="pill pending-pill">{{data.contributors.3.contributions}}</span>
</div>
<div class="person">
<div class="person-info">
<div class="avatar">
<img src="{{data.contributors.4.avatar}}" alt="{{data.contributors.4.login}}" />
</div>
<div>
<div class="person-name">{{data.contributors.4.login}}</div>
<div class="person-role">{{data.contributors.4.contributions}} 次贡献</div>
</div>
</div>
<span class="pill pending-pill">{{data.contributors.4.contributions}}</span>
</div>
</div>
</aside>
</section>
<section class="grid-full">
<div class="card" data-od-id="activity" id="activity">
<div class="card-title"><span class="dot-ring"></span> 近期活动</div>
<div class="table-scroll">
<table>
<thead>
<tr>
<th style="width: 50px;">类型</th>
<th>标题</th>
<th style="width: 120px;">状态</th>
<th style="width: 140px;">作者</th>
<th style="width: 100px;">更新于</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<span class="issue-icon {{data.recentActivity.0.typeClass}}">{{data.recentActivity.0.typeText}}</span>
</td>
<td><strong>{{data.recentActivity.0.title}}</strong></td>
<td>
<span class="pill {{data.recentActivity.0.labelClass}}">{{data.recentActivity.0.label}}</span>
</td>
<td>
<div style="display: flex; align-items: center;">
<span class="avatar" style="margin-right: 8px;">
<img src="{{data.recentActivity.0.authorAvatar}}" alt="{{data.recentActivity.0.author}}" />
</span>
<span>{{data.recentActivity.0.author}}</span>
</div>
</td>
<td class="mono" style="color: var(--text-tertiary);">{{data.recentActivity.0.updated}}</td>
</tr>
<tr>
<td><span class="issue-icon {{data.recentActivity.1.typeClass}}">{{data.recentActivity.1.typeText}}</span></td>
<td><strong>{{data.recentActivity.1.title}}</strong></td>
<td><span class="pill {{data.recentActivity.1.labelClass}}">{{data.recentActivity.1.label}}</span></td>
<td>
<div style="display: flex; align-items: center;">
<span class="avatar" style="margin-right: 8px;"><img src="{{data.recentActivity.1.authorAvatar}}" alt="{{data.recentActivity.1.author}}" /></span>
<span>{{data.recentActivity.1.author}}</span>
</div>
</td>
<td class="mono" style="color: var(--text-tertiary);">{{data.recentActivity.1.updated}}</td>
</tr>
<tr>
<td><span class="issue-icon {{data.recentActivity.2.typeClass}}">{{data.recentActivity.2.typeText}}</span></td>
<td><strong>{{data.recentActivity.2.title}}</strong></td>
<td><span class="pill {{data.recentActivity.2.labelClass}}">{{data.recentActivity.2.label}}</span></td>
<td>
<div style="display: flex; align-items: center;">
<span class="avatar" style="margin-right: 8px;"><img src="{{data.recentActivity.2.authorAvatar}}" alt="{{data.recentActivity.2.author}}" /></span>
<span>{{data.recentActivity.2.author}}</span>
</div>
</td>
<td class="mono" style="color: var(--text-tertiary);">{{data.recentActivity.2.updated}}</td>
</tr>
<tr>
<td><span class="issue-icon {{data.recentActivity.3.typeClass}}">{{data.recentActivity.3.typeText}}</span></td>
<td><strong>{{data.recentActivity.3.title}}</strong></td>
<td><span class="pill {{data.recentActivity.3.labelClass}}">{{data.recentActivity.3.label}}</span></td>
<td>
<div style="display: flex; align-items: center;">
<span class="avatar" style="margin-right: 8px;"><img src="{{data.recentActivity.3.authorAvatar}}" alt="{{data.recentActivity.3.author}}" /></span>
<span>{{data.recentActivity.3.author}}</span>
</div>
</td>
<td class="mono" style="color: var(--text-tertiary);">{{data.recentActivity.3.updated}}</td>
</tr>
<tr>
<td><span class="issue-icon {{data.recentActivity.4.typeClass}}">{{data.recentActivity.4.typeText}}</span></td>
<td><strong>{{data.recentActivity.4.title}}</strong></td>
<td><span class="pill {{data.recentActivity.4.labelClass}}">{{data.recentActivity.4.label}}</span></td>
<td>
<div style="display: flex; align-items: center;">
<span class="avatar" style="margin-right: 8px;"><img src="{{data.recentActivity.4.authorAvatar}}" alt="{{data.recentActivity.4.author}}" /></span>
<span>{{data.recentActivity.4.author}}</span>
</div>
</td>
<td class="mono" style="color: var(--text-tertiary);">{{data.recentActivity.4.updated}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section class="grid">
<div class="card" id="fork-trend">
<div class="card-title"><span class="dot-ring"></span> Fork 趋势(近 30 天)</div>
<div class="chart-container">
<div class="trend-line">
<div class="trend-point" style="height: {{data.charts.forkTrend.0.height}}%;"></div>
<div class="trend-point" style="height: {{data.charts.forkTrend.1.height}}%;"></div>
<div class="trend-point" style="height: {{data.charts.forkTrend.2.height}}%;"></div>
<div class="trend-point" style="height: {{data.charts.forkTrend.3.height}}%;"></div>
<div class="trend-point" style="height: {{data.charts.forkTrend.4.height}}%;"></div>
<div class="trend-point" style="height: {{data.charts.forkTrend.5.height}}%;"></div>
<div class="trend-point" style="height: {{data.charts.forkTrend.6.height}}%;"></div>
<div class="trend-point" style="height: {{data.charts.forkTrend.7.height}}%;"></div>
<div class="trend-point" style="height: {{data.charts.forkTrend.8.height}}%;"></div>
<div class="trend-point" style="height: {{data.charts.forkTrend.9.height}}%;"></div>
<div class="trend-point" style="height: {{data.charts.forkTrend.10.height}}%;"></div>
</div>
</div>
</div>
<div class="card">
<div class="card-title"><span class="dot-ring"></span> 仓库统计</div>
<div class="tick-rule"></div>
<table>
<tbody>
<tr>
<td><strong>主要语言</strong></td>
<td style="text-align: right;">{{data.repository.language}}</td>
</tr>
<tr>
<td><strong>许可证</strong></td>
<td style="text-align: right;">{{data.repository.license}}</td>
</tr>
<tr>
<td><strong>创建时间</strong></td>
<td style="text-align: right;">{{data.repository.created}}</td>
</tr>
<tr>
<td><strong>最后更新</strong></td>
<td style="text-align: right;">{{data.repository.lastUpdated}}</td>
</tr>
<tr>
<td><strong>仓库大小</strong></td>
<td style="text-align: right;">{{data.repository.size}}</td>
</tr>
</tbody>
</table>
</div>
</section>
<footer class="provenance-note" data-od-id="provenance">
更新于 {{data.metadata.lastUpdated}},数据来自公开的 GitHub API 字段。估算的趋势数据记录在 provenance.json 中。
</footer>
</div>
</main>
</div>
</body>
</html>