| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516 |
- // 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<string>} 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);
- }
- });
- });
- }
- })
|