add(派单任务刷新)、modify(派单任务和管片任务详情界面)

This commit is contained in:
yaj
2026-02-28 11:45:25 +08:00
parent 6e74eaf206
commit 37d60ba63e
6 changed files with 178 additions and 85 deletions

View File

@ -14,9 +14,9 @@ sub_interval = 500
[OPC_NODE_LIST]
upper_weight = 2:upper,2:upper_weight
lower_weight = 2:lower,2:lower_weight
pd_data = 2:pd,2:pd_data
upper_hopper_position = 2:upper,2:upper_hopper_position
upper_clamp_status = 2:upper,2:upper_clamp_status
vibration_frequency=2:vibration_frequency
production_progress=2:production_progress
segment_tasks=2:segment_tasks
segment_tasks=2:segment_tasks
dispatch_tasks=2:dispatch_tasks

View File

@ -11,7 +11,9 @@ from service.msg_recorder import MessageRecorder
from service.opcua_ui_client import OpcuaUiClient
from service.artifact_query_thread import ArtifactInfoQueryThread # 管片任务查询
from busisness.models import ArtifactInfoModel
from service.pdrecord_query_thread import PDRecordQueryThread # 派单任务查询
from busisness.models import ArtifactInfoModel
from busisness.models import PDRecordModel
from typing import List
@ -42,8 +44,8 @@ class MainController:
self.__connectSignals()
def showMainWindow(self):
# self.main_window.showFullScreen()
self.main_window.show()
self.main_window.showFullScreen()
# self.main_window.show()
def _initSubControllers(self):
# 右侧视频显示控制模块
@ -158,34 +160,18 @@ class MainController:
import traceback
traceback.print_exc()
def convert_to_ampm(self, time_str: str) -> str:
"""时间格式转换: 转换为AM/PM形式"""
from datetime import datetime
time_formats = [
"%Y-%m-%d %H:%M:%S",
"%Y-%m-%d %H:%M:%S.%f"
]
for fmt in time_formats:
try:
dt = datetime.strptime(time_str, fmt)
return dt.strftime("%I:%M%p")
except ValueError:
continue
return "--:--"
def onUpdateUiByArtifactInfo(self, artifact_list:List[ArtifactInfoModel]):
for index, artifact in enumerate(artifact_list, 1):
if artifact.MouldCode:
self.main_window.segment_task_widget.set_task_id(f"task{index}", artifact.MouldCode) # 模具号
if artifact.BetonVolume:
self.main_window.segment_task_widget.set_task_volume(f"task{index}", artifact.BetonVolume) # 浇筑方量
if artifact.BeginTime:
time_str = self.convert_to_ampm(artifact.BeginTime)
self.main_window.segment_task_widget.set_task_time(f"task{index}", time_str) # 开始时间
self.main_window.SetSegmentTaskDetails(f"task{index}", artifact) # 更新管片任务详情
# 更新管片任务
self.main_window.update_segment_tasks(artifact_list)
# 将opc服务中的 segment_tasks的值复原为 0以便下次触发管片更新
self.opc_client.write_value_by_name("segment_tasks", 0)
def onUpdateUiByPDRecord(self, pdrecord_list:List[PDRecordModel]):
# 更新派单任务
self.main_window.update_dispatch_tasks(pdrecord_list)
# 将opc服务中的 dispatch_tasks的值复原为 0以便下次触发派单更新
self.opc_client.write_value_by_name("dispatch_tasks", 0)
# ======================== OPCUA值更新界面方法 ======================
def _update_upper_weight(self, val):
# 更新上料斗重量
@ -224,18 +210,31 @@ class MainController:
def _update_segment_tasks(self, val):
if val: # 需要更新管片任务
"""更新左侧的管片任务"""
if hasattr(self, "query_thread") and self.query_thread.isRunning():
if hasattr(self, "segment_query_thread") and self.segment_query_thread.isRunning():
return
# 1. 管片信息查询线程
self.query_thread = ArtifactInfoQueryThread()
self.segment_query_thread = ArtifactInfoQueryThread()
# 2. 主线程更新管片任务UI
self.query_thread.query_finished.connect(self.onUpdateUiByArtifactInfo)
self.segment_query_thread.query_finished.connect(self.onUpdateUiByArtifactInfo)
# 3. 查询管片信息错误
self.query_thread.query_error.connect(self.onQueryArtifactInfoError)
self.query_thread.start()
self.segment_query_thread.query_error.connect(self.onQueryInfoError)
self.segment_query_thread.start()
def onQueryArtifactInfoError(self, error_msg:str):
# 查询管片信息失败预警
def _update_dispatch_tasks(self, val):
if val: # 需要更新派单任务
"""更新右侧的派单任务"""
if hasattr(self, "dispatch_query_thread") and self.dispatch_query_thread.isRunning():
return
# 1. 派单信息查询线程
self.dispatch_query_thread = PDRecordQueryThread()
# 2. 主线程更新派单任务UI
self.dispatch_query_thread.query_finished.connect(self.onUpdateUiByPDRecord)
# 3. 查询派单信息错误
self.dispatch_query_thread.query_error.connect(self.onQueryInfoError)
self.dispatch_query_thread.start()
def onQueryInfoError(self, error_msg:str):
# 查询信息失败预警
self.msg_recorder.warning_record(error_msg)
def _update_vibration_frequency(self, val):

