6f96bf50ac
当从外部目录(如D:\ccc)拖入文件时,输出文件会错误地写入源目录。 根因是所有路径使用相对路径 + os.getcwd() 解析,CWD不同则路径错误。 修复方案: - ConfigManager.get_path() 改为使用 app_root (exe所在目录/脚本所在目录) - 将 22 处裸硬编码 "data/result"/"data/output" 替换为 config.get_path() - 添加 result_folder 到默认配置和 config.ini - 修复 error_utils.py 中的路径匹配字符串 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
378 lines
18 KiB
Python
378 lines
18 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
"""处理结果预览对话框模块"""
|
|
|
|
import os
|
|
import re
|
|
import datetime
|
|
import tkinter as tk
|
|
from tkinter import messagebox, scrolledtext
|
|
|
|
from .theme import THEMES, get_theme_mode, apply_theme
|
|
from .ui_widgets import center_window
|
|
from app.core.utils.file_utils import format_file_size
|
|
from app.config.settings import ConfigManager
|
|
|
|
TOBACCO_PREVIEW_WINDOW = None
|
|
|
|
|
|
def _get_output_dir():
|
|
"""获取输出目录的绝对路径"""
|
|
return ConfigManager().get_path('Paths', 'output_folder', fallback='data/output', create=True)
|
|
|
|
|
|
def show_result_preview(command, output):
|
|
"""显示处理结果预览"""
|
|
if "ocr" in command:
|
|
show_ocr_result_preview(output)
|
|
elif "excel" in command:
|
|
show_excel_result_preview(output)
|
|
elif "merge" in command:
|
|
show_merge_result_preview(output)
|
|
elif "pipeline" in command:
|
|
show_pipeline_result_preview(output)
|
|
else:
|
|
messagebox.showinfo("处理完成", f"操作已成功完成!\n请在{_get_output_dir()}目录查看结果。")
|
|
|
|
|
|
def show_ocr_result_preview(output):
|
|
"""显示OCR处理结果预览"""
|
|
files_match = re.search(r'找到 (\d+) 个图片文件,其中 (\d+) 个未处理', output)
|
|
processed_match = re.search(r'所有图片处理完成, 总计: (\d+), 成功: (\d+)', output)
|
|
|
|
if processed_match:
|
|
total = int(processed_match.group(1))
|
|
success = int(processed_match.group(2))
|
|
|
|
preview = tk.Toplevel()
|
|
preview.title("OCR处理结果")
|
|
preview.geometry("400x300")
|
|
preview.resizable(False, False)
|
|
center_window(preview)
|
|
|
|
tk.Label(preview, text="OCR处理完成", font=("Arial", 16, "bold")).pack(pady=10)
|
|
|
|
result_frame = tk.Frame(preview)
|
|
result_frame.pack(pady=10, fill=tk.BOTH, expand=True)
|
|
|
|
tk.Label(result_frame, text=f"总共处理: {total} 个文件", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
|
|
tk.Label(result_frame, text=f"成功处理: {success} 个文件", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
|
|
tk.Label(result_frame, text=f"失败数量: {total - success} 个文件", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
|
|
|
|
if success == total:
|
|
result_text = "全部处理成功!"
|
|
result_color = "#28a745"
|
|
elif success > total * 0.8:
|
|
result_text = "大部分处理成功。"
|
|
result_color = "#ffc107"
|
|
else:
|
|
result_text = "处理失败较多,请检查日志。"
|
|
result_color = "#dc3545"
|
|
|
|
tk.Label(result_frame, text=result_text, font=("Arial", 12, "bold"), fg=result_color).pack(pady=10)
|
|
|
|
button_frame = tk.Frame(preview)
|
|
button_frame.pack(pady=10)
|
|
|
|
tk.Button(button_frame, text="查看输出文件", command=lambda: os.startfile(_get_output_dir())).pack(side=tk.LEFT, padx=10)
|
|
tk.Button(button_frame, text="关闭", command=preview.destroy).pack(side=tk.LEFT, padx=10)
|
|
else:
|
|
messagebox.showinfo("OCR处理完成", f"OCR处理已完成,请在{_get_output_dir()}目录查看结果。")
|
|
|
|
|
|
def show_excel_result_preview(output):
|
|
"""显示Excel处理结果预览"""
|
|
extract_match = re.search(r'提取到 (\d+) 个商品信息', output)
|
|
file_match = re.search(r'采购单已保存到: (.+?)(?:\n|$)', output)
|
|
|
|
if extract_match and file_match:
|
|
products_count = int(extract_match.group(1))
|
|
output_file = file_match.group(1)
|
|
|
|
preview = tk.Toplevel()
|
|
preview.title("Excel处理结果")
|
|
preview.geometry("450x320")
|
|
preview.resizable(False, False)
|
|
center_window(preview)
|
|
|
|
tk.Label(preview, text="Excel处理完成", font=("Arial", 16, "bold")).pack(pady=10)
|
|
|
|
result_frame = tk.Frame(preview)
|
|
result_frame.pack(pady=10, fill=tk.BOTH, expand=True)
|
|
|
|
tk.Label(result_frame, text=f"提取商品数量: {products_count} 个", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
|
|
tk.Label(result_frame, text=f"输出文件: {os.path.basename(output_file)}", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
|
|
|
|
tk.Label(result_frame, text="采购单已成功生成!", font=("Arial", 12, "bold"), fg="#28a745").pack(pady=10)
|
|
|
|
file_frame = tk.Frame(result_frame, relief=tk.GROOVE, borderwidth=1)
|
|
file_frame.pack(fill=tk.X, padx=15, pady=5)
|
|
|
|
tk.Label(file_frame, text="文件信息", font=("Arial", 10, "bold")).pack(anchor=tk.W, padx=10, pady=5)
|
|
|
|
try:
|
|
file_size = os.path.getsize(output_file)
|
|
file_time = datetime.datetime.fromtimestamp(os.path.getmtime(output_file))
|
|
size_text = format_file_size(file_size)
|
|
tk.Label(file_frame, text=f"文件大小: {size_text}", font=("Arial", 10)).pack(anchor=tk.W, padx=10, pady=2)
|
|
tk.Label(file_frame, text=f"创建时间: {file_time.strftime('%Y-%m-%d %H:%M:%S')}", font=("Arial", 10)).pack(anchor=tk.W, padx=10, pady=2)
|
|
except Exception:
|
|
tk.Label(file_frame, text="无法获取文件信息", font=("Arial", 10)).pack(anchor=tk.W, padx=10, pady=2)
|
|
|
|
button_frame = tk.Frame(preview)
|
|
button_frame.pack(pady=10)
|
|
|
|
tk.Button(button_frame, text="打开文件", command=lambda: os.startfile(output_file)).pack(side=tk.LEFT, padx=5)
|
|
tk.Button(button_frame, text="打开所在文件夹", command=lambda: os.startfile(os.path.dirname(output_file))).pack(side=tk.LEFT, padx=5)
|
|
tk.Button(button_frame, text="关闭", command=preview.destroy).pack(side=tk.LEFT, padx=5)
|
|
else:
|
|
messagebox.showinfo("Excel处理完成", f"Excel处理已完成,请在{_get_output_dir()}目录查看结果。")
|
|
|
|
|
|
def show_merge_result_preview(output):
|
|
"""显示合并结果预览"""
|
|
merged_match = re.search(r'合并了 (\d+) 个采购单', output)
|
|
product_match = re.search(r'共处理 (\d+) 个商品', output)
|
|
output_match = re.search(r'已保存到: (.+?)(?:\n|$)', output)
|
|
|
|
if merged_match and output_match:
|
|
merged_count = int(merged_match.group(1))
|
|
product_count = int(product_match.group(1)) if product_match else 0
|
|
output_file = output_match.group(1)
|
|
|
|
preview = tk.Toplevel()
|
|
preview.title("采购单合并结果")
|
|
preview.geometry("450x300")
|
|
preview.resizable(False, False)
|
|
apply_theme(preview)
|
|
|
|
tk.Label(preview, text="采购单合并完成", font=("Arial", 16, "bold")).pack(pady=10)
|
|
|
|
result_frame = tk.Frame(preview)
|
|
result_frame.pack(pady=10, fill=tk.BOTH, expand=True)
|
|
|
|
tk.Label(result_frame, text=f"合并采购单数量: {merged_count} 个", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
|
|
tk.Label(result_frame, text=f"处理商品数量: {product_count} 个", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
|
|
tk.Label(result_frame, text=f"输出文件: {os.path.basename(output_file)}", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
|
|
|
|
theme = THEMES[get_theme_mode()]
|
|
tk.Label(result_frame, text="采购单已成功合并!", font=("Arial", 12, "bold"), fg=theme["success"]).pack(pady=10)
|
|
|
|
button_frame = tk.Frame(preview)
|
|
button_frame.pack(pady=10)
|
|
|
|
tk.Button(button_frame, text="打开文件", command=lambda: os.startfile(output_file)).pack(side=tk.LEFT, padx=10)
|
|
tk.Button(button_frame, text="打开所在文件夹", command=lambda: os.startfile(os.path.dirname(output_file))).pack(side=tk.LEFT, padx=10)
|
|
tk.Button(button_frame, text="关闭", command=preview.destroy).pack(side=tk.LEFT, padx=10)
|
|
else:
|
|
messagebox.showinfo("采购单合并完成", f"采购单合并已完成,请在{_get_output_dir()}目录查看结果。")
|
|
|
|
|
|
def show_pipeline_result_preview(output):
|
|
"""显示完整流程结果预览"""
|
|
ocr_match = re.search(r'所有图片处理完成, 总计: (\d+), 成功: (\d+)', output)
|
|
excel_match = re.search(r'提取到 (\d+) 个商品信息', output)
|
|
output_file_match = re.search(r'采购单已保存到: (.+?)(?:\n|$)', output)
|
|
|
|
preview = tk.Toplevel()
|
|
preview.title("完整流程处理结果")
|
|
preview.geometry("500x400")
|
|
preview.resizable(False, False)
|
|
center_window(preview)
|
|
|
|
tk.Label(preview, text="完整处理流程已完成", font=("Arial", 16, "bold")).pack(pady=10)
|
|
|
|
no_files_match = re.search(r'未找到可合并的文件', output)
|
|
if no_files_match:
|
|
tk.Label(preview, text="未找到可合并的文件,但其他步骤已成功执行", font=("Arial", 12)).pack(pady=0)
|
|
|
|
result_frame = tk.Frame(preview)
|
|
result_frame.pack(pady=10, fill=tk.BOTH, expand=True)
|
|
|
|
result_text = scrolledtext.ScrolledText(result_frame, wrap=tk.WORD, height=15, width=60)
|
|
result_text.pack(fill=tk.BOTH, expand=True, padx=15, pady=5)
|
|
result_text.configure(state=tk.NORMAL)
|
|
|
|
result_text.insert(tk.END, "===== 流程执行结果 =====\n\n", "title")
|
|
|
|
result_text.insert(tk.END, "步骤1: OCR识别\n", "step")
|
|
if ocr_match:
|
|
total = int(ocr_match.group(1))
|
|
success = int(ocr_match.group(2))
|
|
result_text.insert(tk.END, f" 处理图片: {total} 个\n", "info")
|
|
result_text.insert(tk.END, f" 成功识别: {success} 个\n", "info")
|
|
if success == total:
|
|
result_text.insert(tk.END, " 结果: 全部识别成功\n", "success")
|
|
else:
|
|
result_text.insert(tk.END, f" 结果: 部分识别成功 ({success}/{total})\n", "warning")
|
|
else:
|
|
result_text.insert(tk.END, " 结果: 无OCR处理或处理信息不完整\n", "warning")
|
|
|
|
result_text.insert(tk.END, "\n步骤2: Excel处理\n", "step")
|
|
if excel_match:
|
|
products = int(excel_match.group(1))
|
|
result_text.insert(tk.END, f" 提取商品: {products} 个\n", "info")
|
|
result_text.insert(tk.END, " 结果: 成功生成采购单\n", "success")
|
|
if output_file_match:
|
|
output_file = output_file_match.group(1)
|
|
result_text.insert(tk.END, f" 输出文件: {os.path.basename(output_file)}\n", "info")
|
|
else:
|
|
result_text.insert(tk.END, " 结果: 无Excel处理或处理信息不完整\n", "warning")
|
|
|
|
result_text.insert(tk.END, "\n===== 整体评估 =====\n", "title")
|
|
|
|
has_errors = "错误" in output or "失败" in output
|
|
|
|
no_files_match2 = re.search(r'未找到采购单文件', output)
|
|
single_file_match = re.search(r'只有1个采购单文件', output)
|
|
|
|
if no_files_match2:
|
|
result_text.insert(tk.END, "没有找到可合并的文件,但处理流程已成功完成。\n", "warning")
|
|
result_text.insert(tk.END, "可以选择打开Excel文件或查看输出文件夹。\n", "info")
|
|
elif single_file_match:
|
|
result_text.insert(tk.END, "只有一个采购单文件,无需合并,处理流程已成功完成。\n", "warning")
|
|
result_text.insert(tk.END, "可以选择打开生成的Excel文件。\n", "info")
|
|
elif ocr_match and excel_match and not has_errors:
|
|
result_text.insert(tk.END, "流程完整执行成功!\n", "success")
|
|
elif ocr_match or excel_match:
|
|
result_text.insert(tk.END, "流程部分执行成功,请检查日志获取详情。\n", "warning")
|
|
else:
|
|
result_text.insert(tk.END, "流程执行可能存在问题,请查看详细日志。\n", "error")
|
|
|
|
result_text.tag_configure("title", font=("Arial", 12, "bold"))
|
|
result_text.tag_configure("step", font=("Arial", 11, "bold"))
|
|
result_text.tag_configure("info", font=("Arial", 10))
|
|
result_text.tag_configure("success", font=("Arial", 10, "bold"), foreground="#28a745")
|
|
result_text.tag_configure("warning", font=("Arial", 10, "bold"), foreground="#ffc107")
|
|
result_text.tag_configure("error", font=("Arial", 10, "bold"), foreground="#dc3545")
|
|
|
|
result_text.configure(state=tk.DISABLED)
|
|
|
|
button_frame = tk.Frame(preview)
|
|
button_frame.pack(pady=10)
|
|
|
|
if output_file_match:
|
|
output_file = output_file_match.group(1)
|
|
tk.Button(button_frame, text="打开Excel文件", command=lambda: os.startfile(output_file)).pack(side=tk.LEFT, padx=10)
|
|
else:
|
|
if excel_match or no_files_match or single_file_match:
|
|
output_dir = _get_output_dir()
|
|
excel_files = [f for f in os.listdir(output_dir) if f.startswith('采购单_') and (f.endswith('.xls') or f.endswith('.xlsx'))]
|
|
if excel_files:
|
|
excel_files.sort(key=lambda x: os.path.getmtime(os.path.join(output_dir, x)), reverse=True)
|
|
latest_file = os.path.join(output_dir, excel_files[0])
|
|
tk.Button(button_frame, text="打开最新Excel文件",
|
|
command=lambda: os.startfile(latest_file)).pack(side=tk.LEFT, padx=10)
|
|
|
|
tk.Button(button_frame, text="查看输出文件夹", command=lambda: os.startfile(_get_output_dir())).pack(side=tk.LEFT, padx=10)
|
|
tk.Button(button_frame, text="关闭", command=preview.destroy).pack(side=tk.LEFT, padx=10)
|
|
|
|
|
|
def show_tobacco_result_preview(returncode, output):
|
|
"""显示烟草订单处理结果预览"""
|
|
global TOBACCO_PREVIEW_WINDOW
|
|
if returncode != 0:
|
|
return
|
|
|
|
try:
|
|
try:
|
|
if TOBACCO_PREVIEW_WINDOW and TOBACCO_PREVIEW_WINDOW.winfo_exists():
|
|
TOBACCO_PREVIEW_WINDOW.lift()
|
|
return
|
|
except Exception:
|
|
TOBACCO_PREVIEW_WINDOW = None
|
|
|
|
result_file = None
|
|
order_time = "(未知)"
|
|
total_amount = "(未知)"
|
|
items_count = 0
|
|
|
|
abs_path_match = re.search(r'烟草订单处理完成,绝对路径: (.+)(?:\n|$)', output)
|
|
if abs_path_match:
|
|
result_file = abs_path_match.group(1).strip()
|
|
|
|
for line in output.split('\n'):
|
|
if "烟草公司订单处理成功" in line and "订单时间" in line:
|
|
time_match = re.search(r'订单时间: ([^,]+)', line)
|
|
amount_match = re.search(r'总金额: ([^,]+)', line)
|
|
items_match = re.search(r'处理条目: (\d+)', line)
|
|
|
|
if time_match:
|
|
order_time = time_match.group(1).strip()
|
|
if amount_match:
|
|
total_amount = amount_match.group(1).strip()
|
|
if items_match:
|
|
items_count = int(items_match.group(1).strip())
|
|
|
|
if not result_file or not os.path.exists(result_file):
|
|
default_path = os.path.join(_get_output_dir(), "银豹采购单_烟草公司.xls")
|
|
if os.path.exists(default_path):
|
|
result_file = default_path
|
|
|
|
preview = tk.Toplevel()
|
|
preview.title("烟草订单处理结果")
|
|
preview.geometry("450x320")
|
|
preview.resizable(False, False)
|
|
TOBACCO_PREVIEW_WINDOW = preview
|
|
|
|
def _close_preview():
|
|
global TOBACCO_PREVIEW_WINDOW
|
|
TOBACCO_PREVIEW_WINDOW = None
|
|
try:
|
|
preview.destroy()
|
|
except Exception:
|
|
pass
|
|
|
|
preview.protocol("WM_DELETE_WINDOW", _close_preview)
|
|
center_window(preview)
|
|
|
|
tk.Label(preview, text="烟草订单处理完成", font=("Arial", 16, "bold")).pack(pady=10)
|
|
|
|
result_frame = tk.Frame(preview)
|
|
result_frame.pack(pady=10, fill=tk.BOTH, expand=True)
|
|
|
|
tk.Label(result_frame, text=f"订单时间: {order_time}", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
|
|
tk.Label(result_frame, text=f"订单总金额: {total_amount}", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
|
|
tk.Label(result_frame, text=f"处理商品数量: {items_count} 个", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
|
|
|
|
if result_file and os.path.exists(result_file):
|
|
tk.Label(result_frame, text=f"输出文件: {os.path.basename(result_file)}", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
|
|
tk.Label(result_frame, text="银豹采购单已成功生成!", font=("Arial", 12, "bold"), fg="#28a745").pack(pady=10)
|
|
|
|
file_frame = tk.Frame(result_frame, relief=tk.GROOVE, borderwidth=1)
|
|
file_frame.pack(fill=tk.X, padx=15, pady=5)
|
|
tk.Label(file_frame, text="文件信息", font=("Arial", 10, "bold")).pack(anchor=tk.W, padx=10, pady=5)
|
|
|
|
try:
|
|
file_size = os.path.getsize(result_file)
|
|
file_time = datetime.datetime.fromtimestamp(os.path.getmtime(result_file))
|
|
size_text = format_file_size(file_size)
|
|
tk.Label(file_frame, text=f"文件大小: {size_text}", font=("Arial", 10)).pack(anchor=tk.W, padx=10, pady=2)
|
|
tk.Label(file_frame, text=f"创建时间: {file_time.strftime('%Y-%m-%d %H:%M:%S')}", font=("Arial", 10)).pack(anchor=tk.W, padx=10, pady=2)
|
|
except Exception:
|
|
tk.Label(file_frame, text="无法获取文件信息", font=("Arial", 10)).pack(anchor=tk.W, padx=10, pady=2)
|
|
|
|
button_frame = tk.Frame(preview)
|
|
button_frame.pack(pady=10)
|
|
tk.Button(button_frame, text="打开文件", command=lambda: os.startfile(result_file)).pack(side=tk.LEFT, padx=5)
|
|
tk.Button(button_frame, text="打开所在文件夹", command=lambda: os.startfile(os.path.dirname(result_file))).pack(side=tk.LEFT, padx=5)
|
|
tk.Button(button_frame, text="关闭", command=_close_preview).pack(side=tk.LEFT, padx=5)
|
|
else:
|
|
tk.Label(result_frame, text="未找到输出文件", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
|
|
tk.Label(result_frame, text=f"请检查{_get_output_dir()}目录", font=("Arial", 12, "bold"), fg="#dc3545").pack(pady=10)
|
|
|
|
button_frame = tk.Frame(preview)
|
|
button_frame.pack(pady=10)
|
|
tk.Button(button_frame, text="打开输出目录", command=lambda: os.startfile(_get_output_dir())).pack(side=tk.LEFT, padx=5)
|
|
tk.Button(button_frame, text="关闭", command=_close_preview).pack(side=tk.LEFT, padx=5)
|
|
|
|
preview.lift()
|
|
preview.attributes('-topmost', True)
|
|
preview.after_idle(lambda: preview.attributes('-topmost', False))
|
|
|
|
except Exception as e:
|
|
messagebox.showerror(
|
|
"处理异常",
|
|
f"显示预览时发生错误: {e}\n请检查日志了解详细信息。"
|
|
)
|