// pages/invite-manager/invite-manager.js — 组长推广海报 import request from '../../utils/request.js'; import { getFullImageUrl, loadPosterPageConfig, posterInviteCacheKey, posterQrCacheKey, } from '../../utils/poster-page.js'; const app = getApp(); Page({ data: { qrcodeUrl: '', yaoqingma: '', isLoading: false, showPosterCanvas: false, posterImageTemp: '', avatarUrl: '', uid: '', nickName: '', posterBgUrl: '', }, async onLoad() { const { bgUrl, qrCacheKey } = await loadPosterPageConfig('zuzhang', app); this._qrCacheKey = qrCacheKey; this._inviteCacheKey = posterInviteCacheKey(); this.setData({ posterBgUrl: bgUrl }); 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(), }; } }, loadFromCache() { try { const key = this._qrCacheKey || posterQrCacheKey('zuzhang'); const relativeUrl = wx.getStorageSync(key); if (relativeUrl) { this.setData({ qrcodeUrl: getFullImageUrl(relativeUrl, app) }); } const inviteKey = this._inviteCacheKey || posterInviteCacheKey(); const yaoqingma = wx.getStorageSync(inviteKey); if (yaoqingma) this.setData({ yaoqingma }); } catch (error) { console.error('读取缓存失败', error); } }, 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 = getFullImageUrl(touxiang, app); } const uid = wx.getStorageSync('uid') || ''; const nickName = app.globalData.nicheng || wx.getStorageSync('nicheng') || '组长'; this.setData({ avatarUrl, uid, nickName }); }, 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 || {}; if (relativeUrl) { const key = this._qrCacheKey || posterQrCacheKey('zuzhang'); wx.setStorageSync(key, relativeUrl); this.setData({ qrcodeUrl: getFullImageUrl(relativeUrl, app) }); } if (yaoqingma) { const inviteKey = this._inviteCacheKey || posterInviteCacheKey(); wx.setStorageSync(inviteKey, yaoqingma); this.setData({ yaoqingma }); } wx.showToast({ title: '获取成功', icon: 'success' }); } else { wx.showToast({ title: res.data.msg || res.data.message || '获取失败', 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: () => { wx.hideLoading(); 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' }), }); }, generateMyPoster() { if (!this.data.qrcodeUrl) { wx.showToast({ title: '请先生成二维码', icon: 'none' }); return; } wx.showLoading({ title: '生成海报中...', mask: true }); const bgUrl = this.data.posterBgUrl; Promise.all([bgUrl, this.data.qrcodeUrl, this.data.avatarUrl].map((u) => this.loadImage(u))) .then((images) => { wx.hideLoading(); this.setData({ showPosterCanvas: true }, () => { setTimeout(() => this.drawPoster(images[0], images[1], images[2]), 200); }); }) .catch(() => { wx.hideLoading(); wx.showToast({ title: '图片加载失败', icon: 'none' }); }); }, loadImage(url) { return new Promise((resolve, reject) => { wx.getImageInfo({ src: url, success: (res) => resolve(res.path), fail: reject }); }); }, drawPoster(bgPath, qrPath, avatarPath) { const ctx = wx.createCanvasContext('posterCanvas', this); wx.createSelectorQuery().in(this).select('.poster-canvas').boundingClientRect((rect) => { if (!rect) { wx.showToast({ title: '画布获取失败', icon: 'none' }); return; } const canvasWidth = rect.width; const canvasHeight = rect.height; ctx.drawImage(bgPath, 0, 0, canvasWidth, canvasHeight); const qrSize = 100; const margin = 15; const qrX = canvasWidth - qrSize - margin; const qrY = canvasHeight - qrSize - margin; ctx.drawImage(qrPath, qrX, qrY, qrSize, qrSize); const avatarSize = 60; const avatarX = margin + 10; const avatarY = canvasHeight - avatarSize - margin; 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) + '...'; ctx.fillText(nick, avatarX + avatarSize + 8, avatarY + avatarSize / 2 + 6); ctx.setFontSize(18); ctx.setFillStyle('#ffaa00'); ctx.fillText('加入我的团队 ✦', avatarX, avatarY - 12); ctx.draw(false, () => { wx.canvasToTempFilePath({ canvasId: 'posterCanvas', success: (res) => this.setData({ posterImageTemp: res.tempFilePath }), }, 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: (m) => { if (m.confirm) wx.openSetting(); }, }); }, }); } else { this._saveImage(filePath); } }, }); }, _saveImage(filePath) { wx.saveImageToPhotosAlbum({ filePath, success: () => wx.showToast({ title: '保存成功', icon: 'success' }), fail: () => wx.showToast({ title: '保存失败', icon: 'none' }), }); }, });