调用大模型来翻译文本,支持oneapi newapi等兼容openai的模型格式。支持拉取所有模型,然后自己选择用哪个模型来翻译。注意:由于html在前端输入url和key,安全性弱,所以只建议在自己的和自己信任的电脑上用。使用方法:新建记事本文件,把代码复制到里面,修改后缀名为html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文本翻译工具</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #e0f7fa, #f5f5f5);
margin: 0;
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.container {
background: white;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
padding: 30px;
width: 100%;
max-width: 800px;
}
h2 {
color: #00796b;
text-align: center;
margin-bottom: 25px;
font-size: 1.8rem;
}
.text-box {
background-color: #f9f9f9;
border: 1px solid #e0e0e0;
border-radius: 8px;
margin: 15px 0;
overflow: hidden;
display: flex;
flex-direction: row;
align-items: stretch;
position: relative; /* 用于定位复制图标 */
}
textarea {
width: 50%;
height: 200px;
padding: 15px;
border: none;
resize: none;
font-size: 1rem;
background-color: transparent;
box-sizing: border-box;
}
textarea[readonly] {
background-color: #f0f0f0;
cursor: not-allowed;
}
.divider {
width: 1px;
background-color: #e0e0e0;
margin: 10px 0;
}
button {
display: block;
width: 100%;
padding: 12px;
margin: 15px 0;
background-color: #009688;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 1.1rem;
transition: background-color 0.3s, transform 0.2s;
}
button:hover {
background-color: #00796b;
transform: translateY(-2px);
}
.config {
margin: 20px 0;
padding: 15px;
background-color: #f5f5f5;
border-radius: 10px;
}
.config label {
display: block;
margin-bottom: 8px;
color: #555;
font-weight: bold;
}
.config input, .config select {
width: 100%;
padding: 10px;
margin-bottom: 10px;
border: 1px solid #e0e0e0;
border-radius: 6px;
font-size: 1rem;
background-color: white;
}
.config input[type="password"] {
letter-spacing: 2px;
}
.small-btn {
width: auto;
display: inline-block;
margin: 0 0 10px 0;
padding: 8px 16px;
font-size: 0.9rem;
}
.copy-icon {
position: absolute;
top: 10px;
right: 10px;
background-color: #607d8b;
color: white;
border: none;
border-radius: 50%;
width: 30px;
height: 30px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
transition: background-color 0.3s, transform 0.2s;
font-size: 1rem;
}
.copy-icon:hover {
background-color: #455a64;
transform: scale(1.1);
}
@media (max-width: 600px) {
.container {
padding: 20px;
margin: 10px;
}
h2 {
font-size: 1.5rem;
}
.text-box {
flex-direction: column;
}
textarea {
width: 100%;
height: 120px;
}
.divider {
width: 100%;
height: 1px;
margin: 0 0;
}
.copy-icon {
top: 140px; /* 调整位置以适应上下布局 */
}
}
</style>
</head>
<body>
<div class="container">
<h2>智能文本翻译工具</h2>
<div class="config">
<label for="apiUrl">API 端点 URL:</label>
<input type="text" id="apiUrl" value="https://api.openai.com/v1" placeholder="输入 API 端点 URL(如 https://api.openai.com/v1)">
<label for="apiKey">API 密钥:</label>
<input type="password" id="apiKey" placeholder="输入 API 密钥">
<button class="small-btn" onclick="fetchModels()">拉取模型列表</button>
<label for="modelInput">选择模型:</label>
<select id="modelInput" disabled>
<option value="">请先拉取模型列表</option>
</select>
</div>
<div class="text-box">
<textarea id="inputText" placeholder="请输入要翻译的文本..."></textarea>
<div class="divider"></div>
<textarea id="outputText" readonly placeholder="翻译结果会显示在这里..."></textarea>
<button class="copy-icon" onclick="copyToClipboard()" title="一键复制翻译结果">📋</button>
</div>
<button onclick="translateText()">翻译</button>
</div>
<script>
async function fetchModels() {
const apiUrl = document.getElementById('apiUrl').value;
const apiKey = document.getElementById('apiKey').value;
const modelSelect = document.getElementById('modelInput');
if (!apiUrl) {
alert('请输入 API 端点 URL');
return;
}
if (!apiKey) {
alert('请输入 API 密钥');
return;
}
try {
const modelsUrl = apiUrl.endsWith('/v1') ? `${apiUrl}/models` : `${apiUrl}/v1/models`;
const response = await fetch(modelsUrl, {
method: 'GET',
headers: {
'Authorization': `Bearer ${apiKey}`
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
if (data.data && data.data.length > 0) {
modelSelect.innerHTML = '';
data.data.forEach(model => {
const option = document.createElement('option');
option.value = model.id;
option.textContent = model.id;
modelSelect.appendChild(option);
});
modelSelect.disabled = false;
alert(`模型列表拉取成功!共找到 ${data.data.length} 个模型。`);
} else {
alert('未找到可用模型,请检查 API 端点和密钥。');
modelSelect.innerHTML = '<option value="">未找到模型</option>';
modelSelect.disabled = true;
}
} catch (error) {
console.error('拉取模型列表出错:', error);
alert('拉取模型列表失败,请检查网络、API 端点或密钥是否正确。');
modelSelect.innerHTML = '<option value="">拉取失败</option>';
modelSelect.disabled = true;
}
}
async function translateText() {
const inputText = document.getElementById('inputText').value;
const apiUrl = document.getElementById('apiUrl').value;
const apiKey = document.getElementById('apiKey').value;
const modelInput = document.getElementById('modelInput').value;
const outputText = document.getElementById('outputText');
if (!inputText) {
alert('请输入要翻译的文本');
return;
}
if (!apiUrl) {
alert('请输入 API 端点 URL');
return;
}
if (!apiKey) {
alert('请输入 API 密钥');
return;
}
if (!modelInput) {
alert('请选择模型');
return;
}
try {
const chatUrl = apiUrl.endsWith('/v1') ? `${apiUrl}/chat/completions` : apiUrl.includes('/v1/') ? apiUrl : `${apiUrl}/v1/chat/completions`;
const response = await fetch(chatUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`
},
body: JSON.stringify({
model: modelInput,
messages: [
{ role: 'system', content: '你是一个专业的翻译助手,直接将用户输入的中文翻译成英文,不要添加任何前缀或额外说明。' },
{ role: 'user', content: inputText }
],
temperature: 0.3
})
});
const data = await response.json();
if (data.choices && data.choices.length > 0) {
outputText.value = data.choices[0].message.content;
} else {
outputText.value = '翻译失败,请重试。';
}
} catch (error) {
console.error('翻译出错:', error);
outputText.value = '翻译过程中出现错误,请检查网络、API 端点、密钥或模型名称是否正确。';
}
}
function copyToClipboard() {
const outputText = document.getElementById('outputText');
if (outputText.value.trim() === '') {
alert('翻译结果为空,无法复制!');
return;
}
outputText.select();
try {
document.execCommand('copy');
alert('翻译结果已复制到剪贴板!');
} catch (err) {
console.error('复制失败:', err);
alert('复制失败,请手动复制!');
}
}
</script>
</body>
</html>