From ce78ac2c24943797adbbcf14223bcd6397c54763 Mon Sep 17 00:00:00 2001
From: tx <2622874537@qq.com>
Date: Mon, 23 Sep 2024 18:03:27 +0800
Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E7=A4=BA=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 package-lock.json                   |  11 ++
 package.json                        |   1 +
 pages/index/index.vue               | 130 ++++++++++++++++------
 pages_admin/order/device_detail.vue | 162 +++++++++++++++++++++++++---
 4 files changed, 258 insertions(+), 46 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 298c152..a4a5313 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,6 +10,7 @@
       "license": "ISC",
       "dependencies": {
         "fast-xml-parser": "^4.0.12",
+        "uqrcodejs": "^4.0.7",
         "uview-ui": "^1.8.8"
       },
       "devDependencies": {
@@ -274,6 +275,11 @@
         "browserslist": ">= 4.21.0"
       }
     },
+    "node_modules/uqrcodejs": {
+      "version": "4.0.7",
+      "resolved": "https://registry.npmmirror.com/uqrcodejs/-/uqrcodejs-4.0.7.tgz",
+      "integrity": "sha512-84+aZmD2godCVI+93lxE3YUAPNY8zAJvNA7xRS7R7U+q57KzMDepBSfNCwoRUhWOfR6eHFoAOcHRPwsP6ka1cA=="
+    },
     "node_modules/uview-ui": {
       "version": "1.8.8",
       "resolved": "https://registry.npmmirror.com/uview-ui/-/uview-ui-1.8.8.tgz",
@@ -404,6 +410,11 @@
         "picocolors": "^1.0.1"
       }
     },
