const app = getApp(); Page({ data: { address: app.globalData.currentAccountInfo.address, contact: '', phone: '', repairType: '', repairTypeValue: '', repairTypeMap: [ {name: '换表', value: '1'}, {name: '换前阀', value: '2'}, {name: '换后阀', value: '3'}, {name: '换前后阀', value: '4'}, {name: '其他', value: '5'} ], description: '', imageList: [], showNotification: true, countDown: 3, isFormValid: false, isPreviewMode: false, replyTime: '', replyContent: '', id: '', mode: '', isReplied: false, formSubmitted: false, isSubmitting: false, // 新增保存标志位 lastSubmitTime: 0, // 上次提交时间(通过防抖(Debounce)技术,限制用户在一定时间内只能提交一次。) }, onLoad: function (options) { const isReplied = options.isReplied === 'true'; // 更新地址信息,确保是最新的户号地址 this.setData({ address: app.globalData.currentAccountInfo.address }); if (options.mode === 'preview') { this.setData({ isPreviewMode: true, showNotification: false, id: options.id, mode: options.mode, isReplied: isReplied }); this.loadPreviewData(options.id); } else { this.startCountDown(); this.setData({ id: options.id || '', mode: options.mode || '', isReplied: isReplied }); } }, startCountDown: function () { let that = this; let timer = setInterval(function () { if (that.data.countDown > 0) { that.setData({ countDown: that.data.countDown - 1 }); } else { clearInterval(timer); } }, 1000); }, closeNotification: function () { if (this.data.countDown <= 0) { this.setData({ showNotification: false }); } }, goBack: function () { wx.navigateBack(); }, inputContact: function (e) { this.setData({ contact: e.detail.value }); this.checkFormValidity(); }, inputPhone: function (e) { const value = e.detail.value; const phoneNumber = value.replace(/\D/g, ''); this.setData({ phone: phoneNumber }); this.checkFormValidity(); }, validatePhone: function (phone) { const phoneReg = /^1[3-9]\d{9}$/; return phoneReg.test(phone); }, showRepairTypeSelector: function () { let that = this; // 只显示名称列表 const typeNames = this.data.repairTypeMap.map(item => item.name); wx.showActionSheet({ itemList: typeNames, success: function (res) { const selectedType = that.data.repairTypeMap[res.tapIndex]; that.setData({ repairType: selectedType.name, repairTypeValue: selectedType.value }); that.checkFormValidity(); } }); }, inputDescription: function (e) { this.setData({ description: e.detail.value }); this.checkFormValidity(); }, chooseImage: function () { let that = this; if (that.data.imageList.length >= 10) { wx.showToast({ title: '最多只能上传10张图片', icon: 'none' }); return; } wx.chooseMedia({ count: 10 - that.data.imageList.length, mediaType: ['image'], sourceType: ['album', 'camera'], sizeType: ['compressed'], success: function (res) { let tempFiles = res.tempFiles; let validFiles = []; for (let i = 0; i < tempFiles.length; i++) { const file = tempFiles[i]; if (file.size <= 10 * 1024 * 1024) { // 为每个文件添加唯一标识 validFiles.push({ ...file, uid: `${Date.now()}_${Math.random().toString(36).substr(2, 9)}_${i}` }); } else { wx.showToast({ title: '图片大小不能超过10M', icon: 'none' }); } } if (validFiles.length > 0) { wx.showLoading({ title: '图片处理中...', mask: true }); // 创建副本保存待处理的图片列表 const filesToProcess = [...validFiles]; // 使用Map结构存储结果,确保不会丢失 let processedFilesMap = new Map(); let processCount = 0; // 获取当前已有图片的路径列表,用于去重检查 const existingPaths = that.data.imageList.map(img => typeof img === 'string' ? img : img.tempFilePath ); // 处理每个图片 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++; // 如果返回路径与原路径不同,则认为已成功压缩 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++; // 即使压缩失败,也将原图添加到结果中 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(); } } } }); }, // 修改图片压缩函数,确保生成的路径在后续处理中保持一致 compressImage: function(imagePath) { return new Promise((resolve, reject) => { // 对于已经压缩过的图片(通常路径中会包含"compressed"),直接返回 if (imagePath.indexOf("compressed") > -1) { console.log("图片已压缩,直接使用:", imagePath); resolve(imagePath); return; } // 获取图片信息 wx.getImageInfo({ src: imagePath, success: (res) => { // 先获取原图大小,单位KB wx.getFileInfo({ 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; // 默认压缩质量 if (originalSize <= 500) { // 如果原图已经小于500KB,保持较高质量 targetQuality = 0.9; } else if (originalSize <= 1024) { // 1MB以下,适当压缩 targetQuality = 0.7; } else if (originalSize <= 2048) { // 2MB以下,中等压缩 targetQuality = 0.5; } else if (originalSize <= 5120) { // 5MB以下,较大压缩 targetQuality = 0.3; } else { // 超过5MB,大幅压缩 targetQuality = 0.2; } wx.createSelectorQuery() .select('#compressCanvas') .fields({ node: true, size: true }) .exec((canvasRes) => { if (!canvasRes || !canvasRes[0] || !canvasRes[0].node) { // 如果找不到canvas节点,则返回原图 console.log("找不到canvas节点,使用原图"); resolve(imagePath); return; } const canvas = canvasRes[0].node; const ctx = canvas.getContext('2d'); const image = canvas.createImage(); image.onload = () => { // 计算要缩放的尺寸,保持宽高比 let ratio = 1; // 根据原图大小调整尺寸 if (originalSize > 5120) { // 5MB以上 ratio = Math.min(1, 1200 / res.width, 1200 / res.height); } else if (originalSize > 2048) { // 2MB以上 ratio = Math.min(1, 1500 / res.width, 1500 / res.height); } else if (originalSize > 1024) { // 1MB以上 ratio = Math.min(1, 1800 / res.width, 1800 / res.height); } else { ratio = Math.min(1, 2000 / res.width, 2000 / res.height); } const targetWidth = Math.round(res.width * ratio); const targetHeight = Math.round(res.height * ratio); // 设置canvas尺寸 canvas.width = targetWidth; canvas.height = targetHeight; // 清除画布 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, width: targetWidth, height: targetHeight, destWidth: targetWidth, destHeight: targetHeight, fileType: 'jpg', quality: targetQuality, // 添加压缩标记 filePath: `${wx.env.USER_DATA_PATH}/${compressedName}.jpg` }; // 执行一次压缩 wx.canvasToTempFilePath({ ...compressOptions, success: (result) => { console.log("压缩成功,新路径:", result.tempFilePath); resolve(result.tempFilePath); }, fail: (error) => { console.error('Canvas转图片失败:', error); // 如果转换失败则返回原图 resolve(imagePath); } }); }; image.onerror = () => { console.error('图片加载失败'); resolve(imagePath); }; image.src = imagePath; }); }, fail: (error) => { console.error('获取原始图片信息失败:', error); resolve(imagePath); } }); }, fail: (error) => { console.error('获取图片信息失败:', error); resolve(imagePath); } }); }); }, 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: urls[index], urls: urls }); }, deleteImage: function (e) { let index = e.currentTarget.dataset.index; let imageList = this.data.imageList; imageList.splice(index, 1); this.setData({ imageList: imageList }); }, checkFormValidity: function () { const { contact, phone, address, repairType, repairTypeValue, description } = this.data; const hasAddress = address && address.trim() !== ''; const hasContact = contact && contact.trim() !== ''; const hasPhone = phone && phone.trim() !== ''; const hasValidPhone = this.validatePhone(phone); const hasRepairType = repairType && repairType.trim() !== ''; const hasRepairTypeValue = repairTypeValue && repairTypeValue.trim() !== ''; const hasDescription = description && description.trim() !== ''; const isValid = hasAddress && hasContact && hasPhone && hasValidPhone && hasRepairType && hasRepairTypeValue && hasDescription; this.setData({ isFormValid: isValid }); return isValid; }, onInputChange: function (e) { const { field } = e.currentTarget.dataset; const { value } = e.detail; this.setData({ [field]: value }); this.checkFormValidity(); }, bindPickerChange: function (e) { this.checkFormValidity(); }, submitRepair: function () { if (!this.checkFormValidity()) { wx.showToast({ title: '请填写完整信息', icon: 'none' }); return; } if (!this.validatePhone(this.data.phone)) { wx.showToast({ title: '请输入正确的手机号', icon: 'none' }); return; } const submitData = { address: this.data.address, contact: this.data.contact, phone: this.data.phone, repairType: this.data.repairType, repairTypeValue: this.data.repairTypeValue, description: this.data.description, images: this.data.imageList }; console.log('提交的数据:', submitData); wx.showLoading({ title: '提交中...', }); setTimeout(() => { wx.hideLoading(); wx.showToast({ icon: 'success', duration: 2000, success: function () { setTimeout(() => { wx.navigateTo({ url: '/pages/baoxiuSuccess/baoxiuSuccess', }); }, 2000); } }); }, 1500); }, loadPreviewData: function (id) { wx.showLoading({ title: '加载中...', }); // 从上一个页面获取数据 const pages = getCurrentPages(); const prevPage = pages[pages.length - 2]; // 获取上一个页面 if (prevPage && prevPage.data && prevPage.data.noticeList) { // 根据id查找对应的报修项 const item = prevPage.data.noticeList.find(item => item.id == id); debugger if (item) { // 找到对应的报修类型名称 let repairTypeName = ''; const repairTypeValue = item.repairtype || ''; const repairTypeItem = this.data.repairTypeMap.find(type => type.name === repairTypeValue); if (repairTypeItem) { repairTypeName = repairTypeItem.name; } // 格式化时间 const formatTime = (timeString) => { if (!timeString) return ''; // 如果时间为空,返回空字符串 const date = new Date(timeString); const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份补零 const day = String(date.getDate()).padStart(2, '0'); // 日期补零 return `${year}-${month}-${day}`; }; this.setData({ address: item.address || '', contact: item.contact || '', phone: item.contactnumber || '', repairType: repairTypeName, repairTypeValue: repairTypeValue, description: item.faultdescription || '', imageList: item.attachments || [], replyTime: item.isReplied ? formatTime(item.repairtime) : '', replyContent: item.isReplied ? item.remark : '' }); } } wx.hideLoading(); }, submitForm: function () { // 如果正在提交中,直接返回 if (this.data.isSubmitting) { return; } if (!this.data.address || this.data.address.trim() === '') { wx.showToast({ title: '请填写地址', icon: 'none' }); this.setData({ isSubmitting: false }); return; } if (!this.data.contact || this.data.contact.trim() === '') { wx.showToast({ title: '请填写联系人', icon: 'none' }); this.setData({ isSubmitting: false }); return; } if (!this.data.phone || this.data.phone.trim() === '') { wx.showToast({ title: '请填写联系电话', icon: 'none' }); this.setData({ isSubmitting: false }); return; } if (!this.validatePhone(this.data.phone)) { wx.showToast({ title: '请输入正确的手机号', icon: 'none' }); this.setData({ isSubmitting: false }); return; } if (!this.data.repairType || this.data.repairType.trim() === '') { wx.showToast({ title: '请选择报修类型', icon: 'none' }); this.setData({ isSubmitting: false }); return; } if (!this.data.repairTypeValue || this.data.repairTypeValue.trim() === '') { wx.showToast({ title: '请选择报修类型', icon: 'none' }); this.setData({ isSubmitting: false }); return; } if (!this.data.description || this.data.description.trim() === '') { wx.showToast({ title: '请填写故障说明', icon: 'none' }); this.setData({ isSubmitting: false }); return; } const now = Date.now(); const lastSubmitTime = this.data.lastSubmitTime; // 如果距离上次提交时间小于 2 秒,直接返回 if (now - lastSubmitTime < 2000) { // wx.showToast({ // title: '请勿重复提交', // icon: 'none', // }); return; } // 更新上次提交时间 this.setData({ lastSubmitTime: now, }); const fileManager = wx.getFileSystemManager(); this.data.imageList.map(imgInfo => { const base64 = fileManager.readFileSync(imgInfo.tempFilePath, 'base64'); imgInfo.base64 = base64; return imgInfo; }) const submitData = { address: this.data.address, contact: this.data.contact, phone: this.data.phone, repairType: this.data.repairTypeValue, description: this.data.description, images: this.data.imageList, userName: app.globalData.currentAccountInfo.username, userNum: app.globalData.currentAccountInfo.usernumber }; // 设置正在提交中 防止重复点击提交按钮 this.setData({ isSubmitting: true, }); console.log('提交的数据:', submitData); wx.showLoading({ title: '提交中...', mask: true }); const that = this; wx.request({ url: app.globalData.interfaceUrls.repairRegistration, method: 'POST', header: { 'content-type': 'application/json', // 默认值 'token': app.globalData.userWxInfo.token, 'source': "wc", '!SAAS_LOGIN_TOKEN_!': app.globalData.currentAccountInfo.dsKey }, data: submitData, success(res) { wx.hideLoading(); if (res.data.code == '200') { wx.navigateTo({ url: '/pages/baoxiuSuccess/baoxiuSuccess', }); } that.setData({ isSubmitting: false }); }, fail(error) { wx.hideLoading(); wx.showToast({ title: '登记失败,请稍后再试', icon: 'none' }); that.setData({ isSubmitting: false }); }, complete: () => { this.setData({ isSubmitting: false, // 提交完成,重置标志位,可继续提交 formSubmitted: true // 在提交成功后设置标记,返回将重置表单 }); }, }) }, inputAddress: function (e) { this.setData({ address: e.detail.value }); }, onShow: function () { // 检查是否是从成功页面返回 if (this.data.formSubmitted) { // 重置表单数据 this.resetForm(); // 重置提交状态标记 this.setData({ formSubmitted: false }); } else if (!this.data.isPreviewMode) { // 非预览模式下,更新地址信息 this.setData({ address: app.globalData.currentAccountInfo.address }); } }, // 添加重置表单的方法 resetForm: function () { this.setData({ contact: '', phone: '', repairType: '', repairTypeValue: '', description: '', imageList: [] }); }, });