Ai_GirlFriend/xuniYou/pages/mine/invite.vue

286 lines
12 KiB
Vue
Raw Normal View History

2026-01-31 19:15:41 +08:00
<template>
<view>
<view class="body">
<view class="list">
<view class="poster-container">
<canvas canvas-id="posterCanvas" class="poster-canvas" :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }"></canvas>
</view>
</view>
</view>
</view>
</template>
<script>
import {
} from '@/utils/api.js'
import notHave from '@/components/not-have.vue';
import topSafety from '@/components/top-safety.vue';
import tabBar from '@/components/tab-bar.vue';
export default {
components: {
notHave,
topSafety,
tabBar,
},
data() {
return {
canvasWidth: 300,
canvasHeight: 600, // 减小画布高度
posterImageUrl: '',
// 示例数据,实际应从用户信息获取
userInfo: {
name: '154****9090', // 原来的手机号改为用户名
phone: '邀请您加入聊天', // 原来的姓名改为邀请文案
avatar: '/static/images/avatar.png' // 头像路径
},
topImageRatio: 0, // 顶部图片的宽高比
topImageLocalPath: '', // 顶部图片本地路径
qrCodeLocalPath: '' // 二维码图片本地路径
}
},
onLoad() {
this.initCanvas();
},
onReady() {
// 页面准备完成后自动生成海报
setTimeout(() => {
this.downloadImages().then(() => {
this.generatePoster();
}).catch(err => {
console.error('下载图片失败:', err);
uni.hideLoading();
uni.showToast({
title: '图片加载失败',
icon: 'none'
});
});
}, 500);
},
methods: {
initCanvas() {
// 获取设备信息来自适应不同屏幕
const systemInfo = uni.getSystemInfoSync();
// 设置canvas宽度为屏幕宽度的90%,减少左右边距
this.canvasWidth = systemInfo.windowWidth * 0.9;
// 设置canvas高度
this.canvasHeight = this.canvasWidth * 2.0; // 减小长宽比到1.8:1
},
// 下载线上图片到本地临时文件
async downloadImages() {
return new Promise((resolve, reject) => {
uni.showLoading({
title: '图片加载中...'
});
// #ifdef H5
// H5 环境直接使用图片 URL不下载
const topImageUrl = 'https://nvlovers.oss-cn-qingdao.aliyuncs.com/uploads/20251226/cb61a8209c59166e5a56e9c5c470e8f1.png';
const qrCodeUrl = 'https://nvlovers.oss-cn-qingdao.aliyuncs.com/uploads/20251226/54a0da02080e49dbf2d6412791c58281.png';
this.topImageLocalPath = topImageUrl;
this.qrCodeLocalPath = qrCodeUrl;
// 获取顶部图片信息
uni.getImageInfo({
src: topImageUrl,
success: (res) => {
this.topImageRatio = res.width / res.height;
resolve();
},
fail: (err) => {
console.error('获取图片信息失败:', err);
this.topImageRatio = 3;
resolve();
}
});
// #endif
// #ifndef H5
// 非 H5 环境下载图片
2026-01-31 19:15:41 +08:00
Promise.all([
this.downloadImage('https://nvlovers.oss-cn-qingdao.aliyuncs.com/uploads/20251226/cb61a8209c59166e5a56e9c5c470e8f1.png'),
this.downloadImage('https://nvlovers.oss-cn-qingdao.aliyuncs.com/uploads/20251226/54a0da02080e49dbf2d6412791c58281.png')
]).then(([topImagePath, qrCodePath]) => {
this.topImageLocalPath = topImagePath;
this.qrCodeLocalPath = qrCodePath;
// 获取顶部图片信息
uni.getImageInfo({
src: topImagePath,
success: (res) => {
this.topImageRatio = res.width / res.height;
resolve();
},
fail: (err) => {
console.error('获取图片信息失败:', err);
this.topImageRatio = 3;
2026-01-31 19:15:41 +08:00
resolve();
}
});
}).catch(err => {
console.error('下载图片失败:', err);
reject(err);
});
// #endif
2026-01-31 19:15:41 +08:00
});
},
// 下载单个图片
downloadImage(url) {
return new Promise((resolve, reject) => {
uni.downloadFile({
url: url,
success: (res) => {
if (res.statusCode === 200) {
resolve(res.tempFilePath);
} else {
reject(new Error(`下载失败: ${res.statusCode}`));
}
},
fail: (err) => {
reject(err);
}
});
});
},
// 绘制圆角矩形的方法
drawRoundedRect(ctx, x, y, width, height, radius) {
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
ctx.fill();
},
generatePoster() {
uni.showLoading({
title: '海报生成中...'
});
const ctx = uni.createCanvasContext('posterCanvas', this);
// 清空画布
ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
// 绘制圆角背景
ctx.setFillStyle('#ffffff');
this.drawRoundedRect(ctx, 0, 0, this.canvasWidth, this.canvasHeight, 20);
// 计算居中位置
const centerX = this.canvasWidth / 2;
// 绘制顶部图片宽度与canvas一致高度自适应
const topImageWidth = this.canvasWidth;
// 根据图片原始宽高比计算高度
const topImageHeight = this.topImageRatio > 0 ? topImageWidth / this.topImageRatio : topImageWidth * 0.3;
const topImageX = 0;
const topImageY = 0; // 紧贴顶部
ctx.drawImage(this.topImageLocalPath, topImageX, topImageY, topImageWidth, topImageHeight);
// 绘制二维码,减小尺寸
const qrCodeSize = this.canvasWidth * 0.5; // 减小二维码尺寸
const qrCodeY = topImageHeight + 30; // 减少间距
const qrCodeX = (this.canvasWidth - qrCodeSize) / 2;
ctx.drawImage(this.qrCodeLocalPath, qrCodeX, qrCodeY, qrCodeSize, qrCodeSize);
// 绘制用户信息区域
const userInfoY = qrCodeY + qrCodeSize + 10;
const avatarSize = this.canvasWidth * 0.15;
// 计算头像和文字的整体高度,用于居中对齐
const textHeight = 40; // 文字区域高度估算
const totalHeight = Math.max(avatarSize, textHeight);
const avatarY = userInfoY + (totalHeight - avatarSize) / 2;
const textY = userInfoY + (totalHeight - textHeight) / 2;
// 头像居中对齐
const avatarX = (this.canvasWidth - (avatarSize + this.canvasWidth * 0.4)) / 2;
// 绘制头像
ctx.save();
ctx.beginPath();
ctx.arc(avatarX + avatarSize/2, avatarY + avatarSize/2, avatarSize/2, 0, 2 * Math.PI);
ctx.clip();
ctx.drawImage(this.userInfo.avatar, avatarX, avatarY, avatarSize, avatarSize);
ctx.restore();
// 绘制姓名和手机号(现在是手机号和邀请文案),与头像垂直居中对齐
const textAreaX = avatarX + avatarSize + 20;
ctx.setTextAlign('left');
ctx.setFontSize(18);
ctx.setFillStyle('#333333');
ctx.fillText(this.userInfo.name, textAreaX, textY + 20); // 垂直居中显示手机号
ctx.setFontSize(14);
ctx.setFillStyle('#999999');
ctx.fillText(this.userInfo.phone, textAreaX, textY + 45); // 垂直居中显示邀请文案
// 绘制完成,导出图片
ctx.draw(false, () => {
// 延迟执行以确保绘制完成
setTimeout(() => {
uni.canvasToTempFilePath({
canvasId: 'posterCanvas',
success: (res) => {
this.posterImageUrl = res.tempFilePath;
uni.hideLoading();
uni.showToast({
title: '海报生成成功',
icon: 'success'
});
},
fail: (err) => {
console.error('生成海报失败:', err);
uni.hideLoading();
uni.showToast({
title: '海报生成失败',
icon: 'none'
});
}
}, this);
}, 3000);
});
}
}
}
</script>
<style>
page {
background: #FFFFFF;
}
</style>
<style>
.body {
position: relative;
padding: 0 20rpx; /* 减少左右padding */
}
.list {
position: relative;
margin: 20rpx 0 0 0;
}
.poster-container {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 30rpx;
}
.poster-canvas {
background-color: #f5f5f5;
/* 移除之前的圆角设置因为现在在canvas中绘制 */
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
}
</style>