我的网站优化

This commit is contained in:
DelLevin-Home
2026-05-18 14:36:19 +08:00
parent 40278c5d84
commit 47396b88f0
21 changed files with 810 additions and 138 deletions

View File

@@ -19,6 +19,7 @@
const blogPostsClose = document.getElementById('blog-posts-close');
const blogPostsList = document.querySelector('.blog-posts-list');
const blogPostsFullBody = document.querySelector('#blog-posts-full-modal .guestbook-body');
const previewBody = blogPostsPreview ? blogPostsPreview.querySelector('.preview-body') : null;
// 初始化
function init() {
@@ -32,6 +33,20 @@
// 页面加载时自动加载数据(用于 Hover 预览)
loadBlogPosts(true);
// 监听预览面板滚动事件实现触底加载
if (previewBody) {
previewBody.addEventListener('scroll', handleScroll);
}
}
// 处理滚动事件
function handleScroll(e) {
const { scrollTop, scrollHeight, clientHeight } = e.target;
// 距离底部 50px 时触发加载
if (scrollHeight - scrollTop - clientHeight < 50) {
loadMoreBlogPosts();
}
}
// 打开完整弹窗
@@ -65,7 +80,7 @@
}
try {
const response = await fetch(`${BLOG_API_URL}?page=${currentPage}&pageSize=${PAGE_SIZE}&showContent=false&showDigest=excerpt&limit=30`, {
const response = await fetch(`${BLOG_API_URL}?page=${currentPage}&pageSize=${PAGE_SIZE}&showContent=false&showDigest=excerpt&limit=60`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
@@ -105,27 +120,35 @@
// 渲染文章列表
function renderPosts(posts, isReset = false, totalCount = 0) {
let html = '';
// 预览面板 HTML无底部分页按钮使用无限滚动
let previewHtml = '';
// 全屏弹窗 HTML保留底部分页按钮
let fullHtml = '';
if (!posts || posts.length === 0) {
html = '<div class="guestbook-empty">暂无文章</div>';
const emptyHtml = '<div class="guestbook-empty">暂无文章</div>';
previewHtml = emptyHtml;
fullHtml = emptyHtml;
} else {
html = '<div class="blog-posts-container">';
posts.forEach(post => {
html += renderPostItem(post);
});
html += '</div>';
// 只有在还有更多数据时才显示加载更多按钮
const containerHtml = '<div class="blog-posts-container">' +
posts.map(post => renderPostItem(post)).join('') +
'</div>';
previewHtml = containerHtml;
if (!hasMore) {
previewHtml += `<div class="load-complete">已显示全部</div>`;
}
fullHtml = containerHtml;
if (hasMore) {
html += `<button class="load-more-btn" onclick="window.loadMoreBlogPosts()">点击加载更多</button>`;
fullHtml += `<button class="load-more-btn" onclick="window.loadMoreBlogPosts()">点击加载更多</button>`;
} else {
html += `<div class="load-complete">已显示全部</div>`;
fullHtml += `<div class="load-complete">已显示全部</div>`;
}
}
if (blogPostsList) blogPostsList.innerHTML = html;
if (blogPostsFullBody) blogPostsFullBody.innerHTML = html;
if (blogPostsList) blogPostsList.innerHTML = previewHtml;
if (blogPostsFullBody) blogPostsFullBody.innerHTML = fullHtml;
// 更新预览面板标题显示总数
const previewHeader = document.querySelector('#blog-posts-preview .preview-header h3');
@@ -188,9 +211,13 @@
const date = new Date(post.created * 1000);
const dateStr = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
const category = post.categories && post.categories.length > 0 ? post.categories[0].name : '未分类';
const digest = post.digest || '';
let html = `<div class="blog-post-item" onclick="window.open('${post.permalink}', '_blank')">`;
html += `<div class="blog-post-title">${escapeHtml(post.title)}</div>`;
if (digest) {
html += `<div class="blog-post-digest">${escapeHtml(digest)}</div>`;
}
html += `<div class="blog-post-meta">`;
html += `<span>${dateStr}</span>`;
html += `<span class="blog-post-category">${escapeHtml(category)}</span>`;

View File

@@ -33,6 +33,8 @@ const translationsEN = {
social_link3: "Zhihu",
social_link4: "Bilibili",
social_link5: "52pojie",
social_link6: "XiaoHongShu",
// 留言
leave_message_h3: "Leave a Message",
leave_message_p:

View File

@@ -34,6 +34,8 @@ const translationsZH = {
social_link3: "知乎",
social_link4: "B站",
social_link5: "52pojie",
social_link6: "小红书",
// 留言
leave_message_h3: "留言",
leave_message_p:

View File

@@ -185,13 +185,6 @@
// 点击关闭按钮
lightbox.querySelector('.photo-lightbox-close').addEventListener('click', closePhotoLightbox);
// 点击背景关闭
lightbox.addEventListener('click', function(e) {
if (e.target === lightbox) {
closePhotoLightbox();
}
});
// 上一张按钮
lightbox.querySelector('.photo-lightbox-prev').addEventListener('click', function(e) {
e.stopPropagation();

View File

@@ -1,96 +1,53 @@
// ========== 网站链接数据 (包含中英双语) ==========
const websitesData = [
{
// 分类标题
category_zh: '个人博客',
category_en: 'Personal Blogs',
items: [
{
url: 'https://www.ittoolman.top/',
linkText_zh: 'ittoolman.top - Github托管',
linkText_en: 'ittoolman.top - Github Page'
},
{
url: 'https://blog.iletter.top/',
linkText_zh: 'blog.iletter.top - typecho用户的最后坚守',
linkText_en: 'blog.iletter.top - Last Stand for Typecho Users'
}
]
},
{
category_zh: '私人在线应用',
category_en: 'Personal Online Apps',
items: [
{
url: 'https://img.iletter.top/',
linkText_zh: 'EsayImage2 - 私人图床工具',
linkText_en: 'EsayImage2 - Image Uploader Tool'
},
{
url: 'https://gitea.iletter.top/',
linkText_zh: 'Gitea - 私人git托管仓库',
linkText_en: 'Gitea - Private Git Repository'
},
{
url: 'http://umami.iletter.top/',
linkText_zh: 'Umami - 网站访问分析',
linkText_en: 'Umami - Website visit analysis'
},
{
url: 'http://beszel.iletter.top/',
linkText_zh: 'Beszel - 服务器监控',
linkText_en: 'Beszel - Server Monitoring'
},
{
url: 'https://memos.iletter.top/',
linkText_zh: 'Memos - 个人随想',
linkText_en: 'Memos - Personal Thoughts'
},
{
url: 'http://frp.iletter.top/',
linkText_zh: 'FRP - 个人反向代理',
linkText_en: 'FRP - Personal Reverse Proxy'
},
{
url: 'https://bitwarden.iletter.top/',
linkText_zh: 'Bitwarden - 我的密码库',
linkText_en: 'Bitwarden - My Password Library'
},
{
url: 'http://docmost.iletter.top/',
linkText_zh: 'Docmost - 在线笔记',
linkText_en: 'Docmost - Online Notes'
},
{
url: 'http://openlist.iletter.top/',
linkText_zh: 'OpenList - 在线云盘合集',
linkText_en: 'OpenList - Online Cloud Disk Collection'
},
// {
// url: 'http://py.iletter.top/en-de-code',
// linkText_zh: 'Base64在线加密解密 - 自写demo',
// linkText_en: 'Base64 Online Encryption and Decryption - My Demo'
// },
]
}
// 如果你想添加新分类,可以仿照上面的格式:
/*
{
category_zh: '新的分类名',
category_en: 'New Category Name',
items: [
{
url: 'https://example.com/',
linkText_zh: '示例网站',
linkText_en: 'Example Site'
}
]
}
*/
{ category_zh: '我的作品', category_en: 'My Works', items: [
{ url: 'https://mooknote.iletter.top/#/',
linkText_zh: 'MookNote - 观影阅读笔记管理',
linkText_en: 'MookNote - Movie & Reading Note Manager',
desc_zh: '用于记录观影、阅读及笔记的个人知识管理应用。',
desc_en: 'Personal knowledge management app for movies, reading, and notes.',
img: './static/img/my_work/mooknote/banner.jpg'
}
]},
{ category_zh: '个人博客', category_en: 'Personal Blogs', items: [
{ url: 'https://www.ittoolman.top/',
linkText_zh: 'ittoolman - Github托管',
linkText_en: 'ittoolman - Github Page',
desc_zh: '基于 GitHub Pages 搭建的个人技术站点。',
desc_en: 'Personal tech site based on GitHub Pages.',
img: './static/img/my_work/ittoolman/banner.png'
},
{ url: 'https://blog.iletter.top/',
linkText_zh: 'iletter - typecho极简与高效并存',
linkText_en: 'iletter - typecho Minimalism and Efficiency',
desc_zh: '记录日常开发与生活点滴的 Typecho 博客。',
desc_en: 'A Typecho blog recording daily development and life.',
img: './static/img/my_work/blog_iletter/banner.png'
}
]},
{ category_zh: '私人在线应用', category_en: 'Personal Online Apps', items: [
{ img: './static/img/my_work/easyimage2/banner.png',
url: 'https://img.iletter.top/', linkText_zh: 'EsayImage2 - 私人图床工具', linkText_en: 'EsayImage2 - Image Uploader Tool', desc_zh: '稳定高效的图片上传与托管服务。', desc_en: 'Stable and efficient image hosting service.' },
{ url: 'https://gitea.iletter.top/', linkText_zh: 'Gitea - 私人git托管仓库', linkText_en: 'Gitea - Private Git Repository', desc_zh: '轻量级自托管 Git 代码管理平台。', desc_en: 'Lightweight self-hosted Git code management platform.' },
{ url: 'http://umami.iletter.top/', linkText_zh: 'Umami - 网站访问分析', linkText_en: 'Umami - Website visit analysis', desc_zh: '简洁、隐私友好的网站流量统计工具。', desc_en: 'Simple, privacy-friendly website analytics tool.' },
{ url: 'http://beszel.iletter.top/', linkText_zh: 'Beszel - 服务器监控', linkText_en: 'Beszel - Server Monitoring', desc_zh: '实时监控服务器资源占用情况。', desc_en: 'Real-time monitoring of server resource usage.' },
{ url: 'https://memos.iletter.top/', linkText_zh: 'Memos - 个人随想', linkText_en: 'Memos - Personal Thoughts', desc_zh: '碎片化知识管理与灵感记录空间。', desc_en: 'Fragmented knowledge management and inspiration space.' },
{ url: 'http://frp.iletter.top/', linkText_zh: 'FRP - 个人反向代理',
linkText_en: 'FRP - Personal Reverse Proxy', desc_zh: '用于内网穿透的高性能反向代理。',
desc_en: 'High-performance reverse proxy for intranet penetration.',
img: './static/img/my_work/frp_panel/banner.png'
},
{ img: './static/img/my_work/bitwarden/banner.png',
url: 'https://bitwarden.iletter.top/', linkText_zh: 'Bitwarden - 我的密码库', linkText_en: 'Bitwarden - My Password Library', desc_zh: '安全可靠的开源密码管理方案。', desc_en: 'Secure and reliable open-source password management solution.' },
{ url: 'http://docmost.iletter.top/', linkText_zh: 'Docmost - 在线笔记', linkText_en: 'Docmost - Online Notes', desc_zh: '支持协作的实时在线文档编辑平台。', desc_en: 'Real-time online document editing platform supporting collaboration.' },
{ img: './static/img/my_work/openlist/banner.png',
url: 'http://openlist.iletter.top/', linkText_zh: 'OpenList - 在线云盘合集', linkText_en: 'OpenList - Online Cloud Disk Collection', desc_zh: '聚合多种网盘服务的文件列表管理。', desc_en: 'File list management aggregating various cloud storage services.' }
]}
];
// ========== 渲染网站链接的函数 ==========
let currentViewMode = localStorage.getItem('website_view_mode') || 'card'; // 'list' or 'card'
function renderWebsites(websitesArray) {
const container = document.getElementById('dynamic-website-links');
if (!container) {
@@ -109,39 +66,227 @@ function renderWebsites(websitesArray) {
const currentLang = localStorage.getItem("preferred_language") || "zh";
// 清空容器
container.innerHTML = '';
// 清空容器并添加切换按钮
const toggleText = currentViewMode === 'list' ? '切换为卡片视图' : '切换为列表视图';
container.innerHTML = `
<div style="text-align:right;margin-bottom:10px;">
<span class="website-view-toggle" onclick="switchWebsiteView('${currentViewMode === 'list' ? 'card' : 'list'}')">${toggleText}</span>
</div>
<div id="website-content-area"></div>
`;
const contentArea = container.querySelector('#website-content-area');
arrayToRender.forEach(categoryObj => {
// 根据当前语言选择分类标题
const categoryName = currentLang === 'en' ? categoryObj.category_en : categoryObj.category_zh;
if (currentViewMode === 'list') {
arrayToRender.forEach(categoryObj => {
const categoryName = currentLang === 'en' ? categoryObj.category_en : categoryObj.category_zh;
const heading = document.createElement('h3');
heading.textContent = categoryName;
contentArea.appendChild(heading);
// 创建分类标题
const heading = document.createElement('h3');
heading.textContent = categoryName;
container.appendChild(heading);
const linksDiv = document.createElement('div');
linksDiv.className = 'category-links';
// 创建一个 div 来包裹该分类下的所有链接
const linksDiv = document.createElement('div');
linksDiv.className = 'category-links'; // 可选,方便 CSS 样式化
categoryObj.items.forEach(item => {
const linkElement = document.createElement('a');
linkElement.href = item.url;
linkElement.target = '_blank';
// 根据当前语言选择链接文本
const linkText = currentLang === 'en' ? item.linkText_en : item.linkText_zh;
linkElement.textContent = linkText;
linksDiv.appendChild(linkElement);
// 添加一个间隔(例如空格或换行符,取决于你的 CSS 布局)
const space = document.createTextNode(' ');
linksDiv.appendChild(space);
categoryObj.items.forEach(item => {
const linkElement = document.createElement('a');
linkElement.href = '#';
linkElement.textContent = currentLang === 'en' ? item.linkText_en : item.linkText_zh;
if (item.url === 'https://mooknote.iletter.top/#/') {
linkElement.onclick = (e) => {
e.preventDefault();
openMookNoteModal();
};
} else {
linkElement.onclick = (e) => {
e.preventDefault();
window.open(item.url, '_blank');
};
}
linksDiv.appendChild(linkElement);
const space = document.createTextNode(' ');
linksDiv.appendChild(space);
});
contentArea.appendChild(linksDiv);
});
} else {
arrayToRender.forEach(categoryObj => {
const categoryName = currentLang === 'en' ? categoryObj.category_en : categoryObj.category_zh;
const heading = document.createElement('h3');
heading.textContent = categoryName;
contentArea.appendChild(heading);
const gridDiv = document.createElement('div');
gridDiv.className = 'website-card-grid';
categoryObj.items.forEach(item => {
const card = document.createElement('div');
card.className = 'website-card';
if (item.url === 'https://mooknote.iletter.top/#/') {
card.onclick = () => openMookNoteModal();
} else {
card.onclick = () => window.open(item.url, '_blank');
}
const title = currentLang === 'en' ? item.linkText_en : item.linkText_zh;
const desc = currentLang === 'en' ? (item.desc_en || '') : (item.desc_zh || '');
const imgSrc = item.img;
const placeholderText = item.linkText_zh.split(' - ')[0];
const imgHtml = imgSrc
? `<div class="website-card-icon"><img src="${imgSrc}" alt="${placeholderText}" onerror="this.style.display='none';this.parentNode.classList.add('website-card-placeholder');this.parentNode.textContent='${placeholderText}'"></div>`
: `<div class="website-card-icon website-card-placeholder">${placeholderText}</div>`;
card.innerHTML = `
${imgHtml}
<div class="website-card-info">
<div class="website-card-title">${title}</div>
<div class="website-card-desc">${desc}</div>
</div>
`;
gridDiv.appendChild(card);
});
contentArea.appendChild(gridDiv);
});
}
}
container.appendChild(linksDiv);
window.switchWebsiteView = function(mode) {
currentViewMode = mode;
localStorage.setItem('website_view_mode', mode);
renderWebsites();
};
// MookNote 弹窗逻辑
let currentImageIndex = 0;
const mooknoteImages = document.querySelectorAll('.carousel-image');
const totalImages = mooknoteImages.length;
// 全屏预览相关变量
let lightboxImageIndex = 0;
const lightboxImgUrls = [
'./static/img/my_work/mooknote/banner.jpg',
'./static/img/my_work/mooknote/1.jpg',
'./static/img/my_work/mooknote/2.jpg',
'./static/img/my_work/mooknote/3.jpg',
'./static/img/my_work/mooknote/4.jpg',
'./static/img/my_work/mooknote/5.jpg',
'./static/img/my_work/mooknote/6.jpg'
];
// 初始化指示器
function initCarouselIndicators() {
const indicatorsContainer = document.querySelector('.carousel-indicators');
if (!indicatorsContainer) return;
indicatorsContainer.innerHTML = '';
for (let i = 0; i < totalImages; i++) {
const indicator = document.createElement('div');
indicator.className = 'carousel-indicator' + (i === 0 ? ' active' : '');
indicator.onclick = () => goToMooknoteImage(i);
indicatorsContainer.appendChild(indicator);
}
}
// 切换到指定图片
function goToMooknoteImage(index) {
if (index < 0) index = totalImages - 1;
if (index >= totalImages) index = 0;
mooknoteImages.forEach((img, i) => {
img.classList.toggle('active', i === index);
});
const indicators = document.querySelectorAll('.carousel-indicator');
indicators.forEach((indicator, i) => {
indicator.classList.toggle('active', i === index);
});
currentImageIndex = index;
}
// 上一张图片
window.prevMooknoteImage = function() {
goToMooknoteImage(currentImageIndex - 1);
};
// 下一张图片
window.nextMooknoteImage = function() {
goToMooknoteImage(currentImageIndex + 1);
};
// 全屏预览功能
window.openMooknoteLightbox = function(index) {
lightboxImageIndex = index;
const lightbox = document.getElementById('mooknote-lightbox');
const img = lightbox.querySelector('.lightbox-img');
const counter = lightbox.querySelector('.lightbox-counter');
img.src = lightboxImgUrls[index];
counter.textContent = `${index + 1} / ${lightboxImgUrls.length}`;
lightbox.classList.add('active');
};
window.closeMooknoteLightbox = function() {
const lightbox = document.getElementById('mooknote-lightbox');
lightbox.classList.remove('active');
};
window.prevLightboxImage = function() {
lightboxImageIndex = (lightboxImageIndex - 1 + lightboxImgUrls.length) % lightboxImgUrls.length;
updateLightboxImage();
};
window.nextLightboxImage = function() {
lightboxImageIndex = (lightboxImageIndex + 1) % lightboxImgUrls.length;
updateLightboxImage();
};
function updateLightboxImage() {
const lightbox = document.getElementById('mooknote-lightbox');
const img = lightbox.querySelector('.lightbox-img');
const counter = lightbox.querySelector('.lightbox-counter');
img.src = lightboxImgUrls[lightboxImageIndex];
counter.textContent = `${lightboxImageIndex + 1} / ${lightboxImgUrls.length}`;
}
// 键盘事件支持
document.addEventListener('keydown', (e) => {
const lightbox = document.getElementById('mooknote-lightbox');
if (!lightbox.classList.contains('active')) return;
if (e.key === 'Escape') {
closeMooknoteLightbox();
} else if (e.key === 'ArrowLeft') {
prevLightboxImage();
} else if (e.key === 'ArrowRight') {
nextLightboxImage();
}
});
function openMookNoteModal() {
const modal = document.getElementById('mooknote-modal');
if (modal) {
modal.classList.add('active');
document.body.style.overflow = 'hidden';
// 重置轮播到第一张
currentImageIndex = 0;
initCarouselIndicators();
goToMooknoteImage(0);
}
}
const mooknoteClose = document.getElementById('mooknote-close');
if (mooknoteClose) {
mooknoteClose.addEventListener('click', () => {
const modal = document.getElementById('mooknote-modal');
if (modal) {
modal.classList.remove('active');
document.body.style.overflow = '';
}
});
}