站内搜索优化,归档

This commit is contained in:
结发受长生 2018-05-21 15:24:55 +08:00
parent ee2b5a2da4
commit 9fde270ea6
10 changed files with 170 additions and 221 deletions

View File

@ -91,5 +91,5 @@ search:
## Docs: https://hexo.io/docs/deployment.html ## Docs: https://hexo.io/docs/deployment.html
deploy: deploy:
type: git type: git
repo: git@github.com:sookie2010/sookie2010.github.io.git repo: https://github.com/sookie2010/sookie2010.github.io.git
branch: master branch: master

View File

@ -1,28 +0,0 @@
---
title: 实验室
date: 2016-02-01 20:29:57
pageid: lab
projects:
blog_demo:
title: Blog Demo
time: 2016-10-10
content:
1:
name: 基于 vue + vuex + bootstrap 的 blog demo
link: https://github.com/jangdelong/vue-blog-demo
hexo_theme_xups:
title: hexo-theme-xups 博客主题
time: 2016-03-12
content:
1:
name: 基于 hexo 静态博客系统的 博客主题 xups
link: https://github.com/jangdelong/hexo-theme-xups
typecho_theme_xups:
title: Typecho 博客主题
time: 2015-10-15
content:
1:
name: 基于 php 博客系统 typecho 的主题 xups
link: https://github.com/jangdelong/typecho-theme-xups
---

View File

@ -13,17 +13,13 @@ menu:
link: / link: /
icon: icon-home icon: icon-home
lab: lab:
name: 实验室 name: 归档
link: /lab/ link: /archives/
icon: icon-lab icon: icon-drawer
about: about:
name: 关于 name: 关于
link: /about/ link: /about/
icon: icon-user-tie icon: icon-user-tie
# comment:
# name: 留言
# link: /comment/
# icon: icon-bubbles2
rss: rss:
name: RSS name: RSS
link: /atom.xml link: /atom.xml

View File

@ -1,27 +0,0 @@
<!-- 自定义实验室页 -->
<section>
<img title="图片摄于2017年1月1日深圳梧桐山 By iPhone 7。" src="<%- url_for('/img/lab/banner.jpg?v=3') %>" alt="Lab Banner" style="max-width: 100%;" alt="Banner" >
</section>
<%
var projects = page.projects;
for (var i in projects) {
%>
<p style="color: #444;">
<!--
<span class="icon-cogs"></span>
-->
<span class="icon-price-tags"></span>
<%- date(projects[i].time, 'YYYY-MM-DD') %> <%- projects[i].title %>
</p>
<ul style="list-style-type: none;">
<% var content = projects[i].content; %>
<% for (var j in content) { %>
<li>
<a href="<%- content[j].link %>" target="_blank" class="icon-lab fr" title="查看代码" style="color: #ff5e52; border-bottom: none; font-size: 16px; margin-top: 2.5px;"></a>
<span><%- content[j].name %></span>
</li>
<% } %>
</ul>
<% } %>

View File

