瀏覽代碼

图片压缩后重复问题修复

QAQ 陈 3 月之前
父節點
當前提交
830e680350
共有 2 個文件被更改,包括 258 次插入180 次删除
  1. 130 90
      pages/baoxiudj/baoxiudj.js
  2. 128 90
      pages/tousujianyi/tousujianyi.js

+ 130 - 90
pages/baoxiudj/baoxiudj.js

@@ -148,7 +148,11 @@ Page({
         for (let i = 0; i < tempFiles.length; i++) {
           const file = tempFiles[i];
           if (file.size <= 10 * 1024 * 1024) {
-            validFiles.push(file);
+            // 为每个文件添加唯一标识
+            validFiles.push({
+              ...file,
+              uid: `${Date.now()}_${Math.random().toString(36).substr(2, 9)}_${i}` 
+            });
           } else {
             wx.showToast({
               title: '图片大小不能超过10M',
@@ -159,65 +163,117 @@ Page({
 
         if (validFiles.length > 0) {
           wx.showLoading({
-            title: '图片压缩中...',
+            title: '图片处理中...',
             mask: true
           });
           
-          let processedFiles = new Array(validFiles.length);
+          // 创建副本保存待处理的图片列表
+          const filesToProcess = [...validFiles];
+          // 使用Map结构存储结果,确保不会丢失
+          let processedFilesMap = new Map();
           let processCount = 0;
           
+          // 获取当前已有图片的路径列表,用于去重检查
+          const existingPaths = that.data.imageList.map(img => 
+            typeof img === 'string' ? img : img.tempFilePath
+          );
+          
           // 处理每个图片
-          validFiles.forEach((file, index) => {
+          filesToProcess.forEach((file) => {
+            // 检查是否已经存在相同路径的图片
+            if (existingPaths.includes(file.tempFilePath)) {
+              console.log("跳过重复图片:", file.tempFilePath);
+              processCount++;
+              
+              // 检查是否所有图片都已处理完成
+              if (processCount === filesToProcess.length) {
+                finishProcessing();
+              }
+              return;
+            }
+            
             that.compressImage(file.tempFilePath).then(compressedPath => {
               processCount++;
-              // 获取压缩后图片的信息
-              wx.getFileInfo({
-                filePath: compressedPath,
-                success: (fileInfo) => {
-                  console.log('原始大小:', file.size / 1024, 'KB');
-                  console.log('压缩后大小:', fileInfo.size / 1024, 'KB');
-                  
-                  // 在对应位置添加压缩后的图片路径
-                  processedFiles[index] = {
-                    tempFilePath: compressedPath,
-                    size: fileInfo.size
-                  };
-                  
-                  // 检查是否所有图片都已处理完成
-                  if (processCount === validFiles.length) {
-                    // 过滤掉可能的空值,并按顺序合并
-                    let newImageList = that.data.imageList.concat(processedFiles.filter(item => item));
-                    that.setData({
-                      imageList: newImageList
-                    });
-                    wx.hideLoading();
-                  }
-                },
-                fail: (err) => {
-                  console.error('获取文件信息失败:', err);
-                  processCount++;
-                  // 如果失败,也要检查是否处理完所有图片
-                  if (processCount === validFiles.length) {
-                    wx.hideLoading();
-                  }
-                }
-              });
+              
+              // 如果返回路径与原路径不同,则认为已成功压缩
+              if (compressedPath !== file.tempFilePath) {
+                // 使用Map结构通过uid存储处理结果,保证一一对应
+                processedFilesMap.set(file.uid, {
+                  tempFilePath: compressedPath,
+                  size: file.size, // 这里使用原始大小,实际上压缩后大小会变小
+                  uid: file.uid,
+                  originalPath: file.tempFilePath // 保存原始路径以便追踪
+                });
+              } else {
+                // 如果路径没变,可能是压缩失败或无需压缩的小图片
+                processedFilesMap.set(file.uid, {
+                  tempFilePath: compressedPath,
+                  size: file.size,
+                  uid: file.uid
+                });
+              }
+              
+              // 检查是否所有图片都已处理完成
+              if (processCount === filesToProcess.length) {
+                finishProcessing();
+              }
             }).catch(err => {
               console.error('图片压缩失败:', err);
               processCount++;
-              if (processCount === validFiles.length) {
-                wx.hideLoading();
+              
+              // 即使压缩失败,也将原图添加到结果中
+              processedFilesMap.set(file.uid, {
+                tempFilePath: file.tempFilePath,
+                size: file.size,
+                uid: file.uid
+              });
+              
+              if (processCount === filesToProcess.length) {
+                finishProcessing();
               }
             });
           });
+          
+          // 统一处理添加图片到列表的逻辑
+          function finishProcessing() {
+            // 将Map转换为数组,保持原有顺序
+            let processedFiles = filesToProcess.map(file => processedFilesMap.get(file.uid)).filter(Boolean);
+            
+            // 再次检查去重,防止压缩后的图片路径与已有图片重复
+            let currentImagePaths = that.data.imageList.map(img => 
+              typeof img === 'string' ? img : img.tempFilePath
+            );
+            
+            let newFiles = processedFiles.filter(file => 
+              !currentImagePaths.includes(file.tempFilePath)
+            );
+            
+            console.log(`添加 ${newFiles.length} 张新图片,跳过 ${processedFiles.length - newFiles.length} 张重复图片`);
+            
+            if (newFiles.length > 0) {
+              let newImageList = that.data.imageList.concat(newFiles);
+              that.setData({
+                imageList: newImageList
+              });
+            }
+            
+            wx.hideLoading();
+          }
         }
       }
     });
   },
 
-  // 使用canvas进行图片压缩
+  // 修改图片压缩函数,确保生成的路径在后续处理中保持一致
   compressImage: function(imagePath) {
     return new Promise((resolve, reject) => {
+      // 对于已经压缩过的图片(通常路径中会包含"compressed"),直接返回
+      if (imagePath.indexOf("compressed") > -1) {
+        console.log("图片已压缩,直接使用:", imagePath);
+        resolve(imagePath);
+        return;
+      }
+      
       // 获取图片信息
       wx.getImageInfo({
         src: imagePath,
@@ -227,6 +283,14 @@ Page({
             filePath: imagePath,
             success: (fileInfo) => {
               const originalSize = fileInfo.size / 1024; // 原始大小,单位KB
+              
+              // 如果原图已经很小(小于300KB),可以直接使用
+              if (originalSize < 300) {
+                console.log("图片较小,无需压缩:", originalSize, "KB");
+                resolve(imagePath);
+                return;
+              }
+              
               // 根据原图大小确定压缩质量
               let targetQuality = 0.8; // 默认压缩质量
               
@@ -252,6 +316,7 @@ Page({
                 .exec((canvasRes) => {
                   if (!canvasRes || !canvasRes[0] || !canvasRes[0].node) {
                     // 如果找不到canvas节点,则返回原图
+                    console.log("找不到canvas节点,使用原图");
                     resolve(imagePath);
                     return;
                   }
@@ -284,6 +349,10 @@ Page({
                     ctx.clearRect(0, 0, targetWidth, targetHeight);
                     // 绘制图片
                     ctx.drawImage(image, 0, 0, targetWidth, targetHeight);
+                    
+                    // 生成带有标记的压缩后路径名称
+                    const compressedName = `compressed_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`;
+                    
                     // 压缩参数
                     const compressOptions = {
                       canvas: canvas,
@@ -292,57 +361,24 @@ Page({
                       destWidth: targetWidth,
                       destHeight: targetHeight,
                       fileType: 'jpg',
-                      quality: targetQuality
+                      quality: targetQuality,
+                      // 添加压缩标记
+                      filePath: `${wx.env.USER_DATA_PATH}/${compressedName}.jpg`
                     };
                     
-                    // 第一次尝试压缩
-                    const tryCompress = (quality, attempt = 1) => {
-                      compressOptions.quality = quality;
-                      
-                      wx.canvasToTempFilePath({
-                        ...compressOptions,
-                        success: (result) => {
-                          // 检查压缩后的大小
-                          wx.getFileInfo({
-                            filePath: result.tempFilePath,
-                            success: (compressedInfo) => {
-                              const compressedSize = compressedInfo.size / 1024; // 压缩后大小,单位KB
-                              console.log(`压缩后大小 (质量:${quality})`, compressedSize, 'KB');
-                              // 如果压缩后大小仍大于500KB且尝试次数未达上限,继续压缩
-                              if (compressedSize > 500 && attempt < 3) {
-                                // 递减质量
-                                const newQuality = Math.max(0.1, quality - 0.2);
-                                console.log(`尝试重新压缩,质量降低至${newQuality}`);
-                                tryCompress(newQuality, attempt + 1);
-                              } 
-                              // 如果压缩后小于200KB且质量非最高,尝试提高质量
-                              else if (compressedSize < 200 && quality < 0.9 && attempt < 3) {
-                                // 递增质量
-                                const newQuality = Math.min(0.9, quality + 0.2);
-                                console.log(`尝试重新压缩,质量提高至${newQuality}`);
-                                tryCompress(newQuality, attempt + 1);
-                              }
-                              else {
-                                // 返回压缩后的图片
-                                resolve(result.tempFilePath);
-                              }
-                            },
-                            fail: (error) => {
-                              console.error('获取压缩后图片信息失败:', error);
-                              resolve(result.tempFilePath);
-                            }
-                          });
-                        },
-                        fail: (error) => {
-                          console.error('Canvas转图片失败:', error);
-                          // 如果转换失败则返回原图
-                          resolve(imagePath);
-                        }
-                      });
-                    };
-                    
-                    // 开始尝试压缩
-                    tryCompress(targetQuality);
+                    // 执行一次压缩
+                    wx.canvasToTempFilePath({
+                      ...compressOptions,
+                      success: (result) => {
+                        console.log("压缩成功,新路径:", result.tempFilePath);
+                        resolve(result.tempFilePath);
+                      },
+                      fail: (error) => {
+                        console.error('Canvas转图片失败:', error);
+                        // 如果转换失败则返回原图
+                        resolve(imagePath);
+                      }
+                    });
                   };
                   
                   image.onerror = () => {
@@ -369,9 +405,13 @@ Page({
 
   previewImage: function (e) {
     let index = e.currentTarget.dataset.index;
+    let urls = this.data.imageList.map(item => {
+      // 处理不同格式的图片对象
+      return typeof item === 'string' ? item : item.tempFilePath;
+    });
     wx.previewImage({
-      current: this.data.imageList[index],
-      urls: this.data.imageList
+      current: urls[index],
+      urls: urls
     });
   },
 

+ 128 - 90
pages/tousujianyi/tousujianyi.js

@@ -132,7 +132,11 @@ Page({
         for (let i = 0; i < tempFiles.length; i++) {
           const file = tempFiles[i];
           if (file.size <= 10 * 1024 * 1024) {
-            validFiles.push(file);
+            // 为每个文件添加唯一标识
+            validFiles.push({
+              ...file,
+              uid: `${Date.now()}_${Math.random().toString(36).substr(2, 9)}_${i}`
+            });
           } else {
             wx.showToast({
               title: '图片大小不能超过10M',
@@ -143,57 +147,102 @@ Page({
 
         if (validFiles.length > 0) {
           wx.showLoading({
-            title: '图片压缩中...',
+            title: '图片处理中...',
             mask: true
           });
           
-          let processedFiles = new Array(validFiles.length);
+          // 创建副本保存待处理的图片列表
+          const filesToProcess = [...validFiles];
+          // 使用Map结构存储结果,确保不会丢失
+          let processedFilesMap = new Map();
           let processCount = 0;
           
+          // 获取当前已有图片的路径列表,用于去重检查
+          const existingPaths = that.data.imageList.map(img => 
+            typeof img === 'string' ? img : img.tempFilePath
+          );
+          
           // 处理每个图片
-          validFiles.forEach((file, index) => {
+          filesToProcess.forEach((file) => {
+            // 检查是否已经存在相同路径的图片
+            if (existingPaths.includes(file.tempFilePath)) {
+              console.log("跳过重复图片:", file.tempFilePath);
+              processCount++;
+              
+              // 检查是否所有图片都已处理完成
+              if (processCount === filesToProcess.length) {
+                finishProcessing();
+              }
+              return;
+            }
+            
             that.compressImage(file.tempFilePath).then(compressedPath => {
               processCount++;
-              // 获取压缩后图片的信息
-              wx.getFileInfo({
-                filePath: compressedPath,
-                success: (fileInfo) => {
-                  console.log('原始大小:', file.size / 1024, 'KB');
-                  console.log('压缩后大小:', fileInfo.size / 1024, 'KB');
-                  
-                  // 在对应位置添加压缩后的图片路径
-                  processedFiles[index] = {
-                    tempFilePath: compressedPath,
-                    size: fileInfo.size
-                  };
-                  
-                  // 检查是否所有图片都已处理完成
-                  if (processCount === validFiles.length) {
-                    // 过滤掉可能的空值,并按顺序合并
-                    let newImageList = that.data.imageList.concat(processedFiles.filter(item => item));
-                    that.setData({
-                      imageList: newImageList
-                    });
-                    wx.hideLoading();
-                  }
-                },
-                fail: (err) => {
-                  console.error('获取文件信息失败:', err);
-                  processCount++;
-                  // 如果失败,也要检查是否处理完所有图片
-                  if (processCount === validFiles.length) {
-                    wx.hideLoading();
-                  }
-                }
-              });
+              
+              // 如果返回路径与原路径不同,则认为已成功压缩
+              if (compressedPath !== file.tempFilePath) {
+                // 使用Map结构通过uid存储处理结果,保证一一对应
+                processedFilesMap.set(file.uid, {
+                  tempFilePath: compressedPath,
+                  size: file.size, // 这里使用原始大小,实际上压缩后大小会变小
+                  uid: file.uid,
+                  originalPath: file.tempFilePath // 保存原始路径以便追踪
+                });
+              } else {
+                // 如果路径没变,可能是压缩失败或无需压缩的小图片
+                processedFilesMap.set(file.uid, {
+                  tempFilePath: compressedPath,
+                  size: file.size,
+                  uid: file.uid
+                });
+              }
+              
+              // 检查是否所有图片都已处理完成
+              if (processCount === filesToProcess.length) {
+                finishProcessing();
+              }
             }).catch(err => {
               console.error('图片压缩失败:', err);
               processCount++;
-              if (processCount === validFiles.length) {
-                wx.hideLoading();
+              
+              // 即使压缩失败,也将原图添加到结果中
+              processedFilesMap.set(file.uid, {
+                tempFilePath: file.tempFilePath,
+                size: file.size,
+                uid: file.uid
+              });
+              
+              if (processCount === filesToProcess.length) {
+                finishProcessing();
               }
             });
           });
+          
+          // 统一处理添加图片到列表的逻辑
+          function finishProcessing() {
+            // 将Map转换为数组,保持原有顺序
+            let processedFiles = filesToProcess.map(file => processedFilesMap.get(file.uid)).filter(Boolean);
+            
+            // 再次检查去重,防止压缩后的图片路径与已有图片重复
+            let currentImagePaths = that.data.imageList.map(img => 
+              typeof img === 'string' ? img : img.tempFilePath
+            );
+            
+            let newFiles = processedFiles.filter(file => 
+              !currentImagePaths.includes(file.tempFilePath)
+            );
+            
+            console.log(`添加 ${newFiles.length} 张新图片,跳过 ${processedFiles.length - newFiles.length} 张重复图片`);
+            
+            if (newFiles.length > 0) {
+              let newImageList = that.data.imageList.concat(newFiles);
+              that.setData({
+                imageList: newImageList
+              });
+            }
+            
+            wx.hideLoading();
+          }
         }
       }
     });
@@ -202,6 +251,13 @@ Page({
   // 使用canvas进行图片压缩
   compressImage: function(imagePath) {
     return new Promise((resolve, reject) => {
+      // 对于已经压缩过的图片(通常路径中会包含"compressed"),直接返回
+      if (imagePath.indexOf("compressed") > -1) {
+        console.log("图片已压缩,直接使用:", imagePath);
+        resolve(imagePath);
+        return;
+      }
+      
       // 获取图片信息
       wx.getImageInfo({
         src: imagePath,
@@ -211,6 +267,14 @@ Page({
             filePath: imagePath,
             success: (fileInfo) => {
               const originalSize = fileInfo.size / 1024; // 原始大小,单位KB
+              
+              // 如果原图已经很小(小于300KB),可以直接使用
+              if (originalSize < 300) {
+                console.log("图片较小,无需压缩:", originalSize, "KB");
+                resolve(imagePath);
+                return;
+              }
+              
               // 根据原图大小确定压缩质量
               let targetQuality = 0.8; // 默认压缩质量
               
@@ -238,6 +302,7 @@ Page({
                 .exec((canvasRes) => {
                   if (!canvasRes || !canvasRes[0] || !canvasRes[0].node) {
                     // 如果找不到canvas节点,则返回原图
+                    console.log("找不到canvas节点,使用原图");
                     resolve(imagePath);
                     return;
                   }
@@ -274,6 +339,9 @@ Page({
                     // 绘制图片
                     ctx.drawImage(image, 0, 0, targetWidth, targetHeight);
                     
+                    // 生成带有标记的压缩后路径名称
+                    const compressedName = `compressed_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`;
+                    
                     // 压缩参数
                     const compressOptions = {
                       canvas: canvas,
@@ -282,58 +350,24 @@ Page({
                       destWidth: targetWidth,
                       destHeight: targetHeight,
                       fileType: 'jpg',
-                      quality: targetQuality
+                      quality: targetQuality,
+                      // 添加压缩标记
+                      filePath: `${wx.env.USER_DATA_PATH}/${compressedName}.jpg`
                     };
                     
-                    // 第一次尝试压缩
-                    const tryCompress = (quality, attempt = 1) => {
-                      compressOptions.quality = quality;
-                      
-                      wx.canvasToTempFilePath({
-                        ...compressOptions,
-                        success: (result) => {
-                          // 检查压缩后的大小
-                          wx.getFileInfo({
-                            filePath: result.tempFilePath,
-                            success: (compressedInfo) => {
-                              const compressedSize = compressedInfo.size / 1024; // 压缩后大小,单位KB
-                              console.log(`压缩后大小 (质量:${quality})`, compressedSize, 'KB');
-                              
-                              // 如果压缩后大小仍大于500KB且尝试次数未达上限,继续压缩
-                              if (compressedSize > 500 && attempt < 3) {
-                                // 递减质量
-                                const newQuality = Math.max(0.1, quality - 0.2);
-                                console.log(`尝试重新压缩,质量降低至${newQuality}`);
-                                tryCompress(newQuality, attempt + 1);
-                              } 
-                              // 如果压缩后小于200KB且质量非最高,尝试提高质量
-                              else if (compressedSize < 200 && quality < 0.9 && attempt < 3) {
-                                // 递增质量
-                                const newQuality = Math.min(0.9, quality + 0.2);
-                                console.log(`尝试重新压缩,质量提高至${newQuality}`);
-                                tryCompress(newQuality, attempt + 1);
-                              }
-                              else {
-                                // 返回压缩后的图片
-                                resolve(result.tempFilePath);
-                              }
-                            },
-                            fail: (error) => {
-                              console.error('获取压缩后图片信息失败:', error);
-                              resolve(result.tempFilePath);
-                            }
-                          });
-                        },
-                        fail: (error) => {
-                          console.error('Canvas转图片失败:', error);
-                          // 如果转换失败则返回原图
-                          resolve(imagePath);
-                        }
-                      });
-                    };
-                    
-                    // 开始尝试压缩
-                    tryCompress(targetQuality);
+                    // 执行一次压缩
+                    wx.canvasToTempFilePath({
+                      ...compressOptions,
+                      success: (result) => {
+                        console.log("压缩成功,新路径:", result.tempFilePath);
+                        resolve(result.tempFilePath);
+                      },
+                      fail: (error) => {
+                        console.error('Canvas转图片失败:', error);
+                        // 如果转换失败则返回原图
+                        resolve(imagePath);
+                      }
+                    });
                   };
                   
                   image.onerror = () => {
@@ -360,9 +394,13 @@ Page({
 
   previewImage: function (e) {
     let index = e.currentTarget.dataset.index;
+    let urls = this.data.imageList.map(item => {
+      // 处理不同格式的图片对象
+      return typeof item === 'string' ? item : item.tempFilePath;
+    });
     wx.previewImage({
-      current: this.data.imageList[index],
-      urls: this.data.imageList
+      current: urls[index],
+      urls: urls
     });
   },