这一版本优化了很多

This commit is contained in:
王利强
2026-06-03 10:16:37 +08:00
parent 8046316216
commit 2af9f1fd59
954 changed files with 58194 additions and 1609 deletions

94
utils/watermark.js Normal file
View File

@@ -0,0 +1,94 @@
import { nextTick } from 'vue';
/**
* 前端实时渲染防作弊当前时间戳水印
* @param {Object} options
* @param {string} options.tempFilePath - 原始图片临时路径
* @param {string} options.canvasId - canvas的ID名默认为 watermarkCanvas
* @param {Object} options.canvasWidthRef - 绑定的 canvasWidth 响应式变量(ref)
* @param {Object} options.canvasHeightRef - 绑定的 canvasHeight 响应式变量(ref)
* @param {Object} options.instance - 当前Vue组件的实例 (通过 getCurrentInstance() 获取)
* @returns {Promise<string>} 渲染添加完水印后的新图片临时路径
*/
export function addTimestampWatermark({ tempFilePath, canvasId = 'watermarkCanvas', canvasWidthRef, canvasHeightRef, instance }) {
return new Promise((resolve, reject) => {
uni.getImageInfo({
src: tempFilePath,
success: (imageInfo) => {
const imgWidth = imageInfo.width;
const imgHeight = imageInfo.height;
// 动态配置 Canvas 宽高与图片 1:1 比例,确保高清晰度不失真
if (canvasWidthRef && canvasWidthRef.value !== undefined) {
canvasWidthRef.value = imgWidth;
}
if (canvasHeightRef && canvasHeightRef.value !== undefined) {
canvasHeightRef.value = imgHeight;
}
// 延迟至 nextTick 等待 UniApp 应用并渲染新的 Canvas 尺寸
nextTick(() => {
const ctx = uni.createCanvasContext(canvasId, instance);
if (!ctx) {
reject('创建水印画布上下文失败');
return;
}
// 1. 绘制原始图片
ctx.drawImage(tempFilePath, 0, 0, imgWidth, imgHeight);
// 2. 构造防作弊当前真实时间戳字符串
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');
const timeStr = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
// 3. 动态计算合适的水印字体大小(以标准 375px 屏幕下的 14px 为基准,按图片实际宽度等比缩放,保证大图下不模糊且比例完美)
const fontSize = Math.max(14, Math.floor(imgWidth * (14 / 375)));
ctx.setFontSize(fontSize);
ctx.setFillStyle('#C9CBD4'); // 水印文字颜色 #C9CBD4
// 设置半透明黑色文字阴影,确保在亮色背景下时间戳也具有极强的辨识度
ctx.setShadow(2, 2, 4, 'rgba(0, 0, 0, 0.6)');
// 4. 计算右下角坐标
const padding = fontSize;
const textWidth = timeStr.length * (fontSize * 0.55); // 估算英文字符占用宽度
const x = imgWidth - textWidth - padding;
const y = imgHeight - padding;
// 5. 渲染防作弊时间戳
ctx.fillText(timeStr, x, y);
// 6. 执行画布绘制并导出文件路径
ctx.draw(false, () => {
setTimeout(() => {
uni.canvasToTempFilePath({
canvasId: canvasId,
destWidth: imgWidth,
destHeight: imgHeight,
fileType: 'jpg',
quality: 0.9,
success: (exportRes) => {
resolve(exportRes.tempFilePath);
},
fail: (err) => {
console.error('导出带水印图片失败:', err);
reject(err);
}
}, instance);
}, 150);
});
});
},
fail: (err) => {
console.error('获取图片信息失败:', err);
reject(err);
}
});
});
}