feat: 统一创作页表头跟随后台入口配置
This commit is contained in:
@@ -12,7 +12,7 @@ use crate::format_utc_micros;
|
||||
use shared_contracts::creation_entry_config::{
|
||||
CreationEntryConfigResponse, CreationEntryEventBannerResponse, CreationEntryStartCardResponse,
|
||||
CreationEntryTypeModalResponse, CreationEntryTypeResponse,
|
||||
encode_unified_creation_spec_response, resolve_unified_creation_spec_response,
|
||||
encode_unified_creation_spec_response, resolve_unified_creation_spec_response_with_entry_title,
|
||||
};
|
||||
|
||||
/// 将创作入口领域快照转换为前后台共享的 HTTP 契约响应。
|
||||
@@ -45,8 +45,9 @@ pub fn build_creation_entry_config_response(
|
||||
.creation_types
|
||||
.into_iter()
|
||||
.map(|item| {
|
||||
let unified_creation_spec = resolve_unified_creation_spec_response(
|
||||
let unified_creation_spec = resolve_unified_creation_spec_response_with_entry_title(
|
||||
item.id.as_str(),
|
||||
item.title.as_str(),
|
||||
item.unified_creation_spec_json.as_deref(),
|
||||
);
|
||||
CreationEntryTypeResponse {
|
||||
@@ -161,10 +162,9 @@ fn normalize_creation_entry_announcement_banner_value(
|
||||
);
|
||||
}
|
||||
|
||||
let banner = serde_json::from_value::<CreationEntryEventBannerResponse>(Value::Object(
|
||||
object.clone(),
|
||||
))
|
||||
.map_err(|error| format!("第 {} 条公告对象非法:{error}", index + 1))?;
|
||||
let banner =
|
||||
serde_json::from_value::<CreationEntryEventBannerResponse>(Value::Object(object.clone()))
|
||||
.map_err(|error| format!("第 {} 条公告对象非法:{error}", index + 1))?;
|
||||
normalize_creation_entry_event_banner_response(index, banner)
|
||||
}
|
||||
|
||||
@@ -243,8 +243,8 @@ pub fn resolve_creation_entry_event_banner_responses(
|
||||
banners
|
||||
}
|
||||
.into_iter()
|
||||
.map(build_creation_entry_event_banner_response)
|
||||
.collect()
|
||||
.map(build_creation_entry_event_banner_response)
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// 把领域公告快照转换为 HTTP 响应字段。
|
||||
@@ -332,10 +332,7 @@ fn normalize_banner_html_code(
|
||||
}
|
||||
let lower_html_code = html_code.to_ascii_lowercase();
|
||||
if lower_html_code.contains("<script") || lower_html_code.contains("javascript:") {
|
||||
return Err(format!(
|
||||
"第 {} 条 HTML 公告含有不允许的脚本代码",
|
||||
index + 1
|
||||
));
|
||||
return Err(format!("第 {} 条 HTML 公告含有不允许的脚本代码", index + 1));
|
||||
}
|
||||
|
||||
Ok(Some(html_code))
|
||||
|
||||
@@ -339,12 +339,20 @@ mod tests {
|
||||
assert_eq!(banners.len(), 1);
|
||||
assert_eq!(banners[0].render_mode, "html");
|
||||
assert_eq!(banners[0].title, "创作公告");
|
||||
assert!(banners[0].html_code.as_deref().unwrap_or("").contains("创作公告"));
|
||||
assert!(banners[0]
|
||||
.html_code
|
||||
.as_deref()
|
||||
.unwrap_or("")
|
||||
.contains("/creation-type-references/puzzle.webp"));
|
||||
assert!(
|
||||
banners[0]
|
||||
.html_code
|
||||
.as_deref()
|
||||
.unwrap_or("")
|
||||
.contains("创作公告")
|
||||
);
|
||||
assert!(
|
||||
banners[0]
|
||||
.html_code
|
||||
.as_deref()
|
||||
.unwrap_or("")
|
||||
.contains("/creation-type-references/puzzle.webp")
|
||||
);
|
||||
assert_ne!(banners[0].cover_image_src, legacy_banner.cover_image_src);
|
||||
}
|
||||
|
||||
@@ -485,6 +493,60 @@ mod tests {
|
||||
assert_eq!(jump_hop.category_sort_order, 20);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn creation_entry_response_uses_entry_title_for_legacy_unified_creation_title() {
|
||||
let response = build_creation_entry_config_response(CreationEntryConfigSnapshot {
|
||||
config_id: CREATION_ENTRY_CONFIG_GLOBAL_ID.to_string(),
|
||||
start_card: CreationEntryStartCardSnapshot {
|
||||
title: DEFAULT_CREATION_ENTRY_START_TITLE.to_string(),
|
||||
description: DEFAULT_CREATION_ENTRY_START_DESCRIPTION.to_string(),
|
||||
idle_badge: DEFAULT_CREATION_ENTRY_START_IDLE_BADGE.to_string(),
|
||||
busy_badge: DEFAULT_CREATION_ENTRY_START_BUSY_BADGE.to_string(),
|
||||
},
|
||||
type_modal: CreationEntryTypeModalSnapshot {
|
||||
title: DEFAULT_CREATION_ENTRY_MODAL_TITLE.to_string(),
|
||||
description: DEFAULT_CREATION_ENTRY_MODAL_DESCRIPTION.to_string(),
|
||||
},
|
||||
event_banner: default_creation_entry_event_banner_snapshots()
|
||||
.into_iter()
|
||||
.next()
|
||||
.expect("default banner"),
|
||||
event_banners_json: Some(default_creation_entry_event_banners_json()),
|
||||
creation_types: vec![CreationEntryTypeSnapshot {
|
||||
id: "puzzle".to_string(),
|
||||
title: "定制拼图".to_string(),
|
||||
subtitle: "拼图关卡创作".to_string(),
|
||||
badge: "可创建".to_string(),
|
||||
image_src: "/creation-type-references/puzzle.webp".to_string(),
|
||||
visible: true,
|
||||
open: true,
|
||||
sort_order: 30,
|
||||
category_id: "recommended".to_string(),
|
||||
category_label: "热门推荐".to_string(),
|
||||
category_sort_order: 20,
|
||||
updated_at_micros: 1,
|
||||
unified_creation_spec_json: Some(
|
||||
r#"{"playId":"puzzle","title":"想做个什么玩法?","workspaceStage":"puzzle-agent-workspace","generationStage":"puzzle-generating","resultStage":"puzzle-result","fields":[{"id":"pictureDescription","kind":"text","label":"画面描述","required":true}]}"#
|
||||
.to_string(),
|
||||
),
|
||||
}],
|
||||
updated_at_micros: 1,
|
||||
});
|
||||
let puzzle = response
|
||||
.creation_types
|
||||
.iter()
|
||||
.find(|item| item.id == "puzzle")
|
||||
.expect("puzzle entry");
|
||||
|
||||
assert_eq!(
|
||||
puzzle
|
||||
.unified_creation_spec
|
||||
.as_ref()
|
||||
.map(|spec| spec.title.as_str()),
|
||||
Some("定制拼图")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalized_clamps_music_volume_into_valid_range() {
|
||||
let low = RuntimeSettings::normalized(-1.0, RuntimePlatformTheme::Light);
|
||||
|
||||
Reference in New Issue
Block a user