diff --git a/server-rs/crates/api-server/src/runtime_profile.rs b/server-rs/crates/api-server/src/runtime_profile.rs index def489579..c4d22d258 100644 --- a/server-rs/crates/api-server/src/runtime_profile.rs +++ b/server-rs/crates/api-server/src/runtime_profile.rs @@ -1188,19 +1188,8 @@ pub async fn admin_upsert_profile_membership_plan( Extension(admin): Extension, Json(payload): Json, ) -> Result, Response> { - let plan = parse_runtime_profile_membership_plan(&payload.plan).map_err(|error| { - runtime_profile_error_response( - &request_context, - AppError::from_status(StatusCode::BAD_REQUEST).with_message(error), - ) - })?; - let model_access = parse_runtime_profile_membership_model_access(&payload.model_access) - .map_err(|error| { - runtime_profile_error_response( - &request_context, - AppError::from_status(StatusCode::BAD_REQUEST).with_message(error), - ) - })?; + let plan = payload.plan.into(); + let model_access = payload.model_access.into(); let updated_at_micros = OffsetDateTime::now_utc().unix_timestamp_nanos() / 1_000; let record = state .spacetime_client() @@ -2434,22 +2423,7 @@ fn parse_profile_recharge_product_kind( } } -/// 会员档位 token → 枚举。JSON 没有枚举,但解析必须严格:未知 token 一律 400。 -fn parse_runtime_profile_membership_plan( - raw: &str, -) -> Result { - module_runtime::RuntimeProfileMembershipPlan::parse(raw) - .ok_or_else(|| "会员档位无效".to_string()) -} - -/// 模型权限 token → 枚举;`basic` = 仅基础模型,`full` = 基础及高性能模型。 -fn parse_runtime_profile_membership_model_access( - raw: &str, -) -> Result { - module_runtime::RuntimeProfileMembershipModelAccess::parse(raw) - .ok_or_else(|| "模型权限无效".to_string()) -} - +/// 会员档位 / 模型权限 / 周期改由 typed enum 在反序列化阶段校验,未知 token 直接 4xx。 fn parse_tracking_scope_kind(raw: &str) -> Result { match raw.trim().to_ascii_lowercase().as_str() { TRACKING_SCOPE_KIND_SITE => Ok(RuntimeTrackingScopeKind::Site), diff --git a/server-rs/crates/shared-contracts/src/runtime.rs b/server-rs/crates/shared-contracts/src/runtime.rs index bab42b467..fc576d464 100644 --- a/server-rs/crates/shared-contracts/src/runtime.rs +++ b/server-rs/crates/shared-contracts/src/runtime.rs @@ -801,13 +801,13 @@ pub struct ProfileMembershipPlanAdminListResponse { #[serde(rename_all = "camelCase")] pub struct AdminUpsertProfileMembershipPlanRequest { /// 档位 token,作为主键即档位身份。 - pub plan: String, + pub plan: ProfileMembershipPlanToken, pub title: String, pub month_price_cents: u64, pub year_price_cents: u64, pub period_points: u64, /// 模型权限 token:`basic` / `full`;本期只落字段、不做服务端拦截。 - pub model_access: String, + pub model_access: ProfileMembershipModelAccessToken, /// 并发上限;`128` 表示不设上限。 pub concurrent_job_limit: u32, #[serde(default = "default_true")]