This commit is contained in:
fengchuanhn@gmail.com
2026-05-25 02:13:03 +08:00
parent 6eba25ea10
commit 416f5bc113
2 changed files with 85 additions and 3 deletions

View File

@@ -4,6 +4,7 @@ import { storeToRefs } from "pinia";
import { useWorkflowStore } from "../../stores/workflow.js"; import { useWorkflowStore } from "../../stores/workflow.js";
import { useAvatarStore } from "../../stores/avatar.js"; import { useAvatarStore } from "../../stores/avatar.js";
import VoiceManageDialog from "./VoiceManageDialog.vue"; import VoiceManageDialog from "./VoiceManageDialog.vue";
import { revealLocalFileInFolder } from "../../services/fileExport.js";
const workflow = useWorkflowStore(); const workflow = useWorkflowStore();
const avatarStore = useAvatarStore(); const avatarStore = useAvatarStore();
@@ -14,10 +15,12 @@ const {
avatarSelect, avatarSelect,
speechGenerating, speechGenerating,
generatedAudioSrc, generatedAudioSrc,
generatedAudioPath,
currentAudioId, currentAudioId,
audioHistory, audioHistory,
videoGenerating, videoGenerating,
generatedVideoSrc, generatedVideoSrc,
generatedVideoPath,
currentVideoId, currentVideoId,
videoHistory, videoHistory,
} = storeToRefs(workflow); } = storeToRefs(workflow);
@@ -68,6 +71,21 @@ async function onPickAudioHistory() {
await workflow.pickAudioHistory(currentAudioId.value); await workflow.pickAudioHistory(currentAudioId.value);
} }
async function onOpenAudioInExplorer() {
if (!generatedAudioPath.value) {
feedback.value = { severity: "error", message: "暂无音频文件" };
return;
}
try {
await revealLocalFileInFolder(generatedAudioPath.value);
} catch (err) {
feedback.value = {
severity: "error",
message: err instanceof Error ? err.message : String(err),
};
}
}
async function onGenerateTalkingVideo() { async function onGenerateTalkingVideo() {
feedback.value = { severity: "", message: "" }; feedback.value = { severity: "", message: "" };
const result = await workflow.generateTalkingVideo(); const result = await workflow.generateTalkingVideo();
@@ -84,6 +102,21 @@ async function onPickVideoHistory() {
await workflow.pickVideoHistory(currentVideoId.value); await workflow.pickVideoHistory(currentVideoId.value);
} }
async function onOpenVideoInExplorer() {
if (!generatedVideoPath.value) {
feedback.value = { severity: "error", message: "暂无视频文件" };
return;
}
try {
await revealLocalFileInFolder(generatedVideoPath.value);
} catch (err) {
feedback.value = {
severity: "error",
message: err instanceof Error ? err.message : String(err),
};
}
}
onMounted(() => { onMounted(() => {
avatarStore.refresh(); avatarStore.refresh();
workflow.refreshAudioHistory(); workflow.refreshAudioHistory();
@@ -155,7 +188,18 @@ onMounted(() => {
</p> </p>
<div class="dashboard-preview-box mt-3"> <div class="dashboard-preview-box mt-3">
<div class="mb-2 flex items-center justify-between gap-2"> <div class="mb-2 flex items-center justify-between gap-2">
<span class="text-xs text-slate-400">音频预览</span> <div class="flex items-center gap-0.5">
<span class="text-xs text-slate-400">音频预览</span>
<Button
icon="pi pi-folder-open"
size="small"
severity="secondary"
text
:disabled="!generatedAudioPath"
aria-label="在资源管理器中打开"
@click="onOpenAudioInExplorer"
/>
</div>
<Select <Select
v-if="audioHistoryOptions.length" v-if="audioHistoryOptions.length"
v-model="currentAudioId" v-model="currentAudioId"
@@ -198,7 +242,18 @@ onMounted(() => {
/> />
<div class="mt-2"> <div class="mt-2">
<div class="mb-2 flex items-center justify-between gap-2"> <div class="mb-2 flex items-center justify-between gap-2">
<span class="text-xs text-slate-400">视频预览</span> <div class="flex items-center gap-0.5">
<span class="text-xs text-slate-400">视频预览</span>
<Button
icon="pi pi-folder-open"
size="small"
severity="secondary"
text
:disabled="!generatedVideoPath"
aria-label="在资源管理器中打开"
@click="onOpenVideoInExplorer"
/>
</div>
<Select <Select
v-if="videoHistoryOptions.length" v-if="videoHistoryOptions.length"
v-model="currentVideoId" v-model="currentVideoId"

View File

@@ -2,6 +2,7 @@
import { computed, ref } from "vue"; import { computed, ref } from "vue";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
import { useWorkflowStore } from "../../stores/workflow.js"; import { useWorkflowStore } from "../../stores/workflow.js";
import { revealLocalFileInFolder } from "../../services/fileExport.js";
const workflow = useWorkflowStore(); const workflow = useWorkflowStore();
const { const {
@@ -52,6 +53,21 @@ async function onPickPipMaterial() {
feedback.value = { severity: "", message: "" }; feedback.value = { severity: "", message: "" };
showFeedback(await workflow.choosePipMaterial()); showFeedback(await workflow.choosePipMaterial());
} }
async function onOpenVideoInExplorer() {
if (!generatedVideoPath.value) {
feedback.value = { severity: "error", message: "暂无视频文件" };
return;
}
try {
await revealLocalFileInFolder(generatedVideoPath.value);
} catch (err) {
feedback.value = {
severity: "error",
message: err instanceof Error ? err.message : String(err),
};
}
}
</script> </script>
<template> <template>
@@ -122,7 +138,18 @@ async function onPickPipMaterial() {
</p> </p>
<div class="dashboard-preview-box mt-3"> <div class="dashboard-preview-box mt-3">
<div class="mb-2 text-xs text-slate-400">编辑预览</div> <div class="mb-2 flex items-center gap-0.5">
<span class="text-xs text-slate-400">编辑预览</span>
<Button
icon="pi pi-folder-open"
size="small"
severity="secondary"
text
:disabled="!generatedVideoPath"
aria-label="在资源管理器中打开"
@click="onOpenVideoInExplorer"
/>
</div>
<div class="dashboard-aspect-video"> <div class="dashboard-aspect-video">
<video <video
v-if="generatedVideoSrc" v-if="generatedVideoSrc"