// pages/camp_list/index.js import { campApi } from '../../config/camp_api.js'; Page({ /** * 页面的初始数据 */ data: { currentCategoryIndex: 0, categoryId: '-1', categories: [], middleCategories: [], loading: true, camps: [], }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { this.fetchCampCategoies(); }, /** * 获取营地列表数据 */ fetchCampCategoies: function () { var that = this; this.setData({ loading: true }); campApi.getCampCategories() .then(function (res) { // 处理响应数据格式:检查 res.success 和 res.categories if (res.success && res.categories && Array.isArray(res.categories)) { // 对分类按 sort_order 排序(从小到大) const sortedCategories = res.categories.sort((a, b) => { const orderA = a.sort_order || 0; const orderB = b.sort_order || 0; return orderA - orderB; }); // 推荐固定顶部,中间为分类(可滑动),已加入固定底部 const fixedTop = { id: '-1', name: '推荐打卡营', sort_order: -1 }; const fixedBottom = { id: 'joined', name: '已加入打卡营', sort_order: 9999 }; const categoriesAll = [fixedTop, ...sortedCategories, fixedBottom]; that.setData({ categories: categoriesAll, middleCategories: sortedCategories, loading: false }); // 获取打卡营列表 that.fetchCamps(); } else { wx.showToast({ title: '获取分类列表失败', icon: 'none' }); var fixedTop = { id: '-1', name: '推荐打卡营', sort_order: -1 }; var fixedBottom = { id: 'joined', name: '已加入打卡营', sort_order: 9999 }; that.setData({ categories: [fixedTop, fixedBottom], middleCategories: [], loading: false }); } }) .catch(function (err) { wx.showToast({ title: '获取分类列表失败', icon: 'none' }); var fixedTop = { id: '-1', name: '推荐打卡营', sort_order: -1 }; var fixedBottom = { id: 'joined', name: '已加入打卡营', sort_order: 9999 }; that.setData({ categories: [fixedTop, fixedBottom], middleCategories: [], loading: false }); }); }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () { }, /** * 生命周期函数--监听页面显示 */ onShow: function () { // 从详情页返回时,刷新营列表状态(用户可能已报名或完成了某个营) if (this.data.camps && this.data.camps.length > 0) { this.fetchCampsUserStatus(this.data.camps); } }, /** * 生命周期函数--监听页面隐藏 */ onHide: function () { }, /** * 生命周期函数--监听页面卸载 */ onUnload: function () { }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function () { this.fetchCamps(); wx.stopPullDownRefresh(); }, /** * 页面上拉触底事件的处理函数 */ onReachBottom: function () { }, /** * 用户点击右上角分享 */ onShareAppMessage: function () { }, async switchCategory(e) { const categoryId = e.currentTarget.dataset.id; const categoryIndex = e.currentTarget.dataset.index; if (categoryId === undefined || categoryId === null) { wx.showToast({ title: '分类ID无效', icon: 'none' }); return; } var categories = this.data.categories || []; var idx = categoryId === 'joined' ? categories.length - 1 : (categoryId === '-1' ? 0 : (categoryIndex >= 0 ? categoryIndex : 0)); this.setData({ categoryId: String(categoryId), currentCategoryIndex: idx }); this.fetchCamps(); }, async fetchCamps() { try { this.setData({ camps: [] }) const categoryId = this.data.categoryId || '-1' // 默认使用推荐打卡营 if (!categoryId || categoryId === 'undefined') { wx.showToast({ title: '分类ID无效', icon: 'none' }); return; } const campsResult = await campApi.getCamps(categoryId) // 处理两种响应格式: // 1. { code: 200, data: { camps: [...] } } - 旧格式 // 2. { success: true, camps: [...] } - 新格式 let camps = []; if (campsResult.success && campsResult.camps) { camps = campsResult.camps; } else if (campsResult.code === 200 && campsResult.data && campsResult.data.camps) { camps = campsResult.data.camps; } // 处理 camps 可能是对象的情况,转换为数组 if (camps && typeof camps === 'object' && !Array.isArray(camps)) { if (Object.keys(camps).length === 0) { camps = []; } else { camps = Object.values(camps); } } if (Array.isArray(camps) && camps.length > 0) { // 先用默认灰色边框展示列表 const initialCamps = camps.map(item => ({ ...item, cssStyle: 'border-notStarted' })); this.setData({ camps: initialCamps }); // 并行查询每个营的用户报名/完成状态 this.fetchCampsUserStatus(camps); } else { this.setData({ camps: [] }); } } catch (err) { wx.showToast({ title: '获取打卡营列表失败', icon: 'none' }); this.setData({ camps: [] }); } }, /** * 批量查询营的用户状态,更新边框颜色 * A 未报名 → 灰色边框 (border-notStarted) * B 已报名未完成 → 蓝色边框 (border-inProgress) * C 已完成 → 紫红色边框 (border-completed) */ async fetchCampsUserStatus(camps) { var that = this; try { // 并行查询所有营的用户状态 const statusPromises = camps.map(camp => { return campApi.checkUserCampStatus(camp.id) .then(res => ({ campId: camp.id, res })) .catch(() => ({ campId: camp.id, res: null })); }); const results = await Promise.all(statusPromises); // 构建 campId → 用户状态 的映射 // 后端返回: { success, is_joined, camp_status: "not_started" | "in_progress" | "completed" } const statusMap = {}; results.forEach(({ campId, res }) => { if (!res || !res.is_joined) { statusMap[campId] = 'NotStarted'; return; } // 已加入,根据 camp_status 判断 const campStatus = String(res.camp_status || '').toLowerCase(); if (campStatus.indexOf('completed') !== -1) { statusMap[campId] = 'Completed'; } else { statusMap[campId] = 'InProgress'; } }); // 更新列表中每个营的边框样式 const currentCamps = that.data.camps; const updatedCamps = currentCamps.map(item => { const userStatus = statusMap[item.id] || 'NotStarted'; let cssStyle = 'border-notStarted'; if (userStatus === 'Completed') { cssStyle = 'border-completed'; } else if (userStatus === 'InProgress') { cssStyle = 'border-inProgress'; } return { ...item, user_status: userStatus, cssStyle }; }); that.setData({ camps: updatedCamps }); } catch (err) { // 查询状态失败不影响列表展示,保持默认灰色边框 } }, // 跳转到营地详情页 navigateToCamp: function (e) { wx.navigateTo({ url: '/pages/camp_detail/index?id=' + e.currentTarget.dataset.campid }); } });