feat: enhance HttpTTS link generation with dynamic text input and improve UI styling

This commit is contained in:
王锦强
2025-03-13 22:01:51 +08:00
parent 68b284b2c1
commit 57057688f5
4 changed files with 926 additions and 46 deletions

View File

@@ -207,16 +207,20 @@ document.addEventListener('DOMContentLoaded', function() {
// 复制HttpTTS链接按钮点击事件 // 复制HttpTTS链接按钮点击事件
copyHttpTtsLinkButton.addEventListener('click', function() { copyHttpTtsLinkButton.addEventListener('click', function() {
const text = textInput.value.trim();
if (!text) {
showCustomAlert('请输入要转换的文本', 'warning');
return;
}
const voice = voiceSelect.value; const voice = voiceSelect.value;
const style = styleSelect.value; const style = styleSelect.value;
const rate = rateInput.value;
const pitch = pitchInput.value; const pitch = pitchInput.value;
const apiKey = apiKeyInput.value.trim(); const apiKey = apiKeyInput.value.trim();
const text = "{{java.encodeURI(speakText)}}";
const rate = "{{speakSpeed*4}}";
// 构建HttpTTS链接 // 构建HttpTTS链接
let httpTtsLink = `${window.location.origin}${config.basePath}/tts?t=${text}&v=${voice}&r=${rate}&p=${pitch}&s=${style}`; let httpTtsLink = `${window.location.origin}${config.basePath}/tts?t=${encodeURIComponent(text)}&v=${voice}&r=${rate}&p=${pitch}&s=${style}`;
// 添加API Key参数如果有 // 添加API Key参数如果有
if (apiKey) { if (apiKey) {

876
web/static/js/tailwind.js Normal file

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>API文档 - TTS服务</title> <title>API文档 - TTS服务</title>
<script src="https://cdn.tailwindcss.com"></script> <script src="{{.BasePath}}/static/js/tailwind.js"></script>
<link rel="icon" type="image/svg+xml" href="{{.BasePath}}/static/icons/favicon.svg"> <link rel="icon" type="image/svg+xml" href="{{.BasePath}}/static/icons/favicon.svg">
<meta name="description" content="TTS服务API文档"> <meta name="description" content="TTS服务API文档">
<style> <style>
@@ -14,7 +14,7 @@
/* 固定渐变背景,移除动画效果 */ /* 固定渐变背景,移除动画效果 */
.bg-gradient-animated { .bg-gradient-animated {
background: linear-gradient(-45deg, #0f1a2f, #191e3a, #1a365d, #0d2f62); background: linear-gradient(-45deg, #0f1a2f, #2d3748, #1a365d, #0d2f62);
background-size: 400% 400%; background-size: 400% 400%;
position: relative; position: relative;
} }
@@ -317,7 +317,7 @@
} }
</style> </style>
</head> </head>
<body class="bg-gradient-animated text-gray-800 font-sans min-h-screen"> <body class="bg-gradient-animated text-slate-800 font-sans min-h-screen">
<!-- 激光效果 --> <!-- 激光效果 -->
<div class="laser-container"> <div class="laser-container">
<div class="glow"></div> <div class="glow"></div>
@@ -331,7 +331,7 @@
<div class="laser-beam" style="top: 90%; animation-delay: 4s;"></div> <div class="laser-beam" style="top: 90%; animation-delay: 4s;"></div>
</div> </div>
<div class="max-w-4xl mx-auto p-4 relative"> <div class="max-w-4xl mx-auto p-4">
<div class="content-area p-6 shadow-xl my-8"> <div class="content-area p-6 shadow-xl my-8">
<header class="text-center mb-8 py-4"> <header class="text-center mb-8 py-4">
<h1 class="text-4xl font-bold mb-2 text-gray-800">TTS服务 API文档</h1> <h1 class="text-4xl font-bold mb-2 text-gray-800">TTS服务 API文档</h1>
@@ -360,7 +360,7 @@
</header> </header>
<main> <main>
<section class="panel-frosted bg-white rounded-lg shadow-md p-6 mb-6"> <section class="panel-frosted bg-white/90 rounded-lg shadow-lg p-6 mb-8">
<h2 class="text-2xl font-bold mb-4 pb-2 border-b border-gray-200 text-gray-800">API概述</h2> <h2 class="text-2xl font-bold mb-4 pb-2 border-b border-gray-200 text-gray-800">API概述</h2>
<p class="mb-3">TTS服务API提供了简单而强大的方式将文本转换为自然语音。我们支持多种语言和声音并允许您调节语速、语调以适应不同场景需求。</p> <p class="mb-3">TTS服务API提供了简单而强大的方式将文本转换为自然语音。我们支持多种语言和声音并允许您调节语速、语调以适应不同场景需求。</p>
<p class="mb-3">基础URL: <code class="bg-gray-100 px-2 py-1 rounded text-sm font-mono">{{.BasePath}}</code></p> <p class="mb-3">基础URL: <code class="bg-gray-100 px-2 py-1 rounded text-sm font-mono">{{.BasePath}}</code></p>

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文本转语音 - TTS服务</title> <title>文本转语音 - TTS服务</title>
<script src="https://cdn.tailwindcss.com"></script> <script src="{{.BasePath}}/static/js/tailwind.js"></script>
<link rel="icon" type="image/svg+xml" href="{{.BasePath}}/static/icons/favicon.svg"> <link rel="icon" type="image/svg+xml" href="{{.BasePath}}/static/icons/favicon.svg">
<meta name="description" content="基于Microsoft Azure语音服务的在线文本转语音工具"> <meta name="description" content="基于Microsoft Azure语音服务的在线文本转语音工具">
<script src="{{.BasePath}}/static/js/app.js"></script> <script src="{{.BasePath}}/static/js/app.js"></script>
@@ -990,7 +990,7 @@
} }
</style> </style>
</head> </head>
<body class="bg-gradient-animated text-gray-800 font-sans min-h-screen"> <body class="bg-gradient-animated text-slate-800 font-sans min-h-screen">
<!-- 激光效果 --> <!-- 激光效果 -->
<div class="laser-container"> <div class="laser-container">
<div class="glow"></div> <div class="glow"></div>
@@ -998,10 +998,10 @@
</div> </div>
<div class="max-w-4xl mx-auto p-4 relative"> <div class="max-w-4xl mx-auto p-4 relative">
<div class="content-area p-6 shadow-xl my-8"> <div class="content-area p-6 shadow-xl my-8 rounded-xl backdrop-blur-xl bg-white/70">
<header class="text-center mb-8 py-4"> <header class="text-center mb-8 py-4">
<h1 class="text-4xl font-bold mb-2 text-gray-800">文本转语音 (TTS)</h1> <h1 class="text-4xl font-bold mb-2 text-slate-800">文本转语音 (TTS)</h1>
<p class="text-xl text-gray-600 mb-4">将文本转换为自然流畅的语音</p> <p class="text-xl text-slate-600 mb-4">将文本转换为自然流畅的语音</p>
<!-- 新Tab栏设计 --> <!-- 新Tab栏设计 -->
<div class="tab-bar mt-6"> <div class="tab-bar mt-6">
@@ -1030,11 +1030,11 @@
</header> </header>
<main> <main>
<section class="panel-frosted bg-white rounded-lg shadow-md p-6 mb-6"> <section class="panel-frosted bg-white/90 rounded-lg shadow-lg p-6 mb-6">
<!-- 替换原有的API Key管理按钮 --> <!-- 替换原有的API Key管理按钮 -->
<div class="flex justify-end mb-4"> <div class="flex justify-end mb-4">
<button id="toggle-api-key" class="manage-api-btn"> <button id="toggle-api-key" class="manage-api-btn inline-flex items-center gap-1.5 text-blue-600 bg-blue-50/80 px-3 py-1.5 rounded-md transition hover:bg-blue-100 hover:-translate-y-0.5">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="w-5 h-5">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z"/> d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z"/>
</svg> </svg>
@@ -1072,28 +1072,28 @@
</div> </div>
</div> </div>
<h2 class="text-xl font-bold mb-4 pb-2 border-b border-gray-200 text-gray-800">输入文本</h2> <h2 class="text-xl font-bold mb-4 pb-2 border-b border-slate-200 text-slate-800">输入文本</h2>
<div class="relative mb-4"> <div class="relative mb-4">
<textarea id="text" placeholder="输入要转换的文本..." rows="6" maxlength="5000" <textarea id="text" placeholder="输入要转换的文本..." rows="6" maxlength="5000"
class="w-full p-3 border border-gray-300 rounded-md resize-none focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"></textarea> class="w-full p-3 border border-slate-300 rounded-md resize-none focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 bg-white/80 backdrop-blur-sm"></textarea>
<div class="absolute bottom-2 right-2 text-sm text-gray-500"> <div class="absolute bottom-2 right-2 text-sm text-slate-500">
<span id="charCount" class="char-counter">0</span><span class="text-gray-500">/5000</span> <span id="charCount" class="char-counter">0</span><span class="text-slate-500">/5000</span>
</div> </div>
</div> </div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4"> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<div class="flex flex-col"> <div class="flex flex-col">
<label for="voice" class="mb-1 font-semibold text-gray-700">语音:</label> <label for="voice" class="mb-1 font-semibold text-slate-700">语音:</label>
<select id="voice" <select id="voice"
class="p-2 border border-gray-300 rounded-md bg-white focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"> class="p-2 border border-slate-300 rounded-md bg-white/90 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition">
<option value="loading" class="loading-text">加载中</option> <option value="loading" class="loading-text">加载中</option>
</select> </select>
</div> </div>
<div class="flex flex-col"> <div class="flex flex-col">
<label for="style" class="mb-1 font-semibold text-gray-700">风格:</label> <label for="style" class="mb-1 font-semibold text-slate-700">风格:</label>
<select id="style" <select id="style"
class="p-2 border border-gray-300 rounded-md bg-white focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"> class="p-2 border border-slate-300 rounded-md bg-white/90 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition">
<option value="loading">加载中...</option> <option value="loading">加载中...</option>
</select> </select>
</div> </div>
@@ -1103,33 +1103,33 @@
<div class="flex flex-wrap -mx-2"> <div class="flex flex-wrap -mx-2">
<div class="w-full md:w-1/2 px-2 mb-4"> <div class="w-full md:w-1/2 px-2 mb-4">
<div class="slider-label"> <div class="slider-label">
<label for="rate" class="font-semibold text-gray-700">语速:</label> <label for="rate" class="font-semibold text-slate-700">语速:</label>
<span>(调节语音的快慢程度)</span> <span class="text-xs text-slate-500 ml-2">(调节语音的快慢程度)</span>
</div> </div>
<div class="flex items-center"> <div class="flex items-center">
<input type="range" id="rate" min="-100" max="100" value="0" <input type="range" id="rate" min="-100" max="100" value="0"
class="w-full mr-2 focus:outline-none rate-slider"> class="w-full mr-2 focus:outline-none rate-slider accent-blue-600">
<span id="rateValue" class="text-sm text-gray-600 range-value">0%</span> <span id="rateValue" class="text-sm text-slate-600 range-value">0%</span>
</div> </div>
</div> </div>
<div class="w-full md:w-1/2 px-2 mb-4"> <div class="w-full md:w-1/2 px-2 mb-4">
<div class="slider-label"> <div class="slider-label">
<label for="pitch" class="font-semibold text-gray-700">语调:</label> <label for="pitch" class="font-semibold text-slate-700">语调:</label>
<span>(调节语音的高低音)</span> <span class="text-xs text-slate-500 ml-2">(调节语音的高低音)</span>
</div> </div>
<div class="flex items-center"> <div class="flex items-center">
<input type="range" id="pitch" min="-100" max="100" value="0" <input type="range" id="pitch" min="-100" max="100" value="0"
class="w-full mr-2 focus:outline-none pitch-slider"> class="w-full mr-2 focus:outline-none pitch-slider accent-blue-600">
<span id="pitchValue" class="text-sm text-gray-600 range-value">0%</span> <span id="pitchValue" class="text-sm text-slate-600 range-value">0%</span>
</div> </div>
</div> </div>
</div> </div>
<div class="flex justify-center mt-6"> <div class="flex justify-center mt-6">
<button id="speak" class="btn-neo btn-neo-primary btn-neo-pulse btn-neo-icon"> <button id="speak" class="btn-neo btn-neo-primary btn-neo-pulse btn-neo-icon inline-flex items-center gap-2 bg-gradient-to-b from-blue-500 to-blue-700 hover:from-blue-600 hover:to-blue-800 text-white px-5 py-2.5 rounded-md font-medium shadow-lg shadow-blue-500/20 hover:shadow-blue-500/40 transition hover:-translate-y-0.5 active:translate-y-0 focus:outline-none focus:ring-2 focus:ring-blue-500/50">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"
stroke-width="2"> stroke-width="2" class="w-5 h-5">
<path stroke-linecap="round" stroke-linejoin="round" <path stroke-linecap="round" stroke-linejoin="round"
d="M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z"/> d="M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z"/>
</svg> </svg>
@@ -1138,43 +1138,43 @@
</div> </div>
</section> </section>
<section id="resultSection" class="panel-frosted bg-white rounded-lg shadow-md p-6 mb-6 hidden"> <section id="resultSection" class="panel-frosted bg-white/90 rounded-lg shadow-lg p-6 mb-6 hidden">
<h2 class="text-xl font-bold mb-4 pb-2 border-b border-gray-200 text-gray-800">语音输出</h2> <h2 class="text-xl font-bold mb-4 pb-2 border-b border-slate-200 text-slate-800">语音输出</h2>
<div class="flex flex-col items-center"> <div class="flex flex-col items-center">
<audio id="audioPlayer" controls class="w-full mb-4"></audio> <audio id="audioPlayer" controls class="w-full mb-4"></audio>
<div class="flex flex-wrap justify-center"> <div class="flex flex-wrap justify-center gap-2">
<button id="download" class="btn-neo btn-neo-secondary btn-neo-icon m-1"> <button id="download" class="btn-neo btn-neo-secondary btn-neo-icon inline-flex items-center gap-1.5 bg-slate-100 hover:bg-slate-200 text-slate-700 px-4 py-2 rounded-md transition hover:-translate-y-0.5 active:translate-y-0 shadow border border-slate-200">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke="currentColor" stroke-width="2"> stroke="currentColor" stroke-width="2" class="w-5 h-5">
<path stroke-linecap="round" stroke-linejoin="round" <path stroke-linecap="round" stroke-linejoin="round"
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/> d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/>
</svg> </svg>
下载音频 下载音频
</button> </button>
<button id="copyLink" class="btn-neo btn-neo-secondary btn-neo-icon m-1"> <button id="copyLink" class="btn-neo btn-neo-secondary btn-neo-icon inline-flex items-center gap-1.5 bg-slate-100 hover:bg-slate-200 text-slate-700 px-4 py-2 rounded-md transition hover:-translate-y-0.5 active:translate-y-0 shadow border border-slate-200">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke="currentColor" stroke-width="2"> stroke="currentColor" stroke-width="2" class="w-5 h-5">
<path stroke-linecap="round" stroke-linejoin="round" <path stroke-linecap="round" stroke-linejoin="round"
d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3"/> d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3"/>
</svg> </svg>
复制链接 复制链接
</button> </button>
<button id="copyHttpTtsLink" class="btn-neo btn-neo-secondary btn-neo-icon m-1"> <button id="copyHttpTtsLink" class="btn-neo btn-neo-secondary btn-neo-icon inline-flex items-center gap-1.5 bg-slate-100 hover:bg-slate-200 text-slate-700 px-4 py-2 rounded-md transition hover:-translate-y-0.5 active:translate-y-0 shadow border border-slate-200">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke="currentColor" stroke-width="2"> stroke="currentColor" stroke-width="2" class="w-5 h-5">
<path stroke-linecap="round" stroke-linejoin="round" <path stroke-linecap="round" stroke-linejoin="round"
d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"/> d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"/>
</svg> </svg>
复制 HTTP TTS 链接 复制HttpTTS链接
</button> </button>
</div> </div>
</div> </div>
</section> </section>
</main> </main>
<footer class="text-center mt-10 py-4 text-gray-600 text-sm"> <footer class="text-center mt-10 py-4 text-slate-600 text-sm">
<p>© 2025 TTS服务 | <a href="{{.BasePath}}/api-doc" class="text-blue-500 hover:underline">API文档</a></p> <p>© 2025 TTS服务 | <a href="{{.BasePath}}/api-doc" class="text-blue-500 hover:underline">API文档</a></p>
</footer> </footer>
</div> </div>