// invitationCode/index.js const app = getApp(); import util from '../utils/util.js' Page({ /** * 页面的初始数据 */ data: { appAssetsUrl: app.appAssetsUrl, appAssetsUrl3: app.appAssetsUrl3, bottomLeft: app.bottomLeft, user: {}, name: '', memberphoto: '', inviteCode: '', invitationCodeImg: '' }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { let that = this; const user = wx.getStorageSync("USER"); this.setData({ name: options.name ? options.name : (user.name ? user.name : user.vipname), inviteCode: options.inviteCode ? options.inviteCode : user.inviteCode, memberphoto: options.memberphoto ? options.memberphoto : user.memberphoto, user }) if (wx.getStorageSync('invitationCodeImg')) { that.setData({ invitationCodeImg: wx.getStorageSync('invitationCodeImg'), }); } else { this.getCode(); } wx.setNavigationBarTitle({ title: options.inviteCode ? '他/她的会员码' : '会员码' }); }, downloadQR() { console.log('下载海报'); const that = this; wx.getSetting({ //获取权限 success(res) { console.log(res); if (res.authSetting["scope.writePhotosAlbum"]) { that.createPoster(); } else if (res.authSetting["scope.writePhotosAlbum"] == false) { wx.showToast({ title: '请先授权相册', icon: 'none' }) wx.openSetting({ scope: "scope.writePhotosAlbum", success() { that.createPoster(); } }); } else { wx.authorize({ scope: "scope.writePhotosAlbum", success() { that.createPoster(); }, fail(e) { console.log('未授权相册', e); wx.showToast({ title: '请先授权相册', icon: 'none' }) } }); } } }); }, // 生成海报 createPoster() { wx.showLoading({ title: '生成海报中...', }); const that = this; // 获取背景图片的实际尺寸 const bgUrl = that.data.appAssetsUrl3 + 'invitation_code_bg.png'; // 使用背景图片的实际尺寸作为画布尺寸 const canvasWidth = 750; const canvasHeight = 1334; // 计算缩放比例 const scale = Math.min(canvasWidth, canvasHeight) / Math.min(canvasWidth, canvasHeight); // 创建canvas绘图上下文 const ctx = wx.createCanvasContext('myCanvas', that); // 绘制背景图片,沾满整个画布 that.drawImageWithRetry(ctx, bgUrl, 0, 0, canvasWidth, canvasHeight, false, () => { // 背景图片绘制完成后继续绘制其他元素 // 绘制完成,导出图片 ctx.draw(false, () => { // 绘制用户头像 const avatarUrl = that.data.memberphoto ? that.data.memberphoto : (that.data.appAssetsUrl + '/images/bz1_nor.png'); // 按比例调整头像尺寸和位置 const avatarSize = 99 * scale; // 99rpx const avatarX = 40 * scale; const avatarY = 40 * scale; that.drawImageWithRetry(ctx, avatarUrl, avatarX, avatarY, avatarSize, avatarSize, true, () => { // 绘制用户名 (与头像对齐并排展示) ctx.setTextAlign('left'); ctx.setFillStyle('#ffffff'); ctx.setFontSize(30 * scale); // 字体大小 // 文字垂直居中对齐头像 const textY = avatarY + avatarSize / 2 - 10 * scale; ctx.fillText(that.data.name || '--', avatarX + avatarSize + 20 * scale, textY); // 绘制邀请码 (与头像对齐并排展示) ctx.setFontSize(28 * scale); // 字体大小 ctx.fillText('邀请码: ' + (that.data.inviteCode || ''), avatarX + avatarSize + 20 * scale, textY + 35 * scale); // 头像和文字绘制完成后绘制二维码 if (that.data.invitationCodeImg) { // 按比例调整二维码尺寸和位置,保持居中 const qrSize = 148 * scale; // 148rpx const qrX = (canvasWidth - qrSize) / 2; // 居中显示 const qrY = canvasHeight - 200 * scale - 20 * scale; // 向上移动20px that.drawImageWithRetry(ctx, that.data.invitationCodeImg, qrX, qrY, qrSize, qrSize, false, () => { // 二维码绘制完成后绘制底部文字,保持居中 ctx.setTextAlign('center'); ctx.setFillStyle('#ffffff'); ctx.setFontSize(30 * scale); ctx.fillText('青雲慧青年服务平台', canvasWidth / 2, canvasHeight - 30 * scale); // 全部绘制完成,导出图片 ctx.draw(true, () => { that.exportCanvasToImage(); }); }); } else { // 没有二维码时绘制底部文字,保持居中 ctx.setTextAlign('center'); ctx.setFillStyle('#ffffff'); ctx.setFontSize(30 * scale); ctx.fillText('青雲慧青年服务平台', canvasWidth / 2, canvasHeight - 30 * scale); // 全部绘制完成,导出图片 ctx.draw(true, () => { that.exportCanvasToImage(); }); } }); }); }); }, // 带重试机制的图片绘制方法 drawImageWithRetry(ctx, imageUrl, x, y, width, height, isAvatar, callback) { const that = this; // 检查是否为base64格式的图片数据 if (imageUrl && (imageUrl.startsWith('data:image') || imageUrl.startsWith('/9j/'))) { // 处理base64格式的图片 that.drawBase64Image(ctx, imageUrl, x, y, width, height, isAvatar, callback); return; } // 如果imageUrl为空或无效,直接回调 if (!imageUrl) { callback && callback(); return; } wx.getImageInfo({ src: imageUrl, success: function (res) { try { // 检查是否为二维码图片,如果是则添加圆角 if (!isAvatar && that.data.invitationCodeImg && imageUrl === that.data.invitationCodeImg) { // 为二维码添加5px圆角 ctx.save(); ctx.beginPath(); ctx.moveTo(x + 5, y); ctx.lineTo(x + width - 5, y); ctx.quadraticCurveTo(x + width, y, x + width, y + 5); ctx.lineTo(x + width, y + height - 5); ctx.quadraticCurveTo(x + width, y + height, x + width - 5, y + height); ctx.lineTo(x + 5, y + height); ctx.quadraticCurveTo(x, y + height, x, y + height - 5); ctx.lineTo(x, y + 5); ctx.quadraticCurveTo(x, y, x + 5, y); ctx.closePath(); ctx.clip(); ctx.drawImage(res.path, x, y, width, height); ctx.restore(); } else if (isAvatar) { // 如果是头像,需要圆形裁剪 ctx.save(); ctx.beginPath(); ctx.arc(x + width / 2, y + height / 2, width / 2, 0, 2 * Math.PI); ctx.clip(); ctx.drawImage(res.path, x, y, width, height); ctx.restore(); } else { // 普通图片直接绘制 ctx.drawImage(res.path, x, y, width, height); } callback && callback(); } catch (e) { console.log('绘制图片失败', e); callback && callback(); } }, fail: function (err) { console.log('获取图片失败', err, imageUrl); // 如果是头像且获取失败,使用默认头像 if (isAvatar) { const defaultAvatar = that.data.appAssetsUrl + '/images/bz1_nor.png'; if (defaultAvatar !== imageUrl) { // 重试默认头像 that.drawImageWithRetry(ctx, defaultAvatar, x, y, width, height, true, callback); } else { // 默认头像也失败了,直接回调 callback && callback(); } } else { // 非头像图片失败,直接回调 callback && callback(); } } }); }, // 绘制base64格式的图片 drawBase64Image(ctx, base64Data, x, y, width, height, isAvatar, callback) { try { const that = this; // 创建文件管理器 const fsm = wx.getFileSystemManager(); // 生成临时文件路径 const filePath = `${wx.env.USER_DATA_PATH}/temp_image_${Date.now()}_${Math.floor(Math.random() * 1000)}.png`; // 清理base64数据 let imageData = base64Data; if (imageData.includes('data:image')) { imageData = imageData.split(',')[1]; } // 将base64数据写入临时文件 fsm.writeFile({ filePath: filePath, data: imageData, encoding: 'base64', success: function () { try { // 绘制图片 if (isAvatar) { // 如果是头像,需要圆形裁剪 ctx.save(); ctx.beginPath(); ctx.arc(x + width / 2, y + height / 2, width / 2, 0, 2 * Math.PI); ctx.clip(); ctx.drawImage(filePath, x, y, width, height); ctx.restore(); } else { // 普通图片直接绘制 ctx.drawImage(filePath, x, y, width, height); } // 延迟删除临时文件,确保绘制完成 setTimeout(() => { try { fsm.unlinkSync(filePath); } catch (e) { console.log('删除临时文件失败', e); } }, 1000); callback && callback(); } catch (e) { console.log('绘制base64图片失败', e); // 清理临时文件 try { fsm.unlinkSync(filePath); } catch (e) { console.log('删除临时文件失败', e); } callback && callback(); } }, fail: function (err) { console.log('写入base64图片失败', err); callback && callback(); } }); } catch (e) { console.log('处理base64图片异常', e); callback && callback(); } }, // 导出canvas到图片 exportCanvasToImage() { const that = this; wx.canvasToTempFilePath({ canvasId: 'myCanvas', success: function (res) { wx.hideLoading(); // 保存图片到相册 that.saveImageToPhotosAlbum(res.tempFilePath); }, fail: function (err) { wx.hideLoading(); console.log('生成海报失败', err); wx.showToast({ title: '生成海报失败', icon: 'none' }); } }, that); }, // 保存图片到相册 saveImageToPhotosAlbum(filePath) { wx.saveImageToPhotosAlbum({ filePath: filePath, success: function () { wx.showToast({ title: '已保存到相册', icon: 'success' }); }, fail: function (err) { console.log('保存失败', err); wx.showToast({ title: '保存失败', icon: 'none' }); } }); }, //将base64图片转网络图片 sendCode() { let code = this.data.invitationCodeImg; let qrcode = code.replace(/\. +/g, '').replace(/[\r\n]/g, '') /*code是指图片base64格式数据*/ //声明文件系统 const fs = wx.getFileSystemManager(); //随机定义路径名称 var times = new Date().getTime(); var filePath = wx.env.USER_DATA_PATH + '/' + times + '.png'; //将base64图片写入 fs.writeFile({ filePath, data: qrcode.slice(22), encoding: 'base64', success: () => { wx.saveImageToPhotosAlbum({ filePath, success: function (res) { wx.showToast({ title: '已保存图片', icon: 'none' }) } }); } }); }, handleInvite() { wx.navigateTo({ url: "/pages/my/myInvite/myInvite", }); }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () { }, /** * 生命周期函数--监听页面显示 */ onShow: function () { }, /** * 生命周期函数--监听页面隐藏 */ onHide: function () { }, /** * 生命周期函数--监听页面卸载 */ onUnload: function () { }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function () { }, /** * 页面上拉触底事件的处理函数 */ onReachBottom: function () { }, /** * 用户点击右上角分享 */ onShareAppMessage: function () { this.addScore(); return { title: '青雲慧小程序-邀请码分享', path: `/pages/login?inviteCode=${this.data.inviteCode}` } }, //统计积分(每日小程序分享) addScore: function () { if (!util.getUserId()) { return; } wx.showLoading({ title: '努力加载中...', }) app._post_form('scoreStu/share', "", { stuId: util.getUserId() }, function (res) { if (res.code === 0) { } }) }, getCode() { let that = this; wx.showLoading({ title: '努力加载中...', }) app._post_form('create/wxaqrcode', '', { inviteCode: that.data.inviteCode }, function (res) { if (res.code == 0) { that.setData({ invitationCodeImg: res.data }) wx.setStorageSync('invitationCodeImg', res.data); } }) }, copyText() { wx.setClipboardData({ data: this.data.inviteCode || '', success: function (res) { wx.showToast({ title: '已复制邀请码', icon: 'none' }) }, fail: function (err) { console.log(err) wx.showToast({ title: '复制失败', icon: 'none' }) } }) }, /** * 将网络图片转换为base64格式 * @param {string} url - 网络图片地址 * @returns {Promise} base64格式字符串 */ convertImageToBase64(url) { return new Promise((resolve, reject) => { // 下载网络图片 wx.downloadFile({ url: url, success: (res) => { if (res.statusCode === 200) { const tempFilePath = res.tempFilePath; // 读取本地文件内容并转换为base64 const fs = wx.getFileSystemManager(); fs.readFile({ filePath: tempFilePath, encoding: 'base64', success: (readRes) => { // 构造完整的base64数据URI const base64Data = 'data:image/png;base64,' + readRes.data; resolve(base64Data); }, fail: (error) => { console.error('读取图片文件失败:', error); reject(error); } }); } else { reject(new Error('下载图片失败')); } }, fail: (error) => { console.error('下载图片失败:', error); reject(error); } }); }); } })