diff --git a/python_core/cli/commands/template.py b/python_core/cli/commands/template.py index 1dd6b82..f23a845 100644 --- a/python_core/cli/commands/template.py +++ b/python_core/cli/commands/template.py @@ -5,6 +5,7 @@ from pathlib import Path from typing import Optional, List from dataclasses import asdict +from datetime import datetime import typer from python_core.utils.jsonrpc_enhanced import create_response_handler, create_progress_reporter from python_core.services.template_manager_cloud import TemplateManagerCloud, TemplateInfo @@ -454,6 +455,82 @@ def get_popular_tags( response.error(-32603, f"获取热门标签失败: {str(e)}") +@template_app.command("update-segment") +def update_segment_name( + template_id: str = typer.Argument(..., help="模板ID"), + segment_id: str = typer.Argument(..., help="片段ID"), + new_name: str = typer.Argument(..., help="新名称"), + user_id: Optional[str] = typer.Option(None, "--user-id", help="用户ID"), + verbose: bool = typer.Option(False, "--verbose", "-v", help="详细输出"), + json_output: bool = typer.Option(True, "--json", help="JSON格式输出") +): + """更新模板片段名称""" + response = create_response_handler() + try: + # 使用 PostgreSQL 模板表 + from python_core.database.template_postgres import template_table + + # 获取模板 + template = template_table.get_template_by_id(template_id) + if not template: + response.error(-32604, f"模板不存在: {template_id}") + return + + # 检查权限 + if user_id and template.user_id != user_id: + response.error(-32605, f"无权限修改模板: {template_id}") + return + + # 获取 draft_content + draft_content = template_table.get_draft_content(template_id) + if draft_content is None: + response.error(-32606, f"模板详细信息不存在: {template_id}") + return + + # 确保 draft_content 是字典类型 + if not isinstance(draft_content, dict): + draft_content = {} + + # 查找并更新片段名称 + updated = False + tracks_data = draft_content.get('tracks', []) + + for track in tracks_data: + if isinstance(track, dict): + segments = track.get('segments', []) + for segment in segments: + if isinstance(segment, dict) and segment.get('id') == segment_id: + segment['name'] = new_name + updated = True + break + if updated: + break + + if not updated: + response.error(-32607, f"片段不存在: {segment_id}") + return + + # 更新数据库中的 draft_content + success = template_table.update_template(template_id, { + 'draft_content': draft_content, + 'updated_at': datetime.now().isoformat() + }) + + if success: + response.success({ + 'template_id': template_id, + 'segment_id': segment_id, + 'new_name': new_name, + 'updated': True + }) + else: + response.error(-32608, "更新失败") + + except Exception as e: + logger.error(f"更新片段名称失败: {e}") + response.error(-32603, f"更新片段名称失败: {str(e)}") + + @template_app.command("by-tag") def get_templates_by_tag( tag: str = typer.Argument(..., help="标签名称"), @@ -468,7 +545,7 @@ def get_templates_by_tag( try: # 创建模板管理器 manager = TemplateManagerCloud(user_id=user_id or "default") - + # 根据标签获取模板 templates = manager.get_templates_by_tag(tag, include_cloud=include_cloud, limit=limit) diff --git a/src-tauri/src/commands/template.rs b/src-tauri/src/commands/template.rs index 329cbb6..04b7573 100644 --- a/src-tauri/src/commands/template.rs +++ b/src-tauri/src/commands/template.rs @@ -59,6 +59,16 @@ pub struct TemplateSearchRequest { pub json_output: Option, } +#[derive(Debug, Deserialize)] +pub struct TemplateUpdateSegmentRequest { + pub template_id: String, + pub segment_id: String, + pub new_name: String, + pub user_id: Option, + pub verbose: Option, + pub json_output: Option, +} + // Re-export PythonProgress as ImportProgress for backward compatibility // Note: This is used by frontend TypeScript definitions #[allow(unused_imports)] @@ -491,3 +501,33 @@ pub async fn get_templates_by_tag_cli( execute_python_cli_command(app, args).await } + +/// 更新模板片段名称(新版本,使用CLI模式) +#[tauri::command] +pub async fn update_template_segment_cli( + app: AppHandle, + request: TemplateUpdateSegmentRequest, +) -> Result { + let mut args = vec![ + "template".to_string(), + "update-segment".to_string(), + request.template_id, + request.segment_id, + request.new_name, + ]; + + if let Some(user_id) = request.user_id { + args.push("--user-id".to_string()); + args.push(user_id); + } + + if request.verbose.unwrap_or(false) { + args.push("--verbose".to_string()); + } + + if request.json_output.unwrap_or(true) { + args.push("--json".to_string()); + } + + execute_python_cli_command(app, args).await +} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index c510188..48a5a94 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -142,7 +142,8 @@ pub fn run() { commands::template::search_templates_cli, commands::template::get_template_stats_cli, commands::template::get_popular_tags_cli, - commands::template::get_templates_by_tag_cli + commands::template::get_templates_by_tag_cli, + commands::template::update_template_segment_cli ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/src/pages/TemplateDetailPageV2.tsx b/src/pages/TemplateDetailPageV2.tsx index f4cde73..e9c74ec 100644 --- a/src/pages/TemplateDetailPageV2.tsx +++ b/src/pages/TemplateDetailPageV2.tsx @@ -90,24 +90,41 @@ const TemplateDetailPageV2: React.FC = () => { } } - const handleSegmentNameChange = (segmentId: string, newName: string) => { - if (!templateDetail) return + const handleSegmentNameChange = async (segmentId: string, newName: string) => { + if (!templateDetail || !template) return - // 更新本地状态中的片段名称 - const updatedDetail = { - ...templateDetail, - tracks: templateDetail.tracks.map(track => ({ - ...track, - segments: track.segments.map(segment => - segment.id === segmentId ? { ...segment, name: newName } : segment - ) - })) + try { + // 先更新本地状态中的片段名称 + const updatedDetail = { + ...templateDetail, + tracks: templateDetail.tracks.map(track => ({ + ...track, + segments: track.segments.map(segment => + segment.id === segmentId ? { ...segment, name: newName } : segment + ) + })) + } + + setTemplateDetail(updatedDetail) + + // 保存到后端 + const success = await TemplateServiceV2.updateSegmentName( + template.id, + segmentId, + newName + ) + + if (success) { + console.log(`Segment ${segmentId} renamed to: ${newName} - saved to database`) + } else { + console.error('Failed to save segment name change to database') + // 可以选择回滚本地状态或显示错误提示 + } + } catch (error) { + console.error('Error updating segment name:', error) + // 可以选择回滚本地状态或显示错误提示 + alert('保存片段名称失败: ' + (error instanceof Error ? error.message : '未知错误')) } - - setTemplateDetail(updatedDetail) - - // TODO: 保存到后端 - console.log(`Segment ${segmentId} renamed to: ${newName}`) } if (loading) { diff --git a/src/services/TemplateServiceV2.ts b/src/services/TemplateServiceV2.ts index 593e9e6..fdb6a5f 100644 --- a/src/services/TemplateServiceV2.ts +++ b/src/services/TemplateServiceV2.ts @@ -68,6 +68,15 @@ export interface TemplateSearchRequest { json_output?: boolean } +export interface TemplateUpdateSegmentRequest { + template_id: string + segment_id: string + new_name: string + user_id?: string + verbose?: boolean + json_output?: boolean +} + // 批量导入结果 export interface BatchImportResult { imported_count: number @@ -357,9 +366,9 @@ export class TemplateServiceV2 { * 根据标签获取模板 (新功能) */ static async getTemplatesByTag( - tag: string, - includeCloud: boolean = true, - limit: number = 50, + tag: string, + includeCloud: boolean = true, + limit: number = 50, userId?: string ): Promise { try { @@ -370,7 +379,7 @@ export class TemplateServiceV2 { limit: limit, verbose: false }) - + if (!response.success) { throw new Error(response.error || response.message || 'Failed to get templates by tag') } @@ -382,6 +391,38 @@ export class TemplateServiceV2 { } } + /** + * 更新模板片段名称 (新功能) + */ + static async updateSegmentName( + templateId: string, + segmentId: string, + newName: string, + userId?: string + ): Promise { + try { + const request: TemplateUpdateSegmentRequest = { + template_id: templateId, + segment_id: segmentId, + new_name: newName, + user_id: userId || this.getCurrentUserId(), + verbose: false, + json_output: true + } + + const response = await invoke('update_template_segment_cli', { request }) + + if (!response.success) { + throw new Error(response.error || response.message || 'Failed to update segment name') + } + + return response.data?.updated || false + } catch (error) { + console.error('Update segment name failed:', error) + throw error + } + } + /** * 验证模板文件夹结构 */