feat: implement localStorage functionality for TTS form data persistence
This commit is contained in:
@@ -26,6 +26,131 @@ function saveApiKey() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 保存表单数据到localStorage
|
||||||
|
function saveFormData() {
|
||||||
|
const textInput = document.getElementById('text');
|
||||||
|
const voiceSelect = document.getElementById('voice');
|
||||||
|
const styleSelect = document.getElementById('style');
|
||||||
|
const rateInput = document.getElementById('rate');
|
||||||
|
const pitchInput = document.getElementById('pitch');
|
||||||
|
|
||||||
|
// 保存文本内容
|
||||||
|
if (textInput && textInput.value) {
|
||||||
|
localStorage.setItem('ttsText', textInput.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存语音选择
|
||||||
|
if (voiceSelect && voiceSelect.value) {
|
||||||
|
localStorage.setItem('ttsVoice', voiceSelect.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存风格选择
|
||||||
|
if (styleSelect && styleSelect.value) {
|
||||||
|
localStorage.setItem('ttsStyle', styleSelect.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存语速
|
||||||
|
if (rateInput && rateInput.value) {
|
||||||
|
localStorage.setItem('ttsRate', rateInput.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存语调
|
||||||
|
if (pitchInput && pitchInput.value) {
|
||||||
|
localStorage.setItem('ttsPitch', pitchInput.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从localStorage加载表单数据
|
||||||
|
function loadFormData() {
|
||||||
|
const textInput = document.getElementById('text');
|
||||||
|
const voiceSelect = document.getElementById('voice');
|
||||||
|
const styleSelect = document.getElementById('style');
|
||||||
|
const rateInput = document.getElementById('rate');
|
||||||
|
const rateValue = document.getElementById('rateValue');
|
||||||
|
const pitchInput = document.getElementById('pitch');
|
||||||
|
const pitchValue = document.getElementById('pitchValue');
|
||||||
|
|
||||||
|
// 加载文本内容
|
||||||
|
const savedText = localStorage.getItem('ttsText');
|
||||||
|
if (savedText && textInput) {
|
||||||
|
textInput.value = savedText;
|
||||||
|
// 更新字符计数
|
||||||
|
if (document.getElementById('charCount')) {
|
||||||
|
document.getElementById('charCount').textContent = savedText.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载语速
|
||||||
|
const savedRate = localStorage.getItem('ttsRate');
|
||||||
|
if (savedRate && rateInput) {
|
||||||
|
rateInput.value = savedRate;
|
||||||
|
if (rateValue) {
|
||||||
|
rateValue.textContent = savedRate + '%';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载语调
|
||||||
|
const savedPitch = localStorage.getItem('ttsPitch');
|
||||||
|
if (savedPitch && pitchInput) {
|
||||||
|
pitchInput.value = savedPitch;
|
||||||
|
if (pitchValue) {
|
||||||
|
pitchValue.textContent = savedPitch + '%';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存风格选择的值,以便在语音加载后使用
|
||||||
|
const savedStyle = localStorage.getItem('ttsStyle');
|
||||||
|
|
||||||
|
// 加载语音选择(在语音列表加载完成后处理)
|
||||||
|
const savedVoice = localStorage.getItem('ttsVoice');
|
||||||
|
if (savedVoice && voiceSelect) {
|
||||||
|
// 在initVoicesList完成后设置
|
||||||
|
const voiceLoadInterval = setInterval(() => {
|
||||||
|
if (voiceSelect.options.length > 0 && voiceSelect.options[0].value !== "loading") {
|
||||||
|
for (let i = 0; i < voiceSelect.options.length; i++) {
|
||||||
|
if (voiceSelect.options[i].value === savedVoice) {
|
||||||
|
voiceSelect.selectedIndex = i;
|
||||||
|
// 触发change事件以更新风格选项
|
||||||
|
const event = new Event('change');
|
||||||
|
voiceSelect.dispatchEvent(event);
|
||||||
|
|
||||||
|
// 在语音选择更新后,设置保存的风格
|
||||||
|
// 使用setTimeout确保风格选项已经更新
|
||||||
|
setTimeout(() => {
|
||||||
|
if (savedStyle && styleSelect && styleSelect.options.length > 0) {
|
||||||
|
for (let j = 0; j < styleSelect.options.length; j++) {
|
||||||
|
if (styleSelect.options[j].value === savedStyle) {
|
||||||
|
styleSelect.selectedIndex = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clearInterval(voiceLoadInterval);
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
} else {
|
||||||
|
// 如果没有保存的语音选择,但有保存的风格,直接尝试设置风格
|
||||||
|
if (savedStyle && styleSelect) {
|
||||||
|
const styleLoadInterval = setInterval(() => {
|
||||||
|
if (styleSelect.options.length > 0) {
|
||||||
|
for (let i = 0; i < styleSelect.options.length; i++) {
|
||||||
|
if (styleSelect.options[i].value === savedStyle) {
|
||||||
|
styleSelect.selectedIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clearInterval(styleLoadInterval);
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
// 获取DOM元素
|
// 获取DOM元素
|
||||||
const textInput = document.getElementById('text');
|
const textInput = document.getElementById('text');
|
||||||
@@ -58,27 +183,42 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
initVoicesList();
|
initVoicesList();
|
||||||
initEventListeners();
|
initEventListeners();
|
||||||
loadApiKeyFromLocalStorage(); // 加载API Key
|
loadApiKeyFromLocalStorage(); // 加载API Key
|
||||||
|
loadFormData(); // 加载表单数据
|
||||||
|
|
||||||
// 更新字符计数
|
// 更新字符计数
|
||||||
textInput.addEventListener('input', function () {
|
textInput.addEventListener('input', function () {
|
||||||
charCount.textContent = this.value.length;
|
charCount.textContent = this.value.length;
|
||||||
|
// 保存文本内容
|
||||||
|
localStorage.setItem('ttsText', this.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 更新语速值显示
|
// 更新语速值显示
|
||||||
rateInput.addEventListener('input', function () {
|
rateInput.addEventListener('input', function () {
|
||||||
const value = this.value;
|
const value = this.value;
|
||||||
rateValue.textContent = value + '%';
|
rateValue.textContent = value + '%';
|
||||||
|
// 保存语速
|
||||||
|
localStorage.setItem('ttsRate', value);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 更新语调值显示
|
// 更新语调值显示
|
||||||
pitchInput.addEventListener('input', function () {
|
pitchInput.addEventListener('input', function () {
|
||||||
const value = this.value;
|
const value = this.value;
|
||||||
pitchValue.textContent = value + '%';
|
pitchValue.textContent = value + '%';
|
||||||
|
// 保存语调
|
||||||
|
localStorage.setItem('ttsPitch', value);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 语音选择变化时更新可用风格
|
// 语音选择变化时更新可用风格
|
||||||
voiceSelect.addEventListener('change', function () {
|
voiceSelect.addEventListener('change', function () {
|
||||||
updateStyleOptions();
|
updateStyleOptions();
|
||||||
|
// 保存语音选择
|
||||||
|
localStorage.setItem('ttsVoice', this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加风格选择变化事件
|
||||||
|
styleSelect.addEventListener('change', function() {
|
||||||
|
// 保存风格选择
|
||||||
|
localStorage.setItem('ttsStyle', this.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 获取可用语音列表
|
// 获取可用语音列表
|
||||||
@@ -179,6 +319,17 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
|
|
||||||
styleSelect.appendChild(option);
|
styleSelect.appendChild(option);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 在风格选项更新后,尝试恢复保存的风格设置
|
||||||
|
const savedStyle = localStorage.getItem('ttsStyle');
|
||||||
|
if (savedStyle) {
|
||||||
|
for (let i = 0; i < styleSelect.options.length; i++) {
|
||||||
|
if (styleSelect.options[i].value === savedStyle) {
|
||||||
|
styleSelect.selectedIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化事件监听器
|
// 初始化事件监听器
|
||||||
@@ -295,6 +446,9 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
const pitch = pitchInput.value;
|
const pitch = pitchInput.value;
|
||||||
const apiKey = apiKeyInput.value.trim();
|
const apiKey = apiKeyInput.value.trim();
|
||||||
|
|
||||||
|
// 保存表单数据
|
||||||
|
saveFormData();
|
||||||
|
|
||||||
// 禁用按钮,显示加载状态
|
// 禁用按钮,显示加载状态
|
||||||
speakButton.disabled = true;
|
speakButton.disabled = true;
|
||||||
speakButton.textContent = '生成中...';
|
speakButton.textContent = '生成中...';
|
||||||
|
|||||||
@@ -557,6 +557,9 @@ curl ${baseUrl}/v1/audio/speech \\
|
|||||||
const pitch = document.getElementById('pitch').value;
|
const pitch = document.getElementById('pitch').value;
|
||||||
const style = document.getElementById('style').value; // 获取选择的风格
|
const style = document.getElementById('style').value; // 获取选择的风格
|
||||||
|
|
||||||
|
// 保存表单值到localStorage
|
||||||
|
saveFormValuesToLocalStorage(voice, rate, pitch, style, document.getElementById('text').value);
|
||||||
|
|
||||||
if (!text) {
|
if (!text) {
|
||||||
showError('请输入要转换的文本', '文本内容不能为空');
|
showError('请输入要转换的文本', '文本内容不能为空');
|
||||||
return;
|
return;
|
||||||
@@ -604,6 +607,52 @@ curl ${baseUrl}/v1/audio/speech \\
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 保存表单值到localStorage的函数
|
||||||
|
function saveFormValuesToLocalStorage(voice, rate, pitch, style, text) {
|
||||||
|
localStorage.setItem('tts_voice', voice);
|
||||||
|
localStorage.setItem('tts_rate', rate);
|
||||||
|
localStorage.setItem('tts_pitch', pitch);
|
||||||
|
localStorage.setItem('tts_style', style);
|
||||||
|
localStorage.setItem('tts_text', text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从localStorage加载表单值的函数
|
||||||
|
function loadFormValuesFromLocalStorage() {
|
||||||
|
const voice = localStorage.getItem('tts_voice');
|
||||||
|
const rate = localStorage.getItem('tts_rate');
|
||||||
|
const pitch = localStorage.getItem('tts_pitch');
|
||||||
|
const style = localStorage.getItem('tts_style');
|
||||||
|
const text = localStorage.getItem('tts_text');
|
||||||
|
|
||||||
|
// 设置语音选择(在语音列表加载完成后设置)
|
||||||
|
if (voice) {
|
||||||
|
const voiceSelect = document.getElementById('voice');
|
||||||
|
// 我们将在语音列表加载完成后设置这个值
|
||||||
|
voiceSelect.dataset.savedValue = voice;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置语速
|
||||||
|
if (rate) {
|
||||||
|
const rateInput = document.getElementById('rate');
|
||||||
|
rateInput.value = rate;
|
||||||
|
document.getElementById('rateValue').textContent = rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置音调
|
||||||
|
if (pitch) {
|
||||||
|
const pitchInput = document.getElementById('pitch');
|
||||||
|
pitchInput.value = pitch;
|
||||||
|
document.getElementById('pitchValue').textContent = pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置文本(如果有)
|
||||||
|
if (text) {
|
||||||
|
document.getElementById('text').value = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 风格将在语音选择后设置
|
||||||
|
}
|
||||||
|
|
||||||
// 显示错误信息的函数
|
// 显示错误信息的函数
|
||||||
function showError(title, message) {
|
function showError(title, message) {
|
||||||
const errorAlert = document.getElementById('apiErrorAlert');
|
const errorAlert = document.getElementById('apiErrorAlert');
|
||||||
@@ -621,10 +670,10 @@ curl ${baseUrl}/v1/audio/speech \\
|
|||||||
// 清空现有选项
|
// 清空现有选项
|
||||||
styleSelect.innerHTML = '';
|
styleSelect.innerHTML = '';
|
||||||
|
|
||||||
// 默认无风格
|
// 默认添加标准风格
|
||||||
const defaultOption = document.createElement('option');
|
const defaultOption = document.createElement('option');
|
||||||
defaultOption.value = '';
|
defaultOption.value = 'general';
|
||||||
defaultOption.text = '无风格';
|
defaultOption.text = '标准';
|
||||||
styleSelect.appendChild(defaultOption);
|
styleSelect.appendChild(defaultOption);
|
||||||
|
|
||||||
// 查找选定的语音对象
|
// 查找选定的语音对象
|
||||||
@@ -646,6 +695,11 @@ curl ${baseUrl}/v1/audio/speech \\
|
|||||||
styleSelect.appendChild(option);
|
styleSelect.appendChild(option);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加风格选择变化事件监听器
|
||||||
|
styleSelect.addEventListener('change', function() {
|
||||||
|
localStorage.setItem('tts_style', this.value);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 风格名称本地化显示
|
// 风格名称本地化显示
|
||||||
@@ -721,14 +775,53 @@ curl ${baseUrl}/v1/audio/speech \\
|
|||||||
addVoiceGroup(voiceSelect, '其他语言 (Other Languages)', otherVoices);
|
addVoiceGroup(voiceSelect, '其他语言 (Other Languages)', otherVoices);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 默认选择晓晓多语言
|
// 尝试恢复保存的语音选择
|
||||||
const defaultVoice = 'zh-CN-XiaoxiaoMultilingualNeural';
|
const savedVoice = voiceSelect.dataset.savedValue;
|
||||||
if (voiceSelect.querySelector(\`option[value="\${defaultVoice}"]\`)) {
|
if (savedVoice && voiceSelect.querySelector(\`option[value="\${savedVoice}"]\`)) {
|
||||||
voiceSelect.value = defaultVoice;
|
voiceSelect.value = savedVoice;
|
||||||
|
} else {
|
||||||
|
// 默认选择晓晓多语言
|
||||||
|
const defaultVoice = 'zh-CN-XiaoxiaoMultilingualNeural';
|
||||||
|
if (voiceSelect.querySelector(\`option[value="\${defaultVoice}"]\`)) {
|
||||||
|
voiceSelect.value = defaultVoice;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载初始选择语音的风格选项
|
// 加载初始选择语音的风格选项
|
||||||
updateStyleOptions(voiceSelect.value);
|
updateStyleOptions(voiceSelect.value);
|
||||||
|
|
||||||
|
// 尝试恢复保存的风格选择
|
||||||
|
const savedStyle = localStorage.getItem('tts_style');
|
||||||
|
if (savedStyle) {
|
||||||
|
setTimeout(() => {
|
||||||
|
const styleSelect = document.getElementById('style');
|
||||||
|
if (styleSelect.querySelector(\`option[value="\${savedStyle}"]\`)) {
|
||||||
|
styleSelect.value = savedStyle;
|
||||||
|
}
|
||||||
|
}, 100); // 给updateStyleOptions一点时间来填充选项
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加语音选择变化事件监听器,保存选择到localStorage
|
||||||
|
voiceSelect.addEventListener('change', function() {
|
||||||
|
localStorage.setItem('tts_voice', this.value);
|
||||||
|
updateStyleOptions(this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加语速变化事件监听器
|
||||||
|
document.getElementById('rate').addEventListener('change', function() {
|
||||||
|
localStorage.setItem('tts_rate', this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加音调变化事件监听器
|
||||||
|
document.getElementById('pitch').addEventListener('change', function() {
|
||||||
|
localStorage.setItem('tts_pitch', this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加文本变化事件监听器
|
||||||
|
document.getElementById('text').addEventListener('input', function() {
|
||||||
|
localStorage.setItem('tts_text', this.value);
|
||||||
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
console.error('获取语音列表失败:', response.status);
|
console.error('获取语音列表失败:', response.status);
|
||||||
showDefaultVoices();
|
showDefaultVoices();
|
||||||
@@ -804,6 +897,10 @@ curl ${baseUrl}/v1/audio/speech \\
|
|||||||
|
|
||||||
// 页面加载完成后加载语音列表
|
// 页面加载完成后加载语音列表
|
||||||
window.onload = function() {
|
window.onload = function() {
|
||||||
|
// 先加载保存的表单值
|
||||||
|
loadFormValuesFromLocalStorage();
|
||||||
|
|
||||||
|
// 然后加载语音列表
|
||||||
loadVoices();
|
loadVoices();
|
||||||
|
|
||||||
// API Key 相关功能
|
// API Key 相关功能
|
||||||
@@ -821,7 +918,10 @@ curl ${baseUrl}/v1/audio/speech \\
|
|||||||
const rate = document.getElementById('rate').value;
|
const rate = document.getElementById('rate').value;
|
||||||
const pitch = document.getElementById('pitch').value;
|
const pitch = document.getElementById('pitch').value;
|
||||||
const style = document.getElementById('style').value;
|
const style = document.getElementById('style').value;
|
||||||
const displayName = document.getElementById('voice').options[document.getElementById('voice').selectedIndex].text || '微软TTS';
|
const displayName = '微软TTS'; // 可以根据需要修改默认名称
|
||||||
|
|
||||||
|
// 保存当前设置到localStorage
|
||||||
|
saveFormValuesToLocalStorage(voice, rate, pitch, style, document.getElementById('text').value);
|
||||||
|
|
||||||
// 构建URL参数
|
// 构建URL参数
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
|
|||||||
Reference in New Issue
Block a user