💩 搜索功能
This commit is contained in:
parent
2619e151a5
commit
05e0fa354a
@ -10,7 +10,7 @@
|
|||||||
<span v-if="isPerfect(article.articlePerfect)" style="color: gold;" title="优选">
|
<span v-if="isPerfect(article.articlePerfect)" style="color: gold;" title="优选">
|
||||||
<font-awesome-icon :icon="['fas', 'medal']"></font-awesome-icon>
|
<font-awesome-icon :icon="['fas', 'medal']"></font-awesome-icon>
|
||||||
</span>
|
</span>
|
||||||
{{ article.articleTitle }}
|
<span v-html="article.articleTitle"></span>
|
||||||
</h4>
|
</h4>
|
||||||
</el-link>
|
</el-link>
|
||||||
<el-tag
|
<el-tag
|
||||||
@ -21,7 +21,7 @@
|
|||||||
effect="plain">
|
effect="plain">
|
||||||
# {{ tag.tagTitle }}
|
# {{ tag.tagTitle }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
<div class="text-muted article-summary-md">{{ article.articlePreviewContent }}</div>
|
<div class="text-muted article-summary-md" v-html="article.articlePreviewContent"></div>
|
||||||
<el-row class="pt-5">
|
<el-row class="pt-5">
|
||||||
<el-col :xs="3" :sm="1" :xl="1" class="mr-3">
|
<el-col :xs="3" :sm="1" :xl="1" class="mr-3">
|
||||||
<el-avatar v-if="article.articleAuthorAvatarUrl" size="medium"
|
<el-avatar v-if="article.articleAuthorAvatarUrl" size="medium"
|
||||||
|
@ -10,11 +10,11 @@
|
|||||||
<div style="padding: 0 10px;">
|
<div style="padding: 0 10px;">
|
||||||
<h4 class="article-header-md">
|
<h4 class="article-header-md">
|
||||||
<el-link rel="nofollow" @click="onRouter('portfolio',portfolio.idPortfolio)" :underline="false">
|
<el-link rel="nofollow" @click="onRouter('portfolio',portfolio.idPortfolio)" :underline="false">
|
||||||
{{ portfolio.portfolioTitle }}
|
<span v-html="portfolio.portfolioTitle"></span>
|
||||||
</el-link>
|
</el-link>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-muted article-summary-md">{{ portfolio.portfolioDescription }}</div>
|
<div class="text-muted article-summary-md" v-html="portfolio.portfolioDescription"></div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col v-else style="margin-bottom: 20px;">
|
<el-col v-else style="margin-bottom: 20px;">
|
||||||
|
@ -8,9 +8,9 @@
|
|||||||
<el-col :span="21">
|
<el-col :span="21">
|
||||||
<div>
|
<div>
|
||||||
<el-link rel="nofollow" @click="onRouter(user.account)" :underline="false" class="text-default">
|
<el-link rel="nofollow" @click="onRouter(user.account)" :underline="false" class="text-default">
|
||||||
{{ user.nickname }}
|
<span v-html="user.nickname"></span>
|
||||||
</el-link>
|
</el-link>
|
||||||
<small class="d-block text-muted">{{ user.signature }}</small>
|
<small class="d-block text-muted" v-html="user.signature"></small>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
@ -19,29 +19,7 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :xs="10" :sm="6" :md="6" :xl="6" style="padding-top: 1rem;text-align: right;">
|
<el-col :xs="10" :sm="6" :md="6" :xl="6" style="padding-top: 1rem;text-align: right;">
|
||||||
<el-autocomplete
|
<el-input size="small" v-model="queryString" @keyup.enter.native="querySearchAsync"/>
|
||||||
v-model="queryString"
|
|
||||||
size="small"
|
|
||||||
value-key="label"
|
|
||||||
:fetch-suggestions="querySearchAsync"
|
|
||||||
placeholder="搜索帖子、作品集和用户"
|
|
||||||
:trigger-on-focus="false"
|
|
||||||
@select="handleSelect"
|
|
||||||
style="width: 80%;"
|
|
||||||
popper-class="search-result-box"
|
|
||||||
>
|
|
||||||
<template slot-scope="{ item }">
|
|
||||||
<el-col>
|
|
||||||
<span class="search-result-type">
|
|
||||||
<small class="text-muted" v-html="getSearchResultType(item.type)"></small>
|
|
||||||
</span>
|
|
||||||
<span>{{ item.label }}</span>
|
|
||||||
</el-col>
|
|
||||||
</template>
|
|
||||||
<!-- <template slot="append">-->
|
|
||||||
<!-- <el-button size="small" icon="el-icon-search" @click="search"></el-button>-->
|
|
||||||
<!-- </template>-->
|
|
||||||
</el-autocomplete>
|
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :xs="6" :sm="6" :md="6" :xl="3" style="padding-top: 1rem;">
|
<el-col :xs="6" :sm="6" :md="6" :xl="3" style="padding-top: 1rem;">
|
||||||
<client-only>
|
<client-only>
|
||||||
@ -115,8 +93,7 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
...mapState({
|
...mapState({
|
||||||
activeMenu: state => state.activeMenu,
|
activeMenu: state => state.activeMenu,
|
||||||
user: state => state.oauth,
|
user: state => state.oauth
|
||||||
initialSearchData: state => state.search.list
|
|
||||||
}),
|
}),
|
||||||
avatarURL() {
|
avatarURL() {
|
||||||
let _ts = this;
|
let _ts = this;
|
||||||
@ -173,21 +150,10 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
querySearchAsync(queryString, cb) {
|
querySearchAsync() {
|
||||||
let initialSearchData = this.initialSearchData;
|
this.$router.push({
|
||||||
let results = queryString ? initialSearchData.filter(this.createStateFilter(queryString)) : initialSearchData;
|
path: `/search?q=${this.queryString}`
|
||||||
|
})
|
||||||
clearTimeout(this.timeout);
|
|
||||||
this.timeout = setTimeout(() => {
|
|
||||||
cb(results);
|
|
||||||
}, 3000 * Math.random());
|
|
||||||
},
|
|
||||||
createStateFilter(queryString) {
|
|
||||||
return (state) => {
|
|
||||||
if (state && state.label) {
|
|
||||||
return (state.label.toLowerCase().indexOf(queryString.toLowerCase()) > -1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
handleSelectMenu(item) {
|
handleSelectMenu(item) {
|
||||||
let _ts = this;
|
let _ts = this;
|
||||||
@ -217,15 +183,6 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleSelect(item) {
|
|
||||||
console.log(item);
|
|
||||||
let _ts = this;
|
|
||||||
if (item) {
|
|
||||||
_ts.$router.push({
|
|
||||||
path: `/${item.type}/${item.value}`
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleCommand(item) {
|
handleCommand(item) {
|
||||||
let _ts = this;
|
let _ts = this;
|
||||||
switch (item) {
|
switch (item) {
|
||||||
@ -260,23 +217,6 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
|
||||||
search() {
|
|
||||||
console.log(this.queryString)
|
|
||||||
},
|
|
||||||
getSearchResultType(type) {
|
|
||||||
switch (type) {
|
|
||||||
case 'article':
|
|
||||||
type = '文章';
|
|
||||||
break;
|
|
||||||
case 'portfolio':
|
|
||||||
type = '作品集';
|
|
||||||
break;
|
|
||||||
case 'user':
|
|
||||||
type = '用户';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
99
pages/search.vue
Normal file
99
pages/search.vue
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
<template>
|
||||||
|
<el-row class="wrapper">
|
||||||
|
<el-col>
|
||||||
|
<el-input v-model="q" @keyup.enter.native="search"/>
|
||||||
|
</el-col>
|
||||||
|
<el-col>
|
||||||
|
<el-tabs v-model="activeName">
|
||||||
|
<el-tab-pane :label="'文章 (' + getLength(articles.pagination) + ')'" name="articles">
|
||||||
|
<article-list :articles="articles" @currentChange="currentChangeArticle"/>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane :label="'用户 (' + getLength(users.pagination) + ')'" name="users">
|
||||||
|
<user-list :users="users" @currentChange="currentChangeUser"/>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane :label="'作品集 (' + getLength(portfolios.pagination) + ')'" name="portfolios">
|
||||||
|
<portfolio-list :portfolios="portfolios" @currentChange="currentChangePortfolio"/>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {mapState} from "vuex";
|
||||||
|
import ArticleList from "../components/archive/list";
|
||||||
|
import UserList from "../components/common/user/list";
|
||||||
|
import PortfolioList from "../components/common/portfolio/list";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "search",
|
||||||
|
fetch({store, query, error}) {
|
||||||
|
return Promise.all([
|
||||||
|
store
|
||||||
|
.dispatch('search/fetchArticleList', {queryString: query.q})
|
||||||
|
.catch(err => error({statusCode: 404})),
|
||||||
|
store
|
||||||
|
.dispatch('search/fetchUserList', {queryString: query.q})
|
||||||
|
.catch(err => error({statusCode: 404})),
|
||||||
|
store
|
||||||
|
.dispatch('search/fetchPortfolioList', {queryString: query.q})
|
||||||
|
.catch(err => error({statusCode: 404}))
|
||||||
|
])
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'$route.query': function () {
|
||||||
|
let _ts = this;
|
||||||
|
let queryString = _ts.$route.query.q;
|
||||||
|
_ts.$set(_ts, "q", queryString);
|
||||||
|
this.$store.dispatch('search/fetchArticleList', {queryString: queryString})
|
||||||
|
this.$store.dispatch('search/fetchUserList', {queryString: queryString})
|
||||||
|
this.$store.dispatch('search/fetchPortfolioList', {queryString: queryString})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {PortfolioList, UserList, ArticleList},
|
||||||
|
computed: {
|
||||||
|
...mapState({
|
||||||
|
articles: state => state.search.articles.data,
|
||||||
|
users: state => state.search.users.data,
|
||||||
|
portfolios: state => state.search.portfolios.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
q: '',
|
||||||
|
activeName: 'articles'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
search() {
|
||||||
|
this.$store.dispatch("search/fetchArticleList", {queryString: this.q});
|
||||||
|
this.$store.dispatch("search/fetchUserList", {queryString: this.q});
|
||||||
|
this.$store.dispatch("search/fetchPortfolioList", {queryString: this.q});
|
||||||
|
},
|
||||||
|
currentChangeArticle(page) {
|
||||||
|
this.$store.dispatch("search/fetchArticleList", {queryString: this.q, page: page});
|
||||||
|
},
|
||||||
|
currentChangeUser(page) {
|
||||||
|
this.$store.dispatch("search/fetchUserList", {queryString: this.q, page: page});
|
||||||
|
},
|
||||||
|
currentChangePortfolio(page) {
|
||||||
|
this.$store.dispatch("search/fetchPortfolioList", {queryString: this.q, page: page});
|
||||||
|
},
|
||||||
|
getLength(pagination) {
|
||||||
|
if (pagination.total) {
|
||||||
|
return pagination.total;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
let _ts = this;
|
||||||
|
let queryString = _ts.$route.query.q;
|
||||||
|
_ts.$set(_ts, "q", queryString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -76,8 +76,7 @@ export const actions = {
|
|||||||
const initFetchAppData = [
|
const initFetchAppData = [
|
||||||
// 内容数据
|
// 内容数据
|
||||||
store.dispatch('topic/fetchNavList'),
|
store.dispatch('topic/fetchNavList'),
|
||||||
store.dispatch('article/fetchList'),
|
store.dispatch('article/fetchList')
|
||||||
store.dispatch('search/fetchList'),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
return Promise.all(initFetchAppData)
|
return Promise.all(initFetchAppData)
|
||||||
|
127
store/search.js
127
store/search.js
@ -1,9 +1,39 @@
|
|||||||
export const BASE_API_PATH = '/api/console';
|
export const BASE_API_PATH = '/api/lucene';
|
||||||
|
const getDefaultArticleListData = () => {
|
||||||
|
return {
|
||||||
|
articles: [],
|
||||||
|
pagination: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const getDefaultUserListData = () => {
|
||||||
|
return {
|
||||||
|
users: [],
|
||||||
|
pagination: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const getDefaultPortfolioListData = () => {
|
||||||
|
return {
|
||||||
|
portfolios: [],
|
||||||
|
pagination: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const state = () => {
|
export const state = () => {
|
||||||
return {
|
return {
|
||||||
fetching: false,
|
fetching: false,
|
||||||
list: []
|
list: [],
|
||||||
|
articles: {
|
||||||
|
fetching: false,
|
||||||
|
data: getDefaultArticleListData()
|
||||||
|
},
|
||||||
|
users: {
|
||||||
|
fetching: false,
|
||||||
|
data: getDefaultUserListData()
|
||||||
|
},
|
||||||
|
portfolios: {
|
||||||
|
fetching: false,
|
||||||
|
data: getDefaultPortfolioListData()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,25 +44,102 @@ export const mutations = {
|
|||||||
},
|
},
|
||||||
updateListData(state, action) {
|
updateListData(state, action) {
|
||||||
state.list = action
|
state.list = action
|
||||||
}
|
},
|
||||||
|
// 数据列表
|
||||||
|
updateArticleListFetching(state, action) {
|
||||||
|
state.articles.fetching = action
|
||||||
|
},
|
||||||
|
updateArticleListData(state, action) {
|
||||||
|
state.articles.data = action
|
||||||
|
},
|
||||||
|
// 数据列表
|
||||||
|
updateUserListFetching(state, action) {
|
||||||
|
state.users.fetching = action
|
||||||
|
},
|
||||||
|
updateUserListData(state, action) {
|
||||||
|
state.users.data = action
|
||||||
|
},
|
||||||
|
// 数据列表
|
||||||
|
updatePortfolioFetching(state, action) {
|
||||||
|
state.portfolios.fetching = action
|
||||||
|
},
|
||||||
|
updatePortfolioListData(state, action) {
|
||||||
|
state.portfolios.data = action
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
// 获取文章列表
|
// 获取文章列表
|
||||||
fetchList({commit}, params = {}) {
|
fetchArticleList({commit}, params = {}) {
|
||||||
// 清空已有数据
|
// 清空已有数据
|
||||||
commit('updateListData', []);
|
commit('updateArticleListData', getDefaultArticleListData());
|
||||||
commit('updateListFetching', true);
|
if (!params.queryString) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
commit('updateArticleListFetching', true);
|
||||||
|
|
||||||
return this.$axios
|
return this.$axios
|
||||||
.$get(`${BASE_API_PATH}/initial-search`)
|
.$get(`${BASE_API_PATH}/search-article`, {
|
||||||
|
params: {
|
||||||
|
q: params.queryString,
|
||||||
|
page: params.page || 1
|
||||||
|
}
|
||||||
|
})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
commit('updateListFetching', false);
|
commit('updateArticleListFetching', false);
|
||||||
commit('updateListData', response);
|
commit('updateArticleListData', response ? response : getDefaultArticleListData());
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
commit('updateListFetching', false);
|
commit('updateArticleListFetching', false);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fetchUserList({commit}, params = {}) {
|
||||||
|
// 清空已有数据
|
||||||
|
commit('updateUserListData', getDefaultUserListData());
|
||||||
|
if (!params.queryString) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
commit('updateUserListFetching', true);
|
||||||
|
|
||||||
|
return this.$axios
|
||||||
|
.$get(`${BASE_API_PATH}/search-user`, {
|
||||||
|
params: {
|
||||||
|
q: params.queryString,
|
||||||
|
page: params.page || 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
commit('updateUserListFetching', false);
|
||||||
|
commit('updateUserListData', response ? response : getDefaultUserListData());
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.log(error);
|
||||||
|
commit('updateUserListFetching', false);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fetchPortfolioList({commit}, params = {}) {
|
||||||
|
// 清空已有数据
|
||||||
|
commit('updatePortfolioListData', getDefaultPortfolioListData());
|
||||||
|
if (!params.queryString) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
commit('updatePortfolioFetching', true);
|
||||||
|
|
||||||
|
return this.$axios
|
||||||
|
.$get(`${BASE_API_PATH}/search-portfolio`, {
|
||||||
|
params: {
|
||||||
|
q: params.queryString,
|
||||||
|
page: params.page || 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
commit('updatePortfolioFetching', false);
|
||||||
|
commit('updatePortfolioListData', response ? response : getDefaultPortfolioListData());
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.log(error);
|
||||||
|
commit('updatePortfolioFetching', false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user