Merge branch 'version-2.2'

# Conflicts:
#	about.html
#	index.html
#	js/sw.js
This commit is contained in:
hehh
2025-11-25 21:46:40 +08:00
6 changed files with 515 additions and 712 deletions

View File

@@ -181,7 +181,7 @@ open about.html
- [x] 添加骨架屏加载效果 - [x] 添加骨架屏加载效果
- [x] 实现数据缓存机制,提升页面加载速度 - [x] 实现数据缓存机制,提升页面加载速度
- [x] 添加淡入动画效果,提升用户体验 - [x] 添加淡入动画效果,提升用户体验
- [x] 实现 PWA 支持,支持离线访问
### 待完成 ### 待完成
- [ ] 添加更多数据源(如 Twitter、知乎等 - [ ] 添加更多数据源(如 Twitter、知乎等
@@ -193,6 +193,7 @@ open about.html
- [ ] 添加更多主题选项(如高对比度模式等) - [ ] 添加更多主题选项(如高对比度模式等)
- [ ] 实现深色模式下的图片优化处理 - [ ] 实现深色模式下的图片优化处理
- [ ] 添加无障碍访问支持ARIA 属性完善) - [ ] 添加无障碍访问支持ARIA 属性完善)
- [] 实现 PWA 支持,支持离线访问
## 🙏 鸣谢与致敬 ## 🙏 鸣谢与致敬

View File

@@ -5,9 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<title>关于我 - Honesty</title> <title>关于我 - Honesty</title>
<meta http-equiv="X-UA-Compatible" content="ie=edge"> <meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- PWA相关配置 -->
<meta name="theme-color" content="#6c5ce7">
<link rel="manifest" href="./manifest.json">
<!--SEO信息 --> <!--SEO信息 -->
<meta name="description" content="关于Honesty,关于HeHouHui,关于HeHui,关于明厚, About Me Honesty, About Me HeHouHui, About Me HeHui"> <meta name="description" content="关于Honesty,关于HeHouHui,关于HeHui,关于明厚, About Me Honesty, About Me HeHouHui, About Me HeHui">
@@ -430,37 +428,5 @@
initFormatter(); initFormatter();
} }
</script> </script>
<!-- PWA注册 -->
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
setTimeout(() => {
navigator.serviceWorker.register('./js/sw.js')
.then(function(registration) {
console.log('SW registered: ', registration);
})
.catch(function(registrationError) {
console.log('SW registration failed: ', registrationError);
});
}, 3000); // 页面稳定后再注册
});
}
</script>
<!-- Apple PWA支持 -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="Honesty">
<link rel="apple-touch-icon" href="./images/avatar.jpeg">
<!-- Windows PWA支持 -->
<meta name="msapplication-TileImage" content="./images/avatar.jpeg">
<meta name="msapplication-TileColor" content="#6c5ce7">
<meta name="msapplication-tap-highlight" content="no">
<!-- 其他PWA相关meta标签 -->
<meta name="mobile-web-app-capable" content="yes">
</body> </body>
</html> </html>

File diff suppressed because it is too large Load Diff

View File

@@ -13,9 +13,6 @@
<meta name="keywords" content="Honesty,HeHouHui,HeHui,明厚"> <meta name="keywords" content="Honesty,HeHouHui,HeHui,明厚">
<meta name="author" content="Honesty"> <meta name="author" content="Honesty">
<!-- PWA相关配置 -->
<meta name="theme-color" content="#6c5ce7">
<link rel="manifest" href="./manifest.json">
<!-- 社交平台分享优化 --> <!-- 社交平台分享优化 -->
<!-- Open Graph / Facebook --> <!-- Open Graph / Facebook -->
@@ -416,36 +413,5 @@
}() }()
}({id: "3OBGjwDdEIRS7XZ1", ck: "3OBGjwDdEIRS7XZ1"}); }({id: "3OBGjwDdEIRS7XZ1", ck: "3OBGjwDdEIRS7XZ1"});
</script> </script>
<!-- PWA注册 -->
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
setTimeout(() => {
navigator.serviceWorker.register('./js/sw.js')
.then(function(registration) {
console.log('SW registered: ', registration);
})
.catch(function(registrationError) {
console.log('SW registration failed: ', registrationError);
});
}, 3000); // 页面稳定后再注册
});
}
</script>
<!-- Apple PWA支持 -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="Honesty">
<link rel="apple-touch-icon" href="./images/logo.png">
<!-- Windows PWA支持 -->
<meta name="msapplication-TileImage" content="./images/avatar.jpeg">
<meta name="msapplication-TileColor" content="#6c5ce7">
<meta name="msapplication-tap-highlight" content="no">
<!-- 其他PWA相关meta标签 -->
<meta name="mobile-web-app-capable" content="yes">
</body> </body>
</html> </html>

