Files
akmon/pages/mt/index.uvue
2026-01-20 08:04:15 +08:00

262 lines
6.6 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>