用途
- 自用,主要过个人网站备案用的,个人网站备案内容限制很多,放一个很大的网站在主页又不合适,所以做了一个简单的单页面。
- 预览地址:https://blog.ckey.run
核心功能亮点
-
响应式:适配PC和移动端。
-
实时时间统计:动态显示今天的时刻,并用进度条直观呈现今日、本周、本月、本年的流逝比例,让时间看得见。
-
每日一记:以时间为序展示最近日志,每条均可点击下划线链接快速定位,方便查看与扩展。(无实际功能,就做一个假装展示有内容)
-
时光轴浏览:按年份、月份组织内容,可展开/收起,轻松回溯往期记录。(无实际功能)
-
每日一图与心语:自动获取随机美图作背景,并配上一句来自 Hitokoto 或精选的格言,为每天添一份仪式感。
-
多主题色切换:在深色、浅色、护眼绿、深蓝科技四套配色间自由切换,并自动记住你的选择。
-
底部始终置底备案号:站点律备案可见,同时不干扰主内容阅读。
代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>网站标题 每日一记</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
:root {
--primary: #556677;
--secondary: #778899;
--accent: #cc6666;
--light: #f8f9fa;
--dark: #343a40;
--gray: #6c757d;
--success: #669966;
--bg-gradient-start: #2c3e50;
--bg-gradient-mid: #4a6572;
--bg-gradient-end: #34495e;
}
html, body {
height: 100%;
}
body {
background: linear-gradient(135deg, var(--bg-gradient-start), var(--bg-gradient-mid), var(--bg-gradient-end));
background-size: 400% 400%;
animation: gradientBG 15s ease infinite;
color: var(--light);
line-height: 1.6;
min-height: 100vh;
padding: 20px;
display: flex;
flex-direction: column;
}
@keyframes gradientBG {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
.container {
max-width: 1200px;
width: 100%;
margin: 0 auto;
flex: 1;
}
header {
text-align: center;
padding: 20px 0;
margin-bottom: 30px;
background: rgba(0, 0, 0, 0.3);
border-radius: 15px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
position: relative;
overflow: hidden;
}
.daily-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
z-index: -1;
opacity: 0;
transition: opacity 1s ease-in-out;
}
.daily-bg.loaded {
opacity: 0.35;
}
.slogan {
font-size: 1.8rem;
font-style: italic;
color: #ffd700;
margin: 15px 0;
min-height: 60px;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
transition: opacity 0.5s ease;
padding: 0 20px;
position: relative;
z-index: 1;
}
.slogan-author {
font-size: 1.1rem;
color: #a0d2eb;
margin-top: 8px;
font-style: normal;
}
.slogan.loading {
opacity: 0.7;
}
.main-content {
display: grid;
grid-template-columns: 1fr;
gap: 25px;
}
@media (min-width: 768px) {
.main-content {
grid-template-columns: 1fr 1fr;
}
}
@media (min-width: 992px) {
.main-content {
grid-template-columns: 1fr;
}
}
.card {
background: rgba(0, 0, 0, 0.3);
border-radius: 15px;
padding: 25px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);
}
.card-title {
font-size: 1.8rem;
margin-bottom: 15px;
color: #ffffff;
display: flex;
align-items: center;
gap: 10px;
}
.card-title i {
font-size: 1.5rem;
color: #ffffff;
}
.time-display {
font-size: 1.1rem;
margin-bottom: 15px;
color: #a0d2eb;
}
.progress-container {
margin: 20px 0;
}
.progress-item {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
}
.progress-bar {
height: 10px;
background: rgba(255, 255, 255, 0.1);
border-radius: 5px;
overflow: hidden;
margin-bottom: 15px;
}
.progress-fill {
height: 100%;
background: #ffffff;
border-radius: 5px;
}
.log-list {
list-style: none;
}
.log-item {
padding: 8px 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.log-item:last-child {
border-bottom: none;
}
.timeline-container {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 15px;
}
.year-item {
padding: 10px 20px;
background: rgba(255, 255, 255, 0.1);
border-radius: 20px;
cursor: pointer;
transition: all 0.3s ease;
font-weight: bold;
text-align: center;
color: #ffffff;
}
.year-item:hover {
background: var(--primary);
transform: scale(1.05);
}
.year-item.active {
background: #ffffff;
color: #000000;
}
.months-container {
display: none;
grid-template-columns: repeat(4, 1fr);
gap: 8px;
margin-top: 15px;
padding: 15px;
background: rgba(0, 0, 0, 0.2);
border-radius: 10px;
}
.months-container.active {
display: grid;
}
.month-item {
padding: 8px 12px;
background: rgba(255, 255, 255, 0.1);
border-radius: 15px;
cursor: pointer;
transition: all 0.3s ease;
text-align: center;
font-size: 0.9rem;
color: #ffffff;
}
.month-item:hover {
background: var(--primary);
}
.month-item.selected {
background: #ffffff;
color: #000000;
}
footer {
text-align: center;
padding: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 0.9rem;
line-height: 1.4;
margin-top: auto;
width: 100%;
}
.highlight {
color: #ffd700;
font-weight: bold;
}
.dynamic-content {
margin-top: 15px;
}
.expand-btn {
display: inline-block;
padding: 5px 15px;
background: rgba(255, 255, 255, 0.1);
border-radius: 15px;
cursor: pointer;
margin-top: 10px;
font-size: 0.9rem;
transition: all 0.3s ease;
color: #ffffff;
}
.expand-btn:hover {
background: var(--primary);
}
.refresh-btn {
background: none;
border: none;
color: #a0d2eb;
cursor: pointer;
margin-top: 5px;
font-size: 0.9rem;
opacity: 0.7;
transition: opacity 0.3s ease;
}
.refresh-btn:hover {
opacity: 1;
}
.header-buttons {
display: flex;
justify-content: center;
gap: 15px;
margin-top: 15px;
}
.theme-switcher {
display: flex;
justify-content: center;
gap: 10px;
margin-top: 10px;
}
.theme-btn {
width: 24px;
height: 24px;
border-radius: 50%;
border: 2px solid rgba(255,255,255,0.6);
cursor: pointer;
outline: none;
transition: transform 0.2s ease;
}
.theme-btn:hover {
transform: scale(1.2);
}
.theme-btn.active {
border-color: #fff;
box-shadow: 0 0 6px #fff;
}
.theme-dark { background: #343a40; }
.theme-light { background: #f8f9fa; }
.theme-green { background: #52734d; }
.theme-blue { background: #004466; }
.footer-links {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
}
@media (min-width: 768px) {
.footer-links {
flex-direction: row;
justify-content: center;
gap: 12px;
}
}
.footer-links a {
color: rgba(255, 255, 255, 0.7);
text-decoration: none;
transition: color 0.3s ease;
}
.footer-links a:hover {
color: #ffd700;
}
.year-header {
grid-column: 1 / -1;
font-weight: bold;
margin-top: 10px;
color: #ffffff !important;
font-size: 1.1rem;
}
html {
scroll-behavior: smooth;
}
.theme-footer-wrapper {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}
</style>
</head>
<body>
<div class="container">
<header id="main-header">
<img src="" alt="每日一图" class="daily-bg" id="daily-bg" />
<div class="slogan" id="hitokoto-text">
<div id="hitokoto-content" style="color:#ffffff;">每一个人都应该明确自己的方向和位置</div>
<div id="hitokoto-author" class="slogan-author">-「 小白 」</div>
</div>
<div class="header-buttons">
<button class="refresh-btn" id="refresh-hitokoto">
<i class="fas fa-redo-alt"></i> 换一句
</button>
</div>
</header>
<div class="main-content">
<div class="card">
<h2 class="card-title"><i class="fas fa-clock"></i> 时间统计</h2>
<div class="time-display" id="current-time">2000 年 0 月 00 日 星期一 00:00:00</div>
<div class="progress-container">
<div class="progress-item">
<span id="today-text">今日已经度过了 0 小时</span>
<span id="today-percent">0%</span>
</div>
<div class="progress-bar">
<div class="progress-fill" id="today-bar" style="width: 0%"></div>
</div>
<div class="progress-item">
<span id="week-text">本周已经度过了 0 天</span>
<span id="week-percent">0%</span>
</div>
<div class="progress-bar">
<div class="progress-fill" id="week-bar" style="width: 0%"></div>
</div>
<div class="progress-item">
<span id="month-text">本月已经度过了 0 天</span>
<span id="month-percent">0%</span>
</div>
<div class="progress-bar">
<div class="progress-fill" id="month-bar" style="width: 0%"></div>
</div>
<div class="progress-item">
<span id="year-text">今年已经度过了 0 个月</span>
<span id="year-percent">0%</span>
</div>
<div class="progress-bar">
<div class="progress-fill" id="year-bar" style="width: 0%"></div>
</div>
</div>
</div>
<div class="card">
<h2 class="card-title"><i class="fas fa-clipboard-list"></i> 每日一记</h2>
<ul class="log-list" id="recent-logs"></ul>
<div style="text-align: center; margin-top: 15px;">
<a href="#" style="color: #a0d2eb;">加载更多</a>
</div>
</div>
<div class="card">
<h2 class="card-title"><i class="fas fa-history"></i> 时光轴</h2>
<div class="dynamic-content">
<div class="timeline-container" id="years-container"></div>
<div id="months-container" class="months-container"></div>
</div>
<div style="text-align: center; margin-top: 15px;">
<div class="expand-btn" id="expand-all-btn">展开所有年份月份</div>
</div>
</div>
</div>
</div>
<footer>
<div class="theme-footer-wrapper">
<div class="theme-switcher">
<button class="theme-btn theme-dark active" data-theme="dark" title="深色主题"></button>
<button class="theme-btn theme-light" data-theme="light" title="浅色主题"></button>
<button class="theme-btn theme-green" data-theme="green" title="护眼绿"></button>
<button class="theme-btn theme-blue" data-theme="blue" title="深蓝科技"></button>
</div>
<div class="footer-links">
<a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener noreferrer">ICP备x号</a>
<a href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=xxx" target="_blank" rel="noopener noreferrer">公网安备xxx</a>
</div>
</div>
</footer>
<script>
const presetHitokotos = [
{ text: "每一个人都应该明确自己的方向和位置", author: "小白" },
{ text: "生活不止眼前的苟且,还有诗和远方", author: "高晓松" },
{ text: "志不强者智不达,言不信者行不果", author: "墨子" },
{ text: "成功不是将来才有的,而是从决定去做的那一刻起,持续累积而成", author: "佚名" },
{ text: "时间就像海绵里的水,只要愿挤,总还是有的", author: "鲁迅" },
{ text: "生活就像海洋,只有意志坚强的人,才能到达彼岸", author: "马克思" },
{ text: "不要等待机会,而要创造机会", author: "佚名" },
{ text: "路漫漫其修远兮,吾将上下而求索", author: "屈原" },
{ text: "宝剑锋从磨砺出,梅花香自苦寒来", author: "《警世贤文》" },
{ text: "山重水复疑无路,柳暗花明又一村", author: "陆游" }
];
const themes = {
dark: {
'--primary': '#556677',
'--secondary': '#778899',
'--accent': '#cc6666',
'--light': '#f8f9fa',
'--dark': '#343a40',
'--gray': '#6c757d',
'--success': '#669966',
'--bg-gradient-start': '#2c3e50',
'--bg-gradient-mid': '#4a6572',
'--bg-gradient-end': '#34495e'
},
light: {
'--primary': '#334455',
'--secondary': '#667788',
'--accent': '#dd7777',
'--light': '#212529',
'--dark': '#f8f9fa',
'--gray': '#495057',
'--success': '#447744',
'--bg-gradient-start': '#cceeff',
'--bg-gradient-mid': '#aaddee',
'--bg-gradient-end': '#88ccee'
},
green: {
'--primary': '#4a634a',
'--secondary': '#6b8e6b',
'--accent': '#cc9966',
'--light': '#f0f5f0',
'--dark': '#2d3b2d',
'--gray': '#556655',
'--success': '#44aa44',
'--bg-gradient-start': '#3e4e3e',
'--bg-gradient-mid': '#5a705a',
'--bg-gradient-end': '#3e4e3e'
},
blue: {
'--primary': '#335577',
'--secondary': '#557799',
'--accent': '#ee8866',
'--light': '#f0f8ff',
'--dark': '#112233',
'--gray': '#445566',
'--success': '#337755',
'--bg-gradient-start': '#001122',
'--bg-gradient-mid': '#003344',
'--bg-gradient-end': '#001122'
}
};
function applyTheme(themeName) {
const root = document.documentElement;
const vars = themes[themeName];
Object.keys(vars).forEach(key => {
root.style.setProperty(key, vars[key]);
});
document.querySelectorAll('.theme-btn').forEach(btn => btn.classList.remove('active'));
document.querySelector(`.theme-btn[data-theme="${themeName}"]`).classList.add('active');
localStorage.setItem('theme', themeName);
}
async function fetchHitokoto() {
const hitokotoText = document.getElementById('hitokoto-content');
const hitokotoAuthor = document.getElementById('hitokoto-author');
const sloganElement = document.getElementById('hitokoto-text');
try {
sloganElement.classList.add('loading');
const response = await fetch('https://v1.hitokoto.cn/');
if (response.ok) {
const data = await response.json();
hitokotoText.textContent = data.hitokoto;
hitokotoAuthor.textContent = `-「 ${data.from || '佚名'} 」`;
} else {
throw new Error('API请求失败');
}
} catch (error) {
const randomIndex = Math.floor(Math.random() * presetHitokotos.length);
const selectedHitokoto = presetHitokotos[randomIndex];
hitokotoText.textContent = selectedHitokoto.text;
hitokotoAuthor.textContent = `-「 ${selectedHitokoto.author} 」`;
} finally {
sloganElement.classList.remove('loading');
}
}
function updateCurrentTime() {
const now = new Date();
const year = now.getFullYear();
const month = now.getMonth() + 1;
const day = now.getDate();
const weekdays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
const weekday = weekdays[now.getDay()];
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
const timeString = `${year} 年 ${month} 月 ${day} 日 ${weekday} ${hours}:${minutes}:${seconds}`;
document.getElementById('current-time').textContent = timeString;
}
function updateTimeStats() {
const now = new Date();
const hoursPassed = now.getHours();
const todayPercent = Math.round((hoursPassed / 24) * 100);
document.getElementById('today-text').textContent = `今日已经度过了 ${hoursPassed} 小时`;
document.getElementById('today-percent').textContent = `${todayPercent}%`;
document.getElementById('today-bar').style.width = `${todayPercent}%`;
const startOfWeek = new Date(now);
const day = now.getDay();
const diffToMonday = day === 0 ? 6 : day - 1;
startOfWeek.setDate(now.getDate() - diffToMonday);
startOfWeek.setHours(0, 0, 0, 0);
const endOfWeek = new Date(startOfWeek);
endOfWeek.setDate(startOfWeek.getDate() + 6);
endOfWeek.setHours(23, 59, 59, 999);
let daysPassedWeek = 0;
if (now >= startOfWeek && now <= endOfWeek) {
daysPassedWeek = Math.floor((now - startOfWeek) / (1000 * 60 * 60 * 24)) + 1;
}
const weekPercent = Math.round((daysPassedWeek / 7) * 100);
document.getElementById('week-text').textContent = `本周已经度过了 ${daysPassedWeek} 天`;
document.getElementById('week-percent').textContent = `${weekPercent}%`;
document.getElementById('week-bar').style.width = `${weekPercent}%`;
const daysInMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate();
const monthPercent = Math.round((now.getDate() / daysInMonth) * 100);
document.getElementById('month-text').textContent = `本月已经度过了 ${now.getDate()} 天`;
document.getElementById('month-percent').textContent = `${monthPercent}%`;
document.getElementById('month-bar').style.width = `${monthPercent}%`;
const startOfYear = new Date(now.getFullYear(), 0, 1);
const endOfYear = new Date(now.getFullYear() + 1, 0, 1);
const monthsPassedYear = now.getMonth();
const yearPercent = Math.round(((monthsPassedYear + (now.getDate() / daysInMonth)) / 12) * 100);
document.getElementById('year-text').textContent = `今年已经度过了 ${monthsPassedYear + 1} 个月`;
document.getElementById('year-percent').textContent = `${yearPercent}%`;
document.getElementById('year-bar').style.width = `${yearPercent}%`;
}
function generateRecentLogs() {
const logList = document.getElementById('recent-logs');
const now = new Date();
for (let i = 0; i < 6; i++) {
const date = new Date();
date.setDate(now.getDate() - i);
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
const logItem = document.createElement('li');
logItem.className = 'log-item';
const logLink = document.createElement('a');
logLink.href = '#';
logLink.className = 'log-link';
logLink.style.color = 'white';
logLink.textContent = `日志:${year}年${month}月${day}日`;
logItem.appendChild(logLink);
logList.appendChild(logItem);
}
}
function generateYears() {
const yearsContainer = document.getElementById('years-container');
const currentYear = new Date().getFullYear();
for (let i = 0; i <= 5; i++) {
const year = currentYear - i;
const yearItem = document.createElement('div');
yearItem.className = 'year-item';
yearItem.textContent = `${year}年`;
yearItem.dataset.year = year;
yearItem.addEventListener('click', function() {
document.querySelectorAll('.year-item').forEach(item => item.classList.remove('active'));
this.classList.add('active');
generateMonthsForYear(year);
});
yearsContainer.appendChild(yearItem);
}
}
function generateMonthsForYear(year) {
const monthsContainer = document.getElementById('months-container');
monthsContainer.innerHTML = '';
monthsContainer.classList.add('active');
monthsContainer.style.gridTemplateColumns = 'repeat(4, 1fr)';
for (let month = 1; month <= 12; month++) {
const monthItem = document.createElement('div');
monthItem.className = 'month-item';
monthItem.textContent = `${month}月`;
monthItem.dataset.year = year;
monthItem.dataset.month = month;
monthItem.addEventListener('click', function() {
document.querySelectorAll('.month-item').forEach(item => {
item.classList.remove('selected');
item.style.background = 'rgba(255, 255, 255, 0.1)';
});
this.classList.add('selected');
this.style.background = '#ffffff';
document.getElementById('months-container').scrollIntoView({ behavior: 'smooth' });
});
monthsContainer.appendChild(monthItem);
}
}
function setupExpandAllButton() {
const expandBtn = document.getElementById('expand-all-btn');
const monthsContainer = document.getElementById('months-container');
let allMonthsExpanded = false;
expandBtn.addEventListener('click', function() {
if (!allMonthsExpanded) {
const yearsContainer = document.getElementById('years-container');
const years = yearsContainer.querySelectorAll('.year-item');
monthsContainer.innerHTML = '';
monthsContainer.classList.add('active');
monthsContainer.style.gridTemplateColumns = 'repeat(6, 1fr)';
years.forEach(yearItem => {
const year = yearItem.dataset.year;
const yearHeader = document.createElement('div');
yearHeader.className = 'year-header';
yearHeader.textContent = `${year}年`;
monthsContainer.appendChild(yearHeader);
for (let month = 1; month <= 12; month++) {
const monthItem = document.createElement('div');
monthItem.className = 'month-item';
monthItem.textContent = `${month}月`;
monthItem.dataset.year = year;
monthItem.dataset.month = month;
monthItem.addEventListener('click', function() {
document.querySelectorAll('.month-item').forEach(item => {
item.classList.remove('selected');
item.style.background = 'rgba(255, 255, 255, 0.1)';
});
this.classList.add('selected');
this.style.background = '#ffffff';
document.getElementById('months-container').scrollIntoView({ behavior: 'smooth' });
});
monthsContainer.appendChild(monthItem);
}
});
expandBtn.textContent = '收起月份';
allMonthsExpanded = true;
} else {
monthsContainer.innerHTML = '';
monthsContainer.classList.remove('active');
document.querySelectorAll('.year-item').forEach(item => item.classList.remove('active'));
expandBtn.textContent = '展开所有年份月份';
allMonthsExpanded = false;
}
});
}
function loadDailyBackground() {
const dailyImg = document.getElementById('daily-bg');
dailyImg.classList.remove('loaded');
dailyImg.src = `https://picsum.photos/seed/${Date.now()}/1200/400`;
dailyImg.onload = () => dailyImg.classList.add('loaded');
dailyImg.onerror = () => console.warn('每日图加载失败,保持默认背景');
}
async function refreshAll() {
loadDailyBackground();
await fetchHitokoto();
}
document.addEventListener('DOMContentLoaded', function() {
const savedTheme = localStorage.getItem('theme') || 'dark';
applyTheme(savedTheme);
document.querySelectorAll('.theme-btn').forEach(btn => {
btn.addEventListener('click', () => applyTheme(btn.dataset.theme));
});
fetchHitokoto();
updateCurrentTime();
updateTimeStats();
setInterval(() => {
updateCurrentTime();
updateTimeStats();
}, 1000);
generateRecentLogs();
generateYears();
setupExpandAllButton();
loadDailyBackground();
document.getElementById('refresh-hitokoto').addEventListener('click', refreshAll);
document.querySelectorAll('a[style*="color: #a0d2eb"]').forEach(link => {
link.addEventListener('click', e => {
e.preventDefault();
alert('正在加载更多内容...');
});
});
});
</script>
</body>
</html>