fix: 模板移除project关联
This commit is contained in:
@@ -201,9 +201,11 @@ impl DraftContentParser {
|
|||||||
material.template_id = template.id.clone();
|
material.template_id = template.id.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 构建素材映射表:素材ID -> original_id (用于片段关联)
|
||||||
|
// 片段的 material_id 对应素材的 id,需要映射到 original_id
|
||||||
let material_map: HashMap<String, String> = materials
|
let material_map: HashMap<String, String> = materials
|
||||||
.iter()
|
.iter()
|
||||||
.map(|m| (m.original_id.clone(), m.id.clone()))
|
.map(|m| (m.id.clone(), m.original_id.clone())) // 键是素材ID,值是original_id
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
for material in materials {
|
for material in materials {
|
||||||
@@ -330,21 +332,20 @@ impl DraftContentParser {
|
|||||||
missing_files.push(video.path.clone());
|
missing_files.push(video.path.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// original_id 使用 local_material_id,如果没有则使用空字符串
|
||||||
|
let original_id = video.local_material_id.clone()
|
||||||
|
.filter(|id| !id.is_empty())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
let mut material = TemplateMaterial::new(
|
let mut material = TemplateMaterial::new(
|
||||||
|
video.id.clone(), // 使用素材的真实ID
|
||||||
String::new(), // template_id 稍后设置
|
String::new(), // template_id 稍后设置
|
||||||
video.id.clone(), // 主键使用 id
|
original_id, // original_id 对应 local_material_id
|
||||||
name,
|
name,
|
||||||
TemplateMaterialType::Video,
|
TemplateMaterialType::Video,
|
||||||
video.path.clone(),
|
video.path.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// 设置 original_id 为 local_material_id
|
|
||||||
if let Some(local_material_id) = &video.local_material_id {
|
|
||||||
if !local_material_id.is_empty() {
|
|
||||||
material.original_id = local_material_id.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
material.duration = video.duration;
|
material.duration = video.duration;
|
||||||
material.width = video.width;
|
material.width = video.width;
|
||||||
material.height = video.height;
|
material.height = video.height;
|
||||||
@@ -367,14 +368,15 @@ impl DraftContentParser {
|
|||||||
missing_files.push(audio.path.clone());
|
missing_files.push(audio.path.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用 local_material_id 作为主键,如果没有则使用 id
|
// original_id 使用 local_material_id,如果没有则使用空字符串
|
||||||
let material_id = audio.local_material_id.clone()
|
let original_id = audio.local_material_id.clone()
|
||||||
.filter(|id| !id.is_empty())
|
.filter(|id| !id.is_empty())
|
||||||
.unwrap_or_else(|| audio.id.clone());
|
.unwrap_or_default();
|
||||||
|
|
||||||
let mut material = TemplateMaterial::new(
|
let mut material = TemplateMaterial::new(
|
||||||
|
audio.id.clone(), // 使用素材的真实ID
|
||||||
String::new(), // template_id 稍后设置
|
String::new(), // template_id 稍后设置
|
||||||
material_id, // 使用 local_material_id 作为主键
|
original_id, // original_id 对应 local_material_id
|
||||||
audio.name.clone(),
|
audio.name.clone(),
|
||||||
TemplateMaterialType::Audio,
|
TemplateMaterialType::Audio,
|
||||||
audio.path.clone(),
|
audio.path.clone(),
|
||||||
@@ -413,9 +415,15 @@ impl DraftContentParser {
|
|||||||
missing_files.push(path.clone());
|
missing_files.push(path.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// original_id 使用 local_material_id,如果没有则使用空字符串
|
||||||
|
let original_id = image.local_material_id.clone()
|
||||||
|
.filter(|id| !id.is_empty())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
let mut material = TemplateMaterial::new(
|
let mut material = TemplateMaterial::new(
|
||||||
|
image.id.clone(), // 使用素材的真实ID
|
||||||
String::new(), // template_id 稍后设置
|
String::new(), // template_id 稍后设置
|
||||||
image.id.clone(),
|
original_id, // original_id 对应 local_material_id
|
||||||
name,
|
name,
|
||||||
TemplateMaterialType::Image,
|
TemplateMaterialType::Image,
|
||||||
path,
|
path,
|
||||||
@@ -439,8 +447,9 @@ impl DraftContentParser {
|
|||||||
let name = text.content.clone().unwrap_or_else(|| "文本".to_string());
|
let name = text.content.clone().unwrap_or_else(|| "文本".to_string());
|
||||||
|
|
||||||
let mut material = TemplateMaterial::new(
|
let mut material = TemplateMaterial::new(
|
||||||
|
text.id.clone(), // 使用素材的真实ID
|
||||||
String::new(), // template_id 稍后设置
|
String::new(), // template_id 稍后设置
|
||||||
text.id.clone(),
|
String::new(), // 文字素材没有 local_material_id
|
||||||
name,
|
name,
|
||||||
TemplateMaterialType::Text,
|
TemplateMaterialType::Text,
|
||||||
String::new(), // 文本素材没有文件路径
|
String::new(), // 文本素材没有文件路径
|
||||||
@@ -472,8 +481,9 @@ impl DraftContentParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut material = TemplateMaterial::new(
|
let mut material = TemplateMaterial::new(
|
||||||
|
sticker.id.clone(), // 使用素材的真实ID
|
||||||
String::new(), // template_id 稍后设置
|
String::new(), // template_id 稍后设置
|
||||||
sticker.id.clone(),
|
String::new(), // 贴纸素材没有 local_material_id
|
||||||
name,
|
name,
|
||||||
TemplateMaterialType::Sticker,
|
TemplateMaterialType::Sticker,
|
||||||
path,
|
path,
|
||||||
@@ -503,8 +513,9 @@ impl DraftContentParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut material = TemplateMaterial::new(
|
let mut material = TemplateMaterial::new(
|
||||||
|
effect.id.clone(), // 使用素材的真实ID
|
||||||
String::new(), // template_id 稍后设置
|
String::new(), // template_id 稍后设置
|
||||||
effect.id.clone(),
|
String::new(), // 特效素材没有 local_material_id
|
||||||
name,
|
name,
|
||||||
TemplateMaterialType::Effect,
|
TemplateMaterialType::Effect,
|
||||||
path,
|
path,
|
||||||
@@ -525,8 +536,9 @@ impl DraftContentParser {
|
|||||||
let name = "画布".to_string();
|
let name = "画布".to_string();
|
||||||
|
|
||||||
let mut material = TemplateMaterial::new(
|
let mut material = TemplateMaterial::new(
|
||||||
|
canvas.id.clone(), // 使用素材的真实ID
|
||||||
String::new(), // template_id 稍后设置
|
String::new(), // template_id 稍后设置
|
||||||
canvas.id.clone(),
|
String::new(), // 画布素材没有 local_material_id
|
||||||
name,
|
name,
|
||||||
TemplateMaterialType::Canvas,
|
TemplateMaterialType::Canvas,
|
||||||
String::new(), // 画布素材没有文件路径
|
String::new(), // 画布素材没有文件路径
|
||||||
@@ -562,6 +574,7 @@ impl DraftContentParser {
|
|||||||
|
|
||||||
let track_name = format!("轨道{} ({})", track_index + 1, track_raw.track_type);
|
let track_name = format!("轨道{} ({})", track_index + 1, track_raw.track_type);
|
||||||
let mut track = Track::new(
|
let mut track = Track::new(
|
||||||
|
track_raw.id.clone(), // 使用轨道的真实ID
|
||||||
template_id.to_string(),
|
template_id.to_string(),
|
||||||
track_name,
|
track_name,
|
||||||
track_type,
|
track_type,
|
||||||
@@ -603,6 +616,7 @@ impl DraftContentParser {
|
|||||||
|
|
||||||
let segment_name = format!("片段{}", segment_index + 1);
|
let segment_name = format!("片段{}", segment_index + 1);
|
||||||
let mut segment = TrackSegment::new(
|
let mut segment = TrackSegment::new(
|
||||||
|
segment_raw.id.clone(), // 使用片段的真实ID
|
||||||
track_id.to_string(),
|
track_id.to_string(),
|
||||||
segment_name,
|
segment_name,
|
||||||
start_time,
|
start_time,
|
||||||
|
|||||||
@@ -187,7 +187,6 @@ impl TemplateImportService {
|
|||||||
info!(
|
info!(
|
||||||
template_id = %template.id,
|
template_id = %template.id,
|
||||||
template_name = %template.name,
|
template_name = %template.name,
|
||||||
project_id = ?template.project_id,
|
|
||||||
"开始保存模板到数据库"
|
"开始保存模板到数据库"
|
||||||
);
|
);
|
||||||
template.update_import_status(ImportStatus::Processing);
|
template.update_import_status(ImportStatus::Processing);
|
||||||
@@ -311,12 +310,8 @@ impl TemplateImportService {
|
|||||||
return Err(anyhow!("模板验证失败: {}", validation_errors.join(", ")));
|
return Err(anyhow!("模板验证失败: {}", validation_errors.join(", ")));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置项目关联
|
|
||||||
let mut template = parse_result.template.clone();
|
|
||||||
template.project_id = request.project_id.clone();
|
|
||||||
|
|
||||||
Ok(ParseResult {
|
Ok(ParseResult {
|
||||||
template,
|
template: parse_result.template,
|
||||||
missing_files: parse_result.missing_files,
|
missing_files: parse_result.missing_files,
|
||||||
warnings: parse_result.warnings,
|
warnings: parse_result.warnings,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -71,19 +71,14 @@ impl TemplateService {
|
|||||||
// 保存模板基本信息
|
// 保存模板基本信息
|
||||||
tx.execute(
|
tx.execute(
|
||||||
"INSERT OR REPLACE INTO templates (
|
"INSERT OR REPLACE INTO templates (
|
||||||
id, name, description, project_id, canvas_width, canvas_height,
|
id, name, description, canvas_width, canvas_height,
|
||||||
canvas_ratio, duration, fps, import_status, source_file_path,
|
canvas_ratio, duration, fps, import_status, source_file_path,
|
||||||
created_at, updated_at, is_active
|
created_at, updated_at, is_active
|
||||||
) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14)",
|
) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13)",
|
||||||
params![
|
params![
|
||||||
template.id,
|
template.id,
|
||||||
template.name,
|
template.name,
|
||||||
template.description,
|
template.description,
|
||||||
if template.project_id.as_ref().map_or(true, |id| id.is_empty()) {
|
|
||||||
None::<String>
|
|
||||||
} else {
|
|
||||||
template.project_id.clone()
|
|
||||||
},
|
|
||||||
template.canvas_config.width,
|
template.canvas_config.width,
|
||||||
template.canvas_config.height,
|
template.canvas_config.height,
|
||||||
template.canvas_config.ratio,
|
template.canvas_config.ratio,
|
||||||
@@ -183,7 +178,7 @@ impl TemplateService {
|
|||||||
|
|
||||||
// 查询模板基本信息
|
// 查询模板基本信息
|
||||||
let template_result = conn.query_row(
|
let template_result = conn.query_row(
|
||||||
"SELECT id, name, description, project_id, canvas_width, canvas_height,
|
"SELECT id, name, description, canvas_width, canvas_height,
|
||||||
canvas_ratio, duration, fps, import_status, source_file_path,
|
canvas_ratio, duration, fps, import_status, source_file_path,
|
||||||
created_at, updated_at, is_active
|
created_at, updated_at, is_active
|
||||||
FROM templates WHERE id = ?1",
|
FROM templates WHERE id = ?1",
|
||||||
@@ -333,7 +328,7 @@ impl TemplateService {
|
|||||||
|row| Ok(row.get::<_, i64>(0)? as u32)
|
|row| Ok(row.get::<_, i64>(0)? as u32)
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mut sql = "SELECT id, name, description, project_id, canvas_width, canvas_height,
|
let mut sql = "SELECT id, name, description, canvas_width, canvas_height,
|
||||||
canvas_ratio, duration, fps, import_status, source_file_path,
|
canvas_ratio, duration, fps, import_status, source_file_path,
|
||||||
created_at, updated_at, is_active
|
created_at, updated_at, is_active
|
||||||
FROM templates WHERE is_active = 1 ORDER BY created_at DESC".to_string();
|
FROM templates WHERE is_active = 1 ORDER BY created_at DESC".to_string();
|
||||||
@@ -402,7 +397,6 @@ impl TemplateService {
|
|||||||
id: row.get("id")?,
|
id: row.get("id")?,
|
||||||
name: row.get("name")?,
|
name: row.get("name")?,
|
||||||
description: row.get("description")?,
|
description: row.get("description")?,
|
||||||
project_id: row.get("project_id")?,
|
|
||||||
canvas_config,
|
canvas_config,
|
||||||
duration: row.get::<_, i64>("duration")? as u64,
|
duration: row.get::<_, i64>("duration")? as u64,
|
||||||
fps: row.get("fps")?,
|
fps: row.get("fps")?,
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ pub struct Template {
|
|||||||
pub id: String,
|
pub id: String,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub project_id: Option<String>, // 关联的项目ID
|
|
||||||
pub canvas_config: CanvasConfig,
|
pub canvas_config: CanvasConfig,
|
||||||
pub duration: u64, // 模板总时长(微秒)
|
pub duration: u64, // 模板总时长(微秒)
|
||||||
pub fps: f64,
|
pub fps: f64,
|
||||||
@@ -179,7 +178,6 @@ impl Template {
|
|||||||
id: uuid::Uuid::new_v4().to_string(),
|
id: uuid::Uuid::new_v4().to_string(),
|
||||||
name,
|
name,
|
||||||
description: None,
|
description: None,
|
||||||
project_id: None,
|
|
||||||
canvas_config,
|
canvas_config,
|
||||||
duration,
|
duration,
|
||||||
fps,
|
fps,
|
||||||
@@ -237,17 +235,18 @@ impl Template {
|
|||||||
impl TemplateMaterial {
|
impl TemplateMaterial {
|
||||||
/// 创建新的模板素材实例
|
/// 创建新的模板素材实例
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
id: String, // 素材的真实ID(来自剪映草稿)
|
||||||
template_id: String,
|
template_id: String,
|
||||||
original_id: String,
|
original_id: String, // local_material_id
|
||||||
name: String,
|
name: String,
|
||||||
material_type: TemplateMaterialType,
|
material_type: TemplateMaterialType,
|
||||||
original_path: String,
|
original_path: String,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let now = Utc::now();
|
let now = Utc::now();
|
||||||
Self {
|
Self {
|
||||||
id: original_id.clone(), // 使用原始ID作为主键,保持与剪映草稿的一致性
|
id, // 使用传入的真实ID
|
||||||
template_id,
|
template_id,
|
||||||
original_id,
|
original_id, // original_id 对应 local_material_id,可以重复
|
||||||
name,
|
name,
|
||||||
material_type,
|
material_type,
|
||||||
original_path,
|
original_path,
|
||||||
@@ -298,6 +297,7 @@ impl TemplateMaterial {
|
|||||||
impl Track {
|
impl Track {
|
||||||
/// 创建新的轨道实例
|
/// 创建新的轨道实例
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
id: String, // 轨道的真实ID(来自剪映草稿)
|
||||||
template_id: String,
|
template_id: String,
|
||||||
name: String,
|
name: String,
|
||||||
track_type: TrackType,
|
track_type: TrackType,
|
||||||
@@ -305,7 +305,7 @@ impl Track {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
let now = Utc::now();
|
let now = Utc::now();
|
||||||
Self {
|
Self {
|
||||||
id: uuid::Uuid::new_v4().to_string(),
|
id, // 使用传入的真实ID
|
||||||
template_id,
|
template_id,
|
||||||
name,
|
name,
|
||||||
track_type,
|
track_type,
|
||||||
@@ -335,6 +335,7 @@ impl Track {
|
|||||||
impl TrackSegment {
|
impl TrackSegment {
|
||||||
/// 创建新的轨道片段实例
|
/// 创建新的轨道片段实例
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
id: String, // 片段的真实ID(来自剪映草稿)
|
||||||
track_id: String,
|
track_id: String,
|
||||||
name: String,
|
name: String,
|
||||||
start_time: u64,
|
start_time: u64,
|
||||||
@@ -343,7 +344,7 @@ impl TrackSegment {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
let now = Utc::now();
|
let now = Utc::now();
|
||||||
Self {
|
Self {
|
||||||
id: uuid::Uuid::new_v4().to_string(),
|
id, // 使用传入的真实ID
|
||||||
track_id,
|
track_id,
|
||||||
template_material_id: None,
|
template_material_id: None,
|
||||||
name,
|
name,
|
||||||
|
|||||||
@@ -265,7 +265,6 @@ impl Database {
|
|||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
description TEXT,
|
description TEXT,
|
||||||
project_id TEXT,
|
|
||||||
canvas_width INTEGER NOT NULL,
|
canvas_width INTEGER NOT NULL,
|
||||||
canvas_height INTEGER NOT NULL,
|
canvas_height INTEGER NOT NULL,
|
||||||
canvas_ratio TEXT NOT NULL,
|
canvas_ratio TEXT NOT NULL,
|
||||||
@@ -275,8 +274,7 @@ impl Database {
|
|||||||
source_file_path TEXT,
|
source_file_path TEXT,
|
||||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
is_active BOOLEAN DEFAULT 1,
|
is_active BOOLEAN DEFAULT 1
|
||||||
FOREIGN KEY (project_id) REFERENCES projects (id) ON DELETE SET NULL
|
|
||||||
)",
|
)",
|
||||||
[],
|
[],
|
||||||
)?;
|
)?;
|
||||||
@@ -380,11 +378,6 @@ impl Database {
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
// 创建模板表索引
|
// 创建模板表索引
|
||||||
conn.execute(
|
|
||||||
"CREATE INDEX IF NOT EXISTS idx_templates_project_id ON templates (project_id)",
|
|
||||||
[],
|
|
||||||
)?;
|
|
||||||
|
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_templates_import_status ON templates (import_status)",
|
"CREATE INDEX IF NOT EXISTS idx_templates_import_status ON templates (import_status)",
|
||||||
[],
|
[],
|
||||||
@@ -406,6 +399,41 @@ impl Database {
|
|||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 移除模板表的 project_id 字段(如果存在)
|
||||||
|
// SQLite 不支持 DROP COLUMN,需要重建表
|
||||||
|
let _ = conn.execute(
|
||||||
|
"CREATE TABLE IF NOT EXISTS templates_new (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
canvas_width INTEGER NOT NULL,
|
||||||
|
canvas_height INTEGER NOT NULL,
|
||||||
|
canvas_ratio TEXT NOT NULL,
|
||||||
|
duration INTEGER NOT NULL,
|
||||||
|
fps REAL NOT NULL,
|
||||||
|
import_status TEXT NOT NULL DEFAULT 'Pending',
|
||||||
|
source_file_path TEXT,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
is_active BOOLEAN DEFAULT 1
|
||||||
|
)",
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
// 迁移数据(排除 project_id)
|
||||||
|
let _ = conn.execute(
|
||||||
|
"INSERT OR IGNORE INTO templates_new
|
||||||
|
SELECT id, name, description, canvas_width, canvas_height, canvas_ratio,
|
||||||
|
duration, fps, import_status, source_file_path, created_at, updated_at, is_active
|
||||||
|
FROM templates",
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
// 删除旧表并重命名新表
|
||||||
|
let _ = conn.execute("DROP TABLE IF EXISTS templates_old", []);
|
||||||
|
let _ = conn.execute("ALTER TABLE templates RENAME TO templates_old", []);
|
||||||
|
let _ = conn.execute("ALTER TABLE templates_new RENAME TO templates", []);
|
||||||
|
|
||||||
// 创建模板素材表索引
|
// 创建模板素材表索引
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_template_materials_template_id ON template_materials (template_id)",
|
"CREATE INDEX IF NOT EXISTS idx_template_materials_template_id ON template_materials (template_id)",
|
||||||
|
|||||||
Reference in New Issue
Block a user