From 87c0e167c4344faf086f5d842caa10f3236b4c38 Mon Sep 17 00:00:00 2001 From: Linghong Date: Fri, 7 Aug 2026 12:28:41 +0000 Subject: [PATCH] =?UTF-8?q?=E9=9F=B3=E9=A2=91=E4=BF=A1=E6=81=AF=E7=9A=84?= =?UTF-8?q?=E6=97=B6=E9=95=BF=E5=B1=95=E7=A4=BA=E6=94=B6=E6=95=9B=E5=88=B0?= =?UTF-8?q?=E4=B8=A4=E4=BD=8D=E5=B0=8F=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 模型返回的时长是全精度秒数,落库后信息面板会直出 8.306938775510204秒 这类无意义尾数。 - 新增 formatEditorGenerationInputFieldValue,只改写标题为「时长」或 duration 的字段中的首个数字,四舍五入到两位小数 - 接入音频信息弹窗与导出的可见元数据两处用户可见出口 - 不补零,"自动"这类无数字取值与其他字段原样保留 只作用于展示:generationInputs 落库值不变,重绘默认时长与作品时长推断 仍按原精度解析,已有素材也一并生效。 Co-Authored-By: Claude Opus 5 --- .../image-editor/ImageCanvasExportModel.ts | 3 ++- .../ImageCanvasGenerationModel.test.ts | 18 ++++++++++++++ .../ImageCanvasGenerationModel.ts | 24 +++++++++++++++++++ .../ImageCanvasMetadataModalView.tsx | 3 ++- 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/components/image-editor/ImageCanvasExportModel.ts b/src/components/image-editor/ImageCanvasExportModel.ts index 48a203845..b31f5d87c 100644 --- a/src/components/image-editor/ImageCanvasExportModel.ts +++ b/src/components/image-editor/ImageCanvasExportModel.ts @@ -7,6 +7,7 @@ import type { } from './ImageCanvasEditorTypes'; import { DEFAULT_ICON_DESCRIPTIONS, + formatEditorGenerationInputFieldValue, formatLayerImageType, getEditorLayerModelDisplayName, isEditorUserVisibleGenerationInputField, @@ -540,7 +541,7 @@ function buildVisibleGenerationInputs(layer: CanvasLayer) { .filter((field) => !isBuiltInGenerationInputField(field)) .map((field) => ({ title: field.title, - value: field.value, + value: formatEditorGenerationInputFieldValue(field), })) ?? []; const references = layer.generationInputs?.references.map((reference) => ({ diff --git a/src/components/image-editor/ImageCanvasGenerationModel.test.ts b/src/components/image-editor/ImageCanvasGenerationModel.test.ts index c71601aff..a461ac5f6 100644 --- a/src/components/image-editor/ImageCanvasGenerationModel.test.ts +++ b/src/components/image-editor/ImageCanvasGenerationModel.test.ts @@ -39,6 +39,7 @@ import { EDITOR_SOUND_EFFECT_MODEL_OPTIONS, EDITOR_VIDEO_MODEL_MUD_POINT_CONFIG, EDITOR_VIDEO_MODEL_OPTIONS, + formatEditorGenerationInputFieldValue, getGenerationFrameAriaLabel, getGenerationFrameLabel, IMAGE_MODEL_GPT_IMAGE_2, @@ -61,6 +62,23 @@ describe('ImageCanvasGenerationModel', () => { }); }); + it('展示时长时收敛到两位小数且不改动其他字段', () => { + const format = (title: string, value: string) => + formatEditorGenerationInputFieldValue({ title, value }); + + expect(format('时长', '8.306938775510204秒')).toBe('8.31秒'); + expect(format('时长', '3.4512秒')).toBe('3.45秒'); + // 整数与一位小数不补零,"自动"这类无数字取值原样保留。 + expect(format('时长', '5秒')).toBe('5秒'); + expect(format('时长', '2.5秒')).toBe('2.5秒'); + expect(format('时长', '自动')).toBe('自动'); + expect(format('duration', '8.306938775510204s')).toBe('8.31s'); + // 非时长字段一律原样返回,不能误伤提示词里的数字。 + expect(format('用户描述', '持续 8.306938775510204 秒的低鸣')).toBe( + '持续 8.306938775510204 秒的低鸣', + ); + }); + it('为所有编辑器生成模型提供显式定价配置', () => { expect( EDITOR_IMAGE_MODEL_OPTIONS.map((option) => option.value).filter( diff --git a/src/components/image-editor/ImageCanvasGenerationModel.ts b/src/components/image-editor/ImageCanvasGenerationModel.ts index a47fa33d9..80f1d15d9 100644 --- a/src/components/image-editor/ImageCanvasGenerationModel.ts +++ b/src/components/image-editor/ImageCanvasGenerationModel.ts @@ -637,6 +637,30 @@ export function isEditorUserVisibleGenerationInputField( return field.title.trim() !== '处理模型'; } +const GENERATION_INPUT_DURATION_TITLES = new Set(['时长', 'duration']); +const GENERATION_INPUT_DURATION_DECIMALS = 2; + +/** + * 时长字段落库的是模型返回的全精度秒数(例如 8.306938775510204 秒),展示时收敛到两位 + * 小数。只作用于渲染:底层字段保持原值,重绘默认时长与作品时长推断仍按原精度解析。 + */ +export function formatEditorGenerationInputFieldValue( + field: CanvasGenerationInputField, +) { + if (!GENERATION_INPUT_DURATION_TITLES.has(field.title.trim().toLowerCase())) { + return field.value; + } + // 只改写首个数字,"自动"这类无数字取值和"秒"后缀都原样保留。 + return field.value.replace(/\d+(?:\.\d+)?/u, (matched) => { + const parsed = Number.parseFloat(matched); + if (!Number.isFinite(parsed)) { + return matched; + } + const factor = 10 ** GENERATION_INPUT_DURATION_DECIMALS; + return String(Math.round(parsed * factor) / factor); + }); +} + export function getEditorLayerModelDisplayName( model: string | null | undefined, ) { diff --git a/src/components/image-editor/ImageCanvasMetadataModalView.tsx b/src/components/image-editor/ImageCanvasMetadataModalView.tsx index 779157413..7ca69a0c1 100644 --- a/src/components/image-editor/ImageCanvasMetadataModalView.tsx +++ b/src/components/image-editor/ImageCanvasMetadataModalView.tsx @@ -2,6 +2,7 @@ import { UnifiedModal } from '../common/UnifiedModal'; import type { CanvasLayer } from './ImageCanvasEditorTypes'; import { formatTaskIdForDisplay } from './ImageCanvasExportModel'; import { + formatEditorGenerationInputFieldValue, formatLayerImageType, getEditorLayerModelDisplayName, isEditorUserVisibleGenerationInputField, @@ -63,7 +64,7 @@ export function ImageCanvasMetadataModalView({ {field.title} - {field.value} + {formatEditorGenerationInputFieldValue(field)} ))} {generationInputReferences.length ? (