You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

481 lines
11 KiB

<template>
<div class="search-result clear">
<div class="nav-search">
<div class="search-header">
<div class="bread-crumbs">
<router-link to="/research" class="link">Research ></router-link>
<span >{{ store.state.searchVal }}</span>
</div>
<div>
<img class="close" @click="router.go(-1)" style="cursor:pointer;" src="/images/search_close.svg" alt="The image cannot be displayed properly">
</div>
</div>
<div class="search-input">
<img class="ipt-search" src="/images/search.svg" alt="The image cannot be displayed properly"
@click="toSearch(search, 'search')">
<input class="search-ipt" ref="maskSearch1" maxlength="100" type="text" placeholder="Search" v-model="search"
@click="showMask" @input="onInput" @keydown.enter="toSearch(search, 'search')" />
<img class="close" @click="handleClose" style="cursor:pointer;" src="/images/search_close.svg" alt="The image cannot be displayed properly">
</div>
</div>
<!-- 结果数量 -->
<div class="result-mun">
{{ total ? `${total} search results` : `There are no results for the search term "${search}"` }}
</div>
<!-- 搜索结果 -->
<div class="result-contnet container">
<template v-for="(item) in tipList" :key="item.id">
<ResearchComVue :data="item" :type="'searchResult'" :isMid="isMid" :isSma="isSma" />
</template>
</div>
<!-- 分页 -->
<div class="container pagination" v-show="tipList.length">
<PaginationComVue :page="page" @changePage="changePage" :total="total" :per="per" />
</div>
</div>
<!-- <div class="mask" v-show="isMask">
<div class="mask-content">
<div class="search-mask">
<div class="search-input">
<input class="search-ipt" ref="maskSearch2" maxlength="100" type="text" placeholder="Search" v-model="search"
autofocus @input="onInput" @focus="showMask"
@keydown.enter="toSearch(search, 'search')" />
<img class="ipt-search" src="/images/search.svg" alt="The image cannot be displayed properly"
@click="toSearch(search, 'search')">
</div>
<div class="tip-msg" @click="isInput = false">
<ul v-show="tipList.length">
<li class="search-result tip-active" v-for="msg in tipList" :key="msg" @click="toSearch(msg, 'result')">
<span v-html="msg.title"></span>
</li>
</ul>
<div class="no-result" v-show="isInput && !tipList.length && search">
{{ noResult }}
</div>
</div>
</div>
</div>
</div> -->
</template>
<script setup>
import ResearchComVue from '../components/ResearchCom.vue';
import PaginationComVue from '../components/PaginationCom.vue';
import { onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import { useStore } from 'vuex';
// import { searchResult } from '../assets/datas/searchResultData';
import { isTrue } from '../utils/tools'
import {searchTitleApi} from "../api/research.js";
const router = useRouter()
const searchResult = ref([])
const emit = defineEmits(['backTop'])
// vuex store
const store = useStore();
// 是否为中等屏幕 或 小屏幕
const isMid = ref(false);
const isSma = ref(false);
// 是否展示遮罩层
const isMask = ref(false);
// 遮罩层输入框
// const maskSearch1 = ref(null);
const maskSearch2 = ref(null);
// 判断是否在输入
const isInput = ref(false);
// 提示信息列表
const tipList = ref([])
const noResult = ref('')
// 数据总数 Total databases count
let total = ref(0);
// 页码 page number
let page = ref(1);
// 每页显示数量 displays the number per page
let per = ref(10);
// 搜索结果列表
const resultList = ref([])
const search = ref(store.state.searchVal);
// 从搜索栏进入到搜索详情
onMounted(() => {
// 窗口大小改变时触发
function changeSize() {
const pageSize = window.innerWidth;
if (pageSize >= 1440) {
isSma.value = false;
isMid.value = false;
} else if (pageSize > 430 && pageSize < 1440) {
isSma.value = false;
isMid.value = true;
} else if (pageSize <= 430) {
isSma.value = true;
isMid.value = false;
}
}
changeSize()
window.onresize = changeSize
// onSearch(search.value)
getSearchTitle()
window.addEventListener('keydown', (e)=> {
if (e.keyCode === 27) {
isMask.value = false;
}
})
})
// 展示遮罩层
const showMask = () => {
// isMask.value = true
// isTrue(isMask.value).then(() => {
// maskSearch2.value.focus();
// })
}
// 修改页码
const changePage = (data) => {
page.value = data
tipList.value = tipList.value.slice((page.value - 1) * per.value, page.value * per.value);
// onSearch(search.value)
getSearchTitle()
}
// 搜索获取数据
const onSearch = (reg) => {
isMask.value = false;
resultList.value = []
const resultReg = new RegExp(reg, 'gi');
if (search.value) {
searchTitleApi({
keyword: search.value,
page: 1,
limit: 100000,
}).then(res=>{
if (res.data) {
searchResult.value = res.data.research.data;
searchResult.value.forEach((item) => {
const result = resultReg.exec(item.title);
if (result) {
resultList.value.push({ ...item, title: item.title && item.title.replace(resultReg, `<span style="background-color: rgba(255, 109, 0, 0.2);">${result[0]}</span>`) })
}
})
// total.value = res.data.length
// resultList.value = resultList.value.slice((page.value - 1) * per.value, page.value * per.value);
emit('backTop');
}
})
}
}
// 输入时触发
const onInput = () => {
isInput.value = true;
// store.commit('changeSearchVal', search.value)
// 发虚拟请求
// issue a request
// 正则表达式匹配搜索字符
// The regular expression matches the search character
// const searchReg = new RegExp(search.value, 'gi');
// 清空搜索结果重新进行
// Clear the search results and start again
// if (search.value) {
// tipList.value = [];
// page.value = 1;
// per.value = 10
// getSearchTitle()
// }
}
// 搜索结果
const toSearch = (msg, type) => {
if (msg) {
switch (type) {
case 'search':
store.commit('changeSearchVal', search.value);
break;
case 'result':
search.value = msg.t
store.commit('changeSearchVal', msg.t);
break;
default:
break;
}
// isInput.value = false
onSearch(search.value)
} else {
alert('Please enter the content')
}
}
const handleClose= ()=>{
search.value = ''
}
const getSearchTitle = ()=>{
const searchReg = new RegExp(search.value, 'gi');
searchTitleApi({
keyword: search.value,
page: 1,
limit: 100000,
}).then(res=>{
total.value = 0
res.data.research.data.forEach(item=>{
const result = searchReg.exec(item.title);
console.log(result)
if (result) {
const resultMsg = result['input'].replace(searchReg, `<span style="color:#ff6d00">${result[0]}</span>`)
tipList.value.push({...item, t: item.title, title: resultMsg, });
}
})
total.value = tipList.value.length
tipList.value = tipList.value.slice((page.value - 1) * per.value, page.value * per.value);
if (!tipList.value.length) {
noResult.value = `There are no results for the search term "${search.value}"`;
}
})
}
</script>
<style lang="scss" scoped>
::v-deep .van-search {
padding: 0;
.van-field__clear {
margin-right: 5Px;
}
}
.nav-search,
.search-mask {
max-width: 1000px;
margin: 12px auto;
padding: 0 24px;
position: relative;
@media screen and (min-width: 1440Px) and (max-width: 100vw) {
padding: 24px 48px !important;
padding-top: 0 !important;
}
.search-input {
width: 100%;
height: 48px;
line-height: 48px;
background: #F9F9F9;
border-radius: 50px;
padding: 0 20px;
position: relative;
.search-ipt {
width: 90%;
font-size: 16px;
margin: 0 auto;
background-color: transparent;
border: none;
outline: none;
position: absolute;
left: 60px;
}
.search-ipt::placeholder {
font-family: 'Raleway';
font-style: normal;
font-weight: 400;
font-size: 16px;
line-height: 24px;
color: #B6BFC7;
}
.ipt-search {
width: 18px;
height: 18px;
position: absolute;
left: 20px;
top: 50%;
transform: translateY(-50%);
}
.close {
width: 14px;
position: absolute;
right: 20px;
top:50%;
transform: translateY(-50%);
}
}
.tip-msg {
display: block !important;
position: absolute;
left: 0;
background-color: #f5f5f5;
width: 100%;
margin: 0 auto;
height: 420px;
padding: 24px 26px;
overflow-y: scroll;
z-index: 99;
@media screen and (max-width: 431Px) and (min-width: 0Px) {
padding: 24px 24px !important;
}
@media screen and (min-width: 1440Px) and (max-width: 100vw) {
padding: 24px 40px !important
}
.search-result {
width: 100%;
height: 56px;
font-family: 'Libre Bodoni';
font-style: normal;
font-weight: 400;
font-size: 16px;
line-height: 56px;
color: #000000;
padding: 0 16px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.no-result {
font-family: 'Libre Bodoni';
font-style: normal;
font-weight: 400;
font-size: 16px;
color: #000000;
padding: 0 16px;
}
.search-result:hover {
color: #FF6D00;
background: rgba(255, 109, 0, 0.1);
}
}
.tip-msg::-webkit-scrollbar {
display: none;
/* Chrome Safari */
}
}
.nav-search {
.search-header {
display: flex;
justify-content: space-between;
.close {
width: 14px;
}
}
.bread-crumbs {
margin-bottom: 30px;
font-size: 18px;
.link {
color: rgba(0,0,0,.5)
}
span {
margin-left: 5px;
}
}
.search-ipt {
width: 100%;
margin: 0 auto !important;
}
}
.search-result {
max-width: 1000px;
margin: 0 auto;
padding-bottom: 24px;
position: relative;
.result-mun {
font-family: 'Raleway';
font-style: normal;
font-weight: 900;
font-size: 14Px;
line-height: 21px;
color: rgba(0, 0, 0, 0.75);
padding: 12px 36px 12px;
@media screen and (min-width:1440Px) and (max-width: 100vw) {
padding: 20px 52px 0px !important;
}
@media screen and (min-width: 0Px) and (max-width: 431Px) {
padding: 12px 24px 0px;
}
}
.result-contnet {
min-height: 100vh;
}
.pagination {
float: right;
margin: 20px 0px 20px;
@media screen and (min-width:1440Px) and (max-width: 100vw) {
padding-top: 0 !important;
margin: 0px 0px 36px !important;
}
@media screen and (min-width:0Px) and (max-width: 431Px) {
padding-top: 0px !important;
margin: 0 0 20px !important;
}
}
}
.mask {
width: 100%;
height: calc(100% - 80px);
background-color: #00000080;
position: fixed;
top: 80px;
left: 0;
z-index: 98;
.mask-content {
width: 100%;
background-color: #f5f5f5;
padding: 0;
margin: 0;
padding-top: 36px;
min-height: 530px;
}
.search-mask {
margin: 0 auto;
}
}
</style>