feat: 更新托盘信息管理逻辑,添加托盘信息保存和获取功能,优化界面元素以支持托盘类型选择和层数显示,下料托盘已经完成

This commit is contained in:
zhu-mengmeng 2025-06-20 17:47:03 +08:00
parent 01f04fda29
commit 370bf03d13
8 changed files with 337 additions and 81 deletions

View File

@ -61,8 +61,7 @@ class TaryApi:
"product_name": tray_info.get("zx_name", ""), # 产品名称
"axis_type": tray_info.get("zx", ""), # 轴型
"tier": str(tray_info.get("cs", "")), # 托盘料
"weight": str(tray_info.get("zl", "")), # 重量
"quantity": "" # 数量先空下
"size": str(tray_info.get("cc", "")), # 尺寸
}
return {

View File

@ -68,9 +68,7 @@ class PalletTypeDAO:
axios_name,
axios_type,
tier,
size,
amount,
weight
size
FROM wsbz_pallet_archives t1
WHERE pallet_code = ? AND t1.is_deleted = FALSE
"""
@ -331,3 +329,116 @@ class PalletTypeDAO:
except Exception as e:
logging.error(f"更新托盘类型启用状态失败: {str(e)}")
return False
def save_pallet_info(self, pallet_code, pallet_info, user_id):
"""保存托盘信息
Args:
pallet_code: 托盘号
pallet_info: 托盘信息
user_id: 用户ID
"""
try:
# 先查询是否存在该托盘号
check_sql = "SELECT pallet_code FROM wsbz_pallet_archives WHERE pallet_code = ? AND is_deleted = ?"
result = self.db.execute_query(check_sql, (pallet_code, False))
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
if result: # 如果存在,则更新
update_sql = """
UPDATE wsbz_pallet_archives
SET tier = ?,
size = ?,
update_time = ?,
update_by = ?
WHERE pallet_code = ? AND is_deleted = ?
"""
params = (
pallet_info.get("cs", ""),
pallet_info.get("cc", ""),
current_time,
user_id,
pallet_code,
False
)
self.db.execute_update(update_sql, params)
logging.info(f"更新托盘信息成功: {pallet_code}")
else: # 如果不存在,则新增
insert_sql = """
INSERT INTO wsbz_pallet_archives
(pallet_code, tier, size, create_time, create_by, is_deleted)
VALUES (?, ?, ?, ?, ?, ?)
"""
params = (
pallet_code,
pallet_info.get("cs", ""),
pallet_info.get("cc", ""),
current_time,
user_id,
False
)
self.db.execute_update(insert_sql, params)
logging.info(f"新增托盘信息成功: {pallet_code}")
return True
except Exception as e:
logging.error(f"保存托盘信息失败: {str(e)}")
return False
def get_pallet_detail(self, pallet_code):
"""根据托盘号获取托盘信息
Args:
pallet_code: 托盘号
Returns:
dict: 包含托盘详细信息的字典如果未找到返回None
"""
try:
sql = """
SELECT wpa.pallet_code, wpa.tier, wpa.size, wpt.pallet_name,woi.zx_name,woi.zx_code,woi.cz,sum(wipd.weight) AS weight,count(wpa.pallet_code) AS amount
FROM wsbz_pallet_archives wpa
LEFT JOIN wsbz_inspection_pack_data wipd ON wpa.pallet_code = wipd.tray_id
LEFT JOIN wsbz_order_info woi on woi.ddmo = wipd.order_id
left join wsbz_pallet_type wpt on wpt.pallet_id = wpa.size
WHERE wpa.pallet_code = ?
GROUP BY wpa.pallet_code, wpa.tier, wpa.size, wpt.pallet_name,woi.zx_name,woi.zx_code,woi.cz
"""
params = (pallet_code,)
self.db.cursor.execute(sql, params)
row = self.db.cursor.fetchone()
if row:
# 获取列名
columns = [column[0] for column in self.db.cursor.description]
# 将结果转换为字典
result = dict(zip(columns, row))
# 处理可能的None值
for key in result:
if result[key] is None:
result[key] = ""
return result
else:
return None
except Exception as e:
logging.error(f"获取托盘信息失败: {str(e)}")
return None
def get_pallet_types(self):
"""获取托盘类型
Returns:
dict: key为pallet_idvalue为pallet_name的字典
"""
try:
sql = """
SELECT pallet_id,pallet_name FROM wsbz_pallet_type ORDER BY pallet_id
"""
self.db.cursor.execute(sql)
results = self.db.cursor.fetchall()
# 将结果转换为字典
pallet_types = {}
for row in results:
pallet_id, pallet_name = row
pallet_types[pallet_id] = pallet_name
return pallet_types
except Exception as e:
logging.error(f"获取托盘类型失败: {str(e)}")
return {}

Binary file not shown.

View File

@ -103,10 +103,61 @@ class UnloadingDialogUI(QDialog):
row1.addWidget(self.tray_input, 1)
container_layout.addLayout(row1)
# 第二行:轴型和托盘料
# 添加水平分隔布局
split_layout = QHBoxLayout()
split_layout.setSpacing(0)
left_split = QLabel()
left_split.setFixedWidth(100)
left_split.setFixedHeight(1)
left_split.setStyleSheet("background-color: #e0e0e0;")
right_split = QLabel()
right_split.setFixedHeight(1)
right_split.setStyleSheet("background-color: #e0e0e0;")
split_layout.addWidget(left_split)
split_layout.addWidget(right_split, 1)
container_layout.addLayout(split_layout)
# 第二行:托盘类型
row2 = QHBoxLayout()
row2.setSpacing(0)
self.pallet_type_label = QLabel("托盘类型")
self.pallet_type_label.setFont(self.normal_font)
self.pallet_type_label.setStyleSheet(label_style)
self.pallet_type_label.setFixedWidth(100)
self.pallet_type_label.setFixedHeight(45)
self.pallet_type_input = QComboBox()
self.pallet_type_input.setStyleSheet("border: none; padding: 5px 10px;")
self.pallet_type_input.setFont(QFont("微软雅黑", 12))
self.pallet_type_input.setEditable(True) # 允许手动输入
self.pallet_type_input.setFixedHeight(45)
self.pallet_type_input.setInsertPolicy(QComboBox.NoInsert) # 不自动插入用户输入到列表中
self.pallet_type_input.setMaxVisibleItems(10) # 设置下拉框最多显示10个项目
self.pallet_type_input.completer().setCaseSensitivity(Qt.CaseInsensitive) # 设置补全不区分大小写
self.pallet_type_input.completer().setFilterMode(Qt.MatchContains) # 设置模糊匹配模式
row2.addWidget(self.pallet_type_label)
row2.addWidget(self.pallet_type_input, 1)
container_layout.addLayout(row2)
# 添加水平分隔布局
split_layout2 = QHBoxLayout()
split_layout2.setSpacing(0)
left_split2 = QLabel()
left_split2.setFixedWidth(100)
left_split2.setFixedHeight(1)
left_split2.setStyleSheet("background-color: #e0e0e0;")
right_split2 = QLabel()
right_split2.setFixedHeight(1)
right_split2.setStyleSheet("background-color: #e0e0e0;")
split_layout2.addWidget(left_split2)
split_layout2.addWidget(right_split2, 1)
container_layout.addLayout(split_layout2)
# 第三行:轴型和材质
row3 = QHBoxLayout()
row3.setSpacing(0)
axis_layout = QHBoxLayout()
axis_layout.setSpacing(0)
self.axis_label = QLabel("轴型")
@ -125,27 +176,52 @@ class UnloadingDialogUI(QDialog):
tier_layout = QHBoxLayout()
tier_layout.setSpacing(0)
self.pallet_tier_label = QLabel("托盘料")
self.pallet_tier_label.setFont(self.normal_font)
self.pallet_tier_label.setStyleSheet(label_style)
self.pallet_tier_label.setFixedWidth(100)
self.pallet_tier_label.setFixedHeight(40)
self.material_tier_label = QLabel("材质")
self.material_tier_label.setFont(self.normal_font)
self.material_tier_label.setStyleSheet(label_style)
self.material_tier_label.setFixedWidth(100)
self.material_tier_label.setFixedHeight(40)
self.pallet_tier_value = QLabel("--")
self.pallet_tier_value.setFont(self.normal_font)
self.pallet_tier_value.setStyleSheet(value_style)
self.pallet_tier_value.setFixedHeight(40)
self.material_tier_value = QLineEdit()
self.material_tier_value.setFont(self.normal_font)
self.material_tier_value.setStyleSheet("""
QLineEdit {
padding: 5px;
background-color: white;
color: #333333;
}
QLineEdit:focus {
border: 1px solid #66afe9;
outline: none;
}
""")
self.material_tier_value.setFixedHeight(40)
self.material_tier_value.setPlaceholderText(" -- ")
tier_layout.addWidget(self.pallet_tier_label)
tier_layout.addWidget(self.pallet_tier_value, 1)
tier_layout.addWidget(self.material_tier_label)
tier_layout.addWidget(self.material_tier_value, 1)
row2.addLayout(axis_layout, 1)
row2.addLayout(tier_layout, 1)
container_layout.addLayout(row2)
row3.addLayout(axis_layout, 1)
row3.addLayout(tier_layout, 1)
container_layout.addLayout(row3)
# 第三行:数量和重量
row3 = QHBoxLayout()
row3.setSpacing(0)
# 添加水平分隔布局
split_layout3 = QHBoxLayout()
split_layout3.setSpacing(0)
left_split3 = QLabel()
left_split3.setFixedWidth(100)
left_split3.setFixedHeight(1)
left_split3.setStyleSheet("background-color: #e0e0e0;")
right_split3 = QLabel()
right_split3.setFixedHeight(1)
right_split3.setStyleSheet("background-color: #e0e0e0;")
split_layout3.addWidget(left_split3)
split_layout3.addWidget(right_split3, 1)
container_layout.addLayout(split_layout3)
# 第四行:数量和重量
row4 = QHBoxLayout()
row4.setSpacing(0)
quantity_layout = QHBoxLayout()
quantity_layout.setSpacing(0)
@ -179,9 +255,23 @@ class UnloadingDialogUI(QDialog):
weight_layout.addWidget(self.weight_label)
weight_layout.addWidget(self.weight_value, 1)
row3.addLayout(quantity_layout, 1)
row3.addLayout(weight_layout, 1)
container_layout.addLayout(row3)
row4.addLayout(quantity_layout, 1)
row4.addLayout(weight_layout, 1)
container_layout.addLayout(row4)
# 添加水平分隔布局
split_layout4 = QHBoxLayout()
split_layout4.setSpacing(0)
left_split4 = QLabel()
left_split4.setFixedWidth(100)
left_split4.setFixedHeight(1)
left_split4.setStyleSheet("background-color: #e0e0e0;")
right_split4 = QLabel()
right_split4.setFixedHeight(1)
right_split4.setStyleSheet("background-color: #e0e0e0;")
split_layout4.addWidget(left_split4)
split_layout4.addWidget(right_split4, 1)
container_layout.addLayout(split_layout4)
# 添加弹性空间
container_layout.addStretch()

View File

@ -206,3 +206,30 @@ class PalletTypeManager:
return result
else:
return None
def save_pallet_info(self, pallet_code, pallet_info, user_id):
"""保存托盘信息
Args:
pallet_code: 托盘号
pallet_info: 托盘信息
"""
self.dao.save_pallet_info(pallet_code, pallet_info, user_id)
def get_pallet_detail(self, pallet_code):
"""根据托盘号获取托盘信息
Args:
pallet_code: 托盘号
"""
result = self.dao.get_pallet_detail(pallet_code)
if result:
return result
else:
return None
def get_pallet_types(self):
"""获取托盘类型"""
result = self.dao.get_pallet_types()
if result:
return result
else:
return None

View File

@ -128,8 +128,6 @@ class LoadingDialog(LoadingDialogUI):
"product_name": pallet_info[1] if isinstance(pallet_info, tuple) and len(pallet_info) > 1 else "",
"axis_type": pallet_info[4] if isinstance(pallet_info, tuple) and len(pallet_info) > 4 else "",
"tier": str(pallet_info[5]) if isinstance(pallet_info, tuple) and len(pallet_info) > 5 else "",
"weight": str(pallet_info[8]) if isinstance(pallet_info, tuple) and len(pallet_info) > 8 else "",
"quantity": ""
}
}
except (IndexError, TypeError) as e:

View File

@ -442,7 +442,7 @@ class MainWindow(MainWindowUI):
# 创建下料对话框
from widgets.unloading_dialog_widget import UnloadingDialog
dialog = UnloadingDialog(parent=self)
dialog = UnloadingDialog(parent=self, user_id=self.user_id)
# 显示对话框
result = dialog.exec()
@ -450,9 +450,15 @@ class MainWindow(MainWindowUI):
# 如果用户确认,则执行下料操作
if result == QDialog.Accepted:
# 获取托盘料值作为下料层数
stow_num = dialog.pallet_tier_value.text()
if stow_num == "--" or not stow_num:
QMessageBox.warning(self, "错误", "未获取到托盘料信息,请重试")
pallet_type_id = dialog.get_current_pallet_type_id() # 获取托盘类型ID
tier_num = dialog.get_current_tier() # 获取托盘层数
if not pallet_type_id:
QMessageBox.warning(self, "错误", "未获取到托盘类型信息,请重试")
return
if not tier_num:
QMessageBox.warning(self, "错误", "未获取到托盘层数信息,请重试")
return
# 获取托盘号对应的托盘类型
@ -469,16 +475,16 @@ class MainWindow(MainWindowUI):
modbus = ModbusUtils()
client = modbus.get_client()
try:
# 下料 D3 寄存器写入 1 D1 寄存器写入托盘类型
success0 = modbus.write_register_until_success(client, 0, int(stow_num))
success1 = modbus.write_register_until_success(client, 1, int(pallet_type))
# 下料 D3 寄存器写入 1 D1 寄存器写入托盘类型 D0 寄存器写入层数
success0 = modbus.write_register_until_success(client, 0, int(tier_num)) # 写入层数
success1 = modbus.write_register_until_success(client, 1, int(pallet_type_id)) # 写入托盘类型ID
success3 = modbus.write_register_until_success(client, 3, 1)
if success0 and success1 and success3:
# 创建状态标签并显示在右上角
self.show_operation_status("码垛层数", "output", stow_num)
self.show_operation_status("码垛层数", "output", tier_num)
else:
QMessageBox.information(self, "操作提示", "码垛层数")
QMessageBox.information(self, "操作提示", "码垛层数设置失败")
except Exception as e:
logging.error(f"码垛层数操作失败: {str(e)}")
QMessageBox.critical(self, "错误", f"码垛失败: {str(e)}")

View File

@ -10,11 +10,12 @@ class UnloadingDialog(UnloadingDialogUI):
# 定义一个信号,用于向主窗口传递托盘号
tray_code_signal = Signal(str, str, str, str)
def __init__(self, parent=None):
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()
@ -29,9 +30,38 @@ class UnloadingDialog(UnloadingDialogUI):
# 设置对话框特性按下Escape键才能关闭
self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint)
# 初始化托盘类型下拉列表
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):
"""获取当前托盘的层数"""
return self.current_tier if self.current_tier else None
def setup_connections(self):
"""设置事件连接"""
# 托盘号输入框回车事件触发查询
@ -58,61 +88,56 @@ class UnloadingDialog(UnloadingDialogUI):
"""查询托盘信息"""
try:
tray_code = self.tray_input.text().strip()
pallet_type = self.pallet_type_input.currentText().strip()
if not tray_code:
return
logging.info(f"查询托盘号: {tray_code}")
pallet_info = {}
if AppMode.is_api():
self.tary_api = TaryApi()
# 调用API获取托盘信息
# 调用API获取托盘信息,并保存到本地
response = self.tary_api.get_tary_info(tray_code)
else:
pallet_type_manager = PalletTypeManager.get_instance()
pallet_info = pallet_type_manager.get_pallet_info_by_pallet_id(tray_code)
# 检查返回的数据类型并进行适当处理
if pallet_info is None:
response = {
"success": False,
"message": "未找到托盘信息"
}
else:
# 如果返回的是元组(数据库查询结果),将其转换为字典
# 根据dao/pallet_type_dao.py中get_pallet_info_by_pallet_id方法的SQL查询
# 返回的字段顺序为pallet_code, pallet_name, description, axios_name, axios_type, tier, size, amount, weight
response = {
"success": True,
"data": {
"tp_note": pallet_info[0] if len(pallet_info) > 0 else "",
"product_name": pallet_info[1] if len(pallet_info) > 1 else "",
"axis_type": pallet_info[4] if len(pallet_info) > 4 else "",
"tier": str(pallet_info[5]) if len(pallet_info) > 5 else "",
"weight": str(pallet_info[8]) if len(pallet_info) > 8 else "",
"quantity": ""
}
}
logging.info(f"托盘信息响应: {response}")
logging.info(f"response.success={response.get('success')}, response.data存在={response.get('data') is not None}")
if response.get("success", False) and response.get("data"):
tray_data = response.get("data", {})
logging.info(f"托盘数据: {tray_data}")
pallet_type_manager = PalletTypeManager.get_instance()
pallet_type_manager.save_pallet_info(tray_code, tray_data,self.user_id)
else:
# 不是接口,就查询数据库,如果查到了托盘号就回显,查不到就新增
pallet_type_manager = PalletTypeManager.get_instance()
pallet_info = pallet_type_manager.get_pallet_info_by_pallet_id(tray_code)
if not pallet_info:
# 获取页面上的数据,保存到数据库中
pallet_info = {
"cc": pallet_type,
"cs": "",
}
pallet_type_manager.save_pallet_info(tray_code, pallet_info,self.user_id)
#回显数据到页面
pallet_info = pallet_type_manager.get_pallet_detail(tray_code)
if pallet_info:
logging.info(f"托盘数据: {pallet_info}")
# 显示托盘相关信息
axis_type = str(tray_data.get("axis_type", "--"))
tier = str(tray_data.get("tier", "--"))
weight = str(tray_data.get("weight", "--"))
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("tier") # 保存层数
logging.info(f"显示托盘信息: 轴型={axis_type}, 托盘料={tier}, 重量={weight}")
logging.info(f"显示托盘信息: 轴型={axis_type}, 材质={material}, 重量={weight}, 层数={self.current_tier}")
# 设置显示值
self.axis_value.setText(axis_type)
self.pallet_tier_value.setText(tier)
self.quantity_value.setText("") # 数量为空
self.material_tier_value.setPlaceholderText(material)
self.material_tier_value.setText("") # 清空文本,让用户输入
self.quantity_value.setText(amount)
self.weight_value.setText(f"{weight} kg")
self.pallet_type_input.setCurrentText(pallet_info.get("pallet_name", "--"))
# 发送托盘号到主窗口
from widgets.main_window import MainWindow