|
|
@@ -1,75 +1,52 @@
|
|
|
<script setup lang="ts">
|
|
|
-import { onMounted, onUnmounted, ref, watch } from "vue";
|
|
|
+import { onUnmounted, ref, type Ref, onMounted } from "vue";
|
|
|
import { useRoute, useRouter } from "vue-router";
|
|
|
-import { message, type SelectProps } from "ant-design-vue";
|
|
|
import { useSideBarStore } from "@/stores/side-bar";
|
|
|
-import SearchResultItem from "./components/SearchResultItem.vue";
|
|
|
import searchService from "@/services/search.service";
|
|
|
+import type { SearchResult } from "@/types/search.types";
|
|
|
+import SearchBox from "./components/SearchBox.vue";
|
|
|
+import SearchResultToolbar from "./components/SearchResultToolbar.vue";
|
|
|
+import SearchResultList from "./components/SearchResultList.vue";
|
|
|
|
|
|
const sideBarStore = useSideBarStore();
|
|
|
-
|
|
|
+// 路由管理器
|
|
|
+const router = useRouter();
|
|
|
+// 当前路由对象
|
|
|
const route = useRoute();
|
|
|
|
|
|
// 关键词
|
|
|
const keyword = ref("");
|
|
|
-// 搜索的字段
|
|
|
+// 字段
|
|
|
const field = ref("TP");
|
|
|
-// 路由
|
|
|
-const router = useRouter();
|
|
|
+// 排序
|
|
|
+const sort = ref("Relevance");
|
|
|
|
|
|
-function doSearch() {
|
|
|
- if (keyword.value.length == 0) {
|
|
|
- keyword.value = (route.query.kw as string) || "";
|
|
|
- if (keyword.value.length == 0) {
|
|
|
- router.push({name: "SearchIndex"});
|
|
|
- return;
|
|
|
- }
|
|
|
+// 搜索结果
|
|
|
+const searchResult: Ref<SearchResult | null> = ref(null);
|
|
|
+
|
|
|
+function doSearch(field: string, keyword: string) {
|
|
|
+ if (keyword && keyword.length == 0) {
|
|
|
+ router.push({name: "SearchIndex"});
|
|
|
+ return;
|
|
|
}
|
|
|
- searchService.search("query").then((resp) => {
|
|
|
- console.log(resp.data);
|
|
|
+ router.push({name: "SearchResult", query: { kw: keyword }});
|
|
|
+ const query = `${field}=(${keyword})`;
|
|
|
+ searchService.search(query).then((resp) => {
|
|
|
+ searchResult.value = resp.data.data;
|
|
|
}).catch((err) => {
|
|
|
console.log(err);
|
|
|
})
|
|
|
}
|
|
|
|
|
|
-// 搜索事件监听
|
|
|
-const onSearch = () => {
|
|
|
- router.push({name: 'SearchResult', query: { kw: keyword.value }});
|
|
|
-
|
|
|
- doSearch();
|
|
|
-}
|
|
|
-// 搜索框字段选择项列表
|
|
|
-const fieldOptions = ref<SelectProps['options']>([
|
|
|
- { value: 'TP', label: '主题', },
|
|
|
- { value: 'TI', label: '标题', },
|
|
|
- { value: 'AU', label: '作者', },
|
|
|
- { value: 'KW', label: '关键词', },
|
|
|
-]);
|
|
|
-// 排序方式
|
|
|
-const sortOption = ref('Relevance');
|
|
|
-// 排序选择项列表
|
|
|
-const sortOptions = ref<SelectProps['options']>([
|
|
|
- { value: 'Relevance', label: '按相关度排序' },
|
|
|
- { value: 'DateDesc', label: '按时间由近到远排序' },
|
|
|
- { value: 'DateAsc', label: '按时间由远到近排序' },
|
|
|
- { value: 'CitedDesc', label: '按被引量排序' },
|
|
|
-]);
|
|
|
-
|
|
|
-/**
|
|
|
- * 排序方式改变监听函数
|
|
|
- * @param event 排序方式改变事件
|
|
|
- */
|
|
|
-function handleSortChange(event: any) {
|
|
|
- console.log('handleSortChange', event);
|
|
|
-}
|
|
|
-
|
|
|
-const currentPage = ref(1);
|
|
|
-
|
|
|
onMounted(() => {
|
|
|
// 收起左侧边栏
|
|
|
sideBarStore.setCollapse(true);
|
|
|
-
|
|
|
- doSearch();
|
|
|
+ // 初始化关键词
|
|
|
+ if (route.query.kw) {
|
|
|
+ keyword.value = (route.query.kw as string).trim();
|
|
|
+ }
|
|
|
+ // 搜索
|
|
|
+ doSearch(field.value, keyword.value);
|
|
|
});
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
@@ -79,109 +56,53 @@ onUnmounted(() => {
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
|
- <div class="search-box-wrap">
|
|
|
- <a-row type="flex">
|
|
|
- <a-col>
|
|
|
- <a-select
|
|
|
- ref="select"
|
|
|
- v-model:value="field"
|
|
|
- style="width: 120px"
|
|
|
- :options="fieldOptions"
|
|
|
- size="large"
|
|
|
- ></a-select>
|
|
|
+ <div class="search-result-wrap">
|
|
|
+ <div class="search-box-wrap">
|
|
|
+ <SearchBox v-model:keyword="keyword" v-model:field="field" @search="doSearch" />
|
|
|
+ </div>
|
|
|
+ <a-row type="flex" class="search-result-main" :gutter="10">
|
|
|
+ <a-col :span="5">
|
|
|
+ <div class="left-filter-header">
|
|
|
+ 筛选
|
|
|
+ </div>
|
|
|
+ <a-space direction="vertical" style="width: 100%">
|
|
|
+ <a-card title="Default size card">
|
|
|
+ <p>card content</p>
|
|
|
+ <p>card content</p>
|
|
|
+ <p>card content</p>
|
|
|
+ </a-card>
|
|
|
+ <a-card title="Small size card">
|
|
|
+ <p>card content</p>
|
|
|
+ <p>card content</p>
|
|
|
+ <p>card content</p>
|
|
|
+ </a-card>
|
|
|
+ </a-space>
|
|
|
</a-col>
|
|
|
- <a-col flex="1">
|
|
|
- <a-input-search
|
|
|
- v-model:value="keyword"
|
|
|
- placeholder="请输入关键词进行搜索"
|
|
|
- enter-button="搜 索"
|
|
|
- size="large"
|
|
|
- @search="onSearch"
|
|
|
- />
|
|
|
+ <a-col :span="19">
|
|
|
+ <SearchResultToolbar :data="searchResult" v-model:sort="sort" v-if="searchResult" />
|
|
|
+ <SearchResultList :data="searchResult" v-if="searchResult" />
|
|
|
</a-col>
|
|
|
</a-row>
|
|
|
</div>
|
|
|
- <a-row type="flex" class="search-result-main" :gutter="10">
|
|
|
- <a-col :span="5" class="left-filter-wrap">
|
|
|
- <div class="left-filter-header">
|
|
|
- 筛选
|
|
|
- </div>
|
|
|
- <a-space direction="vertical" style="width: 100%">
|
|
|
- <a-card title="Default size card">
|
|
|
- <p>card content</p>
|
|
|
- <p>card content</p>
|
|
|
- <p>card content</p>
|
|
|
- </a-card>
|
|
|
- <a-card title="Small size card">
|
|
|
- <p>card content</p>
|
|
|
- <p>card content</p>
|
|
|
- <p>card content</p>
|
|
|
- </a-card>
|
|
|
- </a-space>
|
|
|
- </a-col>
|
|
|
- <a-col :span="19" class="right-content-wrap">
|
|
|
- <div class="right-header">
|
|
|
- <a-space>
|
|
|
- <span>搜索结果:共 XX 条</span>
|
|
|
- <a-divider type="vertical"></a-divider>
|
|
|
- <span>
|
|
|
- <span>显示:</span>
|
|
|
- <a-space>
|
|
|
- <a href="#">简洁</a>
|
|
|
- <a href="#">详细</a>
|
|
|
- </a-space>
|
|
|
- </span>
|
|
|
- <a-divider type="vertical"></a-divider>
|
|
|
- <a-select
|
|
|
- ref="select"
|
|
|
- v-model:value="sortOption"
|
|
|
- style="width: 160px"
|
|
|
- size="small"
|
|
|
- :options="sortOptions"
|
|
|
- @change="handleSortChange"
|
|
|
- ></a-select>
|
|
|
- </a-space>
|
|
|
- <a-pagination v-model:current="currentPage" :total="50" show-less-items size="small" />
|
|
|
- </div>
|
|
|
- <div class="search-result-content">
|
|
|
- <SearchResultItem />
|
|
|
- <a-divider />
|
|
|
- <SearchResultItem />
|
|
|
- </div>
|
|
|
- </a-col>
|
|
|
- </a-row>
|
|
|
</template>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
-.search-box-wrap {
|
|
|
- padding: 0 120px;
|
|
|
-}
|
|
|
-
|
|
|
-.search-result-main {
|
|
|
+.search-result-wrap {
|
|
|
margin-top: 20px;
|
|
|
|
|
|
- .left-filter-header {
|
|
|
- font-size: 1.25rem;
|
|
|
+ .search-box-wrap {
|
|
|
+ padding: 0 120px;
|
|
|
}
|
|
|
|
|
|
- .right-content-wrap {
|
|
|
- .right-header {
|
|
|
- display: flex;
|
|
|
- padding-top: 5px;
|
|
|
- justify-content: space-between;
|
|
|
- }
|
|
|
+ .search-result-main {
|
|
|
+ margin-top: 20px;
|
|
|
+ }
|
|
|
|
|
|
- .search-result-content {
|
|
|
- background-color: #ffffff;
|
|
|
- margin-top: 18px;
|
|
|
- padding: 10px;
|
|
|
+ @media (max-width: 1024px) {
|
|
|
+ .search-box-wrap {
|
|
|
+ padding: 0 20px;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-@media (max-width: 1024px) {
|
|
|
- .search-box-wrap {
|
|
|
- padding: 0 20px;
|
|
|
- }
|
|
|
-}
|
|
|
</style>
|