123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593 |
- <template>
- <div class="pages--search">
- <div class="j-header jy-app-header" :class="{'h5-header': $envs.inH5}">
- <div class="search-header-flex">
- <van-icon class="header-left" name="arrow-left" @click="clickLeft" />
- <search id="mySearch" ref="input" key="search-page" :defalultValue="listState.value" @input="onInput"
- @submit="doSearch"></search>
- <span class="header-right" @click="doSearch">搜索</span>
- </div>
- <!-- <van-tabs v-model="docsTypeConf.active"
- v-if="docsTypeConf.list.length"
- title-active-color="#2ABED1"
- title-inactive-color="#5F5E64"
- color="#2ABED1"
- @change="docTypeChange"
- >
- <van-tab v-for="(item, index) in docsTypeConf.list" :key="index" :title="item.label" :name="item.type"></van-tab>
- </van-tabs> -->
- <div class="filter-box" v-if="listState.loaded">
- <Filters @onReset="filtersReset" @confirm="filtersConfirm" :saveActive="true"
- :saveActiveData="{ chooseFormat: listState.docFileType, chooseType: listState.productType }"></Filters>
- <div class="sort-list flex-r-c">
- <div class="sort-list-item flex-r-c left flex" :class="{
- active: item.active,
- reverse: item.sort
- }" v-for="(item, index) in sortTypeList" :key="index" @click="sortAndSearch(item, index)">
- <span class="s-i-label">{{ item.label }}</span>
- <van-icon :name="'diy-down-' + (item.active ? 'blue' : 'grey')" class="s-i-icon" />
- </div>
- </div>
- </div>
- </div>
- <div class="j-main" ref="scrollWrap">
- <div class="historySearch" v-if="!listState.loaded && historykeyList.length > 0 && isShowHistory">
- <div class="his_head">
- <div class="his_title">历史搜索</div>
- <van-icon :name="'diy-clear'" @click="clearHistory" />
- </div>
- <div class="his_content">
- <div class="his_item" v-for="item in historykeyList" :key="item.label" @click="historykeySearch(item.label)">{{ item.label }}
- </div>
- </div>
- </div>
- <van-list v-model="listState.loading" :finished="listState.finished" :offset="listState.offset" @load="getList"
- class="more-list calc-height-1px" ref="vanList">
- <div>
- <Card v-for="(item, index) in listState.list" :key="index" :title="item.docName" :desc="item.docSummary"
- :docType="item.docFileType" :isVip="item.productType === 1" :subInfo="calcSubInfo(item)"
- @onClick="toDocDetail(item)" />
- </div>
- <Empty v-if="listState.list.length === 0 && listState.loaded && !listState.loading" style="background: #fff;">
- 暂无数据</Empty>
- </van-list>
- </div>
- </div>
- </template>
- <script lang="ts">
- import { Component, Vue } from 'vue-property-decorator'
- import { Tabs, Tab, Icon, List } from 'vant'
- import Search from '@/components/Search.vue'
- import Filters from '@/components/filters/index.vue'
- import Card from '@/components/docs-card/Card.vue'
- import Empty from '@/components/common/Empty.vue'
- import { mapState, mapMutations, mapActions } from 'vuex'
- import { dateFormatter } from '@/utils/globalFunctions'
- @Component({
- name: 'search-page',
- components: {
- [Tab.name]: Tab,
- [Tabs.name]: Tabs,
- [List.name]: List,
- [Icon.name]: Icon,
- Search,
- Card,
- Empty,
- Filters
- },
- computed: {
- ...mapState('main', {
- searchState: (state: any) => state.searchPageData
- })
- },
- methods: {
- ...mapState([
- 'layoutConf',
- 'defaultLayoutConf'
- ]),
- ...mapMutations({
- saveSearchState: 'main/saveSearchPageState',
- clearSearchState: 'main/clearSearchPageState',
- updateLayoutConfig: 'updateLayoutConfig'
- }),
- ...mapActions({
- doSearchRquesst: 'main/doSearchDocs',
- getIndexTags: 'main/getIndexTags'
- })
- }
- })
- export default class extends Vue {
- protected searchState: any
- protected saveSearchState: any
- protected clearSearchState: any
- protected layoutConf!: any
- protected doSearchRquesst: any
- protected getIndexTags: any
- protected updateLayoutConfig!: any
- $envs: any
- historykeyList: string[] = []
- docsTypeConf = {
- active: '',
- list: []
- }
- sortTypeList = [
- {
- type: 'tSort',
- label: '上传时间',
- sort: 0,
- active: true
- },
- {
- type: 'dSort',
- label: '下载次数',
- sort: 0,
- active: false
- },
- {
- type: 'vSort',
- label: '浏览人数',
- sort: 0,
- active: false
- }
- ]
- listState = {
- docFileType: 0,
- productType: 0,
- value: '',
- loaded: false, // 是否首次加载完成
- loading: false,
- finished: true,
- pageNum: 1,
- pageSize: 10,
- offset: 80,
- scrollTop: 0,
- total: 0,
- list: []
- }
- restored = false // 当前数据是否走过缓存
- isShowHistory = false // 是否展示搜索历史(P572需求-已将历史记录移至剑鱼搜索页-文档搜索tab),本地开发调试可将置为true
- get activeSortType () {
- return this.sortTypeList.find(item => {
- return item.active
- })
- }
- created () {
- this.restored = this.reStoreState()
- if (!this.restored) {
- // this.getTags()
- }
- }
- mounted () {
- if (!this.restored) {
- this.onFocus()
- }
- if (this.$route.query.text && !this.listState.value) {
- this.listState.value = this.$route.query.text as any
- this.doSearch()
- }
- // if (localStorage.getItem('jydocs-searchHistory')) {
- // this.historykeyList = JSON.parse(localStorage.getItem('jydocs-searchHistory') || '[]')
- // }
- const storage = localStorage.getItem('JY-MOBILE--login-clear-AllSearchHistory')
- if (storage) {
- const docStorage = JSON.parse(storage)
- this.historykeyList = docStorage?.data.docs
- }
- this.updateLayoutConfig({
- actionLeftHide: true,
- headerStyle: {
- display: 'none',
- height: 0
- }
- })
- }
- onFocus () {
- const dom = document.querySelector('#mySearch input') as HTMLInputElement
- if (dom) {
- this.$nextTick(() => {
- setTimeout(() => {
- dom.focus()
- }, 200)
- })
- }
- }
- // 恢复数据至第一次请求的状态(页码等)
- resetListState () {
- const state = {
- loading: false,
- finished: true,
- pageNum: 1,
- total: 0,
- scrollTop: 0,
- list: []
- }
- Object.assign(this.listState, state)
- }
- onInput (search: string) {
- this.listState.value = search.trim().replace(/\s+/g, ' ')
- if (!this.listState.value) {
- history.back()
- }
- }
- historykeySearch (val: any) {
- this.listState.value = val
- this.doSearch()
- }
- savesearchHistory () {
- const key: string = this.listState.value + ''
- // 兼容剑鱼搜索通用缓存格式 JY-MOBILE--login-clear-AllSearchHistory
- const storage = localStorage.getItem('JY-MOBILE--login-clear-AllSearchHistory')
- if (storage) {
- const docStorage = JSON.parse(storage)
- this.historykeyList = docStorage?.data.docs
- }
- const isHave = this.historykeyList.some((v: any) => {
- return v.label === key
- })
- if (key && !isHave) {
- const items: any = { label: key }
- this.historykeyList.unshift(items)
- if (this.historykeyList.length > 10) {
- this.historykeyList.pop()
- }
- // localStorage.setItem('jydocs-searchHistory', JSON.stringify(this.historykeyList))
- this.setJySearchHistory()
- } else if (isHave) {
- console.log('搜索的标签在历史搜索列表内或点击已有的标签需要将标签顺序移至前面')
- const items: any = { label: key }
- // 删除当前已有的标签(过滤)
- const filterList = this.historykeyList.filter((item: any) => {
- return item.label !== key
- })
- this.historykeyList = filterList
- this.historykeyList.unshift(items)
- if (this.historykeyList.length > 10) {
- this.historykeyList.pop()
- }
- this.setJySearchHistory()
- }
- }
- setJySearchHistory () {
- const storage = localStorage.getItem('JY-MOBILE--login-clear-AllSearchHistory')
- if (storage) {
- const docStorage = JSON.parse(storage)
- docStorage.data.docs = this.historykeyList
- localStorage.setItem('JY-MOBILE--login-clear-AllSearchHistory', JSON.stringify(docStorage))
- } else {
- const searchHistory = {
- data: {
- bidding: [],
- buyer: [],
- company: [],
- supplier: [],
- docs: this.historykeyList
- }
- }
- localStorage.setItem('JY-MOBILE--login-clear-AllSearchHistory', JSON.stringify(searchHistory))
- }
- }
- clearHistory () {
- if (this.historykeyList.length === 0) return
- this.historykeyList = []
- // localStorage.removeItem('jydocs-searchHistory')
- const storage = localStorage.getItem('JY-MOBILE--login-clear-AllSearchHistory')
- if (storage) {
- const docStorage = JSON.parse(storage)
- docStorage.data.docs = this.historykeyList
- localStorage.setItem('JY-MOBILE--login-clear-AllSearchHistory', JSON.stringify(docStorage))
- }
- }
- docTypeChange () {
- if (!this.listState.value) return
- this.resetListState()
- this.setScrollTop()
- this.listState.finished = false
- this.getList()
- }
- sortAndSearch (item: any) {
- if (item.active) {
- // 改变sort
- // item.sort = item.sort ? 0 : 1
- } else {
- this.sortTypeList.forEach(s => {
- s.active = false
- })
- item.active = true
- }
- if (!this.listState.value) return
- this.resetListState()
- this.setScrollTop()
- this.listState.finished = false
- this.getList()
- }
- filtersReset (val: any) {
- this.listState.productType = val.type
- this.listState.docFileType = val.format
- this.doSearch()
- }
- filtersConfirm (val: any) {
- this.listState.productType = val.type
- this.listState.docFileType = val.format
- this.doSearch()
- }
- doSearch () {
- if (!this.listState.value) return
- this.$router.replace({
- query: { text: this.listState.value }
- })
- this.savesearchHistory()
- const inputComponent = this.$refs.input as any
- inputComponent.setSearchContent(this.listState.value)
- this.resetListState()
- this.setScrollTop()
- this.listState.finished = false
- this.getList()
- }
- toDocDetail (item: any) {
- const { docId: id } = item
- this.saveState()
- this.$router.push({
- name: 'details',
- params: { id }
- })
- }
- async getTags () {
- const { data } = await this.getIndexTags()
- if (Array.isArray(data)) {
- const list: any = data.map(item => {
- return {
- type: item,
- label: item
- }
- })
- this.docsTypeConf.list = list
- if (data.length) {
- const i: any = this.docsTypeConf.list[0]
- this.docsTypeConf.active = i.type
- }
- }
- return data
- }
- async getList () {
- if (!this.listState.value) return
- if (this.listState.pageNum === 1) {
- // this.$toast.loading({
- // forbidClick: true,
- // duration: 0
- // })
- }
- const query = {
- docFileType: this.listState.docFileType,
- productType: this.listState.productType,
- // 搜索关键字
- keyWord: this.listState.value,
- // tag: this.docsTypeConf.active === '全部' ? '' : this.docsTypeConf.active,
- sort: this.activeSortType?.type,
- num: this.listState.pageNum,
- size: this.listState.pageSize
- }
- console.log('搜索参数:', query)
- this.listState.loading = true
- const { data } = await this.doSearchRquesst(query)
- this.listState.loading = false
- this.listState.loaded = true
- // this.$toast.clear()
- if (data && Array.isArray(data.list)) {
- this.listState.pageNum += 1
- this.listState.total = data.total
- this.listState.list = this.listState.list.concat(data.list)
- } else {
- this.listState.finished = true
- }
- // 数据请求完成(根据页码计算,当前页是否是最后一页)
- // 请求完成后,页码就变为了下一页的页面,所以这里要-1
- const isLastPage = (this.listState.pageNum - 1) * this.listState.pageSize >= this.listState.total
- if (isLastPage) {
- this.listState.finished = true
- }
- }
- calcSubInfo (item: any) {
- const { uploadDate, downTimes } = item
- const subInfoArr = []
- if (uploadDate !== undefined) {
- subInfoArr.push(dateFormatter(uploadDate, 'yyyy/MM/dd'))
- }
- if (downTimes !== undefined) {
- subInfoArr.push(`${downTimes}次下载`)
- }
- return subInfoArr
- }
- setScrollTop () {
- this.$nextTick(() => {
- const wrapper: any = this.$refs.scrollWrap
- wrapper.scrollTop = this.listState.scrollTop
- })
- }
- reStoreState () {
- const listInfo = this.searchState
- if (!listInfo || Object.keys(listInfo).length === 0) {
- return false
- } else {
- for (const key in listInfo) {
- this.$data[key] = listInfo[key]
- }
- setTimeout(() => {
- this.setScrollTop()
- this.clearSearchState()
- }, 50)
- return true
- }
- }
- saveState () {
- const wrapper: any = this.$refs.scrollWrap
- this.listState.scrollTop = wrapper.scrollTop
- const d = {
- docsTypeConf: this.docsTypeConf,
- sortTypeList: this.sortTypeList,
- listState: this.listState
- }
- this.saveSearchState(d)
- }
- clickLeft () {
- history.back()
- }
- }
- </script>
- <style scoped lang="scss">
- @include diy-icon('down-grey', 16, 16);
- @include diy-icon('down-blue', 16, 16);
- @include diy-icon('clear', 20, 20);
- .pages--search {
- background-color: #fff;
- box-sizing: border-box;
- ::v-deep .van-tabs {
- width: 100%;
- font-size: 14px;
- line-height: 20px;
- }
- .j-header {
- height: auto!important;
- flex-direction: column;
- background: linear-gradient(280.62deg, #D7F6FB 1.93%, #E7FCFF 49.44%, #E7F2FF 98.41%)!important;
- }
- .j-header:after {
- height: 0;
- }
- .search-header-flex{
- width: 100%;
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding-bottom: 12px;
- .header-right{
- flex-shrink: 0;
- font-size: 14px;
- line-height: 20px;
- color: #2ABED1;
- cursor: pointer;
- }
- ::v-deep{
- .my-search{
- padding: 0 12px;
- }
- .van-search__content{
- background: #fff;
- border-color: transparent;
- border-radius: 4px;
- }
- }
- }
- .filter-box {
- width: calc(100% + 24px);
- border-radius: 12px 12px 0 0;
- background: #fff;
- ::v-deep{
- .van-dropdown-menu__bar{
- background: unset;
- }
- }
- }
- .sort-list {
- width: 100%;
- font-size: 14px;
- line-height: 20px;
- border-bottom: 0.5px solid #0000000D;
- .sort-list-item {
- max-width: 108px;
- box-sizing: border-box;
- padding: 12px 16px;
- &.active {
- color: #2ABED1;
- }
- &.reverse {
- .s-i-icon {
- transform: rotate(180deg);
- }
- }
- .s-i-label {
- margin-right: 4px;
- }
- .s-i-icon {
- font-weight: bold;
- transition: transform .2 ease;
- }
- }
- }
- .historySearch {
- padding: 0 16px;
- .his_head {
- height: 54px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- .his_title {
- font-size: 16px;
- color: #171826;
- }
- }
- .his_content {
- overflow: hidden;
- .his_item {
- float: left;
- margin-right: 8px;
- margin-bottom: 12px;
- padding: 4px 12px;
- line-height: 22px;
- font-size: 13px;
- color: #5F5E64;
- border-radius: 4px;
- background-color: #F7F9FA;
- }
- }
- }
- }
- </style>
|