fix: 修复get_model_by_id死锁问题和批量删除模板功能

- 修复ModelService中get_model_by_id使用get_basic_by_id避免数据库死锁
- 解决MaterialCard组件中关联模特一直加载中的问题
- 修复ProjectTemplateBindingList中executeDelete函数的异步处理
- 在get_model_by_id命令中添加详细的调试日志
- 在MaterialCard中添加组件卸载时的状态清理机制
- 在批量删除服务中添加调试日志追踪问题
- 解决页面切换时loading状态不清除的问题
This commit is contained in:
imeepos 2025-07-15 13:49:43 +08:00
parent ba34481052
commit a1ccde6b89
6 changed files with 66 additions and 22 deletions

View File

@ -71,7 +71,9 @@ impl ModelService {
repository: &ModelRepository, repository: &ModelRepository,
id: &str, id: &str,
) -> Result<Option<Model>> { ) -> Result<Option<Model>> {
repository.get_by_id(id) // 使用 get_basic_by_id 避免死锁问题
// 在MaterialCard等组件中只需要基本信息不需要照片
repository.get_basic_by_id(id)
.map_err(|e| anyhow!("获取模特详情失败: {}", e)) .map_err(|e| anyhow!("获取模特详情失败: {}", e))
} }

View File

@ -29,14 +29,29 @@ pub async fn get_model_by_id(
state: State<'_, AppState>, state: State<'_, AppState>,
id: String, id: String,
) -> Result<Option<Model>, String> { ) -> Result<Option<Model>, String> {
let repository_guard = state.get_model_repository() println!("get_model_by_id 命令开始执行ID: {}", id);
.map_err(|e| format!("获取模特仓库失败: {}", e))?;
let repository = repository_guard.as_ref()
.ok_or("模特仓库未初始化")?;
ModelService::get_model_by_id(repository, &id) let repository_guard = state.get_model_repository()
.map_err(|e| e.to_string()) .map_err(|e| {
println!("获取模特仓库失败: {}", e);
format!("获取模特仓库失败: {}", e)
})?;
let repository = repository_guard.as_ref()
.ok_or_else(|| {
println!("模特仓库未初始化");
"模特仓库未初始化".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
} }
/// 获取所有模特命令 /// 获取所有模特命令

View File

@ -108,25 +108,44 @@ export const MaterialCard: React.FC<MaterialCardProps> = ({ material, onEdit, on
// 获取关联的模特信息 // 获取关联的模特信息
useEffect(() => { useEffect(() => {
let isMounted = true; // 用于防止组件卸载后设置状态
const fetchAssociatedModel = async () => { const fetchAssociatedModel = async () => {
if (!material.model_id) { if (!material.model_id) {
setAssociatedModel(null); if (isMounted) {
setAssociatedModel(null);
setLoadingModel(false);
}
return; return;
} }
setLoadingModel(true); if (isMounted) {
setLoadingModel(true);
}
try { try {
const model = await invoke<Model>('get_model_by_id', { id: material.model_id }); const model = await invoke<Model>('get_model_by_id', { id: material.model_id });
setAssociatedModel(model); if (isMounted) {
setAssociatedModel(model);
}
} catch (error) { } catch (error) {
console.error('获取关联模特失败:', error); console.error('获取关联模特失败:', error);
setAssociatedModel(null); if (isMounted) {
setAssociatedModel(null);
}
} finally { } finally {
setLoadingModel(false); if (isMounted) {
setLoadingModel(false);
}
} }
}; };
fetchAssociatedModel(); fetchAssociatedModel();
// 清理函数
return () => {
isMounted = false;
};
}, [material.model_id]); }, [material.model_id]);
// 加载切分片段 // 加载切分片段

View File

@ -116,16 +116,17 @@ export const ProjectTemplateBindingList: React.FC<ProjectTemplateBindingListProp
}; };
// 执行删除 // 执行删除
const executeDelete = () => { const executeDelete = async () => {
try { try {
if (deleteConfirm.isBatch && onBatchDelete) { if (deleteConfirm.isBatch && onBatchDelete) {
onBatchDelete(selectedIds); await onBatchDelete(selectedIds);
success('批量删除成功', `已删除 ${selectedIds.length} 个绑定`); success('批量删除成功', `已删除 ${selectedIds.length} 个绑定`);
} else if (deleteConfirm.id && onDelete) { } else if (deleteConfirm.id && onDelete) {
onDelete(deleteConfirm.id); await onDelete(deleteConfirm.id);
success('删除成功', `绑定"${deleteConfirm.name}"已删除`); success('删除成功', `绑定"${deleteConfirm.name}"已删除`);
} }
} catch (err) { } catch (err) {
console.error('删除操作失败:', err);
error('删除失败', err instanceof Error ? err.message : '未知错误'); error('删除失败', err instanceof Error ? err.message : '未知错误');
} finally { } finally {
setDeleteConfirm({ isOpen: false }); setDeleteConfirm({ isOpen: false });

View File

@ -131,7 +131,10 @@ export class ProjectTemplateBindingService {
*/ */
static async batchDeleteBindings(request: BatchDeleteProjectTemplateBindingRequest): Promise<number> { static async batchDeleteBindings(request: BatchDeleteProjectTemplateBindingRequest): Promise<number> {
try { try {
return await invoke('batch_delete_project_template_bindings', { request }); console.log('Service: 发送批量删除请求:', request);
const result = await invoke<number>('batch_delete_project_template_bindings', { request });
console.log('Service: 批量删除响应:', result);
return result;
} catch (error) { } catch (error) {
console.error('批量删除项目-模板绑定失败:', error); console.error('批量删除项目-模板绑定失败:', error);
throw new Error(`批量删除绑定失败: ${error}`); throw new Error(`批量删除绑定失败: ${error}`);

View File

@ -235,20 +235,24 @@ export const useProjectTemplateBindingStore = create<ProjectTemplateBindingState
// 批量删除绑定 // 批量删除绑定
batchDeleteBindings: async (ids: string[]) => { batchDeleteBindings: async (ids: string[]) => {
console.log('Store: 开始批量删除绑定, IDs:', ids);
set({ loading: true, error: null }); set({ loading: true, error: null });
try { try {
await ProjectTemplateBindingService.batchDeleteBindings({ binding_ids: ids }); const deletedCount = await ProjectTemplateBindingService.batchDeleteBindings({ binding_ids: ids });
console.log('Store: 批量删除成功, 删除数量:', deletedCount);
const currentBindings = get().bindings; const currentBindings = get().bindings;
set({ set({
bindings: currentBindings.filter(binding => !ids.includes(binding.id)), bindings: currentBindings.filter(binding => !ids.includes(binding.id)),
selectedBindingIds: [], selectedBindingIds: [],
loading: false loading: false
}); });
} catch (error) { } catch (error) {
set({ console.error('Store: 批量删除失败:', error);
set({
error: error instanceof Error ? error.message : '批量删除绑定失败', error: error instanceof Error ? error.message : '批量删除绑定失败',
loading: false loading: false
}); });
throw error; // 重新抛出错误以便上层处理
} }
}, },