国外MOSE官网
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

424 lines
11 KiB

<template>
<view class="activity-detail">
<!-- 轮播图 -->
<view class="banner-container">
<swiper class="banner-swiper" height="450rpx" :indicator-dots="true" :autoplay="true" :interval="3000" :duration="500">
<swiper-item v-for="(image, index) in activityData.image.split(',')" :key="index">
<image class="banner-image" :src="image" mode="aspectFill"></image>
</swiper-item>
</swiper>
</view>
<!-- 活动信息 -->
<view class="activity-info">
<!-- 活动标题和标签 -->
<view class="title-section">
<view class="activity-badge">
<text class="badge-text">{{ activityData.score }}</text>
</view>
<text class="activity-title">{{ activityData.title }}</text>
</view>
<!-- 活动详细信息 -->
<view class="info-section">
<view class="info-item">
<uv-icon name="calendar" size="16" color="#666"></uv-icon>
<text class="info-label">活动时间</text>
<text class="info-value">{{ activityData.activityTime }}</text>
</view>
<view class="info-item">
<uv-icon name="clock" size="16" color="#666"></uv-icon>
<text class="info-label">报名时间</text>
<text class="info-value">{{ activityData.startTime }}</text>
</view>
<view class="info-item">
<uv-icon name="account-fill" size="16" color="#666"></uv-icon>
<text class="info-label">联系人</text>
<text class="info-value">{{ activityData.contact }}</text>
</view>
<view class="info-item">
<uv-icon name="phone" size="16" color="#666"></uv-icon>
<text class="info-label">取消规则</text>
<text class="info-value">{{ activityData.rule }}</text>
</view>
<view class="info-item">
<uv-icon name="map-fill" size="16" color="#666"></uv-icon>
<text class="info-label">活动地点</text>
<text class="info-value">{{ activityData.address }}</text>
</view>
</view>
<!-- 活动详情 -->
<view class="detail-section">
<view class="section-title">
<text class="title-text">活动详情</text>
</view>
<view class="detail-content">
<!-- <text class="detail-text"> -->
<rich-text :nodes="activityData.details"></rich-text>
<!-- </text> -->
</view>
</view>
<!-- 活动图集 -->
<view class="gallery-section">
<view class="section-title">
<text class="title-text">活动图集</text>
</view>
<view class="gallery-grid">
<image
v-for="(image, index) in activityData.atlas.split(',')"
:key="index"
class="gallery-image"
:src="image"
mode="aspectFill"
@click="previewImage(image, activityData.atlas.split(','))"
></image>
<!-- <uv-album :urls="activityData.gallery"></uv-album> -->
</view>
</view>
</view>
<!-- 固定底部操作栏 -->
<view class="bottom-action">
<view class="action-left">
<view class="action-item" @click="shareActivity">
<uv-icon name="share" size="24" color="#000"></uv-icon>
<text class="action-text">分享</text>
</view>
<view class="action-item" @click="collectActivity">
<uv-icon name="heart-fill" size="24" :color="activityData.isCollection === 1 ? '#ff4757' : '#999'"></uv-icon>
<text class="action-text">收藏</text>
</view>
<view class="action-item">
<text class="participants-count">
<text :style="{'color': activityData.numActivity >= activityData.numLimit ? '#999' : '#1488DB'}">{{ activityData.numActivity }}</text>
/{{ activityData.numLimit }}</text>
<text class="action-text">已报名</text>
</view>
</view>
<view class="action-right">
<uv-button
type="primary"
size="normal"
text="我要报名"
shape="circle"
@click="signUpActivity"
:disabled="activityData.numActivity >= activityData.numLimit || activityData.isApply === 1 "
></uv-button>
</view>
</view>
<SignUpForm
ref="signUpFormRef"
@close="onSignUpFormClose"
@submit="onSignUpFormSubmit"
/>
</view>
<!-- 报名表单弹窗 -->
</template>
<script>
import SignUpForm from '@/subPages/index/components/SignUpForm.vue'
export default {
components: {
SignUpForm
},
data() {
return {
// isCollected: false,
showSignUpForm: false,
activityData: {
title: '关爱自闭症儿童活动',
duration: '30积分',
time: '2025-06-12 14:30',
registrationTime: '2025-06-01 14:30——2025-09-01 14:30',
contact: '柳老师 (13256484512)',
cancelRule: '报名随时可取消',
location: '长沙市雨花区时代阳光大夏国际大厅2145',
registeredCount: 9,
maxCount: 30,
details: [
'身体健康,热爱志愿服务工作,富有责任感和奉献精神',
'遵纪守法,思想上进,作风正派,服从安排',
'年龄在60岁以下,具备广告宣传理能力'
],
gallery: [
'/static/bannerImage.png',
'/static/bannerImage.png',
'/static/bannerImage.png',
'/static/bannerImage.png'
]
},
activityId: null
}
},
onLoad(options) {
if (options.id) {
this.activityId = options.id
this.loadActivityDetail(options.id)
}else {
uni.showToast({
title: '没有给活动id',
icon: 'none'
})
}
},
methods: {
async loadActivityDetail(id) {
// 根据ID加载活动详情
const res = await this.$api.activity.queryActivityById({
activityId: id
})
this.activityData = res.result
},
previewImage(current, urls) {
uni.previewImage({
current: current,
urls: urls
})
},
shareActivity() {
uni.showToast({
title: '分享功能',
icon: 'none'
})
},
async collectActivity() {
const res = await this.$api.activity.collectionActivity({
activityId: this.activityId
})
await this.loadActivityDetail(this.activityId)
uni.showToast({
title: `${res.message}`,
icon: 'none'
})
},
signUpActivity() {
if (this.activityData.numActivity >= this.activityData.numLimit) {
uni.showToast({
title: '报名人数已满',
icon: 'none'
})
return
}
this.$refs.signUpFormRef.open()
},
onSignUpFormClose() {
this.$refs.signUpFormRef.close()
},
async onSignUpFormSubmit(formData) {
console.log('报名表单数据:', formData)
// 这里可以调用API提交报名数据
const res = await this.$api.activity.applyActivity({
activityId: this.activityId,
...formData
})
if (res.code === 200) {
uni.showToast({
title: `${res.message}`,
icon: 'success'
})
// 更新状态
this.loadActivityDetail(this.activityId)
}
}
},
async onPullDownRefresh() {
await this.loadActivityDetail(this.activityId)
uni.stopPullDownRefresh()
}
}
</script>
<style lang="scss" scoped>
.activity-detail {
min-height: 100vh;
background: #f8f8f8;
padding-bottom: 120rpx;
.banner-container {
width: 100%;
height: 450rpx;
.banner-swiper {
width: 100%;
height: 100%;
.banner-image {
width: 100%;
height: 100%;
}
}
}
.activity-info {
background: #ffffff;
// border: 1rpx dashed #F3F7F8;
margin: 20rpx;
border-radius: 16rpx;
padding: 30rpx;
.title-section {
display: flex;
align-items: center;
margin-bottom: 30rpx;
.activity-badge {
background: #218CDD;
border-radius: 8rpx;
padding: 4rpx 10rpx;
margin-right: 16rpx;
.badge-text {
color: #ffffff;
font-size: 24rpx;
font-weight: 500;
}
}
.activity-title {
font-size: 36rpx;
font-weight: bold;
color: #333333;
flex: 1;
}
}
.info-section {
background: #F3F7F8;
margin-bottom: 40rpx;
// 虚线属性
border: 2rpx dashed #F3F7F8;
.info-item {
display: flex;
align-items: center;
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
.info-label {
font-size: 28rpx;
color: #999999;
margin-left: 12rpx;
margin-right: 8rpx;
}
.info-value {
font-size: 28rpx;
color: #999999;
flex: 1;
}
}
}
.detail-section {
margin-bottom: 40rpx;
.section-title {
margin-bottom: 20rpx;
.title-text {
font-size: 32rpx;
font-weight: bold;
color: #333333;
}
}
.detail-content {
.detail-text {
display: block;
font-size: 28rpx;
color: #666666;
line-height: 1.6;
margin-bottom: 16rpx;
&:last-child {
margin-bottom: 0;
}
}
}
}
.gallery-section {
.section-title {
margin-bottom: 20rpx;
.title-text {
font-size: 32rpx;
font-weight: bold;
color: #333333;
}
}
.gallery-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16rpx;
.gallery-image {
width: 100%;
height: 200rpx;
border-radius: 12rpx;
}
}
}
}
.bottom-action {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: #ffffff;
padding: 20rpx 30rpx;
border-top: 1rpx solid #eeeeee;
display: flex;
align-items: center;
justify-content: space-between;
z-index: 100;
.action-left {
display: flex;
align-items: center;
gap: 100rpx;
.action-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 8rpx;
.action-text {
font-size: 22rpx;
color: #000;
}
.participants-count {
font-size: 24rpx;
color: #333333;
// font-weight: bold;
}
}
}
.action-right {
flex-shrink: 0;
}
}
}
</style>