This commit is contained in:
2025-09-04 21:06:29 +08:00
parent 2bf56a5789
commit f063ba779d

View File

@@ -37,15 +37,14 @@
</template> </template>
<script> <script>
import { import { addRecord } from "@/api/inspection/record.js"
uploadImg // 如果你已有 uploadImg 封装且内部就是 uni.uploadFile可以继续用
} from "@/api/system/user" // 但前提是它支持 H5 直接传 File 对象(不是 URL 字符串)。
import { // 这里我示范“直接用 uni.uploadFile”的写法更稳妥。
addRecord import { addWatermarkToImage } from "@/utils/watermark.js"
} from "@/api/inspection/record.js" import appConfig from '@/config'
import { const UPLOAD_URL = appConfig.baseUrl + "/common/upload" // 按你后端改
addWatermarkToImage
} from "@/utils/watermark.js"
export default { export default {
data() { data() {
return { return {
@@ -55,233 +54,179 @@
inspectionPoint: "", inspectionPoint: "",
inspectionRequirements: "", inspectionRequirements: "",
inspectionImg: "", inspectionImg: "",
ImgUrl: [], ImgUrl: [], // 存后端返回的文件名/URL
remark: "" remark: ""
}, },
img: [], img: [], // 绑定给 uni-file-picker 的预览列表
sourceType: ['camera'], sourceType: ['camera'],
imgFiles: "",
msgType: '', msgType: '',
messageText: '', messageText: '',
isUploading: false, isUploading: false,
isMobileBrowser: false // 改为更通用的移动浏览器检测标志 isMobileBrowser: false
} }
}, },
methods: { methods: {
submit() { async submit() {
if (this.isUploading) { if (this.isUploading) {
this.showMessage('warning', '图片正在上传中,请稍等'); this.showMessage('warning', '图片正在上传中,请稍等')
return; return
} }
if (!Array.isArray(this.form.ImgUrl) || this.form.ImgUrl.length === 0) { if (!Array.isArray(this.form.ImgUrl) || this.form.ImgUrl.length === 0) {
this.showMessage('error', '请选择要上传的图片'); this.showMessage('error', '请选择要上传的图片')
return; return
} }
this.form.inspectionImg = this.joinList()
this.form.inspectionImg = this.joinList(); try {
addRecord(this.form).then(res => { const res = await addRecord(this.form)
if (res.code === 200) { if (res.code === 200) {
this.showMessage('success', '打卡成功'); this.showMessage('success', '打卡成功')
} else { } else {
this.showMessage('error', '打卡失败'); this.showMessage('error', '打卡失败')
}
} catch (err) {
this.showMessage('error', `提交失败: ${err.message}`)
} }
}).catch(err => {
this.showMessage('error', `提交失败: ${err.message}`);
});
}, },
// uni-file-picker 删除e.tempFile 里通常有 {url/path},与你传给 value 的结构需一致
deleteImg(e) { deleteImg(e) {
const index = this.img.findIndex(f => f.path === e.tempFile.path); const url = e.tempFile?.url || e.tempFile?.path
if (index !== -1) { const idx = this.img.findIndex(x => x.url === url)
this.form.ImgUrl.splice(index, 1); if (idx !== -1) {
this.img.splice(index, 1); this.img.splice(idx, 1)
// 同步移除已上传结果(按你的业务,可以用同索引移除或按返回名移除)
this.form.ImgUrl.splice(idx, 1)
} }
}, },
upload(e) { // 选择文件(支持多张)
if (e.tempFiles && e.tempFiles.length > 0) { async upload(e) {
this.handleImageUpload(e.tempFiles[0]); if (!e?.tempFiles?.length) return
if (this.isUploading) {
this.showMessage('warning', '图片正在上传中,请稍等')
return
}
this.isUploading = true
try {
// 逐张处理
for (const tf of e.tempFiles) {
await this.handleImageUpload(tf) // 这里传入每个 tempFile
}
this.showMessage('success', '图片处理/上传完成')
} catch (err) {
console.error(err)
this.showMessage('error', `图片上传失败:${err.message || err}`)
} finally {
this.isUploading = false
} }
}, },
// 单张处理:加水印 ->(可选)压缩 -> 上传
async handleImageUpload(tempFile) {
// tempFile.file: H5 下是 File 对象App/小程序是临时路径
const raw = tempFile.file || tempFile // 兼容各端
// 生成水印文字
const watermarkText = `${this.form.inspectionPoint || '未命名地点'} \n${this.getCurrentDate()}`
// 加水印(返回 File/Blob
const watermarked = await addWatermarkToImage(raw, watermarkText)
// 可选:移动端压缩(你已有方法,按需启用)
// const finalFile = await this.compressImageForMobile(watermarked)
const finalFile = watermarked
// 预览:用本地 URL仅供前端显示
const previewUrl = URL.createObjectURL(finalFile)
this.img.push({
url: previewUrl, // uni-file-picker 识别 url
name: finalFile.name || `image_${Date.now()}.jpg`,
extname: 'jpg'
})
// 真正上传:**不要传 previewUrl 字符串**,而是传二进制 `file`
// H5 下uni.uploadFile 支持传 `file: File`
const uploadedName = await this.uploadFileWithUni(finalFile)
// 回填后端返回的文件名/URL
this.form.ImgUrl.push(uploadedName)
},
// 用 uni.uploadFile 直接传二进制
uploadFileWithUni(file) {
return new Promise((resolve, reject) => {
uni.uploadFile({
url: UPLOAD_URL,
name: 'file', // 后端接收字段名(按你的后端改)
file, // H5 直接传 File 对象(重点!)
// 如果后端还需要额外字段:
// formData: { bizType: 'inspection' },
success: (res) => {
try {
const data = typeof res.data === 'string' ? JSON.parse(res.data) : res.data
if (data.code === 200) {
// 假设后端返回 { code:200, fileName: 'xxx.jpg', url:'...' }
resolve(data.fileName || data.url)
} else {
reject(new Error(data.msg || '上传失败'))
}
} catch (e) {
reject(new Error('上传响应解析失败'))
}
},
fail: (err) => reject(err)
})
})
},
cancel() { cancel() {
uni.reLaunch({ uni.reLaunch({ url: '/pages/work/index' })
url: '/pages/work/index'
});
}, },
joinList() { joinList() {
return this.form.ImgUrl.join(','); return this.form.ImgUrl.join(',')
},
handleImageUpload(file) {
if (this.isUploading) {
this.showMessage('warning', '图片正在上传中,请稍等');
return;
}
this.isUploading = true;
// 添加水印
this.addWatermarkToImage(file, (watermarkedFile) => {
// 检查是否为移动浏览器且文件大小大于300KB
// if (this.checkMobileBrowser() && watermarkedFile.size > 300 * 1024) {
// 压缩图片
// this.compressImageForMobile(watermarkedFile, (compressedFile) => {
// 上传文件
// this.uploadFile(compressedFile);
// });
// } else {
// 直接上传
this.uploadFile(watermarkedFile);
// }
});
},
// 专门为移动浏览器优化的压缩方法(保留兼容性)
compressImageForMobile(file, quality = 0.6, maxWidth = 1200, maxHeight = 1200) {
return new Promise((resolve, reject) => {
const img = new Image();
const reader = new FileReader();
reader.onload = (event) => {
img.onload = () => {
// 计算压缩比例
let width = img.width;
let height = img.height;
// 限制最大尺寸
if (width > maxWidth || height > maxHeight) {
const ratio = Math.min(maxWidth / width, maxHeight / height);
width = Math.floor(width * ratio);
height = Math.floor(height * ratio);
}
// 创建canvas
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
// 设置更高的压缩质量
ctx.imageSmoothingQuality = 'high';
ctx.drawImage(img, 0, 0, width, height);
// 使用toBlob的polyfill保证兼容性
if (canvas.toBlob) {
canvas.toBlob(
(blob) => {
if (!blob) {
console.warn('压缩失败,返回原始文件');
resolve(file);
return;
}
// 创建压缩后的文件对象
const compressedFile = new File([blob], file.name, {
type: 'image/jpeg',
lastModified: Date.now()
});
resolve(compressedFile);
},
'image/jpeg',
quality
);
} else {
// 不支持toBlob的浏览器直接返回原文件
console.warn('浏览器不支持toBlob方法无法压缩');
resolve(file);
}
};
img.onerror = () => {
console.warn('图片加载失败,返回原始文件');
resolve(file);
};
img.src = event.target.result;
};
reader.onerror = () => {
console.warn('文件读取失败,返回原始文件');
resolve(file);
};
reader.readAsDataURL(file);
});
},
async uploadFile(file) {
return new Promise((resolve, reject) => {
// 创建预览URL用于显示
const previewUrl = URL.createObjectURL(file);
// 实际上传
uploadImg({
filePath: previewUrl
}).then(res => {
this.form.ImgUrl.push(res.fileName);
resolve(previewUrl);
}).catch(err => {
reject(err);
});
});
}, },
getCurrentDate() { getCurrentDate() {
const now = new Date(); const now = new Date()
const year = now.getFullYear(); const y = now.getFullYear()
const month = String(now.getMonth() + 1).padStart(2, '0'); const m = String(now.getMonth() + 1).padStart(2, '0')
const day = String(now.getDate()).padStart(2, '0'); const d = String(now.getDate()).padStart(2, '0')
const hours = String(now.getHours()).padStart(2, '0'); const hh = String(now.getHours()).padStart(2, '0')
const minutes = String(now.getMinutes()).padStart(2, '0'); const mm = String(now.getMinutes()).padStart(2, '0')
const seconds = String(now.getSeconds()).padStart(2, '0'); const ss = String(now.getSeconds()).padStart(2, '0')
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}, },
dialogConfirm() { dialogConfirm() {
if (this.msgType == 'success') { if (this.msgType === 'success') {
uni.reLaunch({ uni.reLaunch({ url: '/pages/work/index' })
url: '/pages/work/index'
});
} }
}, },
showMessage(type, text) { showMessage(type, text) {
this.msgType = type; this.msgType = type
this.messageText = text; this.messageText = text
this.$refs.alertDialog.open(); this.$refs.alertDialog.open()
}, },
// 检测移动浏览器环境
checkMobileBrowser() { checkMobileBrowser() {
// 更全面的移动设备检测 const ua = navigator.userAgent.toLowerCase()
const userAgent = navigator.userAgent.toLowerCase(); const isMobile = /iphone|ipod|android|windows phone|mobile|blackberry/.test(ua)
const isMobile = /iphone|ipod|android|windows phone|mobile|blackberry/.test(userAgent); this.isMobileBrowser = isMobile || window.__uniAppWebview
// 如果是通过uni-app的web-view打开也认为是移动环境
this.isMobileBrowser = isMobile || window.__uniAppWebview;
} }
}, },
onLoad(option) { onLoad(option) {
this.form.inspectionPoint = option.inspectionPoint || ''; this.form.inspectionPoint = option.inspectionPoint || ''
this.form.inspectionRequirements = option.inspectionRequirements || ''; this.form.inspectionRequirements = option.inspectionRequirements || ''
this.form.inspectionPointId = option.inspectionPointId || ''; this.form.inspectionPointId = option.inspectionPointId || ''
}, },
mounted() { mounted() {
this.checkMobileBrowser(); this.checkMobileBrowser()
} }
} }
</script> </script>
<style lang="scss"> <style lang="scss">
page { page {
display: flex; display: flex;