fix: 实现MaterialCard中的打开文件位置功能

问题分析:
MaterialCard组件中的openFileLocation函数只是打印路径,
没有实际实现打开文件位置的功能,导致点击分片文件无响应。

修复内容:
1. 实现openFileLocation函数:
   - 使用revealItemInDir在文件管理器中显示并选中文件
   - 添加路径标准化处理,移除Windows长路径前缀
   - 提供备用方案:如果revealItemInDir失败,尝试openPath打开目录

2. 错误处理优化:
   - 双重备用机制确保功能可用性
   - 用户友好的错误提示
   - 详细的调试日志

3. TypeScript类型修复:
   - 添加MaterialSegment类型导入到materialStore
   - 在MaterialState接口中添加getMaterialSegments方法定义
   - 清理未使用的导入项

4. 技术实现:
   `	ypescript
   // 主要方法:在文件管理器中显示文件
   await revealItemInDir(normalizedPath);

   // 备用方法:打开文件所在目录
   await openPath(normalizedDirPath);
   `

功能特点:
 点击分片文件的外链图标可以打开文件位置
 自动处理Windows长路径格式
 双重备用机制确保兼容性
 用户友好的错误处理

现在用户可以方便地通过点击分片列表中的外链图标来打开文件位置了!
This commit is contained in:
imeepos 2025-07-13 22:12:15 +08:00
parent ee40fe31cf
commit 4a377be983
3 changed files with 45 additions and 11 deletions

View File

@ -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<MaterialCardProps> = ({ 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 (

View File

@ -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';

View File

@ -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<void>;
importMaterials: (request: CreateMaterialRequest) => Promise<MaterialImportResult>;
getMaterialById: (id: string) => Promise<Material | null>;
getMaterialSegments: (materialId: string) => Promise<MaterialSegment[]>;
deleteMaterial: (id: string) => Promise<void>;
processMaterials: (materialIds: string[]) => Promise<void>;
updateMaterialStatus: (id: string, status: ProcessingStatus, errorMessage?: string) => Promise<void>;