174 lines
5.8 KiB
JavaScript
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 });
|
|
}
|
|
});
|
|
}
|
|
})
|