+    "uqrcodejs": {
+      "version": "4.0.7",
+      "resolved": "https://registry.npmmirror.com/uqrcodejs/-/uqrcodejs-4.0.7.tgz",
+      "integrity": "sha512-84+aZmD2godCVI+93lxE3YUAPNY8zAJvNA7xRS7R7U+q57KzMDepBSfNCwoRUhWOfR6eHFoAOcHRPwsP6ka1cA=="
+    },
     "uview-ui": {
       "version": "1.8.8",
       "resolved": "https://registry.npmmirror.com/uview-ui/-/uview-ui-1.8.8.tgz",
diff --git a/package.json b/package.json
index 1e55a81..c54577e 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
   "homepage": "https://github.com/lchighpass/lchighpass-speaking#readme",
   "dependencies": {
     "fast-xml-parser": "^4.0.12",
+    "uqrcodejs": "^4.0.7",
     "uview-ui": "^1.8.8"
   },
   "devDependencies": {
diff --git a/pages/index/index.vue b/pages/index/index.vue
index b2a4022..b4a10dc 100644
--- a/pages/index/index.vue
+++ b/pages/index/index.vue
@@ -946,6 +946,7 @@
 				导航去这里
 			</view>
 		</view>
+		
 		<view class="fixdivce" v-if="showdevice&&false">
 			<view class="scrollable-content">
 				<view class="divce_li" v-for="(item,index) in nearbyMarkers" :key="index" @click="tapsn(item.sn)">
@@ -970,6 +971,7 @@
 				</view>
 			</view>
 		</view>
+		<u-toast ref="uToast" />
 	</view>
 </template>
 
@@ -1588,53 +1590,117 @@
 								// 	});
 								// } else
 								if (this.deviceInfos.status == 0) {
-									uni.showToast({
+									// uni.showToast({
+									// 	title: '车辆未上架,请使用其他车辆',
+									// 	icon: 'none',
+									// 	duration: 4000
+									// });
+									this.$refs.uToast.show({
 										title: '车辆未上架,请使用其他车辆',
-										icon: 'none',
-										duration: 4000
-									});
+										// 如果不传此type参数,默认为default,也可以手动写上 type: 'default'
+										// type: 'warning', 
+										// 如果不需要图标,请设置为false
+										duration: 1000*2
+										// icon: false
+									})
 								} else if (this.deviceInfos.status == 2) {
-									uni.showToast({
+									// uni.showToast({
+									// 	title: '车辆预约中,请使用其他车辆',
+									// 	icon: 'none',
+									// 	duration: 4000
+									// });
+									this.$refs.uToast.show({
 										title: '车辆预约中,请使用其他车辆',
-										icon: 'none',
-										duration: 4000
-									});
+										// 如果不传此type参数,默认为default,也可以手动写上 type: 'default'
+										// type: 'warning', 
+										// 如果不需要图标,请设置为false
+										duration: 1000*2
+										// icon: false
+									})
 								} else if (this.deviceInfos.status == 3) {
-									uni.showToast({
+									// uni.showToast({
+									// 	title: '车辆骑行中,请使用其他车辆',
+									// 	icon: 'none',
+									// 	// duration: 4000
+									// });
+									this.$refs.uToast.show({
 										title: '车辆骑行中,请使用其他车辆',
-										icon: 'none',
-										duration: 4000
-									});
+										// 如果不传此type参数,默认为default,也可以手动写上 type: 'default'
+										// type: 'warning', 
+										// 如果不需要图标,请设置为false
+										duration: 1000*2
+										// icon: false
+									})
 								} else if (this.deviceInfos.status == 4) {
-									uni.showToast({
+									// uni.showToast({
+									// 	title: '车辆临时锁车中,请使用其他车辆',
+									// 	icon: 'none',
+									// 	// duration: 4000
+									// });
+									this.$refs.uToast.show({
 										title: '车辆临时锁车中,请使用其他车辆',
-										icon: 'none',
-										duration: 4000
-									});
+										// 如果不传此type参数,默认为default,也可以手动写上 type: 'default'
+										// type: 'warning', 
+										// 如果不需要图标,请设置为false
+										duration: 1000*2
+										// icon: false
+									})
 								} else if (this.deviceInfos.status == 6) {
-									uni.showToast({
+									// uni.showToast({
+									// 	title: '车辆调度中,请使用其他车辆',
+									// 	icon: 'none',
+									// 	// duration: 4000
+									// });
+									this.$refs.uToast.show({
 										title: '车辆调度中,请使用其他车辆',
-										icon: 'none',
-										duration: 4000
-									});
+										// 如果不传此type参数,默认为default,也可以手动写上 type: 'default'
+										// type: 'warning', 
+										// 如果不需要图标,请设置为false
+										duration: 1000*2
+										// icon: false
+									})
 								} else if (this.deviceInfos.status == 8) {
-									uni.showToast({
+									// uni.showToast({
+									// 	title: '车辆下线中,请使用其他车辆',
+									// 	icon: 'none',
+									// 	duration: 4000
+									// });
+									this.$refs.uToast.show({
 										title: '车辆下线中,请使用其他车辆',
-										icon: 'none',
-										duration: 4000
-									});
+										// 如果不传此type参数,默认为default,也可以手动写上 type: 'default'
+										// type: 'warning', 
+										// 如果不需要图标,请设置为false
+										duration: 1000*2
+										// icon: false
+									})
 								} else if (this.deviceInfos.status == 9) {
-									uni.showToast({
+									// uni.showToast({
+									// 	title: '车辆已废弃,请使用其他车辆',
+									// 	icon: 'none',
+									// 	duration: 4000
+									// });
+									this.$refs.uToast.show({
 										title: '车辆已废弃,请使用其他车辆',
-										icon: 'none',
-										duration: 4000
-									});
+										// 如果不传此type参数,默认为default,也可以手动写上 type: 'default'
+										// type: 'warning', 
+										// 如果不需要图标,请设置为false
+										duration: 1000*2
+										// icon: false
+									})
 								} else if (this.deviceInfos.status == 7) {
-									uni.showToast({
+									// uni.showToast({
+									// 	title: '车辆未上线,请使用其他车辆',
+									// 	icon: 'none',
+									// 	duration: 4000
+									// });
+									this.$refs.uToast.show({
 										title: '车辆未上线,请使用其他车辆',
-										icon: 'none',
-										duration: 4000
-									});
+										// 如果不传此type参数,默认为default,也可以手动写上 type: 'default'
+										// type: 'warning', 
+										// 如果不需要图标,请设置为false
+										duration: 1000*2
+										// icon: false
+									})
 								} else if (this.deviceInfos.status == 1) {
 				
 									if (this.areaInfo.areaId != res.data.areaId) {
diff --git a/pages_admin/order/device_detail.vue b/pages_admin/order/device_detail.vue
index 95a773f..c2b8e36 100644
--- a/pages_admin/order/device_detail.vue
+++ b/pages_admin/order/device_detail.vue
@@ -199,6 +199,9 @@
 			<view class="btn" @click="tipshow=true" v-if="info.type==2">
 				换电处理
 			</view> -->
+			<view class="btn" @click="generateQrcode()">
+				设备二维码
+			</view>
 		</view>
 		<u-mask :show="false" @click="show = false" :z-index='100' />
 
@@ -284,6 +287,15 @@
 				</view>
 			</view>
 		</view>
+		<u-mask :show="showqr" @click="closeQr()" :z-index='100' />
+		<view class="tip_box" v-if="showqr" >
+			<view class="ewm" style="padding-top: 50rpx;">
+				<canvas id="qrcode" canvas-id="qrcode" style="width: 350rpx;height:350rpx;margin-left: 164rpx;" />
+			</view>
+			<view class="saveQr" @click="saveQrcode()">
+				保存二维码
+			</view>
+		</view>
 		<u-mask :show="showbtntip" @click="closevehicle()" :z-index='100' />
 		<view class="tip_box" v-if="showbtntip">
 			<view class="top" v-if="showbtntip">
@@ -312,6 +324,7 @@
 </template>
 
 <script>
+	import UQRCode from 'uqrcodejs';
 	const app = getApp();
 	var xBlufi = require("@/utils/blufi/xBlufi.js");
 	let _this = null;
@@ -381,7 +394,10 @@
 				showvehicle: false,
 				vehicleNum: '',
 				showbtntip: false,
-				btnnum: null
+				btnnum: null,
+				showqr: false,
+				canvasWidth: 300,
+				deptId:null
 
 
 			}
@@ -389,7 +405,7 @@
 		onLoad(e) {
 			this.sn = e.id
 			this.deviceInfo()
-
+			this.deptId = uni.getStorageSync('deptId');
 
 		},
 		onUnload: function() {
@@ -416,6 +432,111 @@
 
 		},
 		methods: {
+			closeQr(){
+				 this.showqr=false
+			},
+			generateQrcode() {
+			  const qr = new UQRCode();
+				if(this.deptId==100){
+					  qr.data = 'https://dche.ccttiot.com?sn=' + this.deviceInfos.sn;
+				}else if(this.deptId==101){
+					  qr.data = 'https://dianche.chuantewulian.cn?sn=' + this.deviceInfos.sn;
+				}
+			    qr.size = 150;
+			    // 创建 canvas 上下文
+			    const ctx = uni.createCanvasContext('qrcode', this);
+			
+			    // 设置 qr 的 canvas 上下文
+			    qr.canvasContext = ctx;
+			    qr.make();  // 生成二维码数据
+			
+			    // 绘制二维码
+			    qr.drawCanvas();
+			
+			    // 手动绘制二维码的同时添加设备序列号(sn)
+			   const sn = this.deviceInfos && this.deviceInfos.sn ? 'SN: ' + this.deviceInfos.sn : 'SN未知';
+			
+			    // 延迟绘制,确保二维码绘制完成后再绘制文字
+			    setTimeout(() => {
+			        // 添加sn到二维码下面
+			        ctx.setFontSize(12);  // 设置字体大小
+			        ctx.setFillStyle('black');  // 设置字体颜色
+			        ctx.setTextAlign('center');  // 设置文本居中
+			        ctx.fillText(sn, qr.size / 2, qr.size + 20);  // 在二维码下方绘制sn,偏移20像素
+			
+			        // 保留二维码,绘制文字
+			        ctx.draw(true);  // 传入 true,保留之前绘制的内容
+			    }, 100);  // 延迟100毫秒确保二维码绘制完成
+			    this.showqr = true;
+			},
+			// generateQrcode() {
+			//    const qr = new UQRCode();
+			//       qr.data = 'https://znb.ccttiot.com/w?sn=' + this.deviceInfos.sn;
+			//       qr.size = 157;
+			  
+			//       // 创建 canvas 上下文
+			//       const ctx = uni.createCanvasContext('qrcode', this);
+			  
+			//       // 设置 qr 的 canvas 上下文
+			//       qr.canvasContext = ctx;
+			//       qr.make();  // 生成二维码数据
+			  
+			//       // 计算绘制二维码的起始位置
+			//       const startX = (uni.getSystemInfoSync().windowWidth - qr.size) / 2;  // 计算中心位置
+			  
+			//       // 绘制二维码
+			//       qr.drawCanvas(startX, 0);  // 指定绘制起始位置
+			  
+			//       // 手动绘制二维码的同时添加设备序列号(sn)
+			//       const sn = this.deviceInfos && this.deviceInfos.sn ? 'SN: ' + this.deviceInfos.sn : 'SN未知';
+			  
+			//       // 延迟绘制,确保二维码绘制完成后再绘制文字
+			//       setTimeout(() => {
+			//           // 添加sn到二维码下面
+			//           ctx.setFontSize(12);  // 设置字体大小
+			//           ctx.setFillStyle('black');  // 设置字体颜色
+			//           ctx.setTextAlign('center');  // 设置文本居中
+			//           ctx.fillText(sn, uni.getSystemInfoSync().windowWidth / 2, qr.size + 20);  // 在二维码下方绘制sn,居中
+			  
+			//           // 保留二维码,绘制文字
+			//           ctx.draw(true);  // 传入 true,保留之前绘制的内容
+			//       }, 100);  // 延迟100毫秒确保二维码绘制完成
+			  
+			//       this.showqr = true;	
+			// },
+			saveQrcode() {
+				uni.canvasToTempFilePath({
+				        canvasId: 'qrcode',
+				        x: -10, // 裁剪区域的 x
+				        y: 0, // 裁剪区域的 y
+				        width: 155 , // 裁剪区域的宽度,包含边距
+				        height: 157+15, // 裁剪区域的高度,包含边距
+				        success: (res) => {
+				            uni.saveImageToPhotosAlbum({
+				                filePath: res.tempFilePath,
+				                success: () => {
+				                    uni.showToast({
+				                        title: '保存成功',
+				                        icon: 'success'
+				                    });
+				                    this.showqr = false;
+				                },
+				                fail: (err) => {
+				                    uni.showToast({
+				                        title: '保存失败',
+				                        icon: 'none'
+				                    });
+				                }
+				            });
+				        },
+				        fail: (err) => {
+				            uni.showToast({
+				                title: '生成二维码失败',
+				                icon: 'none'
+				            });
+				        }
+				    });
+			},
 			closeshowtip() {
 				this.showbtntip = false
 			},
@@ -1234,7 +1355,7 @@
 
 			},
 			deviceInfo() {
-				this.markers=[]
+				this.markers = []
 				this.$u.get('/app/device/info?sn=' + this.sn).then((res) => {
 					console.log(res, 'rererer');
 					if (res.code === 200) {
@@ -1300,8 +1421,8 @@
 								latitude: parseFloat(this.deviceInfos.latitude),
 								longitude: parseFloat(this.deviceInfos.longitude),
 								// title: item.deviceName,
-							width: 40,
-							height: 47,
+								width: 40,
+								height: 47,
 								iconPath: this.deviceInfos.onlineStatus == 0 ?
 									'https://lxnapi.ccttiot.com/bike/img/static/uzhMeExOQJbMcZtrfGUV' :
 									'https://lxnapi.ccttiot.com/bike/img/static/uheL17wVZn24BwCwEztT',
@@ -1321,8 +1442,8 @@
 								latitude: parseFloat(this.deviceInfos.latitude),
 								longitude: parseFloat(this.deviceInfos.longitude),
 								// title: item.deviceName,
-							width: 40,
-							height: 47,
+								width: 40,
+								height: 47,
 								iconPath: this.deviceInfos.onlineStatus == 0 ?
 									'https://lxnapi.ccttiot.com/bike/img/static/uR3DQEssiK62ovhh88y8' :
 									'https://lxnapi.ccttiot.com/bike/img/static/u460R1NKWHEpHbt0U4H7',
@@ -1363,8 +1484,8 @@
 								latitude: parseFloat(this.deviceInfos.latitude),
 								longitude: parseFloat(this.deviceInfos.longitude),
 								// title: item.deviceName,
-							width: 40,
-							height: 47,
+								width: 40,
+								height: 47,
 								// joinCluster: true,
 								iconPath: this.deviceInfos.onlineStatus == 0 ?
 									'https://lxnapi.ccttiot.com/bike/img/static/uRod2zf3t9dAOYafWoWt' :
@@ -1385,13 +1506,13 @@
 								latitude: parseFloat(this.deviceInfos.latitude),
 								longitude: parseFloat(this.deviceInfos.longitude),
 								// title: item.deviceName,
-							width: 40,
-							height: 47,
+								width: 40,
+								height: 47,
 								iconPath: this.deviceInfos.onlineStatus == 0 ?
 									'https://lxnapi.ccttiot.com/bike/img/static/uhZudZM3nEKj0tYKlho2' :
 									'https://lxnapi.ccttiot.com/bike/img/static/ujur6TezvPf4buFAqPHo',
 								callout: {
-									content:  '' + this.deviceInfos.remainingPower + '%', 
+									content: '' + this.deviceInfos.remainingPower + '%',
 									color: '#2679D1', // 修改为文字颜色
 									fontSize: 10, // 修改为文字大小
 									borderRadius: 10, // 修改为气泡圆角大小
@@ -1412,7 +1533,7 @@
 									'https://lxnapi.ccttiot.com/bike/img/static/ucBKG3ebYRAToVweJihu' :
 									'https://lxnapi.ccttiot.com/bike/img/static/uyK7Vg4Lu8xb3oNVuG2l',
 								callout: {
-									content:  this.deviceInfos.remainingPower + '%', // 修改为你想要显示的文字内容
+									content: this.deviceInfos.remainingPower + '%', // 修改为你想要显示的文字内容
 									color: '#ffffff', // 修改为文字颜色
 									fontSize: 10, // 修改为文字大小
 									borderRadius: 10, // 修改为气泡圆角大小
@@ -1660,7 +1781,20 @@
 			border-radius: 30rpx 30rpx 30rpx 30rpx;
 			z-index: 110;
 			padding-bottom: 100rpx;
-
+			.saveQr{
+				margin: 0 auto;
+				margin-top: 30rpx;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+				width: 502rpx;
+				height: 68rpx;
+				background: #4C97E7;
+				border-radius: 10rpx 10rpx 10rpx 10rpx;
+				font-weight: 500;
+				font-size: 36rpx;
+				color: #FFFFFF;
+			}
 			.top {
 				padding: 52rpx 38rpx 42rpx 36rpx;