Compare commits
54 Commits
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
from django import forms
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from .models import ArticleImage
|
||||||
|
|
||||||
|
|
||||||
|
class ImageUploadForm(forms.ModelForm):
|
||||||
|
"""图片上传表单"""
|
||||||
|
class Meta:
|
||||||
|
model = ArticleImage
|
||||||
|
fields = ['image', 'description']
|
||||||
|
widgets = {
|
||||||
|
'image': forms.FileInput(attrs={'class': 'form-control', 'accept': 'image/*'}),
|
||||||
|
'description': forms.TextInput(attrs={'class': 'form-control', 'placeholder': _('可选,添加图片描述')})
|
||||||
|
}
|
||||||
Binary file not shown.
@ -0,0 +1,41 @@
|
|||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from blog.models import Category
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = '创建文章分类'
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
categories = [
|
||||||
|
'技术',
|
||||||
|
'生活',
|
||||||
|
'旅行',
|
||||||
|
'美食',
|
||||||
|
'摄影',
|
||||||
|
'读书',
|
||||||
|
'电影',
|
||||||
|
'音乐',
|
||||||
|
'编程',
|
||||||
|
'设计',
|
||||||
|
'健康',
|
||||||
|
'教育',
|
||||||
|
'职场',
|
||||||
|
'财经',
|
||||||
|
'历史',
|
||||||
|
'文化',
|
||||||
|
'体育',
|
||||||
|
'游戏',
|
||||||
|
'科技'
|
||||||
|
]
|
||||||
|
|
||||||
|
for name in categories:
|
||||||
|
category, created = Category.objects.get_or_create(
|
||||||
|
name=name,
|
||||||
|
defaults={'parent_category': None}
|
||||||
|
)
|
||||||
|
if created:
|
||||||
|
self.stdout.write(self.style.SUCCESS(f'创建分类: {name}'))
|
||||||
|
else:
|
||||||
|
self.stdout.write(self.style.WARNING(f'分类已存在: {name}'))
|
||||||
|
|
||||||
|
self.stdout.write(self.style.SUCCESS('分类创建完成'))
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from blog.models import Category
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = '列出所有文章分类'
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
categories = Category.objects.all()
|
||||||
|
self.stdout.write('当前数据库中的分类:')
|
||||||
|
for category in categories:
|
||||||
|
self.stdout.write(f'- {category.name} (ID: {category.id})')
|
||||||
|
self.stdout.write(f'总计: {categories.count()} 个分类')
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
# Generated by Django 4.2.14 on 2025-11-20 20:45
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('blog', '0006_alter_blogsettings_options'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ArticleImage',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('image', models.ImageField(upload_to='article_images/%Y/%m/%d/', verbose_name='图片')),
|
||||||
|
('description', models.CharField(blank=True, max_length=255, verbose_name='图片描述')),
|
||||||
|
('created_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
|
||||||
|
('article', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='images', to='blog.article')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': '文章图片',
|
||||||
|
'verbose_name_plural': '文章图片',
|
||||||
|
'ordering': ['-created_time'],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,162 +0,0 @@
|
|||||||
|
|
||||||
/* 文章归档页面样式 */
|
|
||||||
|
|
||||||
/* 归档标题样式 */
|
|
||||||
.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,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><rect width="100" height="100" fill="none"/><path d="M0 0L50 50M50 0L100 50M0 50L50 100M50 50L100 100" stroke="rgba(255,255,255,0.1)" stroke-width="0.5"/></svg>');
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
|
|
||||||
/* 网页背景选项 - 默认背景和自定义图片背景 */
|
|
||||||
|
|
||||||
/* 自定义图片背景 - 请将图片放在 /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;
|
|
||||||
}
|
|
||||||
@ -1,640 +0,0 @@
|
|||||||
|
|
||||||
/* 现代化样式 - 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,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><rect width="100" height="100" fill="%23f8f9fa"/><path d="M0 0L50 50M50 0L100 50M0 50L50 100M50 50L100 100" stroke="%23e9ecef" stroke-width="0.5"/></svg>');
|
|
||||||
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,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320"><path fill="rgba(255,255,255,0.1)" d="M0,96L48,112C96,128,192,160,288,160C384,160,480,128,576,112C672,96,768,96,864,112C960,128,1056,160,1152,160C1248,160,1344,128,1392,112L1440,96L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"></path></svg>') 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;
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 440 KiB |
@ -1,185 +0,0 @@
|
|||||||
|
|
||||||
// 背景切换工具
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
// 创建背景切换器
|
|
||||||
function createBackgroundSwitcher() {
|
|
||||||
// 创建背景切换器容器
|
|
||||||
const switcher = document.createElement('div');
|
|
||||||
switcher.className = 'bg-switcher';
|
|
||||||
switcher.innerHTML = `
|
|
||||||
<button class="bg-switcher-toggle" title="切换背景">
|
|
||||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M12 16C14.2091 16 16 14.2091 16 12C16 9.79086 14.2091 8 12 8C9.79086 8 8 9.79086 8 12C8 14.2091 9.79086 16 12 16Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M12 2V4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M12 20V22" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M4.93 4.93L6.34 6.34" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M17.66 17.66L19.07 19.07" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M2 12H4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M20 12H22" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M6.34 17.66L4.93 19.07" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M19.07 4.93L17.66 6.34" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<div class="bg-switcher-panel">
|
|
||||||
<h4>选择背景</h4>
|
|
||||||
<div class="bg-options">
|
|
||||||
<button class="bg-option active" data-bg="default">默认</button>
|
|
||||||
<button class="bg-option" data-bg="custom-image">自定义背景</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
// 添加样式
|
|
||||||
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();
|
|
||||||
});
|
|
||||||
@ -1,134 +0,0 @@
|
|||||||
|
|
||||||
// 现代化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);
|
|
||||||
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue