/**
* 主应用程序 - UI 交互逻辑
*/
import { WatermarkEngine } from './core/watermarkEngine.js';
import i18n from './i18n.js';
// 全局状态
let engine = null;
let imageQueue = [];
let processedCount = 0;
// DOM 元素
const uploadArea = document.getElementById('uploadArea');
const fileInput = document.getElementById('fileInput');
const singlePreview = document.getElementById('singlePreview');
const multiPreview = document.getElementById('multiPreview');
const imageList = document.getElementById('imageList');
const progressText = document.getElementById('progressText');
const downloadAllBtn = document.getElementById('downloadAllBtn');
const loadingOverlay = document.getElementById('loadingOverlay');
const originalCanvas = document.getElementById('originalCanvas');
const processedSection = document.getElementById('processedSection');
const processedImage = document.getElementById('processedImage');
const originalInfo = document.getElementById('originalInfo');
const processedInfo = document.getElementById('processedInfo');
const downloadBtn = document.getElementById('downloadBtn');
const resetBtn = document.getElementById('resetBtn');
const statusMessage = document.getElementById('statusMessage');
/**
* 初始化应用
*/
async function init() {
try {
await i18n.init();
setupLanguageSwitch();
showLoading(i18n.t('status.loading'));
engine = await WatermarkEngine.create();
hideLoading();
setupEventListeners();
} catch (error) {
hideLoading();
console.error('初始化错误:', error);
}
}
/**
* 设置语言切换
*/
function setupLanguageSwitch() {
const btn = document.getElementById('langSwitch');
btn.textContent = i18n.locale === 'zh-CN' ? 'EN' : '中文';
btn.addEventListener('click', async () => {
const newLocale = i18n.locale === 'zh-CN' ? 'en-US' : 'zh-CN';
await i18n.switchLocale(newLocale);
btn.textContent = newLocale === 'zh-CN' ? 'EN' : '中文';
updateDynamicTexts();
});
}
/**
* 设置事件监听器
*/
function setupEventListeners() {
uploadArea.addEventListener('click', () => fileInput.click());
fileInput.addEventListener('change', handleFileSelect);
uploadArea.addEventListener('dragover', (e) => {
e.preventDefault();
uploadArea.classList.add('dragover');
});
uploadArea.addEventListener('dragleave', () => {
uploadArea.classList.remove('dragover');
});
uploadArea.addEventListener('drop', (e) => {
e.preventDefault();
uploadArea.classList.remove('dragover');
handleFiles(Array.from(e.dataTransfer.files));
});
downloadAllBtn.addEventListener('click', downloadAll);
resetBtn.addEventListener('click', reset);
}
function reset() {
singlePreview.style.display = 'none';
multiPreview.style.display = 'none';
imageQueue = [];
processedCount = 0;
fileInput.value = '';
}
function handleFileSelect(e) {
handleFiles(Array.from(e.target.files));
}
function handleFiles(files) {
const validFiles = files.filter(file => {
if (!file.type.match('image/(jpeg|png|webp)')) return false;
if (file.size > 20 * 1024 * 1024) return false;
return true;
});
if (validFiles.length === 0) return;
imageQueue = validFiles.map((file, index) => ({
id: Date.now() + index,
file,
name: file.name,
status: 'pending',
originalImg: null,
processedBlob: null
}));
processedCount = 0;
if (validFiles.length === 1) {
singlePreview.style.display = 'block';
multiPreview.style.display = 'none';
processSingle(imageQueue[0]);
} else {
singlePreview.style.display = 'none';
multiPreview.style.display = 'block';
imageList.innerHTML = '';
updateProgress();
multiPreview.scrollIntoView({ behavior: 'smooth', block: 'start' });
imageQueue.forEach(item => createImageCard(item));
processQueue();
}
}
async function processSingle(item) {
try {
const img = await loadImage(item.file);
item.originalImg = img;
originalCanvas.width = img.width;
originalCanvas.height = img.height;
originalCanvas.getContext('2d').drawImage(img, 0, 0);
// 显示图片信息
const watermarkInfo = engine.getWatermarkInfo(img.width, img.height);
originalInfo.innerHTML = `
${i18n.t('info.size')}:${img.width} × ${img.height} px
${i18n.t('info.watermark')}:${watermarkInfo.size}×${watermarkInfo.size} px
${i18n.t('info.position')}:(${watermarkInfo.position.x}, ${watermarkInfo.position.y})
`;
const result = await engine.removeWatermarkFromImage(img);
const blob = await new Promise(resolve => result.toBlob(resolve, 'image/png'));
item.processedBlob = blob;
processedImage.src = URL.createObjectURL(blob);
processedSection.style.display = 'block';
downloadBtn.style.display = 'flex';
downloadBtn.onclick = () => downloadImage(item);
processedInfo.innerHTML = `
${i18n.t('info.size')}:${img.width} × ${img.height} px
${i18n.t('info.status')}:${i18n.t('info.removed')}
`;
processedSection.scrollIntoView({ behavior: 'smooth', block: 'start' });
} catch (error) {
console.error(error);
}
}
function createImageCard(item) {
const card = document.createElement('div');
card.id = `card-${item.id}`;
card.className = 'bg-white md:h-[130px] rounded-xl shadow-card border border-gray-100 overflow-hidden';
card.innerHTML = `