|
@@ -1,4 +1,92 @@
|
|
|
{{ define "main" }}
|
|
{{ define "main" }}
|
|
|
|
|
+{{ if eq .Type "search" }}
|
|
|
|
|
+<!-- 搜索页面 -->
|
|
|
|
|
+<section class="card page-head">
|
|
|
|
|
+ <span class="eyebrow">Search</span>
|
|
|
|
|
+ <h1>搜索</h1>
|
|
|
|
|
+ <p>搜索全站文章和标签</p>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 搜索框 -->
|
|
|
|
|
+ <div class="search-box">
|
|
|
|
|
+ <input type="text" id="search-input" placeholder="搜索文章标题、内容或标签..." />
|
|
|
|
|
+ <div id="search-results" class="search-results"></div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</section>
|
|
|
|
|
+
|
|
|
|
|
+<script src="https://cdn.jsdelivr.net/npm/fuse.js@6.6.2"></script>
|
|
|
|
|
+<script>
|
|
|
|
|
+ // 文章内容索引
|
|
|
|
|
+ const posts = [
|
|
|
|
|
+ {{ range .Site.RegularPages }}
|
|
|
|
|
+ {
|
|
|
|
|
+ title: {{ .Title | jsonify }},
|
|
|
|
|
+ url: {{ .RelPermalink | jsonify }},
|
|
|
|
|
+ date: {{ .Date.Format "2006-01-02" | jsonify }},
|
|
|
|
|
+ summary: {{ .Summary | plainify | jsonify }},
|
|
|
|
|
+ tags: {{ .Params.tags | jsonify }},
|
|
|
|
|
+ content: {{ .Content | plainify | jsonify }}
|
|
|
|
|
+ },
|
|
|
|
|
+ {{ end }}
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ // 初始化 Fuse.js
|
|
|
|
|
+ const options = {
|
|
|
|
|
+ includeScore: true,
|
|
|
|
|
+ threshold: 0.4,
|
|
|
|
|
+ location: 0,
|
|
|
|
|
+ distance: 100,
|
|
|
|
|
+ maxPatternLength: 32,
|
|
|
|
|
+ minMatchCharLength: 1,
|
|
|
|
|
+ keys: [
|
|
|
|
|
+ { name: "title", weight: 0.5 },
|
|
|
|
|
+ { name: "content", weight: 0.3 },
|
|
|
|
|
+ { name: "tags", weight: 0.2 }
|
|
|
|
|
+ ]
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const fuse = new Fuse(posts, options);
|
|
|
|
|
+
|
|
|
|
|
+ // 搜索事件
|
|
|
|
|
+ document.getElementById("search-input").addEventListener("input", function(e) {
|
|
|
|
|
+ const query = e.target.value.trim();
|
|
|
|
|
+ const resultsDiv = document.getElementById("search-results");
|
|
|
|
|
+
|
|
|
|
|
+ if (!query) {
|
|
|
|
|
+ resultsDiv.innerHTML = "";
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const results = fuse.search(query);
|
|
|
|
|
+
|
|
|
|
|
+ if (results.length === 0) {
|
|
|
|
|
+ resultsDiv.innerHTML = '<p class="no-results">没有找到匹配的内容</p>';
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ resultsDiv.innerHTML = results.slice(0, 10).map(result => {
|
|
|
|
|
+ const post = result.item;
|
|
|
|
|
+ const tagsHtml = post.tags ? post.tags.map(tag =>
|
|
|
|
|
+ `<span class="tag">${tag}</span>`
|
|
|
|
|
+ ).join("") : "";
|
|
|
|
|
+
|
|
|
|
|
+ // 高亮匹配内容
|
|
|
|
|
+ const preview = post.summary
|
|
|
|
|
+ .replace(/<[^>]*>/g, '')
|
|
|
|
|
+ .substring(0, 150) + "...";
|
|
|
|
|
+
|
|
|
|
|
+ return `
|
|
|
|
|
+ <article class="search-result-item">
|
|
|
|
|
+ <h3><a href="${post.url}">${post.title}</a></h3>
|
|
|
|
|
+ <p class="meta">${post.date}</p>
|
|
|
|
|
+ <p class="preview">${preview}</p>
|
|
|
|
|
+ <div class="tags">${tagsHtml}</div>
|
|
|
|
|
+ </article>
|
|
|
|
|
+ `;
|
|
|
|
|
+ }).join("");
|
|
|
|
|
+ });
|
|
|
|
|
+</script>
|
|
|
|
|
+{{ else }}
|
|
|
|
|
+<!-- 普通列表页面 -->
|
|
|
<section class="card page-head">
|
|
<section class="card page-head">
|
|
|
<span class="eyebrow">Section</span>
|
|
<span class="eyebrow">Section</span>
|
|
|
<h1>{{ .Title }}</h1>
|
|
<h1>{{ .Title }}</h1>
|
|
@@ -24,3 +112,4 @@
|
|
|
{{ end }}
|
|
{{ end }}
|
|
|
</section>
|
|
</section>
|
|
|
{{ end }}
|
|
{{ end }}
|
|
|
|
|
+{{ end }}
|