feat: 百度通用文字识别提取供应商/日期(config api_key 持久化)
This commit is contained in:
@@ -295,6 +295,104 @@ def batch_ocr_with_status(log_widget, status_bar):
|
||||
thread.start()
|
||||
|
||||
|
||||
def batch_process_all_inputs(log_widget, status_bar):
|
||||
"""一键处理 data/input/ 下全部图片:每张独立 OCR + 采购单,默认不合并。"""
|
||||
if get_running_task() is not None:
|
||||
messagebox.showinfo("任务进行中", "请等待当前任务完成后再执行新的操作。")
|
||||
return
|
||||
|
||||
def run_in_thread():
|
||||
set_running_task("batch_all_inputs")
|
||||
try:
|
||||
if status_bar:
|
||||
status_bar.set_running(True)
|
||||
reporter = ProgressReporter(status_bar)
|
||||
reporter.running()
|
||||
reporter.set("正在扫描待处理图片...", 0)
|
||||
add_to_log(log_widget, "\n========== 一键处理全部图片 ==========\n", "info")
|
||||
|
||||
init_gui_logger(log_widget)
|
||||
|
||||
from ..services.batch_service import BatchService
|
||||
from ..config.settings import ConfigManager
|
||||
from .memory_editor import show_memory_editor # noqa: F401 触发 import 顺序
|
||||
cfg = ConfigManager()
|
||||
|
||||
svc = BatchService(cfg)
|
||||
|
||||
def progress(done, total, entry):
|
||||
pct = int(done / total * 100) if total else 100
|
||||
name = os.path.basename(entry.get('image', ''))
|
||||
reporter.set(f"处理中 {done}/{total}: {name}", pct)
|
||||
if entry.get('status') == 'success':
|
||||
add_to_log(
|
||||
log_widget,
|
||||
f" ✓ {name} → 供应商={entry.get('supplier') or '?'} "
|
||||
f"日期={entry.get('bill_date') or '?'} "
|
||||
f"金额={entry.get('total_amount', 0):.2f}\n",
|
||||
"success"
|
||||
)
|
||||
else:
|
||||
add_to_log(
|
||||
log_widget,
|
||||
f" ✗ {name}: {entry.get('error') or '未知错误'}\n",
|
||||
"error"
|
||||
)
|
||||
|
||||
summary = svc.process_all_inputs(progress_cb=progress)
|
||||
|
||||
add_to_log(log_widget, "\n========== 处理汇总 ==========\n", "info")
|
||||
add_to_log(
|
||||
log_widget,
|
||||
f"共 {summary['total']} 张 | 成功 {summary['success']} | 失败 {summary['failed']}\n",
|
||||
"info"
|
||||
)
|
||||
for r in summary['results']:
|
||||
line = (
|
||||
f" · {os.path.basename(r['image'])}\n"
|
||||
f" hash={r['hash'][:8]}... status={r['status']}\n"
|
||||
f" 供应商={r.get('supplier') or '未知'} "
|
||||
f"日期={r.get('bill_date') or '未知'} "
|
||||
f"金额={r.get('total_amount', 0):.2f}\n"
|
||||
)
|
||||
if r['status'] == 'success' and r.get('result_file'):
|
||||
line += f" result: {os.path.basename(r['result_file'])}\n"
|
||||
else:
|
||||
line += f" error: {r.get('error') or '-'}\n"
|
||||
add_to_log(log_widget, line,
|
||||
"success" if r['status'] == 'success' else "error")
|
||||
|
||||
failed = [r for r in summary['results'] if r['status'] != 'success']
|
||||
if failed:
|
||||
names = "\n".join(os.path.basename(r['image']) for r in failed)
|
||||
messagebox.showwarning(
|
||||
"处理完成(含失败)",
|
||||
f"共 {summary['total']} 张,成功 {summary['success']},失败 {summary['failed']}\n\n"
|
||||
f"失败清单:\n{names}"
|
||||
)
|
||||
elif summary['total'] == 0:
|
||||
messagebox.showinfo("无待处理图片", "data/input/ 目录下没有待处理的图片。")
|
||||
else:
|
||||
messagebox.showinfo(
|
||||
"处理完成",
|
||||
f"共 {summary['total']} 张,全部处理成功。\n请查看 data/result/ 目录。"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"一键处理失败: {e}", exc_info=True)
|
||||
add_to_log(log_widget, f"一键处理异常: {e}\n", "error")
|
||||
finally:
|
||||
dispose_gui_logger()
|
||||
reporter.done()
|
||||
if status_bar:
|
||||
status_bar.set_running(False)
|
||||
status_bar.set_status("就绪")
|
||||
set_running_task(None)
|
||||
|
||||
thread = Thread(target=run_in_thread)
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
|
||||
def batch_process_orders_with_status(log_widget, status_bar):
|
||||
"""批量处理订单(仅Excel处理,包含合并确认)"""
|
||||
def run_in_thread():
|
||||
|
||||
@@ -26,7 +26,7 @@ from .action_handlers import (
|
||||
process_single_image_with_status, run_pipeline_directly,
|
||||
batch_ocr_with_status, batch_process_orders_with_status,
|
||||
merge_orders_with_status, process_excel_file_with_status,
|
||||
process_dropped_file,
|
||||
process_dropped_file, batch_process_all_inputs,
|
||||
)
|
||||
from .memory_editor import show_memory_editor
|
||||
from .config_dialog import show_config_dialog
|
||||
@@ -101,6 +101,7 @@ def _create_left_panel(content_frame, theme, log_text, status_bar):
|
||||
pipeline_frame = tk.Frame(pipeline_section, bg=theme["card_bg"])
|
||||
pipeline_frame.pack(fill=tk.X, padx=8, pady=6)
|
||||
create_modern_button(pipeline_frame, "一键处理", lambda: run_pipeline_directly(log_text, status_bar), "primary", px_width=150, px_height=32).pack(anchor='w', pady=3)
|
||||
create_modern_button(pipeline_frame, "一键处理全部图片", lambda: batch_process_all_inputs(log_text, status_bar), "primary", px_width=180, px_height=32).pack(anchor='w', pady=3)
|
||||
|
||||
# OCR处理区
|
||||
core_section = tk.LabelFrame(
|
||||
|
||||
Reference in New Issue
Block a user