auto-save 2026-05-27 23:08 (~5)
This commit is contained in:
@@ -1,11 +1,5 @@
|
|||||||
{
|
{
|
||||||
"entries": [
|
"entries": [
|
||||||
{
|
|
||||||
"files_changed": 1,
|
|
||||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:fix: center scaled workbench vertically",
|
|
||||||
"ts": "2026-05-20T12:15:32Z",
|
|
||||||
"type": "session-heartbeat"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"files_changed": 2,
|
"files_changed": 2,
|
||||||
"hash": "bd64b94",
|
"hash": "bd64b94",
|
||||||
@@ -3199,6 +3193,13 @@
|
|||||||
"message": "chore: harden production deploy scripts",
|
"message": "chore: harden production deploy scripts",
|
||||||
"hash": "b6a7e7b",
|
"hash": "b6a7e7b",
|
||||||
"files_changed": 2
|
"files_changed": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ts": "2026-05-27T23:02:52+08:00",
|
||||||
|
"type": "commit",
|
||||||
|
"message": "auto-save 2026-05-27 23:01 (~5)",
|
||||||
|
"hash": "d7f72f6",
|
||||||
|
"files_changed": 5
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,19 @@
|
|||||||
</n-dropdown>
|
</n-dropdown>
|
||||||
</div>
|
</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 | 连接输入指示 -->
|
<!-- Connected inputs indicator | 连接输入指示 -->
|
||||||
<div
|
<div
|
||||||
class="flex items-center gap-2 text-xs text-[var(--text-secondary)] py-1 border-t border-[var(--border-color)]">
|
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 { updateNode, removeNode, duplicateNode, addNode, addEdge, nodes, edges } from '../../stores/canvas'
|
||||||
import NodeHandleMenu from './NodeHandleMenu.vue'
|
import NodeHandleMenu from './NodeHandleMenu.vue'
|
||||||
import { useModelStore } from '../../stores/pinia'
|
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 获取模型选项(根据渠道过滤)
|
// 使用 Pinia store 获取模型选项(根据渠道过滤)
|
||||||
const modelStore = useModelStore()
|
const modelStore = useModelStore()
|
||||||
@@ -170,12 +183,25 @@ const { updateNodeInternals } = useVueFlow()
|
|||||||
// Video generation hook | 视频生成 hook
|
// Video generation hook | 视频生成 hook
|
||||||
const { loading, error, status, video: generatedVideo, progress, createVideoTaskOnly } = useVideoGeneration()
|
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 | 本地状态
|
// Local state | 本地状态
|
||||||
const showHandleMenu = ref(false)
|
const showHandleMenu = ref(false)
|
||||||
const isGenerating = ref(false) // 任务创建中状态
|
const isGenerating = ref(false) // 任务创建中状态
|
||||||
const localModel = ref(props.data?.model || DEFAULT_VIDEO_MODEL)
|
const localModel = ref(props.data?.model || DEFAULT_VIDEO_MODEL)
|
||||||
const localRatio = ref(props.data?.ratio || '16:9')
|
const localRatio = ref(props.data?.ratio || '16:9')
|
||||||
const localDuration = ref(props.data?.dur || 5)
|
const localDuration = ref(props.data?.dur || 5)
|
||||||
|
const localResolution = ref(props.data?.resolution || currentModelDefaultResolution(props.data?.model || DEFAULT_VIDEO_MODEL))
|
||||||
|
|
||||||
// Label editing state | Label 编辑状态
|
// Label editing state | Label 编辑状态
|
||||||
const isEditingLabel = ref(false)
|
const isEditingLabel = ref(false)
|
||||||
@@ -244,6 +270,11 @@ const durationOptions = computed(() => {
|
|||||||
return getModelDurationOptions(localModel.value)
|
return getModelDurationOptions(localModel.value)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Resolution options based on model | 基于模型的清晰度选项
|
||||||
|
const resolutionOptions = computed(() => {
|
||||||
|
return getModelResolutionOptions(localModel.value)
|
||||||
|
})
|
||||||
|
|
||||||
// Handle model selection | 处理模型选择
|
// Handle model selection | 处理模型选择
|
||||||
const handleModelSelect = (key) => {
|
const handleModelSelect = (key) => {
|
||||||
localModel.value = key
|
localModel.value = key
|
||||||
@@ -258,6 +289,9 @@ const handleModelSelect = (key) => {
|
|||||||
localDuration.value = config.defaultParams.duration
|
localDuration.value = config.defaultParams.duration
|
||||||
updates.dur = config.defaultParams.duration
|
updates.dur = config.defaultParams.duration
|
||||||
}
|
}
|
||||||
|
const nextResolution = currentModelDefaultResolution(key)
|
||||||
|
localResolution.value = nextResolution
|
||||||
|
updates.resolution = nextResolution
|
||||||
updateNode(props.id, updates)
|
updateNode(props.id, updates)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,6 +318,12 @@ const handleDurationSelect = (key) => {
|
|||||||
updateNode(props.id, { dur: 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 | 根据角色获取连接的输入
|
// Get connected inputs by role | 根据角色获取连接的输入
|
||||||
const getConnectedInputs = () => {
|
const getConnectedInputs = () => {
|
||||||
const connectedEdges = edges.value.filter(e => e.target === props.id)
|
const connectedEdges = edges.value.filter(e => e.target === props.id)
|
||||||
@@ -411,6 +451,11 @@ const handleGenerate = async () => {
|
|||||||
params.dur = localDuration.value
|
params.dur = localDuration.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add resolution | 添加清晰度
|
||||||
|
if (localResolution.value) {
|
||||||
|
params.resolution = localResolution.value
|
||||||
|
}
|
||||||
|
|
||||||
// 只创建任务,获取 taskId,不在这里轮询
|
// 只创建任务,获取 taskId,不在这里轮询
|
||||||
const { taskId: newTaskId, url } = await createVideoTaskOnly(params)
|
const { taskId: newTaskId, url } = await createVideoTaskOnly(params)
|
||||||
|
|
||||||
@@ -492,7 +537,14 @@ onMounted(() => {
|
|||||||
// 使用 store 中的默认模型或第一个可用模型
|
// 使用 store 中的默认模型或第一个可用模型
|
||||||
const selected = availableModels.find(m => m.key === modelStore.selectedVideoModel)?.key
|
const selected = availableModels.find(m => m.key === modelStore.selectedVideoModel)?.key
|
||||||
localModel.value = selected || availableModels[0]?.key || DEFAULT_VIDEO_MODEL
|
localModel.value = selected || availableModels[0]?.key || DEFAULT_VIDEO_MODEL
|
||||||
updateNode(props.id, { model: localModel.value })
|
localResolution.value = normalizeResolutionForModel(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) => {
|
watch(() => props.data?.model, (newModel) => {
|
||||||
if (newModel && newModel !== localModel.value) {
|
if (newModel && newModel !== localModel.value) {
|
||||||
localModel.value = newModel
|
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)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -282,7 +282,8 @@ export const useVideoGeneration = () => {
|
|||||||
first_image: firstFile ? { kind: 'keyframe', frame_idx: 0 } : null,
|
first_image: firstFile ? { kind: 'keyframe', frame_idx: 0 } : null,
|
||||||
last_image: lastFrameIdx !== null ? { kind: 'keyframe', frame_idx: lastFrameIdx } : null,
|
last_image: lastFrameIdx !== null ? { kind: 'keyframe', frame_idx: lastFrameIdx } : null,
|
||||||
model: params.model || 'seedance',
|
model: params.model || 'seedance',
|
||||||
size: normalizeVideoSize(params.ratio || params.size)
|
size: normalizeVideoSize(params.ratio || params.size),
|
||||||
|
resolution: params.resolution || '720p'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
const created = newestGeneratedVideo(updated)
|
const created = newestGeneratedVideo(updated)
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ export const getModelDurationOptions = (modelKey) => {
|
|||||||
*/
|
*/
|
||||||
export const getModelResolutionOptions = (modelKey) => {
|
export const getModelResolutionOptions = (modelKey) => {
|
||||||
const model = getModelConfig(modelKey) || VIDEO_MODELS.find(m => m.key === modelKey)
|
const model = getModelConfig(modelKey) || VIDEO_MODELS.find(m => m.key === modelKey)
|
||||||
if (model?.resolutionOptions) {
|
if (model?.resolutionOptions?.length) {
|
||||||
return model.resolutionOptions
|
return model.resolutionOptions
|
||||||
}
|
}
|
||||||
if (!model?.resolutions) return SEEDANCE_RESOLUTION_OPTIONS
|
if (!model?.resolutions) return SEEDANCE_RESOLUTION_OPTIONS
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ const normalizeRuntimeVideoModel = (item) => {
|
|||||||
const sizeOptions = normalizeRuntimeSizeOptions(item.size_options)
|
const sizeOptions = normalizeRuntimeSizeOptions(item.size_options)
|
||||||
const durationOptions = normalizeRuntimeDurationOptions(item.duration_options)
|
const durationOptions = normalizeRuntimeDurationOptions(item.duration_options)
|
||||||
const resolutionOptions = normalizeRuntimeResolutionOptions(item.resolution_options)
|
const resolutionOptions = normalizeRuntimeResolutionOptions(item.resolution_options)
|
||||||
const resolutions = resolutionOptions.map(option => option.key)
|
const resolutions = resolutionOptions.length ? resolutionOptions.map(option => option.key) : ['720p']
|
||||||
const defaultResolution = item.default_resolution || resolutions[0] || '720p'
|
const defaultResolution = item.default_resolution || resolutions[0] || '720p'
|
||||||
return {
|
return {
|
||||||
label: item.label || item.model || key,
|
label: item.label || item.model || key,
|
||||||
|
|||||||
Reference in New Issue
Block a user