| | |
| | | |
| | | Page({ |
| | | data: { |
| | | // 活动ID |
| | | activityId: null, |
| | | // 活动详情 |
| | | activity: null, |
| | | // 加载状态 |
| | | myApplication: null, |
| | | buttonDisabled: false, |
| | | buttonText: '我要报名', |
| | | loading: true, |
| | | // 用户报名状态 |
| | | registrationStatus: null, |
| | | // 是否已报名 |
| | | isRegistered: false, |
| | | // 媒体文件列表 |
| | | mediaFiles: [], |
| | | // 当前媒体索引 |
| | | currentMediaIndex: 0, |
| | | // 是否显示媒体预览 |
| | | showMediaPreview: false, |
| | | // 报名人数(实时更新) |
| | | currentParticipants: 0, |
| | | // 是否可以报名 |
| | | canRegisterStatus: false, |
| | | // 报名按钮文本 |
| | | registerButtonText: '立即报名', |
| | | // 报名按钮是否禁用 |
| | | registerButtonDisabled: false |
| | | error: null |
| | | }, |
| | | |
| | | onLoad(options) { |
| | | console.log('活动详情页加载', options) |
| | | |
| | | if (options.id) { |
| | | this.setData({ activityId: options.id }) |
| | | this.loadActivityDetail() |
| | | this.checkRegistrationStatus() |
| | | this.setData({ activityId: options.id }); |
| | | this.loadActivityDetail(options.id); |
| | | } else { |
| | | utils.showError('参数错误') |
| | | utils.navigateBack() |
| | | this.setData({ loading: false, error: '无效的比赛ID' }); |
| | | } |
| | | }, |
| | | |
| | | onShow() { |
| | | console.log('活动详情页显示') |
| | | // 刷新报名人数 |
| | | onPullDownRefresh() { |
| | | if (this.data.activityId) { |
| | | this.refreshParticipantCount() |
| | | this.loadActivityDetail(this.data.activityId).finally(() => { |
| | | wx.stopPullDownRefresh(); |
| | | }); |
| | | } else { |
| | | wx.stopPullDownRefresh(); |
| | | } |
| | | }, |
| | | |
| | | onShareAppMessage() { |
| | | const activity = this.data.activity |
| | | return { |
| | | title: activity ? activity.name : '精彩赛事', |
| | | path: `/pages/activity/detail?id=${this.data.activityId}`, |
| | | imageUrl: activity && activity.coverImage ? activity.coverImage.fullUrl : '' |
| | | } |
| | | }, |
| | | |
| | | // 加载赛事详情 |
| | | loadActivityDetail() { |
| | | this.setData({ loading: true }) |
| | | |
| | | app.graphqlRequest(` |
| | | query getActivityDetail($id: ID!) { |
| | | loadActivityDetail(id) { |
| | | this.setData({ loading: true, error: null }); |
| | | const query = ` |
| | | query GetActivityDetailAndStatus($id: ID!) { |
| | | activity(id: $id) { |
| | | id |
| | | name |
| | |
| | | signupDeadline |
| | | matchTime |
| | | address |
| | | playerMax |
| | | state |
| | | createTime |
| | | updateTime |
| | | playerCount |
| | | stateName |
| | | coverImage { |
| | | id |
| | | name |
| | | path |
| | | fullUrl |
| | | fullThumbUrl |
| | | mediaType |
| | | } |
| | | images { |
| | | id |
| | | name |
| | | path |
| | | fullUrl |
| | | fullThumbUrl |
| | | mediaType |
| | | } |
| | | videos { |
| | | id |
| | | name |
| | | path |
| | | fullUrl |
| | | fullThumbUrl |
| | | mediaType |
| | | } |
| | | } |
| | | } |
| | | `, { |
| | | id: this.data.activityId |
| | | }).then(data => { |
| | | if (data.activity) { |
| | | const activity = data.activity |
| | | |
| | | // 处理媒体文件 |
| | | const mediaFiles = [] |
| | | |
| | | // 添加封面图 |
| | | if (activity.coverImage) { |
| | | mediaFiles.push({ |
| | | type: 'image', |
| | | url: activity.coverImage.fullUrl, |
| | | title: '封面图片' |
| | | }) |
| | | } |
| | | |
| | | // 添加其他图片 |
| | | if (activity.images && activity.images.length > 0) { |
| | | activity.images.forEach((image, index) => { |
| | | mediaFiles.push({ |
| | | type: 'image', |
| | | url: image.fullUrl, |
| | | title: `图片 ${index + 1}` |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | // 添加视频 |
| | | if (activity.videos && activity.videos.length > 0) { |
| | | activity.videos.forEach((video, index) => { |
| | | mediaFiles.push({ |
| | | type: 'video', |
| | | url: video.fullUrl, |
| | | title: `视频 ${index + 1}` |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | // 预处理时间字段 |
| | | if (activity.signupDeadline) { |
| | | activity.formattedSignupDeadline = this.formatDate(activity.signupDeadline) |
| | | } |
| | | if (activity.matchTime) { |
| | | activity.formattedMatchTime = this.formatDate(activity.matchTime) |
| | | } |
| | | |
| | | this.setData({ |
| | | activity: activity, |
| | | mediaFiles: mediaFiles, |
| | | currentParticipants: activity.playerCount, |
| | | loading: false |
| | | }, () => { |
| | | // 在数据设置完成后,检查报名状态 |
| | | this.checkRegistrationStatus() |
| | | this.updateCanRegisterStatus() |
| | | }) |
| | | } else { |
| | | utils.showError('赛事不存在') |
| | | utils.navigateBack() |
| | | } |
| | | }).catch(err => { |
| | | console.error('加载赛事详情失败:', err) |
| | | utils.showError('加载失败,请重试') |
| | | this.setData({ loading: false }) |
| | | }) |
| | | }, |
| | | |
| | | // 检查报名状态 |
| | | checkRegistrationStatus() { |
| | | if (!app.globalData.token) { |
| | | return |
| | | } |
| | | |
| | | app.graphqlRequest(` |
| | | query checkRegistrationStatus($activityId: ID!) { |
| | | playerRegistration(activityId: $activityId) { |
| | | id |
| | | status |
| | | registrationTime |
| | | reviewStatus |
| | | reviewComment |
| | | } |
| | | } |
| | | `, { |
| | | activityId: this.data.activityId |
| | | }).then(data => { |
| | | if (data.playerRegistration) { |
| | | this.setData({ |
| | | registrationStatus: data.playerRegistration, |
| | | isRegistered: true |
| | | }, () => { |
| | | this.updateCanRegisterStatus() |
| | | }) |
| | | } else { |
| | | this.setData({ |
| | | isRegistered: false |
| | | }, () => { |
| | | this.updateCanRegisterStatus() |
| | | }) |
| | | } |
| | | }).catch(err => { |
| | | console.error('检查报名状态失败:', err) |
| | | }) |
| | | }, |
| | | |
| | | // 刷新报名人数 |
| | | refreshParticipantCount() { |
| | | app.graphqlRequest(` |
| | | query getParticipantCount($id: ID!) { |
| | | activity(id: $id) { |
| | | playerCount |
| | | } |
| | | } |
| | | `, { |
| | | id: this.data.activityId |
| | | }).then(data => { |
| | | if (data.activity) { |
| | | this.setData({ |
| | | currentParticipants: data.activity.playerCount |
| | | }, () => { |
| | | this.updateCanRegisterStatus() |
| | | }) |
| | | } |
| | | }).catch(err => { |
| | | console.error('刷新报名人数失败:', err) |
| | | }) |
| | | }, |
| | | |
| | | // 媒体文件点击 |
| | | onMediaTap(e) { |
| | | const index = e.currentTarget.dataset.index |
| | | const media = this.data.mediaFiles[index] |
| | | |
| | | if (media.type === 'image') { |
| | | // 预览图片 |
| | | const imageUrls = this.data.mediaFiles |
| | | .filter(item => item.type === 'image') |
| | | .map(item => item.url) |
| | | |
| | | wx.previewImage({ |
| | | current: media.url, |
| | | urls: imageUrls |
| | | }) |
| | | } else if (media.type === 'video') { |
| | | // 播放视频 |
| | | this.setData({ |
| | | currentMediaIndex: index, |
| | | showMediaPreview: true |
| | | }) |
| | | } |
| | | }, |
| | | |
| | | // 关闭媒体预览 |
| | | closeMediaPreview() { |
| | | this.setData({ |
| | | showMediaPreview: false |
| | | }) |
| | | }, |
| | | |
| | | // 报名按钮点击 |
| | | onRegisterTap() { |
| | | // 如果按钮被禁用,不执行任何操作 |
| | | if (this.data.registerButtonDisabled) { |
| | | return |
| | | } |
| | | |
| | | // 如果已报名,查看报名状态 |
| | | if (this.data.isRegistered) { |
| | | this.onViewRegistrationStatus() |
| | | return |
| | | } |
| | | |
| | | // 检查登录状态 |
| | | if (!app.globalData.token) { |
| | | utils.showToast('请先登录') |
| | | app.login() |
| | | return |
| | | } |
| | | |
| | | const activity = this.data.activity |
| | | |
| | | // 检查报名时间 |
| | | const now = new Date() |
| | | const regEnd = new Date(activity.signupDeadline) |
| | | |
| | | if (now > regEnd) { |
| | | utils.showToast('报名已结束') |
| | | return |
| | | } |
| | | |
| | | // 检查报名人数 |
| | | if (activity.playerMax && this.data.currentParticipants >= activity.playerMax) { |
| | | utils.showToast('报名人数已满') |
| | | return |
| | | } |
| | | |
| | | // 跳转到报名页面 |
| | | utils.navigateTo('/pages/registration/registration', { |
| | | activityId: this.data.activityId |
| | | }) |
| | | }, |
| | | |
| | | // 查看报名状态 |
| | | onViewRegistrationStatus() { |
| | | const status = this.data.registrationStatus |
| | | let statusText = '' |
| | | |
| | | switch (status.status) { |
| | | case 'PENDING': |
| | | statusText = '待审核' |
| | | break |
| | | case 'APPROVED': |
| | | statusText = '已通过' |
| | | break |
| | | case 'REJECTED': |
| | | statusText = '已拒绝' |
| | | break |
| | | case 'CANCELLED': |
| | | statusText = '已取消' |
| | | break |
| | | default: |
| | | statusText = status.status |
| | | } |
| | | |
| | | let content = `报名状态:${statusText}\n报名时间:${utils.formatDate(status.registrationTime)}` |
| | | |
| | | if (status.reviewComment) { |
| | | content += `\n审核意见:${status.reviewComment}` |
| | | } |
| | | |
| | | wx.showModal({ |
| | | title: '报名状态', |
| | | content: content, |
| | | showCancel: false |
| | | }) |
| | | }, |
| | | |
| | | // 联系主办方 |
| | | onContactTap() { |
| | | const activity = this.data.activity |
| | | |
| | | if (activity.contactPhone) { |
| | | wx.showActionSheet({ |
| | | itemList: ['拨打电话', '复制号码'], |
| | | success: (res) => { |
| | | if (res.tapIndex === 0) { |
| | | wx.makePhoneCall({ |
| | | phoneNumber: activity.contactPhone |
| | | }) |
| | | } else if (res.tapIndex === 1) { |
| | | wx.setClipboardData({ |
| | | data: activity.contactPhone, |
| | | success: () => { |
| | | utils.showSuccess('号码已复制') |
| | | } |
| | | }) |
| | | playerMax |
| | | coverImage { fullUrl } |
| | | images { fullUrl } |
| | | videos { fullUrl, fullThumbUrl } |
| | | stages { |
| | | id |
| | | name |
| | | matchTime |
| | | description |
| | | } |
| | | } |
| | | myActivityPlayer(activityId: $id) { |
| | | id |
| | | state |
| | | } |
| | | } |
| | | `; |
| | | |
| | | return app.graphqlRequest(query, { id: id }) |
| | | .then(res => { |
| | | if (res.activity) { |
| | | let buttonDisabled = false; |
| | | let buttonText = '我要报名'; |
| | | const myApplication = res.myActivityPlayer; |
| | | |
| | | if (myApplication) { |
| | | if (myApplication.state === 0) { |
| | | buttonDisabled = true; |
| | | buttonText = '等待审核'; |
| | | } else if (myApplication.state === 1) { |
| | | buttonDisabled = true; |
| | | buttonText = '已报名'; |
| | | } |
| | | } |
| | | |
| | | if (!buttonDisabled) { |
| | | if (new Date() > new Date(res.activity.signupDeadline)) { |
| | | buttonDisabled = true; |
| | | buttonText = '报名已截止'; |
| | | } |
| | | } |
| | | |
| | | this.setData({ |
| | | activity: res.activity, |
| | | myApplication: myApplication, |
| | | loading: false, |
| | | buttonDisabled: buttonDisabled, |
| | | buttonText: buttonText |
| | | }); |
| | | } else { |
| | | throw new Error('未找到比赛信息'); |
| | | } |
| | | }) |
| | | } else { |
| | | utils.showToast('暂无联系方式') |
| | | } |
| | | .catch(err => { |
| | | this.setData({ |
| | | loading: false, |
| | | error: '加载失败,请稍后重试' |
| | | }); |
| | | console.error('加载比赛详情或报名状态失败:', err); |
| | | }); |
| | | }, |
| | | |
| | | // 分享赛事 |
| | | onShareTap() { |
| | | wx.showShareMenu({ |
| | | withShareTicket: true, |
| | | menus: ['shareAppMessage', 'shareTimeline'] |
| | | }) |
| | | handleRegister() { |
| | | if (!this.data.activityId) { |
| | | wx.showToast({ |
| | | title: '无效的活动ID', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | wx.navigateTo({ |
| | | url: `/pages/registration/registration?id=${this.data.activityId}` |
| | | }); |
| | | }, |
| | | |
| | | // 格式化日期 |
| | | formatDate(date) { |
| | | return utils.formatDate(date, 'YYYY-MM-DD HH:mm') |
| | | // 格式化日期和时间 |
| | | formatDateTime(dateStr) { |
| | | return utils.formatDate(dateStr, 'YYYY-MM-DD HH:mm'); |
| | | }, |
| | | |
| | | // 获取状态文本 |
| | | getStatusText(state) { |
| | | const statusMap = { |
| | | 0: '草稿', |
| | | 1: '已发布', |
| | | 2: '报名结束', |
| | | 3: '进行中', |
| | | 4: '已结束', |
| | | 5: '已取消' |
| | | |
| | | // 格式化日期范围 |
| | | formatDateRange(start, end) { |
| | | if (!start && !end) return '待定'; |
| | | const startDate = start ? utils.formatDate(start, 'YYYY-MM-DD') : ''; |
| | | const endDate = end ? utils.formatDate(end, 'YYYY-MM-DD') : ''; |
| | | if (startDate && endDate && startDate !== endDate) { |
| | | return `${startDate} - ${endDate}`; |
| | | } |
| | | return statusMap[state] || '未知状态' |
| | | }, |
| | | |
| | | // 获取状态样式类 |
| | | getStatusClass(state) { |
| | | const classMap = { |
| | | 0: 'text-muted', |
| | | 1: 'text-success', |
| | | 2: 'text-warning', |
| | | 3: 'text-primary', |
| | | 4: 'text-muted', |
| | | 5: 'text-danger' |
| | | } |
| | | return classMap[state] || 'text-muted' |
| | | }, |
| | | |
| | | // 获取报名进度百分比 |
| | | getRegistrationProgress() { |
| | | const activity = this.data.activity |
| | | if (!activity || !activity.playerMax || activity.playerMax <= 0) { |
| | | return 0 |
| | | } |
| | | return Math.min((this.data.currentParticipants / activity.playerMax) * 100, 100) |
| | | }, |
| | | |
| | | // 判断是否可以报名 |
| | | canRegister() { |
| | | const activity = this.data.activity |
| | | if (!activity) return false |
| | | |
| | | const now = new Date() |
| | | const regEnd = new Date(activity.signupDeadline) |
| | | |
| | | return now <= regEnd && |
| | | activity.state === 1 && |
| | | (!activity.playerMax || this.data.currentParticipants < activity.playerMax) && |
| | | !this.data.isRegistered |
| | | }, |
| | | |
| | | // 获取报名按钮状态和文本 |
| | | getRegisterButtonStatus() { |
| | | const activity = this.data.activity |
| | | if (!activity) { |
| | | return { canRegister: false, buttonText: '暂不可报名', disabled: true } |
| | | } |
| | | |
| | | // 如果已报名 |
| | | if (this.data.isRegistered) { |
| | | return { canRegister: false, buttonText: '查看报名状态', disabled: false } |
| | | } |
| | | |
| | | const now = new Date() |
| | | const regEnd = new Date(activity.signupDeadline) |
| | | |
| | | // 检查报名截止时间 |
| | | if (now > regEnd) { |
| | | return { canRegister: false, buttonText: '报名已结束', disabled: true } |
| | | } |
| | | |
| | | // 检查报名人数是否已满 |
| | | if (activity.playerMax && this.data.currentParticipants >= activity.playerMax) { |
| | | return { canRegister: false, buttonText: '人数已满', disabled: true } |
| | | } |
| | | |
| | | // 检查活动状态 |
| | | if (activity.state !== 1) { |
| | | return { canRegister: false, buttonText: '暂不可报名', disabled: true } |
| | | } |
| | | |
| | | // 可以报名 |
| | | return { canRegister: true, buttonText: '立即报名', disabled: false } |
| | | }, |
| | | |
| | | // 更新报名状态 |
| | | updateCanRegisterStatus() { |
| | | const buttonStatus = this.getRegisterButtonStatus() |
| | | this.setData({ |
| | | canRegisterStatus: buttonStatus.canRegister, |
| | | registerButtonText: buttonStatus.buttonText, |
| | | registerButtonDisabled: buttonStatus.disabled |
| | | }) |
| | | return startDate || endDate; |
| | | } |
| | | }) |
| | | }); |