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

View File

@@ -37,251 +37,196 @@
</template>
<script>
import {
uploadImg
} from "@/api/system/user"
import {
addRecord
} from "@/api/inspection/record.js"
import {
addWatermarkToImage
} from "@/utils/watermark.js"
export default {
data() {
return {
form: {
inspectionType: 0,
inspectorId: this.$store.state.user.nickName,
inspectionPoint: "",
inspectionRequirements: "",
inspectionImg: "",
ImgUrl: [],
remark: ""
},
img: [],
sourceType: ['camera'],
imgFiles: "",
msgType: '',
messageText: '',
isUploading: false,
isMobileBrowser: false // 改为更通用的移动浏览器检测标志
}
},
methods: {
submit() {
if (this.isUploading) {
this.showMessage('warning', '图片正在上传中,请稍等');
return;
}
if (!Array.isArray(this.form.ImgUrl) || this.form.ImgUrl.length === 0) {
this.showMessage('error', '请选择要上传的图片');
return;
}
import { addRecord } from "@/api/inspection/record.js"
// 如果你已有 uploadImg 封装且内部就是 uni.uploadFile可以继续用
// 但前提是它支持 H5 直接传 File 对象(不是 URL 字符串)。
// 这里我示范“直接用 uni.uploadFile”的写法更稳妥。
import { addWatermarkToImage } from "@/utils/watermark.js"
import appConfig from '@/config'
const UPLOAD_URL = appConfig.baseUrl + "/common/upload" // 按你后端改
this.form.inspectionImg = this.joinList();
addRecord(this.form).then(res => {
if (res.code === 200) {
this.showMessage('success', '打卡成功');
} else {
this.showMessage('error', '打卡失败');
}
}).catch(err => {
this.showMessage('error', `提交失败: ${err.message}`);
});
},
export default {
data() {
return {
form: {
inspectionType: 0,
inspectorId: this.$store.state.user.nickName,
inspectionPoint: "",
inspectionRequirements: "",
inspectionImg: "",
ImgUrl: [], // 存后端返回的文件名/URL
remark: ""
},
img: [], // 绑定给 uni-file-picker 的预览列表
sourceType: ['camera'],
msgType: '',
messageText: '',
isUploading: false,
isMobileBrowser: false
}
},
methods: {
async submit() {
if (this.isUploading) {
this.showMessage('warning', '图片正在上传中,请稍等')
return
}
if (!Array.isArray(this.form.ImgUrl) || this.form.ImgUrl.length === 0) {
this.showMessage('error', '请选择要上传的图片')
return
}
this.form.inspectionImg = this.joinList()
try {
const res = await addRecord(this.form)
if (res.code === 200) {
this.showMessage('success', '打卡成功')
} else {
this.showMessage('error', '打卡失败')
}
} catch (err) {
this.showMessage('error', `提交失败: ${err.message}`)
}
},
deleteImg(e) {
const index = this.img.findIndex(f => f.path === e.tempFile.path);
if (index !== -1) {
this.form.ImgUrl.splice(index, 1);
this.img.splice(index, 1);
}
},
// uni-file-picker 删除e.tempFile 里通常有 {url/path},与你传给 value 的结构需一致
deleteImg(e) {
const url = e.tempFile?.url || e.tempFile?.path
const idx = this.img.findIndex(x => x.url === url)
if (idx !== -1) {
this.img.splice(idx, 1)
// 同步移除已上传结果(按你的业务,可以用同索引移除或按返回名移除)
this.form.ImgUrl.splice(idx, 1)
}
},
upload(e) {
if (e.tempFiles && e.tempFiles.length > 0) {
this.handleImageUpload(e.tempFiles[0]);
}
},
// 选择文件(支持多张)
async upload(e) {
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)
cancel() {
uni.reLaunch({
url: '/pages/work/index'
});
},
const finalFile = watermarked
joinList() {
return this.form.ImgUrl.join(',');
},
// 预览:用本地 URL仅供前端显示
const previewUrl = URL.createObjectURL(finalFile)
this.img.push({
url: previewUrl, // uni-file-picker 识别 url
name: finalFile.name || `image_${Date.now()}.jpg`,
extname: 'jpg'
})
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);
// }
});
},
// 真正上传:**不要传 previewUrl 字符串**,而是传二进制 `file`
// H5 下uni.uploadFile 支持传 `file: File`
const uploadedName = await this.uploadFileWithUni(finalFile)
// 回填后端返回的文件名/URL
this.form.ImgUrl.push(uploadedName)
},
// 专门为移动浏览器优化的压缩方法(保留兼容性)
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);
});
},
// 用 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)
})
})
},
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);
});
});
},
cancel() {
uni.reLaunch({ url: '/pages/work/index' })
},
getCurrentDate() {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
joinList() {
return this.form.ImgUrl.join(',')
},
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
},
getCurrentDate() {
const now = new Date()
const y = now.getFullYear()
const m = String(now.getMonth() + 1).padStart(2, '0')
const d = String(now.getDate()).padStart(2, '0')
const hh = String(now.getHours()).padStart(2, '0')
const mm = String(now.getMinutes()).padStart(2, '0')
const ss = String(now.getSeconds()).padStart(2, '0')
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
},
dialogConfirm() {
if (this.msgType == 'success') {
uni.reLaunch({
url: '/pages/work/index'
});
}
},
showMessage(type, text) {
this.msgType = type;
this.messageText = text;
this.$refs.alertDialog.open();
},
// 检测移动浏览器环境
checkMobileBrowser() {
// 更全面的移动设备检测
const userAgent = navigator.userAgent.toLowerCase();
const isMobile = /iphone|ipod|android|windows phone|mobile|blackberry/.test(userAgent);
// 如果是通过uni-app的web-view打开也认为是移动环境
this.isMobileBrowser = isMobile || window.__uniAppWebview;
}
},
onLoad(option) {
this.form.inspectionPoint = option.inspectionPoint || '';
this.form.inspectionRequirements = option.inspectionRequirements || '';
this.form.inspectionPointId = option.inspectionPointId || '';
},
mounted() {
this.checkMobileBrowser();
}
}
dialogConfirm() {
if (this.msgType === 'success') {
uni.reLaunch({ url: '/pages/work/index' })
}
},
showMessage(type, text) {
this.msgType = type
this.messageText = text
this.$refs.alertDialog.open()
},
checkMobileBrowser() {
const ua = navigator.userAgent.toLowerCase()
const isMobile = /iphone|ipod|android|windows phone|mobile|blackberry/.test(ua)
this.isMobileBrowser = isMobile || window.__uniAppWebview
}
},
onLoad(option) {
this.form.inspectionPoint = option.inspectionPoint || ''
this.form.inspectionRequirements = option.inspectionRequirements || ''
this.form.inspectionPointId = option.inspectionPointId || ''
},
mounted() {
this.checkMobileBrowser()
}
}
</script>
<style lang="scss">
page {
display: flex;