<!DOCTYPE html> <html> <head> <title>Houbb's Projects</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- 引入Font Awesome图标库 --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <style> :root { --primary-color: #2188ff; --card-bg: #f6f8fa; } .project-container { max-width: 1200px; margin: 0 auto; padding: 2rem; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; } .project-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 1.5rem; padding: 0; } .project-card { padding: 1.5rem; background: var(--card-bg); border: 1px solid #e1e4e8; border-radius: 8px; transition: transform 0.2s ease; display: flex; flex-direction: column; } .project-card:hover { transform: translateY(-5px); box-shadow: 0 4px 12px rgba(0,0,0,0.1); } .card-header { display: flex; align-items: center; margin-bottom: 1rem; } .project-icon { font-size: 1.8rem; margin-right: 1rem; color: var(--primary-color); } .project-title { color: #0366d6; font-size: 1.2rem; font-weight: 600; text-decoration: none; } .project-desc { color: #586069; line-height: 1.5; flex-grow: 1; } .project-meta { margin-top: 1rem; padding-top: 0.8rem; border-top: 1px solid #eee; display: flex; justify-content: space-between; font-size: 0.9em; color: #6a737d; } h2 { color: #2f363d; border-bottom: 2px solid var(--primary-color); padding-bottom: 0.3em; margin: 2em 0 1.5em; } .error { color: #dc3545; padding: 1rem; border: 1px solid #f8d7da; border-radius: 4px; background: #f8d7da; } </style> </head> <body> <div class="project-container"> <h1>开源项目</h1> <h2>核心项目</h2> <div class="project-grid" id="core-projects"></div> <h2>其他项目</h2> <div class="project-grid" id="incubating-projects"></div> </div> <script> // 图标匹配规则 const ICON_MAP = { // 根据仓库名称关键词匹配图标 'validator': 'fa-shield-halved', 'check': 'fa-check-double', 'ml': 'fa-robot', 'ai': 'fa-brain', 'csv': 'fa-table', 'core': 'fa-cube', 'cache': 'fa-database', 'json': 'fa-file-code', 'sync': 'fa-rotate', 'async': 'fa-bolt', 'common': 'fa-layer-group', 'rate': 'fa-chart-line', 'leetcode': 'fa-code', 'test': 'fa-flask', 'doc': 'fa-book', 'admin': 'fa-terminal', 'db': 'fa-database', 'default': 'fa-box-open' }; // 获取图标类名 function getProjectIcon(repoName) { const key = Object.keys(ICON_MAP).find(k => repoName.toLowerCase().includes(k)); return ICON_MAP[key] || ICON_MAP.default; } // 渲染项目卡片 function renderProject(repo) { return ` <div class="project-card"> <div class="card-header"> <i class="fas ${getProjectIcon(repo.name)} project-icon"></i> <a href="${repo.html_url}" class="project-title" target="_blank"> ${repo.name} </a> </div> <p class="project-desc">${repo.description || 'No description provided'}</p> <div class="project-meta"> <span title="Stars">⭐ ${repo.stargazers_count}</span> <span title="Forks">⑂ ${repo.forks_count}</span> <span>Updated: ${new Date(repo.updated_at).toLocaleDateString()}</span> </div> </div> `; } // GitHub API请求 // 通用数据处理函数 function processRepositories(repos) { const coreProjects = document.getElementById('core-projects'); const incubatingProjects = document.getElementById('incubating-projects'); // 清空现有内容 coreProjects.innerHTML = ''; incubatingProjects.innerHTML = ''; repos.filter(repo => !repo.fork).forEach(repo => { const card = renderProject(repo); (repo.stargazers_count > 30 ? coreProjects : incubatingProjects) .insertAdjacentHTML('beforeend', card); }); } // 增强版数据加载函数 function loadRepositoryData() { // 优先尝试GitHub API fetch('https://api.github.com/users/houbb/repos?sort=updated&per_page=100') .then(response => { if (!response.ok) { throw new Error(`GitHub API请求失败 (HTTP ${response.status})`); } return response.json(); }) .then(repos => { processRepositories(repos); // 可选:保存最新数据到本地备用 localStorage.setItem('cachedRepos', JSON.stringify(repos)); }) .catch(error => { console.warn('主数据源加载失败:', error); // 尝试读取本地备用文件 fetch('./opensource-default.json') .then(response => { if (!response.ok) { throw new Error('备用文件加载失败'); } return response.json(); }) .then(localRepos => { processRepositories(localRepos); console.info('已使用本地备用数据'); }) .catch(localError => { console.error('备用数据加载失败:', localError); // 尝试读取本地缓存 const cached = localStorage.getItem('cachedRepos'); if (cached) { processRepositories(JSON.parse(cached)); console.info('已使用本地缓存数据'); } else { // 最终错误处理 document.getElementById('core-projects').innerHTML = '<p class="error">数据加载失败,请检查网络连接</p>'; } }); }); } // 初始化加载 loadRepositoryData(); </script> </body> </html>