Преглед изворни кода

添加声像记录拍照点拍照图片清晰度检测

ZhangLeo пре 2 дана
родитељ
комит
d3549cbea9
2 измењених фајлова са 224 додато и 140 уклоњено
  1. 1 1
      pages/work/download/TaskCamera-scan-code.uvue
  2. 223 139
      pages/work/record/camera-scan-code.uvue

+ 1 - 1
pages/work/download/TaskCamera-scan-code.uvue

@@ -313,7 +313,7 @@
 						  score = result?.['score'] as number
 						  level = result?.['level'] as string
 					      uni.hideLoading();
-						  const customThreshold = 3000;
+						  const customThreshold = 3500;
 						  const isClearWithCustomThreshold = score > customThreshold;
 						  if (!isClearWithCustomThreshold) {
 						  	// 不清晰的图片,提示用户

+ 223 - 139
pages/work/record/camera-scan-code.uvue

@@ -5,58 +5,53 @@
 		<!--
     <camera style="width: 100%; height: 300px;" :resolution="'high'" :mode="'scanCode'" @scancode="handleScanCode">
     </camera> -->
-	<view class="my-page">
-		<swiper class="swiper-box my-swiper" :current="swiperDotIndex" :indicator-dots="true">
-			<swiper-item v-for="item in data">
-				<view class="swiper-item" @tap="previewSingleImage(item.image)">
-					<image class="my-image" :src="item.image" mode="aspectFill" />
+		<view class="my-page">
+			<swiper class="swiper-box my-swiper" :current="swiperDotIndex" :indicator-dots="true">
+				<swiper-item v-for="item in data">
+					<view class="swiper-item" @tap="previewSingleImage(item.image)">
+						<image class="my-image" :src="item.image" mode="aspectFill" />
+					</view>
+					<view>
+						<text class="demo-view-label">{{ item?.name ?? ''}}</text>
+					</view>
+				</swiper-item>
+			</swiper>
+
+			<view class="camera-scan-code-table">
+				<view class="camera-scan-code-table-pair" v-if="joinRecord.imgname!=''">
+					<view class="camera-scan-code-table-pair-label">
+						<text>已存图片(最多能存{{joinRecord.num}}张)</text>
+					</view>
+					<view class="camera-scan-code-table-pair-value" v-for="itemName in joinRecord.imgname.split(',')">
+						<text class="txt">{{ itemName }}</text>
+					</view>
 				</view>
-				<view>
-					<text class="demo-view-label">{{ item?.name ?? ''}}</text>
-				</view>
-			</swiper-item>
-		</swiper>
-	
-
-		<view class="camera-scan-code-back-wrap" v-show="false">
-			<button class="btn block bg-blue lg round" @click="chooseImage">
-				浏览相册
-			</button>
-		</view>
 
-		<view class="camera-scan-code-table">
-			<view class="camera-scan-code-table-pair" v-if="joinRecord.imgname!=''">
-				<view class="camera-scan-code-table-pair-label">
-					<text>已存图片(最多能存{{joinRecord.num}}张)</text>
-				</view>
-				<view class="camera-scan-code-table-pair-value" v-for="itemName in joinRecord.imgname.split(',')"   >					
-					<text class="txt">{{ itemName }}</text>
+				<view class="camera-scan-code-table-pair">
+					<view class="camera-scan-code-table-pair-label">
+						<text>待存图片</text>
+					</view>
+					<view class="camera-scan-code-table-pair-value">
+						<text class="txt">{{ dyImgName+"-"+minAvailableNumber+".jpg"}}</text>
+					</view>
 				</view>
 			</view>
 
-			<view class="camera-scan-code-table-pair">
-				<view class="camera-scan-code-table-pair-label">
-					<text>待存图片</text>
-				</view>
-				<view class="camera-scan-code-table-pair-value">					
-					<text class="txt">{{ dyImgName+"-"+minAvailableNumber+".jpg"}}</text>
-				</view>
-			</view>
-		</view>
 
+			<view class="camera-scan-code-back-wrap">
+				<button class="btn block bg-blue lg round" @click="saveImage" style="min-width: 250px;">
+					保存图片
+				</button>
+			</view>
 
-		<view class="camera-scan-code-back-wrap">
-			<button class="btn block bg-blue lg round" @click="saveImage" style="min-width: 250px;">
-				保存图片
-			</button>
-		</view>
+			<view class="camera-scan-code-back-wrap">
+				<button type="default" class="btn bg-blue round" @click="navigateBack">返回拍照</button>
+				<button type="default" class="btn bg-blue round" @click="navigateExit">退出拍照</button>
 
-		<view class="camera-scan-code-back-wrap">
-			<button type="default" class="btn bg-blue round" @click="navigateBack">返回拍照</button>
-		    <button type="default" class="btn bg-blue round" @click="navigateExit">退出拍照</button>
-		    
+			</view>
 		</view>
-    </view>	
+		<canvas id="canvas"
+			style="position: absolute; left: -9999px; top: -9999px; width: 300px; height: 300px;"></canvas>
 	<!-- #ifdef APP -->
 	</scroll-view>
 	<!-- #endif -->
@@ -73,6 +68,7 @@
 		checked : boolean
 	}
 	import { getJoinList, JoinRecord, updateData } from '@/api/work';
