新增图片画布编辑器
新增 /editor 图片画布入口与 Lovart 风格画布交互 新增图片画布工程和资源持久化的 SpacetimeDB 表、绑定与 api-server BFF 接入图片生成和修改的 VectorEngine gpt-image-2 后端通道 完善素材库文件夹、重命名、上传删除、图层和元数据交互 补充图片画布技术方案、领域词、执行跟踪和浏览器 smoke 截图
This commit is contained in:
226
server-rs/crates/spacetime-client/src/mapper/editor_project.rs
Normal file
226
server-rs/crates/spacetime-client/src/mapper/editor_project.rs
Normal file
@@ -0,0 +1,226 @@
|
||||
use super::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct EditorCanvasViewportRecord {
|
||||
pub x: f64,
|
||||
pub y: f64,
|
||||
pub scale: f64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct EditorProjectRecord {
|
||||
pub project_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub title: String,
|
||||
pub viewport: EditorCanvasViewportRecord,
|
||||
pub layers: serde_json::Value,
|
||||
pub resources: Vec<EditorProjectResourceRecord>,
|
||||
pub created_at: String,
|
||||
pub updated_at: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct EditorProjectResourceRecord {
|
||||
pub resource_id: String,
|
||||
pub project_id: String,
|
||||
pub asset_object_id: Option<String>,
|
||||
pub image_src: String,
|
||||
pub object_key: Option<String>,
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
pub source_type: String,
|
||||
pub prompt: Option<String>,
|
||||
pub actual_prompt: Option<String>,
|
||||
pub model: Option<String>,
|
||||
pub provider: Option<String>,
|
||||
pub task_id: Option<String>,
|
||||
pub source_resource_id: Option<String>,
|
||||
pub created_at: String,
|
||||
pub updated_at: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct EditorProjectCreateRecordInput {
|
||||
pub project_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub title: String,
|
||||
pub now_micros: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct EditorProjectGetRecordInput {
|
||||
pub project_id: String,
|
||||
pub owner_user_id: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct EditorProjectLayoutSaveRecordInput {
|
||||
pub project_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub viewport: EditorCanvasViewportRecord,
|
||||
pub layers_json: String,
|
||||
pub updated_at_micros: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct EditorProjectResourceCreateRecordInput {
|
||||
pub resource_id: String,
|
||||
pub project_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub asset_object_id: Option<String>,
|
||||
pub image_src: String,
|
||||
pub object_key: Option<String>,
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
pub source_type: String,
|
||||
pub prompt: Option<String>,
|
||||
pub actual_prompt: Option<String>,
|
||||
pub model: Option<String>,
|
||||
pub provider: Option<String>,
|
||||
pub task_id: Option<String>,
|
||||
pub source_resource_id: Option<String>,
|
||||
pub updated_at_micros: i64,
|
||||
}
|
||||
|
||||
impl From<EditorProjectCreateRecordInput> for crate::module_bindings::EditorProjectCreateInput {
|
||||
fn from(input: EditorProjectCreateRecordInput) -> Self {
|
||||
Self {
|
||||
project_id: input.project_id,
|
||||
owner_user_id: input.owner_user_id,
|
||||
title: input.title,
|
||||
now_micros: input.now_micros,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EditorProjectGetRecordInput> for crate::module_bindings::EditorProjectGetInput {
|
||||
fn from(input: EditorProjectGetRecordInput) -> Self {
|
||||
Self {
|
||||
project_id: input.project_id,
|
||||
owner_user_id: input.owner_user_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EditorProjectLayoutSaveRecordInput>
|
||||
for crate::module_bindings::EditorProjectLayoutSaveInput
|
||||
{
|
||||
fn from(input: EditorProjectLayoutSaveRecordInput) -> Self {
|
||||
Self {
|
||||
project_id: input.project_id,
|
||||
owner_user_id: input.owner_user_id,
|
||||
viewport: crate::module_bindings::EditorProjectViewportSnapshot {
|
||||
x: input.viewport.x,
|
||||
y: input.viewport.y,
|
||||
scale: input.viewport.scale,
|
||||
},
|
||||
layers_json: input.layers_json,
|
||||
updated_at_micros: input.updated_at_micros,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EditorProjectResourceCreateRecordInput>
|
||||
for crate::module_bindings::EditorProjectResourceCreateInput
|
||||
{
|
||||
fn from(input: EditorProjectResourceCreateRecordInput) -> Self {
|
||||
Self {
|
||||
resource_id: input.resource_id,
|
||||
project_id: input.project_id,
|
||||
owner_user_id: input.owner_user_id,
|
||||
asset_object_id: input.asset_object_id,
|
||||
image_src: input.image_src,
|
||||
object_key: input.object_key,
|
||||
width: input.width,
|
||||
height: input.height,
|
||||
source_type: input.source_type,
|
||||
prompt: input.prompt,
|
||||
actual_prompt: input.actual_prompt,
|
||||
model: input.model,
|
||||
provider: input.provider,
|
||||
task_id: input.task_id,
|
||||
source_resource_id: input.source_resource_id,
|
||||
updated_at_micros: input.updated_at_micros,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn map_editor_project_optional_procedure_result(
|
||||
result: EditorProjectProcedureResult,
|
||||
) -> Result<Option<EditorProjectRecord>, SpacetimeClientError> {
|
||||
if !result.ok {
|
||||
return Err(SpacetimeClientError::procedure_failed(result.error_message));
|
||||
}
|
||||
|
||||
result.project.map(map_editor_project_snapshot).transpose()
|
||||
}
|
||||
|
||||
pub(crate) fn map_editor_project_required_procedure_result(
|
||||
result: EditorProjectProcedureResult,
|
||||
) -> Result<EditorProjectRecord, SpacetimeClientError> {
|
||||
map_editor_project_optional_procedure_result(result)?
|
||||
.ok_or_else(|| SpacetimeClientError::missing_snapshot("图片画布工程快照"))
|
||||
}
|
||||
|
||||
pub(crate) fn map_editor_project_resource_procedure_result(
|
||||
result: EditorProjectResourceProcedureResult,
|
||||
) -> Result<EditorProjectResourceRecord, SpacetimeClientError> {
|
||||
if !result.ok {
|
||||
return Err(SpacetimeClientError::procedure_failed(result.error_message));
|
||||
}
|
||||
|
||||
result
|
||||
.resource
|
||||
.map(map_editor_project_resource_snapshot)
|
||||
.ok_or_else(|| SpacetimeClientError::missing_snapshot("图片画布资源快照"))
|
||||
}
|
||||
|
||||
fn map_editor_project_snapshot(
|
||||
snapshot: EditorProjectSnapshot,
|
||||
) -> Result<EditorProjectRecord, SpacetimeClientError> {
|
||||
let layers = serde_json::from_str(&snapshot.layers_json).map_err(|error| {
|
||||
SpacetimeClientError::validation_failed(format!("图片画布图层布局 JSON 无法解析:{error}"))
|
||||
})?;
|
||||
|
||||
Ok(EditorProjectRecord {
|
||||
project_id: snapshot.project_id,
|
||||
owner_user_id: snapshot.owner_user_id,
|
||||
title: snapshot.title,
|
||||
viewport: EditorCanvasViewportRecord {
|
||||
x: snapshot.viewport.x,
|
||||
y: snapshot.viewport.y,
|
||||
scale: snapshot.viewport.scale,
|
||||
},
|
||||
layers,
|
||||
resources: snapshot
|
||||
.resources
|
||||
.into_iter()
|
||||
.map(map_editor_project_resource_snapshot)
|
||||
.collect(),
|
||||
created_at: format_timestamp_micros(snapshot.created_at_micros),
|
||||
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
|
||||
})
|
||||
}
|
||||
|
||||
fn map_editor_project_resource_snapshot(
|
||||
snapshot: EditorProjectResourceSnapshot,
|
||||
) -> EditorProjectResourceRecord {
|
||||
EditorProjectResourceRecord {
|
||||
resource_id: snapshot.resource_id,
|
||||
project_id: snapshot.project_id,
|
||||
asset_object_id: snapshot.asset_object_id,
|
||||
image_src: snapshot.image_src,
|
||||
object_key: snapshot.object_key,
|
||||
width: snapshot.width,
|
||||
height: snapshot.height,
|
||||
source_type: snapshot.source_type,
|
||||
prompt: snapshot.prompt,
|
||||
actual_prompt: snapshot.actual_prompt,
|
||||
model: snapshot.model,
|
||||
provider: snapshot.provider,
|
||||
task_id: snapshot.task_id,
|
||||
source_resource_id: snapshot.source_resource_id,
|
||||
created_at: format_timestamp_micros(snapshot.created_at_micros),
|
||||
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user