全文检索移动端适配

This commit is contained in:
结发受长生 2019-07-08 21:14:40 +08:00
parent 0917a4c8ed
commit 0e94c2d863
5 changed files with 97 additions and 59 deletions

View File

@ -1,20 +1,25 @@
<div class="page-modal js-search-box" ref="fullTextSearch" >
<a class="close js-modal-close" href="javascript:;"><i class="icon icon-close"></i></a>
<div class="search">
<div class="search-input-icon">
<i class="icon icon-search"></i>
<div class="page-modal" id="search-panel" ref="fullTextSearch" >
<div class="search-container">
<a class="close js-modal-close" href="javascript:;"><i class="icon icon-close"></i></a>
<div class="search">
<div class="search-input-icon">
<i class="icon icon-search"></i>
</div>
<div class="search-input" >
<input placeholder="搜索所有文章" type="text" v-model="fullTextSearchWords" >
</div>
</div>
<div class="search-input" >
<input placeholder="搜索所有文章" type="text" v-model="fullTextSearch.words" >
</div>
</div>
<div class="search-result">
<div class="search-result-item" v-for="(item,index) in fullTextSearchItems" :key="index">
<a v-text="item.title" :href="themeConfig.root + item.path"></a>
<div v-html="item.content"></div>
</div>
<div class="more-item" v-show="fullTextSearchItems.hasMore" @click="loadMoreSearchResult">
<i class="icon icon-chevron-up"></i>
<div class="search-result">
<div class="search-result-item" v-for="(item,index) in fullTextSearchItems" :key="index">
<a v-text="item.title" :href="themeConfig.root + item.path"></a>
<div v-html="item.content"></div>
</div>
<div class="more-item tip" v-show="fullTextSearchItems.hasMore" @click="loadSearchResult">
<i class="icon icon-chevron-up"></i>
</div>
<div class="tip" v-show="fullTextSearchItems.isLoading || fullTextSearchTip"
v-text="fullTextSearchTip || '正在搜索...'"></div>
</div>
</div>
</div>

View File

@ -341,4 +341,20 @@
}
}
}
}
#search-panel {
width: 100%;
height: 100%;
top: 0;
left: 0;
transform: none;
.search-container {
display: flex;
width: 100%;
height: 100%;
flex-direction: column;
.search-result {
flex-grow: 1;
}
}
}

View File

@ -61,7 +61,6 @@
&.in {
display: block;
visibility: visible;
opacity: 1;
}
@ -79,7 +78,7 @@
}
.mask {
visibility: hidden;
display: none;
position: fixed;
top: 0;
left: 0;
@ -93,7 +92,7 @@
pointer-events: none;
transition: .3s ease-in-out;
&.in {
visibility: visible;
display: block;
pointer-events: auto;
opacity: .3;
}

View File

@ -245,13 +245,12 @@ label.bui-switch-label {
}
}
.js-search-box {
#search-panel {
width: 500px;
top: 10%;
transform: translate(-50%,0);
.search {
border-bottom: 1px solid #ccc;
background: #f5f5f5;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
width: 500px;
display: flex;
line-height: 40px;
.search-input-icon {
@ -269,9 +268,9 @@ label.bui-switch-label {
}
}
.search-result {
height: 600px;
width: 500px;
max-height: 600px;
overflow-y: auto;
position: relative;
.search-result-item {
text-align: left;
border-bottom: 1px dashed $colorC;
@ -280,10 +279,16 @@ label.bui-switch-label {
border-bottom-color: $colorA;
}
}
.tip {
text-align: center;
}
.more-item {
cursor: pointer;
text-align: center;
transform: rotate(180deg)
}
transform: rotate(180deg) translateY(60px);
background: linear-gradient(-180deg,$colorBg 10%,rgba(255, 255, 255, 0) 100%);
position: absolute;
height: 70px;
width: 100%;
}
}
}

View File

