优化结果

This commit is contained in:
2025-09-15 19:08:47 +08:00
parent 72084a8782
commit dcfa89e63c
357 changed files with 16156 additions and 1589 deletions

View File

@@ -0,0 +1,452 @@
// 全局变量
let supportedLanguages = {};
let isTranslating = false;
// DOM元素
const elements = {
fromLang: null,
toLang: null,
inputText: null,
outputText: null,
translateBtn: null,
swapBtn: null,
clearBtn: null,
copyBtn: null,
charCount: null,
detectedLang: null,
targetLang: null,
pronounceSection: null
};
// 初始化
document.addEventListener('DOMContentLoaded', function() {
initializeElements();
loadSupportedLanguages();
bindEvents();
updateCharCount();
});
// 初始化DOM元素
function initializeElements() {
elements.fromLang = document.getElementById('from-lang');
elements.toLang = document.getElementById('to-lang');
elements.inputText = document.getElementById('input-text');
elements.outputText = document.getElementById('output-text');
elements.translateBtn = document.getElementById('translate-btn');
elements.swapBtn = document.getElementById('swap-btn');
elements.clearBtn = document.getElementById('clear-btn');
elements.copyBtn = document.getElementById('copy-btn');
elements.charCount = document.getElementById('char-count');
elements.detectedLang = document.getElementById('detected-lang');
elements.targetLang = document.getElementById('target-lang');
elements.pronounceSection = document.getElementById('pronounce-section');
}
// 加载支持的语言列表
async function loadSupportedLanguages() {
try {
const response = await fetch('https://60s.viki.moe/v2/fanyi/langs');
const data = await response.json();
if (data.code === 200 && data.data && Array.isArray(data.data)) {
// 转换数组格式为对象格式
supportedLanguages = {};
supportedLanguages['auto'] = '自动检测';
data.data.forEach(lang => {
supportedLanguages[lang.code] = lang.label;
});
populateLanguageSelectors();
} else {
throw new Error('获取语言列表失败');
}
} catch (error) {
console.error('加载语言列表失败:', error);
showToast('加载语言列表失败,请刷新页面重试', 'error');
// 使用默认语言列表
useDefaultLanguages();
}
}
// 使用默认语言列表(备用方案)
function useDefaultLanguages() {
supportedLanguages = {
'auto': '自动检测',
'zh-CHS': '中文',
'en': '英语',
'ja': '日语',
'ko': '韩语',
'fr': '法语',
'de': '德语',
'es': '西班牙语',
'ru': '俄语',
'th': '泰语',
'ar': '阿拉伯语',
'pt': '葡萄牙语',
'it': '意大利语'
};
populateLanguageSelectors();
}
// 填充语言选择器
function populateLanguageSelectors() {
const fromSelect = elements.fromLang;
const toSelect = elements.toLang;
// 清空现有选项
fromSelect.innerHTML = '';
toSelect.innerHTML = '';
// 添加语言选项
Object.entries(supportedLanguages).forEach(([code, name]) => {
const fromOption = new Option(name, code);
const toOption = new Option(name, code);
fromSelect.appendChild(fromOption);
toSelect.appendChild(toOption);
});
// 设置默认值
fromSelect.value = 'auto';
toSelect.value = 'en';
// 如果没有auto选项则设置为中文
if (!supportedLanguages['auto']) {
fromSelect.value = 'zh-CHS';
}
}
// 绑定事件
function bindEvents() {
// 输入框事件
elements.inputText.addEventListener('input', function() {
updateCharCount();
clearOutput();
});
elements.inputText.addEventListener('keydown', function(e) {
if (e.ctrlKey && e.key === 'Enter') {
translateText();
}
});
// 按钮事件
elements.translateBtn.addEventListener('click', translateText);
elements.swapBtn.addEventListener('click', swapLanguages);
elements.clearBtn.addEventListener('click', clearInput);
elements.copyBtn.addEventListener('click', copyOutput);
// 语言选择器事件
elements.fromLang.addEventListener('change', function() {
clearOutput();
updateLanguageLabels();
});
elements.toLang.addEventListener('change', function() {
clearOutput();
updateLanguageLabels();
});
}
// 更新字符计数
function updateCharCount() {
const text = elements.inputText.value;
const count = text.length;
elements.charCount.textContent = `${count}/5000`;
if (count > 5000) {
elements.charCount.style.color = '#e74c3c';
} else {
elements.charCount.style.color = '#74c69d';
}
}
// 更新语言标签
function updateLanguageLabels() {
const fromLang = elements.fromLang.value;
const toLang = elements.toLang.value;
elements.detectedLang.textContent = supportedLanguages[fromLang] || '未知语言';
elements.targetLang.textContent = supportedLanguages[toLang] || '未知语言';
}
// 翻译文本
async function translateText() {
const text = elements.inputText.value.trim();
if (!text) {
showToast('请输入要翻译的文本', 'error');
return;
}
if (text.length > 5000) {
showToast('文本长度不能超过5000字符', 'error');
return;
}
if (isTranslating) {
return;
}
setTranslating(true);
try {
const fromLang = elements.fromLang.value;
const toLang = elements.toLang.value;
// 构建请求URL
const params = new URLSearchParams({
text: text,
from: fromLang,
to: toLang
});
const response = await fetch(`https://60s.viki.moe/v2/fanyi?${params}`);
const data = await response.json();
if (data.code === 200 && data.data) {
displayTranslationResult(data.data);
} else {
throw new Error(data.msg || '翻译失败');
}
} catch (error) {
console.error('翻译失败:', error);
showToast('翻译失败: ' + error.message, 'error');
elements.outputText.textContent = '翻译失败,请重试';
} finally {
setTranslating(false);
}
}
// 显示翻译结果
function displayTranslationResult(data) {
// 显示翻译结果
const translation = data.target ? data.target.text : '';
elements.outputText.textContent = translation;
// 更新检测到的语言
if (data.source && data.source.type_desc) {
elements.detectedLang.textContent = `检测: ${data.source.type_desc}`;
}
// 显示发音信息
displayPronunciation(data);
// 如果翻译结果为空
if (!translation) {
elements.outputText.textContent = '未获取到翻译结果';
}
}
// 显示发音信息
function displayPronunciation(data) {
const pronounceSection = elements.pronounceSection;
if (!pronounceSection) {
return;
}
pronounceSection.innerHTML = '';
// 原文发音
if (data.source && data.source.pronounce) {
const sourcePhoneticDiv = document.createElement('div');
sourcePhoneticDiv.className = 'pronounce-item show';
sourcePhoneticDiv.textContent = `原文发音: [${data.source.pronounce}]`;
pronounceSection.appendChild(sourcePhoneticDiv);
}
// 译文发音
if (data.target && data.target.pronounce) {
const targetPhoneticDiv = document.createElement('div');
targetPhoneticDiv.className = 'pronounce-item show';
targetPhoneticDiv.textContent = `译文发音: [${data.target.pronounce}]`;
pronounceSection.appendChild(targetPhoneticDiv);
}
}
// 设置翻译状态
function setTranslating(translating) {
isTranslating = translating;
elements.translateBtn.disabled = translating;
if (translating) {
elements.translateBtn.classList.add('loading');
} else {
elements.translateBtn.classList.remove('loading');
}
}
// 交换语言
function swapLanguages() {
const fromValue = elements.fromLang.value;
const toValue = elements.toLang.value;
// 不能交换自动检测
if (fromValue === 'auto') {
showToast('自动检测语言无法交换', 'error');
return;
}
elements.fromLang.value = toValue;
elements.toLang.value = fromValue;
// 交换文本内容
const inputText = elements.inputText.value;
const outputText = elements.outputText.textContent;
if (outputText && outputText !== '翻译结果将在这里显示...' && outputText !== '翻译失败,请重试' && outputText !== '未获取到翻译结果') {
elements.inputText.value = outputText;
elements.outputText.textContent = inputText;
}
updateCharCount();
updateLanguageLabels();
clearPronunciation();
}
// 清空输入
function clearInput() {
elements.inputText.value = '';
updateCharCount();
clearOutput();
}
// 清空输出
function clearOutput() {
elements.outputText.textContent = '翻译结果将在这里显示...';
clearPronunciation();
}
// 清空发音信息
function clearPronunciation() {
if (elements.pronounceSection) {
elements.pronounceSection.innerHTML = '';
}
}
// 复制输出
function copyOutput() {
const text = elements.outputText.textContent;
if (!text || text === '翻译结果将在这里显示...' || text === '翻译失败,请重试' || text === '未获取到翻译结果') {
showToast('没有可复制的内容', 'error');
return;
}
// 使用现代API复制
if (navigator.clipboard) {
navigator.clipboard.writeText(text).then(() => {
showToast('已复制到剪贴板');
}).catch(() => {
fallbackCopy(text);
});
} else {
fallbackCopy(text);
}
}
// 备用复制方法
function fallbackCopy(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
showToast('已复制到剪贴板');
} catch (err) {
showToast('复制失败,请手动复制', 'error');
}
document.body.removeChild(textArea);
}
// 显示提示消息
function showToast(message, type = 'success') {
// 移除现有的toast
const existingToast = document.querySelector('.toast');
if (existingToast) {
existingToast.remove();
}
const toast = document.createElement('div');
toast.className = `toast ${type}`;
toast.textContent = message;
document.body.appendChild(toast);
// 显示toast
setTimeout(() => {
toast.classList.add('show');
}, 100);
// 自动隐藏
setTimeout(() => {
toast.classList.remove('show');
setTimeout(() => {
if (toast.parentNode) {
toast.parentNode.removeChild(toast);
}
}, 300);
}, 3000);
}
// 工具函数:防抖
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
// 添加键盘快捷键支持
document.addEventListener('keydown', function(e) {
// Ctrl+Enter 翻译
if (e.ctrlKey && e.key === 'Enter') {
e.preventDefault();
translateText();
}
// Ctrl+Shift+C 复制结果
if (e.ctrlKey && e.shiftKey && e.key === 'C') {
e.preventDefault();
copyOutput();
}
// Ctrl+Shift+X 清空输入
if (e.ctrlKey && e.shiftKey && e.key === 'X') {
e.preventDefault();
clearInput();
}
// Ctrl+Shift+S 交换语言
if (e.ctrlKey && e.shiftKey && e.key === 'S') {
e.preventDefault();
swapLanguages();
}
});
// 页面可见性变化时的处理
document.addEventListener('visibilitychange', function() {
if (document.hidden) {
// 页面隐藏时暂停翻译请求
if (isTranslating) {
setTranslating(false);
}
}
});
// 错误处理
window.addEventListener('error', function(e) {
console.error('页面错误:', e.error);
});
window.addEventListener('unhandledrejection', function(e) {
console.error('未处理的Promise拒绝:', e.reason);
});