Files
Wechat/pages/invite-manager/invite-manager.js

356 lines
10 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// pages/zuzhanghaibao/zuzhanghaibao.js
import request from '../../utils/request.js';
const app = getApp();
Page({
data: {
qrcodeUrl: '', // 二维码完整URL
yaoqingma: '', // 组长邀请码字符串
isLoading: false,
showPosterCanvas: false,
posterImageTemp: '', // 生成的海报临时路径
avatarUrl: '', // 用户头像完整URL
uid: '',
nickName: '',
},
onLoad() {
this.loadFromCache();
this.loadUserInfo();
},
onShow() {
this.registerNotificationComponent();
},
registerNotificationComponent() {
const notificationComp = this.selectComponent('#global-notification');
if (notificationComp && notificationComp.showNotification) {
app.globalData.globalNotification = {
show: (data) => notificationComp.showNotification(data),
hide: () => notificationComp.hideNotification()
};
}
},
/**
* 从缓存加载二维码URL和邀请码
* 缓存键名使用独特拼音,避免与管事页面冲突
*/
loadFromCache() {
try {
const relativeUrl = wx.getStorageSync('zuzhang_haibao_url');
if (relativeUrl) {
const fullUrl = this.getFullImageUrl(relativeUrl);
this.setData({ qrcodeUrl: fullUrl });
}
const yaoqingma = wx.getStorageSync('zuzhang_yaoqingma');
if (yaoqingma) {
this.setData({ yaoqingma });
}
} catch (error) {
console.error('读取缓存失败', error);
}
},
/**
* 加载用户头像、昵称、UID
*/
loadUserInfo() {
const touxiang = wx.getStorageSync('touxiang');
const ossUrl = app.globalData.ossImageUrl || '';
const defaultAvatar = ossUrl + (app.globalData.morentouxiang || 'avatar/default.jpg');
let avatarUrl = defaultAvatar;
if (touxiang && typeof touxiang === 'string' && touxiang.trim() !== '') {
avatarUrl = this.getFullImageUrl(touxiang);
}
const uid = wx.getStorageSync('uid') || '';
// 组长昵称可能从全局变量或缓存获取
let nickName = app.globalData.nicheng || wx.getStorageSync('nicheng') || '组长';
this.setData({ avatarUrl, uid, nickName });
},
/**
* 拼接完整图片URL
*/
getFullImageUrl(url) {
if (!url) return '';
const ossUrl = app.globalData.ossImageUrl || '';
return url.startsWith('http') ? url : ossUrl + url;
},
/**
* 刷新/获取二维码和邀请码
* 调用 /peizhi/zuzhanghb 接口
*/
refreshQRCode() {
if (this.data.isLoading) return;
this.setData({ isLoading: true });
request({
url: '/peizhi/zuzhanghb',
method: 'POST',
})
.then(res => {
if (res.data && res.data.code === 0) {
const { url: relativeUrl, yaoqingma } = res.data.data; // 假设返回字段为 url 和 yaoqingma
if (relativeUrl) {
wx.setStorageSync('zuzhang_haibao_url', relativeUrl);
const fullUrl = this.getFullImageUrl(relativeUrl);
this.setData({ qrcodeUrl: fullUrl });
}
if (yaoqingma) {
wx.setStorageSync('zuzhang_yaoqingma', yaoqingma);
this.setData({ yaoqingma });
}
wx.showToast({ title: '获取成功', icon: 'success' });
} else {
wx.showToast({ title: res.data.msg || '获取失败', icon: 'none' });
}
})
.catch(err => {
console.error('获取组长海报失败', err);
wx.showToast({ title: '网络错误', icon: 'none' });
})
.finally(() => {
this.setData({ isLoading: false });
});
},
/**
* 保存二维码到相册(先下载网络图片)
*/
saveToAlbum() {
if (!this.data.qrcodeUrl) {
wx.showToast({ title: '暂无二维码', icon: 'none' });
return;
}
wx.showLoading({ title: '保存中...', mask: true });
wx.downloadFile({
url: this.data.qrcodeUrl,
success: (res) => {
wx.hideLoading();
if (res.statusCode === 200) {
this.downloadAndSave(res.tempFilePath);
} else {
wx.showToast({ title: '下载失败', icon: 'none' });
}
},
fail: (err) => {
wx.hideLoading();
console.error('下载二维码失败', err);
wx.showToast({ title: '下载失败', icon: 'none' });
}
});
},
/**
* 复制邀请码到剪贴板
*/
copyInviteCode() {
if (!this.data.yaoqingma) {
wx.showToast({ title: '暂无邀请码', icon: 'none' });
return;
}
wx.setClipboardData({
data: this.data.yaoqingma,
success: () => {
wx.showToast({ title: '复制成功', icon: 'success' });
},
fail: () => {
wx.showToast({ title: '复制失败', icon: 'none' });
}
});
},
/**
* 生成专属海报(包含头像、二维码、昵称、标语)
*/
generateMyPoster() {
if (!this.data.qrcodeUrl) {
wx.showToast({ title: '请先生成二维码', icon: 'none' });
return;
}
wx.showLoading({ title: '生成海报中...', mask: true });
const ossUrl = app.globalData.ossImageUrl || '';
// 🔥 组长海报背景图路径beijing/zuzhangbeijing.jpg
const bgUrl = ossUrl + 'beijing/zuzhangbeijing.jpg';
const urls = [bgUrl, this.data.qrcodeUrl, this.data.avatarUrl];
// 并行加载所有图片
const promises = urls.map(url => this.loadImage(url));
Promise.all(promises)
.then((images) => {
wx.hideLoading();
this.setData({ showPosterCanvas: true }, () => {
// 确保 canvas 已渲染
setTimeout(() => {
this.drawPoster(images[0], images[1], images[2]);
}, 200);
});
})
.catch((err) => {
wx.hideLoading();
wx.showToast({ title: '图片加载失败', icon: 'none' });
console.error('图片加载失败', err);
});
},
/**
* 加载图片为本地路径(用于 canvas 绘制)
*/
loadImage(url) {
return new Promise((resolve, reject) => {
wx.getImageInfo({
src: url,
success: (res) => resolve(res.path),
fail: reject
});
});
},
/**
* 绘制海报
* @param {string} bgPath 背景图本地路径
* @param {string} qrPath 二维码本地路径
* @param {string} avatarPath 头像本地路径
*/
drawPoster(bgPath, qrPath, avatarPath) {
const ctx = wx.createCanvasContext('posterCanvas', this);
const query = wx.createSelectorQuery().in(this);
query.select('.poster-canvas').boundingClientRect(rect => {
if (!rect) {
wx.showToast({ title: '画布获取失败', icon: 'none' });
return;
}
const canvasWidth = rect.width;
const canvasHeight = rect.height;
// 1. 绘制背景
ctx.drawImage(bgPath, 0, 0, canvasWidth, canvasHeight);
// 🔥【位置调整】二维码向右上角移动一丢丢 (增加 margin 从 5 到 15)
const qrSize = 100;
const margin = 15; // 原来 5现在 15向右下各移一点但看起来更协调
const qrX = canvasWidth - qrSize - margin;
const qrY = canvasHeight - qrSize - margin;
ctx.drawImage(qrPath, qrX, qrY, qrSize, qrSize);
// 🔥【位置调整】头像也向右上移动一丢丢 (原来 margin 5现在 margin 15)
const avatarSize = 60;
const avatarMargin = 15;
const avatarX = avatarMargin + 10; // 原来 margin 5+20现在 15+20相当于右移10
const avatarY = canvasHeight - avatarSize - avatarMargin;
// 圆形头像裁剪
ctx.save();
ctx.beginPath();
ctx.arc(avatarX + avatarSize/2, avatarY + avatarSize/2, avatarSize/2, 0, 2 * Math.PI);
ctx.clip();
ctx.drawImage(avatarPath, avatarX, avatarY, avatarSize, avatarSize);
ctx.restore();
// 绘制昵称(右侧)
ctx.setFontSize(16);
ctx.setFillStyle('#333333'); // 根据背景图颜色可调整
ctx.setTextAlign('left');
let nick = this.data.nickName || '组长';
if (nick.length > 3) {
nick = nick.substring(0, 3) + '...';
}
const nameText = nick;
const textX = avatarX + avatarSize + 8;
const textY = avatarY + avatarSize/2 + 6;
ctx.fillText(nameText, textX, textY);
// 绘制邀请语
ctx.setFontSize(18);
ctx.setFillStyle('#9333ea'); // 金黄色,呼应组长主题
ctx.setTextAlign('left');
const slogan = '加入我的团队 ✦';
const sloganX = avatarX;
const sloganY = avatarY - 12;
ctx.fillText(slogan, sloganX, sloganY);
// 异步绘制
ctx.draw(false, () => {
wx.canvasToTempFilePath({
canvasId: 'posterCanvas',
success: (res) => {
this.setData({ posterImageTemp: res.tempFilePath });
},
fail: (err) => {
console.error('生成海报临时文件失败', err);
}
}, this);
});
}).exec();
},
/**
* 保存生成的海报
*/
savePoster() {
if (!this.data.posterImageTemp) {
wx.showToast({ title: '海报尚未生成', icon: 'none' });
return;
}
this.downloadAndSave(this.data.posterImageTemp);
},
/**
* 隐藏海报画布,返回主界面
*/
hidePoster() {
this.setData({ showPosterCanvas: false, posterImageTemp: '' });
},
/**
* 通用保存图片到相册(带权限检查)
*/
downloadAndSave(filePath) {
wx.getSetting({
success: (res) => {
if (!res.authSetting['scope.writePhotosAlbum']) {
wx.authorize({
scope: 'scope.writePhotosAlbum',
success: () => {
this._saveImage(filePath);
},
fail: () => {
wx.showModal({
title: '提示',
content: '需要您授权保存到相册',
success: (modalRes) => {
if (modalRes.confirm) {
wx.openSetting();
}
}
});
}
});
} else {
this._saveImage(filePath);
}
}
});
},
_saveImage(filePath) {
wx.saveImageToPhotosAlbum({
filePath: filePath,
success: () => {
wx.showToast({ title: '保存成功', icon: 'success' });
},
fail: (err) => {
console.error('保存失败', err);
wx.showToast({ title: '保存失败', icon: 'none' });
}
});
},
});