@ -31,9 +31,10 @@ new Vue({
fullTextSearch: {
pageNum: 1,
limit: 10,
words: null
},
fullTextSearchWords: null,
fullTextSearchItems: [],
fullTextSearchTip: undefined,
waifu: {
tip: null, // 提示语文字
tipOpacity: 0, // 提示语框透明度
@ -93,12 +94,26 @@ new Vue({
this.$refs.fullTextSearch.classList.add('in')
this.$refs.mask.classList.add('in')
},
loadMoreSearchResult() {
loadSearchResult() {
this.fullTextSearch.pageNum ++
axios.get(window.themeConfig.root + 'api/common/search', {params: this.fullTextSearch}).then(res => {
this.fullTextSearchItems.isLoading = true
this.fullTextSearchTip = undefined
let params = Object.assign({}, this.fullTextSearch)
params.words = this.fullTextSearchWords
axios.get(/*window.themeConfig.root + 'api/common/search'*/ 'http://localhost:3301/common/search', {params}).then(res => {
this.fullTextSearchItems.isLoading = false
fullTextSearchTimer = null
let result = res.data
if(!Array.isArray(result.data) || !result.data.length) {
this.fullTextSearchTip = '未搜索到匹配文章'
} else {
this.fullTextSearchItems.push(...result.data)
}
this.fullTextSearchItems.hasMore = (result.total > this.fullTextSearch.pageNum * this.fullTextSearch.limit)
this.fullTextSearchItems.push(...result.data)
}).catch(err => {
this.fullTextSearchTip = '加载失败, 请刷新重试'
this.fullTextSearchItems.isLoading = false
throw err
})
},
searchKeydown(event) {
@ -138,31 +153,29 @@ new Vue({
})
}
},
fullTextSearch: {
deep: true,
handler(newVal, oldVal) {
if(!newVal.words) {
return
}
if(fullTextSearchTimer) {
clearTimeout(fullTextSearchTimer)
}
fullTextSearchTimer = setTimeout(() => {
this.fullTextSearchItems.length = 0
axios.get(window.themeConfig.root + 'api/common/search', {params: newVal}).then(res => {
let result = res.data
this.fullTextSearchItems.hasMore = (result.total > this.fullTextSearch.pageNum * this.fullTextSearch.limit)
this.fullTextSearchItems.push(...result.data)
})
}, 1000)
}
fullTextSearchWords (newVal, oldVal) {
this.fullTextSearchItems.hasMore = false
this.fullTextSearchItems.isLoading = false
this.fullTextSearchTip = undefined
this.fullTextSearchItems.splice(0, this.fullTextSearchItems.length)
if(fullTextSearchTimer) {
clearTimeout(fullTextSearchTimer)
fullTextSearchTimer = null
}
if(!newVal) {
return
}
this.fullTextSearch.pageNum = 0
fullTextSearchTimer = setTimeout(() => {
this.fullTextSearchItems.splice(0, this.fullTextSearchItems.length)
this.loadSearchResult()
}, 500)
}
},
mounted () {
axios.get(window.themeConfig.root + 'content.json?t=' + (+ new Date()))
.then((res)=>{
axios.get(window.themeConfig.root + 'content.json').then((res)=>{
this.items = res.data
}).catch((err) => {
}).catch(err => {
console.warn('加载文章列表失败')
})
this.showMessage(welcomeMessage(), 6000)
@ -238,28 +251,28 @@ function welcomeMessage() {
}
const waifuTools = {
"tools.photo"() {
'tools.photo'() {
// 生成canvas快照
window.Live2D.captureName = 'Kesshouban.png'
window.Live2D.captureFrame = true
},
"tools.close"() {
'tools.close'() {
// 隐藏看板娘
setTimeout(function() {
document.querySelector('.waifu').style.display = 'none'
localStorage.setItem('hideWaifu', true)
}, 1300)
},
"tools.eye"() {
'tools.eye'() {
// 切换到夜间模式
document.querySelector('.mid-col').classList.remove('hide')
let night = document.querySelector('body').classList.toggle('night')
localStorage.setItem('night', night)
},
"tools.info"() {
'tools.info'() {
window.open('https://github.com/xiazeyu/live2d-widget.js')
},
"tools.chart"() {
'tools.chart'() {
// 一言
axios.get(`${window.themeConfig.root}api/common/hitokoto?length=40&format=json`).then(res => {
this.showMessage(res.data.hitokoto + (res.data.from?`  ——${res.data.from}`:''))