262 lines
6.6 KiB
Plaintext
262 lines
6.6 KiB
Plaintext
<template>
|
||
<view class="index-container">
|
||
<!-- Banner 区域,可轮播 -->
|
||
<swiper class="banner-swiper" :indicator-dots="true" :autoplay="true" interval="4000" circular>
|
||
<swiper-item v-for="(item, idx) in banners" :key="idx">
|
||
<image class="banner-img" :src="item.cover" @click="onBannerClick(item)"></image>
|
||
<view class="banner-title">{{ item.title }}</view>
|
||
</swiper-item>
|
||
</swiper>
|
||
|
||
<!-- 分类Tab -->
|
||
<scroll-view class="category-tabs" scroll-x>
|
||
<view v-for="(cat, idx) in categories" :key="cat.id" :class="['tab-item', currentCategory === cat.id ? 'active' : '']" @click="switchCategory(cat.id)">
|
||
{{ cat.name }}
|
||
</view>
|
||
</scroll-view>
|
||
|
||
<!-- 资讯列表 -->
|
||
<list-view style="flex:1;" refresher-enabled=true @refresherrefresh="onRefresh" :refresher-triggered="refresherTriggered" enable-back-to-top="true">
|
||
<list-item v-for="(news, idx) in newsList" :key="news.id" type=2>
|
||
<view class="news-card" hover-class="news-card-hover" @click="goDetail(news, idx)">
|
||
<image class="news-cover" :src="news.cover"></image>
|
||
<view class="news-body">
|
||
<text class="news-title">{{ news.title }}</text>
|
||
<text class="news-summary">{{ news.summary }}</text>
|
||
<view class="news-meta">
|
||
<text class="news-author">{{ news.author_name }}</text>
|
||
<text class="news-time">{{ news.published_at }}</text>
|
||
<view class="news-tags">
|
||
<text v-for="tag in news.tags" :key="tag" class="news-tag">{{ tag }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</list-item>
|
||
<view v-if="loading" class="loading-text">{{ $t('status.loading') }}</view>
|
||
<view v-if="!loading && newsList.length === 0" class="empty-text">{{ $t('status.noData') }}</view>
|
||
</list-view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
type Banner = {
|
||
cover: string,
|
||
title: string,
|
||
id: string
|
||
}
|
||
type NewsItem = {
|
||
id: string,
|
||
title: string,
|
||
summary: string,
|
||
author_name: string,
|
||
cover: string,
|
||
published_at: string,
|
||
tags: string[]
|
||
}
|
||
type Category = {
|
||
id: string,
|
||
name: string
|
||
}
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
banners: [] as Banner[],
|
||
categories: [
|
||
{ id: 'all', name: this.$t('title.news') },
|
||
{ id: 'technology', name: this.$t('title.technology') },
|
||
{ id: 'sports', name: this.$t('title.sports') },
|
||
{ id: 'health', name: this.$t('title.health') },
|
||
{ id: 'entertainment', name: this.$t('title.entertainment') }
|
||
] as Category[],
|
||
currentCategory: 'all',
|
||
newsList: [] as NewsItem[],
|
||
refresherTriggered: false,
|
||
loading: false
|
||
};
|
||
},
|
||
onLoad() {
|
||
this.fetchBanners();
|
||
this.fetchNewsList();
|
||
},
|
||
methods: {
|
||
fetchBanners() {
|
||
// TODO: 替换为实际API
|
||
this.banners = [
|
||
{ cover: 'https://example.com/banner1.jpg', title: 'AI科技突破', id: 'b1' },
|
||
{ cover: 'https://example.com/banner2.jpg', title: '体育赛事速递', id: 'b2' }
|
||
];
|
||
},
|
||
fetchNewsList() {
|
||
this.loading = true;
|
||
// TODO: 替换为实际API,按currentCategory过滤
|
||
setTimeout(() => {
|
||
this.newsList = [
|
||
{
|
||
id: 'n1',
|
||
title: 'AI助力医疗新进展',
|
||
summary: '人工智能正在改变医疗行业,提升诊断效率。',
|
||
author_name: '张三',
|
||
cover: 'https://example.com/news1.jpg',
|
||
published_at: '2025-06-29',
|
||
tags: ['AI', '医疗']
|
||
},
|
||
{
|
||
id: 'n2',
|
||
title: '全球体育赛事回顾',
|
||
summary: '本周全球体育赛事精彩纷呈,亮点不断。',
|
||
author_name: '李四',
|
||
cover: 'https://example.com/news2.jpg',
|
||
published_at: '2025-06-28',
|
||
tags: ['体育']
|
||
}
|
||
];
|
||
this.loading = false;
|
||
this.refresherTriggered = false;
|
||
}, 800);
|
||
},
|
||
switchCategory(catId: string) {
|
||
this.currentCategory = catId;
|
||
this.fetchNewsList();
|
||
},
|
||
goDetail(news: NewsItem, idx: number) {
|
||
uni.navigateTo({
|
||
url: `/pages/mt/detail.uvue?id=${news.id}`
|
||
});
|
||
},
|
||
onBannerClick(item: Banner) {
|
||
// 可跳转到专题或详情
|
||
uni.navigateTo({
|
||
url: `/pages/mt/detail.uvue?id=${item.id}`
|
||
});
|
||
},
|
||
onRefresh() {
|
||
this.refresherTriggered = true;
|
||
this.fetchNewsList();
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style>
|
||
.index-container {
|
||
display: flex;
|
||
flex-direction: column;
|
||
width: 100vw;
|
||
min-height: 100vh;
|
||
background: #f7f8fa;
|
||
}
|
||
.banner-swiper {
|
||
width: 100vw;
|
||
height: 180px;
|
||
}
|
||
.banner-img {
|
||
width: 100vw;
|
||
height: 180px;
|
||
object-fit: cover;
|
||
}
|
||
.banner-title {
|
||
position: absolute;
|
||
left: 20px;
|
||
bottom: 20px;
|
||
color: #fff;
|
||
font-size: 18px;
|
||
font-weight: bold;
|
||
text-shadow: 0 2px 8px rgba(0,0,0,0.2);
|
||
}
|
||
.category-tabs {
|
||
display: flex;
|
||
flex-direction: row;
|
||
background: #fff;
|
||
padding: 0 10px;
|
||
height: 44px;
|
||
align-items: center;
|
||
border-bottom: 1px solid #eee;
|
||
}
|
||
.tab-item {
|
||
margin-right: 18px;
|
||
font-size: 15px;
|
||
color: #666;
|
||
padding: 6px 10px;
|
||
border-radius: 16px;
|
||
}
|
||
.tab-item.active {
|
||
background: #007aff;
|
||
color: #fff;
|
||
}
|
||
.news-card {
|
||
display: flex;
|
||
flex-direction: row;
|
||
background: #fff;
|
||
margin: 10px 10px 0 10px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 8px rgba(0,0,0,0.03);
|
||
overflow: hidden;
|
||
}
|
||
.news-cover {
|
||
width: 110px;
|
||
height: 80px;
|
||
object-fit: cover;
|
||
border-radius: 8px 0 0 8px;
|
||
}
|
||
.news-body {
|
||
flex: 1;
|
||
padding: 10px 12px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
}
|
||
.news-title {
|
||
font-size: 16px;
|
||
font-weight: 500;
|
||
color: #222;
|
||
margin-bottom: 6px;
|
||
line-height: 1.3;
|
||
}
|
||
.news-summary {
|
||
font-size: 13px;
|
||
color: #666;
|
||
margin-bottom: 8px;
|
||
line-height: 1.4;
|
||
}
|
||
.news-meta {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
font-size: 12px;
|
||
color: #999;
|
||
justify-content: space-between;
|
||
}
|
||
.news-author {
|
||
margin-right: 10px;
|
||
}
|
||
.news-tags {
|
||
display: flex;
|
||
flex-direction: row;
|
||
}
|
||
.news-tag {
|
||
background: #f0f0f0;
|
||
color: #007aff;
|
||
font-size: 11px;
|
||
border-radius: 10px;
|
||
padding: 2px 8px;
|
||
margin-left: 4px;
|
||
}
|
||
.loading-text, .empty-text {
|
||
text-align: center;
|
||
color: #bbb;
|
||
font-size: 14px;
|
||
margin: 20px 0;
|
||
}
|
||
@media (min-width: 900px) {
|
||
.index-container {
|
||
max-width: 900px;
|
||
margin: 0 auto;
|
||
}
|
||
.banner-swiper, .banner-img {
|
||
width: 900px;
|
||
}
|
||
}
|
||
</style>
|