from ui.unloading_dialog_ui import UnloadingDialogUI from apis.tary_api import TaryApi from PySide6.QtCore import Qt, Signal from PySide6.QtWidgets import QMessageBox, QDialog import logging from utils.app_mode import AppMode from utils.pallet_type_manager import PalletTypeManager from utils.modbus_utils import ModbusUtils class UnloadingDialog(UnloadingDialogUI): # 定义一个信号,用于向主窗口传递托盘号 tray_code_signal = Signal(str, str, str, str) def __init__(self, parent=None, user_id=None): """初始化下料对话框""" super().__init__() self.parent = parent self.user_id = user_id self.current_tier = None # 添加一个变量来保存当前层数 # 初始化API self.tary_api = TaryApi() # 彻底禁用对话框的回车键关闭功能 self.setModal(True) # 禁用所有按钮的默认行为 self.confirm_button.setAutoDefault(False) self.confirm_button.setDefault(False) self.cancel_button.setAutoDefault(False) self.cancel_button.setDefault(False) # 设置对话框特性,按下Escape键才能关闭 self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) # 确保焦点跟踪器能够跟踪此对话框中的输入框 from utils.focus_tracker import FocusTracker self.focus_tracker = FocusTracker.get_instance() # 初始化托盘类型下拉列表 self.init_pallet_types() # 绑定事件 self.setup_connections() def init_pallet_types(self): """初始化托盘类型下拉列表""" # 从数据库获取托盘类型列表 pallet_type_manager = PalletTypeManager.get_instance() pallet_types = pallet_type_manager.get_pallet_types() # 清空现有选项 self.pallet_type_input.clear() # 添加新选项 for pallet_id, pallet_name in pallet_types.items(): self.pallet_type_input.addItem(pallet_name, userData=pallet_id) logging.info(f"从数据库加载{len(pallet_types)}个托盘类型") def get_current_pallet_type_id(self): """获取当前选中的托盘类型ID""" current_index = self.pallet_type_input.currentIndex() if current_index >= 0: pallet_id = self.pallet_type_input.itemData(current_index) logging.info(f"获取当前选中的托盘类型ID: {pallet_id}") return pallet_id logging.warning("未获取到托盘类型ID") return None def get_current_tier(self): """获取当前托盘的层数""" tier = self.tier_input.text().strip() if not tier: return self.current_tier if self.current_tier else "3" return tier def setup_connections(self): """设置事件连接""" # 托盘号输入框回车事件触发查询 self.tray_input.returnPressed.connect(self.handle_tray_return_pressed) # 移除editingFinished事件,避免重复触发查询 # self.tray_input.editingFinished.connect(self.on_tray_query) # 确认按钮点击事件 self.confirm_button.clicked.connect(self.accept) # 取消按钮点击事件 self.cancel_button.clicked.connect(self.reject) def handle_tray_return_pressed(self): """处理托盘输入框的回车事件""" # 阻止事件传播 logging.info("托盘输入框回车事件触发") self.on_tray_query() # 阻止事件继续传播 return True def on_tray_query(self): """查询托盘信息""" try: tray_code = self.tray_input.text().strip() tier = self.tier_input.text().strip() # 获取用户输入的层数 pallet_type = self.pallet_type_input.currentText().strip() if not tray_code: return logging.info(f"查询托盘号: {tray_code}") # 初始化托盘类型管理器 pallet_type_manager = PalletTypeManager.get_instance() if AppMode.is_api(): self.tary_api = TaryApi() # 调用API获取托盘信息 response = self.tary_api.get_tary_info(tray_code) if response.get("success", False) and response.get("data"): tray_data = response.get("data", {}) logging.info(f"API返回托盘数据: {tray_data}") # 如果用户输入了层数,使用用户输入的层数 if tier: tray_data["tier"] = tier pallet_type_manager.save_pallet_info(tray_code, tray_data, self.user_id) else: # API查询失败,保存基本信息到数据库 logging.info(f"API查询失败,保存基本信息到数据库") # if not pallet_type or not tier: # QMessageBox.warning(self, "提示", "请选择托盘类型和层数") # return pallet_info = { "cc": pallet_type, "cs": tier # 使用用户输入的层数 } pallet_type_manager.save_pallet_info(tray_code, pallet_info, self.user_id) else: # 查询数据库中的托盘信息 pallet_info = pallet_type_manager.get_pallet_info_by_pallet_id(tray_code) if not pallet_info: # 数据库中没有记录,保存基本信息 logging.info(f"数据库中未找到记录,保存基本信息") # if not pallet_type or not tier: # QMessageBox.warning(self, "提示", "请选择托盘类型和层数") # return pallet_info = { "cc": pallet_type, "cs": tier # 使用用户输入的层数 } pallet_type_manager.save_pallet_info(tray_code, pallet_info, self.user_id) # 重新获取完整的托盘信息 pallet_info = pallet_type_manager.get_pallet_detail(tray_code) if not pallet_info: logging.warning(f"无法获取托盘详细信息: {tray_code}") pallet_info = { "zx_name": "--", "cz": "--", "weight": "0", "amount": "0", "tier": tier if tier else "4", # 使用用户输入的层数,如果没有则默认3层 "pallet_name": pallet_type } # 显示托盘相关信息 axis_type = str(pallet_info.get("zx_name", "--")) material = str(pallet_info.get("cz", "--")) weight = str(pallet_info.get("weight", "--")) amount = str(pallet_info.get("amount", "--")) self.current_tier = pallet_info.get("cs", tier if tier else "4") # 优先使用数据库中的层数,其次是用户输入的层数,最后是默认值 logging.info(f"显示托盘信息: 轴型={axis_type}, 材质={material}, 重量={weight}, 层数={self.current_tier}") # 设置显示值 self.axis_value.setText(axis_type) self.material_tier_value.setPlaceholderText(material) self.material_tier_value.setText("") # 清空文本,让用户输入 self.quantity_value.setText(amount) self.weight_value.setText(f"{weight} kg") self.tier_input.setText(str(self.current_tier)) # 设置层数输入框的值 self.pallet_type_input.setCurrentText(pallet_info.get("pallet_name", "--")) # 发送托盘号到主窗口 from widgets.main_window import MainWindow main_window = self.parent if main_window and isinstance(main_window, MainWindow): # 检查托盘号是否已存在 existed = False for i in range(main_window.tray_edit.count()): if main_window.tray_edit.itemText(i) == tray_code: existed = True break # 如果不存在,则添加 if not existed: logging.info(f"添加托盘号到主窗口: {tray_code}") main_window.tray_edit.addItem(tray_code) # 设置当前选中的托盘号 main_window.tray_edit.setCurrentText(tray_code) logging.info(f"设置主窗口当前托盘号: {tray_code}") except Exception as e: logging.error(f"查询托盘信息异常: {str(e)}") QMessageBox.critical(self, "查询异常", f"查询托盘信息时发生异常: {str(e)}") def keyPressEvent(self, event): """重写键盘事件处理,防止回车关闭对话框""" # 如果按下回车键 if event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter: logging.info(f"捕获到回车键事件,当前焦点部件: {self.focusWidget()}") # 如果焦点在托盘输入框上,触发查询 if self.focusWidget() == self.tray_input: # 不需要重复调用on_tray_query,因为returnPressed信号已经处理了 event.accept() # 消费掉这个事件 return # 如果焦点在确认按钮上,则允许默认行为(确认) if self.focusWidget() == self.confirm_button: return super().keyPressEvent(event) # 其他情况下,阻止回车事件传播 event.accept() # 消费掉这个事件 return # 其他键位事件交给父类处理 super().keyPressEvent(event) def get_unloading_info(self): """获取当前下料信息""" return { 'tray_code': self.tray_input.text().strip(), 'tier': self.tier_input.text().strip(), 'pallet_type': self.pallet_type_input.currentText().strip(), 'pallet_type_id': self.get_current_pallet_type_id(), 'axis_type': self.axis_value.text().strip(), 'material': self.material_tier_value.text().strip(), 'quantity': self.quantity_value.text().strip(), 'weight': self.weight_value.text().strip() } def set_unloading_info(self, info): """设置下料信息""" if not info: return self.tray_input.setText(info.get('tray_code', '')) self.tier_input.setText(info.get('tier', '')) # 设置托盘类型 pallet_type = info.get('pallet_type', '') index = self.pallet_type_input.findText(pallet_type) if index >= 0: self.pallet_type_input.setCurrentIndex(index) # 设置其他信息 self.axis_value.setText(info.get('axis_type', '--')) self.material_tier_value.setText(info.get('material', '--')) self.quantity_value.setText(info.get('quantity', '0')) self.weight_value.setText(info.get('weight', '0 kg')) # 记录日志 logging.info(f"回显下料信息: 托盘号={info.get('tray_code', '')}, 层数={info.get('tier', '')}") def accept(self): """确认按钮点击事件""" try: # 获取输入的值 tray_code = self.tray_input.text().strip() tier = self.tier_input.text().strip() pallet_type = self.pallet_type_input.currentText().strip() # 验证输入 if not tray_code: QMessageBox.warning(self, "提示", "请输入托盘号") return if not tier: QMessageBox.warning(self, "提示", "请输入层数") return if not pallet_type or pallet_type == "请选择": QMessageBox.warning(self, "提示", "请选择托盘类型") return # 获取托盘类型ID并写入寄存器 pallet_type_id = self.get_current_pallet_type_id() if pallet_type_id is not None: try: modbus = ModbusUtils() client = modbus.get_client() modbus.write_register_until_success(client, 1, int(pallet_type_id)) logging.info(f"已将托盘类型ID {pallet_type_id} 写入寄存器1") except Exception as e: logging.error(f"写入托盘类型ID到寄存器失败: {str(e)}") QMessageBox.critical(self, "Modbus通信错误", f"写入托盘类型ID失败: {str(e)}") # 即使失败也允许继续,但给与提示 finally: if 'modbus' in locals() and client: modbus.close_client(client) else: QMessageBox.warning(self, "提示", "无法获取托盘类型ID,请检查配置") # 保存托盘档案信息 try: pallet_type_manager = PalletTypeManager.get_instance() material = self.material_tier_value.text().strip() pallet_info = {"cc": pallet_type, "cs": tier, "cz": material} pallet_type_manager.save_pallet_info(tray_code, pallet_info, self.user_id) logging.info(f"已保存下料托盘信息: {tray_code}, 层数={tier}, 托盘类型={pallet_type}, 材质={material}") except Exception as e: logging.error(f"保存下料托盘信息失败: {str(e)}") # 调用父类的accept方法关闭对话框,由主窗口处理后续逻辑 super().accept() except Exception as e: logging.error(f"下料对话框确认时发生错误: {str(e)}") QMessageBox.critical(self, "错误", f"确认下料失败: {str(e)}")