站内搜索优化,归档
This commit is contained in:
parent
ee2b5a2da4
commit
9fde270ea6
@ -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
|
||||
|
||||
@ -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
|
||||
---
|
||||
@ -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
|
||||
|
||||
@ -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>
|
||||
<% } %>
|
||||
@ -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>
|
||||
<%
|
||||
|
||||
@ -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 %>
|
||||
|
||||
@ -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 %>"> <%= 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 %>"> <%= 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>
|
||||
|
||||
@ -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
|
||||
|
||||
BIN
themes/hexo-theme-xups/source/img/loading-bar.gif
Normal file
BIN
themes/hexo-theme-xups/source/img/loading-bar.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user