@@ -74,6 +74,19 @@
< / n-dropdown >
< / div >
<!-- Resolution selector | 清晰度选择 -- >
< div class = "flex items-center justify-between" >
< span class = "text-xs text-[var(--text-secondary)]" > 清晰度 < / span >
< n-dropdown trigger = "click" :options = "resolutionOptions" @select ="handleResolutionSelect" >
< button class = "flex items-center gap-1 text-sm text-[var(--text-primary)] hover:text-[var(--accent-color)]" >
{ { localResolution } }
< n-icon :size = "12" >
< ChevronForwardOutline / >
< / n-icon >
< / button >
< / n-dropdown >
< / div >
<!-- Connected inputs indicator | 连接输入指示 -- >
< div
class = "flex items-center gap-2 text-xs text-[var(--text-secondary)] py-1 border-t border-[var(--border-color)]" >
@@ -154,7 +167,7 @@ import { useVideoGeneration } from '../../hooks'
import { updateNode , removeNode , duplicateNode , addNode , addEdge , nodes , edges } from '../../stores/canvas'
import NodeHandleMenu from './NodeHandleMenu.vue'
import { useModelStore } from '../../stores/pinia'
import { getModelRatioOptions , getModelDurationOptions , getModelConfig , DEFAULT _VIDEO _MODEL } from '../../stores/models'
import { getModelRatioOptions , getModelDurationOptions , getModelResolutionOptions , getModelConfig , DEFAULT _VIDEO _MODEL } from '../../stores/models'
// 使用 Pinia store 获取模型选项(根据渠道过滤)
const modelStore = useModelStore ( )
@@ -170,12 +183,25 @@ const { updateNodeInternals } = useVueFlow()
// Video generation hook | 视频生成 hook
const { loading , error , status , video : generatedVideo , progress , createVideoTaskOnly } = useVideoGeneration ( )
const currentModelDefaultResolution = ( modelKey ) => {
const config = getModelConfig ( modelKey )
return config ? . defaultParams ? . resolution || config ? . defaultResolution || config ? . resolutions ? . [ 0 ] || '720p'
}
const normalizeResolutionForModel = ( modelKey , resolution ) => {
const options = getModelResolutionOptions ( modelKey )
const allowed = options . map ( option => option . key )
if ( resolution && allowed . includes ( resolution ) ) return resolution
return currentModelDefaultResolution ( modelKey )
}
// Local state | 本地状态
const showHandleMenu = ref ( false )
const isGenerating = ref ( false ) // 任务创建中状态
const localModel = ref ( props . data ? . model || DEFAULT _VIDEO _MODEL )
const localRatio = ref ( props . data ? . ratio || '16:9' )
const localDuration = ref ( props . data ? . dur || 5 )
const localResolution = ref ( props . data ? . resolution || currentModelDefaultResolution ( props . data ? . model || DEFAULT _VIDEO _MODEL ) )
// Label editing state | Label 编辑状态
const isEditingLabel = ref ( false )
@@ -244,6 +270,11 @@ const durationOptions = computed(() => {
return getModelDurationOptions ( localModel . value )
} )
// Resolution options based on model | 基于模型的清晰度选项
const resolutionOptions = computed ( ( ) => {
return getModelResolutionOptions ( localModel . value )
} )
// Handle model selection | 处理模型选择
const handleModelSelect = ( key ) => {
localModel . value = key
@@ -258,6 +289,9 @@ const handleModelSelect = (key) => {
localDuration . value = config . defaultParams . duration
updates . dur = config . defaultParams . duration
}
const nextResolution = currentModelDefaultResolution ( key )
localResolution . value = nextResolution
updates . resolution = nextResolution
updateNode ( props . id , updates )
}
@@ -284,6 +318,12 @@ const handleDurationSelect = (key) => {
updateNode ( props . id , { dur : key } )
}
// Handle resolution selection | 处理清晰度选择
const handleResolutionSelect = ( key ) => {
localResolution . value = key
updateNode ( props . id , { resolution : key } )
}
// Get connected inputs by role | 根据角色获取连接的输入
const getConnectedInputs = ( ) => {
const connectedEdges = edges . value . filter ( e => e . target === props . id )
@@ -411,6 +451,11 @@ const handleGenerate = async () => {
params . dur = localDuration . value
}
// Add resolution | 添加清晰度
if ( localResolution . value ) {
params . resolution = localResolution . value
}
// 只创建任务,获取 taskId, 不在这里轮询
const { taskId : newTaskId , url } = await createVideoTaskOnly ( params )
@@ -492,7 +537,14 @@ onMounted(() => {
// 使用 store 中的默认模型或第一个可用模型
const selected = availableModels . find ( m => m . key === modelStore . selectedVideoModel ) ? . key
localModel . value = selected || availableModels [ 0 ] ? . key || DEFAULT _VIDEO _MODEL
updateNode ( props . id , { m odel: localModel . value } )
localResolution . value = normalizeResolutionForM odel( localModel . value , localResolution . value )
updateNode ( props . id , { model : localModel . value , resolution : localResolution . value } )
} else {
const nextResolution = normalizeResolutionForModel ( localModel . value , localResolution . value )
if ( nextResolution !== localResolution . value || ! props . data ? . resolution ) {
localResolution . value = nextResolution
updateNode ( props . id , { resolution : nextResolution } )
}
}
} )
@@ -500,6 +552,13 @@ onMounted(() => {
watch ( ( ) => props . data ? . model , ( newModel ) => {
if ( newModel && newModel !== localModel . value ) {
localModel . value = newModel
localResolution . value = normalizeResolutionForModel ( newModel , props . data ? . resolution || localResolution . value )
}
} )
watch ( ( ) => props . data ? . resolution , ( newResolution ) => {
if ( newResolution && newResolution !== localResolution . value ) {
localResolution . value = normalizeResolutionForModel ( localModel . value , newResolution )
}
} )