Files

801 lines
28 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222"><meta name="generator" content="Hexo 6.3.0">
<link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
<link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
<link rel="mask-icon" href="/images/logo.svg" color="#222">
<link rel="stylesheet" href="/css/main.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.0/css/all.min.css" integrity="sha256-VHqXKFhhMxcpubYf9xiWdCiojEbY9NexQ4jh8AxbvcM=" crossorigin="anonymous">
<script class="next-config" data-name="main" type="application/json">{"hostname":"toozhao.com","root":"/","images":"/images","scheme":"Muse","darkmode":false,"version":"8.28.0","exturl":false,"sidebar":{"position":"left","width_expanded":320,"width_dual_column":240,"display":"post","padding":18,"offset":12,"b2t":true,"scrollpercent":true},"hljswrap":true,"codeblock":{"theme":{"light":"default","dark":"stackoverflow-dark"},"prism":{"light":"prism","dark":"prism-dark"},"copy_button":{"enable":true,"style":"mac"},"fold":{"enable":false,"height":500},"language":false},"bookmark":{"enable":true,"color":"#222","save":"auto"},"mediumzoom":true,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":false,"async":false,"duration":200,"transition":{"menu_item":"fadeInDown","post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果:${query}","hits_time":"找到 ${hits} 个搜索结果(用时 ${time} 毫秒)","hits":"找到 ${hits} 个搜索结果"},"path":"/search.xml","localsearch":{"enable":true,"top_n_per_article":5,"unescape":false,"preload":false,"trigger":"auto"}}</script><script src="/js/config.js" defer></script>
<meta name="description" content="分享编程、运维、生活与思考">
<meta property="og:type" content="website">
<meta property="og:title" content="大染志">
<meta property="og:url" content="https://toozhao.com/archives/2014/08/">
<meta property="og:site_name" content="大染志">
<meta property="og:description" content="分享编程、运维、生活与思考">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="Junv">
<meta property="article:tag" content="junv, wahyd4, blog, toozhao, 大染志">
<meta name="twitter:card" content="summary">
<link rel="canonical" href="https://toozhao.com/archives/2014/08/">
<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":false,"isPost":false,"lang":"zh-CN","comments":"","permalink":"","path":"archives/2014/08/index.html","title":""}</script>
<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>归档 | 大染志</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/medium-zoom/1.1.0/medium-zoom.min.js" integrity="sha256-ZgMyDAIYDYGxbcpJcfUnYwNevG/xi9OHKaR/8GK+jWc=" crossorigin="anonymous" defer></script>
<script src="/js/utils.js" defer></script><script src="/js/sidebar.js" defer></script><script src="/js/next-boot.js" defer></script><script src="/js/bookmark.js" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/hexo-generator-searchdb/1.5.0/search.js" integrity="sha256-xFC6PJ82SL9b3WkGjFavNiA9gm5z6UBxWPiu4CYjptg=" crossorigin="anonymous" defer></script>
<script src="/js/third-party/search/local-search.js" defer></script>
<style>
/* =========================================================
Toozhao blog custom styles (injected via head.njk)
阅读体验优化 — 微信读书风格
========================================================= */
html { scroll-behavior: smooth; }
/* 主内容阅读宽度 */
.post-block, .posts-expand .post-block {
max-width: 760px;
}
.post-title {
font-size: 1.7em;
font-weight: 700;
letter-spacing: 0.01em;
}
.post-meta { color: #999; font-size: 0.9em; }
.post-body {
font-size: 1.05em;
line-height: 1.9;
letter-spacing: 0.02em;
color: #333;
}
.post-body p {
margin: 1.1em 0;
text-align: justify;
text-justify: inter-ideograph;
}
.post-body h1, .post-body h2, .post-body h3, .post-body h4, .post-body h5, .post-body h6 {
line-height: 1.4;
margin-top: 1.6em;
margin-bottom: 0.8em;
font-weight: 600;
color: #222;
}
.post-body h2::before, .post-body h3::before, .post-body h4::before {
content: '';
display: inline-block;
width: 4px;
height: 0.9em;
background: #4a90d9;
border-radius: 2px;
margin-right: 10px;
vertical-align: -0.08em;
}
.post-body img {
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
margin: 0.6em auto;
display: block;
max-width: 100%;
}
.post-body blockquote {
border-left: 4px solid #4a90d9;
background: rgba(74, 144, 217, 0.06);
margin: 1.4em 0;
padding: 0.8em 1.2em;
border-radius: 0 8px 8px 0;
color: #555;
}
.post-body blockquote p { margin: 0.4em 0; }
.post-body a {
color: #2d6cdf;
border-bottom: 1px solid rgba(45, 108, 223, 0.3);
transition: color 0.2s, border-color 0.2s;
}
.post-body a:hover { color: #1a4fae; border-bottom-color: #1a4fae; }
.post-body code {
background: rgba(0, 0, 0, 0.05);
border-radius: 4px;
padding: 2px 6px;
font-size: 0.9em;
color: #c7254e;
}
.post-body table {
border-collapse: collapse;
margin: 1.2em auto;
font-size: 0.95em;
}
.post-body table th, .post-body table td {
border: 1px solid #ddd;
padding: 8px 14px;
}
.post-body table th { background: #f5f7fa; font-weight: 600; }
.post-body table tr:nth-child(even) { background: #fafbfc; }
.post-body ul, .post-body ol { padding-left: 1.6em; margin: 0.8em 0; }
.post-body ul li, .post-body ol li { margin: 0.35em 0; }
.post-body hr {
border: none;
border-top: 1px dashed #ccc;
margin: 2em auto;
width: 60%;
}
/* 暗色模式(跟随系统,不依赖 NexT darkmode class */
@media (prefers-color-scheme: dark) {
body { background: #1b1f24; color: #c8cdd3; }
.post-body { color: #c8cdd3; }
.post-body h1, .post-body h2, .post-body h3, .post-body h4, .post-body h5, .post-body h6 { color: #e8eaed; }
.post-body blockquote { background: rgba(74, 144, 217, 0.1); color: #9aa5b1; }
.post-body code { background: rgba(255, 255, 255, 0.1); color: #e88388; }
.post-body table th, .post-body table td { border-color: #3a3f45; }
.post-body table th { background: #2d3238; }
.post-body table tr:nth-child(even) { background: #262a2f; }
.post-meta { color: #777; }
}
::selection { background: rgba(74, 144, 217, 0.25); }
/* =========================================================
阅读设置(Aa 悬浮按钮 + 面板)— 参考 Links Reading settings
========================================================= */
/* 悬浮按钮:左下,与 sidebar-toggle 排成一列 */
.reading-toggle {
position: fixed;
left: 24px;
bottom: 108px;
z-index: 1000;
width: 34px;
height: 34px;
border-radius: 50%;
background: rgba(0, 0, 0, 0.65);
color: #fff;
font-family: Georgia, "Times New Roman", serif;
font-size: 16px;
font-weight: 700;
font-style: italic;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
user-select: none;
border: none;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.28);
transition: background 0.2s, transform 0.2s;
}
.reading-toggle:hover { background: #4a90d9; transform: scale(1.1); }
.reading-toggle.active { background: #4a90d9; }
/* 设置面板 */
.reading-panel {
position: fixed;
left: 68px;
bottom: 108px;
z-index: 1001;
width: 268px;
background: #fff;
border-radius: 14px;
box-shadow: 0 14px 44px rgba(0, 0, 0, 0.2);
padding: 16px 18px 14px;
font-size: 13px;
color: #333;
display: none;
transform-origin: bottom left;
animation: rpIn 0.18s ease;
}
.reading-panel.open { display: block; }
@keyframes rpIn {
from { opacity: 0; transform: translateY(8px) scale(0.96); }
to { opacity: 1; transform: none; }
}
.reading-panel h4 {
margin: 0 0 8px;
font-size: 11px;
font-weight: 700;
letter-spacing: 0.1em;
color: #9aa0a8;
text-transform: uppercase;
}
.reading-panel .rp-row { margin-bottom: 15px; }
.reading-panel .rp-row:last-of-type { margin-bottom: 10px; }
/* 主题色 swatch */
.rp-themes { display: flex; gap: 8px; }
.rp-themes .sw {
flex: 1;
border: 2px solid transparent;
border-radius: 10px;
padding: 6px 4px 5px;
cursor: pointer;
background: none;
font-size: 12px;
color: #666;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
transition: border-color 0.15s;
}
.rp-themes .sw span {
display: block;
width: 30px;
height: 22px;
border-radius: 6px;
border: 1px solid rgba(0, 0, 0, 0.12);
}
.rp-themes .sw.active { border-color: #4a90d9; color: #4a90d9; font-weight: 600; }
.sw-light span { background: #ffffff; }
.sw-paper span { background: #f7f0e4; }
.sw-green span { background: #e2efe4; }
.sw-night span { background: #1b1f24; }
/* 字体选项 */
.rp-fonts { display: flex; flex-wrap: wrap; gap: 6px; }
.rp-fonts button {
flex: 1 1 40%;
border: 1px solid #e2e5ea;
background: #f8f9fb;
border-radius: 8px;
padding: 6px 4px;
font-size: 12.5px;
color: #444;
cursor: pointer;
transition: all 0.15s;
}
.rp-fonts button.active { background: #eaf2fd; border-color: #4a90d9; color: #2d6cdf; font-weight: 600; }
.rp-fonts button:nth-child(n+5) { flex-basis: 100%; }
/* 字号 */
.rp-size { display: flex; align-items: center; gap: 10px; }
.rp-size button {
width: 36px;
height: 30px;
border-radius: 8px;
border: 1px solid #e2e5ea;
background: #f8f9fb;
font-size: 14px;
color: #444;
cursor: pointer;
transition: all 0.15s;
}
.rp-size button:hover { background: #eaf2fd; border-color: #4a90d9; color: #2d6cdf; }
.rp-size-val {
flex: 1;
text-align: center;
font-size: 13.5px;
font-weight: 600;
color: #555;
background: #f8f9fb;
border-radius: 8px;
padding: 5px 0;
}
/* 行距 */
.rp-spacing { display: flex; gap: 6px; }
.rp-spacing button {
flex: 1;
border: 1px solid #e2e5ea;
background: #f8f9fb;
border-radius: 8px;
padding: 6px 0;
font-size: 12.5px;
color: #444;
cursor: pointer;
transition: all 0.15s;
}
.rp-spacing button.active { background: #eaf2fd; border-color: #4a90d9; color: #2d6cdf; font-weight: 600; }
/* 重置 */
.rp-reset {
width: 100%;
border: none;
background: none;
color: #9aa0a8;
font-size: 12.5px;
padding: 8px 0 2px;
cursor: pointer;
border-top: 1px solid #eef0f3;
margin-top: 2px;
transition: color 0.15s;
}
.rp-reset:hover { color: #4a90d9; }
/* ---- 阅读主题应用 ---- */
body[data-rtheme="paper"] { background: #f7f0e4 !important; }
body[data-rtheme="paper"] .post-body { color: #4a4238; }
body[data-rtheme="paper"] .post-body h1, body[data-rtheme="paper"] .post-body h2,
body[data-rtheme="paper"] .post-body h3, body[data-rtheme="paper"] .post-body h4,
body[data-rtheme="paper"] .post-body h5, body[data-rtheme="paper"] .post-body h6 { color: #3a332b; }
body[data-rtheme="paper"] .post-body a { color: #8a5a2b; border-bottom-color: rgba(138, 90, 43, 0.3); }
body[data-rtheme="paper"] .post-body a:hover { color: #6b4420; }
body[data-rtheme="paper"] .post-body blockquote { background: rgba(138, 90, 43, 0.07); color: #6b5d4a; }
body[data-rtheme="paper"] .post-body code { background: rgba(0, 0, 0, 0.06); color: #8a4a3a; }
body[data-rtheme="paper"] .post-body table th { background: #efe7d5; }
body[data-rtheme="paper"] .post-body table tr:nth-child(even) { background: #f4ede0; }
body[data-rtheme="paper"] .reading-panel { background: #fdfaf3; color: #4a4238; }
body[data-rtheme="green"] { background: #e2efe4 !important; }
body[data-rtheme="green"] .post-body { color: #2f4a36; }
body[data-rtheme="green"] .post-body h1, body[data-rtheme="green"] .post-body h2,
body[data-rtheme="green"] .post-body h3, body[data-rtheme="green"] .post-body h4,
body[data-rtheme="green"] .post-body h5, body[data-rtheme="green"] .post-body h6 { color: #23402c; }
body[data-rtheme="green"] .post-body a { color: #1d6b3c; border-bottom-color: rgba(29, 107, 60, 0.3); }
body[data-rtheme="green"] .post-body a:hover { color: #14522d; }
body[data-rtheme="green"] .post-body blockquote { background: rgba(29, 107, 60, 0.08); color: #41604c; }
body[data-rtheme="green"] .post-body code { background: rgba(0, 0, 0, 0.05); color: #1d6b3c; }
body[data-rtheme="green"] .post-body table th { background: #d4e8d8; }
body[data-rtheme="green"] .post-body table tr:nth-child(even) { background: #dcecdd; }
body[data-rtheme="green"] .reading-panel { background: #f0f8f1; color: #2f4a36; }
body[data-rtheme="night"] { background: #1b1f24 !important; }
body[data-rtheme="night"] .post-body { color: #c8cdd3; }
body[data-rtheme="night"] .post-body h1, body[data-rtheme="night"] .post-body h2,
body[data-rtheme="night"] .post-body h3, body[data-rtheme="night"] .post-body h4,
body[data-rtheme="night"] .post-body h5, body[data-rtheme="night"] .post-body h6 { color: #e8eaed; }
body[data-rtheme="night"] .post-body a { color: #7ba6f0; border-bottom-color: rgba(123, 166, 240, 0.35); }
body[data-rtheme="night"] .post-body a:hover { color: #a5c4f5; }
body[data-rtheme="night"] .post-body blockquote { background: rgba(123, 166, 240, 0.1); color: #9aa5b1; }
body[data-rtheme="night"] .post-body code { background: rgba(255, 255, 255, 0.1); color: #e88388; }
body[data-rtheme="night"] .post-body table th, body[data-rtheme="night"] .post-body table td { border-color: #3a3f45; }
body[data-rtheme="night"] .post-body table th { background: #2d3238; }
body[data-rtheme="night"] .post-body table tr:nth-child(even) { background: #262a2f; }
body[data-rtheme="night"] .reading-toggle { background: rgba(255, 255, 255, 0.14); }
body[data-rtheme="night"] .reading-panel { background: #23282e; color: #c8cdd3; }
body[data-rtheme="night"] .reading-panel h4 { color: #7a828c; }
body[data-rtheme="night"] .rp-fonts button, body[data-rtheme="night"] .rp-size button,
body[data-rtheme="night"] .rp-spacing button { background: #2d333a; border-color: #3a414a; color: #c8cdd3; }
body[data-rtheme="night"] .rp-fonts button.active, body[data-rtheme="night"] .rp-size button:hover,
body[data-rtheme="night"] .rp-spacing button.active { background: #35465c; border-color: #4a90d9; color: #9dc0f0; }
body[data-rtheme="night"] .rp-size-val { background: #2d333a; color: #c8cdd3; }
body[data-rtheme="night"] .rp-themes .sw { color: #9aa5b1; }
body[data-rtheme="night"] .rp-reset { border-top-color: #333a42; color: #7a828c; }
/* 移动端:按钮缩小、面板右移防溢出 */
@media (max-width: 600px) {
.reading-toggle { left: 16px; bottom: 96px; width: 32px; height: 32px; }
.reading-panel { left: 56px; bottom: 96px; width: 240px; }
}
</style>
<link rel="stylesheet" href="/css/tag-cloud.css">
<noscript>
<link rel="stylesheet" href="/css/noscript.css">
</noscript>
</head>
<body itemscope itemtype="http://schema.org/WebPage">
<div class="headband"></div>
<main class="main">
<div class="column">
<header class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="site-brand-container">
<div class="site-nav-toggle">
<div class="toggle" aria-label="切换导航栏" role="button">
<span class="toggle-line"></span>
<span class="toggle-line"></span>
<span class="toggle-line"></span>
</div>
</div>
<div class="site-meta">
<a href="/" class="brand" rel="start">
<i class="logo-line"></i>
<h1 class="site-title">大染志</h1>
<i class="logo-line"></i>
</a>
<p class="site-subtitle" itemprop="description">Junv's blog</p>
</div>
<div class="site-nav-right">
<div class="toggle popup-trigger" aria-label="搜索" role="button">
<i class="fa fa-search fa-fw fa-lg"></i>
</div>
</div>
</div>
<nav class="site-nav">
<ul class="main-menu menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a></li><li class="menu-item menu-item-tags"><a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a></li><li class="menu-item menu-item-archives"><a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a></li><li class="menu-item menu-item-about"><a href="/about/" rel="section"><i class="fa fa-user fa-fw"></i>关于</a></li>
<li class="menu-item menu-item-search">
<a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
</a>
</li>
</ul>
</nav>
<div class="search-pop-overlay">
<div class="popup search-popup">
<div class="search-header">
<span class="search-icon">
<i class="fa fa-search"></i>
</span>
<div class="search-input-container">
<input autocomplete="off" autocapitalize="off" maxlength="80"
placeholder="搜索..." spellcheck="false"
type="search" class="search-input">
</div>
<span class="popup-btn-close" role="button">
<i class="fa fa-times-circle"></i>
</span>
</div>
<div class="search-result-container">
<div class="search-result-icon">
<i class="fa fa-spinner fa-pulse fa-5x"></i>
</div>
</div>
</div>
</div>
</header>
<aside class="sidebar">
<div class="sidebar-inner sidebar-overview-active">
<ul class="sidebar-nav">
<li class="sidebar-nav-toc">
文章目录
</li>
<li class="sidebar-nav-overview">
站点概览
</li>
</ul>
<div class="sidebar-panel-container">
<!--noindex-->
<div class="post-toc-wrap sidebar-panel">
</div>
<!--/noindex-->
<div class="site-overview-wrap sidebar-panel">
<div class="site-author animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
<img class="site-author-image" itemprop="image" alt="Junv"
src="/images/avatar.gif">
<p class="site-author-name" itemprop="name">Junv</p>
<div class="site-description" itemprop="description">分享编程、运维、生活与思考</div>
</div>
<div class="site-state-wrap animated">
<nav class="site-state">
<div class="site-state-item site-state-posts">
<a href="/archives/">
<span class="site-state-item-count">310</span>
<span class="site-state-item-name">日志</span>
</a>
</div>
<div class="site-state-item site-state-tags">
<a href="/tags/">
<span class="site-state-item-count">249</span>
<span class="site-state-item-name">标签</span></a>
</div>
</nav>
</div>
<div class="links-of-author animated">
<span class="links-of-author-item">
<a href="https://github.com/wahyd4" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;wahyd4" rel="noopener me" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
</span>
</div>
<div class="cc-license animated" itemprop="license">
<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" class="cc-opacity" rel="noopener" target="_blank"><img src="https://cdnjs.cloudflare.com/ajax/libs/creativecommons-vocabulary/2020.11.3/assets/license_badges/small/by_nc_sa.svg" alt="Creative Commons"></a>
</div>
</div>
</div>
</div>
</aside>
</div>
<div class="main-inner archive posts-collapse">
<div class="post-block">
<div class="post-content">
<div class="collection-title">
<span class="collection-header">太棒了! 目前共计 310 篇日志。 继续努力。</span>
</div>
<div class="collection-year">
<span class="collection-header">2014<span class="collection-year-count">5</span></span>
</div>
<article itemscope itemtype="http://schema.org/Article">
<header class="post-header">
<div class="post-meta-container">
<time itemprop="dateCreated"
datetime="2014-08-31T20:26:00+10:00"
content="2014-08-31">
08-31
</time>
</div>
<div class="post-title">
<a class="post-title-link" href="/2014/08/31/improve-the-load-speed-of-blog/" itemprop="url">
<span itemprop="name">使用七牛云提升博客加载速度</span>
</a>
</div>
</header>
</article>
</div>
</div>
</div>
</main>
<footer class="footer">
<div class="footer-inner">
<div class="copyright">
&copy; 2012
<span itemprop="copyrightYear">2026</span>
<span class="with-love">
<i class="fa fa-heart"></i>
</span>
<span class="author" itemprop="copyrightHolder">Junv</span>
</div>
<div class="powered-by"><a href="https://hexo.io/" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.js.org/muse/" rel="noopener" target="_blank">NexT.Muse</a> 强力驱动
</div>
</div>
</footer>
<div class="toggle sidebar-toggle" role="button">
<span class="toggle-line"></span>
<span class="toggle-line"></span>
<span class="toggle-line"></span>
</div>
<div class="sidebar-dimmer"></div>
<div class="back-to-top" role="button" aria-label="返回顶部">
<i class="fa fa-arrow-up fa-lg"></i>
<span>0%</span>
</div>
<div class="reading-progress-bar"></div>
<a role="button" class="book-mark-link book-mark-link-fixed"></a>
<noscript>
<div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>
<script src="/js/tag-cloud.js"></script>
<script>
/* =========================================================
阅读设置面板(Aa 按钮)— 参考 Links Reading settings
支持:背景主题 / 字体类型 / 字号 / 行距 / 重置,localStorage 记忆
========================================================= */
(function () {
'use strict';
var LS_KEY = 'toozhao-reading';
var state = { theme: 'light', font: 'system', size: 1.05, spacing: 'cozy' };
var FONTS = {
system: '', /* 默认(Linux 系统字体) */
serif: 'Georgia, "Noto Serif SC", "Source Han Serif SC", "Songti SC", SimSun, serif',
sans: '"Noto Sans SC", "Source Han Sans SC", "Microsoft YaHei", "PingFang SC", "WenQuanYi Micro Hei", sans-serif',
kai: '"KaiTi", "STKaiti", "Kaiti SC", "AR PL UKai CN", serif',
mono: 'SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace'
};
var THEMES = { light: '明亮', paper: '纸感', green: '护眼', night: '夜间' };
var SPACING = {
compact: { label: '紧凑', lh: 1.6 },
cozy: { label: '舒适', lh: 1.9 },
relaxed: { label: '宽松', lh: 2.3 }
};
function loadState() {
try {
var raw = localStorage.getItem(LS_KEY);
if (!raw) return;
var s = JSON.parse(raw);
if (THEMES[s.theme]) state.theme = s.theme;
if (FONTS.hasOwnProperty(s.font)) state.font = s.font;
if (typeof s.size === 'number' && s.size >= 0.8 && s.size <= 1.5) state.size = s.size;
if (SPACING[s.spacing]) state.spacing = s.spacing;
} catch (e) { /* ignore */ }
}
function saveState() {
try { localStorage.setItem(LS_KEY, JSON.stringify(state)); } catch (e) { /* ignore */ }
}
function buildUI() {
if (document.getElementById('reading-toggle')) return;
var toggle = document.createElement('button');
toggle.id = 'reading-toggle';
toggle.className = 'reading-toggle';
toggle.title = '阅读设置';
toggle.textContent = 'Aa';
document.body.appendChild(toggle);
var panel = document.createElement('div');
panel.id = 'reading-panel';
panel.className = 'reading-panel';
// 主题(swatch 全部为硬编码静态 HTML,无用户输入,安全)
var rowT = document.createElement('div');
rowT.className = 'rp-row';
rowT.innerHTML = '<h4>主题</h4><div class="rp-themes">' +
['light', 'paper', 'green', 'night'].map(function (t) {
return '<button class="sw sw-' + t + '" data-theme="' + t + '" title="' + THEMES[t] + '"><span></span>' + THEMES[t] + '</button>';
}).join('') + '</div>';
var rowF = document.createElement('div');
rowF.className = 'rp-row';
rowF.innerHTML = '<h4>字体</h4><div class="rp-fonts">' +
['system', 'serif', 'sans', 'kai', 'mono'].map(function (f) {
var label = { system: '系统', serif: '宋体', sans: '黑体', kai: '楷体', mono: '等宽' }[f];
return '<button data-font="' + f + '">' + label + '</button>';
}).join('') + '</div>';
var rowS = document.createElement('div');
rowS.className = 'rp-row';
rowS.innerHTML = '<h4>字号</h4><div class="rp-size">' +
'<button class="rp-minus" title="减小">A</button><span class="rp-size-val">17px</span><button class="rp-plus" title="增大">A+</button></div>';
var rowSp = document.createElement('div');
rowSp.className = 'rp-row';
rowSp.innerHTML = '<h4>行距</h4><div class="rp-spacing">' +
['compact', 'cozy', 'relaxed'].map(function (s) {
return '<button data-spacing="' + s + '">' + SPACING[s].label + '</button>';
}).join('') + '</div>';
var reset = document.createElement('button');
reset.className = 'rp-reset';
reset.textContent = '↺ 恢复默认';
reset.addEventListener('click', function () {
state = { theme: 'light', font: 'system', size: 1.05, spacing: 'cozy' };
saveState();
apply();
render();
});
panel.appendChild(rowT);
panel.appendChild(rowF);
panel.appendChild(rowS);
panel.appendChild(rowSp);
panel.appendChild(reset);
document.body.appendChild(panel);
toggle.addEventListener('click', function (e) {
e.stopPropagation();
panel.classList.toggle('open');
toggle.classList.toggle('active', panel.classList.contains('open'));
});
panel.addEventListener('click', function (e) { e.stopPropagation(); });
panel.querySelectorAll('.sw').forEach(function (b) {
b.addEventListener('click', function () { state.theme = b.dataset.theme; saveState(); apply(); render(); });
});
panel.querySelectorAll('.rp-fonts button').forEach(function (b) {
b.addEventListener('click', function () { state.font = b.dataset.font; saveState(); apply(); render(); });
});
panel.querySelectorAll('.rp-spacing button').forEach(function (b) {
b.addEventListener('click', function () { state.spacing = b.dataset.spacing; saveState(); apply(); render(); });
});
panel.querySelector('.rp-minus').addEventListener('click', function () {
state.size = Math.max(0.8, +(state.size - 0.05).toFixed(2)); saveState(); apply(); render();
});
panel.querySelector('.rp-plus').addEventListener('click', function () {
state.size = Math.min(1.5, +(state.size + 0.05).toFixed(2)); saveState(); apply(); render();
});
document.addEventListener('click', function (e) {
if (panel.classList.contains('open') && !panel.contains(e.target) && e.target !== toggle) {
panel.classList.remove('open');
toggle.classList.remove('active');
}
});
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && panel.classList.contains('open')) {
panel.classList.remove('open');
toggle.classList.remove('active');
}
});
}
function apply() {
var body = document.body;
var pb = document.querySelector('.post-body');
body.setAttribute('data-rtheme', state.theme);
if (pb) {
pb.style.fontFamily = FONTS[state.font] || '';
pb.style.fontSize = state.size + 'em';
pb.style.lineHeight = SPACING[state.spacing].lh;
}
}
function render() {
var panel = document.getElementById('reading-panel');
if (!panel) return;
panel.querySelectorAll('.sw').forEach(function (b) {
b.classList.toggle('active', b.dataset.theme === state.theme);
});
panel.querySelectorAll('.rp-fonts button').forEach(function (b) {
b.classList.toggle('active', b.dataset.font === state.font);
});
panel.querySelectorAll('.rp-spacing button').forEach(function (b) {
b.classList.toggle('active', b.dataset.spacing === state.spacing);
});
var val = panel.querySelector('.rp-size-val');
if (val) val.textContent = Math.round(16 * state.size) + 'px';
}
function init() {
loadState();
buildUI();
apply();
render();
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();
</script>
</body>
</html>