diff --git a/src/pages/devicesSearch/ocrSearch.nvue b/src/pages/devicesSearch/ocrSearch.nvue index 54982e2..29c8a71 100644 --- a/src/pages/devicesSearch/ocrSearch.nvue +++ b/src/pages/devicesSearch/ocrSearch.nvue @@ -78,20 +78,6 @@ - - - - - - - - - - - - - - 请将识别编码置于取景框内,完成扫描 @@ -389,7 +375,7 @@ export default { console.log('开始自动聚焦...'); - await new Promise((resolve, reject) => { + await new Promise((resolve, reject)=> { // 设置聚焦超时 this.focusTimeout = setTimeout(() => { console.log('聚焦超时'); @@ -468,7 +454,7 @@ export default { clearTimeout(this.focusTimeout); } - await new Promise((resolve, reject) => { + await new Promise((resolve, reject)=> { // 设置聚焦超时 this.focusTimeout = setTimeout(() => { console.log('点击聚焦超时'); @@ -506,7 +492,9 @@ export default { resolve(); // 即使聚焦失败也继续 } ); - }); + } + ) + ; } catch (error) { console.error('点击聚焦过程出错:', error); this.isFocusing = false; @@ -591,7 +579,8 @@ export default { await this.performFocusBeforeCapture(); console.log('开始拍照...'); - const imageData = await new Promise((resolve, reject) => { + const imageData = await new Promise((resolve, reject)=> + { const options = { quality: 85, targetHeight: 1920, @@ -609,7 +598,9 @@ export default { reject(new Error(`拍照失败: ${error}`)); } ); - }); + } + ) + ; await this.processImage(imageData); } catch (error) { @@ -636,7 +627,8 @@ export default { console.log('拍照前执行聚焦...'); - await new Promise((resolve, reject) => { + await new Promise((resolve, reject)=> + { // 设置聚焦超时 const focusTimeout = setTimeout(() => { console.log('拍照前聚焦超时,继续拍照'); @@ -659,7 +651,9 @@ export default { resolve(); // 即使聚焦失败也继续拍照 } ); - }); + } + ) + ; } catch (error) { console.error('拍照前聚焦过程出错:', error); this.isFocusing = false; @@ -680,7 +674,8 @@ export default { }); console.log('图片处理完成,开始OCR识别...'); - const response = await new Promise((resolve, reject) => { + const response = await new Promise((resolve, reject)=> + { uni.request({ url: '/material/app/ocr/getOcrCode', method: 'POST', @@ -693,7 +688,9 @@ export default { success: resolve, fail: reject }); - }); + } + ) + ; if (response.data?.data?.result) { this.queryCodeParams.maCode = response.data.data.result; @@ -754,7 +751,8 @@ export default { }); console.log('相册图片处理完成,开始OCR识别...'); - const response = await new Promise((resolve, reject) => { + const response = await new Promise((resolve, reject)=> + { uni.request({ url: '/material/app/ocr/getOcrCode', method: 'POST', @@ -767,7 +765,9 @@ export default { success: resolve, fail: reject }); - }); + } + ) + ; if (response.data?.data?.result) { this.queryCodeParams.maCode = response.data.data.result; @@ -804,7 +804,8 @@ export default { return; } try { - const response = await new Promise((resolve, reject) => { + const response = await new Promise((resolve, reject)=> + { uni.request({ url: '/material/ma_machine/getHisByCode', method: 'GET', @@ -812,7 +813,9 @@ export default { success: resolve, fail: reject }); - }); + } + ) + ; if (response.data?.data && response.data.data.length > 0) { this.optionList = response.data.data.map(option => ({ @@ -841,7 +844,8 @@ export default { async changeTag() { if (!this.queryCodeParams.maId) return; try { - const response = await new Promise((resolve, reject) => { + const response = await new Promise((resolve, reject)=> + { uni.request({ url: '/material/ma_machine/getHisByCode', method: 'GET', @@ -849,7 +853,9 @@ export default { success: resolve, fail: reject }); - }); + } + ) + ; if (response.data?.data && response.data.data.length > 0) { this.codeData = response.data.data[0]; @@ -940,56 +946,10 @@ export default { left: 0; width: 100vw; height: 100vh; - background-color: transparent; /* 改为透明,让相机预览显示 */ + background-color: transparent; z-index: 99999; } -/* 遮罩层样式 */ -.camera-overlay { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - z-index: 1; -} - -.overlay-top { - width: 100%; - height: calc(50% - 300rpx); /* 取景框上方的遮罩 */ - background-color: rgba(0, 0, 0, 0.6); -} - -.overlay-middle { - display: flex; - width: 100%; - height: 600rpx; /* 取景框的高度 */ -} - -.overlay-left { - width: calc(50% - 250rpx); /* 取景框左侧的遮罩 */ - height: 100%; - background-color: rgba(0, 0, 0, 0.6); -} - -.overlay-transparent { - width: 500rpx; /* 取景框的宽度 */ - height: 100%; - background-color: transparent; /* 透明区域,显示相机预览 */ -} - -.overlay-right { - width: calc(50% - 250rpx); /* 取景框右侧的遮罩 */ - height: 100%; - background-color: rgba(0, 0, 0, 0.6); -} - -.overlay-bottom { - width: 100%; - height: calc(50% - 300rpx); /* 取景框下方的遮罩 */ - background-color: rgba(0, 0, 0, 0.6); -} - .top-tip { position: absolute; top: 80rpx; @@ -1001,7 +961,7 @@ export default { } .tip-text { - background-color: rgba(0, 0, 0, 0.7); + background-color: rgba(0, 0, 0, 0.5); color: #fff; font-size: 32rpx; font-weight: bold; @@ -1040,9 +1000,10 @@ export default { position: relative; width: 500rpx; height: 600rpx; - background-color: transparent; /* 透明背景 */ - border: none; /* 移除边框 */ + background-color: transparent; + border: 2rpx solid rgba(255, 255, 255, 0.5); border-radius: 20rpx; + box-shadow: 0 0 20rpx rgba(75, 142, 255, 0.5); } /* 扫描线动画 */ @@ -1052,7 +1013,7 @@ export default { left: 0; width: 100%; height: 4rpx; - background: linear-gradient(90deg, transparent, #4b8eff, transparent); + background: linear-gradient(90deg, transparent, rgba(75, 142, 255, 0.8), transparent); animation: scan 2s linear infinite; border-radius: 2rpx; } @@ -1075,7 +1036,7 @@ export default { position: absolute; width: 60rpx; height: 60rpx; - border: 6rpx solid #4b8eff; + border: 6rpx solid rgba(75, 142, 255, 0.8); background-color: transparent; } @@ -1165,7 +1126,7 @@ export default { .control-btn { width: 100rpx; height: 100rpx; - background-color: rgba(255, 255, 255, 0.2); + background-color: rgba(0, 0, 0, 0.3); border-radius: 50%; display: flex; justify-content: center; @@ -1182,12 +1143,12 @@ export default { .photo-btn { width: 140rpx; height: 140rpx; - background-color: rgba(255, 255, 255, 0.2); + background-color: rgba(0, 0, 0, 0.3); border-radius: 50%; display: flex; justify-content: center; align-items: center; - border: 6rpx solid #fff; + border: 6rpx solid rgba(255, 255, 255, 0.5); transition: all 0.2s ease; } @@ -1204,7 +1165,7 @@ export default { .photo-btn-inner { width: 100rpx; height: 100rpx; - background-color: #fff; + background-color: rgba(255, 255, 255, 0.9); border-radius: 50%; transition: all 0.2s ease; } @@ -1263,4 +1224,4 @@ export default { font-size: 32rpx; font-weight: bold; } - + \ No newline at end of file diff --git a/src/services/utils/imageUtils.js b/src/services/utils/imageUtils.js index 5d71078..4ed4006 100644 --- a/src/services/utils/imageUtils.js +++ b/src/services/utils/imageUtils.js @@ -1,5 +1,17 @@ -// 图片处理工具类 +// 修复后的图片处理工具类 class ImageUtils { + /** + * 获取 uni 对象的引用 + */ + static getUni() { + // 尝试多种方式获取 uni 对象 + const uni = window.uni || global.uni + if (typeof uni !== "undefined") { + return uni + } + throw new Error("uni 对象不可用") + } + /** * 将图片转换为Base64字符串(相当于Android的bitmapToString) * @param {string} imagePath 图片路径 @@ -8,6 +20,8 @@ class ImageUtils { */ static async imageToBase64(imagePath, quality = 50) { try { + const uniInstance = this.getUni() + // 如果已经是base64格式,直接返回数据部分 if (imagePath.startsWith("data:image/")) { return imagePath.split(",")[1] @@ -20,7 +34,7 @@ class ImageUtils { // 压缩图片 const compressResult = await new Promise((resolve, reject) => { - window.uni.compressImage({ + uniInstance.compressImage({ src: imagePath, quality: quality, success: resolve, @@ -29,7 +43,7 @@ class ImageUtils { }) // 读取压缩后的文件并转换为base64 - const fileManager = window.uni.getFileSystemManager() + const fileManager = uniInstance.getFileSystemManager() const base64Data = await new Promise((resolve, reject) => { fileManager.readFile({ filePath: compressResult.tempFilePath, @@ -42,10 +56,58 @@ class ImageUtils { return base64Data } catch (error) { console.error("Image to base64 conversion failed:", error) - throw error + // 如果上述方法失败,尝试使用 Canvas 方法 + return await this.canvasToBase64(imagePath, quality) } } + /** + * 使用 Canvas 将图片转换为 Base64 + * @param {string} imagePath 图片路径 + * @param {number} quality 质量 + * @returns {Promise} Base64字符串 + */ + static async canvasToBase64(imagePath, quality = 50) { + return new Promise((resolve, reject) => { + try { + const uniInstance = this.getUni() + const canvasId = "base64Canvas_" + Date.now() + + // 获取图片信息 + this.getImageInfo(imagePath) + .then((imageInfo) => { + const { width, height } = imageInfo + const ctx = uniInstance.createCanvasContext(canvasId) + + // 绘制图片到 canvas + ctx.drawImage(imagePath, 0, 0, width, height) + ctx.draw(false, () => { + // 导出为临时文件 + uniInstance.canvasToTempFilePath({ + canvasId: canvasId, + fileType: "jpg", + quality: quality / 100, + success: (res) => { + // 读取文件为 base64 + const fileManager = uniInstance.getFileSystemManager() + fileManager.readFile({ + filePath: res.tempFilePath, + encoding: "base64", + success: (fileRes) => resolve(fileRes.data), + fail: reject, + }) + }, + fail: reject, + }) + }) + }) + .catch(reject) + } catch (error) { + reject(error) + } + }) + } + /** * 获取缩放后的图片(相当于Android的getSmallBitmap) * @param {string} imagePath 图片路径 @@ -72,44 +134,48 @@ class ImageUtils { */ static async resizeImageWithCanvas(imagePath, maxWidth, maxHeight) { return new Promise((resolve, reject) => { - // 获取图片信息 - window.uni.getImageInfo({ - src: imagePath, - success: (imageInfo) => { - const { width, height } = imageInfo + try { + const uniInstance = this.getUni() - // 计算缩放比例 - const scale = this.calculateScale(width, height, maxWidth, maxHeight) - const newWidth = Math.floor(width * scale) - const newHeight = Math.floor(height * scale) + // 获取图片信息 + this.getImageInfo(imagePath) + .then((imageInfo) => { + const { width, height } = imageInfo - // 如果不需要缩放,直接返回原图 - if (scale >= 1) { - resolve(imagePath) - return - } + // 计算缩放比例 + const scale = this.calculateScale(width, height, maxWidth, maxHeight) + const newWidth = Math.floor(width * scale) + const newHeight = Math.floor(height * scale) - // 创建canvas上下文 - const canvasId = "imageProcessCanvas_" + Date.now() - const ctx = window.uni.createCanvasContext(canvasId) + // 如果不需要缩放,直接返回原图 + if (scale >= 1) { + resolve(imagePath) + return + } - // 绘制缩放后的图片 - ctx.drawImage(imagePath, 0, 0, newWidth, newHeight) - ctx.draw(false, () => { - // 导出canvas为临时文件 - window.uni.canvasToTempFilePath({ - canvasId: canvasId, - fileType: "jpg", - quality: 0.8, - success: (res) => { - resolve(res.tempFilePath) - }, - fail: reject, + // 创建canvas上下文 + const canvasId = "imageProcessCanvas_" + Date.now() + const ctx = uniInstance.createCanvasContext(canvasId) + + // 绘制缩放后的图片 + ctx.drawImage(imagePath, 0, 0, newWidth, newHeight) + ctx.draw(false, () => { + // 导出canvas为临时文件 + uniInstance.canvasToTempFilePath({ + canvasId: canvasId, + fileType: "jpg", + quality: 0.8, + success: (res) => { + resolve(res.tempFilePath) + }, + fail: reject, + }) }) }) - }, - fail: reject, - }) + .catch(reject) + } catch (error) { + reject(error) + } }) } @@ -122,14 +188,19 @@ class ImageUtils { */ static async fallbackCompress(imagePath, maxWidth, maxHeight) { return new Promise((resolve, reject) => { - window.uni.compressImage({ - src: imagePath, - quality: 80, - compressedWidth: maxWidth, - compressedHeight: maxHeight, - success: (res) => resolve(res.tempFilePath), - fail: reject, - }) + try { + const uniInstance = this.getUni() + uniInstance.compressImage({ + src: imagePath, + quality: 80, + compressedWidth: maxWidth, + compressedHeight: maxHeight, + success: (res) => resolve(res.tempFilePath), + fail: reject, + }) + } catch (error) { + reject(error) + } }) } @@ -145,10 +216,8 @@ class ImageUtils { if (originalWidth <= maxWidth && originalHeight <= maxHeight) { return 1 // 不需要缩放 } - const widthScale = maxWidth / originalWidth const heightScale = maxHeight / originalHeight - // 选择较小的缩放比例,确保图片完全适应限制尺寸 return Math.min(widthScale, heightScale) } @@ -163,17 +232,80 @@ class ImageUtils { const { maxWidth = 1024, maxHeight = 1024, quality = 50, outputFormat = "base64" } = options try { + console.log("开始处理图片:", imagePath) + + // 如果已经是 base64 格式,直接处理 + if (imagePath.startsWith("data:image/")) { + if (outputFormat === "base64") { + return imagePath.split(",")[1] + } else { + return imagePath + } + } + // 1. 先缩放图片 const resizedImagePath = await this.getSmallImage(imagePath, maxWidth, maxHeight) + console.log("图片缩放完成:", resizedImagePath) // 2. 根据输出格式返回结果 if (outputFormat === "base64") { - return await this.imageToBase64(resizedImagePath, quality) + const base64Result = await this.imageToBase64(resizedImagePath, quality) + console.log("图片转换为base64完成") + return base64Result } else { return resizedImagePath } } catch (error) { console.error("Process image failed:", error) + // 如果所有方法都失败,尝试简单的压缩 + return await this.simpleProcess(imagePath, options) + } + } + + /** + * 简单处理方法(备用) + * @param {string} imagePath 图片路径 + * @param {object} options 处理选项 + * @returns {Promise} 处理后的结果 + */ + static async simpleProcess(imagePath, options = {}) { + const { quality = 50, outputFormat = "base64" } = options + + try { + const uniInstance = this.getUni() + + // 如果已经是 base64,直接返回 + if (imagePath.startsWith("data:image/")) { + return outputFormat === "base64" ? imagePath.split(",")[1] : imagePath + } + + // 简单压缩 + const compressResult = await new Promise((resolve, reject) => { + uniInstance.compressImage({ + src: imagePath, + quality: quality, + success: resolve, + fail: reject, + }) + }) + + if (outputFormat === "base64") { + // 转换为 base64 + const fileManager = uniInstance.getFileSystemManager() + const base64Data = await new Promise((resolve, reject) => { + fileManager.readFile({ + filePath: compressResult.tempFilePath, + encoding: "base64", + success: (res) => resolve(res.data), + fail: reject, + }) + }) + return base64Data + } else { + return compressResult.tempFilePath + } + } catch (error) { + console.error("Simple process failed:", error) throw error } } @@ -185,11 +317,16 @@ class ImageUtils { */ static async getImageInfo(imagePath) { return new Promise((resolve, reject) => { - window.uni.getImageInfo({ - src: imagePath, - success: resolve, - fail: reject, - }) + try { + const uniInstance = this.getUni() + uniInstance.getImageInfo({ + src: imagePath, + success: resolve, + fail: reject, + }) + } catch (error) { + reject(error) + } }) } }