+	import { BitmapUtils } from '@/nativeplugins/opencv/android/uts/BitmapUtils.uts'
 	export default {
 		data() {
 			return {
@@ -107,7 +103,10 @@
 					image: '/static/images/banner/banner01.png',
 					name: 'banner01.png',
 					checked: true
-				}] as ImageItem[]
+				}] as ImageItem[],
+				canvas: null as UniCanvasElement | null,
+				canvasContext: null as CanvasContext | null,
+				renderingContext: null as CanvasRenderingContext2D | null,
 			}
 		},
 		onBackPress() {
@@ -160,6 +159,22 @@
 			if (maxcount != '') {
 				this.maxcount = parseInt(maxcount)
 			}
+
+			// 异步调用方式, 跨平台写法
+			uni.createCanvasContextAsync({
+				id: 'canvas',
+				component: this,
+				success: (context : CanvasContext) => {
+					this.canvasContext = context;
+					this.renderingContext = context.getContext('2d')!;
+					this.canvas = this.renderingContext!.canvas;
+				}
+			})
+		},
+		onReady() {
+			// 确认canvas元素可正常使用
+			// UTS中不支持uni.createCanvasContext,改用其他方式验证
+			console.log('Canvas元素已准备就绪');
 		},
 		methods: {
 			navigateBack() {
@@ -191,8 +206,85 @@
 					}
 				});
 			},
