271 lines
10 KiB
JavaScript
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
|
|
});
|
|
}
|
|
}); |