ai-c/pages/happy-school/happy-school.js
2026-02-02 18:21:32 +08:00

395 lines
12 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// pages/happy-school/happy-school.js - 快乐学堂页面
const api = require('../../utils/api')
const app = getApp()
Page({
data: {
statusBarHeight: 44,
navBarHeight: 44,
totalNavHeight: 88,
loading: false,
loadingMore: false,
activeTab: 'featured',
// 活动列表
activityList: [],
// 分页相关
page: 1,
limit: 20,
hasMore: true,
total: 0,
// 二维码弹窗
showQrcodeModal: false,
qrcodeImageUrl: 'https://ai-c.maimanji.com/images/qrcode-happy-school.jpg'
},
onLoad() {
const systemInfo = wx.getSystemInfoSync()
const statusBarHeight = systemInfo.statusBarHeight || 44
const menuButton = wx.getMenuButtonBoundingClientRect()
const navBarHeight = menuButton.height + (menuButton.top - statusBarHeight) * 2
const totalNavHeight = statusBarHeight + navBarHeight
this.setData({
statusBarHeight,
navBarHeight,
totalNavHeight
})
this.loadActivityList()
},
/**
* 返回上一页
*/
onBack() {
wx.navigateBack()
},
/**
* 切换活动标签
*/
onTabChange(e) {
const tab = e.currentTarget.dataset.tab
if (tab === this.data.activeTab) return
this.setData({
activeTab: tab,
activityList: [],
page: 1,
hasMore: true
})
this.loadActivityList()
},
/**
* 下拉刷新
*/
onPullDownRefresh() {
this.loadActivityList(false).finally(() => {
wx.stopPullDownRefresh()
})
},
/**
* 上拉加载更多
*/
onReachBottom() {
if (this.data.hasMore && !this.data.loadingMore && !this.data.loading) {
this.loadActivityList(true)
}
},
/**
* 加载活动列表 - 根据categoryName筛选快乐学堂支持分页
*/
async loadActivityList(isLoadMore = false) {
if (isLoadMore) {
this.setData({ loadingMore: true })
} else {
this.setData({ loading: true, page: 1, hasMore: true, activityList: [] })
}
try {
const { activeTab, page, limit } = this.data
const params = {
category: 'school',
limit: limit,
page: page
}
if (activeTab === 'featured') {
params.tab = 'featured'
} else if (activeTab === 'free') {
params.priceType = 'free'
} else if (activeTab === 'vip') {
params.is_vip = true
} else if (activeTab === 'svip') {
params.is_svip = true
}
const res = await api.activity.getList(params)
if (res.success && res.data && res.data.list) {
const total = res.data.total || 0
const allActivities = res.data.list
const schoolActivities = allActivities.filter(item => item.categoryName === '快乐学堂')
let clubQrcode = ''
const firstWithQrcode = schoolActivities.find(item => item.activityGuideQrcode || item.activity_guide_qrcode)
if (firstWithQrcode && !isLoadMore) {
clubQrcode = firstWithQrcode.activityGuideQrcode || firstWithQrcode.activity_guide_qrcode
}
const newActivityList = schoolActivities.map(item => {
const heat = item.heat || (item.likes * 2 + (item.views || 0) + (item.current_participants || 0) * 3)
return {
id: item.id,
title: item.title,
date: this.formatDate(item.start_date || item.activityDate),
location: item.location || '',
venue: item.venue || '',
image: item.coverImage || item.cover_image || '',
heat: Math.floor(heat),
price: item.price_text || item.priceText || '免费',
priceType: item.is_free || item.priceType === 'free' ? 'free' : 'paid',
likes: item.likes || item.likesCount || 0,
participants: item.current_participants || item.currentParticipants || 0,
isLiked: item.is_liked || item.isLiked || false,
isSignedUp: item.is_registered || item.isSignedUp || false,
status: item.status || (item.currentParticipants >= item.maxParticipants && item.maxParticipants > 0 ? 'full' : 'upcoming'),
activityGuideQrcode: item.activityGuideQrcode || item.activity_guide_qrcode || ''
}
})
const hasMore = newActivityList.length >= limit && (this.data.activityList.length + newActivityList.length) < total
if (isLoadMore) {
this.setData({
activityList: [...this.data.activityList, ...newActivityList],
loadingMore: false,
hasMore,
page: this.data.page + 1,
total
})
} else {
this.setData({
activityList: newActivityList,
hasMore,
total,
qrcodeImageUrl: clubQrcode || this.data.qrcodeImageUrl
})
}
console.log('[happy-school] 加载成功,总数:', total, '当前:', this.data.activityList.length, 'hasMore:', hasMore)
} else {
if (isLoadMore) {
this.setData({ loadingMore: false, hasMore: false })
} else {
this.setData({ activityList: [], hasMore: false })
}
}
} catch (err) {
console.error('加载活动列表失败', err)
if (isLoadMore) {
this.setData({ loadingMore: false })
} else {
this.setData({ activityList: [], loading: false })
}
} finally {
if (!isLoadMore) {
this.setData({ loading: false })
}
}
},
/**
* 格式化日期
*/
formatDate(dateStr) {
if (!dateStr) return ''
const date = new Date(dateStr)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
return `${year}${month}${day}`
},
/**
* 活动卡片点击
*/
onActivityTap(e) {
const id = e.currentTarget.dataset.id
wx.navigateTo({
url: `/pages/activity-detail/activity-detail?id=${id}`
})
},
/**
* 点赞
*/
async onLike(e) {
const id = e.currentTarget.dataset.id
const index = e.currentTarget.dataset.index
if (!app.globalData.isLoggedIn) {
wx.navigateTo({ url: '/pages/login/login' })
return
}
try {
const res = await api.activity.toggleLike(id)
if (res.success) {
this.setData({
[`activityList[${index}].isLiked`]: res.data.isLiked,
[`activityList[${index}].likes`]: res.data.likesCount
})
}
} catch (err) {
console.error('点赞失败', err)
wx.showToast({ title: '操作失败', icon: 'none' })
}
},
/**
* 报名按钮点击
*/
async onSignUp(e) {
const id = e.currentTarget.dataset.id
const index = e.currentTarget.dataset.index
if (!app.globalData.isLoggedIn) {
wx.navigateTo({ url: '/pages/login/login' })
return
}
const activity = this.data.activityList[index]
// 检查活动状态
if (activity.status === 'full' || activity.status === 'ended') {
const qrCode = activity.activityGuideQrcode || activity.activity_guide_qrcode || this.data.qrcodeImageUrl || 'https://ai-c.maimanji.com/api/common/qrcode?type=group'
this.setData({
qrcodeImageUrl: qrCode,
showQrcodeModal: true
})
return
}
try {
if (activity.isSignedUp) {
// 取消报名
const res = await api.activity.cancelSignup(id)
if (res.success) {
wx.showToast({ title: '已取消报名', icon: 'success' })
this.loadActivityList() // 刷新列表获取最新人数
}
} else {
// 报名
const res = await api.activity.signup(id)
if (res.success) {
wx.showToast({ title: '报名成功', icon: 'success' })
this.loadActivityList() // 刷新列表获取最新人数
} else {
// 检查是否需要显示二维码(后端开关关闭或活动已结束)
if (res.code === 'QR_CODE_REQUIRED' || res.error === 'QR_CODE_REQUIRED' || res.code === 'ACTIVITY_ENDED' || res.error === '活动已结束') {
if (activity.activityGuideQrcode || activity.activity_guide_qrcode) {
this.setData({ qrcodeImageUrl: activity.activityGuideQrcode || activity.activity_guide_qrcode })
}
this.setData({ showQrcodeModal: true })
if (res.code === 'ACTIVITY_ENDED' || res.error === '活动已结束') {
wx.showToast({ title: '活动已结束,进群查看更多', icon: 'none' })
}
} else {
wx.showToast({
title: res.error || '报名失败',
icon: 'none'
})
}
}
}
} catch (err) {
console.error('报名操作失败', err)
// 捕获特定错误码以显示二维码
const isQrRequired = err && (err.code === 'QR_CODE_REQUIRED' || (err.data && err.data.code === 'QR_CODE_REQUIRED'))
const isActivityEnded = err && (err.code === 'ACTIVITY_ENDED' || (err.data && err.data.code === 'ACTIVITY_ENDED') || err.error === '活动已结束')
if (isQrRequired || isActivityEnded) {
if (activity.activityGuideQrcode || activity.activity_guide_qrcode) {
this.setData({ qrcodeImageUrl: activity.activityGuideQrcode || activity.activity_guide_qrcode })
}
this.setData({ showQrcodeModal: true })
if (isActivityEnded) {
wx.showToast({ title: '活动已结束,进群查看更多', icon: 'none' })
}
} else {
wx.showToast({
title: err.error || err.message || '操作失败',
icon: 'none'
})
}
}
},
/**
* 加入群组
*/
onJoinGroup() {
// 如果没有二维码,尝试获取第一个活动的二维码
if (!this.data.qrcodeImageUrl && this.data.activityList.length > 0) {
const firstWithQrcode = this.data.activityList.find(item => item.activityGuideQrcode || item.activity_guide_qrcode)
if (firstWithQrcode) {
this.setData({ qrcodeImageUrl: firstWithQrcode.activityGuideQrcode || firstWithQrcode.activity_guide_qrcode })
}
}
this.setData({ showQrcodeModal: true })
},
/**
* 阻止冒泡
*/
preventBubble() {
return
},
/**
* 关闭二维码弹窗
*/
onCloseQrcodeModal() {
this.setData({ showQrcodeModal: false })
},
/**
* 保存二维码
*/
async onSaveQrcode() {
try {
const { qrcodeImageUrl } = this.data
// 下载图片到本地
const downloadRes = await new Promise((resolve, reject) => {
wx.downloadFile({
url: qrcodeImageUrl,
success: resolve,
fail: reject
})
})
if (downloadRes.statusCode !== 200) {
throw new Error('下载失败')
}
// 保存到相册
await new Promise((resolve, reject) => {
wx.saveImageToPhotosAlbum({
filePath: downloadRes.tempFilePath,
success: resolve,
fail: reject
})
})
wx.showToast({ title: '保存成功', icon: 'success' })
this.onCloseQrcodeModal()
} catch (err) {
console.error('保存二维码失败', err)
if (err.errMsg && err.errMsg.includes('auth deny')) {
wx.showModal({
title: '需要授权',
content: '请允许访问相册以保存二维码',
confirmText: '去设置',
success: (res) => {
if (res.confirm) {
wx.openSetting()
}
}
})
} else {
wx.showToast({ title: '保存失败', icon: 'none' })
}
}
}
})