const POSTER_W = 750 const POSTER_H = 640 const QR_SIZE = 480 const TITLE_COLOR = '#165DFF' function resolveLocalImage(url) { return new Promise((resolve, reject) => { if (!url) { reject(new Error('empty url')) return } if (url.startsWith('data:') || url.startsWith('blob:') || url.startsWith('wxfile:') || url.startsWith('file:')) { resolve(url) return } if (!/^https?:\/\//i.test(url)) { resolve(url) return } uni.downloadFile({ url, success: (res) => { if (res.statusCode === 200) resolve(res.tempFilePath) else reject(new Error('download fail')) }, fail: reject }) }) } function drawPoster(ctx, tableNo, imagePath) { const titleY = 80 const qrTop = 130 ctx.setFillStyle('#ffffff') ctx.fillRect(0, 0, POSTER_W, POSTER_H) ctx.setFillStyle(TITLE_COLOR) ctx.setFontSize(32) ctx.setTextAlign('center') ctx.fillText(`${tableNo}桌号二维码`, POSTER_W / 2, titleY) ctx.drawImage(imagePath, (POSTER_W - QR_SIZE) / 2, qrTop, QR_SIZE, QR_SIZE) } function drawPoster2d(ctx, tableNo, img) { const titleY = 80 const qrTop = 130 ctx.fillStyle = '#ffffff' ctx.fillRect(0, 0, POSTER_W, POSTER_H) ctx.fillStyle = TITLE_COLOR ctx.font = '500 32px PingFang SC, sans-serif' ctx.textAlign = 'center' ctx.textBaseline = 'alphabetic' ctx.fillText(`${tableNo}桌号二维码`, POSTER_W / 2, titleY) ctx.drawImage(img, (POSTER_W - QR_SIZE) / 2, qrTop, QR_SIZE, QR_SIZE) } function savePosterH5(tableNo, imagePath) { return new Promise((resolve, reject) => { const img = new Image() img.crossOrigin = 'anonymous' img.onload = () => { try { const canvas = document.createElement('canvas') canvas.width = POSTER_W canvas.height = POSTER_H const ctx = canvas.getContext('2d') drawPoster2d(ctx, tableNo, img) canvas.toBlob((blob) => { if (!blob) { reject(new Error('export fail')) return } const link = document.createElement('a') const objectUrl = URL.createObjectURL(blob) link.href = objectUrl link.download = `${tableNo}-桌号二维码.png` document.body.appendChild(link) link.click() document.body.removeChild(link) URL.revokeObjectURL(objectUrl) resolve() }, 'image/png') } catch (err) { reject(err) } } img.onerror = () => reject(new Error('image load fail')) img.src = imagePath }) } function savePosterApp(tableNo, imagePath, canvasId, vm) { return new Promise((resolve, reject) => { const ctx = uni.createCanvasContext(canvasId, vm) drawPoster(ctx, tableNo, imagePath) ctx.draw(false, () => { setTimeout(() => { uni.canvasToTempFilePath({ canvasId, x: 0, y: 0, width: POSTER_W, height: POSTER_H, destWidth: POSTER_W, destHeight: POSTER_H, fileType: 'png', success: (res) => { uni.saveImageToPhotosAlbum({ filePath: res.tempFilePath, success: resolve, fail: reject }) }, fail: reject }, vm) }, 300) }) }) } /** * 合成桌号标题 + 小程序二维码海报并保存 * 布局:蓝色「XXX桌号二维码」+ 下方二维码,白底 */ export function saveQrPoster({ tableNo, qrUrl, canvasId = 'qrPosterCanvas', vm }) { return resolveLocalImage(qrUrl).then((localPath) => { // #ifdef H5 return savePosterH5(tableNo, localPath) // #endif // #ifndef H5 return savePosterApp(tableNo, localPath, canvasId, vm) // #endif }) } export const posterSize = { width: POSTER_W, height: POSTER_H }