duidui_mini_program/pages/camp_list/index.js
2026-03-27 10:41:46 +08:00

271 lines
10 KiB
JavaScript

// 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
});
}
});