修改::未解析的引用 ‘TrendAnalysisModule’,,未解析的引用 ‘NumberGenerationModule’,,未解析的引用 ‘ModuleFactory’,,方法必须有第一个形参,通常叫做 ‘self’,,未解析的引用 ‘MainWindow’,,,从外部作用域隐藏名称 ‘self’,,方法 ‘on_result’ 可能为 ‘static’,,访问类的 protected 成员 _handle_module_run,,方法 ‘_format_number’ 可能为 ‘static’,,方法 ‘main’ 可能为 ‘static’,,,用户要求:吧子类界面(1.输入分析)标签后面的条目宽度调整要尽量宽,,在号码池里,标签后面的条目的宽度也是要尽量宽,按钮放在底部靠右的位置,,,代码【import sys
import os
import json
import random
import time
import threading
import logging
import uuid
from enum import Enum
from typing import Any, Dict, List, Optional, Callable, Union, Literal, Tuple
from collections import defaultdict
import tkinter as tk
from tkinter import (
Tk, Frame, Label, Button, Entry, StringVar, PanedWindow,
Canvas, Scrollbar, messagebox, Text, LabelFrame, Toplevel, Listbox
)
from tkinter.constants import VERTICAL, RAISED, BOTH, X, Y, LEFT, RIGHT, TOP, BOTTOM, HORIZONTAL
from tkinter import scrolledtext
from tkinter import ttk
from pathlib import Path
确保项目根目录在 sys.path 中
project_root = Path(file).parent.parent
if str(project_root) not in sys.path:
sys.path.insert(0, str(project_root))
尝试导入核心模块,如果失败则创建占位符
try:
from core.ui_config import get_ui_config, init_ui_config, UI_CONFIG
from core.event_center import event_center
from core.event_types import EventType
from core.global_config import GlobalConfig
except ImportError as import_error:
print(f"无法导入核心模块: {import_error}")
# -------------- 1. 先放 EventCenter 定义 -------------- class EventCenter: def __init__(self): from collections import defaultdict self._subscribers = defaultdict(list) def subscribe(self, event_type, handler): # 修复:检查event_type是否为字符串 t = event_type.value if hasattr(event_type, 'value') else event_type self._subscribers[t].append(handler) def publish(self, event): # 修复:检查event.type是否为字符串 if isinstance(event, dict): t = event['type'].value if hasattr(event['type'], 'value') else event['type'] else: t = event.type.value if hasattr(event.type, 'value') else event.type for h in self._subscribers.get(t, []): try: h(event) except Exception as exc: logging.error(f"事件处理失败: {exc}") # -------------- 2. 立即实例化 -------------- event_center = EventCenter() # -------------- 3. 其余占位符不动 -------------- UI_CONFIG = type('UI_CONFIG', (), {})() GlobalConfig = type('GlobalConfig', (), {})() def get_ui_config(): return {} def init_ui_config(): pass # 定义事件类型枚举 class EventType(Enum): START_COMMAND = "start_command" DIALOG_OPEN = "dialog_open" MODULE_RUN = "module_run" MODULE_READY = "module_ready" MODULE_COMPLETE = "module_complete" MODULE_RESULT = "module_result" DATA_SUBMIT = "data_submit" UI_UPDATE = "ui_update" ERROR = "error" LOG_EVENT = "log_event" DATA_FREEZE = "data_freeze" MODULE_SWITCH = "module_switch"
配置日志
logging.basicConfig(
level=logging.INFO,
format=‘%(asctime)s - %(name)s - %(levelname)s - %(message)s’,
datefmt=‘%Y-%m-%d %H:%M:%S’
)
logger = logging.getLogger(‘DLT_Analysis’)
====== 全局配置类 ======
class AppConfig:
VERSION = “大乐透智能分析平台 v6.0”
PROJECT_PATH = r"C:\Users\Administrator\Desktop\project"
MODULES_PATH = os.path.join(PROJECT_PATH, “modules”)
JSON_PATH = os.path.join(PROJECT_PATH, “json”)
LOG_PATH = os.path.join(PROJECT_PATH, “log”)
POOL_SAVE_PATH = os.path.join(MODULES_PATH, “号码池.json”)
CORE_SAVE_PATH = os.path.join(MODULES_PATH, “核心区数据.json”)
DATA_PATH = r’F:\超级\历史数据\历史数据.csv’
MODULE1_SAVE_PATH = os.path.join(JSON_PATH, “module1_save.json”)
# 确保目录存在 os.makedirs(JSON_PATH, exist_ok=True) os.makedirs(MODULES_PATH, exist_ok=True) # 模块ID定义 MODULE_IDS = { 'input_analysis': '1.输入分析', 'combination_analysis': '2.组合分析', 'follow_analysis': '3.跟随分析', 'trend_analysis': '4.趋势分析', 'number_generation': '5.数字生成' } # 核心区标签 CORE_LABELS = [ "前区:", "后区:", "前区热号:", "前区冷号:", "后区热号:", "后区冷号:" ] # 号码池标签 POOL_LABELS = [ "前区:", "后区:", "前数字频:", "前数字缺:", "后数字频:", "后数字缺:", "前频繁推:", "后低频推:", "生组合数:", "未组合码:", "前推荐多:", "前推荐少:", "后推荐多:", "后推荐少:", "和值:", "质合比:", "奇偶比:", "断区推荐:", "连号推荐:", "冷热推荐:", "后区热号:", "后区冷号:", "趋势号:" ] # 各模块动态区标签 MODULE_LABELS = { 'input_analysis': ["排除号码:", "前区:", "后区:", "推荐号码:", "前区:", "后区:"], 'combination_analysis': ["前数字频:", "前数字缺:", "后数字频:", "后数字缺:", "前频繁推:", "后低频推:", "生组合数:", "未组合码:"], 'follow_analysis': ["前推荐多:", "前推荐少:", "后推荐多:", "后推荐少:"], 'trend_analysis': ["和值:", "质合比:", "奇偶比:", "断区推荐:", "连号推荐:", "冷热推荐:", "后区热号:", "后区冷号:", "趋势号:"], 'number_generation': ["胆码:", "前区:", "后区:", "生成号码:", "1", "", "2", "", "3", "", "4", "", "5", ""] } # 添加缺失的常量 MODULES = ['input_analysis', 'combination_analysis', 'follow_analysis', 'trend_analysis', 'number_generation'] HISTORY_DATA_PATH = r'F:\超级\历史数据\历史数据.csv' # 事件类型定义 EVENT_TYPES = { 'MODULE_RUN': 'module_run', 'MODULE_RESULT': 'module_result', 'DATA_UPDATE': 'data_update' }
====== Token 管理类 ======
class TokenManager:
_instance = None
_lock = threading.Lock()
def __new__(cls): if cls._instance is None: with cls._lock: if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance def __init__(self): if not hasattr(self, '_initialized'): self._current_token = str(uuid.uuid4()) self._token_callbacks = [] self._initialized = True def get_token(self): return self._current_token def refresh_token(self): self._current_token = str(uuid.uuid4()) for callback in self._token_callbacks: callback(self._current_token) return self._current_token def register_token_callback(self, callback): self._token_callbacks.append(callback)
事件数据类
class Event:
def init(self, event_id: int, event_type: Union[EventType, str], source: str, target: str, data: dict = None):
self.event_id = event_id
self.type = event_type
self.source = source
self.target = target
self.data = data or {}
self.token = TokenManager().get_token()
def __getitem__(self, key): """允许像字典一样访问事件属性""" if key == 'type': return self.type elif key == 'source': return self.source elif key == 'target': return self.target elif key == 'data': return self.data elif key == 'token': return self.token raise KeyError(f"Event has no key '{key}'")
====== 号码池类 ======
class NumberPool:
def init(self):
self.data_store = {
‘front_hot’: [], ‘back_hot’: [], ‘front_freq’: {}, ‘back_freq’: {},
‘front_missing’: [], ‘back_missing’: [], ‘recommendations’: {},
‘generated_numbers’: [], ‘frozen’: False,
‘front_numbers’: [], ‘back_numbers’: [], ‘special_data’: {},
‘organized_data’: None, ‘core_data’: {}
}
self.lock = threading.Lock()
self.current_module = None
self.module_status = {module: False for module in AppConfig.MODULES}
self.running = True
self._setup_subscriptions()
self._load_data()
def _setup_subscriptions(self): """设置事件订阅""" # 修复:使用正确的event_type格式 event_center.subscribe( EventType.DATA_SUBMIT.value if hasattr(EventType.DATA_SUBMIT, 'value') else EventType.DATA_SUBMIT, self._handle_data_submit) event_center.subscribe( EventType.DATA_FREEZE.value if hasattr(EventType.DATA_FREEZE, 'value') else EventType.DATA_FREEZE, self._handle_data_freeze) def _handle_data_submit(self, event): """处理数据提交事件""" if self.data_store['frozen']: return with self.lock: for key, value in event.data.items(): if key in self.data_store: if isinstance(value, list): self.data_store[key] = ','.join(map(str, value)) else: self.data_store[key] = str(value) self._save_data() def _handle_data_freeze(self, event): """处理数据冻结事件""" with self.lock: self.data_store['frozen'] = event.data.get('freeze', False) self._save_data() def _save_data(self): """保存数据到文件""" try: with open(AppConfig.POOL_SAVE_PATH, 'w', encoding='utf-8') as f: json.dump(self.data_store, f, ensure_ascii=False, indent=2) except IOError as e: logging.error(f"[号码池] 保存数据失败: {str(e)}") def _load_data(self): """从文件加载数据""" if os.path.exists(AppConfig.POOL_SAVE_PATH): try: with open(AppConfig.POOL_SAVE_PATH, 'r', encoding='utf-8') as f: data = json.load(f) with self.lock: self.data_store.update(data) except (IOError, json.JSONDecodeError) as e: logging.error(f"[号码池] 加载数据失败: {str(e)}") def organize_data(self): """整理号码池数据到核心区""" if self.data_store['frozen']: return False with self.lock: # 数据整理逻辑 core_mapping = { '前区': '前区', '后区': '后区', '前区热号': '前频繁推', '前区冷号': '前推荐少', '后区热号': '后区热号', '后区冷号': '后区冷号' } for core_key, pool_key in core_mapping.items(): if pool_key in self.data_store: self.data_store['core_data'][core_key] = self.data_store[pool_key] # 保存核心区数据 try: with open(AppConfig.CORE_SAVE_PATH, 'w', encoding='utf-8') as f: json.dump(self.data_store['core_data'], f, ensure_ascii=False, indent=2) except IOError as e: logging.error(f"[核心区] 保存数据失败: {str(e)}") self._save_data() return True def get_data(self, key=None): """获取数据""" with self.lock: if key: return self.data_store.get(key) return self.data_store.copy()
====== 基础模块类 ======
class BaseModule:
def init(self, module_id: str):
self.module_id = module_id
self.module_name = AppConfig.MODULE_IDS[module_id]
self.dynamic_data = {}
self.token_manager = TokenManager()
self._initialize()
def _initialize(self): """初始化模块""" # 订阅 MODULE_RUN 事件,并检查目标是否为当前模块 # 修复:使用正确的event_type格式 event_center.subscribe( EventType.MODULE_RUN.value if hasattr(EventType.MODULE_RUN, 'value') else EventType.MODULE_RUN, self._handle_module_run) ready_event = Event( event_id=int(time.time()), event_type=EventType.MODULE_READY.value if hasattr(EventType.MODULE_READY, 'value') else EventType.MODULE_READY, source=self.module_id, target='main_ui' ) event_center.publish(ready_event) def _handle_module_run(self, event): """处理模块运行事件""" # 检查事件目标是否为当前模块 if event.target == self.module_id and event.data.get('token') == self.get_token(): self.run_analysis(event.data) def _submit_data(self, data): """提交数据到号码池""" submit_event = Event( event_id=int(time.time()), event_type=EventType.DATA_SUBMIT.value if hasattr(EventType.DATA_SUBMIT, 'value') else EventType.DATA_SUBMIT, source=self.module_id, target='pool', data=data ) event_center.publish(submit_event) def run_analysis(self, input_data=None): """运行分析(子类重写)""" pass def get_dynamic_labels(self): """获取动态区标签""" return AppConfig.MODULE_LABELS.get(self.module_id, []) def get_token(self): """获取当前token""" return self.token_manager.get_token()
====== 输入分析模块 ======
class InputAnalysisModule(BaseModule):
def init(self, module_id: str):
super().init(module_id)
self.dynamic_data = {
“排除号码”: {
“前区”: [“” for _ in range(10)],
“后区”: [“” for _ in range(10)]
},
“推荐号码”: {
“前区”: [],
“后区”: []
}
}
def run_analysis(self, input_data=None): """运行输入分析""" try: exclude_front = input_data.get('exclude_front', []) exclude_back = input_data.get('exclude_back', []) all_front = list(range(1, 36)) recommend_front = [num for num in all_front if num not in exclude_front][:10] all_back = list(range(1, 13)) recommend_back = [num for num in all_back if num not in exclude_back][:4] result_data = { "排除号码": { "前区": ["" for _ in range(10)], "后区": ["" for _ in range(10)] }, "推荐号码": { "前区": recommend_front, "后区": recommend_back } } self.dynamic_data.update(result_data) self._submit_data(result_data) # 发布结果事件 result_event = Event( event_id=int(time.time()), event_type=EventType.MODULE_RESULT.value if hasattr(EventType.MODULE_RESULT, 'value') else EventType.MODULE_RESULT, source=self.module_id, target='main_ui', data={ 'module_id': self.module_id, 'token': self.get_token(), 'data': result_data } ) event_center.publish(result_event) return True, "分析完成" except Exception as e: return False, f"分析失败: {str(e)}"
====== 组合分析模块 ======
class CombinationAnalysisModule(BaseModule):
def init(self, module_id: str):
super().init(module_id)
self.dynamic_data = {
“前数字频”: {}, “前数字缺”: [], “后数字频”: {}, “后数字缺”: [],
“前频繁推”: [], “后低频推”: [], “生组合数”: 0, “未组合码”: []
}
def run_analysis(self, input_data=None): """运行组合分析""" try: result_data = { "前数字频": {i: random.randint(1, 100) for i in range(1, 36)}, "前数字缺": random.sample(range(1, 36), 5), "后数字频": {i: random.randint(1, 50) for i in range(1, 13)}, "后数字缺": random.sample(range(1, 13), 2), "前频繁推": sorted(random.sample(range(1, 36), 5)), "后低频推": sorted(random.sample(range(1, 13), 2)), "生组合数": random.randint(100, 1000), "未组合码": random.sample(range(1, 36), 5) } self.dynamic_data.update(result_data) self._submit_data(result_data) # 发布结果事件 result_event = Event( event_id=int(time.time()), event_type=EventType.MODULE_RESULT.value if hasattr(EventType.MODULE_RESULT, 'value') else EventType.MODULE_RESULT, source=self.module_id, target='main_ui', data={ 'module_id': self.module_id, 'token': self.get_token(), 'data': result_data } ) event_center.publish(result_event) return True, "分析完成" except Exception as e: return False, f"分析失败: {str(e)}"
====== 跟随分析模块 ======
class FollowAnalysisModule(BaseModule):
def init(self, module_id: str):
super().init(module_id)
self.dynamic_data = {
“前推荐多”: [], “前推荐少”: [], “后推荐多”: [], “后推荐少”: []
}
def run_analysis(self, input_data=None): """运行跟随分析""" try: result_data = { "前推荐多": sorted(random.sample(range(1, 36), 5)), "前推荐少": sorted(random.sample(range(1, 36), 5)), "后推荐多": sorted(random.sample(range(1, 13), 3)), "后推荐少": sorted(random.sample(range(1, 13), 3)) } self.dynamic_data.update(result_data) self._submit_data(result_data) # 发布结果事件 result_event = Event( event_id=int(time.time()), event_type=EventType.MODULE_RESULT.value if hasattr(EventType.MODULE_RESULT, 'value') else EventType.MODULE_RESULT, source=self.module_id, target='main_ui', data={ 'module_id': self.module_id, 'token': self.get_token(), 'data': result_data } ) event_center.publish(result_event) return True, "分析完成" except Exception as e: return False, f"分析失败: {str(e)}" # ====== 趋势分析模块 ====== class TrendAnalysisModule(BaseModule): def __init__(self, module_id: str): super().__init__(module_id) self.dynamic_data = { "和值": "", "质合比": "", "奇偶比": "", "断区推荐": "", "连号推荐": "", "冷热推荐": "", "后区热号": "", "后区冷号": "", "趋势号": "" } def run_analysis(self, input_data=None): """运行趋势分析""" try: result_data = { "和值": f"{random.randint(60, 80)}-{random.randint(100, 125)}", "质合比": f"{random.randint(1, 3)}:{random.randint(2, 4)}", "奇偶比": f"{random.randint(2, 4)}:{random.randint(1, 3)}", "断区推荐": random.choice(["一区", "二区", "三区", "四区", "五区,七区"]), "连号推荐": f"{random.randint(1, 10)}-{random.randint(11, 20)}", "冷热推荐": f"热号:{','.join(map(str, sorted(random.sample(range(1, 36), 5))))}", "后区热号": ','.join(map(str, sorted(random.sample(range(1, 13), 3)))), "后区冷号": ','.join(map(str, sorted(random.sample(range(1, 13), 2)))), "趋势号": ','.join(map(str, sorted(random.sample(range(1, 36), 8)))) } self.dynamic_data.update(result_data) self._submit_data(result_data) # 发布结果事件 result_event = Event( event_id=int(time.time()), event_type=EventType.MODULE_RESULT.value if hasattr(EventType.MODULE_RESULT, 'value') else EventType.MODULE_RESULT, source=self.module_id, target='main_ui', data={ 'module_id': self.module_id, 'token': self.get_token(), 'data': result_data } ) event_center.publish(result_event) return True, "分析完成" except Exception as e: return False, f"分析失败: {str(e)}" # ====== 号码生成模块 ====== class NumberGenerationModule(BaseModule): def __init__(self, module_id: str): super().__init__(module_id) self.dynamic_data = { "胆码": { "前区": ["" for _ in range(5)], "后区": ["" for _ in range(5)] }, "推荐5注号码:": { "1.": "", "2.": "", "3.": "", "4.": "", "5.": "" } } def run_analysis(self, input_data=None): """运行号码生成""" try: front_dan = input_data.get('front_dan', []) back_dan = input_data.get('back_dan', []) generated_numbers = [] for _ in range(5): # 前区处理 if front_dan: dan_count = random.randint(1, min(2, len(front_dan))) selected_dan = random.sample(front_dan, dan_count) remaining_front = [num for num in range(1, 36) if num not in selected_dan] other_front = random.sample(remaining_front, 5 - dan_count) front_numbers = sorted(selected_dan + other_front) else: front_numbers = sorted(random.sample(range(1, 36), 5)) # 后区处理 if back_dan: dan_count = min(1, len(back_dan)) selected_dan = random.sample(back_dan, dan_count) remaining_back = [num for num in range(1, 13) if num not in selected_dan] other_back = random.sample(remaining_back, 2 - dan_count) back_numbers = sorted(selected_dan + other_back) else: back_numbers = sorted(random.sample(range(1, 13), 2)) generated_numbers.append(f"前区: {front_numbers} 后区: {back_numbers}") result_data = { "胆码": { "前区": front_dan, "后区": back_dan }, "生成号码": generated_numbers } self.dynamic_data.update(result_data) self._submit_data({"生成号码": generated_numbers}) # 发布结果事件 result_event = Event( event_id=int(time.time()), event_type=EventType.MODULE_RESULT.value if hasattr(EventType.MODULE_RESULT, 'value') else EventType.MODULE_RESULT, source=self.module_id, target='main_ui', data={ 'module_id': self.module_id, 'token': self.get_token(), 'data': result_data } ) event_center.publish(result_event) return True, "号码生成完成" except Exception as e: return False, f"号码生成失败: {str(e)}" # ====== 模块工厂类 ====== class ModuleFactory: @staticmethod def create_module(module_id: str) -> BaseModule: if module_id == 'input_analysis': return InputAnalysisModule(module_id) elif module_id == 'combination_analysis': return CombinationAnalysisModule(module_id) elif module_id == 'follow_analysis': return FollowAnalysisModule(module_id) elif module_id == 'trend_analysis': return TrendAnalysisModule(module_id) elif module_id == 'number_generation': return NumberGenerationModule(module_id) else: raise ValueError(f"未知模块ID: {module_id}") # ====== 主窗口类 ====== class MainWindow: def __init__(self, root, number_pool): self.number_pool = number_pool self.root = root self.root.title(AppConfig.VERSION) self.root.geometry("1400x800") self.token_manager = TokenManager() self._current_token = self.token_manager.get_token() self.token_var = StringVar(value=self._current_token) # 初始化所有属性 self.current_module = None self.modules = {} self.period_var = None self.core_vars = {} self.dynamic_content = None self.dynamic_button_frame = None self.run_button = None self.clear_button = None self.save_button = None self.refresh_button = None self.dynamic_vars = {} self.pool_vars = {} self.module_buttons = {} self.exclude_front_entries = [] # 改为存储Entry控件 self.exclude_back_entries = [] # 改为存储Entry控件 self.var_refront = None self.var_reback = None # 使用全局事件中心 self.event_center = event_center # 注册事件订阅 self._setup_event_subscriptions() # 创建主框架 self.main_frame = Frame(root) self.main_frame.pack(fill='both', expand=True, padx=10, pady=10) # 创建三栏布局 self.create_left_panel() self.create_center_panel() self.create_right_panel() # 状态栏 self.status_var = StringVar(value="就绪") self.status_bar = Label(root, textvariable=self.status_var, bd=1, relief=RAISED, anchor='w') self.status_bar.pack(side='bottom', fill='x') # 注册token更新回调 self.token_manager.register_token_callback(self._on_token_update) logger.info("主窗口初始化完成") def _on_token_update(self, new_token): """Token更新回调""" self._current_token = new_token self.token_var.set(new_token) logger.info(f"Token已更新: {new_token}") def on_result(self, event): """处理结果事件 - 静态方法""" print(f'[MainWindow] 收到回执 token={event["token"]}') # 后续 emit 信号或更新 UI 写这里 def _setup_event_subscriptions(self): """设置事件订阅""" # 修复:使用正确的event_type格式 event_center.subscribe( EventType.MODULE_RESULT.value if hasattr(EventType.MODULE_RESULT, 'value') else EventType.MODULE_RESULT, self._handle_module_result) event_center.subscribe(EventType.ERROR.value if hasattr(EventType.ERROR, 'value') else EventType.ERROR, self._handle_module_error) # 添加MODULE_RUN事件订阅 event_center.subscribe( EventType.MODULE_RUN.value if hasattr(EventType.MODULE_RUN, 'value') else EventType.MODULE_RUN, self._handle_module_run) def _handle_module_run(self, event): """处理模块运行事件 - 转发到对应模块""" if event.target in self.modules: module = self.modules[event.target] if hasattr(module, '_handle_module_run'): module._handle_module_run(event) def create_left_panel(self): """创建左侧模块按钮面板""" left_frame = LabelFrame(self.main_frame, text="功能模块", width=200) left_frame.pack(side='left', fill='y', padx=(0, 10)) left_frame.pack_propagate(False) # 创建按钮面板 button_frame = Frame(left_frame) button_frame.pack(fill='both', expand=True, padx=5, pady=5) # 添加模块按钮 for module_id, module_name in AppConfig.MODULE_IDS.items(): btn = Button(button_frame, text=module_name, command=lambda mid=module_id: self.select_module(mid), height=2, font=("Arial", 11)) btn.pack(fill='x', pady=5) self.module_buttons[module_id] = btn def select_module(self, module_id): """选择模块""" self.current_module = module_id self.update_dynamic_area(module_id) self.status_var.set(f"已选择模块: {AppConfig.MODULE_IDS[module_id]}") def create_center_panel(self): """创建中间面板""" center_frame = Frame(self.main_frame) center_frame.pack(side='left', fill='both', expand=True, padx=(0, 10)) center_frame.config(width=500) # 期号区 period_frame = LabelFrame(center_frame, text="期号信息", height=60) period_frame.pack(fill='x', pady=(0, 10)) period_frame.pack_propagate(False) # 获取最新期号 latest_period = self.get_latest_period() self.period_var = StringVar(value=f"当前期号: {latest_period}") Label(period_frame, textvariable=self.period_var, font=("Arial", 12)).pack(pady=10) # Token显示区域 token_frame = LabelFrame(center_frame, text="Token管理", height=50) token_frame.pack(fill='x', pady=(0, 10)) token_frame.pack_propagate(False) token_content = Frame(token_frame) token_content.pack(fill='x', padx=10, pady=5) Label(token_content, text="当前Token:").pack(side=tk.LEFT) token_label = Label(token_content, textvariable=self.token_var, relief='sunken', width=25) token_label.pack(side=tk.LEFT, padx=5) # Token按钮靠右对齐 token_button_frame = Frame(token_content) token_button_frame.pack(side=tk.RIGHT) refresh_token_btn = Button(token_button_frame, text="刷新Token", command=self.refresh_token, width=10) refresh_token_btn.pack(side=tk.RIGHT, padx=2) # 核心区 core_frame = LabelFrame(center_frame, text="核心区") core_frame.pack(fill='x', pady=(0, 10)) self.core_vars = {} for label in AppConfig.CORE_LABELS: frame = Frame(core_frame) frame.pack(fill='x', pady=2) Label(frame, text=label, width=10, anchor='w').pack(side='left') var = StringVar() self.core_vars[label.strip(':')] = var Label(frame, textvariable=var, relief='sunken', width=15).pack(side='left', fill='x', expand=True) # 动态区 dynamic_frame = LabelFrame(center_frame, text="动态区") dynamic_frame.pack(fill='both', expand=True) # 动态区内容框架 self.dynamic_content = Frame(dynamic_frame) self.dynamic_content.pack(fill='both', expand=True, padx=5, pady=5) # 动态区底部按钮 self.dynamic_button_frame = Frame(dynamic_frame) self.dynamic_button_frame.pack(fill='x', pady=5) # 使用Frame来让按钮靠右 button_right_frame = Frame(self.dynamic_button_frame) button_right_frame.pack(side=tk.RIGHT) self.run_button = Button(button_right_frame, text="运行", command=self.run_module, width=8) self.run_button.pack(side=tk.LEFT, padx=5) self.clear_button = Button(button_right_frame, text="清除", command=self.clear_dynamic, width=8) self.clear_button.pack(side=tk.LEFT, padx=5) self.save_button = Button(button_right_frame, text="保存", command=self.save_dynamic_data, width=8) self.save_button.pack(side=tk.LEFT, padx=5) self.refresh_button = Button(button_right_frame, text="刷新", command=self.refresh_pool, width=8) self.refresh_button.pack(side=tk.LEFT, padx=5) # 初始化动态区 self.dynamic_vars = {} @staticmethod def get_latest_period(): """从历史数据文件中获取最新期号""" try: if os.path.exists(AppConfig.HISTORY_DATA_PATH): encodings = ['utf-8', 'gbk', 'gb2312', 'latin-1'] for encoding in encodings: try: with open(AppConfig.HISTORY_DATA_PATH, 'r', encoding=encoding) as f: lines = f.readlines() if lines: for i in range(len(lines) - 1, -1, -1): line = lines[i].strip() if line and line.split(',')[0].isdigit(): return line.split(',')[0] break except UnicodeDecodeError: continue return "2025001" except Exception as e: logger.error(f"获取最新期号失败: {str(e)}") return "2025001" def refresh_token(self): """刷新Token""" new_token = self.token_manager.refresh_token() self.token_var.set(new_token) self.status_var.set("Token已刷新") def clear_dynamic(self): """清除动态区数据""" for var in self.dynamic_vars.values(): if isinstance(var, StringVar): var.set('') elif isinstance(var, Text): var.delete(1.0, 'end') self.status_var.set("动态区已清除") def save_dynamic_data(self): """保存动态区数据""" try: module_id = self.current_module if not module_id: messagebox.showwarning("警告", "请先选择一个模块") return data_to_save = {} for key, var in self.dynamic_vars.items(): if isinstance(var, StringVar): data_to_save[key] = var.get() elif isinstance(var, Text): data_to_save[key] = var.get(1.0, 'end').strip() save_path = os.path.join(AppConfig.JSON_PATH, f"{module_id}_save.json") with open(save_path, 'w', encoding='utf-8') as f: json.dump(data_to_save, f, ensure_ascii=False, indent=2) self.status_var.set(f"数据已保存到 {save_path}") messagebox.showinfo("成功", f"数据已保存到 {save_path}") except Exception as e: messagebox.showerror("错误", f"保存失败: {str(e)}") def refresh_pool(self): """刷新号码池""" try: pool_data = self.number_pool.get_data() for label in AppConfig.POOL_LABELS: key = label.strip(':') if key in pool_data: value = pool_data[key] if isinstance(value, list): self.pool_vars[label].set(','.join(map(str, value))) else: self.pool_vars[label].set(str(value)) self.status_var.set("号码池已刷新") except Exception as e: messagebox.showerror("错误", f"刷新失败: {str(e)}") def update_dynamic_area(self, module_id): """更新动态区显示""" # 清除现有内容 for widget in self.dynamic_content.winfo_children(): widget.destroy() self.dynamic_vars = {} # 创建模块实例(如果不存在) if module_id not in self.modules: self.modules[module_id] = ModuleFactory.create_module(module_id) module = self.modules[module_id] labels = module.get_dynamic_labels() # 根据模块ID创建不同的UI if module_id == 'input_analysis': self._create_input_analysis_ui(labels) elif module_id == 'number_generation': self._create_number_generation_ui(labels) else: self._create_default_dynamic_ui(labels) def _create_input_analysis_ui(self, labels): """创建输入分析模块的UI""" # 排除号码区域 exclude_frame = LabelFrame(self.dynamic_content, text="排除号码") exclude_frame.pack(fill='x', pady=5) # 前区排除 front_frame = Frame(exclude_frame) front_frame.pack(fill='x', pady=2) Label(front_frame, text="前区:", width=8, anchor='w').pack(side='left') self.exclude_front_entries = [] for i in range(10): var = StringVar() entry = Entry(front_frame, textvariable=var, width=4) entry.pack(side='left', padx=2) self.exclude_front_entries.append(entry) self.dynamic_vars[f"exclude_front_{i}"] = var # 后区排除 back_frame = Frame(exclude_frame) back_frame.pack(fill='x', pady=2) Label(back_frame, text="后区:", width=8, anchor='w').pack(side='left') self.exclude_back_entries = [] for i in range(10): var = StringVar() entry = Entry(back_frame, textvariable=var, width=4) entry.pack(side='left', padx=2) self.exclude_back_entries.append(entry) self.dynamic_vars[f"exclude_back_{i}"] = var # 推荐号码区域 recommend_frame = LabelFrame(self.dynamic_content, text="推荐号码") recommend_frame.pack(fill='x', pady=5) # 前区推荐 front_rec_frame = Frame(recommend_frame) front_rec_frame.pack(fill='x', pady=2) Label(front_rec_frame, text="前区:", width=8, anchor='w').pack(side='left') self.var_refront = StringVar() Label(front_rec_frame, textvariable=self.var_refront, relief='sunken', width=30).pack(side='left', fill='x', expand=True) # 后区推荐 back_rec_frame = Frame(recommend_frame) back_rec_frame.pack(fill='x', pady=2) Label(back_rec_frame, text="后区:", width=8, anchor='w').pack(side='left') self.var_reback = StringVar() Label(back_rec_frame, textvariable=self.var_reback, relief='sunken', width=30).pack(side='left', fill='x', expand=True) def _create_number_generation_ui(self, labels): """创建号码生成模块的UI""" # 胆码区域 dan_frame = LabelFrame(self.dynamic_content, text="胆码") dan_frame.pack(fill='x', pady=5) # 前区胆码 front_dan_frame = Frame(dan_frame) front_dan_frame.pack(fill='x', pady=2) Label(front_dan_frame, text="前区:", width=8, anchor='w').pack(side='left') front_dan_entries = [] for i in range(5): var = StringVar() entry = Entry(front_dan_frame, textvariable=var, width=4) entry.pack(side='left', padx=2) front_dan_entries.append(entry) self.dynamic_vars[f"front_dan_{i}"] = var # 后区胆码 back_dan_frame = Frame(dan_frame) back_dan_frame.pack(fill='x', pady=2) Label(back_dan_frame, text="后区:", width=8, anchor='w').pack(side='left') back_dan_entries = [] for i in range(5): var = StringVar() entry = Entry(back_dan_frame, textvariable=var, width=4) entry.pack(side='left', padx=2) back_dan_entries.append(entry) self.dynamic_vars[f"back_dan_{i}"] = var # 生成号码区域 gen_frame = LabelFrame(self.dynamic_content, text="生成号码") gen_frame.pack(fill='both', expand=True, pady=5) # 使用文本框显示生成的号码 gen_text = scrolledtext.ScrolledText(gen_frame, height=10, width=50) gen_text.pack(fill='both', expand=True, padx=5, pady=5) self.dynamic_vars["generated_numbers"] = gen_text def _create_default_dynamic_ui(self, labels): """创建默认的动态区UI""" for label in labels: frame = Frame(self.dynamic_content) frame.pack(fill='x', pady=2) Label(frame, text=label, width=15, anchor='w').pack(side='left') var = StringVar() entry = Entry(frame, textvariable=var, width=30) entry.pack(side='left', fill='x', expand=True) self.dynamic_vars[label] = var def create_right_panel(self): """创建右侧号码池面板""" right_frame = LabelFrame(self.main_frame, text="号码池", width=300) right_frame.pack(side='right', fill='y', padx=(10, 0)) right_frame.pack_propagate(False) # 创建滚动框架 canvas = Canvas(right_frame) scrollbar = Scrollbar(right_frame, orient='vertical', command=canvas.yview) scrollable_frame = Frame(canvas) scrollable_frame.bind( "<Configure>", lambda e: canvas.configure(scrollregion=canvas.bbox("all")) ) canvas.create_window((0, 0), window=scrollable_frame, anchor="nw") canvas.configure(yscrollcommand=scrollbar.set) canvas.pack(side="left", fill="both", expand=True) scrollbar.pack(side="right", fill="y") # 号码池标签 self.pool_vars = {} for label in AppConfig.POOL_LABELS: frame = Frame(scrollable_frame) frame.pack(fill='x', pady=2, padx=5) Label(frame, text=label, width=12, anchor='w').pack(side='left') var = StringVar() self.pool_vars[label] = var Label(frame, textvariable=var, relief='sunken', width=15).pack(side='left', fill='x', expand=True) # 添加整理按钮 organize_btn = Button(scrollable_frame, text="整理到核心区", command=self.organize_to_core, height=2) organize_btn.pack(fill='x', pady=10, padx=5) def organize_to_core(self): """整理号码池数据到核心区""" try: if self.number_pool.organize_data(): # 更新核心区显示 core_data = self.number_pool.get_data('core_data') or {} for label in AppConfig.CORE_LABELS: key = label.strip(':') if key in core_data: value = core_data[key] if isinstance(value, list): self.core_vars[key].set(','.join(map(str, value))) else: self.core_vars[key].set(str(value)) self.status_var.set("数据已整理到核心区") else: self.status_var.set("数据已冻结,无法整理") except Exception as e: messagebox.showerror("错误", f"整理失败: {str(e)}") def run_module(self): """运行当前模块""" if not self.current_module: messagebox.showwarning("警告", "请先选择一个模块") return try: # 获取输入数据 input_data = {} for key, var in self.dynamic_vars.items(): if key.startswith('exclude_front_'): if key not in input_data: input_data['exclude_front'] = [] value = var.get().strip() if value and value.isdigit(): input_data['exclude_front'].append(int(value)) elif key.startswith('exclude_back_'): if key not in input_data: input_data['exclude_back'] = [] value = var.get().strip() if value and value.isdigit(): input_data['exclude_back'].append(int(value)) elif key.startswith('front_dan_'): if 'front_dan' not in input_data: input_data['front_dan'] = [] value = var.get().strip() if value and value.isdigit(): input_data['front_dan'].append(int(value)) elif key.startswith('back_dan_'): if 'back_dan' not in input_data: input_data['back_dan'] = [] value = var.get().strip() if value and value.isdigit(): input_data['back_dan'].append(int(value)) elif isinstance(var, StringVar): input_data[key] = var.get() elif isinstance(var, Text): input_data[key] = var.get(1.0, 'end').strip() # 创建模块运行事件 run_event = Event( event_id=int(time.time()), event_type=EventType.MODULE_RUN.value if hasattr(EventType.MODULE_RUN, 'value') else EventType.MODULE_RUN, source='main_ui', target=self.current_module, data={ 'token': self.token_manager.get_token(), 'input_data': input_data } ) # 发布事件 event_center.publish(run_event) self.status_var.set(f"正在运行 {AppConfig.MODULE_IDS[self.current_module]}...") except Exception as e: messagebox.showerror("错误", f"运行失败: {str(e)}") def _handle_module_result(self, event): """处理模块结果事件""" try: # 检查token是否有效 if event.data.get('token') != self.token_manager.get_token(): logger.warning( f"Token不匹配,忽略结果: {event.data.get('token')} != {self.token_manager.get_token()}") return module_id = event.data.get('module_id') result_data = event.data.get('data', {}) # 更新动态区显示 if module_id == 'input_analysis': if '推荐号码' in result_data: rec = result_data['推荐号码'] if '前区' in rec: self.var_refront.set(','.join(map(str, rec['前区']))) if '后区' in rec: self.var_reback.set(','.join(map(str, rec['后区']))) elif module_id == 'number_generation': if '生成号码' in result_data: gen_numbers = result_data['生成号码'] text_widget = self.dynamic_vars.get("generated_numbers") if text_widget: text_widget.delete(1.0, 'end') for i, num_str in enumerate(gen_numbers, 1): text_widget.insert('end', f"{i}. {num_str}\n") else: # 更新其他模块的显示 for key, value in result_data.items(): if key in self.dynamic_vars: if isinstance(value, list): self.dynamic_vars[key].set(','.join(map(str, value))) else: self.dynamic_vars[key].set(str(value)) self.status_var.set(f"{AppConfig.MODULE_IDS[module_id]} 完成") except Exception as e: logger.error(f"处理模块结果失败: {str(e)}") def _handle_module_error(self, event): """处理模块错误事件""" error_msg = event.data.get('error', '未知错误') self.status_var.set(f"错误: {error_msg}") messagebox.showerror("错误", error_msg) def _format_number(self, number): """格式化数字显示 - 静态方法""" if isinstance(number, list): return ','.join(map(str, number)) return str(number) def _get_exclude_numbers(self): """获取排除号码 - 静态方法""" exclude_front = [] exclude_back = [] for entry in self.exclude_front_entries: value = entry.get().strip() if value and value.isdigit(): exclude_front.append(int(value)) for entry in self.exclude_back_entries: value = entry.get().strip() if value and value.isdigit(): exclude_back.append(int(value)) return exclude_front, exclude_back # ====== 应用启动函数 ====== def main(): """主函数""" try: # 初始化号码池 number_pool = NumberPool() # 创建主窗口 root = Tk() app = MainWindow(root, number_pool) # 设置初始模块 app.select_module('input_analysis') # 启动主循环 root.mainloop() except Exception as e: logger.error(f"应用启动失败: {str(e)}") messagebox.showerror("启动错误", f"应用启动失败: {str(e)}") if __name__ == "__main__": main()
】
最新发布