File size: 7,144 Bytes
d82405d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
// 全局工具函数和初始化
document.addEventListener('DOMContentLoaded', function() {
    // 等待 marked 库加载完成
    setTimeout(() => {
        // 初始化搜索功能
        initializeSearch();
        // 初始化Markdown渲染
        initializeMarkdownRendering();
        // 初始化返回顶部按钮
        initializeScrollToTop();
        // 初始化移动端导航菜单
        initializeMobileNavigation();
    }, 100);
});

// 搜索功能实现
function initializeSearch() {
    const searchInput = document.querySelector('.search-input');
    const searchResults = document.querySelector('.search-results');
    
    if (searchInput) {
        searchInput.addEventListener('input', debounce(async (event) => {
            const searchTerm = event.target.value.trim().toLowerCase();
            if (searchTerm.length < 2) {
                searchResults.style.display = 'none';
                return;
            }

            try {
                const response = await fetch(`/api/search?q=${encodeURIComponent(searchTerm)}`);
                const data = await response.json();
                
                if (data.articles.length > 0) {
                    displaySearchResults(data.articles, searchResults);
                } else {
                    searchResults.innerHTML = '<div class="no-results">没有找到相关文章</div>';
                }
                searchResults.style.display = 'block';
            } catch (error) {
                console.error('搜索出错:', error);
                searchResults.innerHTML = '<div class="error">搜索服务暂时不可用</div>';
            }
        }, 300));

        // 点击其他区域关闭搜索结果
        document.addEventListener('click', (event) => {
            if (!event.target.closest('.search-container')) {
                searchResults.style.display = 'none';
            }
        });
    }
}

// Markdown渲染初始化
function initializeMarkdownRendering() {
    if (typeof marked === 'undefined') {
        console.error('Marked library not loaded');
        return;
    }

    // 配置 marked
    marked.use({
        breaks: true,
        gfm: true
    });

    const markdownElements = document.querySelectorAll('.markdown-body');
    
    markdownElements.forEach(element => {
        // 检查元素是否已经被渲染过
        if (element.dataset.rendered) {
            return;
        }

        try {
            // 标记为已渲染
            element.dataset.rendered = 'true';
            
            // 如果内容是通过 Flask 的 markdown 过滤器渲染的,就不需要再次渲染
            if (!element.classList.contains('server-rendered')) {
                const content = element.textContent;
                element.innerHTML = marked(content);
            }

            // 处理代码块
            element.querySelectorAll('pre code').forEach(block => {
                if (typeof hljs !== 'undefined') {
                    hljs.highlightElement(block);
                }
            });

            // 为图片添加点击放大功能
            element.querySelectorAll('img').forEach(img => {
                img.addEventListener('click', () => {
                    openImageViewer(img.src);
                });
            });
        } catch (error) {
            console.error('Markdown渲染错误:', error);
        }
    });
}

// 返回顶部按钮实现
function initializeScrollToTop() {
    const scrollTopButton = document.createElement('button');
    scrollTopButton.className = 'scroll-top-button';
    scrollTopButton.innerHTML = '↑';
    document.body.appendChild(scrollTopButton);

    window.addEventListener('scroll', debounce(() => {
        if (window.scrollY > 500) {
            scrollTopButton.classList.add('visible');
        } else {
            scrollTopButton.classList.remove('visible');
        }
    }, 100));

    scrollTopButton.addEventListener('click', () => {
        window.scrollTo({
            top: 0,
            behavior: 'smooth'
        });
    });
}

// 移动端导航菜单实现
function initializeMobileNavigation() {
    const menuButton = document.querySelector('.menu-button');
    const navLinks = document.querySelector('.nav-links');
    
    if (menuButton && navLinks) {
        menuButton.addEventListener('click', () => {
            navLinks.classList.toggle('active');
            menuButton.classList.toggle('active');
        });

        // 点击导航链接后关闭菜单
        navLinks.querySelectorAll('a').forEach(link => {
            link.addEventListener('click', () => {
                navLinks.classList.remove('active');
                menuButton.classList.remove('active');
            });
        });
    }
}

// 图片查看器实现
function openImageViewer(imageSrc) {
    const viewer = document.createElement('div');
    viewer.className = 'image-viewer';
    viewer.innerHTML = `

        <div class="image-viewer-content">

            <img src="${imageSrc}" alt="预览图片">

            <button class="close-button">×</button>

        </div>

    `;

    viewer.addEventListener('click', (event) => {
        if (event.target === viewer || event.target.className === 'close-button') {
            viewer.remove();
        }
    });

    document.body.appendChild(viewer);
}

// 工具函数: 防抖
function debounce(func, wait) {
    let timeout;
    return function executedFunction(...args) {
        const later = () => {
            clearTimeout(timeout);
            func(...args);
        };
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
    };
}

// 工具函数: 搜索结果显示
function displaySearchResults(articles, container) {
    container.innerHTML = articles.map(article => `

        <a href="/article/${article.slug}" class="search-result-item">

            <h3>${highlightSearchTerm(article.title)}</h3>

            ${article.summary ? `<p>${highlightSearchTerm(article.summary)}</p>` : ''}

            <span class="article-date">${formatDate(article.created_at)}</span>

        </a>

    `).join('');
}

// 工具函数: 高亮搜索词
function highlightSearchTerm(text, searchTerm) {
    if (!searchTerm) return text;
    const regex = new RegExp(searchTerm, 'gi');
    return text.replace(regex, match => `<mark>${match}</mark>`);
}

// 工具函数: 日期格式化
function formatDate(dateString) {
    const date = new Date(dateString);
    return date.toLocaleDateString('zh-CN', {
        year: 'numeric',
        month: '2-digit',
        day: '2-digit'
    });
}

// 错误处理函数
function handleError(error, container) {
    console.error('发生错误:', error);
    container.innerHTML = `

        <div class="error-message">

            <p>抱歉,发生了一些错误</p>

            <button onclick="window.location.reload()">刷新页面</button>

        </div>

    `;
}