diff --git a/apps/desktop/src-tauri/src/lib.rs b/apps/desktop/src-tauri/src/lib.rs index c3089f2..4fe7a7e 100644 --- a/apps/desktop/src-tauri/src/lib.rs +++ b/apps/desktop/src-tauri/src/lib.rs @@ -38,6 +38,7 @@ pub fn run() { commands::project_commands::get_default_project_name, commands::system_commands::select_directory, commands::system_commands::select_file, + commands::system_commands::open_file_directory, commands::system_commands::get_app_info, commands::system_commands::validate_directory, commands::system_commands::get_directory_name, diff --git a/apps/desktop/src-tauri/src/presentation/commands/system_commands.rs b/apps/desktop/src-tauri/src/presentation/commands/system_commands.rs index da72945..e173548 100644 --- a/apps/desktop/src-tauri/src/presentation/commands/system_commands.rs +++ b/apps/desktop/src-tauri/src/presentation/commands/system_commands.rs @@ -185,3 +185,63 @@ pub fn select_file(app: AppHandle, filters: Option)>>) Err(_) => Err("文件选择超时".to_string()), } } + +/// 打开文件所在目录命令 +#[command] +pub async fn open_file_directory(file_path: String) -> Result<(), String> { + use std::path::Path; + use std::process::Command; + + let path = Path::new(&file_path); + + // 获取文件所在目录 + let directory = if path.is_file() { + path.parent().ok_or("无法获取文件所在目录")? + } else if path.is_dir() { + path + } else { + return Err("文件路径不存在".to_string()); + }; + + // 根据操作系统打开目录 + let result = if cfg!(target_os = "windows") { + // Windows: 使用 explorer 并选中文件 + if path.is_file() { + Command::new("explorer") + .args(["/select,", &file_path]) + .spawn() + } else { + Command::new("explorer") + .arg(directory) + .spawn() + } + } else if cfg!(target_os = "macos") { + // macOS: 使用 open 命令 + if path.is_file() { + Command::new("open") + .args(["-R", &file_path]) + .spawn() + } else { + Command::new("open") + .arg(directory) + .spawn() + } + } else { + // Linux: 使用 xdg-open + Command::new("xdg-open") + .arg(directory) + .spawn() + }; + + match result { + Ok(_) => { + info!("成功打开目录: {:?}", directory); + Ok(()) + } + Err(e) => { + let error_msg = format!("打开目录失败: {}", e); + tracing::error!("{}", error_msg); + Err(error_msg) + } + } +} diff --git a/apps/desktop/src/components/MaterialSegmentView.tsx b/apps/desktop/src/components/MaterialSegmentView.tsx index c860829..3b73410 100644 --- a/apps/desktop/src/components/MaterialSegmentView.tsx +++ b/apps/desktop/src/components/MaterialSegmentView.tsx @@ -7,7 +7,8 @@ import { RefreshCw, Eye, Edit, - Trash2 + Trash2, + FolderOpen } from 'lucide-react'; import { invoke } from '@tauri-apps/api/core'; import { SearchInput } from './InteractiveInput'; @@ -73,6 +74,25 @@ interface MaterialSegmentView { }; } +// 提取文件名的工具函数 +const extractFileName = (filePath: string): string => { + if (!filePath) return '未知文件'; + + // 处理Windows路径格式,包括长路径前缀 + const cleanPath = filePath.replace(/^\\\\\?\\/, ''); + const parts = cleanPath.split(/[\\\/]/); + return parts[parts.length - 1] || '未知文件'; +}; + +// 打开文件所在目录 +const openFileDirectory = async (filePath: string) => { + try { + await invoke('open_file_directory', { filePath }); + } catch (error) { + console.error('打开目录失败:', error); + } +}; + /** * 素材片段管理组件 - 多条件检索标签页风格 */ @@ -215,9 +235,20 @@ export const MaterialSegmentView: React.FC = ({ projec
-

- {segment.material_name || '未知素材'} -

+
+

+ {extractFileName(segment.segment.file_path)} +

+ {segment.segment.file_path && ( + + )} +

{formatDuration(segment.segment.start_time)} - {formatDuration(segment.segment.end_time)} 时长: {formatDuration(segment.segment.duration)}