""" 复用确认对话框 显示任务差异并让用户确认是否复用 """ import tkinter as tk from tkinter import ttk from typing import List, Callable, Optional from history.task_features import TaskDifference def show_reuse_confirm_dialog( parent: tk.Tk, task_summary: str, timestamp: str, similarity_score: float, differences: List[TaskDifference], on_confirm: Callable, on_reject: Callable ): """ 显示复用确认对话框 Args: parent: 父窗口 task_summary: 任务摘要 timestamp: 任务时间 similarity_score: 相似度分数 differences: 差异列表 on_confirm: 确认回调 on_reject: 拒绝回调 """ dialog = tk.Toplevel(parent) dialog.title("发现相似任务") dialog.geometry("700x600") dialog.resizable(False, False) dialog.configure(bg='#2b2b2b') # 居中显示 dialog.transient(parent) dialog.grab_set() # 主容器 main_frame = tk.Frame(dialog, bg='#2b2b2b') main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20) # 标题 title_label = tk.Label( main_frame, text="🔍 发现相似的成功任务", font=('Microsoft YaHei UI', 14, 'bold'), bg='#2b2b2b', fg='#ffffff' ) title_label.pack(pady=(0, 15)) # 任务信息框 info_frame = tk.Frame(main_frame, bg='#3c3c3c', relief=tk.FLAT, bd=0) info_frame.pack(fill=tk.X, pady=(0, 15)) # 任务摘要 task_label = tk.Label( info_frame, text=f"任务: {task_summary}", font=('Microsoft YaHei UI', 10), bg='#3c3c3c', fg='#e0e0e0', anchor='w', justify='left' ) task_label.pack(fill=tk.X, padx=15, pady=(10, 5)) # 时间 time_label = tk.Label( info_frame, text=f"时间: {timestamp}", font=('Microsoft YaHei UI', 9), bg='#3c3c3c', fg='#a0a0a0', anchor='w' ) time_label.pack(fill=tk.X, padx=15, pady=(0, 5)) # 相似度 similarity_percent = int(similarity_score * 100) similarity_color = '#4caf50' if similarity_score >= 0.8 else '#ff9800' if similarity_score >= 0.6 else '#f44336' similarity_label = tk.Label( info_frame, text=f"相似度: {similarity_percent}%", font=('Microsoft YaHei UI', 9, 'bold'), bg='#3c3c3c', fg=similarity_color, anchor='w' ) similarity_label.pack(fill=tk.X, padx=15, pady=(0, 10)) # 差异部分 if differences: # 统计关键差异 critical_count = sum(1 for d in differences if d.importance == 'critical') high_count = sum(1 for d in differences if d.importance == 'high') # 差异标题 diff_title_frame = tk.Frame(main_frame, bg='#2b2b2b') diff_title_frame.pack(fill=tk.X, pady=(0, 10)) diff_title = tk.Label( diff_title_frame, text=f"⚠️ 发现 {len(differences)} 处差异", font=('Microsoft YaHei UI', 11, 'bold'), bg='#2b2b2b', fg='#ff9800' ) diff_title.pack(side=tk.LEFT) if critical_count > 0: critical_badge = tk.Label( diff_title_frame, text=f"{critical_count} 关键", font=('Microsoft YaHei UI', 9), bg='#f44336', fg='#ffffff', padx=8, pady=2 ) critical_badge.pack(side=tk.LEFT, padx=(10, 5)) if high_count > 0: high_badge = tk.Label( diff_title_frame, text=f"{high_count} 重要", font=('Microsoft YaHei UI', 9), bg='#ff9800', fg='#ffffff', padx=8, pady=2 ) high_badge.pack(side=tk.LEFT) # 差异列表(可滚动) diff_container = tk.Frame(main_frame, bg='#2b2b2b') diff_container.pack(fill=tk.BOTH, expand=True, pady=(0, 15)) # 创建 Canvas 和 Scrollbar canvas = tk.Canvas(diff_container, bg='#2b2b2b', highlightthickness=0) scrollbar = ttk.Scrollbar(diff_container, orient="vertical", command=canvas.yview) scrollable_frame = tk.Frame(canvas, bg='#2b2b2b') scrollable_frame.bind( "", lambda e: canvas.configure(scrollregion=canvas.bbox("all")) ) canvas.create_window((0, 0), window=scrollable_frame, anchor="nw") canvas.configure(yscrollcommand=scrollbar.set) # 显示差异 importance_colors = { 'critical': '#f44336', 'high': '#ff9800', 'medium': '#2196f3', 'low': '#9e9e9e' } importance_labels = { 'critical': '关键', 'high': '重要', 'medium': '一般', 'low': '次要' } for i, diff in enumerate(differences): diff_frame = tk.Frame(scrollable_frame, bg='#3c3c3c', relief=tk.FLAT, bd=0) diff_frame.pack(fill=tk.X, pady=(0, 8), padx=2) # 差异标题行 header_frame = tk.Frame(diff_frame, bg='#3c3c3c') header_frame.pack(fill=tk.X, padx=10, pady=(8, 5)) category_label = tk.Label( header_frame, text=diff.category, font=('Microsoft YaHei UI', 9, 'bold'), bg='#3c3c3c', fg='#ffffff' ) category_label.pack(side=tk.LEFT) importance_badge = tk.Label( header_frame, text=importance_labels[diff.importance], font=('Microsoft YaHei UI', 8), bg=importance_colors[diff.importance], fg='#ffffff', padx=6, pady=1 ) importance_badge.pack(side=tk.LEFT, padx=(8, 0)) # 当前值 current_frame = tk.Frame(diff_frame, bg='#3c3c3c') current_frame.pack(fill=tk.X, padx=10, pady=(0, 3)) current_title = tk.Label( current_frame, text="当前任务:", font=('Microsoft YaHei UI', 8), bg='#3c3c3c', fg='#a0a0a0' ) current_title.pack(side=tk.LEFT) current_value = tk.Label( current_frame, text=diff.current_value, font=('Microsoft YaHei UI', 9), bg='#3c3c3c', fg='#4caf50', wraplength=500, justify='left' ) current_value.pack(side=tk.LEFT, padx=(5, 0)) # 历史值 history_frame = tk.Frame(diff_frame, bg='#3c3c3c') history_frame.pack(fill=tk.X, padx=10, pady=(0, 8)) history_title = tk.Label( history_frame, text="历史任务:", font=('Microsoft YaHei UI', 8), bg='#3c3c3c', fg='#a0a0a0' ) history_title.pack(side=tk.LEFT) history_value = tk.Label( history_frame, text=diff.history_value, font=('Microsoft YaHei UI', 9), bg='#3c3c3c', fg='#ff9800', wraplength=500, justify='left' ) history_value.pack(side=tk.LEFT, padx=(5, 0)) canvas.pack(side="left", fill="both", expand=True) scrollbar.pack(side="right", fill="y") else: # 无差异 no_diff_label = tk.Label( main_frame, text="✅ 未发现关键差异", font=('Microsoft YaHei UI', 10), bg='#2b2b2b', fg='#4caf50' ) no_diff_label.pack(pady=20) # 提示信息 hint_label = tk.Label( main_frame, text="是否直接复用该任务的代码?\n(选择「生成新代码」将根据当前需求重新生成)", font=('Microsoft YaHei UI', 9), bg='#2b2b2b', fg='#a0a0a0', justify='center' ) hint_label.pack(pady=(10, 15)) # 按钮区域 button_frame = tk.Frame(main_frame, bg='#2b2b2b') button_frame.pack(fill=tk.X) def on_confirm_click(): dialog.destroy() on_confirm() def on_reject_click(): dialog.destroy() on_reject() # 复用按钮 confirm_btn = tk.Button( button_frame, text="✓ 复用代码", font=('Microsoft YaHei UI', 10, 'bold'), bg='#4caf50', fg='#ffffff', activebackground='#45a049', activeforeground='#ffffff', relief=tk.FLAT, cursor='hand2', command=on_confirm_click, padx=30, pady=10 ) confirm_btn.pack(side=tk.LEFT, expand=True, fill=tk.X, padx=(0, 5)) # 拒绝按钮 reject_btn = tk.Button( button_frame, text="✗ 生成新代码", font=('Microsoft YaHei UI', 10), bg='#555555', fg='#ffffff', activebackground='#666666', activeforeground='#ffffff', relief=tk.FLAT, cursor='hand2', command=on_reject_click, padx=30, pady=10 ) reject_btn.pack(side=tk.LEFT, expand=True, fill=tk.X, padx=(5, 0)) # 等待对话框关闭 dialog.wait_window()