View File

@@ -239,10 +239,10 @@ class DataManager {
// 创建带超时的fetch函数 // 创建带超时的fetch函数
async fetchWithTimeout(url, options = {}) { async fetchWithTimeout(url, options = {}) {
const { timeout = 5000 } = options; const { timeout = 5000 } = options;
const controller = new AbortController(); const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeout); const id = setTimeout(() => controller.abort(), timeout);
const response = await fetch(url, { const response = await fetch(url, {
...options, ...options,
signal: controller.signal signal: controller.signal
@@ -363,7 +363,7 @@ class DataManager {
<div class="repo-desc">${escapeHtml(dShort)}</div> <div class="repo-desc">${escapeHtml(dShort)}</div>
</div>`; </div>`;
}); });
// 使用requestAnimationFrame避免强制重排 // 使用requestAnimationFrame避免强制重排
requestAnimationFrame(() => { requestAnimationFrame(() => {
const pc = $('#projects-container'); const pc = $('#projects-container');
@@ -480,7 +480,7 @@ class DataManager {
<div class="b-cat">${escapeHtml(cat)}</div> <div class="b-cat">${escapeHtml(cat)}</div>
</div>`; </div>`;
}); });
// 使用requestAnimationFrame避免强制重排 // 使用requestAnimationFrame避免强制重排
requestAnimationFrame(() => { requestAnimationFrame(() => {
const bc = $('#blog-container'); const bc = $('#blog-container');
@@ -567,30 +567,30 @@ class UIManager {
// 发送按钮文字(多语言) // 发送按钮文字(多语言)
sendBtn: isZh ? '发送' : 'Send', sendBtn: isZh ? '发送' : 'Send',
loginBtn: isZh ? '发送' : 'Send', loginBtn: isZh ? '发送' : 'Send',
// 主题支持 // 主题支持
darkMode: document.documentElement.getAttribute('data-theme') === 'night', darkMode: document.documentElement.getAttribute('data-theme') === 'night',
// 编辑器增强配置 // 编辑器增强配置
editor: { editor: {
// 启用 Markdown // 启用 Markdown
markdown: true, markdown: true,
// 表情面板 // 表情面板
emoji: { emoji: {
// 使用默认表情包 // 使用默认表情包
preset: 'twemoji' preset: 'twemoji'
}, },
// 启用 @ 用户提醒功能 // 启用 @ 用户提醒功能
mention: true, mention: true,
// 自动聚焦(仅桌面端) // 自动聚焦(仅桌面端)
autoFocus: !('ontouchstart' in window), autoFocus: !('ontouchstart' in window),
// 限制编辑器高度 // 限制编辑器高度
maxHeight: 200, maxHeight: 200,
// 工具栏 // 工具栏
toolbar: [ toolbar: [
'bold', 'italic', 'strike', 'link', 'bold', 'italic', 'strike', 'link',
@@ -599,7 +599,7 @@ class UIManager {
'emoji', 'mention' 'emoji', 'mention'
] ]
}, },
// 评论格式化函数 // 评论格式化函数
commentFormatter: (comment) => { commentFormatter: (comment) => {
// 美化时间显示 // 美化时间显示
@@ -607,21 +607,21 @@ class UIManager {
const date = new Date(dateStr); const date = new Date(dateStr);
const now = new Date(); const now = new Date();
const diffSec = Math.floor((now - date) / 1000); const diffSec = Math.floor((now - date) / 1000);
if (diffSec < 60) return isZh ? '刚刚' : 'Just now'; if (diffSec < 60) return isZh ? '刚刚' : 'Just now';
if (diffSec < 3600) return isZh ? `${Math.floor(diffSec / 60)}分钟前` : `${Math.floor(diffSec / 60)} minutes ago`; if (diffSec < 3600) return isZh ? `${Math.floor(diffSec / 60)}分钟前` : `${Math.floor(diffSec / 60)} minutes ago`;
if (diffSec < 86400) return isZh ? `${Math.floor(diffSec / 3600)}小时前` : `${Math.floor(diffSec / 3600)} hours ago`; if (diffSec < 86400) return isZh ? `${Math.floor(diffSec / 3600)}小时前` : `${Math.floor(diffSec / 3600)} hours ago`;
const isToday = date.toDateString() === now.toDateString(); const isToday = date.toDateString() === now.toDateString();
if (isToday) return isZh ? if (isToday) return isZh ?
`今天 ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}` : `今天 ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}` :
`Today ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`; `Today ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
const isYesterday = new Date(now - 86400000).toDateString() === date.toDateString(); const isYesterday = new Date(now - 86400000).toDateString() === date.toDateString();
if (isYesterday) return isZh ? if (isYesterday) return isZh ?
`昨天 ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}` : `昨天 ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}` :
`Yesterday ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`; `Yesterday ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
return date.toLocaleString(isZh ? 'zh-CN' : 'en-US', { return date.toLocaleString(isZh ? 'zh-CN' : 'en-US', {
year: 'numeric', year: 'numeric',
month: '2-digit', month: '2-digit',
@@ -630,19 +630,19 @@ class UIManager {
minute: '2-digit' minute: '2-digit'
}).replace(/\//g, '-'); }).replace(/\//g, '-');
}; };
// 如果是管理员,添加徽章 // 如果是管理员,添加徽章
if (comment.is_admin) { if (comment.is_admin) {
comment.nick = `👑${comment.nick}`; comment.nick = `👑${comment.nick}`;
} }
// 更新显示时间 // 更新显示时间
comment.create_date_formatted = formatTime(comment.date || comment.created_at || comment.create_date); comment.create_date_formatted = formatTime(comment.date || comment.created_at || comment.create_date);
return comment; return comment;
} }
}; };
Artalk.init(artalkConfig); Artalk.init(artalkConfig);
this.enhanceArtalkUI(); this.enhanceArtalkUI();
} catch (e) { } catch (e) {
@@ -667,13 +667,13 @@ class UIManager {
} }
} }
// 清空容器 // 清空容器
const container = document.getElementById('artalk-container'); const container = document.getElementById('artalk-container');
if (container) { if (container) {
container.innerHTML = ''; container.innerHTML = '';
} }
// 重新初始化 // 重新初始化
this.initArtalk(); this.initArtalk();
} }
@@ -681,15 +681,15 @@ class UIManager {
enhanceArtalkUI() { enhanceArtalkUI() {
const container = document.getElementById('artalk-container'); const container = document.getElementById('artalk-container');
if (!container) return; if (!container) return;
// 检测是否为移动端 // 检测是否为移动端
const isMobile = window.matchMedia('(max-width: 768px)').matches; const isMobile = window.matchMedia('(max-width: 768px)').matches;
container.classList.toggle('atk-mobile', isMobile); container.classList.toggle('atk-mobile', isMobile);
container.classList.toggle('atk-desktop', !isMobile); container.classList.toggle('atk-desktop', !isMobile);
// 获取当前语言 // 获取当前语言
const lang = getStoredLanguage(); const lang = getStoredLanguage();
// 获取当前主题 // 获取当前主题
const currentTheme = document.documentElement.getAttribute('data-theme'); const currentTheme = document.documentElement.getAttribute('data-theme');
@@ -697,7 +697,7 @@ class UIManager {
if (isMobile) { if (isMobile) {
this.enhanceMobileArtalk(container, lang); this.enhanceMobileArtalk(container, lang);
} }
// 监听主题/语言变化 // 监听主题/语言变化
const themeObserver = new MutationObserver(() => { const themeObserver = new MutationObserver(() => {
const newTheme = document.documentElement.getAttribute('data-theme'); const newTheme = document.documentElement.getAttribute('data-theme');
@@ -709,7 +709,7 @@ class UIManager {
this.reloadArtalk(); this.reloadArtalk();
}, 300); }, 300);
}); });
themeObserver.observe(document.documentElement, { themeObserver.observe(document.documentElement, {
attributes: true, attributes: true,
attributeFilter: ['data-theme', 'data-lang'] attributeFilter: ['data-theme', 'data-lang']
@@ -723,32 +723,32 @@ class UIManager {
container.querySelectorAll('.atk-comment-wrap .atk-content').forEach(el => { container.querySelectorAll('.atk-comment-wrap .atk-content').forEach(el => {
// 检查是否已经处理过 // 检查是否已经处理过
if (el.dataset.mobileProcessed) return; if (el.dataset.mobileProcessed) return;
// 检查内容是否超过3行才添加展开收起功能 // 检查内容是否超过3行才添加展开收起功能
const lineHeight = parseInt(window.getComputedStyle(el).lineHeight); const lineHeight = parseInt(window.getComputedStyle(el).lineHeight);
const paddingTop = parseInt(window.getComputedStyle(el).paddingTop); const paddingTop = parseInt(window.getComputedStyle(el).paddingTop);
const paddingBottom = parseInt(window.getComputedStyle(el).paddingBottom); const paddingBottom = parseInt(window.getComputedStyle(el).paddingBottom);
const actualHeight = el.clientHeight - paddingTop - paddingBottom; const actualHeight = el.clientHeight - paddingTop - paddingBottom;
// 如果内容高度超过3倍行高则添加展开收起功能 // 如果内容高度超过3倍行高则添加展开收起功能
if (actualHeight > lineHeight * 3) { if (actualHeight > lineHeight * 3) {
// 添加移动端内容截断 // 添加移动端内容截断
el.classList.add('clamped'); el.classList.add('clamped');
el.style.setProperty('--max-lines', '3'); el.style.setProperty('--max-lines', '3');
// 创建展开/收起按钮 // 创建展开/收起按钮
const btn = document.createElement('button'); const btn = document.createElement('button');
btn.className = 'atk-expand-btn'; btn.className = 'atk-expand-btn';
const expandText = lang === 'zh' ? '展开' : 'Expand'; const expandText = lang === 'zh' ? '展开' : 'Expand';
const collapseText = lang === 'zh' ? '收起' : 'Collapse'; const collapseText = lang === 'zh' ? '收起' : 'Collapse';
btn.textContent = expandText; btn.textContent = expandText;
btn.addEventListener('click', (e) => { btn.addEventListener('click', (e) => {
e.stopPropagation(); e.stopPropagation();
const isClamped = el.classList.toggle('clamped'); const isClamped = el.classList.toggle('clamped');
btn.textContent = isClamped ? expandText : collapseText; btn.textContent = isClamped ? expandText : collapseText;
}); });
// 将按钮插入到适当位置 // 将按钮插入到适当位置
const actionsElement = el.closest('.atk-comment').querySelector('.atk-actions'); const actionsElement = el.closest('.atk-comment').querySelector('.atk-actions');
if (actionsElement) { if (actionsElement) {
@@ -757,23 +757,23 @@ class UIManager {
el.parentNode.appendChild(btn); el.parentNode.appendChild(btn);
} }
} }
// 标记为已处理 // 标记为已处理
el.dataset.mobileProcessed = '1'; el.dataset.mobileProcessed = '1';
}); });
}; };
// 初始应用 // 初始应用
applyMobileStyles(); applyMobileStyles();
// 创建观察器以处理动态添加的评论 // 创建观察器以处理动态添加的评论
const observer = new MutationObserver(applyMobileStyles); const observer = new MutationObserver(applyMobileStyles);
observer.observe(container, { observer.observe(container, {
childList: true, childList: true,
subtree: true, subtree: true,
attributes: false attributes: false
}); });
// 添加移动端特定的样式类 // 添加移动端特定的样式类
const theme = document.documentElement.getAttribute('data-theme'); const theme = document.documentElement.getAttribute('data-theme');
container.classList.add(`atk-theme-${theme || 'day'}`); container.classList.add(`atk-theme-${theme || 'day'}`);
@@ -826,7 +826,7 @@ class UIManager {
} else { } else {
// PC: 3D Sphere // PC: 3D Sphere
container.classList.remove('mobile-scroll'); container.classList.remove('mobile-scroll');
// 使用防抖优化尺寸计算 // 使用防抖优化尺寸计算
let resizeTimeout; let resizeTimeout;
const updateContainerSize = () => { const updateContainerSize = () => {
@@ -837,19 +837,19 @@ class UIManager {
init3DSphere(); init3DSphere();
}, 100); }, 100);
}; };
// 初始化3D球体 // 初始化3D球体
const init3DSphere = () => { const init3DSphere = () => {
// 清除之前的动画 // 清除之前的动画
if (container.__animToken) { if (container.__animToken) {
cancelAnimationFrame(container.__animToken); cancelAnimationFrame(container.__animToken);
} }
// 清空容器 // 清空容器
container.innerHTML = ''; container.innerHTML = '';
const tags = []; const tags = [];
techStack.forEach((item, index) => { techStack.forEach((item, index) => {
const el = document.createElement('a'); const el = document.createElement('a');
el.className = 'tech-tag-3d'; el.className = 'tech-tag-3d';
@@ -860,13 +860,13 @@ class UIManager {
container.appendChild(el); container.appendChild(el);
tags.push({el, x: 0, y: 0, z: 0}); tags.push({el, x: 0, y: 0, z: 0});
}); });
// 动态半径,避免容器溢出,使用防抖优化 // 动态半径,避免容器溢出,使用防抖优化
let radius = Math.max(160, Math.min(container.offsetWidth, container.offsetHeight) / 2 - 24); let radius = Math.max(160, Math.min(container.offsetWidth, container.offsetHeight) / 2 - 24);
const dtr = Math.PI / 180; const dtr = Math.PI / 180;
let lasta = 1, lastb = 1; let lasta = 1, lastb = 1;
let active = false, mouseX = 0, mouseY = 0; let active = false, mouseX = 0, mouseY = 0;
// 初始化位置 // 初始化位置
tags.forEach((tag, i) => { tags.forEach((tag, i) => {
let phi = Math.acos(-1 + (2 * i + 1) / tags.length); let phi = Math.acos(-1 + (2 * i + 1) / tags.length);
@@ -875,7 +875,7 @@ class UIManager {
tag.y = radius * Math.sin(theta) * Math.sin(phi); tag.y = radius * Math.sin(theta) * Math.sin(phi);
tag.z = radius * Math.cos(phi); tag.z = radius * Math.cos(phi);
}); });
container.onmouseover = () => active = true; container.onmouseover = () => active = true;
container.onmouseout = () => active = false; container.onmouseout = () => active = false;
container.onmousemove = (e) => { container.onmousemove = (e) => {
@@ -886,7 +886,7 @@ class UIManager {
mouseY = (e.clientY - (rect.top + rect.height / 2)) / 5; mouseY = (e.clientY - (rect.top + rect.height / 2)) / 5;
}); });
}; };
const update = () => { const update = () => {
let a, b; let a, b;
if (active) { if (active) {
@@ -898,12 +898,12 @@ class UIManager {
} }
lasta = a; lasta = a;
lastb = b; lastb = b;
if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01 && !active) a = 0.5; // Keep spinning slowly if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01 && !active) a = 0.5; // Keep spinning slowly
let sa = Math.sin(a * dtr), ca = Math.cos(a * dtr); let sa = Math.sin(a * dtr), ca = Math.cos(a * dtr);
let sb = Math.sin(b * dtr), cb = Math.cos(b * dtr); let sb = Math.sin(b * dtr), cb = Math.cos(b * dtr);
// 批量更新样式以减少重排 // 批量更新样式以减少重排
// 先收集所有需要更新的样式信息 // 先收集所有需要更新的样式信息
const updates = []; const updates = [];
@@ -920,7 +920,7 @@ class UIManager {
const zIndex = parseInt(scale * 100); const zIndex = parseInt(scale * 100);
const left = tag.x + container.offsetWidth / 2 - tag.el.offsetWidth / 2; const left = tag.x + container.offsetWidth / 2 - tag.el.offsetWidth / 2;
const top = tag.y + container.offsetHeight / 2 - tag.el.offsetHeight / 2; const top = tag.y + container.offsetHeight / 2 - tag.el.offsetHeight / 2;
updates.push({ updates.push({
el: tag.el, el: tag.el,
transform: `translate(${left}px, ${top}px) scale(${scale})`, transform: `translate(${left}px, ${top}px) scale(${scale})`,
@@ -934,16 +934,16 @@ class UIManager {
update.el.style.opacity = update.opacity; update.el.style.opacity = update.opacity;
update.el.style.zIndex = update.zIndex; update.el.style.zIndex = update.zIndex;
}); });
container.__animToken = requestAnimationFrame(update); container.__animToken = requestAnimationFrame(update);
}; };
container.__animToken = requestAnimationFrame(update); container.__animToken = requestAnimationFrame(update);
}; };
// 初始化3D球体 // 初始化3D球体
init3DSphere(); init3DSphere();
// 监听窗口大小变化 // 监听窗口大小变化
window.addEventListener('resize', updateContainerSize); window.addEventListener('resize', updateContainerSize);
} }
@@ -957,10 +957,10 @@ class UIManager {
const fTheme = document.getElementById('fab-theme'); const fTheme = document.getElementById('fab-theme');
const fMusic = document.getElementById('fab-music'); const fMusic = document.getElementById('fab-music');
if (!main || !menu || !fLang || !fTheme || !fMusic) return; if (!main || !menu || !fLang || !fTheme || !fMusic) return;
// 添加拖拽功能 // 添加拖拽功能
this.initDraggableFab(); this.initDraggableFab();
const updateLabels = () => { const updateLabels = () => {
// 使用requestAnimationFrame避免强制重排 // 使用requestAnimationFrame避免强制重排
requestAnimationFrame(() => { requestAnimationFrame(() => {
@@ -1098,7 +1098,7 @@ class UIManager {
// 确保容器具有正确的主题类 // 确保容器具有正确的主题类
container.classList.remove('atk-theme-day', 'atk-theme-night'); container.classList.remove('atk-theme-day', 'atk-theme-night');
container.classList.add(`atk-theme-${theme || 'day'}`); container.classList.add(`atk-theme-${theme || 'day'}`);
// 更新自定义元素的主题样式 // 更新自定义元素的主题样式
const customElements = container.querySelectorAll('.atk-expand-btn, .atk-pagination .atk-page-item'); const customElements = container.querySelectorAll('.atk-expand-btn, .atk-pagination .atk-page-item');
customElements.forEach(el => { customElements.forEach(el => {

View File

@@ -1,93 +0,0 @@
// Service Worker for PWA
const CACHE_NAME = 'honesty-home-v1.0.1';
const urlsToCache = [
'./index.html',
'./about.html',
'./css/style.css',
'./css/about.css',
'./css/artalk.css',
'./js/config.js',
'./js/main.js',
'./js/about.js',
'./images/avatar.jpeg',
'./images/favicon.ico',
'./images/favicon.png',
'./images/logo.png',
'./images/INFJ.png',
'./images/kl.gif',
'./images/bj/1.jpg',
'./images/bj/2.jpg',
'./images/bj/3.jpg',
'./images/bj/4.jpg',
'./images/bj/5.jpg',
'./images/bj/6.jpg',
'./images/bj/7.jpg',
];
// 安装事件 - 缓存资源
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
);
});
// 获取事件 - 拦截网络请求
self.addEventListener('fetch', event => {
// 对于非GET请求或者不是同源请求直接跳过
if (event.request.method !== 'GET' || !event.request.url.startsWith(self.location.origin)) {
return;
}
event.respondWith(
caches.match(event.request)
.then(response => {
// 如果在缓存中找到响应,则返回缓存的资源
if (response) {
return response;
}
// 克隆请求,因为请求是一个流,只能被消费一次
const fetchRequest = event.request.clone();
// 如果没有在缓存中找到,则发起网络请求
return fetch(fetchRequest).then(response => {
// 检查响应是否有效
if (!response || response.status !== 200 || response.type !== 'basic') {
return response;
}
// 克隆响应,因为响应是一个流,只能被消费一次
const responseToCache = response.clone();
// 打开缓存并将响应添加到缓存中
caches.open(CACHE_NAME)
.then(cache => {
cache.put(event.request, responseToCache);
});
return response;
});
})
);
});
// 激活事件 - 清理旧缓存
self.addEventListener('activate', event => {
const cacheWhitelist = [CACHE_NAME];
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheWhitelist.indexOf(cacheName) === -1) {
return caches.delete(cacheName);
}
})
);
})
);
});