fix: 修复ProjectDetails.tsx中的无限请求问题和模特名称显示
- 修复loadProjectClassificationStats函数的无限循环问题 - 使用useRef跟踪分类统计加载状态,避免重复请求 - 添加模特信息加载功能,显示真实模特名称而非model_id - 优化useEffect依赖,防止不必要的重新渲染和请求 - 在项目切换和导入完成时正确重置加载状态
This commit is contained in:
parent
08fa4eda61
commit
52ce437e63
|
|
@ -29,7 +29,6 @@ pub async fn get_model_by_id(
|
|||
state: State<'_, AppState>,
|
||||
id: String,
|
||||
) -> Result<Option<Model>, String> {
|
||||
println!("get_model_by_id 命令开始执行,ID: {}", id);
|
||||
|
||||
let repository_guard = state.get_model_repository()
|
||||
.map_err(|e| {
|
||||
|
|
@ -43,14 +42,12 @@ pub async fn get_model_by_id(
|
|||
"模特仓库未初始化".to_string()
|
||||
})?;
|
||||
|
||||
println!("调用 ModelService::get_model_by_id");
|
||||
let result = ModelService::get_model_by_id(repository, &id)
|
||||
.map_err(|e| {
|
||||
println!("ModelService::get_model_by_id 失败: {}", e);
|
||||
e.to_string()
|
||||
});
|
||||
|
||||
println!("get_model_by_id 命令执行完成,结果: {:?}", result.is_ok());
|
||||
result
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useEffect, useState, useCallback, useMemo } from 'react';
|
||||
import React, { useEffect, useState, useCallback, useMemo, useRef } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { ArrowLeft, FolderOpen, Upload, FileVideo, FileAudio, FileImage, HardDrive, Brain, Loader2, Link, Layers, Calendar, MapPin, Users, CheckCircle, Filter } from 'lucide-react';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
|
|
@ -134,6 +134,10 @@ export const ProjectDetails: React.FC = () => {
|
|||
const [materialModelFilter, setMaterialModelFilter] = useState<string>('全部');
|
||||
const [materialUsageFilter, setMaterialUsageFilter] = useState<string>('全部');
|
||||
const [materialClassificationRecords, setMaterialClassificationRecords] = useState<{[materialId: string]: any[]}>({});
|
||||
const [modelsMap, setModelsMap] = useState<{[modelId: string]: any}>({});
|
||||
|
||||
// 用于跟踪分类统计是否已加载的ref
|
||||
const classificationStatsLoadedRef = useRef<string | null>(null);
|
||||
|
||||
// 加载片段统计数据
|
||||
const loadSegmentStats = useCallback(async (projectId: string) => {
|
||||
|
|
@ -155,12 +159,30 @@ export const ProjectDetails: React.FC = () => {
|
|||
}
|
||||
}, []);
|
||||
|
||||
// 加载项目分类统计信息
|
||||
const loadProjectClassificationStats = useCallback(async (projectId: string) => {
|
||||
// 加载所有模特信息
|
||||
const loadAllModels = useCallback(async () => {
|
||||
try {
|
||||
const models = await invoke('get_all_models') as any[];
|
||||
const modelMap: {[modelId: string]: any} = {};
|
||||
models.forEach(model => {
|
||||
modelMap[model.id] = model;
|
||||
});
|
||||
setModelsMap(modelMap);
|
||||
} catch (error) {
|
||||
console.error('Failed to load models:', error);
|
||||
setModelsMap({});
|
||||
}
|
||||
}, []);
|
||||
|
||||
// 加载项目分类统计信息
|
||||
const loadProjectClassificationStats = useCallback(async (projectId: string, materialList?: any[]) => {
|
||||
try {
|
||||
// 使用传入的素材列表或当前的素材列表
|
||||
const materialsToProcess = materialList || materials;
|
||||
|
||||
// 获取每个素材的分类记录
|
||||
const classificationRecords: {[materialId: string]: any[]} = {};
|
||||
for (const material of materials) {
|
||||
for (const material of materialsToProcess) {
|
||||
try {
|
||||
const records = await invoke('get_material_classification_records', { materialId: material.id }) as any[];
|
||||
classificationRecords[material.id] = records;
|
||||
|
|
@ -175,7 +197,7 @@ export const ProjectDetails: React.FC = () => {
|
|||
console.error('Failed to load project classification stats:', error);
|
||||
setMaterialClassificationRecords({});
|
||||
}
|
||||
}, [materials]);
|
||||
}, []);
|
||||
|
||||
// 加载项目详情
|
||||
useEffect(() => {
|
||||
|
|
@ -192,6 +214,9 @@ export const ProjectDetails: React.FC = () => {
|
|||
|
||||
// 加载项目素材
|
||||
if (foundProject) {
|
||||
// 重置分类统计加载状态
|
||||
classificationStatsLoadedRef.current = null;
|
||||
|
||||
loadMaterials(foundProject.id);
|
||||
loadMaterialStats(foundProject.id);
|
||||
// 加载项目的模板绑定
|
||||
|
|
@ -200,18 +225,20 @@ export const ProjectDetails: React.FC = () => {
|
|||
loadSegmentStats(foundProject.id);
|
||||
// 加载素材使用状态概览
|
||||
loadUsageOverview(foundProject.id);
|
||||
// 加载项目分类统计信息
|
||||
loadProjectClassificationStats(foundProject.id);
|
||||
// 加载所有模特信息
|
||||
loadAllModels();
|
||||
// 加载项目分类统计信息将在素材加载完成后执行
|
||||
}
|
||||
}
|
||||
}, [id, projects, loadMaterials, loadMaterialStats, bindingActions.fetchTemplatesByProject, loadSegmentStats, loadUsageOverview, loadProjectClassificationStats]);
|
||||
}, [id, projects, loadMaterials, loadMaterialStats, bindingActions.fetchTemplatesByProject, loadSegmentStats, loadUsageOverview, loadAllModels, loadProjectClassificationStats]);
|
||||
|
||||
// 当素材列表变化时,重新加载分类统计信息
|
||||
// 当素材加载完成后,加载分类统计信息
|
||||
useEffect(() => {
|
||||
if (project && materials.length > 0) {
|
||||
loadProjectClassificationStats(project.id);
|
||||
if (project && materials.length > 0 && classificationStatsLoadedRef.current !== project.id) {
|
||||
classificationStatsLoadedRef.current = project.id;
|
||||
loadProjectClassificationStats(project.id, materials);
|
||||
}
|
||||
}, [materials.length, project, loadProjectClassificationStats]);
|
||||
}, [project?.id, materials.length, loadProjectClassificationStats]);
|
||||
|
||||
// 加载模板列表
|
||||
useEffect(() => {
|
||||
|
|
@ -284,6 +311,8 @@ export const ProjectDetails: React.FC = () => {
|
|||
console.log('导入完成:', result);
|
||||
// 重新加载素材列表
|
||||
if (project) {
|
||||
// 重置分类统计加载状态,以便重新加载
|
||||
classificationStatsLoadedRef.current = null;
|
||||
loadMaterials(project.id);
|
||||
loadMaterialStats(project.id);
|
||||
}
|
||||
|
|
@ -591,7 +620,6 @@ export const ProjectDetails: React.FC = () => {
|
|||
const modelCounts: {[key: string]: number} = {};
|
||||
materials.forEach(material => {
|
||||
if (material.model_id) {
|
||||
// 这里需要根据model_id获取模特名称,暂时使用model_id
|
||||
const modelKey = material.model_id;
|
||||
modelCounts[modelKey] = (modelCounts[modelKey] || 0) + 1;
|
||||
} else {
|
||||
|
|
@ -600,15 +628,26 @@ export const ProjectDetails: React.FC = () => {
|
|||
});
|
||||
|
||||
Object.entries(modelCounts).forEach(([modelKey, count]) => {
|
||||
let label = '未指定';
|
||||
if (modelKey !== '未指定') {
|
||||
// 从modelsMap中获取模特的真实名称
|
||||
const model = modelsMap[modelKey];
|
||||
if (model) {
|
||||
label = model.stage_name || model.name;
|
||||
} else {
|
||||
label = `模特-${modelKey}`;
|
||||
}
|
||||
}
|
||||
|
||||
options.push({
|
||||
label: modelKey === '未指定' ? '未指定' : `模特-${modelKey}`,
|
||||
label,
|
||||
value: modelKey,
|
||||
count
|
||||
});
|
||||
});
|
||||
|
||||
return options;
|
||||
}, [materials]);
|
||||
}, [materials, modelsMap]);
|
||||
|
||||
const materialUsageOptions = useMemo(() => {
|
||||
// 计算使用状态统计
|
||||
|
|
|
|||
Loading…
Reference in New Issue