473 lines
11 KiB
Vue
473 lines
11 KiB
Vue
|
|
<!-- 小区活动详情页 -->
|
|||
|
|
<template>
|
|||
|
|
<s-layout title="小区活动">
|
|||
|
|
<view class="activity-detail-page">
|
|||
|
|
<!-- 顶部Banner轮播 -->
|
|||
|
|
<swiper class="banner-swiper" :autoplay="true" :interval="3000" :circular="true" indicator-dots indicator-color="rgba(255,255,255,0.4)" active-color="#FFFFFF">
|
|||
|
|
<swiper-item v-for="(img, index) in activityInfo.banners" :key="index">
|
|||
|
|
<image class="banner-img" :src="img" mode="aspectFill" />
|
|||
|
|
</swiper-item>
|
|||
|
|
</swiper>
|
|||
|
|
|
|||
|
|
<!-- Tab 切换栏 -->
|
|||
|
|
<view class="tab-bar">
|
|||
|
|
<view
|
|||
|
|
class="tab-item"
|
|||
|
|
:class="{ active: currentTab === 'basic' }"
|
|||
|
|
@tap="currentTab = 'basic'"
|
|||
|
|
>
|
|||
|
|
<text class="tab-text">基本信息</text>
|
|||
|
|
</view>
|
|||
|
|
<view
|
|||
|
|
class="tab-item"
|
|||
|
|
:class="{ active: currentTab === 'intro' }"
|
|||
|
|
@tap="currentTab = 'intro'"
|
|||
|
|
>
|
|||
|
|
<text class="tab-text">活动简介</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 内容区域 - 独立滚动 -->
|
|||
|
|
<scroll-view class="detail-scroll" scroll-y :style="{ height: scrollViewHeight + 'px' }">
|
|||
|
|
<view class="detail-content">
|
|||
|
|
<!-- 基本信息 -->
|
|||
|
|
<template v-if="currentTab === 'basic'">
|
|||
|
|
<!-- 活动标题 -->
|
|||
|
|
<view class="activity-title">{{ activityInfo.title }}</view>
|
|||
|
|
|
|||
|
|
<!-- 地址 -->
|
|||
|
|
<view class="info-row location-row">
|
|||
|
|
<text class="sicon-location"></text>
|
|||
|
|
<text class="location-text">{{ activityInfo.location }}</text>
|
|||
|
|
<text class="sicon-right navigation-icon" @tap="openNavigation"></text>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 服务类别 -->
|
|||
|
|
<view class="info-row tag-row">
|
|||
|
|
<text class="label-text">服务类别:</text>
|
|||
|
|
<view class="tag-list">
|
|||
|
|
<text
|
|||
|
|
class="tag-item"
|
|||
|
|
v-for="(tag, index) in activityInfo.serviceTypes"
|
|||
|
|
:key="index"
|
|||
|
|
>{{ tag }}</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 服务对象 -->
|
|||
|
|
<view class="info-row tag-row">
|
|||
|
|
<text class="label-text">服务对象:</text>
|
|||
|
|
<view class="tag-list">
|
|||
|
|
<text
|
|||
|
|
class="tag-item target-tag"
|
|||
|
|
v-for="(tag, index) in activityInfo.targetAudience"
|
|||
|
|
:key="index"
|
|||
|
|
>{{ tag }}</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 报名日期 -->
|
|||
|
|
<view class="info-row text-row">
|
|||
|
|
<text class="label-text">报名日期:</text>
|
|||
|
|
<text class="value-text">{{ activityInfo.registerDate }}</text>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 活动日期 -->
|
|||
|
|
<view class="info-row text-row">
|
|||
|
|
<text class="label-text">活动日期:</text>
|
|||
|
|
<text class="value-text">{{ activityInfo.activityDate }}</text>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 人数上限 -->
|
|||
|
|
<view class="info-row text-row">
|
|||
|
|
<text class="sicon-person"></text>
|
|||
|
|
<text class="label-text">人数上限:</text>
|
|||
|
|
<text class="value-text">{{ activityInfo.maxPeople }}人</text>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 联系人 -->
|
|||
|
|
<view class="info-row contact-row" @tap="callPhone">
|
|||
|
|
<text class="sicon-phone"></text>
|
|||
|
|
<text class="contact-name">{{ activityInfo.contactName }}</text>
|
|||
|
|
<text class="contact-phone">{{ activityInfo.contactPhone }}</text>
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<!-- 活动简介 -->
|
|||
|
|
<template v-if="currentTab === 'intro'">
|
|||
|
|
<view class="intro-content">
|
|||
|
|
<mp-html :content="activityInfo.introduction"></mp-html>
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<!-- 底部占位,防止内容被底部按钮遮挡 -->
|
|||
|
|
<view class="bottom-placeholder"></view>
|
|||
|
|
</view>
|
|||
|
|
</scroll-view>
|
|||
|
|
|
|||
|
|
<!-- 底部固定按钮栏 -->
|
|||
|
|
<view class="bottom-bar">
|
|||
|
|
<view class="registered-btn" @tap="showRegisteredList">
|
|||
|
|
<text class="registered-text">已有{{ activityInfo.registeredCount }}人报名</text>
|
|||
|
|
</view>
|
|||
|
|
<view class="back-btn" @tap="goBack">
|
|||
|
|
<text class="back-text">返回</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</s-layout>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup>
|
|||
|
|
import { ref, onMounted, nextTick, getCurrentInstance } from 'vue';
|
|||
|
|
import { onLoad } from '@dcloudio/uni-app';
|
|||
|
|
|
|||
|
|
// 当前Tab
|
|||
|
|
const currentTab = ref('basic');
|
|||
|
|
|
|||
|
|
// 列表滚动区域高度(单位:px)
|
|||
|
|
const scrollViewHeight = ref(0);
|
|||
|
|
|
|||
|
|
// 活动详情数据
|
|||
|
|
const activityInfo = ref({
|
|||
|
|
id: null,
|
|||
|
|
title: '',
|
|||
|
|
banners: [],
|
|||
|
|
location: '',
|
|||
|
|
serviceTypes: [],
|
|||
|
|
targetAudience: [],
|
|||
|
|
registerDate: '',
|
|||
|
|
activityDate: '',
|
|||
|
|
maxPeople: 0,
|
|||
|
|
contactName: '',
|
|||
|
|
contactPhone: '',
|
|||
|
|
registeredCount: 0,
|
|||
|
|
introduction: ''
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 页面加载
|
|||
|
|
onLoad((options) => {
|
|||
|
|
if (options.id) {
|
|||
|
|
loadActivityDetail(options.id);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 渲染完成后计算scroll-view高度
|
|||
|
|
onMounted(() => {
|
|||
|
|
const instance = getCurrentInstance();
|
|||
|
|
nextTick(() => {
|
|||
|
|
const sysInfo = uni.getSystemInfoSync();
|
|||
|
|
uni.createSelectorQuery()
|
|||
|
|
.in(instance)
|
|||
|
|
.select('.tab-bar')
|
|||
|
|
.boundingClientRect((rect) => {
|
|||
|
|
if (rect) {
|
|||
|
|
// scroll-view高度 = 屏幕可用高度 - tab栏高度 - tab栏距顶部距离 - 底部按钮高度(120rpx)
|
|||
|
|
scrollViewHeight.value = sysInfo.windowHeight - rect.height - rect.top - 60;
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
.exec();
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 加载活动详情
|
|||
|
|
async function loadActivityDetail(id) {
|
|||
|
|
// TODO: 调用API获取活动详情
|
|||
|
|
// 模拟数据
|
|||
|
|
activityInfo.value = {
|
|||
|
|
id: id,
|
|||
|
|
title: 'xxxxxxxxxxxxxxxxx活动',
|
|||
|
|
banners: [
|
|||
|
|
'/static/img/guest.png',
|
|||
|
|
'/static/img/login_img.png'
|
|||
|
|
],
|
|||
|
|
location: '福清市音西街道',
|
|||
|
|
serviceTypes: ['社区服务', '敬老服务', '助残服务', '关爱儿童'],
|
|||
|
|
targetAudience: ['儿童', '孤寡老人', '残障人士', '优抚对象'],
|
|||
|
|
registerDate: '2025/06/30-2025/07/01',
|
|||
|
|
activityDate: '2025/07/05 12:00-2025/07/05 18:00',
|
|||
|
|
maxPeople: 100,
|
|||
|
|
contactName: '王德福',
|
|||
|
|
contactPhone: '13322471131',
|
|||
|
|
registeredCount: 37,
|
|||
|
|
introduction: `<p>本次活动旨在丰富社区居民文化生活,增进邻里关系,共建和谐社区。</p><p>欢迎各位居民踊跃参与!</p>`
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 打开导航
|
|||
|
|
function openNavigation() {
|
|||
|
|
// TODO: 调用地图导航
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 拨打电话
|
|||
|
|
function callPhone() {
|
|||
|
|
if (activityInfo.value.contactPhone) {
|
|||
|
|
uni.makePhoneCall({
|
|||
|
|
phoneNumber: activityInfo.value.contactPhone
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 显示已报名列表
|
|||
|
|
function showRegisteredList() {
|
|||
|
|
// TODO: 弹出已报名人员列表或跳转页面
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '查看报名名单',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 返回上一页
|
|||
|
|
function goBack() {
|
|||
|
|
uni.navigateBack();
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style lang="scss" scoped>
|
|||
|
|
/* 页面容器 */
|
|||
|
|
.activity-detail-page {
|
|||
|
|
position: relative;
|
|||
|
|
min-height: 100vh;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 顶部Banner轮播 */
|
|||
|
|
.banner-swiper {
|
|||
|
|
width: 100%;
|
|||
|
|
height: 400rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.banner-img {
|
|||
|
|
width: 100%;
|
|||
|
|
height: 400rpx;
|
|||
|
|
display: block;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* Tab 切换栏 */
|
|||
|
|
.tab-bar {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
background-color: #FFFFFF;
|
|||
|
|
padding: 0 32rpx;
|
|||
|
|
border-bottom: 1rpx solid #F0F0F0;
|
|||
|
|
|
|||
|
|
.tab-item {
|
|||
|
|
flex: 1;
|
|||
|
|
text-align: center;
|
|||
|
|
padding: 28rpx 0;
|
|||
|
|
position: relative;
|
|||
|
|
|
|||
|
|
.tab-text {
|
|||
|
|
font-size: 30rpx;
|
|||
|
|
color: #999999;
|
|||
|
|
transition: all 0.3s;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&.active {
|
|||
|
|
&::after {
|
|||
|
|
content: '';
|
|||
|
|
position: absolute;
|
|||
|
|
bottom: 0;
|
|||
|
|
left: 50%;
|
|||
|
|
transform: translateX(-50%);
|
|||
|
|
width: 120rpx;
|
|||
|
|
height: 4rpx;
|
|||
|
|
background: #FA7E49;
|
|||
|
|
border-radius: 2rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&.active .tab-text {
|
|||
|
|
font-size: 30rpx;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: #333333;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 内容滚动区域 */
|
|||
|
|
.detail-scroll {
|
|||
|
|
/* 高度由JS动态绑定 */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 详情内容 */
|
|||
|
|
.detail-content {
|
|||
|
|
background-color: #FFFFFF;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 活动标题 */
|
|||
|
|
.activity-title {
|
|||
|
|
padding: 32rpx 32rpx 16rpx;
|
|||
|
|
font-size: 34rpx;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: #FA7E49;
|
|||
|
|
line-height: 1.5;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 信息行 */
|
|||
|
|
.info-row {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: flex-start;
|
|||
|
|
padding: 20rpx 32rpx;
|
|||
|
|
|
|||
|
|
.sicon-location,
|
|||
|
|
.sicon-phone,
|
|||
|
|
.sicon-person {
|
|||
|
|
font-size: 32rpx;
|
|||
|
|
color: #666666;
|
|||
|
|
margin-right: 8rpx;
|
|||
|
|
margin-top: 2rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 地址行 */
|
|||
|
|
.location-row {
|
|||
|
|
align-items: center;
|
|||
|
|
|
|||
|
|
.location-text {
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
color: #333333;
|
|||
|
|
flex: 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.navigation-icon {
|
|||
|
|
font-size: 36rpx;
|
|||
|
|
color: #FA7E49;
|
|||
|
|
flex-shrink: 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 标签行 */
|
|||
|
|
.tag-row {
|
|||
|
|
align-items: flex-start;
|
|||
|
|
|
|||
|
|
.label-text {
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
color: #333333;
|
|||
|
|
flex-shrink: 0;
|
|||
|
|
line-height: 1.8;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tag-list {
|
|||
|
|
display: flex;
|
|||
|
|
flex-wrap: wrap;
|
|||
|
|
gap: 12rpx;
|
|||
|
|
flex: 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tag-item {
|
|||
|
|
font-size: 24rpx;
|
|||
|
|
color: #FA7E49;
|
|||
|
|
border: 1rpx solid #FA7E49;
|
|||
|
|
border-radius: 8rpx;
|
|||
|
|
padding: 6rpx 16rpx;
|
|||
|
|
background-color: rgba(250, 126, 73, 0.04);
|
|||
|
|
line-height: 1.4;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.target-tag {
|
|||
|
|
color: #FA7E49;
|
|||
|
|
border: 1rpx solid #FA7E49;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 文本行 */
|
|||
|
|
.text-row {
|
|||
|
|
.label-text {
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
color: #333333;
|
|||
|
|
flex-shrink: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.value-text {
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
color: #333333;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 联系人行 */
|
|||
|
|
.contact-row {
|
|||
|
|
align-items: center;
|
|||
|
|
|
|||
|
|
&:active {
|
|||
|
|
opacity: 0.7;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.contact-name {
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
color: #333333;
|
|||
|
|
margin-left: 8rpx;
|
|||
|
|
margin-right: 24rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.contact-phone {
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
color: #333333;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 活动简介内容 */
|
|||
|
|
.intro-content {
|
|||
|
|
padding: 32rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 底部占位 */
|
|||
|
|
.bottom-placeholder {
|
|||
|
|
height: 140rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 底部固定按钮栏 */
|
|||
|
|
.bottom-bar {
|
|||
|
|
position: fixed;
|
|||
|
|
bottom: 0;
|
|||
|
|
left: 0;
|
|||
|
|
right: 0;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 24rpx;
|
|||
|
|
padding: 20rpx 32rpx;
|
|||
|
|
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
|||
|
|
background-color: #FFFFFF;
|
|||
|
|
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.06);
|
|||
|
|
|
|||
|
|
.registered-btn {
|
|||
|
|
flex: 1;
|
|||
|
|
height: 88rpx;
|
|||
|
|
border: 2rpx solid #FA7E49;
|
|||
|
|
border-radius: 44rpx;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
|
|||
|
|
&:active {
|
|||
|
|
opacity: 0.85;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.registered-text {
|
|||
|
|
font-size: 30rpx;
|
|||
|
|
color: #FA7E49;
|
|||
|
|
font-weight: 500;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.back-btn {
|
|||
|
|
width: 240rpx;
|
|||
|
|
height: 88rpx;
|
|||
|
|
background-color: #FA7E49;
|
|||
|
|
border-radius: 44rpx;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
|
|||
|
|
&:active {
|
|||
|
|
opacity: 0.85;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.back-text {
|
|||
|
|
font-size: 30rpx;
|
|||
|
|
color: #FFFFFF;
|
|||
|
|
font-weight: 500;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|