From c8b4160fcd8d6bab93e67036e30c32fd68ed241d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Tue, 22 Sep 2026 16:11:17 +0800 Subject: [PATCH] =?UTF-8?q?3D=20=E6=9F=A5=E4=BB=B7=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E5=B9=B6=E5=85=A5=E7=BB=9F=E4=B8=80=E7=9A=84=E5=AE=9A=E4=BB=B7?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E6=9E=9A=E4=B8=BE=20-=20EditorGenerationPric?= =?UTF-8?q?ingError=20=E6=96=B0=E5=A2=9E=20Model3d=20=E5=8F=98=E4=BD=93?= =?UTF-8?q?=E5=B9=B6=E5=AE=9E=E7=8E=B0=20From=20-=20m?= =?UTF-8?q?odel3d=5Fprice=20=E6=94=B9=E4=B8=BA=E8=BF=94=E5=9B=9E=20EditorG?= =?UTF-8?q?enerationPricingError=EF=BC=8C=E5=86=85=E5=B1=82=E6=96=87?= =?UTF-8?q?=E6=A1=88=E7=9B=B4=E9=80=9A=E4=BF=9D=E6=8C=81=E5=93=8D=E5=BA=94?= =?UTF-8?q?=E4=B8=8D=E5=8F=98=20-=20=E6=8F=90=E4=BA=A4=E8=B7=AF=E7=94=B1?= =?UTF-8?q?=E5=AF=B9=203D=20=E5=AE=9A=E4=BB=B7=E9=94=99=E8=AF=AF=E4=B8=8E?= =?UTF-8?q?=E5=AE=9A=E4=BB=B7=E5=BF=AB=E7=85=A7=E9=94=99=E8=AF=AF=E5=88=86?= =?UTF-8?q?=E5=88=AB=E6=98=A0=E5=B0=84=EF=BC=8C=E6=9C=AA=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E7=94=A8=E4=BE=8B=E6=94=B9=E6=96=AD=E8=A8=80=20Model3d(NotConf?= =?UTF-8?q?igured)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/editor_generation_config.rs | 24 +++++++++++++++++-- .../crates/api-server/src/tripo3d/routes.rs | 6 ++++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/server-rs/crates/api-server/src/editor_generation_config.rs b/server-rs/crates/api-server/src/editor_generation_config.rs index 960c77cd3..d1561cac2 100644 --- a/server-rs/crates/api-server/src/editor_generation_config.rs +++ b/server-rs/crates/api-server/src/editor_generation_config.rs @@ -93,21 +93,33 @@ pub(crate) enum EditorGenerationPricingError { Io(io::Error), Json(serde_json::Error), Invalid(String), + /// 3D 定价查询失败:结构化保留「未配置 / 缺底价 / 缺加价项」三种语义。 + Model3d(Model3dPricingError), #[cfg_attr(test, allow(dead_code))] Persistence(String), LockPoisoned, } +impl From for EditorGenerationPricingError { + fn from(error: Model3dPricingError) -> Self { + Self::Model3d(error) + } +} + impl EditorGenerationPricingConfig { /// Tripo 3D 提交查价:缺段或缺键都直接报错,不回退默认值。 + /// + /// 错误与同文件其它查询统一成 [`EditorGenerationPricingError`],3D 结构化原因收在 + /// [`EditorGenerationPricingError::Model3d`] 里,调用方不必再处理第二套错误枚举。 pub(crate) fn model3d_price( &self, query: &Model3dPricingQuery, - ) -> Result { + ) -> Result { self.model3d .as_ref() .ok_or(Model3dPricingError::NotConfigured)? .price(query) + .map_err(Into::into) } /// 后台 payload 的「可省略」语义:`model3d` 缺席或为 null 表示沿用当前 3D 段。 @@ -657,6 +669,8 @@ impl fmt::Display for EditorGenerationPricingError { Self::Invalid(message) => write!(f, "模型定价配置不合法:{message}"), Self::Persistence(message) => write!(f, "模型定价配置入库失败:{message}"), Self::LockPoisoned => write!(f, "模型定价配置锁已损坏"), + // 直接透传内层文案,保持接口响应里的 message 与改造前一致。 + Self::Model3d(error) => write!(f, "{error}"), } } } @@ -760,7 +774,13 @@ mod tests { ), )) .expect_err("未配置 3D 定价时应拒绝查价"); - assert_eq!(error, Model3dPricingError::NotConfigured); + assert!( + matches!( + error, + EditorGenerationPricingError::Model3d(Model3dPricingError::NotConfigured) + ), + "3D 段缺失应以 NotConfigured 收口,实际 {error:?}" + ); } /// 受控默认配置里的 3D 泥点价必须严格等于 `ceil(0.8 × Tripo 官方 credit)`: diff --git a/server-rs/crates/api-server/src/tripo3d/routes.rs b/server-rs/crates/api-server/src/tripo3d/routes.rs index ea59c56a1..03ece8c6c 100644 --- a/server-rs/crates/api-server/src/tripo3d/routes.rs +++ b/server-rs/crates/api-server/src/tripo3d/routes.rs @@ -146,9 +146,13 @@ async fn resolve_price_mud_points( .map_err(|error| error.into_response_with_context(Some(request_context)))?; match pricing.model3d_price(query) { Ok(price_mud_points) => Ok(u64::from(price_mud_points)), - Err(error) => { + // 查价失败只有 3D 定价这一种原因;其它变体理论上不会出现,真出现时按服务端问题上报。 + Err(crate::editor_generation_config::EditorGenerationPricingError::Model3d(error)) => { Err(map_pricing_error(error).into_response_with_context(Some(request_context))) } + Err(error) => { + Err(map_pricing_store_error(error).into_response_with_context(Some(request_context))) + } } }