@ -23,7 +23,7 @@ if(pagination) {
let currentPosts = []; let currentPosts = [];
site.posts.each(function(post) { site.posts.each(function(post) {
if(post.date.year() == page.year && (post.date.month()+1 == page.month || !page.month)) { if((post.date.year() == page.year || !page.year) && (post.date.month()+1 == page.month || !page.month)) {
currentPosts.push(post) currentPosts.push(post)
} }
}) })
@ -41,9 +41,8 @@ if(pagination) {
%> %>
<li class="archive-item"> <li class="archive-item">
<a href="<%=url_for(post.permalink) %>"> <a href="<%=url_for(post.permalink) %>">
<div class="archive-div"> <span class="title"><%=post.title %></span>
<%=post.title %> <span class="date">---- <%=date(post.date, 'YYYY-MM-DD HH:mm') %></span>
</div>
</a> </a>
</li> </li>
<% <%

View File

@ -5,7 +5,7 @@
</header> </header>
<p class="post-meta text-center"> <p class="post-meta text-center">
<%- post.author || '柠烟夏季' %> 发表于 <%- post.author || '柠烟夏季' %> 发表于
<%- partial('post/date', { date_format: 'YYYY-MM-DD' }) %> <%- partial('post/date', { date_format: 'YYYY-MM-DD HH:mm' }) %>
</p> </p>
<div class="post-content"> <div class="post-content">
<%- post.content %> <%- post.content %>

View File

@ -1,71 +1,65 @@
<header class="header"> <header class="header">
<section class="container header-main"> <section class="container header-main">
<div class="logo"> <div class="logo">
<a href="<%- url_for() %>"> <a href="<%- url_for() %>">
<div class="cover"> <div class="cover">
<div class="name"><%= config.title %></div> <div class="name"><%= config.title %></div>
<div class="description"><%= config.subtitle %></div> <div class="description"><%= config.subtitle %></div>
</div>
</a>
</div> </div>
<div class="dropnav icon-paragraph-justify" id="JELON__btnDropNav"></div> </a>
<!-- 导航栏 --> </div>
<ul class="menu hidden" id="JELON__menu"> <div class="dropnav icon-paragraph-justify" id="JELON__btnDropNav"></div>
<% for (var i in theme.menu) { %> <!-- 导航栏 -->
<li rel="<%= url_for(path) %>" class="item <%= url_for(theme.menu[i].link) == url_for(path).substring(0, url_for(path).lastIndexOf('/') + 1) ? 'current' : '' %>"> <ul class="menu hidden" id="JELON__menu">
<a href="<%= url_for(theme.menu[i].link) %>" title="<%= theme.menu[i].name %>" class="<%= theme.menu[i].icon %>">&nbsp;<%= theme.menu[i].name %></a> <% for (var i in theme.menu) { %>
</li> <li rel="<%= url_for(path) %>" class="item <%= url_for(theme.menu[i].link) == url_for(path).substring(0, url_for(path).lastIndexOf('/') + 1) ? 'current' : '' %>">
<% } %> <a href="<%= url_for(theme.menu[i].link) %>" title="<%= theme.menu[i].name %>" class="<%= theme.menu[i].icon %>">&nbsp;<%= theme.menu[i].name %></a>
</li>
<% } %>
</ul>
<!-- 搜索框 -->
<div id="search-box">
<div class="icon"><span class="icon-search"></span></div>
<div class="input-box"><input type="text" id="search-input" v-model="queryText" @focus="searchInit" placeholder="站内搜索"/></div>
<!-- 搜索结果区 -->
<div id="search-result-box" >
<ul class="search-result-list" v-if="searchResult.length && !searchIniting">
<li v-for="(article,index) in searchResult" :key="index">
<a :href='article.url' class='search-result-title' target='_blank'>{{article.title || '无标题'}}</a>
<p class="search-result" v-html="article.matchContent"></p>
</li>
</ul> </ul>
<!-- 搜索框 --> <!-- 搜索未初始化完毕时显示 -->
<div id="search-box"> <div style="text-align:center;padding:10px 0" v-else-if="searchIniting">
<div class="icon"><span class="icon-search"></span></div> <img src="<%= config.root%>img/loading-bar.gif" style="height:8px;width:auto"/>
<div class="input-box"><input type="text" id="search-input" v-model="queryText" placeholder="站内搜索"/></div>
<!-- 搜索结果区 -->
<div id="search-result-box" >
<ul class="search-result-list" v-if="searchResult.length">
<li v-for="(article,index) in searchResult" :key="index">
<a :href='article.url' class='search-result-title' target='_blank'>{{article.title || '无标题'}}</a>
<p class="search-result" v-html="article.matchContent"></p>
</li>
</ul>
<!-- 无匹配时显示 -->
<p class="search-result" v-else>没有搜索到任何结果</p>
</div>
</div> </div>
<div class="profile clearfix"> <!-- 无匹配时显示 -->
<div class="feeds fl"> <p class="search-result" v-else>没有搜索到任何结果</p>
<% if (theme.head_links.enable) { %> </div>
<% </div>
var supList = theme.head_links.list.sup, <div class="profile clearfix">
subList = theme.head_links.list.sub; <div class="feeds fl">
%> <% if (theme.head_links.enable) { %>
<p class="links"> <%
<% for (var i in supList) { %> var supList = theme.head_links.list.sup,
<a href="<%= supList[i]['link'] %>" target="_blank"><%= supList[i]['name'] %></a> subList = theme.head_links.list.sub;
<% if (i != 'last') { %>|<% } %> %>
<% } %> <p class="links">
</p> <% for (var i in supList) { %>
<p class="sns"> <a href="<%= supList[i]['link'] %>" target="_blank"><%= supList[i]['name'] %></a>
<% for (var j in subList) { %> <% if (i != 'last') { %>|<% } %>
<a href="<%= subList[j]['link'] %>" class="<%= j %>" target="_blank"><b>■</b> <%= subList[j]['name'] %></a> <% } %>
<% } %> </p>
<!-- <p class="sns">
<a href="javascript: void(0);" class="wechat"> <% for (var j in subList) { %>
<b>■</b> <a href="<%= subList[j]['link'] %>" class="<%= j %>" target="_blank"><b>■</b> <%= subList[j]['name'] %></a>
公众号 <% } %>
<span class="popover"> </p>
<img src="<%= url_for('img/wechat_mp.jpg') %>" width="120" height="120" alt="我的微信订阅号"> <% } %>
<i class="arrow"></i> </div>
</span> <div class="avatar fr">
</a> <img src="<%- theme.avatar %>" alt="avatar" title="Sookie">
--> </div>
</p> </div>
<% } %> </section>
</div>
<div class="avatar fr">
<img src="<%- theme.avatar %>" alt="avatar" title="Sookie">
</div>
</div>
</section>
</header> </header>

View File

@ -120,17 +120,10 @@
.archive-wapper .archive-wapper
list-style none list-style none
display flex .archive-item > a
flex-wrap wrap display block
justify-content space-between font-size 16px
.archive-item line-height 30px
display inline-block .date
height 50px color #999
padding 5px font-size 14px
width 30%
> a > .archive-div
border 1px solid #a7a7a7
border-radius 5px
height 100%
padding 5px
box-sizing border-box

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,95 +1,117 @@
(function(){ (function(){
var articleDatas = null; var articleDatas = null,
var resultDiv = null; resultDiv = null,
initCallback = function(){};
function executeSearch(keywords) {
var _this = this;
articleDatas.forEach(function(article){
var isMatch = true,
title = article.title.trim().toLowerCase(),
index_title = -1, index_content = -1,
first_occur = -1; //关键字在正文当中第一次出现的位置
keywords.forEach(function(keyword, i) {
index_title = title ? title.indexOf(keyword) : -1;
index_content = article.content ? article.content.indexOf(keyword) : -1;
if( index_title < 0 && index_content < 0 ){
isMatch = false;
} else {
if (index_content < 0) {
index_content = 0;
}
if (i == 0) {
first_occur = index_content;
}
}
});
if (isMatch) {
var resultItem = {};
resultItem.url = article.url;
resultItem.title = article.title;
if (first_occur >= 0) {
// 截取出关键字所在的前后若干字符
var start = first_occur - 10;
var end = first_occur + 15;
if(start <= 0){
start = 0;
end = 25;
}
if(end > article.content.length){
end = article.content.length;
}
var matchContent = article.content.substring(start, end);
// 高亮关键字
keywords.forEach(function(keyword){
var keywordReg = new RegExp(keyword, "gi");
matchContent = matchContent.replace(keywordReg, "<strong class=\"search-keyword\">"+keyword+"</strong>");
})
resultItem.matchContent = matchContent
}
_this.searchResult.push(resultItem)
}
});
}
new Vue({ new Vue({
el: "#search-box", el: "#search-box",
data: { data: {
queryText: null, queryText: null,
searchResult: [] searchResult: [],
searchIniting: false // 搜索是否正在初始化(search.xml文件很大, 异步ajax以及xml解析需要时间)
}, },
mounted: function() { mounted: function() {
resultDiv = document.getElementById("search-result-box") resultDiv = document.getElementById("search-result-box");
axios({ },
url: "/search.xml" methods : {
}).then(function(response){ searchInit: function() {
var xmlDoms = null if(articleDatas || this.searchIniting) return;
if(window.DOMParser) { this.searchIniting = true;
var parser = new DOMParser() var _this = this;
xmlDoms = parser.parseFromString(response.data, "application/xml") axios({
} else { url: "/search.xml"
xmlDoms = new ActiveXObject("Microsoft.XMLDOM"); }).then(function(response){
xmlDoms.async = false; var xmlDoms = null
xmlDoms.loadXML(response.data); if(window.DOMParser) {
} var parser = new DOMParser()
//找出所有文章的标题 正文 URL xmlDoms = parser.parseFromString(response.data, "application/xml")
articleDatas = Array.prototype.map.call(xmlDoms.getElementsByTagName("entry"), function(item){ } else {
return { xmlDoms = new ActiveXObject("Microsoft.XMLDOM");
title: item.getElementsByTagName("title")[0].textContent, xmlDoms.async = false;
content: item.getElementsByTagName("content")[0].textContent, xmlDoms.loadXML(response.data);
url: item.getElementsByTagName("url")[0].textContent,
} }
}) //找出所有文章的标题 正文 URL
}); articleDatas = Array.prototype.map.call(xmlDoms.getElementsByTagName("entry"), function(item){
return {
title: item.getElementsByTagName("title")[0].textContent,
content: item.getElementsByTagName("content")[0].textContent.trim().replace(/<[^>]+>/g,"").toLowerCase(),
url: item.getElementsByTagName("url")[0].textContent,
}
});
_this.searchIniting = false;
initCallback.call(_this);
}).catch(function(){
_this.searchIniting = false;
_this.searchInit();
});
}
}, },
watch: { watch: {
queryText: function(newVal, oldVal) { queryText: function(newVal, oldVal) {
this.searchResult.length = 0; this.searchResult.length = 0;
if(!resultDiv) return; if(!resultDiv) return;
if(newVal && newVal.trim() && articleDatas) { if(newVal && newVal.trim()) {
resultDiv.style.display = "block" resultDiv.style.display = "block";
} else { } else {
resultDiv.style.display = "none" resultDiv.style.display = "none";
return return
} }
var keywords = newVal.trim().toLowerCase().split(/[\s\-]+/); var keywords = newVal.trim().toLowerCase().split(/[\s\-]+/);
var _this = this; var _this = this;
articleDatas.forEach(function(article){ if(this.searchIniting) {
var isMatch = true; initCallback = function(){
var title = article.title.trim().toLowerCase(); executeSearch.call(this, keywords);
var content = article.content.trim().replace(/<[^>]+>/g,"").toLowerCase();
var index_title = -1;
var index_content = -1;
var first_occur = -1; //关键字在正文当中第一次出现的位置
keywords.forEach(function(keyword, i) {
index_title = title ? title.indexOf(keyword) : -1;
index_content = content ? content.indexOf(keyword) : -1;
if( index_title < 0 && index_content < 0 ){
isMatch = false;
} else {
if (index_content < 0) {
index_content = 0;
}
if (i == 0) {
first_occur = index_content;
}
}
});
if (isMatch) {
var resultItem = {};
resultItem.url = article.url;
resultItem.title = article.title;
if (first_occur >= 0) {
// 截取出关键字所在的前后若干字符
var start = first_occur - 10;
var end = first_occur + 15;
if(start <= 0){
start = 0;
end = 25;
}
if(end > content.length){
end = content.length;
}
var matchContent = content.substring(start, end);
// 高亮关键字
keywords.forEach(function(keyword){
var keywordReg = new RegExp(keyword, "gi");
matchContent = matchContent.replace(keywordReg, "<strong class=\"search-keyword\">"+keyword+"</strong>");
})
resultItem.matchContent = matchContent
}
_this.searchResult.push(resultItem)
} }
}) } else {
executeSearch.call(this, keywords);
}
} }
} }
}) })