Files
geminiWX/wechat-mini-program/pages/detail/detail.js
2025-12-08 14:39:07 +08:00

174 lines
5.8 KiB
JavaScript

const app = getApp()
Page({
data: {
project: null,
bestCoupon: null,
finalPrice: 0,
isEnrolled: false,
tagStyle: {
video: 'width: 100%;',
img: 'width: 100%; height: auto; display: block;'
}
},
onLoad(options) {
const { id } = options;
this.fetchProject(id);
this.checkEnrollment(id);
},
checkEnrollment(projectId) {
const user = app.globalData.userInfo;
if (!user) return;
const { request } = require('../../utils/request')
request({
url: `/student-projects/?student=${user.id}&project=${projectId}`
}).then(res => {
// Search result from list
if (res && res.results && res.results.length > 0) {
this.setData({ isEnrolled: true });
} else if (Array.isArray(res) && res.length > 0) {
this.setData({ isEnrolled: true });
}
}).catch(err => console.error('Check enrollment failed', err));
},
fetchProject(id) {
const { request } = require('../../utils/request')
// Fetch project details
request({ url: `/projects/${id}/` })
.then((data) => {
this.setData({ project: data })
// Fetch coupons to calculate best discount
if (parseFloat(data.price) > 0 && data.show_price) {
this.fetchCoupons(data.id, data.price);
} else {
this.setData({
finalPrice: data.price,
bestCoupon: null,
bestCouponId: null
});
}
})
.catch(() => {
// Mock data fallback
this.setData({
project: {
id: id,
title: '示例项目',
category: '示例分类',
rating: 4.8,
students: 120,
duration: '4周',
price: 299,
show_price: true,
detail: '<p>这是一个示例项目详情。</p>',
image: 'https://images.unsplash.com/photo-1526379095098-d400fd0bf935'
}
})
})
},
fetchCoupons(projectId, originalPrice) {
const { request } = require('../../utils/request')
request({ url: '/user-coupons/' }).then(coupons => {
// Filter applicable coupons
const validCoupons = coupons.filter(sc => {
// Check if coupon is applicable to this project
const c = sc.coupon_detail;
const isApplicable = c.applicable_project_titles.length === 0 || c.applicable_project_titles.includes(this.data.project.title);
return isApplicable && sc.status === 'assigned';
});
if (validCoupons.length > 0) {
// Find the best coupon (highest discount)
let maxDiscount = 0;
let bestCoupon = null;
validCoupons.forEach(sc => {
const c = sc.coupon_detail;
const discount = parseFloat(c.amount);
if (discount > maxDiscount) {
maxDiscount = discount;
bestCoupon = sc; // Keep the student_coupon object to get ID
}
});
if (bestCoupon) {
const finalPrice = Math.max(0, originalPrice - maxDiscount);
this.setData({
bestCoupon: bestCoupon.coupon_detail, // For display
bestCouponId: bestCoupon.id, // For submission (StudentCoupon ID)
finalPrice: finalPrice.toFixed(2)
});
} else {
this.setData({ finalPrice: originalPrice });
}
} else {
this.setData({ finalPrice: originalPrice });
}
}).catch(() => {
this.setData({ finalPrice: originalPrice });
});
},
handleEnroll() {
const { request } = require('../../utils/request')
const user = app.globalData.userInfo;
if (!user) {
wx.showToast({ title: '请先登录', icon: 'none' });
return;
}
if (this.data.isEnrolled) {
wx.showToast({ title: '您已报名该项目', icon: 'none' });
return;
}
const payload = {
student: user.id,
project: this.data.project.id,
coupon_id: this.data.bestCouponId || null
};
wx.showLoading({ title: '报名中...' });
request({
url: '/student-projects/',
method: 'POST',
data: payload
}).then(res => {
wx.hideLoading();
wx.showToast({ title: '报名成功', icon: 'success' });
this.setData({ isEnrolled: true });
}).catch(err => {
wx.hideLoading();
console.error('Enrollment error:', err);
let msg = '报名失败';
if (err.data) {
if (err.data.detail) {
msg = err.data.detail;
} else if (err.data.coupon_id) {
msg = Array.isArray(err.data.coupon_id) ? err.data.coupon_id[0] : err.data.coupon_id;
} else if (typeof err.data === 'string') {
msg = err.data;
} else {
// Try to find first error value
const keys = Object.keys(err.data);
if (keys.length > 0) {
const firstVal = err.data[keys[0]];
msg = Array.isArray(firstVal) ? firstVal[0] : firstVal;
}
}
} else if (err.detail) {
msg = err.detail;
}
wx.showToast({ title: msg, icon: 'none' });
if (msg && (msg.includes('重复') || msg.includes('exist'))) {
this.setData({ isEnrolled: true });
}
});
}
})