View File

@ -0,0 +1,27 @@
from PySide6.QtWidgets import QWidget
from PySide6.QtCore import QThread, Signal
from busisness.blls import PDRecordBll
from busisness.models import PDRecordModel
class PDRecordQueryThread(QThread):
# 定义信号:子线程查询完成
query_finished = Signal(list)
# 定义信号:发送错误信息
query_error = Signal(str)
def __init__(self):
super().__init__()
def run(self):
try:
pdrecord_dal = PDRecordBll()
pdrecords = pdrecord_dal.get_PD_record() # 获取派单任务数据
if pdrecords:
# 查询完成,发射信号
self.query_finished.emit(pdrecords)
else:
raise ValueError("未查询到有效数据")
except Exception as e:
print(f"更新派单任务数据失败: {str(e)}")
self.query_error.emit(f"更新派单任务数据失败: {str(e)}")

View File

@ -26,6 +26,7 @@ from .widgets.segment_details_dialog import SegmentDetailsDialog
from .widgets.dispatch_details_dialog import DispatchDetailsDialog
from busisness.models import ArtifactInfoModel
from busisness.models import PDRecordModel
class MainWindow(QWidget):
@ -35,17 +36,12 @@ class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.initWindow()
# 保存管片任务信息的字典 task1: ArtifactInfoModel1.... (用于显示管片任务详情)
self.artifact_dict = {}
# 当前点击/选中的 管片任务详情对应的任务名(task1\task2\task3) (用于刷新选中的管片任务详情)
self.current_selected_segment_detail_name = None
self.init_business_attributes() # 初始化业务属性
self.createSubWidgets() # 创建子部件
self.initSubWidgets() # 初始化子部件
self.setupLayout() # 设置布局
self.connectSignalToSlot()
# 安装事件过滤器,处理计划方量的 QLineEdit的失去焦点事件
self.installEventFilter(self)
@ -103,6 +99,16 @@ class MainWindow(QWidget):
self.update_background()
def init_business_attributes(self):
# 保存管片任务信息的字典 task1: ArtifactInfoModel1.... (用于显示管片任务详情)
self.artifact_dict = {}
# 当前点击/选中的 管片任务详情对应的任务名(task1\task2\task3) (用于刷新选中的管片任务详情)
self.current_selected_segment_detail_name = None
# 保存派单任务信息的字典 task1: PDRecordModel1.... (用于显示派单任务详情)
self.dispatch_dict = {}
# 当前点击/选中的 派单任务详情对应的任务名(task1\task2\task3) (用于刷新选中的派单任务详情)
self.current_selected_dispatch_detail_name = None
def createSubWidgets(self):
"""创建所有子部件实例"""
@ -157,44 +163,54 @@ class MainWindow(QWidget):
return "--:--"
def _init_segment_tasks(self):
"""从数据库中读取管片任务数据并更新到UI"""
"""初始化管片任务, 从数据库中读取管片任务数据并更新到UI"""
try:
from busisness.blls import ArtifactBll
artifact_dal = ArtifactBll()
artifacts = artifact_dal.get_artifact_task() # 获取管片任务数据
# 遍历数据并更新UI
for i, artifact in enumerate(artifacts, 1):
if artifact.MouldCode: # 更新模具号
self.segment_task_widget.set_task_id(f"task{i}", artifact.MouldCode)
if artifact.BetonVolume: # 更新方量
self.segment_task_widget.set_task_volume(f"task{i}", artifact.BetonVolume)
if artifact.BeginTime: # 更新时间 (管片任务的开始时间)
# print("artifact.BeginTime: ", artifact.BeginTime)
self.segment_task_widget.set_task_time(f"task{i}", self.convert_to_ampm(artifact.BeginTime))
self.SetSegmentTaskDetails(f"task{i}", artifact) # 设置管片任务详情信息
# 更新管片任务
self.update_segment_tasks(artifacts)
except Exception as e:
print(f"更新管片任务数据失败: {e}")
def update_segment_tasks(self, artifact_list:List[ArtifactInfoModel]):
# 更新管片任务相关的信息
# 遍历数据并更新UI (包括左侧的管片任务 以及 管片任务详情)
for index, artifact in enumerate(artifact_list, 1):
if artifact.MouldCode: # 更新模具号
self.segment_task_widget.set_task_id(f"task{index}", artifact.MouldCode)
if artifact.BetonVolume: # 更新浇筑方量
self.segment_task_widget.set_task_volume(f"task{index}", artifact.BetonVolume)
if artifact.BeginTime: # 更新时间 (管片任务的开始时间)
# print("artifact.BeginTime: ", artifact.BeginTime)
self.segment_task_widget.set_task_time(f"task{index}", self.convert_to_ampm(artifact.BeginTime))
self.SetSegmentTaskDetails(f"task{index}", artifact) # 设置管片任务详情信息
def _init_dispatch_tasks(self):
"""从数据库中读取派单任务数据并更新到UI"""
"""初始化派单任务, 从数据库中读取派单任务数据并更新到UI"""
try:
from busisness.blls import PDRecordBll
pdrecord_dal = PDRecordBll()
pdrecords = pdrecord_dal.get_PD_record() # 获取派单任务数据
# 遍历数据并更新UI
for i, record in enumerate(pdrecords, 1):
if record.MouldCode: # 更新模具号
self.dispatch_task_widget.set_task_id(f"task{i}", record.MouldCode)
if record.BetonVolume: # 更新方量
self.dispatch_task_widget.set_task_volume(f"task{i}", record.BetonVolume)
if record.CreateTime: # 更新时间 (派单任务的创建时间)
self.dispatch_task_widget.set_task_time(f"task{i}", self.convert_to_ampm(record.CreateTime))
# 更新派单任务
self.update_dispatch_tasks(pdrecords)
except Exception as e:
print(f"更新派单任务数据失败: {e}")
def update_dispatch_tasks(self, pdrecord_list:List[PDRecordModel]):
# 更新派单任务相关的信息
# 遍历数据并更新UI
for index, record in enumerate(pdrecord_list, 1):
if record.MouldCode: # 更新模具号
self.dispatch_task_widget.set_task_id(f"task{index}", record.MouldCode)
if record.BetonVolume: # 更新方量(派单方量[最终计算出来的派单方量])
self.dispatch_task_widget.set_task_volume(f"task{index}", record.FBetonVolume)
if record.CreateTime: # 更新时间 (派单任务的创建时间)
self.dispatch_task_widget.set_task_time(f"task{index}", self.convert_to_ampm(record.CreateTime))
self.SetPDRecordTaskDetails(f"task{index}", record)
def setupLayout(self):
"""设置垂直布局,从上到下排列部件"""
main_layout = QVBoxLayout(self) # 主布局:垂直布局
@ -323,21 +339,28 @@ class MainWindow(QWidget):
def handleDispatchTaskDetails(self, dispatch_task_name:str):
# 派单任务名 task1、task2、task3 (分别对应第一条派单任务、 第二条派单任务...)
print("main_window: handleDispatchTaskDetails", dispatch_task_name)
# print("main_window: handleDispatchTaskDetails", dispatch_task_name)
# 显示派单任务详情对话框
dispatch_details_dialog = DispatchDetailsDialog(dispatch_task_name, self)
if not hasattr(self, "dispatch_details_dialog"):
self.dispatch_details_dialog = DispatchDetailsDialog(dispatch_task_name, self)
pd_record:PDRecordModel = self.dispatch_dict.get(dispatch_task_name)
# 这里可以设置对话框显示的内容 如 set_segment_id
# dispatch_details_dialog.set_segment_id("9999999999")
# 设置派单任务详情中的方量的值
current_volume = self.dispatch_task_widget.get_task_volume(dispatch_task_name)
dispatch_details_dialog.set_row_value(4, str(current_volume)) # 派单方量的值的行号为4第五行
# current_volume = self.dispatch_task_widget.get_task_volume(dispatch_task_name)
# self.dispatch_details_dialog.set_row_value(4, str(current_volume)) # 派单方量的值的行号为4第五行
# 更新派单任务详情按钮弹窗的显示
self.updateDispatchTaskDetailsDialog(pd_record)
# 派单任务详情页面中确定修改了派单任务的方量
# 备注:褚工说管片任务和派单任务中的方量都只有一位小数,料斗上的方量显示两位 2025/11/8
dispatch_details_dialog.confirm_modify_volume.connect(self.handleModifyDispatchTaskVolume)
dispatch_details_dialog.show()
self.dispatch_details_dialog.confirm_modify_volume.connect(self.handleModifyDispatchTaskVolume)
self.dispatch_details_dialog.show()
# 更新选中的派单任务详情对应的任务名
self.current_selected_dispatch_detail_name = dispatch_task_name
def handleModifyDispatchTaskVolume(self, dispatch_task_name:str, modifyed_volume:float):
"""派单任务详情页面中, 修改了派单任务的方量"""
@ -345,6 +368,33 @@ class MainWindow(QWidget):
self.dispatch_task_widget.set_task_volume(dispatch_task_name, modifyed_volume)
# 其他操作,可能需要修改数据库的派单任务方量
def updateDispatchTaskDetailsDialog(self, pd_record:PDRecordModel):
if pd_record and hasattr(self, "dispatch_details_dialog"):
self.dispatch_details_dialog.set_segment_id(pd_record.ArtifactActionID) # 管片ID
self.dispatch_details_dialog.set_row_value(0, pd_record.CreateTime.split('.')[0] if pd_record.CreateTime else None) # 创建时间 (去掉毫秒)
self.dispatch_details_dialog.set_row_value(1, pd_record.OptTime.split('.')[0] if pd_record.OptTime else None) # 派单时间 (去掉毫秒)
self.dispatch_details_dialog.set_row_value(2, pd_record.TaskID) # 任务编号
self.dispatch_details_dialog.set_row_value(3, pd_record.ProduceMixID) # 生产配合比编号(配比编号)
self.dispatch_details_dialog.set_row_value(4, pd_record.FBetonVolume) # 派单方量(最终计算出来的实际派单方量)
# 派单状态 1计划中2已下发0未知)默认1
status_mapping = {
1: "计划中",
2: "已下发",
0: None # 未知
}
status_text = status_mapping.get(pd_record.Status)
self.dispatch_details_dialog.set_row_value(5, status_text)
# 派单模式(1自动派单 2手动派单 0未知 Mode: int = 0
mode_mapping = {
1: "自动派单",
2: "手动派单",
0: None # 未知
}
mode_text = mode_mapping.get(pd_record.Mode)
self.dispatch_details_dialog.set_row_value(6, mode_text)
# 更新 派单任务widget的坐标
@ -426,8 +476,17 @@ class MainWindow(QWidget):
# self.artifact_dict 管片信息的字典
def SetSegmentTaskDetails(self, task_name:str, artifact_info:ArtifactInfoModel):
self.artifact_dict[task_name] = artifact_info
if task_name == self.current_selected_segment_detail_name:
self.updateSegmentTaskDetailsDialog(artifact_info) # 刷新管片任务详情按钮弹窗
if hasattr(self, "segment_details_dialog") and self.segment_details_dialog and self.segment_details_dialog.isVisible():
if task_name == self.current_selected_segment_detail_name:
self.updateSegmentTaskDetailsDialog(artifact_info) # 刷新管片任务详情按钮弹窗
# ======= 设置派单任务详情接口 ==========
# self.dispatch_dict 派单信息的字典
def SetPDRecordTaskDetails(self, task_name:str, pd_record:PDRecordModel):
self.dispatch_dict[task_name] = pd_record
if hasattr(self, "dispatch_details_dialog") and self.dispatch_details_dialog and self.dispatch_details_dialog.isVisible():
if task_name == self.current_selected_dispatch_detail_name:
self.updateDispatchTaskDetailsDialog(pd_record) # 刷新派单任务详情按钮弹窗
if __name__ == "__main__":
import sys

