11
This commit is contained in:
103
src/services/soundPromptStorage.js
Normal file
103
src/services/soundPromptStorage.js
Normal file
@@ -0,0 +1,103 @@
|
||||
/** 克隆音色本地存储(对齐 Electron be.list/add/update/delete SoundPrompt) */
|
||||
|
||||
import { findSystemVoice } from "../data/systemVoices.js";
|
||||
|
||||
const STORAGE_KEY = "aiclient_sound_prompts";
|
||||
|
||||
/**
|
||||
* @typedef {{ id: string, title: string, content: { url?: string, promptText?: string, aliyunVoiceId?: string } }} SoundPromptRecord
|
||||
*/
|
||||
|
||||
/** @returns {SoundPromptRecord[]} */
|
||||
export function listCloneVoices() {
|
||||
try {
|
||||
const raw = localStorage.getItem(STORAGE_KEY);
|
||||
if (!raw) return [];
|
||||
const data = JSON.parse(raw);
|
||||
return Array.isArray(data) ? data : [];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {SoundPromptRecord[]} list */
|
||||
function saveCloneVoices(list) {
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(list));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{ title: string, content?: SoundPromptRecord['content'] }} payload
|
||||
* @returns {SoundPromptRecord}
|
||||
*/
|
||||
export function addCloneVoice(payload) {
|
||||
const list = listCloneVoices();
|
||||
const record = {
|
||||
id: `clone_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
|
||||
title: String(payload.title || "").trim(),
|
||||
content: {
|
||||
url: payload.content?.url || "",
|
||||
promptText: payload.content?.promptText || "",
|
||||
aliyunVoiceId: payload.content?.aliyunVoiceId || "",
|
||||
},
|
||||
};
|
||||
list.unshift(record);
|
||||
saveCloneVoices(list);
|
||||
return record;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} id
|
||||
* @param {{ title: string, content?: SoundPromptRecord['content'] }} payload
|
||||
*/
|
||||
export function updateCloneVoice(id, payload) {
|
||||
const list = listCloneVoices();
|
||||
const idx = list.findIndex((item) => item.id === id);
|
||||
if (idx < 0) return null;
|
||||
list[idx] = {
|
||||
...list[idx],
|
||||
title: String(payload.title || "").trim(),
|
||||
content: {
|
||||
...list[idx].content,
|
||||
...payload.content,
|
||||
},
|
||||
};
|
||||
saveCloneVoices(list);
|
||||
return list[idx];
|
||||
}
|
||||
|
||||
/** @param {string} id */
|
||||
export function deleteCloneVoice(id) {
|
||||
const list = listCloneVoices().filter((item) => item.id !== id);
|
||||
saveCloneVoices(list);
|
||||
}
|
||||
|
||||
/** @param {string} id */
|
||||
export function getCloneVoice(id) {
|
||||
return listCloneVoices().find((item) => item.id === id) ?? null;
|
||||
}
|
||||
|
||||
/** @param {string} title */
|
||||
export function cloneVoiceTitleExists(title, excludeId = null) {
|
||||
const t = String(title || "").trim();
|
||||
return listCloneVoices().some(
|
||||
(item) => item.title === t && item.id !== excludeId,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析选中音色对应的阿里云 voiceId
|
||||
* @param {string} selectedVoiceId
|
||||
* @param {SoundPromptRecord[]} [clones]
|
||||
*/
|
||||
export function resolveAliyunVoiceId(selectedVoiceId, clones = listCloneVoices()) {
|
||||
if (!selectedVoiceId) return "Cherry";
|
||||
if (selectedVoiceId.startsWith("sys_")) {
|
||||
return findSystemVoiceFromId(selectedVoiceId);
|
||||
}
|
||||
const clone = clones.find((c) => c.id === selectedVoiceId);
|
||||
return String(clone?.content?.aliyunVoiceId || "").trim() || "Cherry";
|
||||
}
|
||||
|
||||
function findSystemVoiceFromId(id) {
|
||||
return findSystemVoice(id)?.aliyunVoiceId || "Cherry";
|
||||
}
|
||||
Reference in New Issue
Block a user