吾码-上传成功后V8引擎代码

// 图片上传控件 - 上传成功后事件
// 电脑端和手机端通用版
// 功能:上传后自动添加时间、记录人、部门水印,处理期间锁定控件防止重复操作

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();

 

请登录后发表评论

    没有回复内容