This commit is contained in:
Ubuntu
2026-07-03 16:58:28 +08:00
commit 32b43f85bd
6240 changed files with 1987678 additions and 0 deletions
+770
View File
@@ -0,0 +1,770 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>玩Android - 体系</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Roboto', 'Noto Sans SC', sans-serif; background: #F5F5F5; }
/* 容器 */
.container { max-width: 750px; margin: 0 auto; background: white; min-height: 100vh; }
/* 状态栏 */
.status-bar { height: 40px; background: #6200EE; }
/* 顶部导航 */
.top-nav { background: #6200EE; padding: 12px 16px; display: flex; align-items: center; justify-content: space-between; color: white; }
.nav-title { font-size: 20px; font-weight: 500; }
.nav-actions { display: flex; gap: 16px; }
.nav-icon { font-size: 24px; cursor: pointer; }
/* 搜索栏 */
.search-bar { background: #6200EE; padding: 12px 16px; }
.search-container { background: rgba(255,255,255,0.9); border-radius: 24px; padding: 12px 16px; display: flex; align-items: center; }
.search-icon { font-size: 20px; margin-right: 12px; color: #6200EE; }
.search-input { font-size: 16px; color: #212121; flex: 1; border: none; outline: none; background: transparent; }
.search-input::placeholder { color: #757575; }
/* 双栏布局 */
.tree-layout { display: flex; height: calc(100vh - 160px); overflow: hidden; }
/* 左侧分类树 */
.tree-sidebar { width: 320rpx; background: white; border-right: 1px solid #EEEEEE; overflow-y: auto; }
/* 分类列表 */
.category-list { padding: 16px; }
.category-item { margin-bottom: 8px; border-radius: 12px; overflow: hidden; transition: all 0.3s; }
.category-item.selected { background: #F0F9FF; border-left: 4px solid #6200EE; }
.category-header { display: flex; justify-content: space-between; align-items: center; padding: 16px; cursor: pointer; }
.category-header:hover { background: #F8F8F8; }
.category-info { display: flex; align-items: center; flex: 1; }
.category-icon { font-size: 20px; margin-right: 12px; color: #6200EE; }
.category-name { font-size: 16px; font-weight: 500; color: #212121; flex: 1; }
.category-count { font-size: 12px; color: #757575; margin-left: 8px; }
.category-actions { display: flex; align-items: center; gap: 12px; }
.expand-icon { font-size: 12px; color: #757575; padding: 4px; cursor: pointer; }
.selected-icon { font-size: 14px; color: #6200EE; font-weight: bold; }
/* 子分类列表 */
.subcategory-list { background: #FAFAFA; border-top: 1px solid #F0F0F0; padding: 0 16px; }
.subcategory-item { display: flex; justify-content: space-between; align-items: center; padding: 12px 0; border-bottom: 1px solid #F0F0F0; cursor: pointer; }
.subcategory-item:last-child { border-bottom: none; }
.subcategory-item:hover { background: #F5F5F5; }
.subcategory-item.selected { background: #F0F9FF; }
.subcategory-info { display: flex; align-items: center; flex: 1; }
.subcategory-icon { font-size: 16px; margin-right: 12px; color: #666; }
.subcategory-name { font-size: 14px; color: #666; flex: 1; }
/* 右侧内容区域 */
.tree-content { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
/* 当前分类信息 */
.current-category { padding: 20px; background: white; border-bottom: 1px solid #EEEEEE; }
.category-header { display: flex; align-items: center; margin-bottom: 12px; }
.category-title { font-size: 20px; font-weight: 500; color: #212121; flex: 1; }
.category-count { font-size: 14px; color: #757575; margin-left: 8px; }
.category-path { margin-bottom: 16px; }
.path-text { font-size: 14px; color: #666; background: #F8F8F8; padding: 6px 12px; border-radius: 6px; }
.category-actions { display: flex; gap: 12px; }
.action-item { display: flex; align-items: center; padding: 8px 16px; background: #F8F8F8; border-radius: 20px; cursor: pointer; transition: all 0.3s; }
.action-item:hover { background: #F0F0F0; }
.action-icon { font-size: 16px; margin-right: 6px; }
.action-text { font-size: 14px; color: #666; }
/* 文章滚动区域 */
.article-scroll { flex: 1; overflow-y: auto; }
/* 文章列表 */
.article-list { padding: 20px; }
/* 文章卡片 */
.article-card { background: white; border-radius: 16px; padding: 20px; margin-bottom: 16px; box-shadow: 0 2px 8px rgba(0,0,0,0.08); cursor: pointer; transition: all 0.3s; }
.article-card:hover { box-shadow: 0 4px 16px rgba(0,0,0,0.12); transform: translateY(-2px); }
.article-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 12px; }
.article-title { font-size: 18px; font-weight: 500; color: #212121; line-height: 1.4; flex: 1; }
.article-tags { display: flex; gap: 8px; margin-left: 12px; }
.tag { padding: 4px 8px; border-radius: 4px; font-size: 12px; font-weight: 500; }
.tag.fresh { background: #FF4444; color: white; }
.tag.top { background: #FF9900; color: white; }
.article-summary { font-size: 14px; color: #666; line-height: 1.5; margin-bottom: 16px; }
.article-meta { display: flex; flex-wrap: wrap; gap: 16px; margin-bottom: 16px; padding-bottom: 16px; border-bottom: 1px solid #F0F0F0; }
.meta-item { display: flex; align-items: center; font-size: 12px; color: #999; }
.meta-icon { margin-right: 4px; font-size: 12px; }
.article-actions { display: flex; justify-content: space-around; align-items: center; }
.action-item { display: flex; flex-direction: column; align-items: center; padding: 8px 16px; border-radius: 8px; cursor: pointer; }
.action-item:hover { background: #F8F8F8; }
.action-icon { font-size: 20px; margin-bottom: 4px; }
.action-icon.collected { color: #FF9900; }
.action-text { font-size: 12px; color: #666; }
.action-text.collected { color: #FF9900; }
/* 加载更多 */
.load-more { text-align: center; padding: 32px; }
.load-btn { background: #6200EE; color: white; border: none; padding: 12px 32px; border-radius: 24px; font-size: 16px; cursor: pointer; }
.load-btn:hover { background: #3700B3; }
/* 空状态 */
.empty-state { text-align: center; padding: 60px 20px; color: #757575; }
.empty-icon { font-size: 48px; margin-bottom: 16px; }
.empty-title { font-size: 18px; font-weight: 500; margin-bottom: 8px; color: #212121; }
.empty-desc { font-size: 14px; margin-bottom: 24px; }
.empty-action { background: #6200EE; color: white; border: none; padding: 10px 24px; border-radius: 20px; font-size: 14px; cursor: pointer; }
/* 底部导航 */
.tab-bar { position: fixed; bottom: 0; left: 0; right: 0; background: white; border-top: 1px solid #EEEEEE; display: flex; justify-content: space-around; padding: 12px 0; max-width: 750px; margin: 0 auto; z-index: 100; }
.tab-item { display: flex; flex-direction: column; align-items: center; padding: 8px 16px; border-radius: 12px; transition: all 0.3s; cursor: pointer; }
.tab-item.active { background: rgba(98, 0, 238, 0.08); }
.tab-icon { font-size: 24px; margin-bottom: 4px; }
.tab-text { font-size: 12px; }
.tab-item.active .tab-icon, .tab-item.active .tab-text { color: #6200EE; }
.tab-item:not(.active) .tab-icon, .tab-item:not(.active) .tab-text { color: #757575; }
/* 安全区域 */
.safe-area { height: 80px; }
/* 加载动画 */
.loading { text-align: center; padding: 40px; color: #757575; }
.loading-spinner { width: 40px; height: 40px; border: 4px solid #E0E0E0; border-top: 4px solid #6200EE; border-radius: 50%; animation: spin 1s linear infinite; margin: 0 auto 16px; }
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
/* 响应式设计 */
@media (max-width: 600px) {
.tree-layout { flex-direction: column; }
.tree-sidebar { width: 100%; height: 200px; border-right: none; border-bottom: 1px solid #EEEEEE; }
}
</style>
</head>
<body>
<div class="container">
<!-- 状态栏 -->
<div class="status-bar"></div>
<!-- 顶部导航 -->
<div class="top-nav">
<div class="nav-title">玩Android - 体系</div>
<div class="nav-actions">
<div class="nav-icon" onclick="showMenu()">⋮</div>
</div>
</div>
<!-- 搜索栏 -->
<div class="search-bar">
<div class="search-container">
<div class="search-icon">🔍</div>
<input type="text" class="search-input" placeholder="搜索体系分类..." id="searchInput" onkeypress="handleSearchKeypress(event)">
</div>
</div>
<!-- 双栏布局 -->
<div class="tree-layout">
<!-- 左侧分类树 -->
<div class="tree-sidebar">
<div class="category-list" id="categoryList">
<div class="loading" id="loadingCategories">
<div class="loading-spinner"></div>
<div>正在加载分类...</div>
</div>
</div>
</div>
<!-- 右侧内容区域 -->
<div class="tree-content">
<!-- 当前分类信息 -->
<div class="current-category" id="currentCategory" style="display: none;">
<div class="category-header">
<div class="category-title" id="categoryTitle">请选择分类</div>
<div class="category-count" id="categoryCount"></div>
</div>
<div class="category-path" id="categoryPath"></div>
<div class="category-actions">
<div class="action-item" onclick="refreshArticles()">
<div class="action-icon">🔄</div>
<div class="action-text">刷新</div>
</div>
<div class="action-item" onclick="shareCategory()">
<div class="action-icon">↗️</div>
<div class="action-text">分享</div>
</div>
<div class="action-item" onclick="collectCategory()" id="collectBtn">
<div class="action-icon">⭐</div>
<div class="action-text">收藏</div>
</div>
</div>
</div>
<!-- 文章滚动区域 -->
<div class="article-scroll" id="articleScroll">
<!-- 空状态 -->
<div class="empty-state" id="emptyState">
<div class="empty-icon">📚</div>
<div class="empty-title">请选择分类</div>
<div class="empty-desc">点击左侧分类查看对应文章</div>
</div>
<!-- 文章列表 -->
<div class="article-list" id="articleList" style="display: none;">
<!-- 文章卡片会通过JavaScript动态生成 -->
</div>
<!-- 加载更多 -->
<div class="load-more" id="loadMoreContainer" style="display: none;">
<button class="load-btn" onclick="loadMoreArticles()">加载更多</button>
</div>
</div>
</div>
</div>
<!-- 安全区域 -->
<div class="safe-area"></div>
<!-- 底部导航 -->
<div class="tab-bar">
<div class="tab-item" onclick="switchTab('home')">
<div class="tab-icon">🏠</div>
<div class="tab-text">首页</div>
</div>
<div class="tab-item" onclick="switchTab('project')">
<div class="tab-icon">📦</div>
<div class="tab-text">项目</div>
</div>
<div class="tab-item" onclick="switchTab('wechat')">
<div class="tab-icon">📱</div>
<div class="tab-text">公众号</div>
</div>
<div class="tab-item active" onclick="switchTab('system')">
<div class="tab-icon">🌳</div>
<div class="tab-text">体系</div>
</div>
<div class="tab-item" onclick="switchTab('profile')">
<div class="tab-icon">👤</div>
<div class="tab-text">我的</div>
</div>
</div>
</div>
<script>
// 当前选中的分类
let selectedCategory = null;
let currentPage = 0;
let isLoading = false;
let hasMore = true;
let categories = [];
// 初始化页面
document.addEventListener('DOMContentLoaded', function() {
console.log('玩Android体系页面已加载');
console.log('公网访问: http://129.211.173.87:3000/tree.html');
// 加载体系分类
loadCategories();
});
// 加载体系分类
async function loadCategories() {
try {
const response = await fetch('/api/tree/json');
const data = await response.json();
if (data.errorCode === 0 && data.data && data.data.length > 0) {
categories = data.data;
renderCategories(categories);
} else {
// 使用默认分类数据
renderDefaultCategories();
}
} catch (error) {
console.error('加载分类失败:', error);
renderDefaultCategories();
}
}
// 渲染分类树
function renderCategories(categories) {
const container = document.getElementById('categoryList');
container.innerHTML = '';
categories.forEach(category => {
const categoryItem = document.createElement('div');
categoryItem.className = 'category-item';
categoryItem.setAttribute('data-id', category.id);
// 计算子分类数量
const childCount = category.children ? category.children.length : 0;
categoryItem.innerHTML = `
<div class="category-header" onclick="selectCategory(${category.id})">
<div class="category-info">
<div class="category-icon">📚</div>
<div class="category-name">${category.name}</div>
${childCount > 0 ? `<div class="category-count">(${childCount})</div>` : ''}
</div>
<div class="category-actions">
${childCount > 0 ? `<div class="expand-icon" onclick="event.stopPropagation(); toggleCategory(${category.id})">▶</div>` : ''}
<div class="selected-icon" id="selectedIcon${category.id}" style="display: none;">✓</div>
</div>
</div>
<div class="subcategory-list" id="subcategory${category.id}" style="display: none;">
${category.children ? category.children.map(child => `
<div class="subcategory-item" onclick="selectSubcategory(${child.id}, ${category.id})">
<div class="subcategory-info">
<div class="subcategory-icon">📖</div>
<div class="subcategory-name">${child.name}</div>
</div>
<div class="selected-icon" id="selectedIcon${child.id}" style="display: none;">✓</div>
</div>
`).join('') : ''}
</div>
`;
container.appendChild(categoryItem);
});
}
// 渲染默认分类
function renderDefaultCategories() {
const defaultCategories = [
{
id: 1,
name: "开发环境",
children: [
{ id: 11, name: "Android Studio相关" },
{ id: 12, name: "gradle" },
{ id: 13, name: "官方发布" },
{ id: 14, name: "90-120hz" }
]
},
{
id: 2,
name: "基础知识",
children: [
{ id: 21, name: "Activity" },
{ id: 22, name: "Service" },
{ id: 23, name: "BroadcastReceiver" },
{ id: 24, name: "ContentProvider" }
]
},
{
id: 3,
name: "四大组件",
children: [
{ id: 31, name: "Activity详解" },
{ id: 32, name: "Service详解" },
{ id: 33, name: "Broadcast详解" },
{ id: 34, name: "ContentProvider详解" }
]
},
{
id: 4,
name: "常用控件",
children: [
{ id: 41, name: "TextView" },
{ id: 42, name: "Button" },
{ id: 43, name: "ImageView" },
{ id: 44, name: "RecyclerView" }
]
}
];
categories = defaultCategories;
renderCategories(defaultCategories);
}
// 选择分类
function selectCategory(categoryId) {
// 清除之前的选中状态
document.querySelectorAll('.category-item.selected').forEach(item => {
item.classList.remove('selected');
});
document.querySelectorAll('.subcategory-item.selected').forEach(item => {
item.classList.remove('selected');
});
document.querySelectorAll('.selected-icon').forEach(icon => {
icon.style.display = 'none';
});
// 设置新的选中状态
const categoryItem = document.querySelector(`.category-item[data-id="${categoryId}"]`);
if (categoryItem) {
categoryItem.classList.add('selected');
const selectedIcon = document.getElementById(`selectedIcon${categoryId}`);
if (selectedIcon) {
selectedIcon.style.display = 'block';
}
}
// 查找分类
const category = categories.find(c => c.id === categoryId);
if (category) {
selectedCategory = {
id: category.id,
name: category.name,
level: 1
};
// 更新当前分类信息
updateCurrentCategory();
// 加载文章
loadArticles(category.id);
}
}
// 选择子分类
function selectSubcategory(subcategoryId, parentCategoryId) {
// 清除之前的选中状态
document.querySelectorAll('.category-item.selected').forEach(item => {
item.classList.remove('selected');
});
document.querySelectorAll('.subcategory-item.selected').forEach(item => {
item.classList.remove('selected');
});
document.querySelectorAll('.selected-icon').forEach(icon => {
icon.style.display = 'none';
});
// 设置新的选中状态
const subcategoryItem = document.querySelector(`.subcategory-item[onclick*="${subcategoryId}"]`);
if (subcategoryItem) {
subcategoryItem.classList.add('selected');
const selectedIcon = document.getElementById(`selectedIcon${subcategoryId}`);
if (selectedIcon) {
selectedIcon.style.display = 'block';
}
}
// 查找父分类
const parentCategory = categories.find(c => c.id === parentCategoryId);
if (parentCategory) {
// 查找子分类
const subcategory = parentCategory.children.find(c => c.id === subcategoryId);
if (subcategory) {
selectedCategory = {
id: subcategory.id,
name: subcategory.name,
level: 2,
parentCategory: {
id: parentCategory.id,
name: parentCategory.name
}
};
// 更新当前分类信息
updateCurrentCategory();
// 加载文章
loadArticles(subcategory.id);
}
}
}
// 切换分类展开状态
function toggleCategory(categoryId) {
const subcategoryList = document.getElementById(`subcategory${categoryId}`);
const expandIcon = event.target;
if (subcategoryList.style.display === 'none') {
subcategoryList.style.display = 'block';
expandIcon.textContent = '▼';
} else {
subcategoryList.style.display = 'none';
expandIcon.textContent = '▶';
}
}
// 更新当前分类信息
function updateCurrentCategory() {
const currentCategoryDiv = document.getElementById('currentCategory');
const emptyState = document.getElementById('emptyState');
const articleList = document.getElementById('articleList');
if (selectedCategory) {
currentCategoryDiv.style.display = 'block';
emptyState.style.display = 'none';
articleList.style.display = 'block';
// 更新分类标题
document.getElementById('categoryTitle').textContent = selectedCategory.name;
// 更新分类路径
const categoryPath = document.getElementById('categoryPath');
if (selectedCategory.level === 2 && selectedCategory.parentCategory) {
categoryPath.innerHTML = `<div class="path-text">父分类: ${selectedCategory.parentCategory.name}</div>`;
} else {
categoryPath.innerHTML = '';
}
} else {
currentCategoryDiv.style.display = 'none';
emptyState.style.display = 'block';
articleList.style.display = 'none';
}
}
// 加载文章
async function loadArticles(categoryId, page = 0) {
if (isLoading) return;
isLoading = true;
try {
const response = await fetch(`/api/article/list/${page}/json?cid=${categoryId}`);
const data = await response.json();
if (data.errorCode === 0 && data.data && data.data.datas) {
renderArticles(data.data.datas);
hasMore = !data.data.over;
// 更新文章数量
const total = data.data.total || data.data.datas.length;
document.getElementById('categoryCount').textContent = `(${total}篇文章)`;
// 显示或隐藏加载更多按钮
const loadMoreContainer = document.getElementById('loadMoreContainer');
loadMoreContainer.style.display = hasMore ? 'block' : 'none';
} else {
// 使用默认文章数据
renderDefaultArticles();
}
} catch (error) {
console.error('加载文章失败:', error);
renderDefaultArticles();
} finally {
isLoading = false;
currentPage = page;
}
}
// 渲染文章列表
function renderArticles(articles) {
const container = document.getElementById('articleList');
// 如果是第一页,清空容器
if (currentPage === 0) {
container.innerHTML = '';
}
articles.forEach(article => {
const articleElement = document.createElement('div');
articleElement.className = 'article-card';
articleElement.onclick = () => showArticleDetail(article.id);
// 格式化时间
const publishTime = new Date(article.publishTime);
const timeAgo = getTimeAgo(publishTime);
articleElement.innerHTML = `
<div class="article-header">
<div class="article-title">${article.title || '无标题'}</div>
<div class="article-tags">
${article.fresh ? '<div class="tag fresh">新</div>' : ''}
${article.top ? '<div class="tag top">置顶</div>' : ''}
</div>
</div>
<div class="article-summary">${article.desc || '暂无描述'}</div>
<div class="article-meta">
<div class="meta-item">
<span class="meta-icon">👤</span>
<span>${article.author || '未知作者'}</span>
</div>
<div class="meta-item">
<span class="meta-icon">🏷️</span>
<span>${article.superChapterName || ''}${article.chapterName ? ' · ' + article.chapterName : ''}</span>
</div>
<div class="meta-item">
<span class="meta-icon">🕒</span>
<span>${timeAgo}</span>
</div>
</div>
<div class="article-actions">
<div class="action-item" onclick="event.stopPropagation(); likeArticle(${article.id})">
<div class="action-icon">❤️</div>
<div class="action-text">${article.zan || 0}</div>
</div>
<div class="action-item" onclick="event.stopPropagation(); collectArticle(${article.id})">
<div class="action-icon ${article.collect ? 'collected' : ''}">⭐</div>
<div class="action-text ${article.collect ? 'collected' : ''}">${article.collect ? '已收藏' : '收藏'}</div>
</div>
<div class="action-item" onclick="event.stopPropagation(); shareArticle(${article.id})">
<div class="action-icon">↗️</div>
<div class="action-text">分享</div>
</div>
</div>
`;
container.appendChild(articleElement);
});
}
// 渲染默认文章
function renderDefaultArticles() {
const defaultArticles = [
{
id: 101,
title: "Android Studio优化技巧",
author: "Android开发者",
publishTime: Date.now() - 3600000,
superChapterName: "开发环境",
chapterName: "Android Studio相关",
desc: "本文介绍Android Studio的各种优化技巧,包括内存优化、编译加速、插件推荐等,帮助提升开发效率。",
zan: 42,
collect: false,
fresh: true
},
{
id: 102,
title: "Gradle配置详解",
author: "Gradle专家",
publishTime: Date.now() - 7200000,
superChapterName: "开发环境",
chapterName: "gradle",
desc: "深入解析Gradle配置文件,包括依赖管理、构建变体、自定义任务等高级功能。",
zan: 28,
collect: true,
fresh: false
},
{
id: 103,
title: "最新Android官方发布说明",
author: "Google",
publishTime: Date.now() - 10800000,
superChapterName: "开发环境",
chapterName: "官方发布",
desc: "Android最新版本的发布说明,包括新特性、API变更、兼容性说明等重要信息。",
zan: 56,
collect: false,
fresh: false,
top: true
}
];
renderArticles(defaultArticles);
}
// 加载更多文章
function loadMoreArticles() {
if (!selectedCategory || isLoading || !hasMore) return;
currentPage++;
loadArticles(selectedCategory.id, currentPage);
}
// 刷新文章
function refreshArticles() {
if (!selectedCategory) return;
currentPage = 0;
const articleList = document.getElementById('articleList');
articleList.innerHTML = '<div class="loading"><div class="loading-spinner"></div><div>正在刷新文章...</div></div>';
loadArticles(selectedCategory.id, 0);
setTimeout(() => {
alert('文章刷新成功!');
}, 1000);
}
// 分享分类
function shareCategory() {
if (!selectedCategory) return;
const shareText = `分享体系分类: ${selectedCategory.name}\n来自玩Android客户端`;
alert(`已复制分享内容:\n\n${shareText}`);
// 模拟复制到剪贴板
navigator.clipboard.writeText(shareText).then(() => {
console.log('分享内容已复制');
});
}
// 收藏分类
function collectCategory() {
if (!selectedCategory) return;
const collectBtn = document.getElementById('collectBtn');
const isCollected = collectBtn.querySelector('.action-text').textContent === '已收藏';
if (isCollected) {
collectBtn.querySelector('.action-text').textContent = '收藏';
alert(`已取消收藏分类: ${selectedCategory.name}`);
} else {
collectBtn.querySelector('.action-text').textContent = '已收藏';
alert(`已收藏分类: ${selectedCategory.name}`);
}
}
// 显示文章详情
function showArticleDetail(articleId) {
alert(`查看文章详情: ${articleId}\n\n文章详情功能开发中...`);
}
// 处理搜索按键
function handleSearchKeypress(event) {
if (event.key === 'Enter') {
const query = document.getElementById('searchInput').value.trim();
if (query) {
alert(`搜索体系分类: ${query}\n\n搜索功能开发中...`);
}
}
}
// 点赞文章
function likeArticle(articleId) {
alert(`已点赞文章 ${articleId}!`);
}
// 收藏文章
function collectArticle(articleId) {
alert(`已收藏文章 ${articleId}!`);
}
// 分享文章
function shareArticle(articleId) {
alert(`分享文章 ${articleId}!`);
}
// 显示菜单
function showMenu() {
alert('菜单功能开发中...\n\n包括设置、关于、反馈等功能');
}
// 切换Tab
function switchTab(tab) {
switch(tab) {
case 'home':
window.location.href = '/index.html';
break;
case 'project':
window.location.href = '/projects_fixed.html';
break;
case 'wechat':
window.location.href = '/wechat.html';
break;
case 'system':
// 当前页面,不需要跳转
break;
case 'profile':
window.location.href = '/profile.html';
break;
}
}
// 获取相对时间
function getTimeAgo(date) {
const now = new Date();
const diff = now - date;
const minutes = Math.floor(diff / 60000);
const hours = Math.floor(diff / 3600000);
const days = Math.floor(diff / 86400000);
if (minutes < 1) return '刚刚';
if (minutes < 60) return `${minutes}分钟前`;
if (hours < 24) return `${hours}小时前`;
if (days < 30) return `${days}天前`;
return date.toLocaleDateString();
}
</script>
</body>
</html>