This commit is contained in:
fengchuanhn@gmail.com
2026-05-18 15:11:59 +08:00
parent 4771397301
commit cdbf605205
25 changed files with 1497 additions and 112 deletions

75
src/stores/avatar.js Normal file
View File

@@ -0,0 +1,75 @@
import { defineStore, acceptHMRUpdate } from "pinia";
import {
listAvatars,
insertAvatar,
updateAvatarName,
deleteAvatar,
avatarNameExists,
migrateLegacyAvatarsIfNeeded,
} from "../services/avatarDb.js";
export const useAvatarStore = defineStore("avatar", {
state: () => ({
templates: [],
loading: false,
}),
getters: {
selectOptions: (state) => [
{ label: "请选择形象", value: null },
...state.templates.map((t) => ({
label: t.name,
value: t.id,
})),
],
},
actions: {
async refresh() {
this.loading = true;
try {
await migrateLegacyAvatarsIfNeeded();
this.templates = await listAvatars();
} finally {
this.loading = false;
}
},
/**
* @param {{ name: string, filePath: string }} payload
*/
async addTemplate(payload) {
const record = await insertAvatar(payload.name, payload.filePath);
this.templates = await listAvatars();
return record;
},
/**
* @param {number} id
* @param {string} name
*/
async renameTemplate(id, name) {
const exists = await avatarNameExists(name, id);
if (exists) {
return { ok: false, message: "名称重复" };
}
try {
await updateAvatarName(id, name);
this.templates = await listAvatars();
return { ok: true };
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
return { ok: false, message: msg || "重命名失败" };
}
},
async removeTemplate(item) {
await deleteAvatar(item.id);
this.templates = await listAvatars();
},
},
});
if (import.meta.hot) {
import.meta.hot.accept(acceptHMRUpdate(useAvatarStore, import.meta.hot));
}

View File

@@ -21,6 +21,8 @@ import {
executeGenerateSpeech,
selectAudioHistory,
} from "../services/voiceGenerate.js";
import { listGeneratedAudios } from "../services/audioDb.js";
import { localAudioToPlayableUrl } from "../services/localAudio.js";
@@ -165,7 +167,7 @@ export const useWorkflowStore = defineStore("workflow", {
currentAudioId: null,
/** @type {Array<{ id: string, label: string, audioPath: string, audioSrc: string, createdAt: number }>} */
/** @type {Array<{ id: number, name: string, filePath: string, createdAt: string, audioSrc?: string }>} */
audioHistory: [],
@@ -451,10 +453,27 @@ export const useWorkflowStore = defineStore("workflow", {
},
pickAudioHistory(audioId) {
selectAudioHistory(this, audioId);
async refreshAudioHistory() {
try {
const rows = await listGeneratedAudios();
this.audioHistory = await Promise.all(
rows.map(async (row) => {
let audioSrc = "";
try {
audioSrc = await localAudioToPlayableUrl(row.filePath);
} catch {
audioSrc = "";
}
return { ...row, audioSrc };
}),
);
} catch {
this.audioHistory = [];
}
},
async pickAudioHistory(audioId) {
await selectAudioHistory(this, audioId);
},
resetAll() {