View File

@ -171,11 +171,18 @@ class DispatchDetailsDialog(QDialog):
}
"""
)
self.close_btn.clicked.connect(self.close)
self.close_btn.clicked.connect(self._on_close_button_clicked)
parent_layout.addStretch()
parent_layout.addWidget(self.close_btn)
def _on_close_button_clicked(self):
"""关闭按钮点击后的处理逻辑"""
# 1. 执行取消修改方量的逻辑
self.onCancelModifyVolume()
# 2. 执行关闭窗口的逻辑
self.close()
def _add_segment_id_area(self, parent_layout):
id_layout = QHBoxLayout()
@ -349,7 +356,8 @@ class DispatchDetailsDialog(QDialog):
self.modify_btn.show()
# 2、关闭派单方量调整控件
self.volume_value_adjuster.close()
if hasattr(self, "volume_value_adjuster") and self.volume_value_adjuster:
self.volume_value_adjuster.close()
def paintEvent(self, event):
if not self.bg_pixmap.isNull():
@ -368,12 +376,12 @@ class DispatchDetailsDialog(QDialog):
def set_row_label(self, row, new_label_text: str):
"""修改左侧的显示的标签的文本,如: 创建时间、派单时间等"""
if 0 <= row < len(self.rows):
self.rows[row].label.setText(new_label_text)
self.rows[row].label.setText(str(new_label_text) if new_label_text is not None else "")
def set_row_value(self, row, new_value_text: str):
"""修改右侧的显示的值, 如: 2025年9月9日 9:9:9"""
if 0 <= row < len(self.rows):
self.rows[row].value.setText(new_value_text)
self.rows[row].value.setText(str(new_value_text) if new_value_text is not None else "")
# 测试代码

View File

@ -257,9 +257,10 @@ class SegmentDetailsDialog(QDialog):
row: 左列网格行号(0-6,共7行)
new_label_text: 新的标签文字(如“管片编号”)
"""
if new_label_text and 0 <= row < len(self.left_cells):
if 0 <= row < len(self.left_cells):
cell = self.left_cells[row]
cell.label.setText(str(new_label_text))
cell.label.setText(str(new_label_text) if new_label_text else "")
def set_left_value(self, row, new_value_text:str):
"""
@ -268,9 +269,9 @@ class SegmentDetailsDialog(QDialog):
row: 左列网格行号(0-6,共7行)
new_value_text: 新的值(如“FB789”)
"""
if new_value_text and 0 <= row < len(self.left_cells):
if 0 <= row < len(self.left_cells):
cell = self.left_cells[row]
cell.value.setText(str(new_value_text))
cell.value.setText(str(new_value_text) if new_value_text else "")
def set_right_label(self, row, new_label_text:str):
"""
@ -279,9 +280,9 @@ class SegmentDetailsDialog(QDialog):
row: 右列网格行号(0-6,共7行)
new_label_text: 新的标签文字(如“分块号”)
"""
if new_label_text and 0 <= row < len(self.right_cells):
if 0 <= row < len(self.right_cells):
cell = self.right_cells[row]
cell.label.setText(str(new_label_text))
cell.label.setText(str(new_label_text) if new_label_text else "")
def set_right_value(self, row, new_value_text:str):
"""
@ -290,10 +291,9 @@ class SegmentDetailsDialog(QDialog):
row: 右列网格行号(0-6,共7行)
new_value_text: 新的值(如“FB789”)
"""
if new_value_text and 0 <= row < len(self.left_cells):
if 0 <= row < len(self.left_cells):
cell = self.right_cells[row]
cell.value.setText(str(new_value_text))
cell.value.setText(str(new_value_text) if new_value_text else "")
# 测试代码
if __name__ == "__main__":