-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
31 changed files
with
3,224 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
229 changes: 229 additions & 0 deletions
229
bitcron-pro-plus/assets/media/gridea-search/gridea-search.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,229 @@ | ||
//获取url参数 | ||
function getParam(url, param) { | ||
if (url.indexOf('?') > -1) { | ||
var urlSearch = url.split('?'); | ||
var paramList = urlSearch[1].split('&'); | ||
for (var i = paramList.length - 1; i >= 0; i--) { | ||
var tep = paramList[i].split('='); | ||
if (tep[0] == param) { | ||
return tep[1]; | ||
} | ||
} | ||
} | ||
}; | ||
|
||
//原生js Ajax 异步GET请求 | ||
function ajax(obj) { | ||
var xhr = new XMLHttpRequest(); | ||
xhr.open('get', obj.url, true); | ||
xhr.send(null); | ||
xhr.onreadystatechange = function () { | ||
//异步请求:响应状态为4,数据加载完毕 | ||
if (xhr.readyState == 4) | ||
callback(); | ||
} | ||
function callback() { | ||
if (xhr.status == 200) { | ||
obj.success(xhr.responseText); | ||
} else { | ||
obj.error(xhr.status); | ||
} | ||
} | ||
} | ||
|
||
//模糊搜索 https://github.com/krisk/fuse | ||
function fuzzySearch(data, phrase) { | ||
var phrase_len = phrase.length; | ||
var min_len = 4; | ||
var max_len = 32; | ||
//根据搜索的词数决定匹配大小,最小匹配词数不能大于词数,最大匹配词数不能小于词数 | ||
if(phrase_len<4){ | ||
min_len = phrase_len; | ||
} | ||
if(phrase_len<=0){ | ||
min_len = 99999999; | ||
max_len = 99999999; | ||
} | ||
if(phrase_len>32){ | ||
max_len = phrase_len; | ||
} | ||
|
||
var options = { | ||
shouldSort: true, | ||
includeMatches: true, | ||
threshold: 0.5,// 匹配算法阈值。阈值为0.0需要完全匹配(字母和位置),阈值为1.0将匹配任何内容。 | ||
location: 0,// 确定文本中预期找到的模式的大致位置。 | ||
distance: 1000, | ||
maxPatternLength: max_len, // 模式的最大长度 | ||
minMatchCharLength: min_len, // 模式的最小字符长度 | ||
// 搜索标题与内容 | ||
keys: [ | ||
'title', | ||
'content', | ||
'tags.name' | ||
] | ||
}; | ||
var fuse = new Fuse(data, options); | ||
var fuzzyResult = fuse.search(phrase); | ||
return fuzzyResult; | ||
} | ||
|
||
//检查缓存是否最新 | ||
function checkCache() { | ||
var infosCache = JSON.parse(localStorage.getItem('InfosCache')); | ||
var contentsCache = JSON.parse(localStorage.getItem('ContentsCache')); | ||
if (infosCache && contentsCache) { | ||
var cachedTime = infosCache.utils.now.toString(); | ||
var updateTime = document.getElementById('gridea-search-form').getAttribute('data-update'); | ||
if (cachedTime === updateTime) { | ||
return true; | ||
} | ||
} | ||
localStorage.removeItem('InfosCache'); | ||
localStorage.removeItem('ContentsCache'); | ||
return false; | ||
} | ||
|
||
//获取博客全文api | ||
function getContents(callback) { | ||
if (checkCache()) { | ||
var contentsCache = JSON.parse(localStorage.getItem('ContentsCache')); | ||
callback(contentsCache); | ||
} | ||
else { | ||
ajax({ | ||
url: '/api-content/index.html', | ||
success: function (data) { | ||
callback(JSON.parse(data)); | ||
localStorage.setItem('ContentsCache', data); | ||
} | ||
}); | ||
} | ||
} | ||
|
||
//获取博客信息api | ||
function getInfos(callback) { | ||
if (checkCache()) { | ||
var infosCache = JSON.parse(localStorage.getItem('InfosCache')); | ||
callback(infosCache); | ||
} | ||
else { | ||
ajax({ | ||
url: '/api-info/index.html', | ||
success: function (data) { | ||
callback(JSON.parse(data)); | ||
localStorage.setItem('InfosCache', data); | ||
} | ||
}); | ||
} | ||
} | ||
|
||
//根据一段文本调用模糊搜索 | ||
function searchBy(phrase, callback) { | ||
var result = ''; | ||
var getFuzzyResult = function (data) { | ||
result = fuzzySearch(data.posts, phrase); | ||
callback(result); | ||
} | ||
//根据全文内容获取搜索结果 | ||
getContents(getFuzzyResult); | ||
} | ||
|
||
//显示无搜索结果 | ||
function showNoResult() { | ||
var resultDIV = document.getElementById('gridea-search-result'); | ||
var noResult = resultDIV.getElementsByClassName('no-result')[0]; | ||
noResult.style.display = 'block'; | ||
resultDIV.innerHTML = noResult.outerHTML; | ||
} | ||
|
||
//根据URL参数执行搜索 | ||
function searchByParam(resultHandler) { | ||
var phrase = getParam(window.location.href, 'q'); | ||
if (phrase === '' || typeof (phrase) === 'undefined') { | ||
showNoResult(); | ||
} else { | ||
searchBy(decodeURI(phrase), resultHandler); | ||
} | ||
} | ||
|
||
//获取搜索结果列表模板的URL | ||
function getTemplateURL() { | ||
var scripts = document.getElementsByTagName('script'); | ||
var templateURL = ''; | ||
for (var i = 0; i < scripts.length; i++) { | ||
if (scripts[i].type === 'text/ejs') { | ||
templateURL = scripts[i].src; | ||
return templateURL; | ||
} | ||
} | ||
} | ||
|
||
//渲染搜索结果列表 | ||
function renderResult(searchedInfos) { | ||
if (searchedInfos.posts.length > 0) { | ||
ajax({ | ||
url: getTemplateURL(), | ||
success: function (data) { | ||
var resultDIV = document.getElementById('gridea-search-result'); | ||
resultDIV.innerHTML = ejs.compile(data)(searchedInfos); | ||
} | ||
}); | ||
} else { | ||
showNoResult(); | ||
} | ||
} | ||
|
||
//搜索结果关键字高亮 | ||
function keywordsHighlight(searchedContent) { | ||
var searchedPostContent = searchedContent.item.content;//搜索结果内容预览 | ||
var preview = ''; | ||
for (var i = 0; i < searchedContent.matches.length; i++) { | ||
if (searchedContent.matches[i].key === 'content') {//如果匹配到文章内容,截取关键字 | ||
var indices = searchedContent.matches[i].indices[0]; | ||
var beforeKeyword = searchedPostContent.substring(indices[0] - 10, indices[0]);//关键字前20字 | ||
var keyword = searchedPostContent.substring(indices[0], indices[1] + 1);//关键字 | ||
var afterKeyword = searchedPostContent.substring(indices[1] + 1, indices[1] + 70);//关键字后80字 | ||
preview = beforeKeyword + '<span class="searched-keyword">' | ||
+ keyword + '</span>' + afterKeyword; | ||
} else {//没有匹配到文章内容,则是标题 | ||
preview = searchedPostContent.substring(0, 80); | ||
} | ||
} | ||
return preview + '...'; | ||
} | ||
|
||
//循环匹配搜索到的内容与展示信息 | ||
function getResult(infos, searchedContents) { | ||
var searchedInfos = JSON.parse(JSON.stringify(infos));//对象深拷贝 | ||
searchedInfos.posts = []; | ||
for (var i = 0; i < infos.posts.length; i++) { | ||
for (var j = 0; j < searchedContents.length; j++) { | ||
if (searchedContents[j].item.link === infos.posts[i].link) { | ||
infos.posts[i].searchedPreview = keywordsHighlight(searchedContents[j]);//预览关键字高亮 | ||
infos.posts[i].content = searchedContents[j].item.content;//content注入 | ||
searchedInfos.posts.push(infos.posts[i]);//push到所需结果中 | ||
} | ||
} | ||
} | ||
return searchedInfos; | ||
} | ||
|
||
//主方法 | ||
function grideaSearch() { | ||
//搜索结果回调 | ||
var resultHandler = function (searchedContents) { | ||
getInfos(function (infos) { | ||
//console.log(infos); | ||
//console.log(searchedContents); | ||
var searchedInfos = getResult(infos, searchedContents); | ||
renderResult(searchedInfos); | ||
}); | ||
} | ||
searchByParam(resultHandler); | ||
} | ||
|
||
//页面加载完执行 | ||
window.onload = function () { | ||
grideaSearch(); | ||
} |
22 changes: 22 additions & 0 deletions
22
bitcron-pro-plus/assets/media/gridea-search/result-template.ejs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<div class="post-container"> | ||
<% posts.forEach(function(post,seq) { %> | ||
<article class="post"> | ||
<a href="<%= post.link %>"> | ||
<h2 class="post-title"><%= post.title %></h2> | ||
</a> | ||
<div class="post-info"> | ||
<time class="post-time"> | ||
· <%= post.dateFormat %> · | ||
</time> | ||
<% post.tags.forEach(function(tag) { %> | ||
<a href="<%= tag.link %>" class="post-tag"> | ||
# <%= tag.name %> | ||
</a> | ||
<% }); %> | ||
</div> | ||
<div class="post-abstract" style="word-break: break-all"> | ||
<%- post.searchedPreview %> | ||
</div> | ||
</article> | ||
<% }); %> | ||
</div> |
Binary file added
BIN
+15.4 KB
...pro-plus/assets/media/images/custom-array-imguploud-1666488314977-uploadimg.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+527 KB
...pro-plus/assets/media/images/custom-array-imguploud-1666488314981-uploadimg.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.