From a3b62878081b4d349f372de9dace634b201822bb Mon Sep 17 00:00:00 2001 From: yaj <1229314433@qq.com> Date: Fri, 6 Mar 2026 18:33:58 +0800 Subject: [PATCH] =?UTF-8?q?add(=E6=B4=BE=E5=8D=95=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E5=92=8C=E7=AE=A1=E7=89=87=E4=BB=BB=E5=8A=A1=E7=9A=84=E5=88=B7?= =?UTF-8?q?=E6=96=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/constant_config.ini | 4 +- config/opc_config.ini | 18 ++- controller/bottom_control_controller.py | 20 ++- controller/main_controller.py | 51 ++++++- view/main_window.py | 185 +++++++++++++++++++++--- view/widgets/arc_progress_widget.py | 8 + view/widgets/dispatch_details_dialog.py | 14 +- view/widgets/plan_widget.py | 50 ++++++- view/widgets/task_widget.py | 85 ++++++++++- 9 files changed, 393 insertions(+), 42 deletions(-) diff --git a/config/constant_config.ini b/config/constant_config.ini index d356d88..c3b550d 100644 --- a/config/constant_config.ini +++ b/config/constant_config.ini @@ -10,9 +10,9 @@ interval_days = 10 # 方量调节控件最小值 min = 0.0 # 方量调节控件最大值 -max = 99.0 +max = 2.4 # 方量调节控件初始值 -initial = 2.5 +initial = 1.9 diff --git a/config/opc_config.ini b/config/opc_config.ini index 3a5d824..a4a70ba 100644 --- a/config/opc_config.ini +++ b/config/opc_config.ini @@ -14,9 +14,15 @@ sub_interval = 500 [OPC_NODE_LIST] upper_weight = 2:upper,2:upper_weight lower_weight = 2:lower,2:lower_weight -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 -dispatch_tasks=2:dispatch_tasks \ No newline at end of file +; ; upper_hopper_position = 2:upper,2:upper_hopper_position +; upper_clamp_status = 2:upper,2:upper_clamp_status +; production_progress=2:production_progress +; segment_tasks=2:segment_tasks +; dispatch_tasks=2:dispatch_tasks +segment_tasks=2:sys,2:segment_refresh +dispatch_tasks=2:sys,2:pd_refresh +mould_vibrate_status=2:mould,2:mould_vibrate_status +vibration_frequency=2:mould,2:mould_frequency +mould_finish_weight=2:mould,2:mould_finish_weight +pd_mode=2:pd,2:set_mode +pd_plan_volume=2:pd,2:set_volume \ No newline at end of file diff --git a/controller/bottom_control_controller.py b/controller/bottom_control_controller.py index 457b2dc..6b486db 100644 --- a/controller/bottom_control_controller.py +++ b/controller/bottom_control_controller.py @@ -4,7 +4,7 @@ from view.widgets.system_center_dialog import SystemCenterDialog from view.widgets.bottom_control_widget import BottomControlWidget from view.widgets.system_diagnostics_dialog import SystemDiagnosticsDialog from view.widgets.message_popup_widget import MessagePopupWidget - +from view.main_window import MainWindow from service.msg_recorder import MessageRecorder from service.msg_query_thread import MsgQueryThread @@ -16,7 +16,7 @@ from service.monitor_thread import MonitorThread """ class BottomControlController: - def __init__(self, bottom_control_widget:BottomControlWidget, main_window): + def __init__(self, bottom_control_widget:BottomControlWidget, main_window:MainWindow): self.bottom_control_widget = bottom_control_widget self.main_window = main_window @@ -25,7 +25,7 @@ class BottomControlController: self.diagnostics_device_row = 0 # 系统诊断弹窗的设备检测行号,从0开始 self.diagnostics_device_col = 0 # 系统诊断弹窗的设备检测列号,从0开始 self.diagnostics_service_row = 0 # 系统诊断弹窗的服务检测行号,从0开始 - self.diagnostics_service_col = 2 # 系统诊断弹窗的服务检测行号,从2开始 + self.diagnostics_service_col = 2 # 系统诊断弹窗的服务检测列号,从2开始 # 系统中心弹窗 self.system_center_dialog = SystemCenterDialog(self.main_window) @@ -211,8 +211,17 @@ class BottomControlController: self.system_diagnostics_dialog.set_ms_value(row, col, delay) if delay <= self.device_monitor.warning_delay: self.system_diagnostics_dialog.set_circle_status(row, col, "normal") + # 设置上料斗或者下料斗的设备状态(主界面的上料斗、下料斗控件中) + if device_name == "上料斗": + self.main_window.hopper_widget.setUpperHopperStatus(0) + elif device_name == "下料斗": + self.main_window.hopper_widget.setLowerHopperStatus(0) else: self.system_diagnostics_dialog.set_circle_status(row, col, "warning") + if device_name == "上料斗": + self.main_window.hopper_widget.setUpperHopperStatus(1) + elif device_name == "下料斗": + self.main_window.hopper_widget.setLowerHopperStatus(1) # 显示检测组件 self.system_diagnostics_dialog.set_selected_show(row, col) @@ -225,6 +234,11 @@ class BottomControlController: self.system_diagnostics_dialog.set_circle_status(row, col, "error") # 显示检测组件 self.system_diagnostics_dialog.set_selected_show(row, col) + # 设置上料斗或者下料斗的设备状态(主界面的上料斗、下料斗控件中) + if device_name == "上料斗": + self.main_window.hopper_widget.setUpperHopperStatus(2) + elif device_name == "下料斗": + self.main_window.hopper_widget.setLowerHopperStatus(2) def _get_diagnostics_service_row_col(self): """获取系统诊断弹窗中 服务检测的 行号 和 列号""" diff --git a/controller/main_controller.py b/controller/main_controller.py index 707e481..4451339 100644 --- a/controller/main_controller.py +++ b/controller/main_controller.py @@ -80,6 +80,11 @@ class MainController: self.opc_client.opc_signal.opc_log.connect(self.msg_recorder.normal_record, Qt.QueuedConnection) # opcua客户端日志 + # 主界面的计划表单自动派单控制 + self.main_window.plan_table_widget.auto_dispatch_signal.connect(self.handlePlanTableAutoDispatch) # 计划表单的自动派单切换 + + # 主界面的计划表单中的计划方量修改控制 + self.main_window.plan_volume_modified_signal.connect(self.handleVolumeModified) # 计划方量修改 def handleMainWindowClose(self): """主界面关闭""" @@ -92,6 +97,19 @@ class MainController: if hasattr(self, 'opc_client'): self.opc_client.stop_run() + def handlePlanTableAutoDispatch(self, auto_status:bool): + """处理计划表单的 自动派单和手动派单的切换 + pd_mode: 1,自动派单 2,手动派单 + """ + if auto_status: # 自动派单 + self.opc_client.write_value_by_name("pd_mode", 1) + else: # 手动派单 + self.opc_client.write_value_by_name("pd_mode", 2) + + def handleVolumeModified(self, volume_json_str:str): + """处理 修改方量 (计划表单中 和 派单详情中)""" + self.opc_client.write_value_by_name("pd_plan_volume", volume_json_str) + def start_msg_database_clean_task(self): """启动清理消息数据库(messages.db)中过期消息的定时任务""" from PySide6.QtCore import QTimer, QDateTime, QDate, QTime @@ -239,4 +257,35 @@ class MainController: def _update_vibration_frequency(self, val): # 更新振捣频率 - self.main_window.frequency_button_group.set_selected_frequency(val) \ No newline at end of file + self.main_window.frequency_button_group.set_selected_frequency(val) # 频率选择按钮上显示的选中的频率 + self.main_window.arc_progress.setFrequency(val) # 模具车上显示的振捣频率 + + def _update_mould_vibrate_status(self, vibrate_status:bool): + # 更新模具车上显示的振捣状态 + # vibrate_status: False:未振捣、True:振捣中 + if vibrate_status: + self.main_window.arc_progress.setState("振捣中") + else: + self.main_window.arc_progress.setState("未振捣") + self.opc_client.write_value_by_name("vibration_frequency", 0) # 将振捣频率设置为0 + + def _update_mould_finish_weight(self, finish_weight:int): + # 更新模具车中的下料重量 + # finish_weight:已下料重量 + self.main_window.arc_progress.setWeight(finish_weight) + + def _update_pd_mode(self, mode:int): + # 更新计划表单中的 派单模式(主界面下发状态的下面的切换开关),自动派单/手动派单 + mode_mapping = { + 1: "自动派单", + 2: "手动派单", + 0: None # 未知 + } + mode_text = mode_mapping.get(mode) + if mode_text == "自动派单": + # 设置主界面下发状态的下面的切换开关 + self.main_window.plan_table_widget.set_auto_dispatch(True) # 开启,自动派单 + # 修改系统配置文件中的 派单状态为自动派单... + else: + self.main_window.plan_table_widget.set_auto_dispatch(False) # 关闭,手动派单 + # 修改系统配置文件中的 派单状态为手动派单... diff --git a/view/main_window.py b/view/main_window.py index 9dee8f8..dae6a89 100644 --- a/view/main_window.py +++ b/view/main_window.py @@ -27,12 +27,16 @@ from .widgets.dispatch_details_dialog import DispatchDetailsDialog from busisness.models import ArtifactInfoModel from busisness.models import PDRecordModel +import json class MainWindow(QWidget): - # 定义“即将关闭”的信号 + # 定义“即将关闭”的信号 about_to_close = Signal() + # 计划方量修改信号 + plan_volume_modified_signal = Signal(str) + def __init__(self): super().__init__() self.initWindow() @@ -45,6 +49,9 @@ class MainWindow(QWidget): # 安装事件过滤器,处理计划方量的 QLineEdit的失去焦点事件 self.installEventFilter(self) + # 初始化派单任务控件 + self.dispatch_task_widget.set_task_select_btn_selected("task2") # 派单任务控件,初始化选中第二条派单任务 + # 连接槽函数 def connectSignalToSlot(self): # 可添加信号槽连接 @@ -61,6 +68,11 @@ class MainWindow(QWidget): # 派单任务详情 self.dispatch_task_widget.task_details_signal.connect(self.handleDispatchTaskDetails) # 派单任务详情按钮 + # 派单任务选择 (用于更新计划表单) + self.dispatch_task_widget.task_selected_signal.connect(self.handleDispatchTaskSelected) # 派单任务选择按钮 + + # 计划表单方量修改 + self.plan_table_widget.final_modify_volume_signal.connect(self.handleDispatchTaskVolumeModified) # 计划方量修改 def handleSystemStart(self): # 测试系统开启,进度条动画 @@ -109,6 +121,8 @@ class MainWindow(QWidget): self.dispatch_dict = {} # 当前点击/选中的 派单任务详情对应的任务名(task1\task2\task3) (用于刷新选中的派单任务详情) self.current_selected_dispatch_detail_name = None + # 当前点击/选中的 派单任务选择按钮对应的任务名 (用于刷新 计划表单) + self.current_dispatch_task_select_btn_name = None def createSubWidgets(self): """创建所有子部件实例""" @@ -177,7 +191,21 @@ class MainWindow(QWidget): def update_segment_tasks(self, artifact_list:List[ArtifactInfoModel]): # 更新管片任务相关的信息 # 遍历数据并更新UI (包括左侧的管片任务 以及 管片任务详情) - for index, artifact in enumerate(artifact_list, 1): + SEGMENT_STATUS_MAP = { + 1: "待生产", + 2: "正生产", + 3: "已生产" # 完成生产 + } + SEGMENT_STATUS_IMAGE = { + 1: ImagePaths.TASK_RECT5, + 2: ImagePaths.TASK_RECT4, + 3: ImagePaths.TASK_RECT3 + } + for index, artifact in enumerate(reversed(artifact_list), 1): + # 提取管片生产状态 + segment_status_text = SEGMENT_STATUS_MAP.get(artifact.Status, "未知") # 管片状态文本 + segment_status_icon = SEGMENT_STATUS_IMAGE.get(artifact.Status, ImagePaths.TASK_RECT1) # 管片状态图标 + if artifact.MouldCode: # 更新模具号 self.segment_task_widget.set_task_id(f"task{index}", artifact.MouldCode) if artifact.BetonVolume: # 更新浇筑方量 @@ -185,6 +213,14 @@ class MainWindow(QWidget): if artifact.BeginTime: # 更新时间 (管片任务的开始时间) # print("artifact.BeginTime: ", artifact.BeginTime) self.segment_task_widget.set_task_time(f"task{index}", self.convert_to_ampm(artifact.BeginTime)) + if segment_status_text: # 更新管片状态 + self.segment_task_widget.set_task_status(f"task{index}", segment_status_text, segment_status_icon) + # 更新模具车上的管片信息 + if segment_status_text == "正生产": # 模具车上只显示 正生产的管片信息 + self.arc_progress.setRingNumber(artifact.ProduceRingNumber) # 设置模具车上的环号 + self.arc_progress.setSegmentModel(artifact.BuriedDepth+": "+artifact.RingTypeCode) # 管片类型(如:中埋: R12) + self.arc_progress.setSegmentSize(artifact.SizeSpecification) # 管片规格(尺寸) + self.arc_progress.setSegmentNumber(artifact.MouldCode) # 管片号(如:SHRB1-3)[模具编号] self.SetSegmentTaskDetails(f"task{index}", artifact) # 设置管片任务详情信息 def _init_dispatch_tasks(self): @@ -202,14 +238,60 @@ class MainWindow(QWidget): 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) + # 倒着查,过滤掉 搅拌生产状态不是 未知的, + # 1、查到的第一个 派单状态为 已下发或者已超时 作为task1 + # 2、查到的第一个 派单状态为 计划中的作为 task2,第二个派单状态为 计划中作为 task3 + # 初始化标记:控制只取第一条Status=2/3、前两条Status=1的记录 + # 派单状态映射(1计划中 2已下发 0未知 3已超时) + DISPATCH_STATUS_MAP = { + 0: "未知", + 1: "计划中", + 2: "派单中", # 已下发 + 3: "已超时", + 4: "未扫码" + } + # 派单状态图标映射 + DISPATCH_STATUS_IMAGE = { + 0: ImagePaths.TASK_RECT1, + 1: ImagePaths.TASK_RECT2, + 2: ImagePaths.TASK_RECT3, + 3: ImagePaths.TASK_RECT4, + 4: ImagePaths.TASK_RECT5, + } + # 搅拌生产状态映射 + PRODUCE_STATUS_MAP = { + 0: "未知", + 1: "已取消", + 2: "已完成", + 3: "异常" + } + task_count = 0 # 有效的派单任务数量(需要显示的, task1,task2,task3) + + # 倒序遍历pdrecord_list + for record in reversed(pdrecord_list): + # 提取状态文字 + dispatch_status_text = DISPATCH_STATUS_MAP.get(record.Status, "未知") # 派单状态 + dispatch_status_icon = DISPATCH_STATUS_IMAGE.get(record.Status, ImagePaths.TASK_RECT1) # 派单状态图标 + produce_status_text = PRODUCE_STATUS_MAP.get(record.GStatus, "未知") # 搅拌生产状态 + + # 过滤掉GStatus不为0的记录,搅拌生产状态为未知(0)才需要显示 + if produce_status_text != "未知": + continue + + task_count += 1 # 有效任务数量加一 + self._set_dispatch_tasks_info(f"task{task_count}", record, dispatch_status_text, dispatch_status_icon) + + def _set_dispatch_tasks_info(self, task_name, record:PDRecordModel, status_text:str, status_icon:str): + # 设置派单任务的tasks信息 + if record.MouldCode: + self.dispatch_task_widget.set_task_id(task_name, record.MouldCode) + if record.FBetonVolume: + self.dispatch_task_widget.set_task_volume(task_name, record.FBetonVolume) + if record.CreateTime: + self.dispatch_task_widget.set_task_time(task_name, self.convert_to_ampm(record.CreateTime)) + if status_text: + self.dispatch_task_widget.set_task_status(task_name, status_text, status_icon) + self.SetPDRecordTask(task_name, record) def setupLayout(self): """设置垂直布局,从上到下排列部件""" @@ -344,6 +426,7 @@ class MainWindow(QWidget): # 显示派单任务详情对话框 if not hasattr(self, "dispatch_details_dialog"): self.dispatch_details_dialog = DispatchDetailsDialog(dispatch_task_name, self) + self.dispatch_details_dialog.confirm_modify_volume.connect(self.handleModifyDispatchTaskVolume) pd_record:PDRecordModel = self.dispatch_dict.get(dispatch_task_name) # 这里可以设置对话框显示的内容 如 set_segment_id @@ -351,25 +434,28 @@ class MainWindow(QWidget): # 设置派单任务详情中的方量的值 # 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.current_selected_dispatch_detail_name = dispatch_task_name # 更新派单任务详情按钮弹窗的显示 self.updateDispatchTaskDetailsDialog(pd_record) # 派单任务详情页面中确定修改了派单任务的方量 # 备注:褚工说管片任务和派单任务中的方量都只有一位小数,料斗上的方量显示两位 2025/11/8 - self.dispatch_details_dialog.confirm_modify_volume.connect(self.handleModifyDispatchTaskVolume) + self.dispatch_details_dialog.set_dispatch_task_name(dispatch_task_name) # 更新派单任务名 self.dispatch_details_dialog.show() - # 更新选中的派单任务详情对应的任务名 - self.current_selected_dispatch_detail_name = dispatch_task_name def handleModifyDispatchTaskVolume(self, dispatch_task_name:str, modifyed_volume:float): - """派单任务详情页面中, 修改了派单任务的方量""" + """派单任务详情页面中, 修改派单任务的方量""" # 修改相应的派单任务条目显示的 派单任务方量 self.dispatch_task_widget.set_task_volume(dispatch_task_name, modifyed_volume) # 其他操作,可能需要修改数据库的派单任务方量 - + self.handleDispatchTaskVolumeModified(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) # 创建时间 (去掉毫秒) @@ -380,13 +466,20 @@ class MainWindow(QWidget): # 派单状态 (1计划中2已下发0未知),默认1 status_mapping = { + 0: None, # 未知 1: "计划中", - 2: "已下发", - 0: None # 未知 + 2: "派单中", # 已下发 # 付工说改为派单中更好 + 3: "已超时", + 4: "未扫码" } status_text = status_mapping.get(pd_record.Status) self.dispatch_details_dialog.set_row_value(5, status_text) + if status_text == "计划中": # 只有派单状态为计划中,详情界面才能够修改方量 + self.dispatch_details_dialog.set_modify_volume_status(True) + else: + self.dispatch_details_dialog.set_modify_volume_status(False) + # 派单模式(1自动派单 2手动派单 0未知 )Mode: int = 0 mode_mapping = { 1: "自动派单", @@ -395,7 +488,57 @@ class MainWindow(QWidget): } mode_text = mode_mapping.get(pd_record.Mode) self.dispatch_details_dialog.set_row_value(6, mode_text) - + + def handleDispatchTaskSelected(self, dispatch_task_name:str): + """处理派单任务按钮选中, 更新计划表单相关的(计划单号、计划方量等)""" + pd_record:PDRecordModel = self.dispatch_dict.get(dispatch_task_name) # 根据派单任务名获取派单记录 + self.current_dispatch_task_select_btn_name = dispatch_task_name # 更新派单任务选择按钮对应的任务名 + self.updatePlanTableWidget(pd_record) # 更新计划表单 + + def handleDispatchTaskVolumeModified(self, dispatch_task_name:str, final_volume:float): + """处理派单任务方量修改""" + pd_record:PDRecordModel = self.dispatch_dict.get(dispatch_task_name) + if pd_record: + volume_dict = { + "ID": pd_record.ID, + "ArtifactActionID": pd_record.ArtifactActionID, + "Volume": final_volume + } + volume_json_str = json.dumps(volume_dict, ensure_ascii=False) + # print("volume_json_str: ", volume_json_str) + self.plan_volume_modified_signal.emit(volume_json_str) + + def updatePlanTableWidget(self, pd_record:PDRecordModel): + """更新计划表单""" + def format_plan_number(num): + # 格式化计划单号 + # 保留最后5位,再补零 + remainder = num % 100000 + return f"{remainder:05d}" + + if pd_record and hasattr(self, "plan_table_widget"): + plan_number = format_plan_number(pd_record.ID) # 计划单号 + self.plan_table_widget.set_plan_no(f"PD{plan_number}") # 更新计划表单的计划单号 (PD+表单ID) + self.plan_table_widget.set_plan_volume(pd_record.FBetonVolume) # 更新计划表单的计划方量 + self.plan_table_widget.set_plan_ratio(pd_record.ProduceMixID) # 更新计划表单的计划配比 + # 派单模式(1自动派单 2手动派单 0未知 )Mode: int = 0 + status_mapping = { + 0: "", # 未知 + 1: "计划中", + 2: "派单中", # 已下发 # 付工说改为派单中更好 + 3: "已超时", + 4: "未扫码" + } + status_text = status_mapping.get(pd_record.Status) + self.plan_table_widget.set_status(status_text) + + if status_text == "计划中": # 计划表单只有派单状态为计划中,才能够修改方量 + self.plan_table_widget.set_modify_volume_status(True) + else: + self.plan_table_widget.set_modify_volume_status(False) + + # 更新计划表单对应的任务名 + self.plan_table_widget.set_plan_table_task_name(self.current_dispatch_task_select_btn_name) # 更新 派单任务widget的坐标 def update_dispatch_task_position(self): @@ -480,13 +623,15 @@ class MainWindow(QWidget): 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): + def SetPDRecordTask(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 hasattr(self, "plan_table_widget") and task_name == self.current_dispatch_task_select_btn_name: + self.updatePlanTableWidget(pd_record) # 刷新计划表单 if __name__ == "__main__": import sys diff --git a/view/widgets/arc_progress_widget.py b/view/widgets/arc_progress_widget.py index 0aeca4f..113be42 100644 --- a/view/widgets/arc_progress_widget.py +++ b/view/widgets/arc_progress_widget.py @@ -278,6 +278,14 @@ class ArcProgressWidget(QWidget): # 管片编号设置 def setSegmentNumber(self, segmentNumberStr:str): self.segment_number_label.setText(segmentNumberStr) + + # 环号设置 + def setRingNumber(self, ringNumber:int): + self.ring_number_label.setText(f"环号: {ringNumber}") + + # 管片尺寸(规格)设置 (比如:6900*1500) + def setSegmentSize(self, SizeSpecification:str): + self.segment_size_label.setText(SizeSpecification) if __name__ == "__main__": diff --git a/view/widgets/dispatch_details_dialog.py b/view/widgets/dispatch_details_dialog.py index 77ddedd..b3ef437 100644 --- a/view/widgets/dispatch_details_dialog.py +++ b/view/widgets/dispatch_details_dialog.py @@ -337,10 +337,10 @@ class DispatchDetailsDialog(QDialog): self.modify_btn.show() # 2、修改 派单方量标签的值 - volume_label = self.rows[4].value + # volume_label = self.rows[4].value # modifyed_value 为float类型, 一位小数 modifyed_value = self.volume_value_adjuster.get_value() - volume_label.setText(str(modifyed_value)) + # volume_label.setText(str(modifyed_value)) # 3、发送派单方量确定修改的信号 (发送派单任务名 + 确认修改之后的派单方量) self.confirm_modify_volume.emit(self.dispatch_task_name, modifyed_value) @@ -383,6 +383,16 @@ class DispatchDetailsDialog(QDialog): if 0 <= row < len(self.rows): self.rows[row].value.setText(str(new_value_text) if new_value_text is not None else "") + def set_dispatch_task_name(self, task_name:str): + """设置/刷新 派单任务名""" + self.dispatch_task_name = task_name + + def set_modify_volume_status(self, status:bool): + """设置是否能够在派单详情界面修改方量, + status为False即不能修改方量, 为True表示能够修改方量 + """ + self.modify_btn.setVisible(status) + # 测试代码 if __name__ == "__main__": diff --git a/view/widgets/plan_widget.py b/view/widgets/plan_widget.py index 83c3249..d2409fe 100644 --- a/view/widgets/plan_widget.py +++ b/view/widgets/plan_widget.py @@ -1,6 +1,6 @@ from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, QApplication) -from PySide6.QtCore import Qt +from PySide6.QtCore import Qt, Signal, QTimer from PySide6.QtGui import QPainter, QPixmap from .value_adjuster import ValueAdjuster from .switch_button import SwitchButton @@ -10,6 +10,14 @@ import resources.resources_rc from utils.image_paths import ImagePaths class PlanWidget(QWidget): + # 自动派单切换信号 + # True: 自动派单 False: 手动派单 + auto_dispatch_signal = Signal(bool) + + # 计划表单最终的确认的修改的方量 + # 对应的任务名, 最终的方量 + final_modify_volume_signal = Signal(str, float) + def __init__(self, parent=None): super().__init__(parent) # 加载背景图 @@ -25,6 +33,16 @@ class PlanWidget(QWidget): "auto_dispatch": None # 自动派单(SwitchButton) } + # ================================================== + # 用于计划表单的修改方量的最终确认 + # 1、确认最终修改的方量的计时器(超时代表着确认了最终的方量) + self.volume_timer = QTimer(self) + self.volume_timer.setInterval(2500) # 2.5秒延迟(根据需求调整) + self.volume_timer.setSingleShot(True) # 单次触发:避免重复执行 + self.volume_timer.timeout.connect(self._sync_final_volume) + # 2、该计划表单对应的任务名 + self.plan_table_task_name = None + # 主垂直布局 main_layout = QVBoxLayout(self) main_layout.setContentsMargins(13, 5, 6, 15) @@ -63,6 +81,8 @@ class PlanWidget(QWidget): row2_layout.addWidget(label2) self.fangliang_adjuster = ValueAdjuster() # 导入的方量调整控件 + self.fangliang_adjuster.minus_btn.clicked.connect(self._reset_volume_timer) + self.fangliang_adjuster.plus_btn.clicked.connect(self._reset_volume_timer) row2_layout.addWidget(self.fangliang_adjuster) main_layout.addLayout(row2_layout) self.controls["volume"] = self.fangliang_adjuster @@ -75,7 +95,7 @@ class PlanWidget(QWidget): row3_layout.addWidget(status_icon3) row3_layout.addSpacing(4) - label3 = QLabel("计划配比") + label3 = QLabel("配合比") label3.setStyleSheet("font-size: 18px; color: #03f5ff;") row3_layout.addWidget(label3) @@ -117,11 +137,24 @@ class PlanWidget(QWidget): row5_layout.addWidget(label5) self.switch = SwitchButton() + self.switch.switched.connect(self.auto_dispatch_signal) self.switch.setChecked(True) row5_layout.addWidget(self.switch, alignment=Qt.AlignLeft) main_layout.addLayout(row5_layout) self.controls["auto_dispatch"] = self.switch + def _reset_volume_timer(self): + """每次调整方量时,重置定时器(倒计时重新开始)""" + if self.volume_timer.isActive(): # 如果定时器正在运行,先停止 + self.volume_timer.stop() + self.volume_timer.start() # 重启定时器 + + def _sync_final_volume(self): + """同步 确认的最终的修改方量""" + final_volume = self.fangliang_adjuster.get_value() + # print("最终确认的方量为:", final_volume) + self.final_modify_volume_signal.emit(self.plan_table_task_name, final_volume) + def paintEvent(self, event): """绘制背景图片""" painter = QPainter(self) @@ -150,10 +183,21 @@ class PlanWidget(QWidget): self.controls["status"].setText(new_status) def set_auto_dispatch(self, is_checked:bool): - """修改自动派单开关状态, true: 开启自动派单, False: 关闭自动派单""" + """修改自动派单开关状态, true: 自动派单, False: 手动派单""" if self.controls["auto_dispatch"]: self.controls["auto_dispatch"].setChecked(is_checked) + def set_modify_volume_status(self, status:bool): + """设置 计划表单中修改方量控件的状态, 是否能够修改方量 + status: True, 能够修改方量 + False, 不能修改方量 + """ + self.fangliang_adjuster.setEnabled(status) + + def set_plan_table_task_name(self, task_name:str): + """设置 计划表单对应的选中任务名""" + self.plan_table_task_name = task_name + if __name__ == "__main__": app = QApplication(sys.argv) widget = PlanWidget() diff --git a/view/widgets/task_widget.py b/view/widgets/task_widget.py index 161ca04..4e94046 100644 --- a/view/widgets/task_widget.py +++ b/view/widgets/task_widget.py @@ -11,8 +11,10 @@ from utils.image_paths import ImagePaths 任务控件,如:管片任务、派单任务 """ class TaskWidget(QWidget): - # 任务详情信号: task1表示第一条任务 + # 任务详情信号: task1表示第一条任务 (用于详情对话框) task_details_signal = Signal(str) + # 任务选择按钮选中的信号 (用于上方的计划表单) + task_selected_signal = Signal(str) def __init__(self, taskTitle:str, parent=None): super().__init__(parent) @@ -40,6 +42,7 @@ class TaskWidget(QWidget): # 用字典存储每个任务的可修改控件(键:任务名,值:控件字典) self.task_controls = {} # 结构:{"task1": {"volume_label": xxx, "time_label": xxx, ...}, ...} + self.current_selected_task = None # 选择按钮,当前选中的任务的任务名 # 三条任务条目 self._add_task("task1", "SHRB1-3", ImagePaths.TASK_RECT1) @@ -87,12 +90,17 @@ class TaskWidget(QWidget): }} """) select_btn.setCheckable(True) + select_btn.clicked.connect(lambda checked, tn=task_name: self._on_select_btn_clicked(tn, checked)) controls["select_btn"] = select_btn row1_layout.addWidget(select_btn) # 任务编号 task_id_label = QLabel(task_id) task_id_label.setStyleSheet("font-size: 18px; color: #16ffff;padding-left: 6px;") + # 1. 设置鼠标样式为手型,提示可点击 + task_id_label.setCursor(Qt.PointingHandCursor) + # 2. 绑定点击事件:点击标签时,选中对应的select_btn + task_id_label.mousePressEvent = lambda event, tn=task_name: self._on_task_id_clicked(tn) controls["task_id_label"] = task_id_label row1_layout.addWidget(task_id_label) @@ -124,7 +132,7 @@ class TaskWidget(QWidget): row2_layout = QHBoxLayout() # 方量标签 volume_label = QLabel("方量 200") - volume_label.setStyleSheet("color: #a1c1d7; font-size: 14px;padding-left: 19px;") + volume_label.setStyleSheet("color: #a1c1d7; font-size: 14px;padding-left: 6px;") controls["volume_label"] = volume_label row2_layout.addWidget(volume_label) @@ -138,13 +146,19 @@ class TaskWidget(QWidget): time_label.setStyleSheet("color: #a1c1d7; font-size: 14px;") controls["time_label"] = time_label row2_layout.addWidget(time_label) + + # 状态文本标签 + status_text_label = QLabel() + status_text_label.setStyleSheet("color: #16ffff; font-size: 14px;") + controls["status_text_label"] = status_text_label + row2_layout.addWidget(status_text_label) - # 状态标签 + # 状态图标标签 status_icon_label = QLabel() status_icon_label.setPixmap(QPixmap(status_icon)) controls["status_icon_label"] = status_icon_label row2_layout.addWidget(status_icon_label, alignment=Qt.AlignRight) - + # 添加水平布局2到item_layout item_layout.addLayout(row2_layout) # 分隔线 @@ -165,6 +179,42 @@ class TaskWidget(QWidget): # 发送任务详情信号 self.task_details_signal.emit(task_name) + def _on_select_btn_clicked(self, task_name: str, checked: bool): + """ + 处理选择按钮点击事件,实现互斥选中 + :param task_name: 点击的任务名(task1/task2/task3) + :param checked: 按钮是否被选中(True/False) + """ + # 1. 如果是选中操作(checked=True) + if checked: + # 取消之前选中的任务按钮 + if self.current_selected_task and self.current_selected_task != task_name: + prev_select_btn = self.task_controls[self.current_selected_task]["select_btn"] + prev_select_btn.setChecked(False) # 取消选中 + # 更新当前选中的任务 + self.current_selected_task = task_name + # 通知任务选中按钮更新了选中 + self.task_selected_signal.emit(task_name) + else: + # 2. 如果是取消选中操作(checked=False) + # 重新设为选中状态,阻止取消 (确保该按钮继续为选中状态,保证至少有一个按钮被选中) + current_select_btn = self.task_controls[task_name]["select_btn"] + current_select_btn.setChecked(True) + # 确保选中标记不丢失 + self.current_selected_task = task_name + + def _on_task_id_clicked(self, task_name: str): + """ + 点击任务编号标签时,选中对应的选择按钮(复用互斥逻辑) + :param task_name: 点击的任务名(task1/task2/task3) + """ + if task_name in self.task_controls: + # 1. 获取对应select_btn + select_btn = self.task_controls[task_name]["select_btn"] + # 2. 模拟点击相应的选择按钮 + if not select_btn.isChecked(): + select_btn.click() + # -------------------------- # 对外接口:修改任务属性 # 三个任务条目对应的任务名task_name,分别为 task1、task2、task3 @@ -185,11 +235,36 @@ class TaskWidget(QWidget): time_label = self.task_controls[task_name]["time_label"] time_label.setText(time_str) + def set_task_status(self, task_name:str, status_str: str, icon_path:str): + """修改指定任务的状态, 比如: 已下发、计划中等""" + ICON_COLOR_MAP = { + ImagePaths.TASK_RECT1: "#16ffff", + ImagePaths.TASK_RECT2: "#ffab11", + ImagePaths.TASK_RECT3: "#54f529", + ImagePaths.TASK_RECT4: "#ff6a5c", + ImagePaths.TASK_RECT5: "#f6f44b" + } + DEFAULT_COLOR = "#000000" + if task_name in self.task_controls: + status_label = self.task_controls[task_name]["status_text_label"] # 状态文本 + status_label.setText(status_str) + icon_label = self.task_controls[task_name]["status_icon_label"] # 状态图标 + icon_label.setPixmap(QPixmap(icon_path)) + # 修改状态文本的颜色 + status_text_color = ICON_COLOR_MAP.get(icon_path, DEFAULT_COLOR) + status_label.setStyleSheet(f"QLabel {{ color: {status_text_color}; font-size: 14px;}}") + def set_task_id(self, task_name:str, new_id: str): """修改指定任务的编号, 如: SHRB2-3""" if task_name in self.task_controls: task_id_label = self.task_controls[task_name]["task_id_label"] - task_id_label.setText(new_id) + task_id_label.setText(new_id) + + def set_task_select_btn_selected(self, task_name:str): + """设置 任务选择按钮选中 (主要用于刷新计划表单)""" + if task_name in self.task_controls: + task_select_btn = self.task_controls[task_name]["select_btn"] + task_select_btn.click() def get_task_volume(self, task_name:str): """