- 新增许愿树页面(Canvas绘制、许愿条展示) - 新增许愿详情页面 - 新增许愿创建弹窗(免费/付费两种模式) - 新增网络请求封装 utils/request.js - 新增Go后端项目结构(Gin + Inertia.js) - 新增用户、订单、许愿数据模型 - 新增数据库迁移脚本 - 更新.gitignore补全忽略规则 - 更新.env.local配置(robot=2, 版本1.0.1) - 添加secrets目录说明文档
275 lines
7.2 KiB
JavaScript
275 lines
7.2 KiB
JavaScript
const { request } = require('../../utils/request.js');
|
|
|
|
Page({
|
|
data: {
|
|
tree: null,
|
|
wishes: [],
|
|
loading: true,
|
|
canvasWidth: 375,
|
|
canvasHeight: 600,
|
|
showCreateModal: false,
|
|
wishContent: '',
|
|
wishType: 'free', // free: 免费, paid: 付费
|
|
maxFreeLength: 20,
|
|
maxPaidLength: 100,
|
|
products: [],
|
|
selectedProduct: null,
|
|
},
|
|
|
|
onLoad() {
|
|
this.loadWishTree();
|
|
this.loadProducts();
|
|
},
|
|
|
|
onPullDownRefresh() {
|
|
this.loadWishTree().then(() => {
|
|
wx.stopPullDownRefresh();
|
|
});
|
|
},
|
|
|
|
// 加载许愿树数据
|
|
async loadWishTree() {
|
|
try {
|
|
const res = await request({
|
|
url: '/api/wish/tree',
|
|
method: 'GET',
|
|
});
|
|
|
|
if (res.code === 0) {
|
|
this.setData({
|
|
tree: res.data.tree,
|
|
wishes: res.data.wishes || [],
|
|
loading: false,
|
|
});
|
|
this.drawTree();
|
|
}
|
|
} catch (err) {
|
|
console.error('加载许愿树失败:', err);
|
|
this.setData({ loading: false });
|
|
// 使用本地模拟数据
|
|
this.setData({
|
|
tree: { id: 1, name: '祈福许愿树', maxWishes: 100 },
|
|
wishes: this.getMockWishes(),
|
|
loading: false,
|
|
});
|
|
this.drawTree();
|
|
}
|
|
},
|
|
|
|
// 加载许愿商品
|
|
async loadProducts() {
|
|
try {
|
|
const res = await request({
|
|
url: '/api/wish/products',
|
|
method: 'GET',
|
|
});
|
|
|
|
if (res.code === 0) {
|
|
this.setData({ products: res.data.list || [] });
|
|
}
|
|
} catch (err) {
|
|
console.error('加载商品失败:', err);
|
|
// 使用默认商品
|
|
this.setData({
|
|
products: [
|
|
{ id: 1, name: '普通许愿条', price: 100, duration: 7, position: 0 },
|
|
{ id: 2, name: '精品许愿条', price: 500, duration: 30, position: 10 },
|
|
{ id: 3, name: '至尊许愿条', price: 2000, duration: 90, position: 100 },
|
|
],
|
|
});
|
|
}
|
|
},
|
|
|
|
// 模拟许愿数据
|
|
getMockWishes() {
|
|
return [
|
|
{ id: 1, content: '愿家人平安健康', type: 'paid', position: 10, isRobot: false },
|
|
{ id: 2, content: '事业顺利', type: 'free', position: 5, isRobot: false },
|
|
{ id: 3, content: '心想事成', type: 'paid', position: 20, isRobot: true },
|
|
{ id: 4, content: '考试通过', type: 'free', position: 3, isRobot: false },
|
|
{ id: 5, content: '财源广进', type: 'paid', position: 15, isRobot: false },
|
|
];
|
|
},
|
|
|
|
// 绘制许愿树
|
|
drawTree() {
|
|
const ctx = wx.createCanvasContext('wishTree', this);
|
|
const { canvasWidth, canvasHeight, wishes } = this.data;
|
|
|
|
// 清空画布
|
|
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
|
|
|
|
// 绘制树干
|
|
ctx.setFillStyle('#8B4513');
|
|
ctx.fillRect(canvasWidth / 2 - 20, canvasHeight - 150, 40, 150);
|
|
|
|
// 绘制树冠(圆形)
|
|
ctx.setFillStyle('#228B22');
|
|
ctx.beginPath();
|
|
ctx.arc(canvasWidth / 2, canvasHeight - 200, 120, 0, 2 * Math.PI);
|
|
ctx.fill();
|
|
|
|
// 绘制许愿条
|
|
wishes.forEach((wish, index) => {
|
|
const angle = (index / wishes.length) * 2 * Math.PI;
|
|
const radius = 80 + Math.random() * 40;
|
|
const x = canvasWidth / 2 + radius * Math.cos(angle);
|
|
const y = canvasHeight - 200 + radius * Math.sin(angle);
|
|
|
|
// 根据类型设置颜色
|
|
if (wish.type === 'paid') {
|
|
ctx.setFillStyle('#FFD700'); // 金色 - 付费
|
|
} else {
|
|
ctx.setFillStyle('#FF6B6B'); // 红色 - 免费
|
|
}
|
|
|
|
// 绘制许愿条(小矩形)
|
|
ctx.fillRect(x - 15, y - 5, 30, 10);
|
|
|
|
// 绘制文字
|
|
ctx.setFillStyle('#FFFFFF');
|
|
ctx.setFontSize(8);
|
|
ctx.setTextAlign('center');
|
|
ctx.fillText(wish.content.substring(0, 4), x, y + 3);
|
|
});
|
|
|
|
ctx.draw();
|
|
},
|
|
|
|
// 打开许愿弹窗
|
|
openCreateModal() {
|
|
this.setData({ showCreateModal: true });
|
|
},
|
|
|
|
// 关闭许愿弹窗
|
|
closeCreateModal() {
|
|
this.setData({
|
|
showCreateModal: false,
|
|
wishContent: '',
|
|
wishType: 'free',
|
|
selectedProduct: null,
|
|
});
|
|
},
|
|
|
|
// 输入许愿内容
|
|
onInputContent(e) {
|
|
this.setData({ wishContent: e.detail.value });
|
|
},
|
|
|
|
// 选择许愿类型
|
|
selectType(e) {
|
|
const type = e.currentTarget.dataset.type;
|
|
this.setData({ wishType: type });
|
|
},
|
|
|
|
// 选择商品
|
|
selectProduct(e) {
|
|
const id = e.currentTarget.dataset.id;
|
|
const product = this.data.products.find(p => p.id === id);
|
|
this.setData({ selectedProduct: product });
|
|
},
|
|
|
|
// 提交许愿
|
|
async submitWish() {
|
|
const { wishContent, wishType, selectedProduct } = this.data;
|
|
|
|
if (!wishContent.trim()) {
|
|
wx.showToast({ title: '请输入许愿内容', icon: 'none' });
|
|
return;
|
|
}
|
|
|
|
// 检查字数限制
|
|
const maxLength = wishType === 'free' ? this.data.maxFreeLength : this.data.maxPaidLength;
|
|
if (wishContent.length > maxLength) {
|
|
wx.showToast({ title: `最多输入${maxLength}个字`, icon: 'none' });
|
|
return;
|
|
}
|
|
|
|
// 付费许愿需要选择商品
|
|
if (wishType === 'paid' && !selectedProduct) {
|
|
wx.showToast({ title: '请选择许愿商品', icon: 'none' });
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// 如果是付费许愿,先创建订单
|
|
if (wishType === 'paid') {
|
|
const orderRes = await request({
|
|
url: '/api/pay/create',
|
|
method: 'POST',
|
|
data: {
|
|
type: 'wish',
|
|
productId: selectedProduct.id,
|
|
content: wishContent,
|
|
},
|
|
});
|
|
|
|
if (orderRes.code === 0) {
|
|
// 调起微信支付
|
|
await this.wxPay(orderRes.data);
|
|
}
|
|
} else {
|
|
// 免费许愿直接创建
|
|
const res = await request({
|
|
url: '/api/wish/create',
|
|
method: 'POST',
|
|
data: {
|
|
content: wishContent,
|
|
type: 'free',
|
|
treeId: this.data.tree.id,
|
|
},
|
|
});
|
|
|
|
if (res.code === 0) {
|
|
wx.showToast({ title: '许愿成功', icon: 'success' });
|
|
this.closeCreateModal();
|
|
this.loadWishTree();
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.error('许愿失败:', err);
|
|
wx.showToast({ title: '许愿失败,请重试', icon: 'none' });
|
|
}
|
|
},
|
|
|
|
// 微信支付
|
|
async wxPay(orderData) {
|
|
return new Promise((resolve, reject) => {
|
|
wx.requestPayment({
|
|
timeStamp: orderData.timeStamp,
|
|
nonceStr: orderData.nonceStr,
|
|
package: orderData.package,
|
|
signType: orderData.signType,
|
|
paySign: orderData.paySign,
|
|
success: () => {
|
|
wx.showToast({ title: '支付成功', icon: 'success' });
|
|
this.closeCreateModal();
|
|
this.loadWishTree();
|
|
resolve();
|
|
},
|
|
fail: (err) => {
|
|
console.error('支付失败:', err);
|
|
wx.showToast({ title: '支付失败', icon: 'none' });
|
|
reject(err);
|
|
},
|
|
});
|
|
});
|
|
},
|
|
|
|
// 查看许愿详情
|
|
viewWishDetail(e) {
|
|
const id = e.currentTarget.dataset.id;
|
|
wx.navigateTo({
|
|
url: `/pages/wish-detail/wish-detail?id=${id}`,
|
|
});
|
|
},
|
|
|
|
// 分享
|
|
onShareAppMessage() {
|
|
return {
|
|
title: '快来许愿树许下你的愿望吧!',
|
|
path: '/pages/wish-tree/wish-tree',
|
|
};
|
|
},
|
|
});
|