9.5上午更新

This commit is contained in:
zoujiandong
2025-09-05 10:19:10 +08:00
parent 9a26193ea4
commit 397cf0c88e
13 changed files with 3146 additions and 222 deletions
+638
View File
@@ -0,0 +1,638 @@
<template>
<view class="news-list-page">
<!-- 顶部导航栏 -->
<uni-nav-bar
left-icon="left"
:title="title"
@clickLeft="goBack"
fixed
color="#8B2316"
height="140rpx"
:border="false"
backgroundColor="#eeeeee"
></uni-nav-bar>
<!-- 新闻列表 -->
<scroll-view
class="news-scroll-view"
scroll-y="true"
:refresher-enabled="true"
:refresher-triggered="isRefreshing"
@refresherrefresh="onRefresh"
@scrolltolower="onScrollToLower"
:show-scrollbar="false"
>
<view class="news-list">
<view
class="news-item"
v-for="(news, index) in newsList"
:key="news.uuid || index"
@click="goToNewsDetail(news)"
>
<view class="item-image-container">
<image
class="item-image"
:src="docUrl + (news.headImg || news.imgPath) "
mode="aspectFill"
></image>
<view class="important-tag" v-if="news.isImportant">重要通知</view>
</view>
<view class="item-content">
<view class="item-title">{{ news.title || news.topic }}</view>
<view class="item-meta">
<text class="item-date">{{ formatDate(news.createDate || news.submitDate) }}</text>
<view class="item-stats">
<uni-icons type="eye" size="14" color="#999"></uni-icons>
<text>{{ news.readnum || 0 }}</text>
<uni-icons type="hand-up" size="14" color="#999" style="margin-left: 20rpx;"></uni-icons>
<text>{{ news.likenum || news.agreenum }}</text>
</view>
</view>
</view>
</view>
<!-- 加载更多/无数据提示 -->
<view class="load-more-status">
<view v-if="loadMoreStatus === 'loading'" class="loading">
<uni-icons type="spinner-cycle" size="20" color="#999"></uni-icons>
<text>加载中...</text>
</view>
<view v-else-if="loadMoreStatus === 'more'" class="more">
<text>上拉加载更多</text>
</view>
<view v-else-if="loadMoreStatus === 'noMore'" class="no-more">
<text>没有更多数据了</text>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<script setup>
import { ref, onMounted, reactive } from 'vue';
import { onShow, onPullDownRefresh, onReachBottom,onLoad } from '@dcloudio/uni-app';
import api from '@/api/api.js';
import docUrl from '@/utils/docUrl.js';
import dayjs from 'dayjs';
import navTo from '@/utils/navTo.js';
const from=ref('');
const title=ref('肝胆新闻');
// Banner相关数据
const bannerList = ref([]);
const currentBannerIndex = ref(0);
const newstagid=ref('');
// 响应式数据
const activeTab = ref(-1); // '肝胆新闻' is the second tab (index 1)
const tabs = ref(['精选', '肝胆新闻', '技术快讯', '基地动态', '专家动态']);
const newsList = ref([]);
const page = ref(1);
const pageSize = ref(10);
const total = ref(0);
const loadMoreStatus = ref('more'); // more, loading, noMore
const isRefreshing = ref(false); // 控制下拉刷新状态
const keywords=ref('');
const loadMoreText = reactive({
contentdown: '上拉显示更多',
contentrefresh: '正在加载...',
contentnomore: '没有更多数据了'
});
const newsTags = ref([]); // 新闻标签列表
onLoad((options) => {
if(options.from){
from.value = options.from
title.value = '患教学堂'
}
if(options.keywords){
keywords.value = options.keywords
}
})
onShow(() => {
if(from.value){
loadNewsListKePu();
}else{
loadNewsListIndex();
}
});
const onSwiperChange = (e) => {
currentBannerIndex.value = e.detail.current;
};
// scroll-view 下拉刷新
const onRefresh = async () => {
console.log('scroll-view 下拉刷新触发');
isRefreshing.value = true;
await refreshData();
isRefreshing.value = false;
};
// scroll-view 滚动到底部
const onScrollToLower = () => {
console.log('=== onScrollToLower 触发 ===');
console.log('当前状态:', {
loadMoreStatus: loadMoreStatus.value,
isRefreshing: isRefreshing.value,
currentPage: page.value,
listLength: newsList.value.length
});
if (loadMoreStatus.value === 'more' && !isRefreshing.value) {
console.log('条件满足,开始加载更多数据');
if(from.value){
loadNewsListKePu();
}else{
loadNewsListIndex();
}
} else {
console.log('条件不满足,跳过加载:', {
loadMoreStatus: loadMoreStatus.value,
isRefreshing: isRefreshing.value
});
}
};
// 方法
const goBack = () => {
uni.navigateBack();
};
const goToSearch = () => {
// Implement navigation to search page
console.log('Go to search page');
};
// 加载新闻轮播数据
// 加载新闻标签列表
const loadNewsTags = async () => {
try {
const res = await api.newsTagList({});
console.log('新闻标签响应:', res);
if (res && res.code === 200) {
console.log('获取到标签数据:', res.data);
tabs.value = res.data;
// 确保标签数据存在且有效
if (res.data && Array.isArray(res.data) && res.data.length > 0) {
newstagid.value = res.data[0].ID;
//loadNewsList(true); // Initial load
} else {
console.warn('标签数据为空或格式不正确');
newstagid.value = '';
}
} else {
console.error('加载新闻标签失败:', res.message);
}
} catch (e) {
console.error('加载新闻标签异常:', e);
}
};
// 加载新闻列表数据
const loadNewsListKePu = async (isRefresh = false) => {
if (isRefresh) {
page.value = 1;
newsList.value = [];
loadMoreStatus.value = 'more';
console.log('刷新模式:重置分页状态');
}
// 检查加载状态
if (loadMoreStatus.value === 'noMore' || loadMoreStatus.value === 'loading') {
console.log('当前状态不允许加载:', loadMoreStatus.value);
return;
}
// 设置加载状态
loadMoreStatus.value = 'loading';
console.log(`开始加载第${page.value}页数据,newstagid: ${newstagid.value}`);
try {
const res = await api.polularScienceArticleListIndexNew({
page: page.value,
pageSize: pageSize.value,
topic: keywords.value
});
console.log('新闻列表API响应:', res);
if (res && res.code === 200) {
// 尝试多种可能的数据结构
let newItems = [];
let totalCount = 0;
if (res.data && res.data.list) {
newItems = res.data.list;
totalCount = res.data.totalRow;
console.log('使用 res.data.list 结构');
}
console.log('解析后的数据:', { newItems, totalCount, newItemsLength: newItems.length });
// 确保 newItems 是数组
if (Array.isArray(newItems)) {
if (isRefresh) {
newsList.value = newItems;
console.log('刷新模式:替换列表数据');
} else {
newsList.value = [...newsList.value, ...newItems];
console.log('加载更多:追加数据到列表');
}
total.value = totalCount;
console.log(`当前页数据: ${newItems.length}, 总数: ${total.value}, 当前列表长度: ${newsList.value.length}`);
// 判断是否还有更多数据
if (newItems.length < pageSize.value || newsList.value.length >= total.value) {
loadMoreStatus.value = 'noMore';
console.log('没有更多数据了');
} else {
loadMoreStatus.value = 'more';
page.value++;
console.log(`还有更多数据,下一页: ${page.value}`);
}
} else {
console.error('API返回的数据不是数组格式:', newItems);
loadMoreStatus.value = 'noMore';
}
} else {
console.error('加载新闻列表失败:', res.message);
loadMoreStatus.value = 'noMore';
}
} catch (e) {
console.error('加载新闻列表异常:', e);
loadMoreStatus.value = 'noMore';
}
console.log('=== loadNewsList 结束 ===');
console.log('最终状态:', {
loadMoreStatus: loadMoreStatus.value,
page: page.value,
listLength: newsList.value.length
});
};
const loadNewsListIndex = async (isRefresh = false) => {
console.log('=== loadNewsList 开始 ===');
console.log('当前参数:', { isRefresh, page: page.value, newstagid: newstagid.value });
// 验证 newstagid 是否有效
if (isRefresh) {
page.value = 1;
newsList.value = [];
loadMoreStatus.value = 'more';
console.log('刷新模式:重置分页状态');
}
// 检查加载状态
if (loadMoreStatus.value === 'noMore' || loadMoreStatus.value === 'loading') {
console.log('当前状态不允许加载:', loadMoreStatus.value);
return;
}
// 设置加载状态
loadMoreStatus.value = 'loading';
console.log(`开始加载第${page.value}页数据,newstagid: ${newstagid.value}`);
try {
const res = await api.defaultNewsListNew({
page: page.value,
pageSize: pageSize.value,
});
console.log('新闻列表API响应:', res);
if (res && res.code === 200) {
// 尝试多种可能的数据结构
let newItems = [];
let totalCount = 0;
if (res.data && res.data.list) {
newItems = res.data.list;
totalCount = res.data.totalRow || 0;
console.log('使用 res.data.list 结构');
}
console.log('解析后的数据:', { newItems, totalCount, newItemsLength: newItems.length });
// 确保 newItems 是数组
if (Array.isArray(newItems)) {
if (isRefresh) {
newsList.value = newItems;
console.log('刷新模式:替换列表数据');
} else {
newsList.value = [...newsList.value, ...newItems];
console.log('加载更多:追加数据到列表');
}
total.value = totalCount;
console.log(`当前页数据: ${newItems.length}, 总数: ${total.value}, 当前列表长度: ${newsList.value.length}`);
// 判断是否还有更多数据
if (newItems.length < pageSize.value || newsList.value.length >= total.value) {
loadMoreStatus.value = 'noMore';
console.log('没有更多数据了');
} else {
loadMoreStatus.value = 'more';
page.value++;
console.log(`还有更多数据,下一页: ${page.value}`);
}
} else {
console.error('API返回的数据不是数组格式:', newItems);
loadMoreStatus.value = 'noMore';
}
} else {
console.error('加载新闻列表失败:', res.message);
loadMoreStatus.value = 'noMore';
}
} catch (e) {
console.error('加载新闻列表异常:', e);
loadMoreStatus.value = 'noMore';
}
console.log('=== loadNewsList 结束 ===');
console.log('最终状态:', {
loadMoreStatus: loadMoreStatus.value,
page: page.value,
listLength: newsList.value.length
});
};
const refreshData = async () => {
console.log('Refreshing data...');
// 重置分页状态
page.value = 1;
newsList.value = [];
loadMoreStatus.value = 'more';
if(from.value){
// 重新加载数据
await loadNewsListKePu(true);
}else{
await loadNewsListIndex(true);
}
uni.showToast({
title: '刷新成功',
icon: 'success'
});
};
const goToNewsDetail = (item) => {
console.log('Go to news detail:', item);
let url=encodeURIComponent(docUrl+item.path)
navTo({
url: `/pages_app/webview/webview?url=${url}`
});
};
const formatDate = (dateString) => {
if (!dateString) return '';
try {
// 使用 dayjs 格式化日期
return dayjs(dateString).format('YYYY-MM-DD');
} catch (error) {
console.error('日期格式化失败:', error, dateString);
return '';
}
};
</script>
<style lang="scss" scoped>
.news-list-page {
background-color: #f8f8f8;
height: 100vh;
overflow-y: hidden;
}
.uni-navbar {
/* Custom styles for uni-nav-bar if needed */
.uni-navbar__content {
height: 44px; // Standard navbar height
}
}
.nav-tabs {
background-color: #ffffff;
padding: 20rpx 0;
border-bottom: 1rpx solid #f0f0f0;
position: sticky;
top: calc(var(--status-bar-height) + 44px); // Below navbar
z-index: 99;
.tabs-scroll {
width: 100%;
white-space: nowrap;
}
.tabs-container {
display: flex;
padding: 0 20rpx;
min-width: 100%;
}
.tab-item {
flex-shrink: 0;
padding: 10rpx 30rpx;
font-size: 28rpx;
color: #666;
position: relative;
margin-right: 20rpx;
&:last-child {
margin-right: 0;
}
&.active {
color: #ff4757;
font-weight: bold;
&::after {
content: '';
position: absolute;
bottom: -10rpx;
left: 50%;
transform: translateX(-50%);
width: 60%;
height: 4rpx;
background-color: #ff4757;
border-radius: 2rpx;
}
}
}
}
/* Fixed Banner Container */
.banner-container {
position: relative;
background-color: #fff;
.swipemask{
width:100%;
z-index:3;
box-sizing:border-box;
position: absolute;
bottom:0;
padding:0 20rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: space-between;
background-color: rgba(0,0,0,0.7);
.banner-subtitle {
font-size: 24rpx;
color: rgba(255,255,255,0.8);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 60%;
}
.dotbox{
display:flex;
align-items: center;
.circle{
margin:0 4rpx;
width:16rpx;
height:16rpx;
background-color: #eee;
border-radius: 50%;
}
.circle.active{
background-color: #8B2316;
}
}
}
}
.news-scroll-view {
position: fixed;
bottom:0;
width:100%;
top:140rpx;
height: calc(100vh - 140rpx); // 仅减去导航栏高度
background-color: #f8f8f8;
}
.news-list {
padding: 20rpx;
background-color: #f8f8f8;
.news-item {
display: flex;
background-color: #ffffff;
border-radius: 16rpx;
margin-bottom: 20rpx;
padding: 20rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
overflow: hidden; // Ensure content respects border-radius
.item-image-container {
flex-shrink: 0;
width: 200rpx;
height: 160rpx;
border-radius: 8rpx;
overflow: hidden;
margin-right: 20rpx;
position: relative;
background-color: #f0f0f0; // Placeholder background
.item-image {
width: 100%;
height: 100%;
object-fit: cover;
}
.important-tag {
position: absolute;
top: 0;
left: 0;
background-color: #ff4757;
color: #fff;
font-size: 20rpx;
padding: 4rpx 12rpx;
border-bottom-right-radius: 8rpx;
z-index: 1;
}
}
.item-content {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.item-title {
font-size: 32rpx;
font-weight: normal; // Removed bold as per previous request
color: #333;
line-height: 1.4;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2; // Fixed two-line height
overflow: hidden;
text-overflow: ellipsis;
margin-bottom: 10rpx;
}
.item-meta {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 24rpx;
color: #999;
.item-date {
flex-shrink: 0;
}
.item-stats {
display: flex;
align-items: center;
text {
margin-left: 8rpx;
}
}
}
}
}
.load-more-status {
text-align: center;
padding: 40rpx 0;
color: #999;
font-size: 28rpx;
.loading {
display: flex;
align-items: center;
justify-content: center;
gap: 10rpx;
}
.more {
color: #666;
}
.no-more {
color: #ccc;
}
}
</style>