diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..bb14cf9
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "Codegeex.RepoIndex": true
+}
\ No newline at end of file
diff --git a/src/blog/static/blog/css/archives-style.css b/src/blog/static/blog/css/archives-style.css
new file mode 100644
index 0000000..3c29318
--- /dev/null
+++ b/src/blog/static/blog/css/archives-style.css
@@ -0,0 +1,162 @@
+
+/* 文章归档页面样式 */
+
+/* 归档标题样式 */
+.archive-header {
+ margin-bottom: 2rem;
+ padding: 1.5rem;
+ background: linear-gradient(135deg, var(--primary-color), #2980b9);
+ border-radius: 8px;
+ box-shadow: var(--box-shadow);
+ position: relative;
+ overflow: hidden;
+}
+
+.archive-header::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: url('data:image/svg+xml;utf8,');
+ background-size: 100px 100px;
+ opacity: 0.5;
+}
+
+.archive-title {
+ font-size: 1.8rem;
+ font-weight: 600;
+ color: #fff;
+ margin: 0;
+ position: relative;
+ z-index: 1;
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+/* 归档内容样式 */
+.entry-content {
+ background-color: #fff;
+ border-radius: 8px;
+ box-shadow: var(--box-shadow);
+ padding: 2rem;
+}
+
+/* 年份样式 */
+.archive-year {
+ margin-bottom: 1.5rem;
+ list-style-type: none;
+ position: relative;
+ padding-left: 2.5rem;
+}
+
+.archive-year::before {
+ content: '📅';
+ position: absolute;
+ left: 0;
+ top: 0.5rem;
+ width: 1.5rem;
+ height: 1.5rem;
+ background-color: var(--primary-color);
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: #fff;
+ font-weight: bold;
+ font-size: 0.8rem;
+}
+
+.year-label {
+ font-size: 1.3rem;
+ font-weight: 600;
+ color: var(--dark-color);
+ margin-bottom: 0.5rem;
+ display: block;
+}
+
+/* 月份样式 */
+.archive-month {
+ margin-bottom: 1rem;
+ list-style-type: none;
+ position: relative;
+ padding-left: 2rem;
+}
+
+.archive-month::before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0.5rem;
+ width: 0.8rem;
+ height: 0.8rem;
+ background-color: var(--secondary-color);
+ border-radius: 50%;
+}
+
+.month-label {
+ font-size: 1.1rem;
+ font-weight: 500;
+ color: var(--dark-color);
+ margin-bottom: 0.5rem;
+ display: block;
+}
+
+/* 文章列表样式 */
+.article-list {
+ margin-top: 0.5rem;
+ padding-left: 1rem;
+}
+
+.article-list > li {
+ margin-bottom: 0.5rem;
+ list-style-type: none;
+ position: relative;
+ padding-left: 1.5rem;
+}
+
+.article-list > li::before {
+ content: '📄';
+ position: absolute;
+ left: 0;
+ top: 0.2rem;
+ font-size: 0.9rem;
+}
+
+.article-list > li a {
+ color: var(--text-color);
+ text-decoration: none;
+ transition: var(--transition);
+ display: inline-block;
+ padding: 0.3rem 0.5rem;
+ border-radius: 4px;
+}
+
+.article-list > li a:hover {
+ color: var(--primary-color);
+ background-color: rgba(52, 152, 219, 0.1);
+ transform: translateX(5px);
+}
+
+/* 响应式设计 */
+@media screen and (max-width: 768px) {
+ .archive-header {
+ padding: 1rem;
+ }
+
+ .archive-title {
+ font-size: 1.5rem;
+ }
+
+ .entry-content {
+ padding: 1rem;
+ }
+
+ .entry-content > ul > li {
+ padding-left: 2rem;
+ }
+
+ .entry-content > ul > li > ul > li {
+ padding-left: 1.5rem;
+ }
+}
diff --git a/src/blog/static/blog/css/background-options.css b/src/blog/static/blog/css/background-options.css
new file mode 100644
index 0000000..761bf11
--- /dev/null
+++ b/src/blog/static/blog/css/background-options.css
@@ -0,0 +1,22 @@
+
+/* 网页背景选项 - 默认背景和自定义图片背景 */
+
+/* 自定义图片背景 - 请将图片放在 /blog/static/blog/images/ 目录下 */
+.bg-custom-image {
+ background-image: url('{% static "blog/images/background.jpg" %}');
+ background-attachment: fixed;
+ background-size: cover;
+ background-position: center;
+}
+
+/* 半透明遮罩层,用于自定义图片背景上 */
+.bg-overlay::before {
+ content: '';
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(255, 255, 255, 0.7);
+ z-index: -1;
+}
diff --git a/src/blog/static/blog/css/modern-style.css b/src/blog/static/blog/css/modern-style.css
new file mode 100644
index 0000000..e80444d
--- /dev/null
+++ b/src/blog/static/blog/css/modern-style.css
@@ -0,0 +1,640 @@
+
+/* 现代化样式 - DjangoBlog美化 */
+
+/* 全局变量 */
+:root {
+ --primary-color: #3498db;
+ --secondary-color: #2c3e50;
+ --accent-color: #e74c3c;
+ --light-color: #ecf0f1;
+ --dark-color: #2c3e50;
+ --text-color: #333;
+ --text-light: #777;
+ --border-color: #ddd;
+ --box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+ --transition: all 0.3s ease;
+}
+
+/* 基础样式重置和优化 */
+body {
+ font-family: 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif;
+ line-height: 1.6;
+ color: var(--text-color);
+ background-color: #f8f9fa;
+ background-image: url('data:image/svg+xml;utf8,');
+ background-attachment: fixed;
+ background-size: 100px 100px;
+}
+
+/* 网站容器 */
+.site {
+ max-width: 1200px;
+ margin: 0 auto;
+ background-color: #fff;
+ box-shadow: var(--box-shadow);
+ border-radius: 8px;
+ overflow: hidden;
+}
+
+/* 头部样式 */
+.site-header {
+ background: linear-gradient(135deg, var(--secondary-color), var(--primary-color));
+ color: #fff;
+ padding: 3rem 2rem;
+ text-align: center;
+ position: relative;
+ overflow: hidden;
+}
+
+.site-header::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: url('data:image/svg+xml,') no-repeat bottom;
+ background-size: cover;
+ opacity: 0.5;
+}
+
+.site-header h1, .site-header h2 {
+ position: relative;
+ z-index: 1;
+ margin: 0;
+ padding: 0;
+}
+
+.site-header h1 {
+ font-size: 2.5rem;
+ font-weight: 700;
+ margin-bottom: 0.5rem;
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+}
+
+.site-header h1 a {
+ color: #fff;
+ text-decoration: none;
+ transition: var(--transition);
+}
+
+.site-header h1 a:hover {
+ opacity: 0.8;
+ transform: translateY(-2px);
+}
+
+.site-header h2 {
+ font-size: 1.2rem;
+ font-weight: 300;
+ opacity: 0.9;
+}
+
+/* 导航菜单样式 */
+.main-navigation {
+ background-color: #fff;
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
+ position: sticky;
+ top: 0;
+ z-index: 100;
+ border-top: 1px solid var(--border-color);
+}
+
+.main-navigation ul.nav-menu {
+ display: flex;
+ justify-content: center;
+ flex-wrap: wrap;
+ padding: 0;
+ margin: 0;
+ list-style: none;
+}
+
+.main-navigation li {
+ margin: 0;
+ position: relative;
+}
+
+.main-navigation a {
+ display: block;
+ padding: 1rem 1.5rem;
+ color: var(--dark-color);
+ text-decoration: none;
+ font-weight: 500;
+ transition: var(--transition);
+ position: relative;
+}
+
+.main-navigation a::after {
+ content: '';
+ position: absolute;
+ bottom: 0;
+ left: 50%;
+ width: 0;
+ height: 3px;
+ background-color: var(--primary-color);
+ transition: var(--transition);
+ transform: translateX(-50%);
+}
+
+.main-navigation a:hover::after,
+.main-navigation a:focus::after {
+ width: 80%;
+}
+
+.main-navigation a:hover,
+.main-navigation a:focus {
+ color: var(--primary-color);
+}
+
+/* 主要内容区域 - 保持经典两栏布局 */
+#main {
+ display: flex;
+ padding: 2rem;
+ gap: 2rem;
+}
+
+#primary {
+ flex: 0 0 65%;
+ max-width: 65%;
+}
+
+/* 文章样式 - 优化列表布局 */
+article {
+ margin-bottom: 2rem;
+ padding: 1.5rem;
+ background-color: #fff;
+ border-radius: 8px;
+ box-shadow: var(--box-shadow);
+ transition: var(--transition);
+ border-left: 4px solid var(--primary-color);
+}
+
+article:hover {
+ transform: translateY(-3px);
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
+}
+
+.entry-header {
+ margin-bottom: 1.5rem;
+ border-bottom: 1px solid var(--border-color);
+ padding-bottom: 1rem;
+}
+
+.entry-title {
+ font-size: 1.8rem;
+ margin-bottom: 0.5rem;
+ line-height: 1.3;
+}
+
+.entry-title a {
+ color: var(--dark-color);
+ text-decoration: none;
+ transition: var(--transition);
+}
+
+.entry-title a:hover {
+ color: var(--primary-color);
+}
+
+.entry-meta {
+ color: var(--text-light);
+ font-size: 0.9rem;
+ margin-bottom: 1rem;
+}
+
+.entry-meta a {
+ color: var(--primary-color);
+ text-decoration: none;
+}
+
+.entry-meta a:hover {
+ text-decoration: underline;
+}
+
+.entry-content {
+ line-height: 1.7;
+}
+
+.entry-content p {
+ margin-bottom: 1.2rem;
+}
+
+.entry-content img {
+ max-width: 100%;
+ height: auto;
+ border-radius: 4px;
+ margin: 1.5rem 0;
+}
+
+.read-more {
+ display: inline-block;
+ margin-top: 1rem;
+ padding: 0.5rem 1.2rem;
+ background-color: var(--primary-color);
+ color: #fff;
+ border-radius: 4px;
+ text-decoration: none;
+ transition: var(--transition);
+ font-weight: 500;
+}
+
+.read-more:hover {
+ background-color: #2980b9;
+ transform: translateY(-2px);
+}
+
+/* 侧边栏样式 - 保持右侧布局并优化外观 */
+.widget-area {
+ flex: 0 0 30%;
+ max-width: 30%;
+}
+
+.widget {
+ margin-bottom: 2rem;
+ background-color: #fff;
+ border-radius: 8px;
+ box-shadow: var(--box-shadow);
+ padding: 1.5rem;
+ border-top: 3px solid var(--primary-color);
+ transition: var(--transition);
+}
+
+.widget:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
+}
+
+.widget-title {
+ font-size: 1.2rem;
+ margin-bottom: 1rem;
+ padding-bottom: 0.5rem;
+ border-bottom: 2px solid var(--primary-color);
+ color: var(--dark-color);
+ position: relative;
+ padding-left: 10px;
+}
+
+.widget-title::before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: 0.5rem;
+ width: 4px;
+ background-color: var(--primary-color);
+ border-radius: 2px;
+}
+
+.widget ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.widget li {
+ margin-bottom: 0.5rem;
+ padding-bottom: 0.5rem;
+ border-bottom: 1px solid var(--border-color);
+}
+
+.widget li:last-child {
+ border-bottom: none;
+}
+
+.widget a {
+ color: var(--text-color);
+ text-decoration: none;
+ transition: var(--transition);
+}
+
+.widget a:hover {
+ color: var(--primary-color);
+}
+
+/* 分页样式 */
+.pagination {
+ margin: 2rem 0;
+ display: flex;
+ justify-content: center;
+ gap: 0.5rem;
+}
+
+.pagination a, .pagination span {
+ display: block;
+ padding: 0.5rem 1rem;
+ border: 1px solid var(--border-color);
+ border-radius: 4px;
+ text-decoration: none;
+ transition: var(--transition);
+}
+
+.pagination a:hover {
+ background-color: var(--primary-color);
+ color: #fff;
+ border-color: var(--primary-color);
+}
+
+.pagination span.current {
+ background-color: var(--primary-color);
+ color: #fff;
+ border-color: var(--primary-color);
+}
+
+/* 评论区域 */
+.comments-area {
+ margin-top: 2rem;
+ padding: 1.5rem;
+ background-color: #fff;
+ border-radius: 8px;
+ box-shadow: var(--box-shadow);
+}
+
+.comment-list {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.comment {
+ margin-bottom: 1.5rem;
+ padding-bottom: 1.5rem;
+ border-bottom: 1px solid var(--border-color);
+}
+
+.comment:last-child {
+ border-bottom: none;
+}
+
+.comment-author {
+ display: flex;
+ align-items: center;
+ margin-bottom: 0.5rem;
+}
+
+.comment-author img {
+ border-radius: 50%;
+ margin-right: 1rem;
+}
+
+.comment-meta {
+ font-size: 0.9rem;
+ color: var(--text-light);
+ margin-bottom: 1rem;
+}
+
+.comment-content {
+ line-height: 1.7;
+}
+
+/* 表单样式 */
+form {
+ margin-top: 1.5rem;
+}
+
+.form-group {
+ margin-bottom: 1rem;
+}
+
+label {
+ display: block;
+ margin-bottom: 0.5rem;
+ font-weight: 500;
+}
+
+input[type="text"],
+input[type="email"],
+input[type="url"],
+textarea {
+ width: 100%;
+ padding: 0.75rem;
+ border: 1px solid var(--border-color);
+ border-radius: 4px;
+ font-family: inherit;
+ font-size: 1rem;
+ transition: var(--transition);
+}
+
+input[type="text"]:focus,
+input[type="email"]:focus,
+input[type="url"]:focus,
+textarea:focus {
+ border-color: var(--primary-color);
+ outline: none;
+ box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.2);
+}
+
+textarea {
+ min-height: 120px;
+ resize: vertical;
+}
+
+button, input[type="submit"] {
+ display: inline-block;
+ padding: 0.75rem 1.5rem;
+ background-color: var(--primary-color);
+ color: #fff;
+ border: none;
+ border-radius: 4px;
+ font-family: inherit;
+ font-size: 1rem;
+ font-weight: 500;
+ cursor: pointer;
+ transition: var(--transition);
+}
+
+button:hover, input[type="submit"]:hover {
+ background-color: #2980b9;
+ transform: translateY(-2px);
+}
+
+/* 页脚样式 */
+#colophon {
+ background-color: var(--dark-color);
+ color: #fff;
+ padding: 2rem;
+ text-align: center;
+}
+
+.site-info {
+ margin-bottom: 1rem;
+}
+
+.site-info:last-child {
+ margin-bottom: 0;
+}
+
+.site-info a {
+ color: #fff;
+ text-decoration: none;
+ transition: var(--transition);
+}
+
+.site-info a:hover {
+ color: var(--primary-color);
+ text-decoration: underline;
+}
+
+/* 响应式设计 - 保持两栏布局直到移动设备 */
+@media screen and (max-width: 992px) {
+ #main {
+ flex-direction: column;
+ }
+
+ #primary {
+ flex: 0 0 100%;
+ max-width: 100%;
+ padding-right: 0;
+ margin-bottom: 2rem;
+ }
+
+ .widget-area {
+ flex: 0 0 100%;
+ max-width: 100%;
+ }
+}
+
+@media screen and (max-width: 768px) {
+ .site-header {
+ padding: 2rem 1rem;
+ }
+
+ .site-header h1 {
+ font-size: 2rem;
+ }
+
+ .main-navigation ul.nav-menu {
+ flex-direction: column;
+ }
+
+ .main-navigation li {
+ width: 100%;
+ text-align: center;
+ }
+
+ #main {
+ padding: 1rem;
+ }
+
+ article, .widget {
+ padding: 1rem;
+ }
+}
+
+@media screen and (max-width: 480px) {
+ .site-header h1 {
+ font-size: 1.5rem;
+ }
+
+ .site-header h2 {
+ font-size: 1rem;
+ }
+
+ .entry-title {
+ font-size: 1.5rem;
+ }
+}
+
+/* 动画效果 */
+@keyframes fadeIn {
+ from { opacity: 0; transform: translateY(20px); }
+ to { opacity: 1; transform: translateY(0); }
+}
+
+article {
+ animation: fadeIn 0.6s ease-out;
+}
+
+/* 滚动到顶部按钮 */
+#back-to-top {
+ position: fixed;
+ bottom: 2rem;
+ right: 2rem;
+ width: 50px;
+ height: 50px;
+ background-color: var(--primary-color);
+ color: #fff;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ text-decoration: none;
+ opacity: 0;
+ visibility: hidden;
+ transition: var(--transition);
+ z-index: 1000;
+ box-shadow: var(--box-shadow);
+}
+
+#back-to-top.visible {
+ opacity: 1;
+ visibility: visible;
+}
+
+#back-to-top:hover {
+ background-color: #2980b9;
+ transform: translateY(-5px);
+}
+
+/* 搜索框样式 - 优化为侧边栏设计 */
+.search-form {
+ position: relative;
+ margin-bottom: 1.5rem;
+}
+
+.search-form input[type="search"] {
+ width: 100%;
+ padding: 0.75rem 3rem 0.75rem 1.2rem;
+ border: 1px solid var(--border-color);
+ border-radius: 25px;
+ font-family: inherit;
+ font-size: 0.9rem;
+ transition: var(--transition);
+ background-color: #f9f9f9;
+}
+
+.search-form input[type="search"]:focus {
+ border-color: var(--primary-color);
+ outline: none;
+ box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.2);
+ background-color: #fff;
+}
+
+.search-form button {
+ position: absolute;
+ top: 50%;
+ right: 8px;
+ transform: translateY(-50%);
+ background: none;
+ border: none;
+ padding: 0.5rem;
+ color: var(--primary-color);
+ cursor: pointer;
+ border-radius: 50%;
+ transition: var(--transition);
+}
+
+.search-form button:hover {
+ background-color: rgba(52, 152, 219, 0.1);
+}
+
+/* 标签云样式 */
+.tagcloud {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.5rem;
+}
+
+.tagcloud a {
+ display: inline-block;
+ padding: 0.3rem 0.8rem;
+ background-color: var(--light-color);
+ color: var(--dark-color);
+ border-radius: 15px;
+ font-size: 0.9rem;
+ text-decoration: none;
+ transition: var(--transition);
+}
+
+.tagcloud a:hover {
+ background-color: var(--primary-color);
+ color: #fff;
+}
diff --git a/src/blog/static/blog/images/README.md b/src/blog/static/blog/images/README.md
new file mode 100644
index 0000000..8774a92
--- /dev/null
+++ b/src/blog/static/blog/images/README.md
@@ -0,0 +1,16 @@
+# 博客背景图片
+
+将您想用作背景的图片放在此目录下,然后在background-options.css中更新路径。
+
+支持的图片格式:
+- JPG
+- PNG
+- GIF
+- WebP
+
+建议的图片尺寸:
+- 宽度:1920px或更大
+- 高度:1080px或更大
+- 分辨率:72dpi或更高
+
+推荐使用有轻微纹理或图案的图片,避免过于复杂的图像,以免影响内容可读性。
diff --git a/src/blog/static/blog/images/background.jpg b/src/blog/static/blog/images/background.jpg
new file mode 100644
index 0000000..6d46d0c
Binary files /dev/null and b/src/blog/static/blog/images/background.jpg differ
diff --git a/src/blog/static/blog/js/background-switcher.js b/src/blog/static/blog/js/background-switcher.js
new file mode 100644
index 0000000..d9ef7ac
--- /dev/null
+++ b/src/blog/static/blog/js/background-switcher.js
@@ -0,0 +1,185 @@
+
+// 背景切换工具
+
+document.addEventListener('DOMContentLoaded', function() {
+ // 创建背景切换器
+ function createBackgroundSwitcher() {
+ // 创建背景切换器容器
+ const switcher = document.createElement('div');
+ switcher.className = 'bg-switcher';
+ switcher.innerHTML = `
+
+
+
选择背景
+
+
+
+
+
+ `;
+
+ // 添加样式
+ const style = document.createElement('style');
+ style.textContent = `
+ .bg-switcher {
+ position: fixed;
+ bottom: 20px;
+ left: 20px;
+ z-index: 1000;
+ }
+
+ .bg-switcher-toggle {
+ width: 50px;
+ height: 50px;
+ border-radius: 50%;
+ background-color: var(--primary-color);
+ color: white;
+ border: none;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow: var(--box-shadow);
+ transition: var(--transition);
+ }
+
+ .bg-switcher-toggle:hover {
+ background-color: #2980b9;
+ transform: scale(1.1);
+ }
+
+ .bg-switcher-panel {
+ position: absolute;
+ bottom: 60px;
+ left: 0;
+ background-color: white;
+ border-radius: 8px;
+ box-shadow: var(--box-shadow);
+ padding: 15px;
+ width: 200px;
+ opacity: 0;
+ visibility: hidden;
+ transform: translateY(10px);
+ transition: var(--transition);
+ }
+
+ .bg-switcher.active .bg-switcher-panel {
+ opacity: 1;
+ visibility: visible;
+ transform: translateY(0);
+ }
+
+ .bg-switcher-panel h4 {
+ margin: 0 0 10px;
+ font-size: 16px;
+ color: var(--dark-color);
+ }
+
+ .bg-options {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 8px;
+ }
+
+ .bg-option {
+ padding: 8px;
+ border: 1px solid var(--border-color);
+ border-radius: 4px;
+ background-color: #f9f9f9;
+ cursor: pointer;
+ transition: var(--transition);
+ font-size: 14px;
+ }
+
+ .bg-option:hover {
+ background-color: #f0f0f0;
+ border-color: var(--primary-color);
+ }
+
+ .bg-option.active {
+ background-color: var(--primary-color);
+ color: white;
+ border-color: var(--primary-color);
+ }
+ `;
+ document.head.appendChild(style);
+
+ // 添加到页面
+ document.body.appendChild(switcher);
+
+ // 切换面板显示/隐藏
+ const toggle = switcher.querySelector('.bg-switcher-toggle');
+ toggle.addEventListener('click', function() {
+ switcher.classList.toggle('active');
+ });
+
+ // 点击其他地方关闭面板
+ document.addEventListener('click', function(e) {
+ if (!switcher.contains(e.target)) {
+ switcher.classList.remove('active');
+ }
+ });
+
+ // 背景切换功能
+ const options = switcher.querySelectorAll('.bg-option');
+ options.forEach(option => {
+ option.addEventListener('click', function() {
+ // 移除所有active类
+ options.forEach(opt => opt.classList.remove('active'));
+ // 添加active类到当前选项
+ this.classList.add('active');
+
+ // 切换背景
+ const bgType = this.getAttribute('data-bg');
+ switchBackground(bgType);
+
+ // 保存用户选择
+ localStorage.setItem('preferredBackground', bgType);
+ });
+ });
+
+ // 检查用户之前的选择
+ const savedBg = localStorage.getItem('preferredBackground');
+ if (savedBg) {
+ // 设置对应的选项为active
+ options.forEach(opt => {
+ if (opt.getAttribute('data-bg') === savedBg) {
+ opt.classList.add('active');
+ } else {
+ opt.classList.remove('active');
+ }
+ });
+
+ // 应用保存的背景
+ switchBackground(savedBg);
+ }
+ }
+
+ // 切换背景函数
+ function switchBackground(bgType) {
+ const body = document.body;
+
+ // 移除所有背景类
+ body.classList.remove('bg-custom-image', 'bg-overlay');
+
+ // 根据类型添加对应的背景类
+ if (bgType === 'custom-image') {
+ body.classList.add('bg-custom-image', 'bg-overlay');
+ }
+ }
+
+ // 初始化背景切换器
+ createBackgroundSwitcher();
+});
diff --git a/src/blog/static/blog/js/modern-ui.js b/src/blog/static/blog/js/modern-ui.js
new file mode 100644
index 0000000..b78b8d8
--- /dev/null
+++ b/src/blog/static/blog/js/modern-ui.js
@@ -0,0 +1,134 @@
+
+// 现代化UI交互效果
+
+document.addEventListener('DOMContentLoaded', function() {
+ // 返回顶部按钮功能
+ const backToTopButton = document.getElementById('back-to-top');
+
+ if (backToTopButton) {
+ // 监听滚动事件
+ window.addEventListener('scroll', function() {
+ // 当页面滚动超过300px时显示返回顶部按钮
+ if (window.pageYOffset > 300) {
+ backToTopButton.classList.add('visible');
+ } else {
+ backToTopButton.classList.remove('visible');
+ }
+ });
+
+ // 点击返回顶部
+ backToTopButton.addEventListener('click', function(e) {
+ e.preventDefault();
+ window.scrollTo({
+ top: 0,
+ behavior: 'smooth'
+ });
+ });
+ }
+
+ // 为所有外部链接添加target="_blank"属性
+ const links = document.querySelectorAll('a[href^="http"]:not([href*="' + window.location.hostname + '"])');
+ links.forEach(function(link) {
+ link.setAttribute('target', '_blank');
+ link.setAttribute('rel', 'noopener noreferrer');
+ });
+
+ // 文章内容图片添加懒加载效果
+ const articleImages = document.querySelectorAll('.entry-content img');
+ if ('IntersectionObserver' in window) {
+ const imageObserver = new IntersectionObserver(function(entries, observer) {
+ entries.forEach(function(entry) {
+ if (entry.isIntersecting) {
+ const img = entry.target;
+ img.classList.add('fade-in');
+ imageObserver.unobserve(img);
+ }
+ });
+ });
+
+ articleImages.forEach(function(img) {
+ imageObserver.observe(img);
+ });
+ }
+
+ // 搜索框交互效果
+ const searchForms = document.querySelectorAll('.search-form');
+ searchForms.forEach(function(form) {
+ const input = form.querySelector('input[type="search"]');
+ const button = form.querySelector('button');
+
+ if (input && button) {
+ input.addEventListener('focus', function() {
+ form.classList.add('active');
+ });
+
+ input.addEventListener('blur', function() {
+ if (!input.value) {
+ form.classList.remove('active');
+ }
+ });
+ }
+ });
+
+ // 为代码块添加复制按钮
+ const codeBlocks = document.querySelectorAll('pre code');
+ codeBlocks.forEach(function(block) {
+ const button = document.createElement('button');
+ button.className = 'copy-button';
+ button.textContent = '复制';
+ button.setAttribute('title', '复制代码');
+
+ const pre = block.parentElement;
+ pre.style.position = 'relative';
+ pre.appendChild(button);
+
+ button.addEventListener('click', function() {
+ navigator.clipboard.writeText(block.textContent).then(function() {
+ button.textContent = '已复制!';
+ setTimeout(function() {
+ button.textContent = '复制';
+ }, 2000);
+ }).catch(function(err) {
+ console.error('复制失败:', err);
+ });
+ });
+ });
+});
+
+// 添加代码块复制按钮的CSS
+const style = document.createElement('style');
+style.textContent = `
+ .copy-button {
+ position: absolute;
+ top: 8px;
+ right: 8px;
+ background-color: rgba(0, 0, 0, 0.7);
+ color: white;
+ border: none;
+ border-radius: 4px;
+ padding: 4px 8px;
+ font-size: 12px;
+ cursor: pointer;
+ opacity: 0;
+ transition: opacity 0.2s;
+ }
+
+ pre:hover .copy-button {
+ opacity: 1;
+ }
+
+ .fade-in {
+ animation: fadeIn 0.6s ease-out;
+ }
+
+ @keyframes fadeIn {
+ from { opacity: 0; transform: translateY(20px); }
+ to { opacity: 1; transform: translateY(0); }
+ }
+
+ .search-form.active input[type="search"] {
+ border-color: var(--primary-color);
+ box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.2);
+ }
+`;
+document.head.appendChild(style);
diff --git a/src/templates/blog/article_archives.html b/src/templates/blog/article_archives.html
index 959319e..2faead5 100644
--- a/src/templates/blog/article_archives.html
+++ b/src/templates/blog/article_archives.html
@@ -20,23 +20,24 @@
-
{% regroup article_list by pub_time.year as year_post_group %}
-
+
{% for year in year_post_group %}
- - {{ year.grouper }} {% trans 'year' %}
+
-
+ {{ year.grouper }} {% trans 'year' %}
{% regroup year.list by pub_time.month as month_post_group %}
-
+
{% for month in month_post_group %}
- - {{ month.grouper }} {% trans 'month' %}
-
+ -
+ {{ month.grouper }} {% trans 'month' %}
+
{% for article in month.list %}
- - {{ article.title }}
+
-
+ {{ article.title }}
{% endfor %}
diff --git a/src/templates/share_layout/base.html b/src/templates/share_layout/base.html
index bb17933..7bac388 100644
--- a/src/templates/share_layout/base.html
+++ b/src/templates/share_layout/base.html
@@ -54,6 +54,11 @@
+
+
+ {% if request.resolver_match.url_name == 'blog:archives' %}
+
+ {% endif %}
{% block compress_css %}
{% endblock %}
@@ -101,6 +106,8 @@
+
+
{% block compress_js %}
{% endblock %}
@@ -113,6 +120,13 @@
{% block footer %}
{% endblock %}
+
+
+
+
+
{% plugin_body_resources %}