fjrcloud-community-app/pages/sub/activity/list.vue

332 lines
7.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!-- 小区活动列表页 -->
<template>
<s-layout title="小区活动">
<view class="activity-list-page">
<!-- 渐变背景装饰 -->
<view class="gradient-bg"></view>
<!-- 固定头部区域 -->
<view class="list-header">
<!-- 顶部提示条 -->
<view class="top-banner">
<text class="banner-text">融侨馨苑开展活动啦</text>
</view>
</view>
<!-- 活动列表 - 独立滚动 -->
<scroll-view class="activity-scroll" scroll-y :style="{ height: scrollViewHeight + 'px' }">
<view class="list-inner">
<view
class="activity-item"
v-for="(item, index) in activityList"
:key="index"
@tap="goDetail(item)"
>
<!-- 左侧封面图 -->
<image class="item-cover" :src="item.cover" mode="aspectFill" />
<!-- 右侧内容区 -->
<view class="item-content">
<text class="item-title">{{ item.title }}</text>
<view class="item-row">
<text class="item-location">{{ item.location }}</text>
<text class="item-status" :class="'status-' + item.statusType">{{ item.statusText }}</text>
</view>
<view class="item-row">
<text class="item-label">报名日期:</text>
<text class="item-value">{{ item.registerDate }}</text>
</view>
<view class="item-row">
<text class="item-date">{{ item.dateRange }}</text>
</view>
</view>
</view>
<!-- 空状态 -->
<view class="empty-state" v-if="activityList.length === 0">
<text class="empty-text">暂无活动</text>
</view>
</view>
</scroll-view>
<!-- 右下角浮动按钮 -->
<view class="float-btn" @tap="handleFloatBtn">
<text class="sicon-edit"></text>
</view>
</view>
</s-layout>
</template>
<script setup>
import { ref, onMounted, nextTick, getCurrentInstance } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
// 列表滚动区域高度单位px
const scrollViewHeight = ref(0);
// 活动列表数据
const activityList = ref([
{
id: 1,
title: 'xxxxxxxxxxxxx活动',
location: '福清市音西街道融侨馨苑',
statusText: '进行中',
statusType: 'ongoing',
registerDate: '2025/06/30-2025/07/01',
dateRange: '2025/07/05 12:00-2025/07/05 18:00',
cover: '/static/img/guest.png'
},
{
id: 2,
title: 'xxxxxxxxxxxxx活动',
location: '福清市音西街道融侨馨苑',
statusText: '报名中',
statusType: 'registering',
registerDate: '2025/06/30-2025/07/01',
dateRange: '2025/07/05 12:00-2025/07/05 18:00',
cover: '/static/img/guest.png'
},
{
id: 3,
title: 'xxxxxxxxxxxxx活动',
location: '福清市音西街道融侨馨苑',
statusText: '已结束',
statusType: 'ended',
registerDate: '2025/06/30-2025/07/01',
dateRange: '2025/07/05 12:00-2025/07/05 18:00',
cover: '/static/img/guest.png'
},
{
id: 4,
title: 'xxxxxxxxxxxxx活动',
location: '福清市音西街道融侨馨苑',
statusText: '已结束',
statusType: 'ended',
registerDate: '2025/06/30-2025/07/01',
dateRange: '2025/07/05 12:00-2025/07/05 18:00',
cover: '/static/img/guest.png'
},
{
id: 3,
title: 'xxxxxxxxxxxxx活动',
location: '福清市音西街道融侨馨苑',
statusText: '已结束',
statusType: 'ended',
registerDate: '2025/06/30-2025/07/01',
dateRange: '2025/07/05 12:00-2025/07/05 18:00',
cover: '/static/img/guest.png'
},
{
id: 4,
title: 'xxxxxxxxxxxxx活动',
location: '福清市音西街道融侨馨苑',
statusText: '已结束',
statusType: 'ended',
registerDate: '2025/06/30-2025/07/01',
dateRange: '2025/07/05 12:00-2025/07/05 18:00',
cover: '/static/img/guest.png'
}
]);
// 页面加载
onLoad(() => {
loadActivityList();
});
// 渲染完成后计算scroll-view高度
onMounted(() => {
const instance = getCurrentInstance();
nextTick(() => {
const sysInfo = uni.getSystemInfoSync();
uni.createSelectorQuery()
.in(instance)
.select('.list-header')
.boundingClientRect((rect) => {
if (rect) {
// scroll-view高度 = 屏幕可用高度 - 头部区域高度 - 头部距顶部距离
scrollViewHeight.value = sysInfo.windowHeight - rect.height - rect.top;
}
})
.exec();
});
});
// 加载活动列表
async function loadActivityList() {
// TODO: 调用API获取活动列表
}
// 跳转详情
function goDetail(item) {
uni.navigateTo({
url: `/pages/sub/activity/detail?id=${item.id}`
});
}
// 浮动按钮点击
function handleFloatBtn() {
// TODO: 发布活动或跳转相关页面
}
</script>
<style lang="scss" scoped>
/* 页面容器 - flex布局头部固定 + 列表滚动 */
.activity-list-page {
display: flex;
flex-direction: column;
min-height: 100vh;
position: relative;
}
/* 渐变背景装饰 - 覆盖导航栏到内容区 */
.gradient-bg {
position: absolute;
top: -176rpx; /* 向上延伸覆盖inner-navbar */
left: 0;
right: 0;
height: calc(100% + 176rpx);
background: linear-gradient(180deg, #F8EDE8 0%, #FFFFFF 30%);
z-index: -1; /* 在内容层下方 */
}
/* 固定头部区域 */
.list-header {
flex-shrink: 0; /* 不被压缩,固定不动 */
}
/* 顶部提示条 */
.top-banner {
padding: 24rpx 32rpx;
.banner-text {
font-size: 28rpx;
color: #FA7E49;
font-weight: 500;
}
}
/* 活动列表滚动区域 - 高度由JS动态绑定 */
.activity-scroll {
flex: 1; /* 占据剩余空间 */
}
/* 列表内容包裹层 */
.list-inner {
padding: 0 32rpx 160rpx; /* 底部留出空间给浮动按钮 */
}
/* 活动卡片 */
.activity-item {
display: flex;
background-color: #FFFFFF;
border-radius: 20rpx;
padding: 24rpx;
margin-bottom: 24rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
.item-cover {
width: 220rpx;
height: 180rpx;
border-radius: 12rpx;
flex-shrink: 0;
}
.item-content {
flex: 1;
margin-left: 24rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
.item-title {
font-size: 30rpx;
font-weight: 500;
color: #FA7E49;
line-height: 1.4;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
overflow: hidden;
text-overflow: ellipsis;
}
.item-row {
display: flex;
align-items: center;
margin-top: 8rpx;
}
.item-location {
font-size: 26rpx;
color: #333333;
flex: 1;
}
// 状态标签颜色
.item-status {
font-size: 26rpx;
font-weight: 500;
flex-shrink: 0;
&.status-ongoing { color: #52C41A; } // 进行中-绿色
&.status-registering { color: #FAAD14; } // 报名中-橙色
&.status-ended { color: #999999; } // 已结束-灰色
}
.item-label {
font-size: 24rpx;
color: #666666;
}
.item-value {
font-size: 24rpx;
color: #333333;
}
.item-date {
font-size: 24rpx;
color: #666666;
}
}
}
/* 空状态 */
.empty-state {
display: flex;
align-items: center;
justify-content: center;
padding: 200rpx 0;
.empty-text {
font-size: 28rpx;
color: #999999;
}
}
/* 右下角浮动按钮 */
.float-btn {
position: fixed;
right: 40rpx;
bottom: 80rpx;
width: 100rpx;
height: 100rpx;
background: linear-gradient(135deg, #FA7E49 0%, #E86935 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 8rpx 24rpx rgba(250, 126, 73, 0.4);
z-index: 99;
&:active {
opacity: 0.85;
transform: scale(0.95);
}
.sicon-edit {
font-size: 44rpx;
color: #FFFFFF;
}
}
</style>