@@ -499,9 +499,28 @@ def start_backend_task(self):
499499 self .logger .warning ("一个任务已经在运行中。" )
500500 return
501501
502+ # 检查文件列表是否为空
502503 files_to_process = self ._resolve_input_files ()
503504 if not files_to_process :
504505 self .logger .warning ("没有找到有效的图片文件,任务中止" )
506+ from PyQt6 .QtWidgets import QMessageBox
507+ QMessageBox .warning (
508+ None ,
509+ "文件列表为空" ,
510+ "请先添加要翻译的图片文件!\n \n 可以通过以下方式添加:\n • 点击「添加文件」按钮\n • 点击「添加文件夹」按钮\n • 直接拖拽文件到文件列表"
511+ )
512+ return
513+
514+ # 检查输出目录是否合法
515+ output_path = self .config_service .get_config ().app .last_output_path
516+ if not output_path or not os .path .isdir (output_path ):
517+ self .logger .warning (f"输出目录不合法: { output_path } " )
518+ from PyQt6 .QtWidgets import QMessageBox
519+ QMessageBox .warning (
520+ None ,
521+ "输出目录不合法" ,
522+ "请先设置有效的输出目录!\n \n 可以通过以下方式设置:\n • 点击「浏览...」按钮选择输出目录\n • 直接在输出目录输入框中输入路径"
523+ )
505524 return
506525
507526 self .saved_files_count = 0
@@ -644,20 +663,40 @@ def stop_task(self) -> bool:
644663 self .state_manager .set_translating (False )
645664 self .state_manager .set_status_message ("正在停止翻译..." )
646665
666+ # 1. 先通知 worker 停止
647667 if self .worker :
648668 self .worker .stop ()
669+
670+ # 2. 请求线程退出
649671 self .thread .quit ()
650672
651673 # 保存线程引用,避免在等待过程中被清空
652674 thread_ref = self .thread
675+ worker_ref = self .worker
653676
654677 # 在后台等待线程停止,不阻塞UI
655678 from PyQt6 .QtCore import QTimer
679+ timeout_counter = [0 ] # 使用列表以便在闭包中修改
680+
656681 def wait_for_thread ():
657682 try :
658683 if thread_ref and not thread_ref .wait (100 ): # 等待100ms
659- # 如果还没停止,继续等待
660- QTimer .singleShot (100 , wait_for_thread )
684+ timeout_counter [0 ] += 100
685+
686+ # 如果超过5秒还没停止,强制终止
687+ if timeout_counter [0 ] >= 5000 :
688+ self .logger .warning ("线程5秒内未停止,强制终止..." )
689+ try :
690+ thread_ref .terminate ()
691+ thread_ref .wait (1000 ) # 等待1秒
692+ self .logger .info ("翻译线程已被强制终止。" )
693+ self .state_manager .set_status_message ("任务已强制停止" )
694+ except Exception as e :
695+ self .logger .error (f"强制终止线程失败: { e } " )
696+ self .state_manager .set_status_message ("停止失败" )
697+ else :
698+ # 继续等待
699+ QTimer .singleShot (100 , wait_for_thread )
661700 else :
662701 # 线程已停止
663702 self .logger .info ("翻译线程已成功停止。" )
@@ -839,9 +878,32 @@ async def _do_processing(self):
839878 'input_folders' : input_folders
840879 }
841880
881+ # 确定翻译流程模式
882+ workflow_mode = "正常翻译流程"
883+ workflow_tip = ""
884+ cli_config = self .config_dict .get ('cli' , {})
885+ if cli_config .get ('generate_and_export' , False ):
886+ workflow_mode = "导出翻译"
887+ workflow_tip = "💡 提示:导出翻译后,可在 manga_translator_work/translations/ 目录查看 图片名_translated.txt 文件"
888+ elif cli_config .get ('template' , False ):
889+ workflow_mode = "导出原文"
890+ workflow_tip = "💡 提示:导出原文后,可在 manga_translator_work/originals/ 目录手动翻译 图片名_original.txt 文件,然后使用「导入翻译并渲染」模式"
891+ elif cli_config .get ('load_text' , False ):
892+ workflow_mode = "导入翻译并渲染"
893+ workflow_tip = "💡 提示:将从 manga_translator_work/originals/ 或 translations/ 目录读取 TXT 文件并渲染(优先使用 _original.txt)"
894+
842895 if is_hq or (len (self .files ) > 1 and batch_size > 1 ):
843896 self .log_received .emit (f"--- [12] THREAD: Starting batch processing ({ 'HQ mode' if is_hq else 'Batch mode' } )..." )
844897
898+ # 输出批量处理信息
899+ total_images = len (self .files )
900+ total_batches = (total_images + batch_size - 1 ) // batch_size if batch_size > 0 else 1
901+ self .log_received .emit (f"📊 批量处理模式:共 { total_images } 张图片,分 { total_batches } 个批次处理" )
902+ self .log_received .emit (f"🔧 翻译流程:{ workflow_mode } " )
903+ self .log_received .emit (f"📁 输出目录:{ self .output_folder } " )
904+ if workflow_tip :
905+ self .log_received .emit (workflow_tip )
906+
845907 images_with_configs = []
846908 for file_path in self .files :
847909 if not self ._is_running : raise asyncio .CancelledError ("Task stopped by user." )
@@ -850,39 +912,62 @@ async def _do_processing(self):
850912 image .name = file_path
851913 images_with_configs .append ((image , config ))
852914
915+ self .log_received .emit (f"🚀 开始翻译..." )
853916 contexts = await translator .translate_batch (images_with_configs , save_info = save_info )
854917
855918 # The backend now handles saving for batch jobs. We just need to collect the paths/status.
919+ success_count = 0
856920 for ctx in contexts :
857921 if not self ._is_running : raise asyncio .CancelledError ("Task stopped by user." )
858922 if ctx :
859923 results .append ({'success' : True , 'original_path' : ctx .image_name , 'image_data' : None })
924+ success_count += 1
860925 else :
861926 results .append ({'success' : False , 'original_path' : 'Unknown' , 'error' : 'Batch translation returned no context' })
862927
863- else :
928+ self .log_received .emit (f"✅ 批量翻译完成:成功 { success_count } /{ total_images } 张" )
929+ self .log_received .emit (f"💾 文件已保存到:{ self .output_folder } " )
930+
931+ else :
864932 self .log_received .emit ("--- [12] THREAD: Starting sequential processing..." )
865933 total_files = len (self .files )
934+
935+ # 输出顺序处理信息
936+ self .log_received .emit (f"📊 顺序处理模式:共 { total_files } 张图片" )
937+ self .log_received .emit (f"🔧 翻译流程:{ workflow_mode } " )
938+ self .log_received .emit (f"📁 输出目录:{ self .output_folder } " )
939+ if workflow_tip :
940+ self .log_received .emit (workflow_tip )
941+
942+ success_count = 0
866943 for i , file_path in enumerate (self .files ):
867944 if not self ._is_running :
868945 raise asyncio .CancelledError ("Task stopped by user." )
869946
947+ current_num = i + 1
870948 self .progress .emit (i , total_files , f"Processing: { os .path .basename (file_path )} " )
871-
949+ self .log_received .emit (f"🔄 [{ current_num } /{ total_files } ] 正在处理:{ os .path .basename (file_path )} " )
950+
872951 try :
873952 image = Image .open (file_path )
874953 image .name = file_path
875-
954+
876955 ctx = await translator .translate (image , config , image_name = image .name )
877-
956+
878957 if ctx and ctx .result :
879958 self .file_processed .emit ({'success' : True , 'original_path' : file_path , 'image_data' : ctx .result })
959+ success_count += 1
960+ self .log_received .emit (f"✅ [{ current_num } /{ total_files } ] 完成:{ os .path .basename (file_path )} " )
880961 else :
881962 self .file_processed .emit ({'success' : False , 'original_path' : file_path , 'error' : 'Translation returned no result or image' })
963+ self .log_received .emit (f"❌ [{ current_num } /{ total_files } ] 失败:{ os .path .basename (file_path )} " )
882964
883965 except Exception as e :
884- self .log_received .emit (f"Error processing file { os .path .basename (file_path )} : { e } " )
966+ self .log_received .emit (f"❌ [ { current_num } / { total_files } ] 错误: { os .path .basename (file_path )} - { e } " )
885967 self .file_processed .emit ({'success' : False , 'original_path' : file_path , 'error' : str (e )})
968+
969+ self .log_received .emit (f"✅ 顺序翻译完成:成功 { success_count } /{ total_files } 张" )
970+ self .log_received .emit (f"💾 文件已保存到:{ self .output_folder } " )
886971
887972 self .finished .emit (results )
888973
0 commit comments