364 lines
10 KiB
Plaintext
364 lines
10 KiB
Plaintext
<template>
|
||
<view class="container">
|
||
<view class="search">
|
||
<uni-cms-article-search-bar
|
||
ref="searchBar"
|
||
v-model="searchVal"
|
||
:show-placeholder="false"
|
||
:focus="true"
|
||
@clear="showSearchResultPanel = false"
|
||
@confirm="search"
|
||
></uni-cms-article-search-bar>
|
||
</view>
|
||
<view class="search-result" v-if="showSearchResultPanel">
|
||
<uni-cms-article-list
|
||
ref="articleList"
|
||
:collectionList="colList"
|
||
:refresherEnabled="false"
|
||
loadTime="manual"
|
||
style="flex: 1;"
|
||
></uni-cms-article-list>
|
||
</view>
|
||
<template v-else>
|
||
<view class="panel history-panel" v-if="searchHistory.length > 0">
|
||
<view class="panel__title">
|
||
<view class="panel__title-text">
|
||
<text class="text">搜索历史</text>
|
||
</view>
|
||
|
||
<view class="delete-history-btns" v-if="deleteHistoryLoading">
|
||
<text class="text" @click="deleteAllSearchHistory">全部删除</text>
|
||
<text class="text danger" @click="deleteHistoryLoading = false">完成</text>
|
||
</view>
|
||
<uni-cms-article-icons
|
||
class="panel__after-icon"
|
||
type="trash"
|
||
:size="18"
|
||
color="#999"
|
||
@click="deleteHistoryLoading = true"
|
||
v-else
|
||
></uni-cms-article-icons>
|
||
</view>
|
||
<view class="panel__list">
|
||
<view class="panel__list-item" v-for="text in searchHistory">
|
||
<text class="text" @click="search(text)">{{text}}</text>
|
||
<uni-cms-article-icons
|
||
class="icon"
|
||
type="closeempty"
|
||
:size="12"
|
||
color="#999"
|
||
v-if="deleteHistoryLoading"
|
||
@click="deleteSearchHistory(text)"
|
||
></uni-cms-article-icons>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<unicloud-db ref="udb" #default="{ data, loading, error }" field="content"
|
||
collection="opendb-search-hot" orderby="create_date desc,count desc" page-data="replace"
|
||
:page-size="10">
|
||
<view class="panel recommend-panel">
|
||
<view class="panel__title">
|
||
<view class="panel__title-text">
|
||
<text class="text">搜索发现</text>
|
||
<uni-cms-article-icons
|
||
class="icon"
|
||
type="reload"
|
||
:size="14"
|
||
color="#999"
|
||
v-if="!hideSearchRecommend"
|
||
@click="reLoadSearchRecommend"
|
||
></uni-cms-article-icons>
|
||
</view>
|
||
<uni-cms-article-icons
|
||
class="panel__after-icon"
|
||
:type="hideSearchRecommend ? 'eye-slash': 'eye'"
|
||
:size="18"
|
||
color="#999"
|
||
@click="hideSearchRecommend = !hideSearchRecommend"
|
||
></uni-cms-article-icons>
|
||
</view>
|
||
<view class="panel__list">
|
||
<view class="panel__list-tip" v-if="loading">
|
||
<text class="text">正在加载...</text>
|
||
</view>
|
||
<view class="panel__list-tip" v-else-if="error != null">
|
||
<text class="text">{{error.message}}</text>
|
||
</view>
|
||
<view class="panel__list-tip" v-else-if="hideSearchRecommend">
|
||
<text class="text">当前搜索发现已隐藏</text>
|
||
</view>
|
||
<template v-else>
|
||
<view
|
||
class="panel__list-item"
|
||
v-for="(word, index) in data"
|
||
:key="index"
|
||
@click="search(word.getString('content')!)"
|
||
>
|
||
<text class="text">{{ word.getString('content') }}</text>
|
||
</view>
|
||
</template>
|
||
</view>
|
||
</view>
|
||
</unicloud-db>
|
||
</template>
|
||
</view>
|
||
</template>
|
||
|
||
<script lang="uts">
|
||
type ArticleAuthor = {
|
||
_id: string
|
||
nickname: string
|
||
}
|
||
type ArticleItem = {
|
||
_id: string
|
||
title: string
|
||
publish_date: number
|
||
thumbnail: string[]
|
||
user_id: ArticleAuthor[]
|
||
}
|
||
|
||
const db = uniCloud.databaseForJQL()
|
||
const searchLogDB = db.collection('opendb-search-log')
|
||
const cmsArticleDB = db.collection('uni-cms-articles')
|
||
const uniIdUsersDB = db.collection('uni-id-users')
|
||
const localSearchHistoryKey = '__local_search_history'; // 本地历史存储字段名
|
||
const localSearchRecommendHiddenKey = '__local_search_recommend_hidden'; // 本地搜索发现开关字段名
|
||
const localSearchHistoryMax = 10; // 本地历史存储最大值
|
||
export default {
|
||
data() {
|
||
const localSearchRecommendHidden = uni.getStorageSync(localSearchRecommendHiddenKey)
|
||
|
||
return {
|
||
searchVal: "",
|
||
searchHistory: [] as string[],
|
||
searchRecommend: [] as string[],
|
||
deleteHistoryLoading: false,
|
||
hideSearchRecommend: (localSearchRecommendHidden == "" ? false : localSearchRecommendHidden) as boolean,
|
||
showSearchResultPanel: false,
|
||
searchResult: [] as ArticleItem[]
|
||
}
|
||
},
|
||
watch: {
|
||
hideSearchRecommend(newValue) {
|
||
uni.setStorageSync(localSearchRecommendHiddenKey, newValue)
|
||
}
|
||
},
|
||
computed: {
|
||
hasSearchValue(): boolean {
|
||
return this.searchVal != ""
|
||
},
|
||
where(): string {
|
||
let where = "\"article_status\" == 1"
|
||
|
||
if (this.searchVal != "") {
|
||
where += `&& /${this.searchVal}/.test(title)`
|
||
}
|
||
|
||
return where
|
||
},
|
||
colList(): any[] {
|
||
// 返回文章和用户列表
|
||
return [
|
||
cmsArticleDB.where(this.where).field('thumbnail,title,publish_date,user_id').getTemp(),
|
||
uniIdUsersDB.field('_id,nickname').getTemp()
|
||
]
|
||
}
|
||
},
|
||
mounted() {
|
||
// 本地历史存储
|
||
const localSearchHistory = uni.getStorageSync(localSearchHistoryKey)
|
||
this.searchHistory = (localSearchHistory == "" ? [] as string[] : localSearchHistory) as string[]
|
||
},
|
||
methods: {
|
||
deleteAllSearchHistory() {
|
||
uni.showModal({
|
||
title: "确定清空搜索历史吗",
|
||
confirmText: "删除",
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
this.deleteSearchHistory(null)
|
||
}
|
||
}
|
||
})
|
||
},
|
||
deleteSearchHistory(searchText: string | null) {
|
||
let history: string[] = []
|
||
if (searchText != null) {
|
||
history = this.searchHistory.filter((item: string): boolean => item != searchText)
|
||
}
|
||
|
||
this.searchHistory = history
|
||
uni.setStorageSync(localSearchHistoryKey, history)
|
||
|
||
console.log(history.length, 'history.length')
|
||
if (history.length <= 0) {
|
||
this.deleteHistoryLoading = false
|
||
}
|
||
},
|
||
search(searchText: string) {
|
||
searchText = searchText.trim()
|
||
|
||
if (searchText == "" || this.deleteHistoryLoading) return
|
||
// 隐藏键盘
|
||
;(this.$refs['searchBar'] as UniCmsArticleSearchBarComponentPublicInstance)!.hideKeyboard()
|
||
|
||
// 保存搜索历史
|
||
this.setLocalSearchHistory(searchText)
|
||
// 显示搜索结果Panel
|
||
this.showSearchResultPanel = true
|
||
// 搜索
|
||
this.loadSearchResult(searchText)
|
||
// 添加搜索记录
|
||
this.addSearchRecord(searchText)
|
||
},
|
||
loadSearchResult(searchText: string) {
|
||
// 设置查询条件
|
||
this.searchVal = searchText
|
||
|
||
// 延迟0ms后加载数据
|
||
setTimeout(() => {
|
||
(this.$refs['articleList'] as UniCmsArticleListComponentPublicInstance)!.reLoadList()
|
||
}, 0)
|
||
},
|
||
addSearchRecord(searchText: string) {
|
||
const systemInfo = uni.getSystemInfoSync()
|
||
/*
|
||
在此处存搜索记录,如果登录则需要存 user_id,若未登录则存device_id
|
||
*/
|
||
searchLogDB.add({
|
||
// user_id: device_id,
|
||
device_id: systemInfo.deviceId,
|
||
// device_uuid: systemInfo.deviceId,
|
||
content: searchText,
|
||
create_date: Date.now()
|
||
})
|
||
},
|
||
setLocalSearchHistory(searchText: string) {
|
||
const history = this.searchHistory.filter((item: string): boolean => item != searchText)
|
||
|
||
history.unshift(searchText)
|
||
|
||
if (history.length > localSearchHistoryMax) {
|
||
history.pop()
|
||
}
|
||
|
||
this.searchHistory = history
|
||
this.deleteHistoryLoading = false
|
||
uni.setStorageSync(localSearchHistoryKey, history)
|
||
},
|
||
reLoadSearchRecommend() {
|
||
(this.$refs['udb'] as UniCloudDBElement)!.loadData({
|
||
clear: true
|
||
})
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
.container {
|
||
display: flex;
|
||
flex-direction: column;
|
||
height: 100%;
|
||
|
||
.search-result {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
}
|
||
|
||
.panel {
|
||
margin-top: 40rpx;
|
||
padding: 10rpx 20rpx;
|
||
|
||
&__title {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
|
||
&-text {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
|
||
.text {
|
||
color: #3e3e3e;
|
||
font-size: 30rpx;
|
||
line-height: 36rpx;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.icon {
|
||
margin-left: 10rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
&__after-icon {
|
||
margin-left: 10rpx;
|
||
}
|
||
|
||
&__list {
|
||
margin-top: 30rpx;
|
||
display: flex;
|
||
flex-direction: row;
|
||
flex-wrap: wrap;
|
||
|
||
&-item {
|
||
background-color: #f6f6f6;
|
||
border-radius: 30rpx;
|
||
padding: 10rpx 20rpx;
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-right: 10rpx;
|
||
margin-bottom: 10rpx;
|
||
|
||
.text {
|
||
font-size: 26rpx;
|
||
color: #666;
|
||
}
|
||
|
||
.icon {
|
||
margin-left: 10rpx;
|
||
}
|
||
}
|
||
|
||
&-tip {
|
||
display: flex;
|
||
flex-direction: row;
|
||
justify-content: center;
|
||
flex: 1;
|
||
margin-top: 20rpx;
|
||
|
||
.text {
|
||
font-size: 26rpx;
|
||
color: #808080;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.delete-history-btns {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.text {
|
||
color: #666;
|
||
font-size: 22rpx;
|
||
margin-left: 20rpx;
|
||
|
||
&.danger {
|
||
color: #c0402b;
|
||
}
|
||
}
|
||
}
|
||
|
||
</style>
|