// 图片上传控件 - 上传成功后事件
// 电脑端和手机端通用版
// 功能:上传后自动添加时间、记录人、部门水印,处理期间锁定控件防止重复操作
function getCurrentTime() {
const date = new Date();
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
const nowTime = getCurrentTime();
var userName = V8.CurrentUser.Name;
var dept = V8.CurrentUser.DeptName;
const watermarkConfig = {
imageQuality: 0.85,
maxWidth: 1280,
maxHeight: 1280,
texts: [
{
text: nowTime,
font: '16px "Microsoft YaHei"',
color: 'rgba(0, 0, 0, 1)',
position: 'bottomLeft',
margin: 20,
offsetX: 150,
offsetY: -120,
rotation: 0
},
{
text: '记录人:' + userName,
font: '20px Arial',
color: 'rgba(0, 0, 0, 1)',
position: 'bottomLeft',
margin: 20,
offsetX: 40,
offsetY: -75,
rotation: 0
},
{
text: '记录部门:' + dept,
font: '20px Arial',
color: 'rgba(0, 0, 0, 1)',
position: 'bottomLeft',
margin: 20,
offsetX: 40,
offsetY: -35,
rotation: 0
}
],
tile: false,
tileSpacing: 200,
logoUrl: 'https://x.pdyou.com/public/itdos/img/sy.png',
logoWidth: 330,
logoHeight: 200,
logoOpacity: 0.8,
logoPosition: 'bottomLeft',
logoMargin: 20,
logoOffsetX: 0,
logoOffsetY: 0,
logoRotation: 0,
showMode: 'both'
};
let cachedLogo = null;
async function loadImage(src) {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = 'anonymous';
img.onload = () => resolve(img);
img.onerror = reject;
img.src = src;
});
}
async function getLogo() {
if (cachedLogo) return cachedLogo;
try {
cachedLogo = await loadImage(watermarkConfig.logoUrl);
return cachedLogo;
} catch (e) {
return null;
}
}
async function compressAndWatermark(blob) {
// 加载图片
const url = URL.createObjectURL(blob);
const img = await loadImage(url);
URL.revokeObjectURL(url);
// 计算压缩尺寸
let width = img.width;
let height = img.height;
if (width > watermarkConfig.maxWidth || height > watermarkConfig.maxHeight) {
if (width > height) {
height = height * (watermarkConfig.maxWidth / width);
width = watermarkConfig.maxWidth;
} else {
width = width * (watermarkConfig.maxHeight / height);
height = watermarkConfig.maxHeight;
}
width = Math.round(width);
height = Math.round(height);
}
// 创建Canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
// 绘制Logo
if (watermarkConfig.showMode === 'logo' || watermarkConfig.showMode === 'both') {
const logo = await getLogo();
if (logo) {
let logoWidth = watermarkConfig.logoWidth;
let logoHeight = watermarkConfig.logoHeight;
ctx.globalAlpha = watermarkConfig.logoOpacity;
ctx.drawImage(logo, watermarkConfig.logoMargin, canvas.height - logoHeight - watermarkConfig.logoMargin, logoWidth, logoHeight);
ctx.globalAlpha = 1;
}
}
// 绘制文字
if (watermarkConfig.showMode === 'text' || watermarkConfig.showMode === 'both') {
watermarkConfig.texts.forEach(textConfig => {
ctx.font = textConfig.font;
ctx.fillStyle = textConfig.color;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
const lines = textConfig.text.split('\n');
const fontSize = parseInt(textConfig.font) || 16;
const lineHeight = fontSize * 1.5;
const maxWidth = Math.max(...lines.map(l => ctx.measureText(l).width));
const totalHeight = lines.length * lineHeight;
let x, y;
if (textConfig.position === 'bottomLeft') {
x = textConfig.margin + maxWidth / 2 + (textConfig.offsetX || 0);
y = canvas.height - textConfig.margin - totalHeight + lineHeight + (textConfig.offsetY || 0);
} else {
x = canvas.width - textConfig.margin - maxWidth / 2 + (textConfig.offsetX || 0);
y = canvas.height - textConfig.margin - totalHeight + lineHeight + (textConfig.offsetY || 0);
}
lines.forEach((line, index) => {
ctx.fillText(line, x, y + (index - (lines.length - 1) / 2) * lineHeight);
});
});
}
// 输出Blob
return new Promise((resolve) => {
canvas.toBlob(resolve, 'image/jpeg', watermarkConfig.imageQuality);
});
}
// ========== 主流程 ==========
async function processUpload() {
const fieldName = 'YongpinTP';
// 【新增功能】开始处理前,锁定图片上传控件,防止用户重复操作
try {
V8.FieldSet(fieldName, 'Readonly', true);
} catch(e) {
// 如果当前环境不支持 FieldSet,忽略错误继续执行主流程
console.warn('设置控件只读状态失败,但不影响水印处理:', e);
}
// 等待表单更新(等待图片控件完成数据写入)
await new Promise(r => setTimeout(r, 1500));
try {
// 获取当前表单数据
let currentValue = V8.Form[fieldName];
if (!currentValue) return false;
// 解析图片列表
let allImages = [];
if (typeof currentValue === 'string') {
try {
const parsed = JSON.parse(currentValue);
allImages = Array.isArray(parsed) ? parsed : [parsed];
} catch(e) { return false; }
} else if (Array.isArray(currentValue)) {
allImages = currentValue;
} else if (currentValue && currentValue.Id) {
allImages = [currentValue];
}
// 找出未处理的图片(没有 watermarked 标记的)
const pendingImages = allImages.filter(img => img && img.Name && !img.Name.includes('watermarked'));
if (pendingImages.length === 0) return false;
// 处理最新的一张
const target = pendingImages[pendingImages.length - 1];
// 构建图片URL
let imageUrl = target.Path;
if (imageUrl && !imageUrl.startsWith('http')) {
const server = V8.SysConfig.FileServer || '';
if (server) {
imageUrl = server.replace(/\/$/, '') + '/' + imageUrl.replace(/^\//, '');
}
}
if (!imageUrl) return false;
V8.Tips('添加水印中...', true);
// 下载原图
const response = await fetch(imageUrl);
const originalBlob = await response.blob();
// 压缩并添加水印
const watermarkedBlob = await compressAndWatermark(originalBlob);
// 上传水印图
const timestamp = Date.now();
const newName = target.Name.replace(/\.\w+$/, '') + '_watermarked_' + timestamp + '.jpg';
const formData = new FormData();
formData.append('file', new File([watermarkedBlob], newName, { type: 'image/jpeg' }));
formData.append('Path', '/img');
formData.append('Limit', false);
formData.append('Preview', false);
const uploadResult = await new Promise((resolve, reject) => {
V8.Post({ url: '/api/HDFS/Upload', data: formData, success: resolve, fail: reject });
});
if (uploadResult && uploadResult.Code === 1) {
// 替换原图
const newFile = {
Id: uploadResult.Data.Id,
State: 1,
Name: uploadResult.Data.Name || newName,
Size: uploadResult.Data.Size || watermarkedBlob.size,
CreateTime: uploadResult.Data.CreateTime || new Date().toISOString().replace('T', ' ').split('.')[0],
Path: uploadResult.Data.Path
};
const updatedImages = allImages.filter(img => img.Id !== target.Id);
updatedImages.push(newFile);
V8.Form[fieldName] = updatedImages;
// 更新RealPath
const server = V8.SysConfig.FileServer || '';
let realPath = newFile.Path;
if (realPath && !realPath.startsWith('http') && server) {
realPath = server.replace(/\/$/, '') + '/' + realPath.replace(/^\//, '');
}
V8.Form[`${fieldName}_${newFile.Id}_RealPath`] = realPath;
if (V8.FieldSet) {
V8.FieldSet(fieldName, 'Value', V8.Form[fieldName]);
}
V8.Tips('水印添加成功', true);
}
} catch (e) {
console.error('水印处理失败:', e);
V8.Tips('水印添加失败', false);
} finally {
// 【新增功能】无论成功还是失败,最终都要恢复控件为可编辑状态
try {
V8.FieldSet(fieldName, 'Readonly', false);
} catch(e) {
console.warn('恢复控件可编辑状态失败:', e);
}
}
return false;
}
processUpload();
没有回复内容