diff --git a/apps/desktop/src/components/MaterialCard.tsx b/apps/desktop/src/components/MaterialCard.tsx index ee9cf3a..1bd5ac1 100644 --- a/apps/desktop/src/components/MaterialCard.tsx +++ b/apps/desktop/src/components/MaterialCard.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState } from 'react'; import { FileVideo, FileAudio, FileImage, File, Clock, ExternalLink, ChevronDown, ChevronUp } from 'lucide-react'; import { Material, MaterialSegment } from '../types/material'; import { useMaterialStore } from '../store/materialStore'; @@ -74,9 +74,42 @@ export const MaterialCard: React.FC = ({ material }) => { }; // 打开文件所在文件夹 - const openFileLocation = (filePath: string) => { - // 这里可以调用 Tauri 的 API 来打开文件夹 - console.log('打开文件位置:', filePath); + const openFileLocation = async (filePath: string) => { + try { + const { revealItemInDir } = await import('@tauri-apps/plugin-opener'); + + // 处理 Windows 路径格式,移除 \\?\ 前缀 + let normalizedPath = filePath; + if (normalizedPath.startsWith('\\\\?\\')) { + normalizedPath = normalizedPath.substring(4); + } + + console.log('打开文件位置:', normalizedPath); + await revealItemInDir(normalizedPath); + } catch (error) { + console.error('打开文件位置失败:', error); + + // 如果 revealItemInDir 失败,尝试打开文件所在目录 + try { + const { openPath } = await import('@tauri-apps/plugin-opener'); + + // 获取文件所在目录 + const pathParts = filePath.split(/[/\\]/); + pathParts.pop(); // 移除文件名 + const dirPath = pathParts.join('\\'); + + let normalizedDirPath = dirPath; + if (normalizedDirPath.startsWith('\\\\?\\')) { + normalizedDirPath = normalizedDirPath.substring(4); + } + + console.log('尝试打开目录:', normalizedDirPath); + await openPath(normalizedDirPath); + } catch (fallbackError) { + console.error('备用方法也失败:', fallbackError); + alert('无法打开文件位置,请检查文件是否存在'); + } + } }; return ( diff --git a/apps/desktop/src/pages/ProjectDetails.tsx b/apps/desktop/src/pages/ProjectDetails.tsx index 1ceffe2..e5a0a81 100644 --- a/apps/desktop/src/pages/ProjectDetails.tsx +++ b/apps/desktop/src/pages/ProjectDetails.tsx @@ -1,10 +1,10 @@ import React, { useEffect, useState } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; -import { ArrowLeft, FolderOpen, Calendar, Settings, Upload, FileVideo, Clock, ExternalLink } from 'lucide-react'; +import { ArrowLeft, FolderOpen, Calendar, Settings, Upload } from 'lucide-react'; import { useProjectStore } from '../store/projectStore'; import { useMaterialStore } from '../store/materialStore'; import { Project } from '../types/project'; -import { MaterialImportResult, Material, MaterialSegment } from '../types/material'; +import { MaterialImportResult } from '../types/material'; import { LoadingSpinner } from '../components/LoadingSpinner'; import { ErrorMessage } from '../components/ErrorMessage'; import { MaterialImportDialog } from '../components/MaterialImportDialog'; diff --git a/apps/desktop/src/store/materialStore.ts b/apps/desktop/src/store/materialStore.ts index 6c99175..bfef9d1 100644 --- a/apps/desktop/src/store/materialStore.ts +++ b/apps/desktop/src/store/materialStore.ts @@ -1,12 +1,12 @@ import { create } from 'zustand'; import { invoke } from '@tauri-apps/api/core'; -import { - Material, - MaterialStats, - CreateMaterialRequest, +import { + Material, + MaterialStats, + CreateMaterialRequest, MaterialImportResult, ProcessingStatus, - MaterialProcessingConfig + MaterialSegment } from '../types/material'; /** @@ -35,6 +35,7 @@ interface MaterialState { loadMaterialStats: (projectId: string) => Promise; importMaterials: (request: CreateMaterialRequest) => Promise; getMaterialById: (id: string) => Promise; + getMaterialSegments: (materialId: string) => Promise; deleteMaterial: (id: string) => Promise; processMaterials: (materialIds: string[]) => Promise; updateMaterialStatus: (id: string, status: ProcessingStatus, errorMessage?: string) => Promise;