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
+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>