895 lines
25 KiB
JavaScript
895 lines
25 KiB
JavaScript
// pages/entertainment/entertainment.js - 休闲文娱页面
|
||
// 根据Figma设计实现
|
||
|
||
const api = require('../../utils/api')
|
||
const app = getApp()
|
||
|
||
Page({
|
||
data: {
|
||
statusBarHeight: 44,
|
||
navBarHeight: 44,
|
||
totalNavHeight: 88,
|
||
loading: false,
|
||
loadingMore: false,
|
||
|
||
// 顶部轮播数据 - 从后台素材管理API加载
|
||
bannerList: [],
|
||
swiperHeight: 400,
|
||
currentBannerIndex: 0,
|
||
|
||
// 功能入口 - 使用正式环境图片URL
|
||
categoryList: [
|
||
{
|
||
id: 1,
|
||
name: '兴趣搭子',
|
||
icon: '/images/icon-interest.png'
|
||
},
|
||
{
|
||
id: 2,
|
||
name: '同城活动',
|
||
icon: '/images/icon-city.png'
|
||
},
|
||
{
|
||
id: 3,
|
||
name: '户外郊游',
|
||
icon: '/images/icon-outdoor.png'
|
||
},
|
||
{
|
||
id: 4,
|
||
name: '高端定制',
|
||
icon: '/images/icon-travel.png'
|
||
},
|
||
{
|
||
id: 5,
|
||
name: '快乐学堂',
|
||
icon: '/images/icon-checkin.png'
|
||
},
|
||
{
|
||
id: 6,
|
||
name: '单身聚会',
|
||
icon: '/images/icon-love.png'
|
||
}
|
||
],
|
||
|
||
// 滚动公告
|
||
noticeList: [],
|
||
currentNoticeIndex: 0,
|
||
|
||
// 活动标签
|
||
activeTab: 'featured', // featured: 精选活动, free: 免费活动, vip: VIP活动, svip: SVIP活动
|
||
|
||
// 活动列表
|
||
activityList: [],
|
||
|
||
// 分页相关
|
||
page: 1,
|
||
limit: 20,
|
||
hasMore: true,
|
||
total: 0,
|
||
|
||
// 二维码引导弹窗
|
||
showQrcodeModal: false,
|
||
qrcodeImageUrl: '',
|
||
|
||
// 未读消息数
|
||
totalUnread: 0,
|
||
|
||
// 审核状态
|
||
auditStatus: 0
|
||
},
|
||
|
||
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.loadPageData()
|
||
this.loadNotices()
|
||
this.startNoticeScroll()
|
||
},
|
||
|
||
/**
|
||
* 加载页面数据
|
||
*/
|
||
async loadPageData() {
|
||
// 并行加载Banner、功能入口和活动列表
|
||
await Promise.all([
|
||
this.loadBanners(),
|
||
this.loadEntries(),
|
||
this.loadActivityList()
|
||
])
|
||
},
|
||
|
||
/**
|
||
* 处理图片URL,如果是相对路径则拼接域名,并设置清晰度为85
|
||
*/
|
||
processImageUrl(url) {
|
||
if (!url) return ''
|
||
let fullUrl = url
|
||
if (!url.startsWith('http://') && !url.startsWith('https://')) {
|
||
const baseUrl = 'https://ai-c.maimanji.com'
|
||
fullUrl = baseUrl + (url.startsWith('/') ? '' : '/') + url
|
||
}
|
||
|
||
// 添加清晰度参数 q=85
|
||
if (fullUrl.includes('?')) {
|
||
if (!fullUrl.includes('q=')) {
|
||
fullUrl += '&q=85'
|
||
}
|
||
} else {
|
||
fullUrl += '?q=85'
|
||
}
|
||
return fullUrl
|
||
},
|
||
|
||
/**
|
||
* 轮播图图片加载完成,自适应高度
|
||
*/
|
||
onBannerLoad(e) {
|
||
if (this.data.swiperHeight !== 300) return; // 只计算一次
|
||
const { width, height } = e.detail;
|
||
const sysInfo = wx.getSystemInfoSync();
|
||
// 减去左右padding (32rpx * 2)
|
||
const swiperWidth = sysInfo.windowWidth - (32 * 2 / 750 * sysInfo.windowWidth);
|
||
const ratio = width / height;
|
||
const swiperHeight = swiperWidth / ratio;
|
||
const swiperHeightRpx = swiperHeight * (750 / sysInfo.windowWidth);
|
||
|
||
this.setData({
|
||
swiperHeight: swiperHeightRpx
|
||
});
|
||
},
|
||
|
||
/**
|
||
* 加载功能入口图标
|
||
* 从后台素材管理API加载 (group=entries)
|
||
*/
|
||
async loadEntries() {
|
||
try {
|
||
const res = await api.pageAssets.getAssets('entries')
|
||
console.log('功能入口 API响应:', res)
|
||
|
||
if (res.success && res.data) {
|
||
const icons = res.data
|
||
const { categoryList } = this.data
|
||
|
||
// 映射图标:搭子(id=1), 同城(id=2), 户外(id=3), 定制(id=4), 学堂(id=5), 传递(id=6)
|
||
const idMap = {
|
||
1: 'entry_1', // 兴趣搭子
|
||
2: 'entry_2', // 同城活动
|
||
3: 'entry_3', // 户外郊游
|
||
4: 'entry_4', // 定制主题
|
||
5: 'entry_5', // 快乐学堂
|
||
6: 'entry_6' // 爱心传递
|
||
}
|
||
|
||
const updatedCategoryList = categoryList.map(item => {
|
||
const assetKey = idMap[item.id]
|
||
const iconUrl = icons[assetKey]
|
||
if (iconUrl) {
|
||
return {
|
||
...item,
|
||
icon: this.processImageUrl(iconUrl)
|
||
}
|
||
}
|
||
return item
|
||
})
|
||
|
||
this.setData({ categoryList: updatedCategoryList })
|
||
console.log('已更新娱乐页功能入口图标')
|
||
}
|
||
} catch (err) {
|
||
console.error('加载功能入口失败', err)
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 加载娱乐页Banner
|
||
* 调用专用API:/api/page-assets/entertainment-banners
|
||
*/
|
||
async loadBanners() {
|
||
try {
|
||
const res = await api.pageAssets.getEntertainmentBanners()
|
||
|
||
console.log('娱乐页Banner API响应:', res)
|
||
|
||
if (res.success && res.data) {
|
||
// 处理相对路径,拼接完整URL
|
||
// 兼容不同可能的字段名:asset_url, url, imageUrl
|
||
const bannerList = res.data.map(item => {
|
||
const rawUrl = item.asset_url || item.url || item.imageUrl || item.image_url || ''
|
||
return {
|
||
id: item.id,
|
||
imageUrl: this.processImageUrl(rawUrl),
|
||
// 只保留标签,不显示标题和副标题
|
||
tag: item.description || item.tag || '热门推荐',
|
||
title: '',
|
||
subtitle: '',
|
||
bgColor: item.bg_color || item.bgColor || 'linear-gradient(135deg, #E8D5F0 0%, #F5E6D3 100%)'
|
||
}
|
||
}).filter(item => item.imageUrl) // 只保留有图片的
|
||
|
||
if (bannerList.length > 0) {
|
||
this.setData({ bannerList })
|
||
console.log(`加载了 ${bannerList.length} 个娱乐页Banner`)
|
||
} else {
|
||
console.log('娱乐页Banner数据为空或解析失败,使用默认配置')
|
||
this.setDefaultBanners()
|
||
}
|
||
} else {
|
||
console.log('娱乐页Banner API返回失败,使用默认配置')
|
||
this.setDefaultBanners()
|
||
}
|
||
} catch (err) {
|
||
console.error('加载娱乐页Banner失败', err)
|
||
this.setDefaultBanners()
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 设置默认Banner(降级方案 - 使用CDN URL)
|
||
*/
|
||
setDefaultBanners() {
|
||
const cdnBase = 'https://ai-c.maimanji.com/images'
|
||
this.setData({
|
||
bannerList: [
|
||
{
|
||
id: 1,
|
||
imageUrl: `${cdnBase}/service-banner-1.png`,
|
||
tag: '热门',
|
||
title: '',
|
||
subtitle: '',
|
||
bgColor: 'linear-gradient(135deg, #E8D5F0 0%, #F5E6D3 100%)'
|
||
},
|
||
{
|
||
id: 2,
|
||
imageUrl: `${cdnBase}/service-banner-2.png`,
|
||
tag: '活动',
|
||
title: '',
|
||
subtitle: '',
|
||
bgColor: 'linear-gradient(135deg, #D5E8F0 0%, #E6F5D3 100%)'
|
||
},
|
||
{
|
||
id: 3,
|
||
imageUrl: `${cdnBase}/service-banner-3.png`,
|
||
tag: '推荐',
|
||
title: '',
|
||
subtitle: '',
|
||
bgColor: 'linear-gradient(135deg, #F0E8D5 0%, #F5D3E6 100%)'
|
||
}
|
||
]
|
||
})
|
||
console.log('使用默认娱乐页Banner配置')
|
||
},
|
||
|
||
/**
|
||
* 加载公告
|
||
*/
|
||
async loadNotices() {
|
||
try {
|
||
const res = await api.common.getNotices()
|
||
console.log('[notice] 公告API响应:', res)
|
||
|
||
if (res.success && res.data && res.data.length > 0) {
|
||
const noticeList = res.data.map(item => ({
|
||
id: item.id,
|
||
content: item.content,
|
||
linkType: item.linkType || 'none',
|
||
linkValue: item.linkValue || ''
|
||
}))
|
||
this.setData({ noticeList })
|
||
}
|
||
} catch (err) {
|
||
console.error('[notice] 加载公告失败', err)
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 点击公告栏
|
||
*/
|
||
onNoticeTap() {
|
||
wx.navigateTo({
|
||
url: '/pages/notices/notices'
|
||
})
|
||
},
|
||
|
||
onShow() {
|
||
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
|
||
this.getTabBar().setData({ selected: 1 })
|
||
}
|
||
wx.hideTabBar({ animation: false })
|
||
const app = getApp()
|
||
this.setData({
|
||
auditStatus: app.globalData.auditStatus
|
||
})
|
||
this.loadUnreadCount()
|
||
},
|
||
|
||
onUnload() {
|
||
if (this.noticeTimer) {
|
||
clearInterval(this.noticeTimer)
|
||
}
|
||
},
|
||
|
||
|
||
/**
|
||
* 开始公告滚动
|
||
*/
|
||
startNoticeScroll() {
|
||
this.noticeTimer = setInterval(() => {
|
||
const { noticeList, currentNoticeIndex } = this.data
|
||
const nextIndex = (currentNoticeIndex + 1) % noticeList.length
|
||
this.setData({ currentNoticeIndex: nextIndex })
|
||
}, 3000)
|
||
},
|
||
|
||
/**
|
||
* 加载活动列表 - 根据activeTab加载不同的活动(支持分页)
|
||
*/
|
||
async loadActivityList(isLoadMore = false) {
|
||
console.log('========== 加载活动列表 ==========')
|
||
console.log('[6] activeTab:', this.data.activeTab)
|
||
console.log('[6.1] isLoadMore:', isLoadMore)
|
||
|
||
if (isLoadMore) {
|
||
this.setData({ loadingMore: true })
|
||
} else {
|
||
this.setData({ loading: true, page: 1, hasMore: true })
|
||
}
|
||
|
||
try {
|
||
const config = require('../../config/index')
|
||
const { activeTab, page, limit } = this.data
|
||
|
||
console.log('[8] 请求URL:', `${config.API_BASE_URL}/entertainment/home`)
|
||
console.log('[9] 请求参数:', { type: activeTab, page, limit })
|
||
|
||
const res = await new Promise((resolve, reject) => {
|
||
wx.request({
|
||
url: `${config.API_BASE_URL}/entertainment/home`,
|
||
method: 'GET',
|
||
data: {
|
||
type: activeTab,
|
||
page,
|
||
limit
|
||
},
|
||
timeout: 10000,
|
||
success: (res) => resolve(res),
|
||
fail: (err) => reject(err)
|
||
})
|
||
})
|
||
|
||
console.log('[10] API响应状态:', res.statusCode)
|
||
console.log('[11] API响应数据:', JSON.stringify(res.data, null, 2))
|
||
|
||
if (res.statusCode === 200 && res.data.success && res.data.data) {
|
||
const homeData = res.data.data
|
||
const total = res.data.data.total || 0
|
||
|
||
let activities = []
|
||
if (activeTab === 'featured') {
|
||
activities = homeData.featuredActivities || []
|
||
console.log('[12] 精选活动原始数量:', activities.length)
|
||
} else if (activeTab === 'free') {
|
||
activities = homeData.freeActivities || []
|
||
console.log('[12] 免费活动原始数量:', activities.length)
|
||
} else if (activeTab === 'vip') {
|
||
activities = homeData.vipActivities || []
|
||
console.log('[12] VIP活动原始数量:', activities.length)
|
||
} else if (activeTab === 'svip') {
|
||
activities = homeData.svipActivities || []
|
||
console.log('[12] SVIP活动原始数量:', activities.length)
|
||
}
|
||
|
||
const newActivityList = activities.map(item => {
|
||
const heat = item.heat !== undefined && item.heat !== null
|
||
? item.heat
|
||
: (item.likesCount || 0) * 2 + (item.viewsCount || 0) + ((item.virtualParticipants || 0) + (item.currentParticipants || 0)) * 3
|
||
|
||
return {
|
||
id: item.id,
|
||
title: item.title,
|
||
date: this.formatDate(item.activityDate),
|
||
location: item.location || '',
|
||
venue: item.venue || '',
|
||
image: item.coverImage || '/images/activity-default.jpg',
|
||
bgColor: this.getRandomGradient(),
|
||
price: item.priceText || '免费',
|
||
priceType: item.priceType || 'free',
|
||
likes: item.likesCount || 0,
|
||
participants: item.currentParticipants || 0,
|
||
maxParticipants: item.maxParticipants || 0,
|
||
isLiked: item.isLiked || false,
|
||
isSignedUp: item.isSignedUp || false,
|
||
signupEnabled: item.signupEnabled !== undefined ? item.signupEnabled : true,
|
||
activityGuideQrcode: item.activityGuideQrcode || '',
|
||
categoryName: item.categoryName || '',
|
||
heat: Math.floor(heat),
|
||
participantAvatars: item.participantAvatars || [
|
||
'https://i.pravatar.cc/100?u=1',
|
||
'https://i.pravatar.cc/100?u=2',
|
||
'https://i.pravatar.cc/100?u=3'
|
||
]
|
||
}
|
||
})
|
||
|
||
console.log('[13] 转换后活动数量:', newActivityList.length)
|
||
|
||
const hasMore = activities.length >= limit && (this.data.activityList.length + activities.length) < total
|
||
console.log('[14] hasMore:', hasMore, 'current:', this.data.activityList.length + activities.length, 'total:', 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
|
||
})
|
||
}
|
||
console.log('[15] setData完成,当前页面活动数量:', this.data.activityList.length)
|
||
} else {
|
||
console.log('[ERROR] API返回失败')
|
||
if (isLoadMore) {
|
||
this.setData({ loadingMore: false })
|
||
} else {
|
||
this.setData({ activityList: [], hasMore: false })
|
||
}
|
||
}
|
||
} catch (err) {
|
||
console.error('[ERROR] 加载活动列表失败:', err)
|
||
if (isLoadMore) {
|
||
this.setData({ loadingMore: false })
|
||
} else {
|
||
this.setData({ activityList: [], loading: false, hasMore: false })
|
||
}
|
||
} finally {
|
||
if (!isLoadMore) {
|
||
this.setData({ loading: false })
|
||
}
|
||
console.log('========== 加载完成 ==========')
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 加载模拟数据(降级方案)
|
||
*/
|
||
loadMockActivities() {
|
||
// 使用空数据,等待后端API返回真实数据
|
||
const mockActivities = []
|
||
|
||
this.setData({ activityList: mockActivities })
|
||
},
|
||
|
||
/**
|
||
* 格式化日期
|
||
*/
|
||
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}日`
|
||
},
|
||
|
||
/**
|
||
* 获取随机渐变色
|
||
*/
|
||
getRandomGradient() {
|
||
const gradients = [
|
||
'linear-gradient(135deg, #E8D5F0 0%, #F5E6D3 100%)',
|
||
'linear-gradient(135deg, #D5F0E8 0%, #E6D3F5 100%)',
|
||
'linear-gradient(135deg, #F0D5E8 0%, #D3F5E6 100%)',
|
||
'linear-gradient(135deg, #F5E6D3 0%, #E8D5F0 100%)'
|
||
]
|
||
return gradients[Math.floor(Math.random() * gradients.length)]
|
||
},
|
||
|
||
/**
|
||
* 加载未读消息数
|
||
*/
|
||
async loadUnreadCount() {
|
||
if (!app.globalData.isLoggedIn) {
|
||
this.setData({ totalUnread: 0 })
|
||
return
|
||
}
|
||
|
||
try {
|
||
const res = await api.chat.getConversations()
|
||
if (res.success && res.data) {
|
||
const totalUnread = res.data.reduce((sum, conv) => sum + (conv.unread_count || 0), 0)
|
||
this.setData({ totalUnread })
|
||
}
|
||
} catch (err) {
|
||
console.log('获取未读消息数失败', err)
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 轮播图切换
|
||
*/
|
||
onBannerChange(e) {
|
||
// 只在用户手动滑动或自动播放时更新索引
|
||
if (e.detail.source === 'autoplay' || e.detail.source === 'touch') {
|
||
this.setData({ currentBannerIndex: e.detail.current })
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 轮播指示器点击
|
||
*/
|
||
onDotTap(e) {
|
||
const index = e.currentTarget.dataset.index
|
||
// 避免重复设置相同索引
|
||
if (index !== this.data.currentBannerIndex) {
|
||
this.setData({ currentBannerIndex: index })
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 分类点击
|
||
*/
|
||
onCategoryTap(e) {
|
||
const { id, name } = e.currentTarget.dataset
|
||
|
||
// 兴趣搭子跳转到专门页面
|
||
if (id === 1) {
|
||
wx.navigateTo({
|
||
url: '/pages/interest-partner/interest-partner'
|
||
})
|
||
return
|
||
}
|
||
|
||
// 同城活动跳转到专门页面
|
||
if (id === 2) {
|
||
wx.navigateTo({
|
||
url: '/pages/city-activities/city-activities'
|
||
})
|
||
return
|
||
}
|
||
|
||
// 户外郊游跳转到专门页面
|
||
if (id === 3) {
|
||
wx.navigateTo({
|
||
url: '/pages/outdoor-activities/outdoor-activities'
|
||
})
|
||
return
|
||
}
|
||
|
||
// 定制主题跳转到专门页面
|
||
if (id === 4) {
|
||
wx.navigateTo({
|
||
url: '/pages/theme-travel/theme-travel'
|
||
})
|
||
return
|
||
}
|
||
|
||
// 快乐学堂跳转到专门页面
|
||
if (id === 5) {
|
||
wx.navigateTo({
|
||
url: '/pages/happy-school/happy-school'
|
||
})
|
||
return
|
||
}
|
||
|
||
// 单身聚会跳转到专门页面
|
||
if (id === 6) {
|
||
wx.navigateTo({
|
||
url: '/pages/singles-party/singles-party'
|
||
})
|
||
return
|
||
}
|
||
|
||
wx.showToast({ title: `${name}功能开发中`, icon: 'none' })
|
||
// TODO: 跳转到对应分类页面
|
||
},
|
||
|
||
/**
|
||
* 切换活动标签
|
||
*/
|
||
onTabChange(e) {
|
||
const tab = e.currentTarget.dataset.tab
|
||
console.log('========== Tab切换开始 ==========')
|
||
console.log('[1] 点击的Tab:', tab)
|
||
console.log('[2] 当前activeTab:', this.data.activeTab)
|
||
|
||
if (tab === this.data.activeTab) {
|
||
console.log('[3] Tab未变化,跳过')
|
||
return
|
||
}
|
||
|
||
console.log('[4] 更新activeTab为:', tab)
|
||
this.setData({
|
||
activeTab: tab,
|
||
activityList: [],
|
||
page: 1,
|
||
hasMore: true
|
||
})
|
||
console.log('[5] 调用loadActivityList()')
|
||
this.loadActivityList()
|
||
},
|
||
|
||
/**
|
||
* 下拉刷新
|
||
*/
|
||
onPullDownRefresh() {
|
||
this.loadActivityList(false).finally(() => {
|
||
wx.stopPullDownRefresh()
|
||
})
|
||
},
|
||
|
||
/**
|
||
* 上拉加载更多
|
||
*/
|
||
onReachBottom() {
|
||
if (this.data.hasMore && !this.data.loadingMore && !this.data.loading) {
|
||
console.log('[100] 触发上拉加载更多')
|
||
this.loadActivityList(true)
|
||
} else {
|
||
console.log('[101] 不满足加载条件:', {
|
||
hasMore: this.data.hasMore,
|
||
loadingMore: this.data.loadingMore,
|
||
loading: this.data.loading
|
||
})
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 活动卡片点击
|
||
*/
|
||
onActivityTap(e) {
|
||
const id = e.currentTarget.dataset.id
|
||
wx.navigateTo({
|
||
url: `/pages/activity-detail/activity-detail?id=${id}`
|
||
})
|
||
},
|
||
|
||
/**
|
||
* 报名按钮点击
|
||
*/
|
||
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]
|
||
|
||
// 检查活动状态:满员或结束时弹出二维码
|
||
const isFull = activity.participants >= activity.maxParticipants && activity.maxParticipants > 0
|
||
const isEnded = activity.status === 'ended' || (activity.endDate && new Date(activity.endDate) < new Date())
|
||
|
||
if (isFull || isEnded) {
|
||
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
|
||
}
|
||
|
||
// 如果报名功能已关闭,直接显示二维码
|
||
if (activity.signupEnabled === false) {
|
||
if (activity.activityGuideQrcode) {
|
||
this.setData({ qrcodeImageUrl: activity.activityGuideQrcode })
|
||
}
|
||
this.setData({ showQrcodeModal: true })
|
||
return
|
||
}
|
||
|
||
try {
|
||
if (activity.isSignedUp) {
|
||
// 取消报名
|
||
const res = await api.activity.cancelSignup(id)
|
||
if (res.success) {
|
||
wx.showToast({ title: '已取消报名', icon: 'success' })
|
||
this.setData({
|
||
[`activityList[${index}].isSignedUp`]: false,
|
||
[`activityList[${index}].participants`]: res.data.currentParticipants
|
||
})
|
||
}
|
||
} else {
|
||
// 报名
|
||
const userInfo = app.globalData.userInfo || {}
|
||
const res = await api.activity.signup(id, {
|
||
remark: userInfo.nickname || '',
|
||
contactPhone: userInfo.phone || ''
|
||
})
|
||
if (res.success) {
|
||
wx.showToast({ title: '报名成功', icon: 'success' })
|
||
this.setData({
|
||
[`activityList[${index}].isSignedUp`]: true,
|
||
[`activityList[${index}].participants`]: res.data.currentParticipants
|
||
})
|
||
} else {
|
||
// 检查是否需要显示二维码(后端开关关闭)
|
||
if (res.code === 'QR_CODE_REQUIRED') {
|
||
if (activity.activityGuideQrcode) {
|
||
this.setData({ qrcodeImageUrl: activity.activityGuideQrcode })
|
||
}
|
||
this.setData({ showQrcodeModal: true })
|
||
} else if (res.code === 'ACTIVITY_ENDED' || res.error === '活动已结束') {
|
||
if (activity.activityGuideQrcode) {
|
||
this.setData({ qrcodeImageUrl: activity.activityGuideQrcode })
|
||
}
|
||
this.setData({ showQrcodeModal: true })
|
||
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) {
|
||
this.setData({ qrcodeImageUrl: activity.activityGuideQrcode })
|
||
}
|
||
this.setData({ showQrcodeModal: true })
|
||
if (isActivityEnded) {
|
||
wx.showToast({ title: '活动已结束,进群查看更多', icon: 'none' })
|
||
}
|
||
} else {
|
||
wx.showToast({
|
||
title: err.error || err.message || '操作失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 关闭二维码弹窗
|
||
*/
|
||
onCloseQrcodeModal() {
|
||
this.setData({ showQrcodeModal: false })
|
||
},
|
||
|
||
/**
|
||
* 保存二维码
|
||
*/
|
||
async onSaveQrcode() {
|
||
try {
|
||
const { qrcodeImageUrl } = this.data
|
||
if (!qrcodeImageUrl) {
|
||
wx.showToast({ title: '二维码链接不存在', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
wx.showLoading({ title: '保存中...' })
|
||
|
||
let filePath = ''
|
||
|
||
// 判断是否是 Base64 格式
|
||
if (qrcodeImageUrl.startsWith('data:image')) {
|
||
const fs = wx.getFileSystemManager()
|
||
const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(qrcodeImageUrl) || []
|
||
if (!format || !bodyData) {
|
||
throw new Error('Base64 格式错误')
|
||
}
|
||
filePath = `${wx.env.USER_DATA_PATH}/qrcode_${Date.now()}.${format}`
|
||
fs.writeFileSync(filePath, bodyData, 'base64')
|
||
} else {
|
||
// 远程 URL 格式
|
||
const downloadRes = await new Promise((resolve, reject) => {
|
||
wx.downloadFile({
|
||
url: qrcodeImageUrl,
|
||
success: resolve,
|
||
fail: reject
|
||
})
|
||
})
|
||
|
||
if (downloadRes.statusCode !== 200) {
|
||
throw new Error('下载图片失败')
|
||
}
|
||
filePath = downloadRes.tempFilePath
|
||
}
|
||
|
||
// 保存到相册
|
||
await new Promise((resolve, reject) => {
|
||
wx.saveImageToPhotosAlbum({
|
||
filePath: filePath,
|
||
success: resolve,
|
||
fail: reject
|
||
})
|
||
})
|
||
|
||
wx.hideLoading()
|
||
wx.showToast({ title: '保存成功', icon: 'success' })
|
||
this.onCloseQrcodeModal()
|
||
} catch (err) {
|
||
wx.hideLoading()
|
||
console.error('保存二维码失败', err)
|
||
|
||
if (err.errMsg && (err.errMsg.includes('auth deny') || err.errMsg.includes('auth denied'))) {
|
||
wx.showModal({
|
||
title: '需要授权',
|
||
content: '请允许访问相册以保存二维码',
|
||
confirmText: '去设置',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
wx.openSetting()
|
||
}
|
||
}
|
||
})
|
||
} else {
|
||
wx.showToast({ title: err.message || '保存失败', icon: 'none' })
|
||
}
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 阻止冒泡
|
||
*/
|
||
preventBubble() {
|
||
return
|
||
},
|
||
|
||
/**
|
||
* 点赞
|
||
*/
|
||
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' })
|
||
}
|
||
},
|
||
|
||
/**
|
||
* Tab bar 导航
|
||
*/
|
||
switchTab(e) {
|
||
const path = e.currentTarget.dataset.path
|
||
|
||
if (path === '/pages/chat/chat') {
|
||
if (!app.globalData.isLoggedIn) {
|
||
wx.navigateTo({
|
||
url: '/pages/login/login?redirect=' + encodeURIComponent(path)
|
||
})
|
||
return
|
||
}
|
||
}
|
||
wx.switchTab({ url: path })
|
||
}
|
||
})
|