拆分自动分离模型并增加文字遮罩区域
将 separation model 拆为 note、node、binding、result 模块 为 SeparationNode 增加 text_mask_areas 字段并同步 TypeScript 类型
This commit is contained in:
@@ -118,6 +118,7 @@ mod tests {
|
||||
description: "image".to_string(),
|
||||
rework_notes: Vec::new(),
|
||||
},
|
||||
text_mask_areas: vec![],
|
||||
children: vec![],
|
||||
rework_count: 0,
|
||||
};
|
||||
@@ -204,6 +205,7 @@ mod tests {
|
||||
width_px: 1,
|
||||
height_px: 1,
|
||||
note: SeparationNote::default(),
|
||||
text_mask_areas: vec![],
|
||||
children: vec![],
|
||||
rework_count: 0,
|
||||
};
|
||||
@@ -263,6 +265,7 @@ mod tests {
|
||||
width_px: 10,
|
||||
height_px: 10,
|
||||
note: SeparationNote::default(),
|
||||
text_mask_areas: vec![],
|
||||
children: vec![],
|
||||
rework_count: 0,
|
||||
};
|
||||
@@ -273,6 +276,7 @@ mod tests {
|
||||
width_px: 10,
|
||||
height_px: 10,
|
||||
note: SeparationNote::default(),
|
||||
text_mask_areas: vec![],
|
||||
children: vec![],
|
||||
rework_count: 0,
|
||||
};
|
||||
@@ -283,6 +287,7 @@ mod tests {
|
||||
width_px: 5,
|
||||
height_px: 5,
|
||||
note: SeparationNote::default(),
|
||||
text_mask_areas: vec![],
|
||||
children: vec![],
|
||||
rework_count: 0,
|
||||
};
|
||||
@@ -295,6 +300,7 @@ mod tests {
|
||||
width_px: 100,
|
||||
height_px: 100,
|
||||
note: SeparationNote::default(),
|
||||
text_mask_areas: vec![],
|
||||
children: vec![a, b, c],
|
||||
rework_count: 0,
|
||||
},
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
use crate::ui_editor::utils::{NodeId, UIDesignImageId};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ts_rs::TS;
|
||||
|
||||
pub const SEPARATION_STATE_SCHEMA_VERSION: &str = "ui-editor-separation-state.v1";
|
||||
pub const MAX_REWORK_COUNT: u32 = 3;
|
||||
pub const MAX_REWORK_NOTE_CHARS: usize = 512;
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize, TS)]
|
||||
#[ts(export, export_to = concat!(env!("CARGO_MANIFEST_DIR"), "/../src/features/ui-editor/types/"))]
|
||||
pub struct SeparationNote {
|
||||
pub description: String,
|
||||
pub rework_notes: Vec<String>,
|
||||
}
|
||||
impl SeparationNote {
|
||||
pub fn as_prompt(&self) -> String {
|
||||
let mut prompt = format!("desc: {}", self.description);
|
||||
if !self.rework_notes.is_empty() {
|
||||
prompt.push_str("\nprevious rework notes:");
|
||||
for note in &self.rework_notes {
|
||||
prompt.push_str("\n- ");
|
||||
prompt.push_str(note);
|
||||
}
|
||||
}
|
||||
prompt
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, TS)]
|
||||
#[ts(export, export_to = concat!(env!("CARGO_MANIFEST_DIR"), "/../src/features/ui-editor/types/"))]
|
||||
pub struct SeparationNode {
|
||||
pub id: NodeId,
|
||||
pub global_pos_x_px: u32,
|
||||
pub global_pos_y_px: u32,
|
||||
pub width_px: u32,
|
||||
pub height_px: u32,
|
||||
pub note: SeparationNote,
|
||||
pub children: Vec<SeparationNode>,
|
||||
pub rework_count: u32,
|
||||
}
|
||||
impl SeparationNode {
|
||||
pub fn as_prompt(&self) -> String {
|
||||
format!(
|
||||
"node_id={} note: {}",
|
||||
self.id.as_str(),
|
||||
self.note.as_prompt()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, TS)]
|
||||
#[ts(export, export_to = concat!(env!("CARGO_MANIFEST_DIR"), "/../src/features/ui-editor/types/"))]
|
||||
pub struct SeparationTree {
|
||||
pub src_ui_design: UIDesignImageId,
|
||||
pub root: SeparationNode,
|
||||
pub root_extractable: bool,
|
||||
}
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, TS)]
|
||||
#[ts(export, export_to = concat!(env!("CARGO_MANIFEST_DIR"), "/../src/features/ui-editor/types/"))]
|
||||
pub struct BoundNode {
|
||||
pub node_id: NodeId,
|
||||
pub cut_image_path: String,
|
||||
}
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, TS)]
|
||||
#[ts(export, export_to = concat!(env!("CARGO_MANIFEST_DIR"), "/../src/features/ui-editor/types/"))]
|
||||
pub struct ProblematicNode {
|
||||
pub node_id: NodeId,
|
||||
pub problem_description: String,
|
||||
pub rework_count: u32,
|
||||
}
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, TS)]
|
||||
#[ts(export, export_to = concat!(env!("CARGO_MANIFEST_DIR"), "/../src/features/ui-editor/types/"))]
|
||||
pub struct SeparationState {
|
||||
pub schema_version: String,
|
||||
pub trees: Vec<SeparationTree>,
|
||||
pub bound: Vec<BoundNode>,
|
||||
pub problematic_nodes: Vec<ProblematicNode>,
|
||||
}
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, TS)]
|
||||
#[ts(export, export_to = concat!(env!("CARGO_MANIFEST_DIR"), "/../src/features/ui-editor/types/"))]
|
||||
pub struct SeparationDTO {
|
||||
pub bound_nodes: Vec<BoundNode>,
|
||||
pub problematic_nodes: Vec<ProblematicNode>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, TS)]
|
||||
#[ts(export, export_to = concat!(env!("CARGO_MANIFEST_DIR"), "/../src/features/ui-editor/types/"))]
|
||||
pub struct SeparationRecoveryDTO {
|
||||
pub exists: bool,
|
||||
pub bound_node_count: usize,
|
||||
pub problematic_node_count: usize,
|
||||
pub has_pending_tree: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct BindingArea {
|
||||
pub global_pos_x_px: u32,
|
||||
pub global_pos_y_px: u32,
|
||||
pub width_px: u32,
|
||||
pub height_px: u32,
|
||||
}
|
||||
impl BindingArea {
|
||||
pub fn validate_in(&self, w: u32, h: u32) -> Result<(), String> {
|
||||
if self.width_px == 0 || self.height_px == 0 {
|
||||
return Err("BindingArea 宽度和高度必须大于 0".into());
|
||||
}
|
||||
if self
|
||||
.global_pos_x_px
|
||||
.checked_add(self.width_px)
|
||||
.is_none_or(|v| v > w)
|
||||
|| self
|
||||
.global_pos_y_px
|
||||
.checked_add(self.height_px)
|
||||
.is_none_or(|v| v > h)
|
||||
{
|
||||
return Err("BindingArea 超出处理图边界".into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub enum BindingDecision {
|
||||
Ok {
|
||||
extracted_area: BindingArea,
|
||||
to_node: NodeId,
|
||||
},
|
||||
NeedRework {
|
||||
problem_description: String,
|
||||
to_node: NodeId,
|
||||
},
|
||||
}
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
|
||||
pub struct BindingResp {
|
||||
pub decisions: Vec<BindingDecision>,
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
use crate::ui_editor::utils::NodeId;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct BindingArea {
|
||||
pub global_pos_x_px: u32,
|
||||
pub global_pos_y_px: u32,
|
||||
pub width_px: u32,
|
||||
pub height_px: u32,
|
||||
}
|
||||
|
||||
impl BindingArea {
|
||||
pub fn validate_in(&self, w: u32, h: u32) -> Result<(), String> {
|
||||
if self.width_px == 0 || self.height_px == 0 {
|
||||
return Err("BindingArea 宽度和高度必须大于 0".into());
|
||||
}
|
||||
if self
|
||||
.global_pos_x_px
|
||||
.checked_add(self.width_px)
|
||||
.is_none_or(|v| v > w)
|
||||
|| self
|
||||
.global_pos_y_px
|
||||
.checked_add(self.height_px)
|
||||
.is_none_or(|v| v > h)
|
||||
{
|
||||
return Err("BindingArea 超出处理图边界".into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub enum BindingDecision {
|
||||
Ok {
|
||||
extracted_area: BindingArea,
|
||||
to_node: NodeId,
|
||||
},
|
||||
NeedRework {
|
||||
problem_description: String,
|
||||
to_node: NodeId,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
|
||||
pub struct BindingResp {
|
||||
pub decisions: Vec<BindingDecision>,
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
mod binding;
|
||||
mod node;
|
||||
mod note;
|
||||
mod result;
|
||||
|
||||
pub use binding::*;
|
||||
pub use node::*;
|
||||
pub use note::*;
|
||||
pub use result::*;
|
||||
|
||||
pub const SEPARATION_STATE_SCHEMA_VERSION: &str = "ui-editor-separation-state.v1";
|
||||
pub const MAX_REWORK_COUNT: u32 = 3;
|
||||
pub const MAX_REWORK_NOTE_CHARS: usize = 512;
|
||||
@@ -0,0 +1,44 @@
|
||||
use crate::ui_editor::utils::{NodeId, UIDesignImageId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ts_rs::TS;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, TS)]
|
||||
#[ts(export, export_to = concat!(env!("CARGO_MANIFEST_DIR"), "/../src/features/ui-editor/types/"))]
|
||||
pub struct TextMaskArea {
|
||||
pub global_pos_x_px: u32,
|
||||
pub global_pos_y_px: u32,
|
||||
pub width_px: u32,
|
||||
pub height_px: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, TS)]
|
||||
#[ts(export, export_to = concat!(env!("CARGO_MANIFEST_DIR"), "/../src/features/ui-editor/types/"))]
|
||||
pub struct SeparationNode {
|
||||
pub id: NodeId,
|
||||
pub global_pos_x_px: u32,
|
||||
pub global_pos_y_px: u32,
|
||||
pub width_px: u32,
|
||||
pub height_px: u32,
|
||||
pub note: super::SeparationNote,
|
||||
pub text_mask_areas: Vec<TextMaskArea>,
|
||||
pub children: Vec<SeparationNode>,
|
||||
pub rework_count: u32,
|
||||
}
|
||||
|
||||
impl SeparationNode {
|
||||
pub fn as_prompt(&self) -> String {
|
||||
format!(
|
||||
"node_id={} note: {}",
|
||||
self.id.as_str(),
|
||||
self.note.as_prompt()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, TS)]
|
||||
#[ts(export, export_to = concat!(env!("CARGO_MANIFEST_DIR"), "/../src/features/ui-editor/types/"))]
|
||||
pub struct SeparationTree {
|
||||
pub src_ui_design: UIDesignImageId,
|
||||
pub root: SeparationNode,
|
||||
pub root_extractable: bool,
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ts_rs::TS;
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize, TS)]
|
||||
#[ts(export, export_to = concat!(env!("CARGO_MANIFEST_DIR"), "/../src/features/ui-editor/types/"))]
|
||||
pub struct SeparationNote {
|
||||
pub description: String,
|
||||
pub rework_notes: Vec<String>,
|
||||
}
|
||||
|
||||
impl SeparationNote {
|
||||
pub fn as_prompt(&self) -> String {
|
||||
let mut prompt = format!("desc: {}", self.description);
|
||||
if !self.rework_notes.is_empty() {
|
||||
prompt.push_str("\nprevious rework notes:");
|
||||
for note in &self.rework_notes {
|
||||
prompt.push_str("\n- ");
|
||||
prompt.push_str(note);
|
||||
}
|
||||
}
|
||||
prompt
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
use crate::ui_editor::utils::NodeId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ts_rs::TS;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, TS)]
|
||||
#[ts(export, export_to = concat!(env!("CARGO_MANIFEST_DIR"), "/../src/features/ui-editor/types/"))]
|
||||
pub struct BoundNode {
|
||||
pub node_id: NodeId,
|
||||
pub cut_image_path: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, TS)]
|
||||
#[ts(export, export_to = concat!(env!("CARGO_MANIFEST_DIR"), "/../src/features/ui-editor/types/"))]
|
||||
pub struct ProblematicNode {
|
||||
pub node_id: NodeId,
|
||||
pub problem_description: String,
|
||||
pub rework_count: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, TS)]
|
||||
#[ts(export, export_to = concat!(env!("CARGO_MANIFEST_DIR"), "/../src/features/ui-editor/types/"))]
|
||||
pub struct SeparationState {
|
||||
pub schema_version: String,
|
||||
pub trees: Vec<super::SeparationTree>,
|
||||
pub bound: Vec<BoundNode>,
|
||||
pub problematic_nodes: Vec<ProblematicNode>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, TS)]
|
||||
#[ts(export, export_to = concat!(env!("CARGO_MANIFEST_DIR"), "/../src/features/ui-editor/types/"))]
|
||||
pub struct SeparationDTO {
|
||||
pub bound_nodes: Vec<BoundNode>,
|
||||
pub problematic_nodes: Vec<ProblematicNode>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, TS)]
|
||||
#[ts(export, export_to = concat!(env!("CARGO_MANIFEST_DIR"), "/../src/features/ui-editor/types/"))]
|
||||
pub struct SeparationRecoveryDTO {
|
||||
pub exists: bool,
|
||||
pub bound_node_count: usize,
|
||||
pub problematic_node_count: usize,
|
||||
pub has_pending_tree: bool,
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { NodeId } from "./NodeId";
|
||||
import type { SeparationNote } from "./SeparationNote";
|
||||
import type { TextMaskArea } from "./TextMaskArea";
|
||||
|
||||
export type SeparationNode = { id: NodeId, global_pos_x_px: number, global_pos_y_px: number, width_px: number, height_px: number, note: SeparationNote, children: Array<SeparationNode>, rework_count: number, };
|
||||
export type SeparationNode = { id: NodeId, global_pos_x_px: number, global_pos_y_px: number, width_px: number, height_px: number, note: SeparationNote, text_mask_areas: Array<TextMaskArea>, children: Array<SeparationNode>, rework_count: number, };
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type TextMaskArea = { global_pos_x_px: number, global_pos_y_px: number, width_px: number, height_px: number, };
|
||||
Reference in New Issue
Block a user