diff --git a/apis/gc_api.py b/apis/gc_api.py index 88e74e4..10b951d 100644 --- a/apis/gc_api.py +++ b/apis/gc_api.py @@ -254,4 +254,53 @@ class GcApi: "status": False, "data": [], "message": f"获取线材类型参数失败: {str(e)}" - } \ No newline at end of file + } + + def get_luno_list(self, params): + """ + 获取炉号列表 + + Args: + params: 查询参数字典,包含: + - srch_rq1: 开始日期 + - srch_rq2: 结束日期 + - luono: 炉号 + - cz: 材质 + - gg: 规格 + - gc: 钢厂 + - corp_id: 公司ID + + Returns: + dict: 炉号列表 + """ + try: + # API 配置中的键名 + api_key = "get_luno" + + # 构建查询参数 + luno_dict = { + "srch_rq1": params.get("srch_rq1", ""), + "srch_rq2": params.get("srch_rq2", ""), + "luono": params.get("luono", ""), + "cz": params.get("cz", ""), + "gg": params.get("gg", ""), + "gc": params.get("gc", ""), + "data_corp": params.get("corp_id", "") + } + + # 构建 form-data 格式的数据 + data = { + "parms": json.dumps(luno_dict), # 必须将数据序列化为JSON字符串 + "pageIndex": 0, + "pageSize": 50, # 获取更多数据 + "sortField": "create_time", + "sortOrder": "desc" + } + + # 调用API + response = self.api_utils.post(api_key, data=data) + return response + + except Exception as e: + logging.error(f"获取炉号列表失败: {str(e)}") + return {"status": False, "message": f"获取炉号列表失败: {str(e)}"} \ No newline at end of file diff --git a/config/app_config.json b/config/app_config.json index 3b5bbbd..36bc314 100644 --- a/config/app_config.json +++ b/config/app_config.json @@ -17,7 +17,8 @@ "add_order_info": "/jsjt/xcsc/tprk/bzrkAdd01.do", "get_xpack": "/jsjt/xcsc/tprk/getXpackToWsbz.do", "ismt_option": "/jsjt/xcsc/tprk/ismtOptioTonWsbz.do", - "get_params": "/select/getcombcodeWsbz.do" + "get_params": "/select/getcombcodeWsbz.do", + "get_luno": "/common/luno/getLunoListWsbz.do" }, "database": { "default": "sqlite", diff --git a/dao/inspection_dao.py b/dao/inspection_dao.py index bd6b24c..bfee744 100644 --- a/dao/inspection_dao.py +++ b/dao/inspection_dao.py @@ -970,4 +970,145 @@ class InspectionDAO: 'order_num_month': 0, 'order_num_year': 0, 'order_num_all': 0 - } \ No newline at end of file + } + + def save_luno_info(self, luno_code, luno_data): + """保存炉号信息到数据库 + + Args: + luno_code: 炉号编码 + luno_data: 炉号数据字典 + + Returns: + bool: 保存是否成功 + """ + try: + current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + + # 检查是否已存在该炉号 + check_sql = "SELECT id FROM wsbz_luno_info WHERE luono = ?" + with SQLUtils('sqlite') as db: + db.cursor.execute(check_sql, (luno_code,)) + existing = db.cursor.fetchone() + + if existing: + # 更新现有记录 + update_sql = """ + UPDATE wsbz_luno_info SET + cz = ?, gg = ?, gc = ?, bz = ?, data_corp = ?, data_corp_name = ?, + c = ?, si = ?, mn = ?, p = ?, s = ?, ni = ?, cr = ?, ti = ?, mo = ?, cu = ?, + others = ?, klqd = ?, ysl = ?, rq = ?, update_time = ?, update_by = ? + WHERE luono = ? + """ + params = ( + luno_data.get('cz', ''), + luno_data.get('gg', ''), + luno_data.get('gc', ''), + luno_data.get('bz', ''), + luno_data.get('data_corp', ''), + luno_data.get('data_corp_name', ''), + luno_data.get('c', ''), + luno_data.get('si', ''), + luno_data.get('mn', ''), + luno_data.get('p', ''), + luno_data.get('s', ''), + luno_data.get('ni', ''), + luno_data.get('cr', ''), + luno_data.get('ti', ''), + luno_data.get('mo', ''), + luno_data.get('cu', ''), + luno_data.get('others', ''), + luno_data.get('klqd', ''), + luno_data.get('ysl', ''), + luno_data.get('rq', ''), + current_time, + luno_data.get('user_name', 'system'), + luno_code + ) + db.cursor.execute(update_sql, params) + else: + # 插入新记录 + insert_sql = """ + INSERT INTO wsbz_luno_info ( + luono, cz, gg, gc, bz, data_corp, data_corp_name, + c, si, mn, p, s, ni, cr, ti, mo, cu, others, klqd, ysl, rq, + create_time, create_by, update_time, update_by + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """ + params = ( + luno_code, + luno_data.get('cz', ''), + luno_data.get('gg', ''), + luno_data.get('gc', ''), + luno_data.get('bz', ''), + luno_data.get('data_corp', ''), + luno_data.get('data_corp_name', ''), + luno_data.get('c', ''), + luno_data.get('si', ''), + luno_data.get('mn', ''), + luno_data.get('p', ''), + luno_data.get('s', ''), + luno_data.get('ni', ''), + luno_data.get('cr', ''), + luno_data.get('ti', ''), + luno_data.get('mo', ''), + luno_data.get('cu', ''), + luno_data.get('others', ''), + luno_data.get('klqd', ''), + luno_data.get('ysl', ''), + luno_data.get('rq', ''), + current_time, + luno_data.get('user_name', 'system'), + current_time, + luno_data.get('user_name', 'system') + ) + db.cursor.execute(insert_sql, params) + + db.connection.commit() + + logging.info(f"成功保存炉号信息: {luno_code}") + return True + + except Exception as e: + logging.error(f"保存炉号信息失败: {str(e)}") + return False + + def get_luno_info(self, luno_code): + """根据炉号获取炉号信息 + + Args: + luno_code: 炉号编码 + + Returns: + dict: 炉号信息字典,未找到返回None + """ + try: + sql = """ + SELECT luono, cz, gg, gc, bz, data_corp, data_corp_name, + c, si, mn, p, s, ni, cr, ti, mo, cu, others, klqd, ysl, rq, + create_time, create_by, update_time, update_by + FROM wsbz_luno_info + WHERE luono = ? AND is_deleted = FALSE + """ + + with SQLUtils('sqlite') as db: + db.cursor.execute(sql, (luno_code,)) + row = db.cursor.fetchone() + + if row: + # 获取列名 + column_names = [desc[0] for desc in db.cursor.description] + + # 转换为字典 + luno_info = {} + for i, value in enumerate(row): + if i < len(column_names): + luno_info[column_names[i]] = value + + return luno_info + else: + return None + + except Exception as e: + logging.error(f"获取炉号信息失败: {str(e)}") + return None \ No newline at end of file diff --git a/data/inspection.db b/data/inspection.db new file mode 100644 index 0000000..2249470 Binary files /dev/null and b/data/inspection.db differ diff --git a/db/jtDB.db b/db/jtDB.db index 80a0324..5706bfa 100644 Binary files a/db/jtDB.db and b/db/jtDB.db differ diff --git a/db/schema.sql b/db/schema.sql index 5f27921..2ac7bf5 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -161,4 +161,36 @@ CREATE TABLE IF NOT EXISTS packaging_record ( create_by VARCHAR(50) NOT NULL, update_time TIMESTAMP, update_by VARCHAR(50) +); + +-- 创建炉号信息表 +CREATE TABLE IF NOT EXISTS wsbz_luno_info ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + luono VARCHAR(50) NOT NULL, -- 炉号 + cz VARCHAR(50), -- 材质 + gg VARCHAR(50), -- 规格 + gc VARCHAR(50), -- 钢厂 + bz VARCHAR(50), -- 标准 + data_corp VARCHAR(50), -- 公司账套 + data_corp_name VARCHAR(100), -- 公司账套名称 + c VARCHAR(20), -- C含量 + si VARCHAR(20), -- Si含量 + mn VARCHAR(20), -- Mn含量 + p VARCHAR(20), -- P含量 + s VARCHAR(20), -- S含量 + ni VARCHAR(20), -- Ni含量 + cr VARCHAR(20), -- Cr含量 + ti VARCHAR(20), -- Ti含量 + mo VARCHAR(20), -- Mo含量 + cu VARCHAR(20), -- Cu含量 + others VARCHAR(100), -- 其他元素 + klqd VARCHAR(50), -- 抗拉强度 + ysl VARCHAR(50), -- 延伸率 + rq VARCHAR(50), -- 日期 + create_time TIMESTAMP NOT NULL, + create_by VARCHAR(50) NOT NULL, + update_time TIMESTAMP, + update_by VARCHAR(50), + is_deleted BOOLEAN DEFAULT FALSE, + UNIQUE(luono, is_deleted) -- 确保炉号唯一 ); \ No newline at end of file diff --git a/ui/luno_query_dialog_ui.py b/ui/luno_query_dialog_ui.py new file mode 100644 index 0000000..52d2677 --- /dev/null +++ b/ui/luno_query_dialog_ui.py @@ -0,0 +1,347 @@ +from PySide6.QtWidgets import ( + QDialog, QLabel, QLineEdit, QComboBox, QPushButton, + QVBoxLayout, QHBoxLayout, QFrame, QTableWidget, QTableWidgetItem, + QHeaderView, QDateEdit, QApplication +) +from PySide6.QtCore import Qt, QDate +from PySide6.QtGui import QFont + +class LunoQueryDialogUI(QDialog): + def __init__(self): + super().__init__() + self.setWindowTitle("炉号查询") + self.resize(1200, 600) # 调整宽度和高度 + + # 设置字体 + self.normal_font = QFont("微软雅黑", 10) + self.title_font = QFont("微软雅黑", 10, QFont.Bold) + + # 初始化UI + self.init_ui() + + def init_ui(self): + """初始化UI""" + # 主布局 + self.main_layout = QVBoxLayout(self) + self.main_layout.setContentsMargins(20, 20, 20, 20) + self.main_layout.setSpacing(10) + + # 创建查询条件区域 + self.create_query_frame() + + # 创建结果表格 + self.create_result_table() + + # 创建按钮 + self.create_buttons() + + def create_query_frame(self): + """创建查询条件区域""" + # 创建一个带边框的容器 + query_frame = QFrame() + query_frame.setStyleSheet(""" + QFrame { + border: 1px solid #e0e0e0; + background-color: white; + border-radius: 4px; + } + """) + + # 容器的垂直布局 + query_layout = QVBoxLayout(query_frame) + query_layout.setContentsMargins(15, 15, 15, 15) + query_layout.setSpacing(10) + + # 第一行:日期范围和炉号 + row1 = QHBoxLayout() + + # 日期标签 + date_label = QLabel("日期:") + date_label.setFont(self.normal_font) + date_label.setFixedWidth(40) + + # 开始日期 + self.start_date = QDateEdit() + self.start_date.setFont(self.normal_font) + self.start_date.setCalendarPopup(True) + self.start_date.setDate(QDate.currentDate().addDays(-7)) + self.start_date.setFixedWidth(120) + self.start_date.setStyleSheet(""" + QDateEdit { + border: 1px solid #e0e0e0; + padding: 4px; + border-radius: 4px; + } + """) + + # 至标签 + to_label = QLabel("至:") + to_label.setFont(self.normal_font) + to_label.setFixedWidth(20) + + # 结束日期 + self.end_date = QDateEdit() + self.end_date.setFont(self.normal_font) + self.end_date.setCalendarPopup(True) + self.end_date.setDate(QDate.currentDate()) + self.end_date.setFixedWidth(120) + self.end_date.setStyleSheet(""" + QDateEdit { + border: 1px solid #e0e0e0; + padding: 4px; + border-radius: 4px; + } + """) + + # 炉号标签 + luno_label = QLabel("炉号:") + luno_label.setFont(self.normal_font) + luno_label.setFixedWidth(50) + + # 炉号输入框 + self.luno_input = QLineEdit() + self.luno_input.setFont(self.normal_font) + self.luno_input.setStyleSheet(""" + QLineEdit { + border: 1px solid #e0e0e0; + padding: 4px; + border-radius: 4px; + } + QLineEdit:focus { + border: 1px solid #66afe9; + } + """) + + # 材质标签 + material_label = QLabel("材质") + material_label.setFont(self.normal_font) + material_label.setFixedWidth(40) + + # 材质下拉框 + self.material_combo = QComboBox() + self.material_combo.setFont(self.normal_font) + self.material_combo.addItem("全部") + self.material_combo.setStyleSheet(""" + QComboBox { + border: 1px solid #e0e0e0; + padding: 4px; + border-radius: 4px; + } + QComboBox::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 20px; + border-left: 1px solid #e0e0e0; + } + """) + + # 规格标签 + spec_label = QLabel("规格") + spec_label.setFont(self.normal_font) + spec_label.setFixedWidth(40) + + # 规格输入框 + self.spec_input = QLineEdit() + self.spec_input.setFont(self.normal_font) + self.spec_input.setStyleSheet(""" + QLineEdit { + border: 1px solid #e0e0e0; + padding: 4px; + border-radius: 4px; + } + QLineEdit:focus { + border: 1px solid #66afe9; + } + """) + + # 钢厂标签 + steel_label = QLabel("钢厂") + steel_label.setFont(self.normal_font) + steel_label.setFixedWidth(40) + + # 钢厂输入框 + self.steel_input = QLineEdit() + self.steel_input.setFont(self.normal_font) + self.steel_input.setStyleSheet(""" + QLineEdit { + border: 1px solid #e0e0e0; + padding: 4px; + border-radius: 4px; + } + QLineEdit:focus { + border: 1px solid #66afe9; + } + """) + + # 查询按钮 + self.query_button = QPushButton("查询") + self.query_button.setFont(self.normal_font) + self.query_button.setStyleSheet(""" + QPushButton { + background-color: #0078d4; + color: white; + border: none; + border-radius: 4px; + padding: 6px 16px; + } + QPushButton:hover { + background-color: #106ebe; + } + QPushButton:pressed { + background-color: #005a9e; + } + """) + self.query_button.setFixedWidth(80) + + # 添加组件到第一行布局 + row1.addWidget(date_label) + row1.addWidget(self.start_date) + row1.addWidget(to_label) + row1.addWidget(self.end_date) + row1.addSpacing(20) + row1.addWidget(luno_label) + row1.addWidget(self.luno_input, 1) + row1.addSpacing(20) + row1.addWidget(material_label) + row1.addWidget(self.material_combo, 1) + row1.addSpacing(20) + row1.addWidget(spec_label) + row1.addWidget(self.spec_input, 1) + row1.addSpacing(20) + row1.addWidget(steel_label) + row1.addWidget(self.steel_input, 1) + row1.addSpacing(20) + row1.addWidget(self.query_button) + + # 添加第一行到查询布局 + query_layout.addLayout(row1) + + # 将查询框架添加到主布局 + self.main_layout.addWidget(query_frame) + + def create_result_table(self): + """创建结果表格""" + # 创建表格 + self.result_table = QTableWidget() + self.result_table.setFont(self.normal_font) + + # 设置表头样式 + header = self.result_table.horizontalHeader() + header.setStyleSheet(""" + QHeaderView::section { + background-color: #f5f5f5; + color: #333333; + padding: 5px; + border: 1px solid #e0e0e0; + font-weight: bold; + } + """) + + # 设置表格样式 + self.result_table.setStyleSheet(""" + QTableWidget { + border: 1px solid #e0e0e0; + gridline-color: #e0e0e0; + selection-background-color: #0078d4; + selection-color: white; + } + QTableWidget::item { + padding: 5px; + border-bottom: 1px solid #e0e0e0; + } + """) + + # 启用水平滚动条 + self.result_table.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) + + # 设置表头固定宽度模式,确保所有列都能显示 + header.setSectionResizeMode(QHeaderView.Fixed) + + # 设置表格最小宽度,确保有足够空间显示滚动条 + self.result_table.setMinimumWidth(800) + + # 设置默认列宽 + self.result_table.setColumnWidth(0, 60) # 序号 + self.result_table.setColumnWidth(1, 100) # 日期 + self.result_table.setColumnWidth(2, 120) # 炉号 + self.result_table.setColumnWidth(3, 100) # 材质 + self.result_table.setColumnWidth(4, 100) # 规格 + self.result_table.setColumnWidth(5, 100) # 钢厂 + self.result_table.setColumnWidth(6, 80) # 标准 + self.result_table.setColumnWidth(7, 100) # 公司账套 + self.result_table.setColumnWidth(8, 60) # C + self.result_table.setColumnWidth(9, 60) # Si + self.result_table.setColumnWidth(10, 60) # Mn + self.result_table.setColumnWidth(11, 60) # P + self.result_table.setColumnWidth(12, 60) # S + self.result_table.setColumnWidth(13, 60) # Ni + self.result_table.setColumnWidth(14, 60) # Cr + self.result_table.setColumnWidth(15, 60) # Ti + self.result_table.setColumnWidth(16, 60) # Mo + self.result_table.setColumnWidth(17, 60) # Cu + self.result_table.setColumnWidth(18, 80) # 其他 + self.result_table.setColumnWidth(19, 100) # 抗拉强度 + self.result_table.setColumnWidth(20, 80) # 延伸率 + + # 设置表格可以选择整行 + self.result_table.setSelectionBehavior(QTableWidget.SelectRows) + + # 设置表格只能单选 + self.result_table.setSelectionMode(QTableWidget.SingleSelection) + + # 添加表格到主布局 + self.main_layout.addWidget(self.result_table, 1) # 1表示拉伸因子,让表格占据更多空间 + + def create_buttons(self): + """创建底部按钮""" + button_layout = QHBoxLayout() + + # 确认和取消按钮 + self.confirm_button = QPushButton("确认") + self.confirm_button.setFont(self.normal_font) + self.confirm_button.setStyleSheet(""" + QPushButton { + background-color: #0078d4; + color: white; + border: none; + border-radius: 4px; + padding: 8px 16px; + font-weight: bold; + } + QPushButton:hover { + background-color: #106ebe; + } + QPushButton:pressed { + background-color: #005a9e; + } + """) + self.confirm_button.setFixedSize(100, 35) + + self.cancel_button = QPushButton("取消") + self.cancel_button.setFont(self.normal_font) + self.cancel_button.setStyleSheet(""" + QPushButton { + background-color: white; + color: #333333; + border: 1px solid #e0e0e0; + border-radius: 4px; + padding: 8px 16px; + font-weight: bold; + } + QPushButton:hover { + background-color: #f5f5f5; + } + QPushButton:pressed { + background-color: #e0e0e0; + } + """) + self.cancel_button.setFixedSize(100, 35) + + # 添加按钮到布局 + button_layout.addStretch() + button_layout.addWidget(self.confirm_button) + button_layout.addSpacing(30) # 添加30px的间距 + button_layout.addWidget(self.cancel_button) + + # 添加按钮布局到主布局 + self.main_layout.addLayout(button_layout) \ No newline at end of file diff --git a/ui/main_window_ui.py b/ui/main_window_ui.py index 04807f1..6aa707f 100644 --- a/ui/main_window_ui.py +++ b/ui/main_window_ui.py @@ -384,6 +384,51 @@ class MainWindowUI(QMainWindow): # 添加默认选项(后续会从API动态加载) value.addItem("请选择") value.setCurrentIndex(0) # 默认选择第一个 + elif field_name == "炉号": + # 炉号字段使用QLineEdit + 查询按钮,复刻订单号的逻辑 + + # 创建水平布局容器 + value_container = QWidget() + value_layout = QHBoxLayout(value_container) + value_layout.setContentsMargins(0, 0, 0, 0) + value_layout.setSpacing(0) + + # 创建输入框 + value = QLineEdit("") + value.setFont(self.normal_font) + value.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) + value.setStyleSheet("background-color: white; padding: 5px; border: 1px solid #cccccc; border-right: none;") + value.setFixedHeight(35) + + # 创建查询按钮 + query_button = QPushButton("...") + query_button.setFont(self.normal_font) + query_button.setFixedSize(35, 35) + query_button.setStyleSheet(""" + QPushButton { + border: 1px solid #cccccc; + border-left: none; + background-color: #f5f5f5; + color: #333333; + font-weight: bold; + } + QPushButton:hover { + background-color: #e0e0e0; + } + QPushButton:pressed { + background-color: #d0d0d0; + } + """) + + # 添加到布局 + value_layout.addWidget(value) + value_layout.addWidget(query_button) + + # 保存按钮引用,以便后续连接信号 + self.luno_query_button = query_button + + # 将容器作为值组件 + value = value_container elif field_name == "包装方式": # 包装方式字段使用QLineEdit,与其他字段保持一致 value = QLineEdit("") diff --git a/widgets/luno_query_dialog.py b/widgets/luno_query_dialog.py new file mode 100644 index 0000000..af8f446 --- /dev/null +++ b/widgets/luno_query_dialog.py @@ -0,0 +1,413 @@ +import logging +from datetime import datetime +from PySide6.QtWidgets import QTableWidgetItem, QMessageBox +from PySide6.QtCore import Qt, Signal +from ui.luno_query_dialog_ui import LunoQueryDialogUI +from utils.sql_utils import SQLUtils +from utils.app_mode import AppMode +from apis.gc_api import GcApi + +class LunoQueryDialog(LunoQueryDialogUI): + """炉号查询对话框,用于查询炉号信息""" + + # 定义信号,用于向上传递选中的炉号信息 + luno_selected = Signal(dict) + + def __init__(self, parent=None): + super().__init__() + + # 存储查询结果 + self.query_results = [] + + # 获取父窗口的用户信息 + self.corp_id = None + self.user_id = None + self.user_name = None + if parent: + if hasattr(parent, 'corp_id'): + self.corp_id = parent.corp_id + if hasattr(parent, 'user_id'): + self.user_id = parent.user_id[0] if isinstance(parent.user_id, tuple) else parent.user_id + if hasattr(parent, 'user_name'): + self.user_name = parent.user_name + + # 连接信号和槽 + self.connect_signals() + + def connect_signals(self): + """连接信号和槽""" + # 查询按钮点击事件 + self.query_button.clicked.connect(self.on_luno_query) + + # 确认按钮点击事件 + self.confirm_button.clicked.connect(self.on_confirm) + + # 取消按钮点击事件 + self.cancel_button.clicked.connect(self.reject) + + # 表格双击事件 + self.result_table.cellDoubleClicked.connect(self.on_table_double_clicked) + + def on_luno_query(self): + """执行炉号查询""" + try: + # 获取查询参数 + start_date = self.start_date.date().toString("yyyy-MM-dd") + end_date = self.end_date.date().toString("yyyy-MM-dd") + luno = self.luno_input.text().strip() + material = self.material_combo.currentText() + if material == "全部": + material = "" + spec = self.spec_input.text().strip() + steel = self.steel_input.text().strip() + + # 构建查询参数 + query_params = { + "srch_rq1": start_date, + "srch_rq2": end_date, + "luono": luno, + "cz": material, + "gg": spec, + "gc": steel, + "corp_id": self.corp_id + } + + # 执行查询 + results = self.query_lunos(query_params) + + # 更新表格 + self.update_result_table(results) + + except Exception as e: + logging.error(f"炉号查询失败: {e}") + QMessageBox.critical(self, "查询错误", f"查询炉号时发生错误: {str(e)}") + + def query_lunos(self, params): + """查询炉号数据 + + Args: + params: 查询参数字典 + + Returns: + list: 炉号数据列表 + """ + try: + # 如果是API模式,优先从接口获取数据 + if AppMode.is_api(): + return self._query_lunos_from_api(params) + else: + return self._query_lunos_from_db(params) + + except Exception as e: + logging.error(f"查询炉号数据失败: {e}") + raise + + def _query_lunos_from_api(self, params): + """从API获取炉号数据 + + Args: + params: 查询参数字典 + + Returns: + list: 炉号数据列表 + """ + try: + # 调用接口 + gc_api = GcApi() + + # 调用接口查询炉号列表 + response = gc_api.get_luno_list(params) + + # 处理接口返回结果 - 接口直接返回数据列表 + if response and isinstance(response, list): + # 接口直接返回炉号数据列表 + lunos_data = response + results = [] + + for luno_data in lunos_data: + # 转换为统一格式的字典,处理接口返回的实际字段 + luno_dict = { + "luono": luno_data.get("luono", ""), + "cz": luno_data.get("cz", ""), + "gg": luno_data.get("gg", ""), + "gc": luno_data.get("gc", ""), + "bz": luno_data.get("bz", ""), + "data_corp": luno_data.get("data_corp", ""), + "data_corp_name": luno_data.get("data_corp_name", ""), + "c": luno_data.get("c", ""), + "si": luno_data.get("si", ""), + "mn": luno_data.get("mn", ""), + "p": luno_data.get("p", ""), + "s": luno_data.get("s", ""), + "ni": luno_data.get("ni", ""), + "cr": luno_data.get("cr", ""), + "ti": luno_data.get("ti", ""), + "mo": luno_data.get("mo", ""), + "cu": luno_data.get("cu", ""), + "others": luno_data.get("others", ""), + "klqd": luno_data.get("klqd", ""), + "ysl": luno_data.get("ysl", ""), + "rq": luno_data.get("rq", "") + } + + # 处理null值,转换为空字符串 + for key, value in luno_dict.items(): + if value is None: + luno_dict[key] = "" + + results.append(luno_dict) + + # 保存查询结果 + self.query_results = results + + # 如果接口查询到数据,则保存到数据库中 + if results: + self._save_lunos_to_db(results) + + return results + else: + # 如果接口返回的不是列表或为空,则尝试从数据库查询 + logging.warning("从API获取炉号数据失败或返回格式不正确,尝试从数据库查询") + return self._query_lunos_from_db(params) + + except Exception as e: + logging.error(f"从API获取炉号数据失败: {e}") + # 如果接口查询失败,则尝试从数据库查询 + logging.warning("从API获取炉号数据失败,尝试从数据库查询") + return self._query_lunos_from_db(params) + + def _save_lunos_to_db(self, lunos): + """将炉号数据保存到数据库 + + Args: + lunos: 炉号数据列表 + """ + try: + # 导入DAO + from dao.inspection_dao import InspectionDAO + inspection_dao = InspectionDAO() + + # 遍历炉号数据,保存到数据库 + for luno_data in lunos: + luno_code = luno_data.get("luono", "") + if luno_code: + # 设置用户信息 + if self.user_id: + luno_data['user_id'] = self.user_id + if self.user_name: + luno_data['user_name'] = self.user_name + if self.corp_id: + luno_data['data_corp'] = self.corp_id + + # 保存炉号信息 + inspection_dao.save_luno_info(luno_code, luno_data) + + logging.info(f"成功保存{len(lunos)}条炉号数据到数据库") + + except Exception as e: + logging.error(f"保存炉号数据到数据库失败: {e}") + + def _query_lunos_from_db(self, params): + """从数据库获取炉号数据 + + Args: + params: 查询参数字典 + + Returns: + list: 炉号数据列表 + """ + # 构建SQL查询 + sql = """ + SELECT + l.luono, l.cz, l.gg, l.gc, l.bz, l.data_corp, l.data_corp_name, + l.c, l.si, l.mn, l.p, l.s, l.ni, l.cr, l.ti, l.mo, l.cu, l.others, + l.klqd, l.ysl, l.create_time as rq + FROM wsbz_luno_info l + WHERE 1=1 + """ + + query_params = [] + + # 添加查询条件 + if params.get("srch_rq1") and params.get("srch_rq2"): + sql += " AND l.create_time BETWEEN ? AND ?" + query_params.append(params["srch_rq1"] + " 00:00:00") + query_params.append(params["srch_rq2"] + " 23:59:59") + + if params.get("luono"): + sql += " AND l.luono LIKE ?" + query_params.append(f"%{params['luono']}%") + + if params.get("cz"): + sql += " AND l.cz = ?" + query_params.append(params["cz"]) + + if params.get("gg"): + sql += " AND l.gg LIKE ?" + query_params.append(f"%{params['gg']}%") + + if params.get("gc"): + sql += " AND l.gc LIKE ?" + query_params.append(f"%{params['gc']}%") + + # 添加排序 + sql += " ORDER BY l.create_time DESC" + + # 执行查询 + with SQLUtils('sqlite') as db: + db.execute_query(sql, query_params) + rows = db.fetchall() + + # 处理查询结果 + results = [] + for row in rows: + # 将元组转换为字典 + luno_data = { + "luono": row[0], + "cz": row[1], + "gg": row[2], + "gc": row[3], + "bz": row[4], + "data_corp": row[5], + "data_corp_name": row[6], + "c": row[7], + "si": row[8], + "mn": row[9], + "p": row[10], + "s": row[11], + "ni": row[12], + "cr": row[13], + "ti": row[14], + "mo": row[15], + "cu": row[16], + "others": row[17], + "klqd": row[18], + "ysl": row[19], + "rq": row[20] + } + results.append(luno_data) + + # 保存查询结果 + self.query_results = results + + return results + + def update_result_table(self, results): + """更新结果表格 + + Args: + results: 炉号数据列表 + """ + # 清空表格 + self.result_table.setRowCount(0) + + if not results: + return + + # 定义表头和对应的字段名 + columns = [ + {"title": "序号", "field": None}, + {"title": "日期", "field": "rq"}, + {"title": "炉号", "field": "luono"}, + {"title": "材质", "field": "cz"}, + {"title": "规格", "field": "gg"}, + {"title": "钢厂", "field": "gc"}, + {"title": "标准", "field": "bz"}, + {"title": "公司账套", "field": "data_corp_name"}, + {"title": "C", "field": "c"}, + {"title": "Si", "field": "si"}, + {"title": "Mn", "field": "mn"}, + {"title": "P", "field": "p"}, + {"title": "S", "field": "s"}, + {"title": "Ni", "field": "ni"}, + {"title": "Cr", "field": "cr"}, + {"title": "Ti", "field": "ti"}, + {"title": "Mo", "field": "mo"}, + {"title": "Cu", "field": "cu"}, + {"title": "其他", "field": "others"}, + {"title": "抗拉强度", "field": "klqd"}, + {"title": "延伸率", "field": "ysl"} + ] + + # 设置表头 + self.result_table.setColumnCount(len(columns)) + header_labels = [col["title"] for col in columns] + self.result_table.setHorizontalHeaderLabels(header_labels) + + # 设置行数 + self.result_table.setRowCount(len(results)) + + # 填充数据 + for row, luno_data in enumerate(results): + # 序号 + item_index = QTableWidgetItem(str(row + 1)) + item_index.setTextAlignment(Qt.AlignCenter) + self.result_table.setItem(row, 0, item_index) + + # 遍历列,填充数据 + for col_idx, column in enumerate(columns[1:], 1): # 从1开始,跳过序号列 + field = column["field"] + if field: + value = "" + + # 特殊处理某些字段 + if field == "rq": + create_time = luno_data.get(field, "") + if create_time: + try: + # 尝试解析日期时间字符串,支持多种格式 + if " " in create_time: + # 包含时间的格式:2025-07-09 10:30:00 + dt = datetime.strptime(create_time, "%Y-%m-%d %H:%M:%S") + value = dt.strftime("%Y-%m-%d") + else: + # 只有日期的格式:2025-07-09 + dt = datetime.strptime(create_time, "%Y-%m-%d") + value = dt.strftime("%Y-%m-%d") + except: + # 如果解析失败,直接使用原值 + value = create_time + else: + # 其他普通字段 + value = str(luno_data.get(field, "")) + + # 创建表格项并设置文本 + item = QTableWidgetItem(value) + + # 居中对齐特定的列 + if field in ["rq", "c", "si", "mn", "p", "s", "ni", "cr", "ti", "mo", "cu", "klqd", "ysl"]: + item.setTextAlignment(Qt.AlignCenter) + + # 设置表格项 + self.result_table.setItem(row, col_idx, item) + + # 存储原始数据到第一列的item中 + item_index.setData(Qt.UserRole, luno_data) + + def on_table_double_clicked(self, row, column): + """表格双击事件处理""" + self.select_current_row(row) + + def on_confirm(self): + """确认按钮点击事件处理""" + # 获取当前选中行 + selected_rows = self.result_table.selectionModel().selectedRows() + if not selected_rows: + QMessageBox.warning(self, "提示", "请选择一个炉号") + return + + # 获取选中行的索引 + row_index = selected_rows[0].row() + self.select_current_row(row_index) + + def select_current_row(self, row): + """选择当前行并返回数据""" + if 0 <= row < self.result_table.rowCount(): + # 获取存储在item中的原始数据 + item = self.result_table.item(row, 0) + if item: + luno_data = item.data(Qt.UserRole) + if luno_data: + # 发出信号 + self.luno_selected.emit(luno_data) + self.accept() \ No newline at end of file diff --git a/widgets/main_window.py b/widgets/main_window.py index 180f005..1b1ae98 100644 --- a/widgets/main_window.py +++ b/widgets/main_window.py @@ -306,6 +306,10 @@ class MainWindow(MainWindowUI): # 连接急停信号 self.emergency_stop_signal.connect(self._handle_emergency_stop_ui) + + # 连接炉号查询按钮信号 + if hasattr(self, 'luno_query_button'): + self.luno_query_button.clicked.connect(self.handle_luno_query) def update_inspection_columns(self): """更新检验列配置 - 使用检验配置管理器获取启用的列数和标题""" @@ -3768,6 +3772,14 @@ class MainWindow(MainWindowUI): current_value = self.info_values[field_name].toPlainText() elif isinstance(self.info_values[field_name], QComboBox): current_value = self.info_values[field_name].currentText() + elif field_name == "炉号": + # 炉号字段是容器,需要找到其中的QLineEdit + luno_container = self.info_values[field_name] + if luno_container: + for child in luno_container.children(): + if hasattr(child, 'text') and hasattr(child, 'setText'): + current_value = child.text() + break else: current_value = self.info_values[field_name].text() except RuntimeError as e: @@ -3833,6 +3845,14 @@ class MainWindow(MainWindowUI): # 如果没找到匹配的选项,添加新选项 combo.addItem(new_value) combo.setCurrentText(new_value) + elif field_name == "炉号": + # 炉号字段是容器,需要找到其中的QLineEdit并设置文本 + luno_container = self.info_values[field_name] + if luno_container: + for child in luno_container.children(): + if hasattr(child, 'text') and hasattr(child, 'setText'): + child.setText(new_value) + break else: self.info_values[field_name].setText(new_value) logging.debug(f"更新字段 '{field_name}': '{current_value}' -> '{new_value}'") @@ -4187,4 +4207,57 @@ class MainWindow(MainWindowUI): return has_any_value except Exception as e: logging.error(f"检查检验完成状态失败: {str(e)}") - return False \ No newline at end of file + return False + + def handle_luno_query(self): + """处理炉号查询按钮点击事件""" + try: + # 导入炉号查询对话框 + from widgets.luno_query_dialog import LunoQueryDialog + + # 创建炉号查询对话框 + luno_dialog = LunoQueryDialog(self) + + # 连接炉号选择信号 + luno_dialog.luno_selected.connect(self.on_luno_selected) + + # 显示对话框 + luno_dialog.exec() + + except Exception as e: + logging.error(f"打开炉号查询对话框失败: {str(e)}") + from PySide6.QtWidgets import QMessageBox + QMessageBox.critical(self, "错误", f"打开炉号查询对话框失败: {str(e)}") + + def on_luno_selected(self, luno_data): + """处理炉号选择事件 + + Args: + luno_data: 选中的炉号数据字典 + """ + try: + # 获取炉号输入框 + luno_input = None + luno_container = self.info_values.get("炉号") + if luno_container: + # 查找容器中的QLineEdit + for child in luno_container.children(): + if hasattr(child, 'text') and hasattr(child, 'setText'): + luno_input = child + break + + if luno_input: + # 设置炉号值 + luno_value = luno_data.get("luono", "") + luno_input.setText(luno_value) + logging.info(f"已选择炉号: {luno_value}") + + # 显示状态消息 + self.statusBar().showMessage(f"已选择炉号: {luno_value}", 2000) + else: + logging.warning("未找到炉号输入框") + + except Exception as e: + logging.error(f"处理炉号选择失败: {str(e)}") + from PySide6.QtWidgets import QMessageBox + QMessageBox.critical(self, "错误", f"处理炉号选择失败: {str(e)}") \ No newline at end of file