-			saveImage() {
+			async saveImage() {
 				//保存图片进入相册文件
+				const saveImageToDatabase = () => {
+					let updateImgs = ''
+					let updateNames = ''
+					let updateStatus = ''
+
+					// 动态生成最小的可用图片编号
+					const getMinAvailableNumber = () => {
+						if (this.imgArrLen === 0) return 1;
+
+						// 从已有的图片名称中提取编号
+						const existingNumbers = new Set<number>();
+						const imgNames = this.joinRecord.imgname.split(',');
+
+						imgNames.forEach((name : string) => {
+							if (name != '') {
+								// 提取图片名称中的数字部分
+								const match = name.match(/-(\d+)\.jpg$/);
+								if (match != null && match[1] != null) {
+									const numStr = match[1] as string;
+									existingNumbers.add(parseInt(numStr));
+								}
+							}
+						});
+
+						// 查找1到所需图片数量之间最小的未使用编号
+						for (let i = 1; i <= this.joinRecord.num; i++) {
+							if (!existingNumbers.has(i)) {
+								return i;
+							}
+						}
+
+						// 如果1到所需数量都被使用了,则使用当前数量+1
+						return this.imgArrLen + 1;
+					};
+
+					const minAvailableNumber = getMinAvailableNumber();
+					const newImgName = this.dyImgName + "-" + minAvailableNumber + ".jpg";
+					const relativePath = `/uploadImgs/${newImgName}`
+
+					if (this.imgArrLen == 0) {
+						updateImgs = relativePath
+						updateNames = newImgName;
+					} else {
+						updateImgs = this.joinRecord.urlpdt + "," + relativePath
+						updateNames = this.joinRecord.imgname + "," + newImgName;
+					}
+
+					let updatedData = "imgname='" + updateNames + "',urlpdt='" + updateImgs + "'"
+
+					if (this.joinRecord.num === this.imgArrLen + 1) {
+						updateStatus = "status='3'"
+						updatedData = updatedData + "," + updateStatus
+					} else if (this.joinRecord.status === 1) {
+						updateStatus = "status='2'"
+						updatedData = updatedData + "," + updateStatus
+					}
+					console.log(updatedData)
+
+					updateData('app_media_record', updatedData, 'sxid', this.recordId.toString()).then((res : UTSJSONObject) => {
+						let data = res?.['data'] as boolean ?? false
+						if (data != null && data == true) {
+							uni.showToast({
+								title: "保存成功!",
+							});
+							const newPath = `${uni.env.USER_DATA_PATH}/uploadImgs/${newImgName}`
+							this.renameFile(this.path, newPath)
+
+							uni.navigateTo({
+								url: `/pages/work/record/RecordList?part=${this.joinRecord.part}&senum=${this.senum}&pid=${this.joinRecord.pid}`,
+								// 修改动画方向为从左到右退回
+								animationType: 'slide-in-left', // 使用从左到右滑出的动画效果
+								animationDuration: 300 // 动画持续时间,单位ms
+							})
+						}
+					});
+				}
+
 				if (this.path == '') {
 					uni.showToast({
 						title: '没有拍照文件',
@@ -209,80 +301,72 @@
 					});
 					return;
 				}
-				let updateImgs = ''
-				let updateNames = ''
-				let updateStatus = ''
-
-				// 动态生成最小的可用图片编号
-				const getMinAvailableNumber = () => {
-					if (this.imgArrLen === 0) return 1;
-
-					// 从已有的图片名称中提取编号
-					const existingNumbers = new Set<number>();
-					const imgNames = this.joinRecord.imgname.split(',');
-
-					imgNames.forEach((name : string) => {
-						if (name != '') {
-							// 提取图片名称中的数字部分
-							const match = name.match(/-(\d+)\.jpg$/);
-							if (match != null && match[1] != null) {
-								const numStr = match[1] as string;
-								existingNumbers.add(parseInt(numStr));
-							}
-						}
-					});
+				// 检测图片清晰度
+				try {
+					uni.showLoading({ title: '检测图片清晰度...' });
+					this.renderingContext!.clearRect(0, 0, 1000, 1000)
+					let image = this.canvasContext!.createImage();
+					image.src = this.path
+					let score = 0
+					let level = ""
+					image.onload = () => {
+
+						this.renderingContext?.drawImage(image, 0, 0, image.width, image.height);
+						console.log(image.width)
+						console.log(image.height)
+						setTimeout(() => {
+							try {
+								// 将canvas内容转换为base64格式
+								const base64Data = this.canvasContext!.toDataURL();
+								const result = BitmapUtils.checkImageClarityFromBase64(base64Data)
+								console.log(result)
+								console.log("清晰度检测结果得分:", result?.['score']);
+								score = result?.['score'] as number
+								level = result?.['level'] as string
+								uni.hideLoading();
+								const customThreshold = 3500;
+								const isClearWithCustomThreshold = score > customThreshold;
+								if (!isClearWithCustomThreshold) {
+									// 不清晰的图片,提示用户
+									uni.showModal({
+										title: '提示',
+										content: `图片清晰度检测结果:${level}\n图片可能不够清晰,是否继续保存?`,
+										success: (res) => {
+											if (!res.confirm) {
+												// 用户取消保存
+												return;
+											}
+											// 用户确认后执行保存流程
+											saveImageToDatabase();
+										},
+										fail: () => {
+											// 模态框失败时继续保存
+											saveImageToDatabase();
+										}
+									});
+								} else {
+									// 图片清晰,直接保存
+									saveImageToDatabase();
+								}
 
-					// 查找1到所需图片数量之间最小的未使用编号
-					for (let i = 1; i <= this.joinRecord.num; i++) {
-						if (!existingNumbers.has(i)) {
-							return i;
-						}
+							} catch (error) {
+								console.error("转换图片为Base64失败:", error);
+							}
+						}, 100);
 					}
 
-					// 如果1到所需数量都被使用了,则使用当前数量+1
-					return this.imgArrLen + 1;
-				};
-
-				const minAvailableNumber = getMinAvailableNumber();
-				const newImgName = this.dyImgName + "-" + minAvailableNumber + ".jpg";				
-				const relativePath = `/uploadImgs/${newImgName}`
-
-				if (this.imgArrLen == 0) {
-					updateImgs = relativePath
-					updateNames = newImgName;
-				} else {
-					updateImgs = this.joinRecord.urlpdt + "," + relativePath
-					updateNames = this.joinRecord.imgname + "," + newImgName;
-				}
-
-				let updatedData = "imgname='" + updateNames + "',urlpdt='" + updateImgs + "'"
-
-				if (this.joinRecord.num === this.imgArrLen + 1) {
-					updateStatus = "status='3'"
-					updatedData = updatedData + "," + updateStatus
-				} else if (this.joinRecord.status === 1) {
-					updateStatus = "status='2'"
-					updatedData = updatedData + "," + updateStatus
+				} catch (error) {
+					uni.hideLoading();
+					console.error('图片清晰度检测失败:', error);
+					// 检测失败时继续保存流程
+					uni.showToast({
+						title: '清晰度检测失败,继续保存',
+						icon: 'none',
+						duration: 2000
+					});
+					saveImageToDatabase();
 				}
-				console.log(updatedData)
-				
-				updateData('app_media_record', updatedData, 'sxid', this.recordId.toString()).then((res : UTSJSONObject) => {
-					let data = res?.['data'] as boolean ?? false
-					if (data != null && data== true) {
-						uni.showToast({
-							title: "保存成功!",
-						});
-						const newPath = `${uni.env.USER_DATA_PATH}/uploadImgs/${newImgName}`
-						this.renameFile(this.path, newPath)
-
-						uni.navigateTo({
-							url: `/pages/work/record/RecordList?part=${this.joinRecord.part}&senum=${this.senum}&pid=${this.joinRecord.pid}`,
-							// 修改动画方向为从左到右退回
-							animationType: 'slide-in-left', // 使用从左到右滑出的动画效果
-							animationDuration: 300 // 动画持续时间,单位ms
-						})
-					}
-				});
+				return;
 			},
 			previewSingleImage(imageUrl : string) {
 				uni.previewImage({
@@ -292,30 +376,30 @@
 					loop: false // 是否可循环预览
 				});
 			},
-			renameFile(oldPath:string, newPath:string) {
-			    // 先拷贝文件到新路径
-			    uni.getFileSystemManager().copyFile({
-			        srcPath: oldPath,
-			        destPath: newPath,
-			        success: function () {
-			            // 可选:删除原文件,如果你需要释放空间的话
-			            uni.getFileSystemManager().unlink({
-			                filePath: oldPath,
-			                success: function () {
-			                    console.log('原文件已删除');
-			                },
-			                fail: function (unlinkErr) {
-			                    console.error('删除原文件失败', unlinkErr);
-			                }
-			            });
-			            console.log('文件重命名成功');
-			        },
-			        fail: function (copyErr) {
-			            console.error('拷贝文件失败', copyErr);
-			        }
-			    });
+			renameFile(oldPath : string, newPath : string) {
+				// 先拷贝文件到新路径
+				uni.getFileSystemManager().copyFile({
+					srcPath: oldPath,
+					destPath: newPath,
+					success: function () {
+						// 可选:删除原文件,如果你需要释放空间的话
+						uni.getFileSystemManager().unlink({
+							filePath: oldPath,
+							success: function () {
+								console.log('原文件已删除');
+							},
+							fail: function (unlinkErr) {
+								console.error('删除原文件失败', unlinkErr);
+							}
+						});
+						console.log('文件重命名成功');
+					},
+					fail: function (copyErr) {
+						console.error('拷贝文件失败', copyErr);
+					}
+				});
 			},
-			
+
 			handleScanCode(ev : UniCameraScanCodeEvent) {
 				const deatil = ev.detail;
 				this.result = {
@@ -398,7 +482,7 @@
 	.camera-scan-code-table-top-line {
 		border-top: 1px solid #eee;
 	}
-	
+
 	.my-page {
 		display: flex;
 		flex-direction: column;