siteFront/pages/category/category.vue
2024-11-26 22:36:36 +08:00

314 lines
7.5 KiB
Vue

<template>
<view class="category-tab-page">
<view class="banner">
<view class="img">
<image :src="topImg" mode="aspectFill" style="width: 100%;height: 100%;"></image>
<view class="topText tn-flex tn-flex-center-between tn-w-full tn-p-lg">
<view class="icon tn-mt-sm">
<image :src="config.logo" mode="aspectFill" style="width: 100%;height: 100%;"></image>
</view>
<view class="title tn-text-xl tn-mt-xl">
#{{headerTitle}}
</view>
</view>
</view>
</view>
<view class="content tn-radius">
<view class="top tn-flex tn-flex-center-between tn-border-bottom tn-grey-light_border">
<view class="tabList tn-w-3-5">
<TnTabs v-model="currentTabIndex" :scroll="false" :bottom-shadow="false" active-color="tn-blue-dark" bar-color="tn-blue-dark" bg-color="rgba(255,255,255,0.001)">
<TnTabsItem
v-for="(item, index) in cateList"
:key="index"
:title="item.cateName"
@click="changeTab(item)"
/>
</TnTabs>
</view>
<view class="search tn-p-sm tn-flex tn-flex-center-end">
<view class="search-btn tn-border tn-gray-dark_border tn-p-xs tn-pt-0 tn-pb-0 tn-text tn-gray-dark_text" @click="showSearch">
<TnIcon name="search"/>
<span class="tn-pl-xs">搜 索</span>
</view>
</view>
</view>
<view class="list tn-shadow tn-p-sm">
<view class="item tn-flex tn-flex-center-between tn-pt-sm tn-pb-sm tn-border-bottom tn-grey-light_border"
v-for="(item,index) in articleList"
:key="index"
@click="toDetail(item)">
<view class="left tn-flex tn-flex-column tn-pr-sm tn-flex-1">
<view class="title tn-text-lg tn-text-ellipsis-2">
{{item.title}}
</view>
<view class="info tn-flex tn-flex-row tn-flex-center-between tn-text-xs">
<view class="time">
<TnIcon name="time"/>{{dayjs(item.createTime).format('YYYY-MM-DD')}}
</view>
<view class="author">
<TnIcon name="eye"/>{{item.addNum + item.clickNum}}
</view>
</view>
</view>
<view class="right tn-shadow tn-shadow-blur" style="border-radius: 6rpx;">
<image :src="item.image?item.image:defaultImg" mode="aspectFill" style="width: 150rpx;height: 150rpx;display: block;"></image>
</view>
</view>
<view class="loadmore tn-mt tn-mb">
<TnLoadmore :status="loadmoreStatus" color="#666" loading-icon-mode="flower" />
</view>
</view>
</view>
<TnPopup v-model="showPopup" open-direction="top" :radius="0">
<view class="tn-pt-sm tn-pb-sm tn-pl-lg tn-pr-lg">
<TnSearchBox
v-model="searchValue"
shape="round"
@search="searchBtnClickEvent"
@clear="clearEvent"
/>
</view>
</TnPopup>
</view>
</template>
<script lang="ts" setup>
import { ref,onMounted, reactive } from 'vue';
import { onLoad,onReachBottom } from "@dcloudio/uni-app";
import request from '@/utils/request';
import dayjs from "dayjs";
import TnTabs from '@/uni_modules/tuniaoui-vue3/components/tabs/src/tabs.vue'
import TnTabsItem from '@/uni_modules/tuniaoui-vue3/components/tabs/src/tabs-item.vue'
import type { LoadmoreStatus } from '@tuniao/tnui-vue3-uniapp'
import TnLoadmore from '@/uni_modules/tuniaoui-vue3/components/loadmore/src/loadmore.vue'
import TnPopup from '@/uni_modules/tuniaoui-vue3/components/popup/src/popup.vue'
import TnSearchBox from '@/uni_modules/tuniaoui-vue3/components/search-box/src/search-box.vue'
import config from '@/config/config';
const cateId = ref();
const headerTitle = ref();
const topImg = ref('/static/index_top.jpg')
const defaultImg = ref('http://static.cqtlcm.com/lhdefault.jpg');
const currentTabIndex = ref(0)
const searchValue = ref()
const cateList = ref()
const hasMore = ref(true);
const showPopup = ref(false)
const params = reactive<{
page?:number,
limit?:number,
cateId?:number,
keyword?:string
}>({
page:1,
limit:10
})
const articleList = ref([])
const loadmoreStatus = ref<LoadmoreStatus>('loadmore')
const getMenuConfig = () => {
let url = '/front/content/category/info'
request({
url:url,
data:{
'cateId':cateId.value,
},
method:'GET'
}).then(res=>{
headerTitle.value = res.data.data.cateName
uni.setNavigationBarTitle({
title:res.data.data.cateName
})
})
}
const getCateList = ()=>{
let url = '/front/content/category/son'
request({
url:url,
method:'GET',
data:{
menuId:cateId.value
}
}).then(res=>{
cateList.value = res.data.data
params.cateId = res.data.data[0].cateId
getArticleList()
})
}
const showSearch = () => {
showPopup.value = true
}
const clearEvent = () => {
params.page = 1
params.keyword = undefined
articleList.value = []
getArticleList()
}
const searchBtnClickEvent = (value:string) => {
params.page = 1;
params.keyword = value
articleList.value = [];
showPopup.value = false;
getArticleList()
}
const getArticleList = () => {
loadmoreStatus.value = 'loading'
let url = '/front/content/list'
request({
url:url,
method:'GET',
data:params
}).then(res=>{
if(res.data.data.list && res.data.data.list.length > 0){
res.data.data.list.forEach((item:any)=>{
if(item.image){
item.image = JSON.parse(item.image)[0]
}
})
}
if(res.data.data.list.length < params.limit){
loadmoreStatus.value = 'nomore'
hasMore.value = false
}
articleList.value = articleList.value.concat(res.data.data.list)
})
}
const changeTab = (item:any) => {
articleList.value = []
params.page = 1
hasMore.value = true
params.keyword = ''
params.cateId = item.cateId
getArticleList()
}
const toDetail = (item:any) =>{
if(item.type === 0){
let routeUrl = '/pages/detail/index'
if(item.template){
routeUrl = item.template //定义模板后
}
uni.navigateTo({
url:routeUrl + '?cateId=' + item.cateId + '&id=' + item.id
})
}else if(item.type === 1){
//外链
if(item.link && item.link.slice(0,25) !== 'https://mp.weixin.qq.com/'){
uni.navigateTo({
url:'/pages/webview/index?url=' + item.link
})
}else{
window.location.href = item.link
}
}else{
uni.navigateTo({
url:'/pages/detail/album?id=' + item.id
})
}
}
onLoad((options)=>{
cateId.value = options.cateId
})
onReachBottom(()=>{
if(hasMore.value){
params.page += 1
getArticleList()
}else{
loadmoreStatus.value = 'nomore'
}
})
onMounted(()=>{
getMenuConfig()
getCateList()
})
</script>
<style lang="scss" scoped>
.category-tab-page{
min-height: 100vh;
.banner{
height: 450rpx;
position: relative;
.img{
width: 100%;
height: 100%;
.topText{
color: #fff;
position: absolute;
top: 100rpx;
left: 0;
.icon{
width: 220rpx;
height: 80rpx;
}
.title{
letter-spacing: 4rpx;
}
}
::after{
content: "";
position: absolute;
width: 100%;
height: 120rpx;
top: 330rpx;
left: 0;
background:linear-gradient(180deg,rgba(255, 255, 255, 0.01),rgba(255, 255, 255, 0.9))
}
}
}
.search-btn{
width: 150rpx;
border-radius: 40rpx;
padding-top: 4rpx;
padding-bottom: 5rpx;
}
.content{
position: relative;
background-color: #FFF;
margin-top: -160rpx;
.top{
border-radius: 0;
}
.list{
.item{
background-color: #FFF;
border-radius: 0;
.left{
height: 170rpx;
justify-content: space-between;
.title{
line-height: 1.5em;
color: #444;
}
.info{
color: #666;
}
}
}
}
}
}
</style>