buddhism/pages/activity/activity.vue
2025-08-04 11:47:19 +08:00

248 lines
6.4 KiB
Vue

<template>
<view class="page">
<custom-navbar title="寺庙活动" />
<view class="header" :style="{ backgroundColor: CommonEnum.BASE_COLOR }">
<!-- 状态展示 -->
<status-display
v-if="loading"
type="loading"
loading-text="加载中..."
/>
<!-- 错误状态 -->
<status-display
v-if="error"
type="error"
:error-text="error"
@retry="loadPageData"
/>
<!-- 空状态 -->
<status-display
v-if="!loading && !error && activityList.length === 0"
type="empty"
empty-text="暂无活动"
/>
<!-- 活动卡片列表 -->
<view class="activity-list" v-if="!loading && !error && activityList.length > 0">
<activity-card
v-for="activity in activityList"
:key="activity.id"
:activity="activity"
:show-title="true"
@card-click="handleCardClick"
@register="handleRegister"
/>
</view>
</view>
</view>
</template>
<script>
import CommonEnum from "../../enum/common";
import { ACTIVITY_STATUS, ACTIVITY_TYPE } from "../../enum/activity";
import StatusDisplay from "../../components/status-display/status-display.vue";
import ActivityCard from "../../components/activity-card/activity-card.vue";
import activityApi from "../../api/activity/activity.js";
import activityFormatter from "../../utils/activity-data-formatter.js";
export default {
components: {
StatusDisplay,
ActivityCard
},
data() {
return {
CommonEnum,
loading: false,
error: '',
activityList: [],
// 分页参数
pageNum: 1,
pageSize: 20,
hasMore: true
}
},
onLoad() {
// 页面加载时获取数据
this.loadPageData()
},
// 下拉刷新
onPullDownRefresh() {
this.refreshData()
},
// 上拉加载更多
onReachBottom() {
if (this.hasMore && !this.loading) {
this.loadMoreData()
}
},
methods: {
// 加载页面数据
async loadPageData() {
this.loading = true
this.error = ''
try {
const response = await activityApi.getActivityList({
pageNum: this.pageNum,
pageSize: this.pageSize
})
if (response.code === 200 && response.data) {
// 格式化数据
const formattedData = activityFormatter.formatActivityList(response.data)
this.activityList = formattedData
// 判断是否还有更多数据
this.hasMore = response.data.length >= this.pageSize
} else {
this.error = response.msg || '获取活动列表失败'
}
} catch (error) {
console.error('获取活动列表失败:', error)
this.error = '网络错误,请稍后重试'
} finally {
this.loading = false
uni.stopPullDownRefresh()
}
},
// 刷新数据
async refreshData() {
this.pageNum = 1
this.hasMore = true
await this.loadPageData()
},
// 加载更多数据
async loadMoreData() {
if (!this.hasMore || this.loading) return
this.loading = true
try {
const nextPage = this.pageNum + 1
const response = await activityApi.getActivityList({
pageNum: nextPage,
pageSize: this.pageSize
})
if (response.code === 200 && response.data) {
const formattedData = activityFormatter.formatActivityList(response.data)
this.activityList = [...this.activityList, ...formattedData]
this.pageNum = nextPage
this.hasMore = response.data.length >= this.pageSize
} else {
this.hasMore = false
}
} catch (error) {
console.error('加载更多活动失败:', error)
this.hasMore = false
} finally {
this.loading = false
}
},
// 处理卡片点击
handleCardClick(activity) {
console.log('点击活动卡片:', activity)
// 跳转到活动详情页
uni.navigateTo({
url: `/pages/activity/activityDetail?actId=${activity.id}`
})
},
// 处理报名
async handleRegister(activity) {
console.log('报名活动:', activity)
// 检查用户是否登录
const userInfo = uni.getStorageSync('userInfo')
if (!userInfo) {
uni.showModal({
title: '提示',
content: '请先登录后再报名活动',
confirmText: '去登录',
success: (res) => {
if (res.confirm) {
// 跳转到登录页
uni.navigateTo({
url: '/pages/login/login'
})
}
}
})
return
}
// 确认报名
uni.showModal({
title: '确认报名',
content: `确定要报名参加"${activity.name}"活动吗?`,
success: async (res) => {
if (res.confirm) {
try {
const response = await activityApi.registerActivity({
activityId: activity.id,
userId: userInfo.id,
userName: userInfo.userName || userInfo.nickName,
phone: userInfo.phone
})
if (response.code === 200) {
uni.showToast({
title: '报名成功',
icon: 'success'
})
// 刷新活动列表以更新报名状态
this.refreshData()
} else {
uni.showToast({
title: response.msg || '报名失败',
icon: 'none'
})
}
} catch (error) {
console.error('报名失败:', error)
uni.showToast({
title: '报名失败,请稍后重试',
icon: 'none'
})
}
}
}
})
}
}
}
</script>
<style lang="scss">
page {
background: #FAF8F3;
align-items: center;
justify-content: center;
flex-direction: column;
}
.header {
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 0 34rpx;
padding-bottom: 40rpx;
}
.activity-list {
margin-top: 40rpx;
width: 100%;
align-items: center;
flex-direction: column;
}
</style>