站内搜索优化,归档

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
deploy:
type: git
repo: git@github.com:sookie2010/sookie2010.github.io.git
repo: https://github.com/sookie2010/sookie2010.github.io.git
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: /
icon: icon-home
lab:
name: 实验室
link: /lab/
icon: icon-lab
name: 归档
link: /archives/
icon: icon-drawer
about:
name: 关于
link: /about/
icon: icon-user-tie
# comment:
# name: 留言
# link: /comment/
# icon: icon-bubbles2
rss:
name: RSS
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 = [];
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)
}
})
@ -41,9 +41,8 @@ if(pagination) {
%>
<li class="archive-item">
<a href="<%=url_for(post.permalink) %>">
<div class="archive-div">
<%=post.title %>
</div>
<span class="title"><%=post.title %></span>
<span class="date">---- <%=date(post.date, 'YYYY-MM-DD HH:mm') %></span>
</a>
</li>
<%

View File

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

View File

@ -1,71 +1,65 @@
<header class="header">
<section class="container header-main">
<div class="logo">
<a href="<%- url_for() %>">
<div class="cover">
<div class="name"><%= config.title %></div>
<div class="description"><%= config.subtitle %></div>
</div>
</a>
<section class="container header-main">
<div class="logo">
<a href="<%- url_for() %>">
<div class="cover">
<div class="name"><%= config.title %></div>
<div class="description"><%= config.subtitle %></div>
</div>
<div class="dropnav icon-paragraph-justify" id="JELON__btnDropNav"></div>
<!-- 导航栏 -->
<ul class="menu hidden" id="JELON__menu">
<% 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' : '' %>">
<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>
<% } %>
</a>
</div>
<div class="dropnav icon-paragraph-justify" id="JELON__btnDropNav"></div>
<!-- 导航栏 -->
<ul class="menu hidden" id="JELON__menu">
<% 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' : '' %>">
<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>
<!-- 搜索框 -->
<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" 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 style="text-align:center;padding:10px 0" v-else-if="searchIniting">
<img src="<%= config.root%>img/loading-bar.gif" style="height:8px;width:auto"/>
</div>
<div class="profile clearfix">
<div class="feeds fl">
<% if (theme.head_links.enable) { %>
<%
var supList = theme.head_links.list.sup,
subList = theme.head_links.list.sub;
%>
<p class="links">
<% for (var i in supList) { %>
<a href="<%= supList[i]['link'] %>" target="_blank"><%= supList[i]['name'] %></a>
<% if (i != 'last') { %>|<% } %>
<% } %>
</p>
<p class="sns">
<% for (var j in subList) { %>
<a href="<%= subList[j]['link'] %>" class="<%= j %>" target="_blank"><b>■</b> <%= subList[j]['name'] %></a>
<% } %>
<!--
<a href="javascript: void(0);" class="wechat">
<b>■</b>
公众号
<span class="popover">
<img src="<%= url_for('img/wechat_mp.jpg') %>" width="120" height="120" alt="我的微信订阅号">
<i class="arrow"></i>
</span>
</a>
-->
</p>
<% } %>
</div>
<div class="avatar fr">
<img src="<%- theme.avatar %>" alt="avatar" title="Sookie">
</div>
</div>
</section>
<!-- 无匹配时显示 -->
<p class="search-result" v-else>没有搜索到任何结果</p>
</div>
</div>
<div class="profile clearfix">
<div class="feeds fl">
<% if (theme.head_links.enable) { %>
<%
var supList = theme.head_links.list.sup,
subList = theme.head_links.list.sub;
%>
<p class="links">
<% for (var i in supList) { %>
<a href="<%= supList[i]['link'] %>" target="_blank"><%= supList[i]['name'] %></a>
<% if (i != 'last') { %>|<% } %>
<% } %>
</p>
<p class="sns">
<% for (var j in subList) { %>
<a href="<%= subList[j]['link'] %>" class="<%= j %>" target="_blank"><b>■</b> <%= subList[j]['name'] %></a>
<% } %>
</p>
<% } %>
</div>
<div class="avatar fr">
<img src="<%- theme.avatar %>" alt="avatar" title="Sookie">
</div>
</div>
</section>
</header>

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,95 +1,117 @@
(function(){
var articleDatas = null;
var resultDiv = null;
var articleDatas = 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({
el: "#search-box",
data: {
queryText: null,
searchResult: []
searchResult: [],
searchIniting: false // 搜索是否正在初始化(search.xml文件很大, 异步ajax以及xml解析需要时间)
},
mounted: function() {
resultDiv = document.getElementById("search-result-box")
axios({
url: "/search.xml"
}).then(function(response){
var xmlDoms = null
if(window.DOMParser) {
var parser = new DOMParser()
xmlDoms = parser.parseFromString(response.data, "application/xml")
} else {
xmlDoms = new ActiveXObject("Microsoft.XMLDOM");
xmlDoms.async = false;
xmlDoms.loadXML(response.data);
}
//找出所有文章的标题 正文 URL
articleDatas = Array.prototype.map.call(xmlDoms.getElementsByTagName("entry"), function(item){
return {
title: item.getElementsByTagName("title")[0].textContent,
content: item.getElementsByTagName("content")[0].textContent,
url: item.getElementsByTagName("url")[0].textContent,
resultDiv = document.getElementById("search-result-box");
},
methods : {
searchInit: function() {
if(articleDatas || this.searchIniting) return;
this.searchIniting = true;
var _this = this;
axios({
url: "/search.xml"
}).then(function(response){
var xmlDoms = null
if(window.DOMParser) {
var parser = new DOMParser()
xmlDoms = parser.parseFromString(response.data, "application/xml")
} else {
xmlDoms = new ActiveXObject("Microsoft.XMLDOM");
xmlDoms.async = false;
xmlDoms.loadXML(response.data);
}
})
});
//找出所有文章的标题 正文 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: {
queryText: function(newVal, oldVal) {
this.searchResult.length = 0;
if(!resultDiv) return;
if(newVal && newVal.trim() && articleDatas) {
resultDiv.style.display = "block"
if(newVal && newVal.trim()) {
resultDiv.style.display = "block";
} else {
resultDiv.style.display = "none"
resultDiv.style.display = "none";
return
}
var keywords = newVal.trim().toLowerCase().split(/[\s\-]+/);
var _this = this;
articleDatas.forEach(function(article){
var isMatch = true;
var title = article.title.trim().toLowerCase();
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)
if(this.searchIniting) {
initCallback = function(){
executeSearch.call(this, keywords);
}
})
} else {
executeSearch.call(this, keywords);
}
}
}
})