This commit is contained in:
2026-04-30 17:49:07 +08:00
parent 805d6f8cae
commit 9d684cb7b3
615 changed files with 15368 additions and 6172 deletions

View File

@@ -2217,6 +2217,27 @@ pub fn record_custom_world_profile_play(
}
}
#[spacetimedb::procedure]
pub fn record_custom_world_profile_like(
ctx: &mut ProcedureContext,
input: module_custom_world::CustomWorldProfileLikeRecordInput,
) -> CustomWorldLibraryMutationResult {
match ctx.try_with_tx(|tx| record_custom_world_profile_like_record(tx, input.clone())) {
Ok((entry, gallery_entry)) => CustomWorldLibraryMutationResult {
ok: true,
entry: Some(entry),
gallery_entry: Some(gallery_entry),
error_message: None,
},
Err(message) => CustomWorldLibraryMutationResult {
ok: false,
entry: None,
gallery_entry: None,
error_message: Some(message),
},
}
}
#[spacetimedb::procedure]
pub fn list_custom_world_works(
ctx: &mut ProcedureContext,
@@ -2856,7 +2877,9 @@ fn list_custom_world_profile_snapshots(
Ok(entries)
}
fn build_custom_world_profile_list_snapshot(row: &CustomWorldProfile) -> CustomWorldProfileSnapshot {
fn build_custom_world_profile_list_snapshot(
row: &CustomWorldProfile,
) -> CustomWorldProfileSnapshot {
let mut snapshot = build_custom_world_profile_snapshot(row);
snapshot.profile_payload_json = build_custom_world_profile_list_payload_json(row);
snapshot
@@ -3256,6 +3279,89 @@ fn record_custom_world_profile_play_record(
))
}
fn record_custom_world_profile_like_record(
ctx: &ReducerContext,
input: module_custom_world::CustomWorldProfileLikeRecordInput,
) -> Result<(CustomWorldProfileSnapshot, CustomWorldGalleryEntrySnapshot), String> {
let owner_user_id = input.owner_user_id.trim();
let profile_id = input.profile_id.trim();
let user_id = input.user_id.trim();
if owner_user_id.is_empty() || profile_id.is_empty() || user_id.is_empty() {
return Err("custom_world like 参数不能为空".to_string());
}
let existing = ctx
.db
.custom_world_profile()
.profile_id()
.find(&profile_id.to_string())
.filter(|row| row.owner_user_id == owner_user_id)
.filter(|row| {
row.publication_status == CustomWorldPublicationStatus::Published
&& row.deleted_at.is_none()
&& row.published_at.is_some()
})
.ok_or_else(|| "custom_world 已发布作品不存在,无法点赞".to_string())?;
let liked_at = Timestamp::from_micros_since_unix_epoch(input.liked_at_micros);
let inserted_like = record_public_work_like(
ctx,
crate::runtime::PublicWorkLikeRecordInput {
source_type: "custom-world".to_string(),
owner_user_id: existing.owner_user_id.clone(),
profile_id: existing.profile_id.clone(),
user_id: user_id.to_string(),
liked_at_micros: input.liked_at_micros,
},
)?;
if !inserted_like {
let gallery_entry = ctx
.db
.custom_world_gallery_entry()
.profile_id()
.find(&existing.profile_id)
.filter(|row| row.owner_user_id == existing.owner_user_id)
.map(|row| build_custom_world_gallery_entry_snapshot(ctx, &row))
.ok_or_else(|| "custom_world gallery_entry 不存在".to_string())?;
return Ok((build_custom_world_profile_snapshot(&existing), gallery_entry));
}
// 中文注释:点赞关系表先保证一人一作品一次,再递增公开作品计数,避免前端重复点击造成热度膨胀。
let next_row = CustomWorldProfile {
profile_id: existing.profile_id.clone(),
owner_user_id: existing.owner_user_id.clone(),
public_work_code: existing.public_work_code.clone(),
author_public_user_code: existing.author_public_user_code.clone(),
source_agent_session_id: existing.source_agent_session_id.clone(),
publication_status: existing.publication_status,
world_name: existing.world_name.clone(),
subtitle: existing.subtitle.clone(),
summary_text: existing.summary_text.clone(),
theme_mode: existing.theme_mode,
cover_image_src: existing.cover_image_src.clone(),
profile_payload_json: existing.profile_payload_json.clone(),
playable_npc_count: existing.playable_npc_count,
landmark_count: existing.landmark_count,
play_count: existing.play_count,
remix_count: existing.remix_count,
like_count: existing.like_count.saturating_add(1),
author_display_name: existing.author_display_name.clone(),
published_at: existing.published_at,
deleted_at: existing.deleted_at,
created_at: existing.created_at,
updated_at: liked_at,
};
ctx.db
.custom_world_profile()
.profile_id()
.delete(&existing.profile_id);
let inserted = ctx.db.custom_world_profile().insert(next_row);
let gallery_entry = sync_custom_world_gallery_entry_from_profile(ctx, &inserted)?;
Ok((
build_custom_world_profile_snapshot(&inserted),
gallery_entry,
))
}
fn list_custom_world_work_snapshots(
ctx: &ReducerContext,
input: CustomWorldWorksListInput,