uniapp-app/pages/live/live.vue
2025-08-21 17:45:03 +08:00

808 lines
18 KiB
Vue
Raw 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>
<uni-nav-bar title="肝胆会议" fixed color="#8B2316" height="140rpx" :border="false" backgroundColor="#eeeeee"></uni-nav-bar>
<view class="page">
<!-- 筛选标签栏 -->
<view class="filter-bar">
<view class="filter-item active" @click="showTimePopup">
<text>会议时间</text>
<up-image :src="select" width="26rpx" height="26rpx" ></up-image>
</view>
<view class="filter-divider"></view>
<view class="filter-item" @click="showLocationPopup">
<text>会议地点</text>
<up-image :src="select" width="26rpx" height="26rpx" ></up-image>
</view>
<view class="filter-divider"></view>
<view class="filter-item">
<text>会议回放</text>
</view>
</view>
<!-- 可滚动内容区域 -->
<scroll-view
ref="scrollView"
class="scroll-content"
scroll-y="true"
refresher-enabled="true"
:refresher-triggered="isRefreshing"
:refresher-threshold="100"
@refresherrefresh="onRefresh"
@scrolltolower="onLoadMore"
:lower-threshold="100"
:scroll-top="scrollTop"
:enable-back-to-top="true"
>
<!-- 时间标题 -->
<view class="time-header">2025年08月</view>
<!-- 会议列表 -->
<view class="meeting-list">
<view class="meeting-item" v-for="(item, index) in meetingList" :key="index">
<!-- 左侧日期标识 -->
<view class="date-tag" :style="{backgroundColor: item.tagColor}">
<text class="date-text">{{ item.date }}</text>
</view>
<!-- 会议内容 -->
<view class="meeting-content">
<view class="meeting-title">{{ item.title }}</view>
<view class="meeting-poster" @click="playVideo(item)">
<image :src="item.poster" class="poster-image"></image>
<view class="play-btn">
<up-image :src="playImg" width="108rpx" height="108rpx" ></up-image>
</view>
<view class="preview-tag">预告</view>
</view>
<view class="meeting-info">
<view class="info-item">
<view class="timebox">
<up-image :src="timeImg" width="24rpx" height="24rpx" ></up-image>
</view>
<text class="info-text">{{ item.time }}</text>
</view>
<view class="info-item">
<uni-icons type="location" size="14" color="#999"></uni-icons>
<text class="info-text">{{ item.location }}</text>
</view>
</view>
</view>
</view>
</view>
<!-- 加载更多提示 -->
<view class="load-more" v-if="showLoadMore">
<view class="load-more-content" v-if="isLoadingMore">
<uni-icons type="spinner-cycle" size="20" color="#999"></uni-icons>
<text class="load-more-text">加载中...</text>
</view>
<view class="load-more-content" v-else-if="hasMoreData">
<text class="load-more-text">上拉加载更多</text>
</view>
<view class="load-more-content" v-else>
<text class="load-more-text">没有更多数据了</text>
</view>
</view>
</scroll-view>
<!-- 时间选择弹窗 -->
<view class="time-popup" v-if="isTimePopupShow" @click="hideTimePopup">
<view class="popup-mask"></view>
<view class="time-popup-content" @click.stop>
<view class="time-list">
<view
class="time-item"
v-for="(month, index) in monthList"
:key="index"
:class="{ active: selectedMonth === month.value }"
@click="selectMonth(month)"
>
<text>{{ month.label }}</text>
</view>
</view>
</view>
</view>
<!-- 地区选择弹窗 -->
<view class="location-popup" v-if="isLocationPopupShow" @click="hideLocationPopup">
<view class="popup-mask"></view>
<view class="popup-content" @click.stop>
<view class="location-grid">
<view
class="location-item"
v-for="(province, index) in provinceList"
:key="index"
:class="{ active: selectedProvince === province.code }"
@click="selectProvince(province)"
>
<text>{{ province.name }}</text>
</view>
</view>
</view>
</view>
<!-- 过往会议提示 -->
<view class="history-tip">
<view class="tip-icon">
<up-icon name="clock" color="#00cbc0" size="28"></up-icon>
</view>
<text class="tip-text">过往会议</text>
</view>
<!-- 底部导航栏 -->
<CustomTabbar></CustomTabbar>
</view>
</template>
<script setup>
import { ref,nextTick} from 'vue';
import { onShow } from "@dcloudio/uni-app";
import CustomTabbar from '@/components/tabBar/tabBar.vue';
import select from "@/static/triangle_normal.png"
import selectOn from "@/static/triangle_normal.png"
import playImg from "@/static/bofang.png"
import timeImg from "@/static/play_long.png"
// 弹窗状态
const isTimePopupShow = ref(false);
const isLocationPopupShow = ref(false);
const selectedMonth = ref('all');
const selectedProvince = ref('');
// 下拉刷新和上拉加载状态
const isRefreshing = ref(false);
const isLoadingMore = ref(false);
const hasMoreData = ref(true);
const showLoadMore = ref(true);
const currentPage = ref(1);
const pageSize = ref(10);
const scrollTop = ref(0);
// 月份数据
const monthList = ref([
{ value: 'all', label: '所有' },
{ value: '8', label: '8月' },
{ value: '9', label: '9月' },
{ value: '10', label: '10月' },
{ value: '11', label: '11月' },
{ value: '12', label: '12月' },
{ value: '1', label: '1月' },
{ value: '2', label: '2月' },
{ value: '3', label: '3月' },
{ value: '4', label: '4月' },
{ value: '5', label: '5月' },
{ value: '6', label: '6月' },
{ value: '7', label: '7月' }
]);
// 省份数据
const provinceList = ref([
{ code: 'all', name: '全国' },
{ code: 'beijing', name: '北京市' },
{ code: 'tianjin', name: '天津市' },
{ code: 'hebei', name: '河北省' },
{ code: 'shanxi', name: '山西省' },
{ code: 'neimenggu', name: '内蒙古...' },
{ code: 'liaoning', name: '辽宁省' },
{ code: 'jilin', name: '吉林省' },
{ code: 'heilongjiang', name: '黑龙江省' },
{ code: 'shanghai', name: '上海市' },
{ code: 'jiangsu', name: '江苏省' },
{ code: 'zhejiang', name: '浙江省' },
{ code: 'anhui', name: '安徽省' },
{ code: 'fujian', name: '福建省' },
{ code: 'jiangxi', name: '江西省' },
{ code: 'shandong', name: '山东省' },
{ code: 'henan', name: '河南省' },
{ code: 'hubei', name: '湖北省' },
{ code: 'hunan', name: '湖南省' },
{ code: 'guangdong', name: '广东省' },
{ code: 'guangxi', name: '广西壮...' },
{ code: 'hainan', name: '海南省' },
{ code: 'chongqing', name: '重庆市' },
{ code: 'sichuan', name: '四川省' },
{ code: 'guizhou', name: '贵州省' },
{ code: 'yunnan', name: '云南省' },
{ code: 'xizang', name: '西藏自...' },
{ code: 'shaanxi', name: '陕西省' },
{ code: 'gansu', name: '甘肃省' },
{ code: 'qinghai', name: '青海省' },
{ code: 'ningxia', name: '宁夏回...' },
{ code: 'xinjiang', name: '新疆维...' },
{ code: 'taiwan', name: '台湾省' },
{ code: 'hongkong', name: '香港特...' },
{ code: 'macao', name: '澳门特...' }
]);
// 会议列表数据
const meetingList = ref([
{
date: '13',
tagColor: '#FF4444',
title: '"天山论·见"—疑难危重病患维训练营',
poster: '/static/meeting-poster-1.jpg',
time: '2025.08.13',
location: '线上'
},
{
date: '13',
tagColor: '#FFA500',
title: '护肝新声大咖谈',
poster: '/static/meeting-poster-2.jpg',
time: '2025.08.13',
location: '线上'
},
{
date: '15',
tagColor: '#00BCD4',
title: '小罐医生讲HIV和感染专题二:抗菌药物-抗真菌药物特性解读',
poster: '/static/meeting-poster-3.jpg',
time: '2025.08.15',
location: '线上'
}
]);
// 显示时间选择弹窗
const showTimePopup = () => {
isTimePopupShow.value = !isTimePopupShow.value;
};
// 隐藏时间选择弹窗
const hideTimePopup = () => {
isTimePopupShow.value = false;
};
// 选择月份
const selectMonth = (month) => {
selectedMonth.value = month.value;
console.log('选择月份:', month.label);
// 这里可以根据选择的月份筛选会议数据
hideTimePopup();
};
// 显示地区选择弹窗
const showLocationPopup = () => {
isLocationPopupShow.value = !isLocationPopupShow.value;
};
// 隐藏地区选择弹窗
const hideLocationPopup = () => {
isLocationPopupShow.value = false;
};
// 选择省份
const selectProvince = (province) => {
selectedProvince.value = province.code;
console.log('选择省份:', province.name);
// 这里可以根据选择的省份筛选会议数据
hideLocationPopup();
};
// 播放视频
const playVideo = (item) => {
console.log('播放视频:', item.title);
// 这里可以实现视频播放逻辑
};
// 下拉刷新
const onRefresh = () => {
isRefreshing.value = true;
currentPage.value = 1;
hasMoreData.value = true;
// 模拟网络请求
setTimeout(() => {
// 重置会议列表为初始数据
meetingList.value = [
{
date: '13',
tagColor: '#FF4444',
title: '"天山论·见"—疑难危重病患维训练营',
poster: '/static/meeting-poster-1.jpg',
time: '2025.08.13',
location: '线上'
},
{
date: '13',
tagColor: '#FFA500',
title: '护肝新声大咖谈',
poster: '/static/meeting-poster-2.jpg',
time: '2025.08.13',
location: '线上'
},
{
date: '15',
tagColor: '#00BCD4',
title: '小罐医生讲HIV和感染专题二:抗菌药物-抗真菌药物特性解读',
poster: '/static/meeting-poster-3.jpg',
time: '2025.08.15',
location: '线上'
}
];
isRefreshing.value = false;
uni.showToast({
title: '刷新成功',
icon: 'success',
duration: 1500
});
}, 1500);
};
// 上拉加载更多
const onLoadMore = () => {
console.log('上拉加载');
if (isLoadingMore.value || !hasMoreData.value) return;
isLoadingMore.value = true;
currentPage.value++;
// 模拟网络请求
setTimeout(() => {
// 模拟新增数据
const newMeetings = [
{
date: '16',
tagColor: '#9C27B0',
title: '肝胆外科微创技术研讨会',
poster: '/static/meeting-poster-4.jpg',
time: '2025.08.16',
location: '北京'
},
{
date: '17',
tagColor: '#FF9800',
title: '胆囊疾病诊疗新进展',
poster: '/static/meeting-poster-5.jpg',
time: '2025.08.17',
location: '上海'
},
{
date: '18',
tagColor: '#4CAF50',
title: '肝移植术后管理专题讲座',
poster: '/static/meeting-poster-6.jpg',
time: '2025.08.18',
location: '广州'
}
];
meetingList.value.push(...newMeetings);
// 模拟没有更多数据的情况第3页后
if (currentPage.value >= 3) {
hasMoreData.value = false;
}
isLoadingMore.value = false;
// 强制更新页面确保scroll-view可以正常滚动
nextTick(() => {
console.log('数据加载完成,列表长度:', meetingList.value.length);
});
}, 1000);
};
</script>
<style lang="scss" scoped>
// 颜色变量
$primary-color: #D32F2F;
$secondary-color: #8B2316;
$background-color: #f5f5f5;
$white: #ffffff;
$gray-light: #f0f0f0;
$gray: #666;
$gray-dark: #333;
$gray-text: #999;
$border-color: #e0e0e0;
$green-accent: #00D4AA;
$shadow: 0 2px 8px rgba(0,0,0,0.1);
.page {
background-color: $background-color;
min-height: 100vh;
padding-bottom: 120rpx;
}
// 可滚动内容区域
.scroll-content {
position: fixed;
top: 228rpx; // 导航栏140rpx + 筛选栏88rpx
left: 0;
right: 0;
bottom: 120rpx; // 底部导航栏高度
width: 100%;
}
// 筛选标签栏
.filter-bar {
position:fixed ;
top:140rpx;
width:100%;
z-index:2;
background-color: $white;
height: 88rpx;
display: flex;
align-items: center;
padding: 0 30rpx;
border-bottom: 2rpx solid $gray-light;
.filter-item {
flex:1;
display: flex;
align-items: center;
padding: 0 20rpx;
font-size: 28rpx;
color: $gray;
text{
margin-right: 10rpx;
}
&.active {
color: $gray-dark;
}
}
.filter-divider {
width: 2rpx;
height: 32rpx;
background-color: $border-color;
margin: 0 10rpx;
}
}
// 时间选择弹窗
.time-popup {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
display: flex;
.popup-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.time-popup-content {
margin-top: 231rpx;
position: relative;
background-color: $white;
width: 100%;
height: calc(100vh - 348rpx);
.time-list {
padding: 0;
height: 100%;
overflow-y: auto;
.time-item {
padding: 25rpx 60rpx;
font-size: 32rpx;
color: #666;
border-bottom: 2rpx solid #f0f0f0;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
&:hover {
background-color: #f8f8f8;
}
&.active {
background-color: #f8f8f8;
color: $primary-color;
text {
font-weight: 500;
}
}
&:last-child {
border-bottom: none;
}
text {
display: block;
width: 100%;
}
}
}
}
}
// 地区选择弹窗
.location-popup {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
display: flex;
.popup-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.popup-content {
margin-top: 231rpx;
position: relative;
background-color: $white;
width: 100%;
height: calc(100vh - 433rpx);
padding:40rpx;
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
.popup-title {
font-size: 18px;
font-weight: 500;
color: $gray-dark;
}
.close-btn {
width: 30px;
height: 30px;
background-color: $gray-light;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
color: $gray;
cursor: pointer;
}
}
.location-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 30rpx;
height: 100%;
overflow-y: auto;
.location-item {
padding: 16rpx;
background-color: $background-color;
border-radius: 16rpx;
text-align: center;
font-size: 28rpx;
color: #999;
border: 2rpx solid #999;
cursor: pointer;
transition: all 0.3s ease;
&:hover {
background-color: lighten($primary-color, 45%);
}
&.active {
background-color: lighten($primary-color, 40%);
border-color: $primary-color;
color: $primary-color;
}
text {
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-all;
}
}
}
}
}
// 时间标题
.time-header {
text-align: center;
padding: 30rpx 0;
font-size: 32rpx;
color: $gray;
background-color: $background-color;
}
// 会议列表
.meeting-list {
padding: 0 30rpx;
.meeting-item {
display: flex;
margin-bottom: 30rpx;
background-color: $white;
border-radius: 16rpx;
overflow: hidden;
box-shadow: $shadow;
// 日期标识
.date-tag {
width: 50rpx;
display: flex;
align-items: center;
justify-content: center;
position:relative;
.date-text {
background: $white;
position:absolute;
top:50%;
color:red;
transform:translateY(-50%);
font-size: 32rpx;
width:40rpx;
display: flex;
justify-content: center;
align-items: center;
left: 35rpx;
height: 40rpx;
border-radius:50%;
}
}
// 会议内容
.meeting-content {
flex: 1;
padding: 30rpx;
.meeting-title {
font-size: 32rpx;
font-weight: 500;
color: $gray-dark;
margin-bottom: 20rpx;
line-height: 1.4;
}
.meeting-poster {
position: relative;
height: 240rpx;
border-radius: 12rpx;
overflow: hidden;
margin-bottom: 20rpx;
.poster-image {
width: 100%;
height: 100%;
object-fit: cover;
}
.play-btn {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width:210rpx;
height:210rpx;
opacity: 0.3;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.preview-tag {
position: absolute;
top: 16rpx;
right: 16rpx;
border: 4rpx solid #fff;
color: $white;
font-size: 24rpx;
padding: 4rpx 16rpx;
border-radius: 20rpx;
}
}
.meeting-info {
display: flex;
justify-content: space-between;
.info-item {
display: flex;
align-items: center;
.timebox{
margin-top: -19rpx;
}
.info-text {
font-size: 24rpx;
color: $gray-text;
margin-left: 8rpx;
}
}
}
}
}
}
// 加载更多提示
.load-more {
padding: 30rpx;
.load-more-content {
display: flex;
align-items: center;
justify-content: center;
.load-more-text {
font-size: 28rpx;
color: $gray-text;
margin-left: 10rpx;
}
}
}
// 过往会议提示
.history-tip {
position: fixed;
bottom:200rpx;
z-index:9;
right:0;
border-radius: 50rpx 0 0 50rpx;
background:#00cbc0;
display: flex;
align-items: center;
justify-content: center;
padding: 10rpx 10rpx;
.tip-icon {
padding:10rpx;
background-color: #fff;
margin-right: 10rpx;
border-radius: 50%;
}
.tip-text {
width: 60rpx;
font-size: 26rpx;
color:#fff;
}
}
// 底部导航栏
.bottom-nav {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 60px;
background-color: $white;
display: flex;
border-top: 1px solid $gray-light;
.nav-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 5px 0;
.nav-text {
font-size: 10px;
color: $gray-text;
margin-top: 2px;
&.active {
color: $primary-color;
}
}
}
}
</style>