|
@@ -1,170 +1,346 @@
|
|
|
<template>
|
|
|
- <div class="pages--search" :data-top="Offset">
|
|
|
- <search ref="getH" id="mySearch" key="search-page" @input="goSearchInput" @submit="goSearch"></search>
|
|
|
- <van-sticky :offset-top="Offset">
|
|
|
- <van-tabs v-model="active"
|
|
|
- title-active-color="#2ABED1"
|
|
|
- title-inactive-color="#5F5E64"
|
|
|
- color="#2ABED1"
|
|
|
- >
|
|
|
- <van-tab :title="item.label" :name="item.type" v-for="item in tabs" :key="item.type"></van-tab>
|
|
|
+ <div class="pages--search">
|
|
|
+ <div class="j-header">
|
|
|
+ <search id="mySearch" key="search-page" :defalultValue="listState.value" @input="onInput" @submit="doSearch"></search>
|
|
|
+ <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>
|
|
|
- </van-sticky>
|
|
|
- <h1>4544454545454</h1>
|
|
|
- <h1>4544454545454</h1>
|
|
|
- <h1>4544454545454</h1>
|
|
|
- <h1>4544454545454</h1>
|
|
|
- <h1>4544454545454</h1>
|
|
|
- <h1>4544454545454</h1>
|
|
|
- <h1>4544454545454</h1>
|
|
|
- <h1>4544454545454</h1>
|
|
|
- <h1>4544454545454</h1>
|
|
|
- <h1>4544454545454</h1>
|
|
|
- <h1>4544454545454</h1>
|
|
|
- <h1>4544454545454</h1>
|
|
|
- <h1>4544454545454</h1>
|
|
|
- <h1>4544454545454</h1>
|
|
|
- <h1>4544454545454</h1>
|
|
|
- <h1>4544454545454</h1>
|
|
|
- <h1>4544454545454</h1>
|
|
|
- <h1>4544454545454</h1>
|
|
|
+ <div class="sort-list flex-r-c center">
|
|
|
+ <div
|
|
|
+ class="sort-list-item flex-r-c center 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="down" class="s-i-icon" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="j-main" ref="scrollWrap">
|
|
|
+ <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"
|
|
|
+ :highlightKey="highlightKey"
|
|
|
+ :price="item.price"
|
|
|
+ :subInfo="calcSubInfo(item)"
|
|
|
+ @onClick="toDocDetail(item)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <Empty v-if="listState.list.length === 0 && listState.loaded">暂无数据</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 { Tabs, Tab, Icon, Sticky } from 'vant'
|
|
|
-// import { mapActions } from 'vuex'
|
|
|
- // import { MixinTop } from '@/utils/mixin-top'
|
|
|
- @Component({
|
|
|
- name: 'home',
|
|
|
- // mixins: [MixinTop],
|
|
|
- components: {
|
|
|
- [Tab.name]: Tab,
|
|
|
- [Tabs.name]: Tabs,
|
|
|
- [Sticky.name]: Sticky,
|
|
|
- [Icon.name]: Icon,
|
|
|
- Search
|
|
|
+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: 'home',
|
|
|
+ components: {
|
|
|
+ [Tab.name]: Tab,
|
|
|
+ [Tabs.name]: Tabs,
|
|
|
+ [List.name]: List,
|
|
|
+ [Icon.name]: Icon,
|
|
|
+ Search,
|
|
|
+ Card,
|
|
|
+ Empty
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ ...mapState('main', {
|
|
|
+ searchState: (state: any) => state.searchPageData
|
|
|
+ }),
|
|
|
+ ...mapMutations({
|
|
|
+ saveSearchState: 'main/saveSearchPageState',
|
|
|
+ clearSearchState: 'main/clearSearchPageState'
|
|
|
+ }),
|
|
|
+ ...mapActions({
|
|
|
+ doSearchRquesst: 'main/doSearchDocs',
|
|
|
+ getIndexTags: 'main/getIndexTags'
|
|
|
+ })
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+export default class extends Vue {
|
|
|
+ protected searchState: any
|
|
|
+ protected saveSearchState: any
|
|
|
+ protected clearSearchState: any
|
|
|
+
|
|
|
+ protected doSearchRquesst: any
|
|
|
+ protected getIndexTags: any
|
|
|
+
|
|
|
+ docsTypeConf = {
|
|
|
+ active: '',
|
|
|
+ list: []
|
|
|
+ }
|
|
|
+
|
|
|
+ sortTypeList = [
|
|
|
+ {
|
|
|
+ type: 'tSort',
|
|
|
+ label: '上传时间',
|
|
|
+ sort: 0,
|
|
|
+ active: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'dSort',
|
|
|
+ label: '下载次数',
|
|
|
+ sort: 0,
|
|
|
+ active: false
|
|
|
},
|
|
|
- methods: {
|
|
|
- // ...mapActions({
|
|
|
- // ajaxData: 'main/getHome'
|
|
|
- // })
|
|
|
+ {
|
|
|
+ type: 'vSort',
|
|
|
+ label: '浏览人数',
|
|
|
+ sort: 0,
|
|
|
+ active: false
|
|
|
}
|
|
|
- })
|
|
|
+ ]
|
|
|
|
|
|
-export default class extends Vue {
|
|
|
- // protected ajaxData: any
|
|
|
- pageData: any = {}
|
|
|
- searchTop = 54
|
|
|
- active = 'all1'
|
|
|
- searchInput = ''
|
|
|
- tabs = [
|
|
|
- {
|
|
|
- type: 'all1',
|
|
|
- label: '全部'
|
|
|
- },
|
|
|
- {
|
|
|
- type: 'all2',
|
|
|
- label: '招标'
|
|
|
- },
|
|
|
- {
|
|
|
- type: 'all3',
|
|
|
- label: '法律法规'
|
|
|
- },
|
|
|
- {
|
|
|
- type: 'all4',
|
|
|
- label: '行业报告'
|
|
|
- }
|
|
|
- ]
|
|
|
-
|
|
|
- created () {
|
|
|
- this.pageData = {
|
|
|
- new: [
|
|
|
- {
|
|
|
- img: require('@/assets/images/bgApp.png'),
|
|
|
- type: 'pdf',
|
|
|
- id: '1',
|
|
|
- title: '优化招投标市场营商环境与国企优化招投标市场营商环境与国企...',
|
|
|
- money: 200000
|
|
|
- },
|
|
|
- {
|
|
|
- type: 'excel',
|
|
|
- img: require('@/assets/images/bgApp.png'),
|
|
|
- id: '2',
|
|
|
- title: '优化招投标市场营商环境与国企优化招投标市场营商环境与国企...',
|
|
|
- money: 200
|
|
|
- },
|
|
|
- {
|
|
|
- type: 'word',
|
|
|
- img: require('@/assets/images/bgApp.png'),
|
|
|
- id: '3',
|
|
|
- title: '优化招投标市场营商环境与国企优化招投标市场营商环境与国企...',
|
|
|
- money: 200
|
|
|
- },
|
|
|
- {
|
|
|
- type: 'ppt',
|
|
|
- img: require('@/assets/images/bgApp.png'),
|
|
|
- id: '4',
|
|
|
- title: '优化招投标市场营商环境与国企优化招投标市场营商环境与国企...',
|
|
|
- money: 200
|
|
|
- },
|
|
|
- {
|
|
|
- type: 'other',
|
|
|
- img: require('@/assets/images/bgApp.png'),
|
|
|
- id: '5',
|
|
|
- title: '优化招投标市场营商环境与国企优化招投标市场营商环境与国企...',
|
|
|
- money: 200
|
|
|
- }
|
|
|
- ]
|
|
|
- }
|
|
|
+ listState ={
|
|
|
+ value: '',
|
|
|
+ loaded: false, // 是否首次加载完成
|
|
|
+ loading: false,
|
|
|
+ finished: true,
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ offset: 80,
|
|
|
+ scrollTop: 0,
|
|
|
+ total: 0,
|
|
|
+ list: []
|
|
|
+ }
|
|
|
+
|
|
|
+ get activeSortType () {
|
|
|
+ return this.sortTypeList.find(item => {
|
|
|
+ return item.active
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ get highlightKey () {
|
|
|
+ return this.listState.value.split(/\s+/)
|
|
|
+ }
|
|
|
+
|
|
|
+ created () {
|
|
|
+ const y = this.reStoreState()
|
|
|
+ if (!y) {
|
|
|
+ this.getTags()
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ mounted () {
|
|
|
+ this.onFocus()
|
|
|
+ }
|
|
|
|
|
|
- mounted () {
|
|
|
- this.onFocus()
|
|
|
- const tempI = (this.$refs.getH as Vue).$el as HTMLDivElement
|
|
|
- this.searchTop = tempI.offsetHeight
|
|
|
+ onFocus () {
|
|
|
+ const dom = document.querySelector('#mySearch input') as HTMLInputElement
|
|
|
+ if (dom) {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ setTimeout(() => {
|
|
|
+ dom.focus()
|
|
|
+ }, 200)
|
|
|
+ })
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- get Offset () {
|
|
|
- const tempN = document.querySelector('.j-header.jy-app-header') as HTMLDivElement
|
|
|
- if (tempN) {
|
|
|
- return tempN.offsetHeight - 1 + this.searchTop
|
|
|
- } else {
|
|
|
- return 0
|
|
|
- }
|
|
|
+ // 恢复数据至第一次请求的状态(页码等)
|
|
|
+ resetListState () {
|
|
|
+ const state = {
|
|
|
+ loading: false,
|
|
|
+ finished: true,
|
|
|
+ pageNum: 1,
|
|
|
+ total: 0,
|
|
|
+ list: []
|
|
|
}
|
|
|
+ Object.assign(this.listState, state)
|
|
|
+ }
|
|
|
+
|
|
|
+ onInput (search: string) {
|
|
|
+ this.listState.value = search
|
|
|
+ }
|
|
|
|
|
|
- onFocus () {
|
|
|
- const tempN = document.querySelector('#mySearch input') as HTMLInputElement
|
|
|
- if (tempN) {
|
|
|
- this.$nextTick(() => {
|
|
|
- tempN.focus()
|
|
|
- setTimeout(() => {
|
|
|
- tempN.focus()
|
|
|
- }, 200)
|
|
|
- })
|
|
|
+ docTypeChange () {
|
|
|
+ if (!this.listState.value) return
|
|
|
+ this.resetListState()
|
|
|
+ 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.listState.finished = false
|
|
|
+ this.getList()
|
|
|
+ }
|
|
|
+
|
|
|
+ doSearch () {
|
|
|
+ this.resetListState()
|
|
|
+ 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
|
|
|
+ }
|
|
|
|
|
|
- goSearch (search: any) {
|
|
|
- console.log(search)
|
|
|
+ async getList () {
|
|
|
+ if (!this.listState.value) return
|
|
|
+ const query = {
|
|
|
+ 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
|
|
|
+ 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
|
|
|
}
|
|
|
|
|
|
- goSearchInput (search: string) {
|
|
|
- this.searchInput = search
|
|
|
+ // 数据请求完成(根据页码计算,当前页是否是最后一页)
|
|
|
+ // 请求完成后,页码就变为了下一页的页面,所以这里要-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
|
|
|
+ return [dateFormatter(uploadDate, 'yyyy/MM/dd'), `${downTimes}次下载`]
|
|
|
+ }
|
|
|
|
|
|
- goContent (item: any) {
|
|
|
- console.log(item)
|
|
|
+ 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]
|
|
|
+ }
|
|
|
+ this.$nextTick(() => {
|
|
|
+ const wrapper: any = this.$refs.scrollWrap
|
|
|
+ wrapper.scrollTop = this.listState.scrollTop
|
|
|
+ })
|
|
|
+ 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
|
|
|
+ }
|
|
|
+ console.log(d)
|
|
|
+ this.saveSearchState(d)
|
|
|
+ }
|
|
|
}
|
|
|
</script>
|
|
|
<style scoped lang="scss">
|
|
|
.pages--search {
|
|
|
- background: #F5F6F7;
|
|
|
- padding-bottom: 40px;
|
|
|
+ background-color: #F5F6F7;
|
|
|
box-sizing: border-box;
|
|
|
+ ::v-deep .van-tabs {
|
|
|
+ width: 100%;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .j-header {
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sort-list {
|
|
|
+ width: 100%;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 20px;
|
|
|
+ .sort-list-item {
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|