chengjunhui před 1 měsícem
rodič
revize
092a293b02

+ 268 - 5
invitationCode/index.js

@@ -9,6 +9,7 @@ Page({
 	 */
 	data: {
 		appAssetsUrl: app.appAssetsUrl,
+		appAssetsUrl3: app.appAssetsUrl3,
 		bottomLeft: app.bottomLeft,
 		user: {},
 		name: '',
@@ -31,16 +32,17 @@ Page({
 		})
 		this.getCode();
 		wx.setNavigationBarTitle({
-			title: options.inviteCode ? '他/她的邀请码' : '我的邀请码'
+			title: options.inviteCode ? '他/她的会员码' : '我的会员码'
 		});
 	},
 	downloadQR() {
+		console.log('下载海报');
 		const that = this;
 		wx.getSetting({ //获取权限
 			success(res) {
 				console.log(res);
 				if (res.authSetting["scope.writePhotosAlbum"]) {
-					that.sendCode();
+					that.createPoster();
 				} else if (res.authSetting["scope.writePhotosAlbum"] == false) {
 					wx.showToast({
 						title: '请先授权相册',
@@ -49,14 +51,14 @@ Page({
 					wx.openSetting({
 						scope: "scope.writePhotosAlbum",
 						success() {
-							that.sendCode();
+							that.createPoster();
 						}
 					});
 				} else {
 					wx.authorize({
 						scope: "scope.writePhotosAlbum",
 						success() {
-							that.sendCode();
+							that.createPoster();
 						},
 						fail(e) {
 							console.log('未授权相册', e);
@@ -70,6 +72,267 @@ Page({
 			}
 		});
 	},
+
+	// 生成海报
+	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;
@@ -203,4 +466,4 @@ Page({
 			}
 		})
 	}
-})
+})

+ 23 - 25
invitationCode/index.wxml

@@ -1,25 +1,23 @@
-<!--invitationCode/index.wxml-->
-<view class="main" style="background-image: url({{appAssetsUrl}}/images/invitationCode/bg.png);">
-	<image mode="widthFix" src="{{appAssetsUrl}}/images/invitationCode/top-left.png" class="top-left"></image>
-	<image mode="widthFix" src="{{appAssetsUrl}}/images/invitationCode/top-right.png" class="top-right"></image>
-	<image mode="widthFix" src="{{appAssetsUrl}}/images/invitationCode/bottom-left.png" class="bottom-left" style="bottom: calc(113rpx + {{bottomLeft}}px);"></image>
-	<image mode="widthFix" src="{{appAssetsUrl}}/images/invitationCode/bottom-right.png" class="bottom-right" style="bottom: calc(113rpx + {{bottomLeft}}px);"></image>
-	
-	<view class="qrcode-box" style="background-image: url({{appAssetsUrl}}/images/invitationCode/qrcode-bg.png);height: calc(78vh + {{bottomLeft}}px);">
-		<image mode="aspectFill" src="{{memberphoto?memberphoto:(appAssetsUrl+'/images/bz1_nor.png')}}" class="head"></image>
-		<view class="name">{{name==null?'--':name}}</view>
-		<view class="code" bindtap="copyText">邀请码: {{inviteCode}} 复制</view>
-		<view class="qr-box">
-			<image src="{{invitationCodeImg}}"></image>
-		</view>
-		<view class="tip">邀请二维码</view>
-	</view>
-	<view class="bottom">
-		<button class="btn1" bindtap="downloadQR">保存图片</button>
-		<button class="btn2" style="margin-bottom: 20rpx;" bindtap="handleInvite">我的邀请</button>
-		<button class="btn2" open-type="share">分享</button>
-	</view>
-</view>
-<!-- <button class="custCare" open-type="contact" session-from="sessionFrom">
-	<image mode="aspectFill" src="{{appAssetsUrl}}/images/custCare.png"></image>
-</button> -->
+<!-- invitationCode/index.wxml -->
+<view class="main">
+    <view class="main-content" style="background-image: url({{appAssetsUrl3}}invitation_code_bg.png);">
+        <view class="user-info">
+            <image mode="aspectFill" src="{{memberphoto?memberphoto:(appAssetsUrl+'/images/bz1_nor.png')}}" class="head"></image>
+            <view class="right">
+                <view class="name">{{name==null?'--':name}}</view>
+                <view class="code">邀请码: {{inviteCode}}</view>
+            </view>
+        </view>
+        <view class="qrcode-info">
+            <image class="invitationCode" mode="widthFix" src="{{invitationCodeImg}}"></image>
+            <view class="text">青雲慧青年服务平台</view>
+        </view>
+    </view>
+    <view class="bottom">
+        <button class="btn btn1" bindtap="copyText">复制邀请码</button>
+        <button class="btn btn2" bindtap="downloadQR">保存海报</button>
+        <button class="btn btn3" bindtap="handleInvite">我的邀请</button>
+        <!-- <button class="btn btn3" open-type="share">分享</button> -->
+    </view>
+    <canvas canvas-id="myCanvas" style="position: fixed; top: -9999px; left: -9999px; width: 750px; height: 1334px;"></canvas>
+</view>

+ 84 - 104
invitationCode/index.wxss

@@ -1,124 +1,104 @@
 /* invitationCode/index.wxss */
-page{
-	overflow: hidden;
+page {
+  overflow: hidden;
 }
-.main{
-	height: 100vh;
-	background-size: cover;
-	background-position: center;
-	padding-top: 5vh;
-	box-sizing: border-box;
+.main {
+  height: 100vh;
+  background-size: cover;
+  background-position: center;
+  box-sizing: border-box;
+  padding: 46rpx 60rpx 225rpx 60rpx;
 }
-.top-left{
-	position: fixed;
-	top: -85rpx;
-	left: -70rpx;
-	width: 500rpx;
-	z-index: 100;
-}
-.top-right{
-	position: fixed;
-	top: -50rpx;
-	right: 0;
-	width: 300rpx;
-	transform: rotate(-12deg);
-	z-index: 100;
-}
-.bottom-left{
-	position: fixed;
-	bottom: 113rpx;
-	left: -50rpx;
-	width: 300rpx;
-	z-index: 100;
+
+.main-content {
+  height: 100%;
+  background-size: 100% 100%;
+  background-repeat: no-repeat;
+  position: relative;
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+  padding: 24rpx;
 }
-.bottom-right{
-	position: fixed;
-	bottom: 113rpx;
-	right: -60rpx;
-	width: 180rpx;
-	z-index: 100;
+
+.main-content .user-info {
+  display: flex;
+  box-sizing: border-box;
+  align-items: center;
 }
 
-.qrcode-box{
-	height: 78vh;
-	width: 94vw;
-	background-size: 100%,100%;
-	margin: 0 3vw -0 3vw;
-	background-repeat: no-repeat;
-	padding-top: 80rpx;
-	box-sizing: border-box;
-	text-align: center;
+.main-content .user-info .head {
+  width: 99rpx;
+  height: 99rpx;
+  border: 4rpx solid #ffffff;
+  border-radius: 50%;
+  flex-shrink: 0;
 }
-.qrcode-box .head{
-	width: 126rpx;
-	height: 126rpx;
-	background: white;
-	border-radius: 50%;
-	margin-bottom: 16rpx;
+
+.main-content .user-info .right {
+  flex: 1;
+  color: #ffffff;
+  margin-left: 25rpx;
+  font-size: 24rpx;
+  font-family: PingFang SC, PingFang SC-Regular;
+  font-weight: 400;
 }
-.qrcode-box .name{
-	font-size: 34rpx;
-	font-weight: 400;
-	color: #ffffff;
-	margin-bottom: 22rpx;
+
+.main-content .user-info .right .name {
+  margin-bottom: 13rpx;
 }
-.qrcode-box .code{
-	font-size: 28rpx;
-	font-weight: 400;
-	color: #ffffff;
-	margin-bottom: 100rpx;
+
+.main-content .qrcode-info {
+  text-align: center;
+  color: #ffffff;
+  font-size: 30rpx;
+  font-family: PingFang SC, PingFang SC-Regular;
+  font-weight: 400;
 }
 
-.qrcode-box .qr-box{
-	width: 402rpx;
-	height: 402rpx;
-	background: white;
-	box-sizing: border-box;
-	padding: 22rpx 25rpx;
-	margin: 0 auto;
-	margin-bottom: 24rpx;
+.main-content .qrcode-info .invitationCode{
+	margin-bottom: 18rpx;
+	width: 148rpx;
 	border-radius: 10rpx;
 }
-.qrcode-box .qr-box image{
-	height: 358rpx;
-	width: 352rpx;
-	background: #f6f6f6;
+
+.bottom {
+  position: fixed;
+  width: 750rpx;
+  left: 0;
+  bottom: 0;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 30rpx;
+  box-sizing: border-box;
 }
 
-.qrcode-box .tip{
-	font-size: 34rpx;
-	font-weight: 400;
-	color: #ffffff;
+.btn {
+  width: 220rpx;
+  height: 85rpx;
+  line-height: 85rpx;
+  border-radius: 44rpx;
+  font-size: 30rpx;
+  font-family: PingFang SC, PingFang SC-Regular;
+  font-weight: 400;
+  text-align: center;
+  box-sizing: border-box;
 }
 
-.bottom{
-	position: fixed;
-	bottom: 24rpx;
-	left: 50%;
-	transform: translateX(-50%);
-	/* height: 12vh; */
+.btn1 {
+  background: #ffffff;
+  border: 1px solid #cccccc;
+  color: #333333;
+}
+.btn2 {
+  background: #88bb26;
+  color: #ffffff;
+  border: 1px solid #88bb26;
 }
 
-.btn1{
-	width: 294rpx;
-	line-height: 60rpx;
-	background: #f1ffdf;
-	border: 1px solid #9ddb52;
-	border-radius: 31rpx;
-	text-align: center;
-	font-size: 28rpx;
-	font-weight: 700;
-	color: #9ddb52;
-	margin-bottom: 20rpx;
+.btn3 {
+  background: #2b58a5;
+  color: #ffffff;
+  border: 1px solid #2b58a5;
 }
-.btn2{
-	width: 294rpx;
-	line-height: 60rpx;
-	background: #9ddb52;
-	color: white;
-	border: 1px solid #9ddb52;
-	border-radius: 31rpx;
-	text-align: center;
-	font-size: 28rpx;
-	font-weight: 700;
-}

+ 0 - 38
pages/checkin/index_1874359642.js

@@ -37,44 +37,6 @@ Page({
           let list2 = res.data.singleTask ? [...res.data.singleTask] : [];
           // console.log([...list, ...list1, ...list2]);
           let dataList = [...list, ...list1, ...list2].map(v => { 
-            switch (v.taskName) {
-              case '邀请好友':
-                v.desc = '邀请好友获得积分';
-                break;
-              case '参与兼职':
-              case '参加兼职/成长会':
-                v.desc = '参与兼职获得积分';
-                break;
-                break;
-              case '每日签到':
-                v.desc = '每日签到获得积分';
-                break;
-              case '购买会员':
-              case '开通会员':
-                v.desc = '开通会员获得积分';
-                break;
-              case '学籍认证':
-              case '完成学籍认证':
-                v.desc = '学籍认证获得积分';
-                break;
-              case '完善资料':
-              case '完善个人资料':
-                v.desc = '完善个人资料获得积分';
-                break;
-              case '参与活动':
-                v.desc = '参与活动获得积分';
-                break;
-              case '观看广告':
-                v.desc = '观看广告获得积分';
-                break;
-              
-              case '分享小程序':
-                v.desc = '分享小程序可获得积分奖励';
-                break;
-              case '每日登录':
-                v.desc = '每日登录获得积分';
-                  break;
-            }
             return v
           })
           that.setData({

+ 2 - 2
pages/checkin/index_1874359642.wxml

@@ -62,8 +62,8 @@
             <image class="task-icon" wx:if="{{item.taskName=='每日登录'}}" mode="widthFix" src="{{appAssetsUrl3}}task-icon/icon_10.png"></image>
           </view>
           <view class="task-info">
-            <view class="task-title">{{item.taskName}}</view>
-            <view class="task-desc">{{item.desc}}</view>
+            <view class="task-title">{{item.taskTitle || ''}}</view>
+            <view class="task-desc">{{item.taskDesc || ''}}</view>
           </view>
         </view>
         <button open-type='share' wx:if="{{item.taskName=='分享小程序' && !item.complete}}" class="task-action {{item.complete ? 'complete' : ''}}">

+ 29 - 7
pages/login.js

@@ -77,14 +77,36 @@ Page({
         );
       },
     });
-    if (options.inviteCode) {
-      var inviteCode = decodeURIComponent(options.inviteCode);
-      // let inviteCode = options.inviteCode;
-      this.setData({
-        inviteCode,
-      });
+    // if (options.inviteCode) {
+    //   let sceneStr = decodeURIComponent(options.scene);
+    //   const params = new URLSearchParams(sceneStr);
+    //   const inviteCode = params.get('inviteCode');
+    //   // let inviteCode = options.inviteCode;
+    //   this.setData({
+    //     inviteCode,
+    //   });
+    // }
+    if (options.scene) {
+      // 解码scene参数
+      const sceneStr = decodeURIComponent(options.scene);
+      console.log('解码后的scene:', sceneStr);
+
+      // 解析参数格式:inviteCode=xxx
+      const params = new URLSearchParams(sceneStr);
+      const inviteCode = params.get('inviteCode');
+
+      if (inviteCode) {
+        console.log('获取到邀请码:', inviteCode);
+        // 在这里处理邀请码逻辑
+          this.setData({
+            inviteCode,
+          });
+      } else {
+        console.log('未找到邀请码参数');
+      }
     }
-    console.log(options, "options");
+
+    // console.log(options, "options");
   },
 
   reCode() {