From e6c7c3a46ebbe8491f0ad847c2ec13ef89fb5850 Mon Sep 17 00:00:00 2001 From: zhu-mengmeng <15588200382@163.com> Date: Sat, 19 Jul 2025 10:29:10 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E5=BA=93=E6=88=BF?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apis/gc_api.py | 50 +++++++++++- config/app_config.json | 7 +- db/jtDB.db | Bin 172032 -> 180224 bytes ui/main_window_ui.py | 35 ++++++-- widgets/main_window.py | 179 +++++++++++++++++++++++++++++++++++++---- 5 files changed, 242 insertions(+), 29 deletions(-) diff --git a/apis/gc_api.py b/apis/gc_api.py index 626c3ef..f93fd7e 100644 --- a/apis/gc_api.py +++ b/apis/gc_api.py @@ -184,4 +184,52 @@ class GcApi: except Exception as e: logging.error(f"获取订单列表失败: {str(e)}") - return {"status": False, "message": f"获取订单列表失败: {str(e)}"} \ No newline at end of file + return {"status": False, "message": f"获取订单列表失败: {str(e)}"} + + def get_params(self, stype, main, corp_id): + """ + 获取指定参数信息 + + Args: + stype: 参数类型,如"库房档案" + main: 主参数,如"XC" + corp_id: 公司ID + + Returns: + dict: 参数信息列表 + """ + try: + # API 配置中的键名 + api_key = "get_params" + + # 构建GET请求参数 + params = { + "stype": stype, + "main": main, + "corp_id": corp_id + } + + # 发送GET请求 + response = self.api_utils.get(api_key, params=params) + + # 检查响应状态 + if response.get("success", False): + return { + "status": True, + "data": response.get("data", []), + "message": "获取参数信息成功" + } + else: + return { + "status": False, + "data": [], + "message": response.get("message", "获取参数信息失败") + } + + except Exception as e: + logging.error(f"获取参数信息失败: {str(e)}") + return { + "status": False, + "data": [], + "message": f"获取参数信息失败: {str(e)}" + } \ No newline at end of file diff --git a/config/app_config.json b/config/app_config.json index e4f95e2..3b5bbbd 100644 --- a/config/app_config.json +++ b/config/app_config.json @@ -7,8 +7,8 @@ "enable_keyboard_listener": false, "enable_camera": false }, - "base_url": "http://localhost:8084", - "mode": "standalone" + "base_url": "http://localhost:8085", + "mode": "api" }, "apis": { "get_tray_info": "/apjt/xcsc/tpda/getByTp_note/", @@ -16,7 +16,8 @@ "get_order_info": "/jsjt/xcsc/tprk/getXsddBzrkGridListToWsbz.do", "add_order_info": "/jsjt/xcsc/tprk/bzrkAdd01.do", "get_xpack": "/jsjt/xcsc/tprk/getXpackToWsbz.do", - "ismt_option": "/jsjt/xcsc/tprk/ismtOptioTonWsbz.do" + "ismt_option": "/jsjt/xcsc/tprk/ismtOptioTonWsbz.do", + "get_params": "/select/getcombcodeWsbz.do" }, "database": { "default": "sqlite", diff --git a/db/jtDB.db b/db/jtDB.db index bc2709f32907ecf0e4e224f793cb3e928ff127d1..649277a5512c9f0edbb058f03efa4c6e5206b356 100644 GIT binary patch delta 3032 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 Y!RsfbQUyk%O$G_oSC+~bkE5gi1Gdjs*#H0l diff --git a/ui/main_window_ui.py b/ui/main_window_ui.py index 702613a..88811a1 100644 --- a/ui/main_window_ui.py +++ b/ui/main_window_ui.py @@ -9,6 +9,7 @@ from PySide6.QtCore import Qt, QDateTime, QTimer class MainWindowUI(QMainWindow): # 定义字段映射为类属性,方便外部引用 FIELD_MAPPING = { + "库房": "lib", "客户": "customerexp", "规格": "size", "材质": "cz", @@ -348,14 +349,32 @@ class MainWindowUI(QMainWindow): label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) label.setStyleSheet("background-color: #FAFAFA; padding: 5px;") - # 创建值(改为QLineEdit) - value = QLineEdit("") - value.setFont(self.normal_font) - value.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) - value.setStyleSheet("background-color: white; padding: 5px; border: 1px solid #cccccc;") - value.setFrame(False) - value.setContentsMargins(0, 0, 0, 0) - value.setFixedHeight(35) + # 根据字段类型创建不同的值组件 + if field_name == "库房": + # 库房字段使用QComboBox,完全复刻托盘号组件的配置 + value = QComboBox() + value.setFixedHeight(35) + value.setStyleSheet("QComboBox { border: 1px solid #cccccc; padding: 3px; background-color: white; } QComboBox::drop-down { border: none; width: 20px; }") + value.setFont(QFont("微软雅黑", 12)) + value.setEditable(False) # 设置为不可编辑,确保是纯下拉选择 + value.setInsertPolicy(QComboBox.NoInsert) # 不自动插入用户输入到列表中 + value.setMaxVisibleItems(10) # 设置下拉框最多显示10个项目 + # 添加默认选项 + value.addItem("成品库") + value.addItem("退回仓") + value.addItem("散装库") + value.addItem("不合格库(线材)") + value.addItem("废丝库") + value.setCurrentIndex(0) # 默认选择第一个 + else: + # 其他字段使用QLineEdit + value = QLineEdit("") + value.setFont(self.normal_font) + value.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) + value.setStyleSheet("background-color: white; padding: 5px; border: 1px solid #cccccc;") + value.setFrame(False) + value.setContentsMargins(0, 0, 0, 0) + value.setFixedHeight(35) # 保存引用 self.info_labels[field_name] = label diff --git a/widgets/main_window.py b/widgets/main_window.py index 6a5ab13..f37d0ef 100644 --- a/widgets/main_window.py +++ b/widgets/main_window.py @@ -339,6 +339,9 @@ class MainWindow(MainWindowUI): # 加载托盘号列表 self.load_pallet_codes() + # 加载库房数据 + self.load_warehouse_data() + logging.info("显示主页面") def load_pallet_codes(self): @@ -378,6 +381,78 @@ class MainWindow(MainWindowUI): self.tray_edit.clear() self.tray_edit.setCurrentText("") + def load_warehouse_data(self): + """从API加载库房数据并更新到信息表格的库房组件""" + try: + # 获取信息表格中的库房组件 + warehouse_combo = self.info_values.get("库房") + if not warehouse_combo: + logging.warning("未找到库房组件") + return + + # 获取当前选中的库房,以便保留用户选择 + current_warehouse = warehouse_combo.currentText() + + # 清空当前项目 + warehouse_combo.clear() + + # 调用API获取库房数据 + from apis.gc_api import GcApi + gc_api = GcApi() + + # 调用get_params接口获取库房信息 + response = gc_api.get_params("库房档案", "XC", self.corp_id) + + if response.get("status", False): + warehouse_data = response.get("data", []) + + if warehouse_data and len(warehouse_data) > 0: + # 添加库房到下拉框 + for warehouse in warehouse_data: + warehouse_name = warehouse.get("combtext", "") + if warehouse_name: + warehouse_combo.addItem(warehouse_name) + + # 默认选择成品库房 + default_index = warehouse_combo.findText("成品库") + if default_index != -1: + warehouse_combo.setCurrentIndex(default_index) + elif warehouse_combo.count() > 0: + # 如果没有找到成品库,选择第一个 + warehouse_combo.setCurrentIndex(0) + + # 如果有之前的选择,尝试恢复它 + if current_warehouse: + index = warehouse_combo.findText(current_warehouse) + if index != -1: + warehouse_combo.setCurrentIndex(index) + + logging.info(f"已加载库房数据,共 {len(warehouse_data)} 个") + else: + logging.warning("未找到库房数据,库房列表将为空") + else: + logging.error(f"获取库房数据失败: {response.get('message', '未知错误')}") + # 如果API调用失败,添加默认选项 + warehouse_combo.addItem("成品库") + warehouse_combo.addItem("退回仓") + warehouse_combo.addItem("散装库") + warehouse_combo.addItem("不合格库(线材)") + warehouse_combo.addItem("废丝库") + warehouse_combo.setCurrentIndex(0) + + except Exception as e: + logging.error(f"加载库房数据失败: {str(e)}") + # 如果加载失败,添加默认选项 + warehouse_combo = self.info_values.get("库房") + if warehouse_combo: + warehouse_combo.clear() + warehouse_combo.addItem("成品库") + warehouse_combo.addItem("退回仓") + warehouse_combo.addItem("散装库") + warehouse_combo.addItem("不合格库(线材)") + warehouse_combo.addItem("废丝库") + warehouse_combo.setCurrentIndex(0) + def show_settings_page(self): """显示设置页面""" # 创建设置窗口 @@ -741,12 +816,23 @@ class MainWindow(MainWindowUI): order_info = {} for field_name, label in self.info_values.items(): order_info_key = self.FIELD_MAPPING.get(field_name) - if order_info_key: - # 根据控件类型选择合适的方法获取文本 - if isinstance(label, QTextEdit): - order_info[order_info_key] = label.toPlainText() - else: - order_info[order_info_key] = label.text() + if order_info_key and label is not None: + try: + # 根据控件类型选择合适的方法获取文本 + if isinstance(label, QTextEdit): + order_info[order_info_key] = label.toPlainText() + elif isinstance(label, QComboBox): + order_info[order_info_key] = label.currentText() + else: + order_info[order_info_key] = label.text() + except RuntimeError as e: + # 如果对象已被删除,记录错误并跳过 + logging.warning(f"控件对象已被删除,字段: {field_name}, 错误: {str(e)}") + continue + except Exception as e: + # 其他异常也记录并跳过 + logging.warning(f"获取控件文本失败,字段: {field_name}, 错误: {str(e)}") + continue # 更新/补充 qd 字段 order_info["qd"] = self._current_gc_qd # 再调用 update_info_table @@ -1998,6 +2084,12 @@ class MainWindow(MainWindowUI): info['pono'] = self._current_order_code info["dycz"] = info.get("cz") info['qd'] = self._current_gc_qd + # 添加库房信息 + warehouse_combo = self.info_values.get("库房") + if warehouse_combo: + info['lib'] = warehouse_combo.currentText() + else: + info['lib'] = "成品库" # 默认值 # 获取本机IP地址 # import socket # try: @@ -3563,29 +3655,82 @@ class MainWindow(MainWindowUI): # 记录 order_info 中的所有键,用于调试 logging.debug(f"订单信息键: {list(order_info.keys())}") - # 更新表格内容 + # 更新表格内容 - 智能更新:已有就更新,没有就新增,空值不覆盖 for field_name, field_key in field_mapping.items(): - if field_name in self.info_values: - value = "" - # 对可能存在的键进行安全检查 + if field_name in self.info_values and self.info_values[field_name] is not None: + try: + # 获取当前控件中的值 + current_value = "" + if isinstance(self.info_values[field_name], QTextEdit): + current_value = self.info_values[field_name].toPlainText() + elif isinstance(self.info_values[field_name], QComboBox): + current_value = self.info_values[field_name].currentText() + else: + current_value = self.info_values[field_name].text() + except RuntimeError as e: + # 如果对象已被删除,记录错误并跳过 + logging.warning(f"控件对象已被删除,字段: {field_name}, 错误: {str(e)}") + continue + except Exception as e: + # 其他异常也记录并跳过 + logging.warning(f"获取控件文本失败,字段: {field_name}, 错误: {str(e)}") + continue + + # 获取API返回的新值 + new_value = "" if field_key and field_key in order_info: - value = str(order_info[field_key]) + new_value = str(order_info[field_key]) + # 特殊处理线径公差 if field_name == "线径公差" and "bccd" in order_info and "tccd" in order_info: bccd = order_info.get("bccd") tccd = order_info.get("tccd") if bccd is not None and tccd is not None: - value = f"{bccd} - {tccd}" + new_value = f"{bccd} - {tccd}" + + # 特殊处理强度范围 if field_name == "强度范围" and "bqd" in order_info and "tqd" in order_info: bqd = order_info.get("bqd") tqd = order_info.get("tqd") if bqd is not None and tqd is not None: - value = f"{bqd} - {tqd}" - # 根据控件类型选择合适的方法设置文本 - if isinstance(self.info_values[field_name], QTextEdit): - self.info_values[field_name].setPlainText(value) + new_value = f"{bqd} - {tqd}" + + # 智能更新逻辑:如果新值不为空且与当前值不同,则更新;如果新值为空但当前值不为空,则保持当前值 + if new_value and new_value != current_value: + # 有新值且与当前值不同,进行更新 + try: + if isinstance(self.info_values[field_name], QTextEdit): + self.info_values[field_name].setPlainText(new_value) + elif isinstance(self.info_values[field_name], QComboBox): + # 对于QComboBox,尝试找到匹配的选项并设置 + combo = self.info_values[field_name] + index = combo.findText(new_value) + if index != -1: + combo.setCurrentIndex(index) + else: + # 如果没找到匹配的选项,添加新选项 + combo.addItem(new_value) + combo.setCurrentText(new_value) + else: + self.info_values[field_name].setText(new_value) + logging.debug(f"更新字段 '{field_name}': '{current_value}' -> '{new_value}'") + except RuntimeError as e: + # 如果对象已被删除,记录错误并跳过 + logging.warning(f"控件对象已被删除,无法更新字段: {field_name}, 错误: {str(e)}") + continue + except Exception as e: + # 其他异常也记录并跳过 + logging.warning(f"更新控件文本失败,字段: {field_name}, 错误: {str(e)}") + continue + elif not new_value and current_value: + # 新值为空但当前值不为空,保持当前值 + logging.debug(f"保持字段 '{field_name}' 的当前值: '{current_value}' (API返回空值)") + elif not new_value and not current_value: + # 新值和当前值都为空,无需操作 + logging.debug(f"字段 '{field_name}' 新值和当前值都为空,无需更新") else: - self.info_values[field_name].setText(value) + # 新值与当前值相同,无需更新 + logging.debug(f"字段 '{field_name}' 值未变化: '{current_value}'") else: logging.warning(f"字段名 '{field_name}' 在info_values中不存在")