From 28e6e67e984cc594999d4c923f4b5a444c29b6e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Sat, 19 Sep 2026 14:23:18 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E9=BD=90=E5=90=8E=E5=8F=B0=E5=AE=9A?= =?UTF-8?q?=E4=BB=B7=E4=BF=9D=E5=AD=98=E7=94=A8=E4=BE=8B=E7=9A=84=20GPT=20?= =?UTF-8?q?Image=202.5=20=E6=A1=A3=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 后台保存 payload 用 gpt-image-2.5-flare-c 与 gpt-image-2.5-sunburst-c 替换历史单 key,保存重新返回 200 公开定价断言改为读取业务模型名 gpt-image-2.5 的生成档价格,并新增 admin 定价读回具体 key 的断言 --- server-rs/crates/api-server/src/app.rs | 52 +++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/server-rs/crates/api-server/src/app.rs b/server-rs/crates/api-server/src/app.rs index 40887c04e..c2fb8e7d4 100644 --- a/server-rs/crates/api-server/src/app.rs +++ b/server-rs/crates/api-server/src/app.rs @@ -5780,10 +5780,14 @@ mod tests { "unit": "perGeneration", "prices": { "0.5K": 9, "1K": 18, "2K": 36 } }, - "gpt-image-2": { + "gpt-image-2.5-flare-c": { "unit": "perGeneration", "prices": { "1K": 31, "2K": 62 } }, + "gpt-image-2.5-sunburst-c": { + "unit": "perGeneration", + "prices": { "1K": 41, "2K": 82 } + }, "seedance2.0-fast": { "unit": "perSecond", "prices": { "480p": 11, "720p": 22, "1080p": 44 } @@ -5823,6 +5827,7 @@ mod tests { assert_eq!(response.status(), StatusCode::OK); let public_response = app + .clone() .oneshot( Request::builder() .uri("/api/editor/generation-pricing") @@ -5840,10 +5845,24 @@ mod tests { let payload: Value = serde_json::from_slice(&body).expect("public pricing payload should be json"); + // 公开投影按业务模型名暴露生成档价格;具体 provider key 不下发普通前端。 assert_eq!( - payload["models"]["gpt-image-2"]["prices"]["2K"], + payload["models"]["gpt-image-2.5"]["prices"]["2K"], Value::Number(62.into()) ); + let public_models = payload["models"] + .as_object() + .expect("公开定价必须暴露 models 对象"); + for hidden_model in [ + "gpt-image-2", + "gpt-image-2.5-flare-c", + "gpt-image-2.5-sunburst-c", + ] { + assert!( + !public_models.contains_key(hidden_model), + "公开定价不应暴露 {hidden_model}" + ); + } assert_eq!( payload["models"]["audio1.0"]["unit"], Value::String("perGeneration".to_string()) @@ -5856,6 +5875,35 @@ mod tests { payload["models"]["seedance2.0"]["prices"]["720p"], Value::Number(26.into()) ); + + // admin 定价接口是 concrete provider key 的明确例外,读回的是保存时的原始 key。 + let admin_response = app + .oneshot( + Request::builder() + .uri("/admin/api/editor-generation-pricing") + .header("authorization", format!("Bearer {admin_token}")) + .body(Body::empty()) + .expect("admin pricing request should build"), + ) + .await + .expect("admin pricing request should succeed"); + assert_eq!(admin_response.status(), StatusCode::OK); + let admin_body = admin_response + .into_body() + .collect() + .await + .expect("admin pricing body should collect") + .to_bytes(); + let admin_payload: Value = + serde_json::from_slice(&admin_body).expect("admin pricing payload should be json"); + assert_eq!( + admin_payload["models"]["gpt-image-2.5-flare-c"]["prices"]["2K"], + Value::Number(62.into()) + ); + assert_eq!( + admin_payload["models"]["gpt-image-2.5-sunburst-c"]["prices"]["2K"], + Value::Number(82.into()) + ); } /// 中文注释:验证入口公告拒绝可执行脚本,避免后台配置变成不受控注入。