diff --git a/.idea/InsertData.iml b/.idea/InsertData.iml
index 29bca85..74d515a 100644
--- a/.idea/InsertData.iml
+++ b/.idea/InsertData.iml
@@ -4,7 +4,7 @@
-
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index db5199f..df3bfff 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -3,5 +3,5 @@
-
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 1326942..94a25f7 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -2,6 +2,5 @@
-
\ No newline at end of file
diff --git a/API/send_data_test.py b/API/send_data_test.py
index 4159774..a7d031c 100644
--- a/API/send_data_test.py
+++ b/API/send_data_test.py
@@ -205,9 +205,10 @@ def get_not_pour_info():
"Code": 200,
"Message": None,
"Data": [
+
{
"ArtifactID": "QR1B12000151AD",
- "ArtifactActionID": 346482967298117,
+ "ArtifactActionID": 346482967298138,
"ArtifactIDVice1": "Q00001AD",
"ProduceRingNumber": 1,
"MouldCode": "SHR2B1-9",
@@ -215,16 +216,33 @@ def get_not_pour_info():
"RingTypeCode": "R22",
"SizeSpecification": "6900*1500",
"BuriedDepth": "中埋",
- "BlockNumber": "B1",
+ "BlockNumber": "F",
"HoleRingMarking": "否",
"GroutingPipeMarking": "否",
"PolypropyleneFiberMarking": "否",
- "BetonVolume": 2.0000,
+ "BetonVolume": 0.6,
+ "BetonTaskID": "20251020-01"
+ },
+ {
+ "ArtifactID": "QR1B12000151AD",
+ "ArtifactActionID": 3464829672981339,
+ "ArtifactIDVice1": "Q00001AD",
+ "ProduceRingNumber": 1,
+ "MouldCode": "SHR2B1-9",
+ "SkeletonID": "QR1B12000046A",
+ "RingTypeCode": "R22",
+ "SizeSpecification": "6900*1500",
+ "BuriedDepth": "中埋",
+ "BlockNumber": "F",
+ "HoleRingMarking": "否",
+ "GroutingPipeMarking": "否",
+ "PolypropyleneFiberMarking": "否",
+ "BetonVolume": 0.6,
"BetonTaskID": "20251020-01"
},
{
"ArtifactID": "QR1B32000153AD",
- "ArtifactActionID": 346482967298119,
+ "ArtifactActionID": 346482967298140,
"ArtifactIDVice1": "Q00001AD",
"ProduceRingNumber": 1,
"MouldCode": "SHR2B3-9",
@@ -232,30 +250,14 @@ def get_not_pour_info():
"RingTypeCode": "R22",
"SizeSpecification": "6900*1500",
"BuriedDepth": "中埋",
- "BlockNumber": "B2",
+ "BlockNumber": "F",
"HoleRingMarking": "否",
"GroutingPipeMarking": "否",
"PolypropyleneFiberMarking": "否",
- "BetonVolume": 2.0000,
- "BetonTaskID": "20251020-01"
- },
- {
- "ArtifactID": "QR1B12000151AD",
- "ArtifactActionID": 346482967298120,
- "ArtifactIDVice1": "Q00001AD",
- "ProduceRingNumber": 1,
- "MouldCode": "SHR2B1-9",
- "SkeletonID": "QR1B12000046A",
- "RingTypeCode": "R22",
- "SizeSpecification": "6900*1500",
- "BuriedDepth": "中埋",
- "BlockNumber": "B3",
- "HoleRingMarking": "否",
- "GroutingPipeMarking": "否",
- "PolypropyleneFiberMarking": "否",
- "BetonVolume": 2.0000,
+ "BetonVolume": 0.6,
"BetonTaskID": "20251020-01"
},
+
]
}
diff --git a/InsertData_list.py b/InsertData_list.py
index 96566f2..60d0d6e 100644
--- a/InsertData_list.py
+++ b/InsertData_list.py
@@ -241,6 +241,8 @@ def _handle_two_f_blocks(f_positions, current_task, total_f_volume, artifact_lis
if f_positions == [0, 1] and task_before.get("block_number") == "F":
adjusted_volume = 0
block_number = "补方"
+ elif f_positions == [1, 2]:
+ adjusted_volume = artifact_list[0]["BetonVolume"]
else:
adjusted_volume = total_f_volume - half_volume[0]
block_number = current_task["block_number"]
diff --git a/main.py b/main.py
index 59122bb..476ab8f 100644
--- a/main.py
+++ b/main.py
@@ -27,6 +27,7 @@ def start_api_service():
api.run(host='127.0.0.1', port=5001, debug=False, threaded=True)
def main():
+ global tcp_server
api_thread = threading.Thread(target=start_api_service)
api_thread.daemon = True
api_thread.start()
@@ -42,7 +43,7 @@ def main():
# 初始化服务
api_client = APIClient()
- task_service = TaskService()
+ task_service = TaskService(tcp_server)
monitoring_service = MonitoringService(tcp_server)
# 步骤1:获取AppID
@@ -101,6 +102,10 @@ def main():
# 步骤3:获取任务单信息
task_service.insert_into_produce_table(sql_db, task_info, task["beton_volume"], erp_id,
task["artifact_id"], 1)
+ with monitoring_service.tasks_lock:
+ monitoring_service.monitored_tasks.add(erp_id)
+ monitoring_service.inserted_tasks[erp_id] = task["artifact_id"]
+ print(f"任务 {erp_id} (ArtifactID: {task['artifact_id']}) 已添加到监控列表")
finally:
sql_db.close()
diff --git a/services/monitoring_service.py b/services/monitoring_service.py
index c02059b..d1dcdfd 100644
--- a/services/monitoring_service.py
+++ b/services/monitoring_service.py
@@ -7,6 +7,7 @@ from database.access_db import AccessDB
from database.sql_server import SQLServerDB
from config.settings import ACCESS_DB_PATH, ACCESS_DB_PASSWORD, MONITOR_INTERVAL
from tcp.server import TCPServer
+from services.task_service import TaskService
class MonitoringService:
def __init__(self, tcp_server):
@@ -15,6 +16,7 @@ class MonitoringService:
self.monitored_tasks = set()
self.inserted_tasks = {}
self.tasks_lock = threading.Lock()
+ self.task_service = TaskService(tcp_server)
def monitor_access_flag_changes(self):
"""监控Access数据库中派发任务的Flag状态"""
@@ -44,8 +46,6 @@ class MonitoringService:
erp_ids_str = [str(erp_id) for erp_id in tasks_to_monitor]
deleted_from_sql_tasks = set(erp_ids_str) - existing_tasks_in_sql
- print(f"SQL Server中仍存在的任务: {existing_tasks_in_sql}")
- print(f"已从SQL Server删除的任务: {deleted_from_sql_tasks}")
# 只有已从SQL Server删除的任务才需要在Access中查找
if not deleted_from_sql_tasks:
@@ -75,8 +75,6 @@ class MonitoringService:
current_flag = current_tasks.get(erp_id_str, "")
previous_flag = self.task_flags.get(erp_id_str, "")
- # 添加调试信息
- print(f"检查任务 {erp_id} - 当前Flag: '{current_flag}', 之前Flag: '{previous_flag}'")
# 如果状态发生变化
if current_flag != previous_flag:
@@ -98,119 +96,114 @@ class MonitoringService:
def _handle_flag_status_change(self, erp_id, current_flag, artifact_id):
"""处理标志状态变化"""
if current_flag.endswith('d'):
- self._handle_status_d(erp_id, artifact_id)
+ self._handle_status_d(erp_id,artifact_id)
elif current_flag.endswith('w'):
- self._handle_status_w(erp_id, artifact_id)
+ self._handle_status_w(erp_id,artifact_id)
elif current_flag.endswith('n'):
- self._handle_status_n(erp_id, artifact_id)
+ self._handle_status_n(erp_id,artifact_id)
elif current_flag.endswith('p'):
- self._handle_status_p(erp_id, artifact_id)
+ self._handle_status_p(erp_id,artifact_id)
elif current_flag.endswith('x'):
- self._handle_status_x(erp_id, artifact_id)
+ self._handle_status_x(erp_id,artifact_id)
- def _handle_status_d(self, erp_id, artifact_id):
+ def _handle_status_d(self,erp_id, artifact_id):
"""处理状态'd' - 未进行生产"""
- print(f"派发任务 ErpID {erp_id}: 未进行生产")
- # 调用同事提供的状态更新函数
+ print(f"派发任务 artifact_id {artifact_id}: 未进行生产")
try:
print(1)
- update_custom_table_status(erp_id, "未进行生产")
+ self.task_service.update_custom_table_status(artifact_id, "未进行生产")
except Exception as e:
print(f"更新状态时出错: {e}")
- # 发送数据给TCP客户端(只发送erp_id和状态)
try:
status_data = {
- "erp_id": erp_id,
- "status": "未进行生产"
+ "erp_id":erp_id,
+ "artifact_id": artifact_id,
+ "flag": "未进行生产"
}
self.tcp_server.send_data(status_data)
except Exception as e:
print(f"发送状态数据给TCP客户端时出错: {e}")
- def _handle_status_w(self, erp_id, artifact_id):
+ def _handle_status_w(self, erp_id,artifact_id):
"""处理状态'w' - 正在生产中"""
- print(f"派发任务 ErpID {erp_id}: 正在生产中")
- # 调用同事提供的状态更新函数
+ print(f"派发任务 artifact_id {artifact_id}: 正在生产中")
try:
print(2)
- update_custom_table_status(erp_id, "正在生产中")
+ self.task_service.update_custom_table_status(artifact_id, "正在生产中")
except Exception as e:
print(f"更新状态时出错: {e}")
- # 发送数据给TCP客户端(只发送erp_id和状态)
try:
status_data = {
- "erp_id": erp_id,
- "status": "正在生产中"
+ "erp_id":erp_id,
+ "artifact_id": artifact_id,
+ "flag": "正在生产中"
}
self.tcp_server.send_data(status_data)
except Exception as e:
print(f"发送状态数据给TCP客户端时出错: {e}")
- def _handle_status_n(self, erp_id, artifact_id):
+ def _handle_status_n(self,erp_id, artifact_id):
"""处理状态'n' - 生产完毕"""
- print(f"派发任务 ErpID {erp_id}: 生产完毕")
+ print(f"派发任务 artifact_id {artifact_id}: 生产完毕")
# 任务完成,可以从监控列表中移除
with self.tasks_lock:
- self.monitored_tasks.discard(erp_id)
- print(f"派发任务 ErpID {erp_id} 已完成,停止监控")
- # 调用同事提供的状态更新函数
+ self.monitored_tasks.discard(artifact_id)
+ print(f"派发任务 artifact_id {artifact_id} 已完成,停止监控")
try:
print(3)
- update_custom_table_status(erp_id, "生产完毕")
+ self.task_service.update_custom_table_status(artifact_id, "生产完毕")
except Exception as e:
print(f"更新状态时出错: {e}")
- # 发送数据给TCP客户端(只发送erp_id和状态)
try:
status_data = {
- "erp_id": erp_id,
- "status": "生产完毕"
+ "erp_id":erp_id,
+ "artifact_id": artifact_id,
+ "flag": "生产完毕"
}
self.tcp_server.send_data(status_data)
except Exception as e:
print(f"发送状态数据给TCP客户端时出错: {e}")
- def _handle_status_p(self, erp_id, artifact_id):
+ def _handle_status_p(self, erp_id,artifact_id):
"""处理状态'p' - 生产中断"""
- print(f"派发任务 ErpID {erp_id}: 生产中断")
+ print(f"派发任务 ErpID {artifact_id}: 生产中断")
# 任务中断,可以从监控列表中移除
with self.tasks_lock:
- self.monitored_tasks.discard(erp_id)
- print(f"派发任务 ErpID {erp_id} 已中断,停止监控")
- # 调用同事提供的状态更新函数
+ self.monitored_tasks.discard(artifact_id)
+ print(f"派发任务 ErpID {artifact_id} 已中断,停止监控")
try:
print(4)
- update_custom_table_status(erp_id, "生产中断")
+ self.task_service.update_custom_table_status(artifact_id, "生产中断")
except Exception as e:
print(f"更新状态时出错: {e}")
- # 发送数据给TCP客户端(只发送erp_id和状态)
try:
status_data = {
"erp_id": erp_id,
- "status": "生产中断"
+ "artifact_id": artifact_id,
+ "flag": "生产中断"
}
self.tcp_server.send_data(status_data)
except Exception as e:
print(f"发送状态数据给TCP客户端时出错: {e}")
- def _handle_status_x(self, erp_id, artifact_id):
+ def _handle_status_x(self, erp_id,artifact_id):
"""处理状态'x' - 数据已接收"""
- print(f"派发任务 ErpID {erp_id}: 数据已接收")
- # 调用同事提供的状态更新函数
+ print(f"派发任务 ErpID {artifact_id}: 已插入")
try:
print(5)
- # update_custom_table_status(erp_id, "数据已接收")
+ self.task_service.update_custom_table_status(artifact_id, "已插入")
except Exception as e:
print(f"更新状态时出错: {e}")
- # 发送数据给TCP客户端(只发送erp_id和状态)
try:
status_data = {
- "erp_id": erp_id,
- "status": "数据已接收"
+ "erp_id":erp_id,
+ "artifact_id": artifact_id,
+ "flag": "已插入"
}
self.tcp_server.send_data(status_data)
except Exception as e:
diff --git a/services/task_service.py b/services/task_service.py
index 00da6a9..0baa681 100644
--- a/services/task_service.py
+++ b/services/task_service.py
@@ -5,14 +5,17 @@ from database.access_db import AccessDB
from database.sql_server import SQLServerDB
from config.settings import ACCESS_DB_PATH, ACCESS_DB_PASSWORD
from utils.helpers import get_f_block_positions
+import threading
+import time
class TaskService:
- def __init__(self):
+ def __init__(self, tcp_server=None):
self.api_client = APIClient()
self.half_volume = [0, 0]
- self.task_before = None
+ self.task_before = {"block_number":None, "beton_volume":None, "artifact_id":None}
self.artifact_timestamps = {}
+ self.tcp_server = tcp_server
def process_not_pour_info(self):
"""处理未浇筑信息"""
@@ -31,6 +34,11 @@ class TaskService:
# 处理当前任务
current_task = self._process_current_task(artifact_list[0])
+ # 根据F块情况处理任务
+ task_result = self._handle_tasks_by_f_blocks(
+ f_block_count, f_positions, current_task,
+ f_blocks, total_f_volume, artifact_list
+ )
# 更新上一个任务信息
self.task_before = {
"beton_task_id": current_task["beton_task_id"],
@@ -38,13 +46,6 @@ class TaskService:
"artifact_id": current_task["artifact_id"],
"block_number": current_task["block_number"]
}
-
- # 根据F块情况处理任务
- task_result = self._handle_tasks_by_f_blocks(
- f_block_count, f_positions, current_task,
- f_blocks, total_f_volume, artifact_list
- )
-
return task_result
def _process_f_blocks(self, artifact_list):
@@ -98,41 +99,49 @@ class TaskService:
def _handle_multiple_f_blocks(self, current_task, total_f_volume, artifact_list):
"""处理多个F块的情况"""
- adjusted_volume = total_f_volume - self.half_volume[0]
+ if self.task_before.get("block_number") == "F":
+ print("报警:,超出正常补块逻辑")
+ else:
+ adjusted_volume = total_f_volume - self.half_volume[0]
- tasks = [{
- "beton_task_id": current_task["beton_task_id"],
- "beton_volume": adjusted_volume,
- "artifact_id": current_task["artifact_id"],
- "block_number": current_task["block_number"],
- }]
+ tasks = [{
+ "beton_task_id": current_task["beton_task_id"],
+ "beton_volume": adjusted_volume,
+ "artifact_id": current_task["artifact_id"],
+ "block_number": current_task["block_number"],
+ }]
- send_list = [{
- "beton_task_id": current_task["beton_task_id"],
- "beton_volume": adjusted_volume,
- "artifact_id": current_task["artifact_id"],
- "block_number": current_task["block_number"],
- "beton_grade": current_task["task_data"]["BetonGrade"],
- "mix_id": current_task["task_data"]["MixID"],
- "time": self.artifact_timestamps.get(current_task["artifact_id"], datetime.now())
- }]
+ send_list = [{
+ "beton_task_id": current_task["beton_task_id"],
+ "beton_volume": adjusted_volume,
+ "artifact_id": current_task["artifact_id"],
+ "block_number": current_task["block_number"],
+ "beton_grade": current_task["task_data"]["BetonGrade"],
+ "mix_id": current_task["task_data"]["MixID"],
+ "time": self.artifact_timestamps.get(current_task["artifact_id"], datetime.now())
+ }]
- # 处理后续任务
- self._append_additional_tasks(send_list, artifact_list, [0, 0])
+ # 处理后续任务
+ self._append_additional_tasks(send_list, artifact_list, [0, 0])
- # 更新时间戳
- self._update_artifact_timestamps(send_list)
+ # 更新时间戳
+ self._update_artifact_timestamps(send_list)
- return tasks, artifact_list, send_list, self.half_volume
+ return tasks, artifact_list, send_list, self.half_volume
def _handle_two_f_blocks(self, f_positions, current_task, total_f_volume, artifact_list):
"""处理两个F块的情况"""
if f_positions == [0, 1] and self.task_before.get("block_number") == "F":
adjusted_volume = 0
block_number = "补方"
- else:
+ elif f_positions == [1, 2]:
+ adjusted_volume = artifact_list[0]["BetonVolume"]
+ block_number = current_task["block_number"]
+ elif f_positions == [0, 1] and self.task_before.get("block_number") != "F":
adjusted_volume = total_f_volume - self.half_volume[0]
block_number = current_task["block_number"]
+ else:
+ print("报警")
tasks = [{
"beton_task_id": current_task["beton_task_id"],
@@ -153,9 +162,7 @@ class TaskService:
# 处理后续任务
volumes = [adjusted_volume,
- artifact_list[2]["BetonVolume"] if len(artifact_list) > 2 else 0] if f_positions == [0,
- 1] and self.task_before.get(
- "block_number") == "F" else [0, 0]
+ artifact_list[2]["BetonVolume"] if len(artifact_list) > 2 else 0] if f_positions == [0, 1] and self.task_before.get("block_number") == "F" else [0, 0]
self._append_additional_tasks(send_list, artifact_list, volumes)
# 更新时间戳
@@ -305,7 +312,7 @@ class TaskService:
def insert_into_produce_table(self, connection, task_info, beton_volume, erp_id, artifact_id, status):
"""插入数据到Produce表"""
sql_db = SQLServerDB()
- if status == "1":
+ if status == 1:
# 准备插入数据
insert_data = {
"ErpID": erp_id,
@@ -331,14 +338,14 @@ class TaskService:
try:
# 假设同事提供的函数名为 save_to_custom_table
# 参数包括: MISID(即erp_id), Flag, TaskID, ProduceMixID, ProjectName, BetonGrade, 调整后的方量
- save_to_custom_table(
+ self.save_to_custom_table(
misid=erp_id,
- flag="1", # 初始Flag值
+ flag="已插入", # 初始Flag值
task_id=task_info["TaskID"],
produce_mix_id=task_info["ProduceMixID"],
project_name=task_info["ProjectName"],
beton_grade=task_info["BetonGrade"],
- adjusted_volume=beton_volume,
+ adjusted_volume=round(beton_volume,2),
artifact_id=artifact_id
# 已经调整后的方量
)
@@ -346,21 +353,49 @@ class TaskService:
except Exception as e:
print(f"调用保存函数时出错: {e}")
+ # 发送数据给TCP客户端
+ if self.tcp_server:
+ try:
+ time.sleep(2)
+ task_data = {
+ "erp_id": erp_id, # 车号,相当于序号
+ "task_id": task_info["TaskID"], # 任务单号
+ "artifact_id": artifact_id,
+ "produce_mix_id": task_info["ProduceMixID"], # 配比号
+ "project_name": task_info["ProjectName"], # 任务名
+ "beton_grade": task_info["BetonGrade"], # 砼强度
+ "adjusted_volume": round(beton_volume,2), # 方量
+ "flag": "已插入", # 状态
+ "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S") # 时间
+ }
+ self.tcp_server.send_data(task_data)
+ print(f"任务 {artifact_id} 的数据已发送给TCP客户端")
+ except Exception as e:
+ print(f"发送数据给TCP客户端时出错: {e}")
+
return erp_id
else:
try:
- # 假设同事提供的函数名为 save_to_custom_table
# 参数包括: MISID(即erp_id), Flag, TaskID, ProduceMixID, ProjectName, BetonGrade, 调整后的方量
- save_to_custom_table(
+ self.save_to_custom_table(
misid=erp_id,
- flag="1", # 初始Flag值
+ flag="已插入", # 初始Flag值
task_id=task_info["TaskID"],
produce_mix_id=task_info["ProduceMixID"],
project_name=task_info["ProjectName"],
beton_grade=task_info["BetonGrade"],
- adjusted_volume=beton_volume,
+ adjusted_volume=round(beton_volume,2),
artifact_id=artifact_id
)
print(f"任务 {erp_id} 的数据已保存到自定义数据表")
except Exception as e:
print(f"调用保存函数时出错: {e}")
+
+
+ return erp_id
+
+ def save_to_custom_table(self,misid, flag, task_id, produce_mix_id, project_name, beton_grade, adjusted_volume, artifact_id):
+ print(f"保存到自定义数据表: MISID={misid}, Flag={flag}, TaskID={task_id}, 调整后方量={adjusted_volume}")
+
+ def update_custom_table_status(self, erp_id, status):
+ print(f"更新自定义数据表状态: ERP ID={erp_id}, 状态={status}")
diff --git a/tcp/server.py b/tcp/server.py
index 91643ff..4461c03 100644
--- a/tcp/server.py
+++ b/tcp/server.py
@@ -108,7 +108,9 @@ class TCPServer:
print(f"收到异常生产通知 - 时间: {timestamp}, ERP ID: {erp_id}")
# 调用update_custom_table_status更新数据库状态
try:
- update_custom_table_status(erp_id, "异常生产")
+ from services.task_service import TaskService
+ task_service = TaskService()
+ task_service.update_custom_table_status(erp_id, "异常生产")
print(f"数据库状态已更新为: 异常生产 (ERP ID: {erp_id})")
except Exception as e:
print(f"更新数据库状态时出错: {e}")
@@ -116,7 +118,9 @@ class TCPServer:
print(f"收到中断生产通知 - 时间: {timestamp}, ERP ID: {erp_id}")
# 调用update_custom_table_status更新数据库状态
try:
- update_custom_table_status(erp_id, "取消生产")
+ from services.task_service import TaskService
+ task_service = TaskService()
+ task_service.update_custom_table_status(erp_id, "取消生产")
print(f"数据库状态已更新为: 取消生产 (ERP ID: {erp_id})")
except Exception as e:
print(f"更新数据库状态时出错: {e}")
diff --git a/temp.py b/temp.py
index 2214966..a17eb97 100644
--- a/temp.py
+++ b/temp.py
@@ -415,7 +415,7 @@ def get_all_not_pour_info(app_id): # 添加这一行声明
{
"ArtifactID": "QR1B32000153AD",
- "ArtifactActionID": 346482967298128,
+ "ArtifactActionID": 346482967298140,
"ArtifactIDVice1": "Q00001AD",
"ProduceRingNumber": 1,
"MouldCode": "SHR2B3-9",
@@ -427,6 +427,6 @@ def get_all_not_pour_info(app_id): # 添加这一行声明
"HoleRingMarking": "否",
"GroutingPipeMarking": "否",
"PolypropyleneFiberMarking": "否",
- "BetonVolume": 0.55,
+ "BetonVolume": 0.6,
"BetonTaskID": "20251020-01"
},
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/.idea/.gitignore b/zjsh_ui_sysytem/.idea/.gitignore
deleted file mode 100644
index 359bb53..0000000
--- a/zjsh_ui_sysytem/.idea/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# 默认忽略的文件
-/shelf/
-/workspace.xml
diff --git a/zjsh_ui_sysytem/.idea/inspectionProfiles/Project_Default.xml b/zjsh_ui_sysytem/.idea/inspectionProfiles/Project_Default.xml
deleted file mode 100644
index 78dfc6d..0000000
--- a/zjsh_ui_sysytem/.idea/inspectionProfiles/Project_Default.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/.idea/inspectionProfiles/profiles_settings.xml b/zjsh_ui_sysytem/.idea/inspectionProfiles/profiles_settings.xml
deleted file mode 100644
index 105ce2d..0000000
--- a/zjsh_ui_sysytem/.idea/inspectionProfiles/profiles_settings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/.idea/misc.xml b/zjsh_ui_sysytem/.idea/misc.xml
deleted file mode 100644
index 62ef35e..0000000
--- a/zjsh_ui_sysytem/.idea/misc.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/.idea/modules.xml b/zjsh_ui_sysytem/.idea/modules.xml
deleted file mode 100644
index acf6533..0000000
--- a/zjsh_ui_sysytem/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/.idea/vcs.xml b/zjsh_ui_sysytem/.idea/vcs.xml
deleted file mode 100644
index 35eb1dd..0000000
--- a/zjsh_ui_sysytem/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/.idea/zjsh_ui_sysytem.iml b/zjsh_ui_sysytem/.idea/zjsh_ui_sysytem.iml
deleted file mode 100644
index 53e58ed..0000000
--- a/zjsh_ui_sysytem/.idea/zjsh_ui_sysytem.iml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/README.md b/zjsh_ui_sysytem/README.md
deleted file mode 100644
index edfe241..0000000
--- a/zjsh_ui_sysytem/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# zjsh_ui_sysytem
-
-中交三航精准布料浇筑要料系统
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/config/config.json b/zjsh_ui_sysytem/config/config.json
deleted file mode 100644
index 65a36b5..0000000
--- a/zjsh_ui_sysytem/config/config.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "task_id": "20250706-01",
- "project_name": "18号线二期工程",
- "section": "停车场工作井上行",
- "slump": "50~70 mm",
- "mix_ratio_id": "P2022=001",
- "request_status": "请求中",
- "material_grade": "C50P12",
- "volume": "2m³",
- "request_time": "10分钟后",
- "car_status": "移动后"
-}
diff --git a/zjsh_ui_sysytem/config/tcp_server.py b/zjsh_ui_sysytem/config/tcp_server.py
deleted file mode 100644
index b46d34a..0000000
--- a/zjsh_ui_sysytem/config/tcp_server.py
+++ /dev/null
@@ -1,191 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-'''
-# @Time : 2025/9/19 09:48
-# @Author : reenrr
-# @File : mock_server.py
-'''
-import socket
-import json
-import threading
-import time
-from datetime import datetime
-import os
-
-class TCPServerSimulator:
- def __init__(self, host='127.0.0.1', port=8888, config_file='config.json'):
- self.host = host
- self.port = port
- self.server_socket = None
- self.is_running = False
- self.client_sockets = []
- self.config_file = config_file
-
- # 初始状态为None
- self.data_template = None
-
- # 从配置文件中加载固定数据
- self.load_config_data()
-
- # 模拟数据模板
- if self.data_template is None:
- self.data_template = {
- "task_id": "None",
- "project_name": "None",
- "section": "None",
- "slump": "None",
- "mix_ratio_id": "None",
- "request_status": "None",
- "material_grade": "None",
- "volume": "None",
- "request_time": "None",
- "car_status": "None"
- }
-
- def load_config_data(self):
- """从配置文件中加载固定数据"""
- try:
- if os.path.exists(self.config_file):
- with open(self.config_file, 'r', encoding='utf-8') as f:
- self.data_template = json.load(f)
- print(f"成功从 {self.config_file} 加载配置数据")
- else:
- print(f"配置文件 {self.config_file} 不存在,将使用默认数据")
- # 创建默认配置文件
- self.create_default_config()
- except Exception as e:
- print(f"加载配置文件时发生错误:{e},将使用默认数据")
- self.data_template = None
-
- def create_default_config(self):
- """创建默认配置文件"""
- default_data = {
- "task_id": "None",
- "project_name": "None",
- "section": "None",
- "slump": "None",
- "mix_ratio_id": "None",
- "request_status": "None",
- "material_grade": "None",
- "volume": "None",
- "request_time": "None",
- "car_status": "None"
- }
-
- try:
- with open(self.config_file, 'w', encoding='utf-8') as f:
- json.dump(default_data, f, ensure_ascii=False, indent=4)
- print(f"已创建默认配置文件 {self.config_file}")
- self.data_template = default_data
- except Exception as e:
- print(f"创建默认配置文件时发生错误: {e}")
- self.data_template = None
-
- def start(self):
- """启动服务器"""
- self.is_running = True
- self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.server_socket.bind((self.host, self.port))
- self.server_socket.listen(5)
- print(f"服务器已启动,监听 {self.host}:{self.port}...")
-
- # 启动接受连接的线程
- accept_thread = threading.Thread(target=self.accept_connections, daemon=True)
- accept_thread.start()
-
- try:
- while self.is_running:
- time.sleep(1)
- except KeyboardInterrupt:
- print("\n服务器正在关闭...")
- self.stop()
-
- def accept_connections(self):
- """接受客户端连接"""
- while self.is_running:
- try:
- client_socket, client_address = self.server_socket.accept()
- self.client_sockets.append(client_socket)
- print(f"客户端 {client_address} 已连接")
-
- # 发送数据
- data = self.generate_simulated_data()
- self.send_data(client_socket, data)
- print(f"已向客户端 {client_address} 发送数据:{data}")
-
- # 启动一个线程监听客户端发送的指令
- threading.Thread(
- target=self.listen_client_commands,
- args=(client_socket,client_address),
- daemon=True
- ).start()
-
- except Exception as e:
- if self.is_running:
- print(f"接受连接时发生错误: {e}")
- break
-
- def listen_client_commands(self, client_socket, client_address):
- """监听客户端发送的指令"""
- while self.is_running and client_socket in self.client_sockets:
- try:
- # 接收客户端发送的指令
- data = client_socket.recv(1024).decode('utf-8').strip()
- if data:
- print(f"客户端 {client_address} 发送指令: {data}")
- else:
- print(f"客户端 {client_address} 已断开连接")
- self.client_sockets.remove(client_socket)
- client_socket.close()
- break
- except Exception as e:
- print(f"监听客户端 {client_address} 指令时发生错误: {e}")
- self.client_sockets.remove(client_socket)
- client_socket.close()
- break
-
- def generate_simulated_data(self):
- """生成模拟的状态数据"""
- if self.data_template is None:
- return None
-
- data = self.data_template.copy()
- data["timestamp"] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
-
- return data
-
- def send_data(self, client_socket, data):
- """向客户端发送数据"""
- try:
- # 转换为JSON字符串并添加换行符作为结束标记
- if data is None:
- data_str = json.dumps(None) + "\n"
- else:
- data_str = json.dumps(data) + "\n"
- client_socket.sendall(data_str.encode('utf-8'))
- except Exception as e:
- print(f"向客户端 {client_socket.getpeername()} 发送数据时发生错误: {e}")
-
- def stop(self):
- """停止服务器"""
- self.is_running = False
-
- # 关闭所有客户端连接
- for sock in self.client_sockets:
- try:
- sock.close()
- except Exception as e:
- print(f"关闭客户端连接时发生错误: {e}")
-
- # 关闭服务器套接字
- if self.server_socket:
- try:
- self.server_socket.close()
- except Exception as e:
- print(f"关闭服务器套接字时发生错误: {e}")
-
- print("服务器已关闭")
-
-if __name__ == '__main__':
- server = TCPServerSimulator(host='127.0.0.1', port=8888)
- server.start()
diff --git a/zjsh_ui_sysytem/img.png b/zjsh_ui_sysytem/img.png
deleted file mode 100644
index 975dfcd..0000000
Binary files a/zjsh_ui_sysytem/img.png and /dev/null differ
diff --git a/zjsh_ui_sysytem/img_1.png b/zjsh_ui_sysytem/img_1.png
deleted file mode 100644
index 21a7abc..0000000
Binary files a/zjsh_ui_sysytem/img_1.png and /dev/null differ
diff --git a/zjsh_ui_sysytem/img_2.png b/zjsh_ui_sysytem/img_2.png
deleted file mode 100644
index 2799737..0000000
Binary files a/zjsh_ui_sysytem/img_2.png and /dev/null differ
diff --git a/zjsh_ui_sysytem/main1.py b/zjsh_ui_sysytem/main1.py
deleted file mode 100644
index f844033..0000000
--- a/zjsh_ui_sysytem/main1.py
+++ /dev/null
@@ -1,587 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-'''
-# @Time : 2025/9/10 11:29
-# @Author : reenrr
-# @File : test.py
-'''
-import sys
-from PySide6.QtWidgets import (
- QApplication, QWidget, QVBoxLayout, QHBoxLayout,
- QLabel, QFrame, QSizePolicy, QPushButton
-)
-from PySide6.QtCore import Qt, QTimer, QPoint, QSize, Slot
-from PySide6.QtGui import QFont, QPainter, QColor, QPen, QIcon
-from datetime import datetime
-from PySide6.QtNetwork import QTcpSocket, QAbstractSocket
-import json
-import os
-
-
-# -----------
-# 参数配置
-# -----------
-tcp_server_host = "127.0.0.1"
-tcp_server_port = 8888
-
-# 数据保存目录
-SAVE_DIR = "operation_records"
-
-class StatusMonitor(QWidget):
- """
- 中交三航精准布料浇筑要料系统 - 主界面类(深色主题)
- 使用TCP进行数据传输(客户端模型,与TCP服务器通信)
- """
-
- def __init__(self, parent=None):
- """构造函数:初始化主界面的UI布局、控件和定时器"""
- super().__init__(parent=parent)
- self.is_running = False # 系统运行状态标记
- self.current_datetime = self.get_current_time() # 当前日期时间
- # 缓存服务端发送的最新JSON数据
- self.latest_json_data = {}
-
- # ---------------
- # TCP客户端核心配置
- # ---------------
- self.tcp_socket = QTcpSocket(self) # TCP socket实例
- self.tcp_server_host = tcp_server_host
- self.tcp_server_port = tcp_server_port
- self.is_tcp_connected = False # TCP连接状态标记
-
- # 绑定TCP信号与槽(事件驱动)
- self._bind_tcp_signals()
-
- # 窗口基础设置
- self.setWindowTitle("中交三航精准布料浇筑要料系统")
- self.setGeometry(100, 100, 850, 500) # 设置窗口位置和大小
- self.setStyleSheet("background-color: #121212;") # 窗口背景设为深黑色
-
- # 初始化主布局(垂直布局)
- self.mainLayout = QVBoxLayout(self)
- self.mainLayout.setContentsMargins(10, 40, 10, 10) # 上边距留空用于显示日期
- self.mainLayout.setSpacing(10) # 相邻控件的间距
-
- # 初始化界面组件
- self._init_title_label()
- self._init_status_container()
- self._init_timers()
- self._init_save_dir()
-
- # ----------------
- # 客户端自动后自动连接服务端
- # ----------------
- print(f"客户端启动,自动连接服务端{self.tcp_server_host}:{self.tcp_server_port}...")
- self.tcp_socket.connectToHost(self.tcp_server_host, self.tcp_server_port)
-
- def _init_save_dir(self):
- """初始化数据保存目录"""
- if not os.path.exists(SAVE_DIR):
- os.makedirs(SAVE_DIR)
- print(f"已创建数据保存目录:{os.path.abspath(SAVE_DIR)}")
- else:
- print(f"数据保存目录已存在:{os.path.abspath(SAVE_DIR)}")
-
- def _bind_tcp_signals(self):
- """绑定TCP socket的核心信号(连接、断开、接收数据、错误)"""
- # 连接成功信号
- self.tcp_socket.connected.connect(self._on_tcp_connected)
- # 断开连接信号
- self.tcp_socket.disconnected.connect(self._on_tcp_disconnected)
- # 接收数据信号(有新数据时触发)
- self.tcp_socket.readyRead.connect(self._on_tcp_data_received)
- # 错误信号(连接/通信出错时触发)
- self.tcp_socket.errorOccurred.connect(self._on_tcp_error)
-
- def _init_title_label(self):
- """初始化系统标题标签"""
- titleLabel = QLabel("中交三航精准布料浇筑要料系统")
- titleLabel.setStyleSheet("""
- QLabel {
- color: #00FF9D;
- font-size: 20px;
- font-weight: bold;
- }
- """)
- titleLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
- titleLabel.setFont(QFont("Microsoft YaHei", 24, QFont.Bold))
- self.mainLayout.addWidget(titleLabel)
-
- def _init_status_container(self):
- """初始化核心状态监控容器(包含状态组和操作按钮)"""
- self.bigContainer = QFrame()
- self.bigContainer.setStyleSheet("""
- QFrame {
- background-color: #1E1E1E;
- border: 2px solid #333333;
- border-radius: 8px;
- }
- """)
- self.bigContainer.setSizePolicy(
- QSizePolicy.Policy.Expanding,
- QSizePolicy.Policy.Expanding
- )
-
- containerLayout = QVBoxLayout(self.bigContainer)
- containerLayout.setContentsMargins(20, 20, 20, 20)
-
- self._init_status_groups(containerLayout)
- self._init_operation_buttons(containerLayout)
-
- self.mainLayout.addWidget(self.bigContainer, 1)
-
- def _init_status_groups(self, parent_layout):
- """初始化左右信息(各包含5个状态项)"""
- statusWidget = QWidget()
- statusLayout = QHBoxLayout(statusWidget)
- statusLayout.setContentsMargins(0, 0, 0, 0)
- statusLayout.setSpacing(30) # 减小中间空白间距(原30)
-
- leftGroup = QWidget()
- leftLayout = QVBoxLayout(leftGroup)
- leftLayout.setSpacing(15)
- leftLayout.setContentsMargins(30, 0, 0, 0) # 左边组左内边距设为20,增加左边留白
-
- rightGroup = QWidget()
- rightLayout = QVBoxLayout(rightGroup)
- rightLayout.setSpacing(15)
- rightLayout.setContentsMargins(0, 0, 30, 0) # 右边组右内边距设为20,增加右边留白(若需左边也留白,可设左内边距)
-
- # 左边5个状态项及对应初始值
- leftStatusInfo = [
- {"name": "任务单号", "value": "20250706-01", "api_field": "task_id"},
- {"name": "工程名称", "value": "18号线二期工程", "api_field": "project_name"},
- {"name": "区间段", "value": "停车场工作并上行", "api_field": "section"},
- {"name": "坍落度", "value": "50~70 mm", "api_field": "slump"},
- {"name": "配合比编号", "value": "P2022=001", "api_field": "mix_ratio_id"}
- ]
- # 右边5个状态项及对应初始值
- rightStatusInfo = [
- {"name": "要料状态", "value": "请求中", "api_field": "request_status"},
- {"name": "要料标号", "value": "C50P12", "api_field": "material_grade"},
- {"name": "要料方量", "value": "2m³", "api_field": "volume"},
- {"name": "要料时间", "value": "2分钟后", "api_field": "request_time"},
- {"name": "小车状态", "value": "移动后", "api_field": "car_status"}
- ]
- self.statusWidgets = []
-
- # 处理左边状态项
- for info in leftStatusInfo:
- statusItem = self._create_status_item(info)
- leftLayout.addWidget(statusItem)
-
- # 处理右边状态项
- for info in rightStatusInfo:
- statusItem = self._create_status_item(info)
- rightLayout.addWidget(statusItem)
-
- statusLayout.addWidget(leftGroup)
- statusLayout.addStretch(0) # 减小中间空白比例(原1)
- statusLayout.addWidget(rightGroup)
-
- parent_layout.addWidget(statusWidget)
-
- def _create_status_item(self, info):
- """创建单个状态项"""
- statusItem = QFrame()
- statusItem.setStyleSheet("""
- QFrame {
- background-color: #2D2D2D;
- border: 1px solid #444444;
- border-radius: 6px;
- padding: 10px;
- }
- """)
- statusItem.setFixedHeight(80)
- statusItem.setFixedWidth(320) # 统一加长状态项宽度(原无固定宽度)
-
- itemLayout = QHBoxLayout(statusItem)
- itemLayout.setContentsMargins(10, 5, 10, 5)
-
- # 状态指示灯
- indicator = QLabel()
- indicator.setFixedSize(20, 20)
- indicator.setStyleSheet("""
- QLabel {
- background-color: #9E9E9E;
- border-radius: 10px;
- border: 2px solid #555555;
- }
- """)
-
- # 状态名称标签
- nameLabel = QLabel(info["name"])
- nameLabel.setFixedWidth(100) # 加宽名称标签(原90)
- nameLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
- nameLabel.setStyleSheet("font-size: 14px; color: #FFFFFF;")
- nameLabel.setFont(QFont("Microsoft YaHei", 12))
-
- # 状态值标签
- valueLabel = QLabel(info["value"])
- valueLabel.setStyleSheet("""
- QLabel {
- font-size: 16px;
- font-weight: bold;
- color: #FFFFFF;
- background-color: #2D2D2D;
- border: none;
- padding: 0px;
- }
- """)
- valueLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
- valueLabel.setMinimumWidth(150) # 加宽值标签(原80)
-
- itemLayout.addWidget(indicator)
- itemLayout.addSpacing(10)
- itemLayout.addWidget(nameLabel)
- itemLayout.addStretch()
- itemLayout.addWidget(valueLabel)
-
- self.statusWidgets.append({
- 'indicator': indicator,
- 'nameLabel': nameLabel,
- 'valueLabel': valueLabel,
- 'status': False,
- 'initial_value': info["value"],
- 'api_field': info["api_field"]
- })
-
- return statusItem
-
- def _init_operation_buttons(self, parent_layout):
- """初始化操作按钮(下料完成/生产异常/生产取消)"""
- buttonContainer = QWidget()
- buttonLayout = QHBoxLayout(buttonContainer)
- buttonLayout.setContentsMargins(0, 20, 0, 0)
- buttonLayout.setSpacing(30)
-
- # 按钮图标(需替换为实际图标路径)
- start_icon_path = "img.png"
- down_icon_path = "img.png"
- error_icon_path = "img.png"
- cancel_icon_path = "img.png"
-
- self.startFeedButton = QPushButton("开始下料")
- self.finishButton = QPushButton("下料完成")
- self.errorButton = QPushButton("生产异常")
- self.cancelButton = QPushButton("生产取消")
-
- # 设置按钮图标
- self.startFeedButton.setIcon(QIcon(start_icon_path))
- self.finishButton.setIcon(QIcon(down_icon_path))
- self.errorButton.setIcon(QIcon(error_icon_path))
- self.cancelButton.setIcon(QIcon(cancel_icon_path))
-
- # 设置图标大小
- self.startFeedButton.setIconSize(QSize(20, 20))
- self.finishButton.setIconSize(QSize(20, 20))
- self.errorButton.setIconSize(QSize(20, 20))
- self.cancelButton.setIconSize(QSize(20, 20))
-
- button_base_style = """
- QPushButton {
- font-size: 16px;
- font-weight: bold;
- padding: 10px 20px;
- border-radius: 15px;
- border: 1px solid;
- min-width: 100px;
- }
- QPushButton:hover {
- opacity: 0.9;
- }
- QPushButton:pressed {
- opacity: 0.8;
- }
- """
-
- self.startFeedButton.setStyleSheet(button_base_style + """
- QPushButton {
- background-color: #2196F3;
- color: white;
- border-color: #1976D2;
- }
- """)
-
- self.finishButton.setStyleSheet(button_base_style + """
- QPushButton {
- background-color: #00796B;
- color: white;
- border-color: #004D40;
- }
- """)
-
- self.errorButton.setStyleSheet(button_base_style + """
- QPushButton {
- background-color: #E65100;
- color: white;
- border-color: #BF360C;
- }
- """)
-
- self.cancelButton.setStyleSheet(button_base_style + """
- QPushButton {
- background-color: #C62828;
- color: white;
- border-color: #8E0000;
- }
- """)
-
- button_font = QFont("Microsoft YaHei", 12, QFont.Bold)
- self.startFeedButton.setFont(button_font)
- self.finishButton.setFont(button_font)
- self.errorButton.setFont(button_font)
- self.cancelButton.setFont(button_font)
-
- self.startFeedButton.clicked.connect(self.on_start_clicked)
- self.finishButton.clicked.connect(self.on_finish_clicked)
- self.errorButton.clicked.connect(self.on_error_clicked)
- self.cancelButton.clicked.connect(self.on_cancel_clicked)
-
- # 初始禁用“停止”和“异常”按钮(未连接时不可用)
- self.startFeedButton.setDisabled(False)
- self.finishButton.setDisabled(True)
- self.errorButton.setDisabled(True)
- self.cancelButton.setDisabled(True)
-
- buttonLayout.addStretch(1)
- buttonLayout.addWidget(self.startFeedButton)
- buttonLayout.addWidget(self.finishButton)
- buttonLayout.addWidget(self.errorButton)
- buttonLayout.addWidget(self.cancelButton)
- buttonLayout.addStretch(1)
-
- parent_layout.addWidget(buttonContainer)
-
- def _init_timers(self):
- """初始化定时器(时间更新+状态模拟)"""
- # 时间更新定时器(每秒更新一次)
- self.time_timer = QTimer()
- self.time_timer.timeout.connect(self.update_time)
- self.time_timer.start(1000)
-
- def get_current_time(self):
- """获取格式化的当前时间"""
- return datetime.now().strftime('%Y-%m-%d %H:%M:%S')
-
- def get_timestamp(self):
- """获取当前时间戳(秒级)"""
- return datetime.now().strftime('%Y%m%d_%H%M%S_%f')[:-3]
-
- def update_time(self):
- """更新时间显示并触发重绘"""
- self.current_datetime = self.get_current_time()
- self.update() # 触发paintEvent重绘
-
- def paintEvent(self, event):
- """重写绘画事件,在右上角绘制日期时间文本"""
- super().paintEvent(event) # 调用父类方法保持原有绘制
-
- # 创建QPainter对象
- painter = QPainter(self)
- painter.setRenderHint(QPainter.RenderHint.TextAntialiasing) # 文本抗锯齿
-
- # 设置字体
- font = QFont("Arial", 12, QFont.Bold)
- painter.setFont(font)
-
- # 设置文本颜色
- painter.setPen(QColor("#00FF9D"))
-
- # 计算文本位置(右上角,留出边距)
- text = f"🕒 {self.current_datetime}"
- text_rect = painter.boundingRect(self.rect(), Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTop, text)
- x = self.width() - text_rect.width() - 15 # 右边距15px
- y = 15 # 上边距15px
-
- # 绘制文本
- painter.drawText(x, y + text_rect.height(), text)
-
- def _save_data_to_file(self, button_name):
- """
- 将服务端数据+按钮操作信息保存到JSON文件
-
- 参数:button_name:点击的按钮名称
- """
- # 1、检查是否有服务端数据
- if not self.latest_server_data:
- print(f"⚠️ 未收到服务端数据,无法保存「{button_name}」操作记录")
- return
-
- # 2、构建完整数据(服务端数据+按钮操作信息+存档时间)
- save_data = {
- "opration_button": button_name,
- "save_time": self.get_current_time(),
- "server_data":self.latest_server_data
- }
-
- # 3、生成唯一文件名(按时间戳命名)
- file_name = f"operation_record_{self.get_timestamp()}.json"
- file_path = os.path.join(SAVE_DIR, file_name)
-
- # 4、写入JSON文件
- try:
- with open(file_path, "w", encoding="utf-8") as f:
- json.dump(save_data, f, ensure_ascii=False, indent=4)
- print(f"💾 保存「{button_name}」操作记录成功:{os.path.abspath(file_path)}")
- except Exception as e:
- print(f"💾 保存「{button_name}」操作记录失败:{str(e)}")
-
- # ------------------
- # TCP客户端核心功能
- # ------------------
- @Slot()
- def _on_tcp_connected(self):
- """TCP连接成功回调"""
- self.is_tcp_connected = True
- self.is_running = True
- print(f"TCP连接成功:{self.tcp_server_host}:{self.tcp_server_port}")
-
- # 连接成功后,向服务器发送“请求初始数据”指令
- self._send_tcp_request("get_initial_data")
-
- # 更新按钮状态:启用“下料完成”“生产异常”“生产取消”
- self.finishButton.setDisabled(False)
- self.errorButton.setDisabled(False)
- self.cancelButton.setDisabled(False)
-
- @Slot()
- def _on_tcp_disconnected(self):
- """TCP连接断开回调"""
- self.is_tcp_connected = False
- self.is_running = False
- print(f"TCP连接断开:{self.tcp_server_host}:{self.tcp_server_port}")
-
- # 启用/禁用按钮
- self.startFeedButton.setDisabled(False)
- self.finishButton.setDisabled(True)
- self.errorButton.setDisabled(True)
- self.cancelButton.setDisabled(True)
-
- # 重置状态指示灯为“未连接”状态
- for widget in self.statusWidgets:
- widget['indicator'].setStyleSheet("""
- QLabel {
- background-color: #9E9E9E;
- border-radius: 10px;
- border: 2px solid #555555;
- }
- """)
-
- @Slot()
- def _on_tcp_data_received(self):
- """TCP数据接收回调(服务器发送数据时触发)"""
- tcp_data = self.tcp_socket.readAll().data().decode("utf-8").strip()
- print(f"TCP数据接收:{tcp_data}")
-
- # 解析数据
- try:
- status_data = json.loads(tcp_data)
- self.latest_server_data = status_data
- self._update_ui_from_data(status_data)
- except json.JSONDecodeError as e:
- print(f"TCP数据解析失败(非JSON格式):{e}, 原始数据:{tcp_data}")
- except Exception as e:
- print(f"TCP数据处理异常:{e}")
-
- @Slot(QAbstractSocket.SocketError)
- def _on_tcp_error(self, error):
- """TCP错误回调"""
- error_str = self.tcp_socket.errorString()
- print(f"TCP错误:{error_str}")
- self.is_tcp_connected = False
- self.is_running = False
-
- # 启用/禁用按钮
- self.startFeedButton.setDisabled(False)
- self.finishButton.setDisabled(True)
- self.errorButton.setDisabled(True)
- self.cancelButton.setDisabled(True)
-
- def _send_tcp_request(self, request_cmd="get_status"):
- """向TCP服务器发送请求指令"""
- if not self.is_tcp_connected:
- print("TCP连接未建立,无法发送请求")
- return
-
- # 构造请求数据
- request_data = json.dumps({
- "cmd": request_cmd,
- "timestamp": self.get_current_time(),
- "client_info": "布料系统客户端"
- }) + "\n" # 增加换行符作为数据结束标识
-
- # 发送请求数据
- self.tcp_socket.write(request_data.encode("utf-8"))
- print(f"TCP请求发送:{request_data.strip()}")
-
- def _update_ui_from_data(self, data):
- """根据TCP获取的数据更新界面状态"""
- for widget in self.statusWidgets:
- api_field = widget['api_field']
- if api_field in data:
- new_value = str(data[api_field])
- widget['valueLabel'].setText(new_value)
- self.set_indicator_status(widget, new_value)
-
- # ------------------
- # 状态指示灯逻辑
- # ------------------
- def set_indicator_status(self, widget, value):
- """根据值设置状态指示灯颜色"""
- if value and value != "未知" and value != "" and value != "None":
- # 有效数据:绿色指示灯
- widget['indicator'].setStyleSheet("""
- QLabel {
- background-color: #00E676;
- border-radius: 10px;
- border: 2px solid #00796B;
- }
- """)
- else:
- # 无效数据:红色指示灯
- widget['indicator'].setStyleSheet("""
- QLabel {
- background-color: #FF5252;
- border-radius: 10px;
- border: 2px solid #C62828;
- }
- """)
-
- # ------------------
- # 按钮点击事件
- # ------------------
- def on_start_clicked(self):
- """点击“开始下料”:向服务端发送开始指令"""
- print("🔘 点击「开始下料」按钮")
- if not self.is_tcp_connected:
- print("TCP连接未建立,尝试重新连接")
- self.tcp_socket.connectToHost(self.tcp_server_host, self.tcp_server_port)
- QTimer.singleShot(1000, lambda: self._send_tcp_request("start_feed")) # 等待连接成功后再发送请求
- else:
- print("TCP连接已建立")
- self._send_tcp_request("start_feed")
-
- def on_finish_clicked(self):
- """点击“下料完成”:向服务端发送完成指令"""
- print("🔘 点击「下料完成」按钮")
- self._send_tcp_request("finish_feed")
- self._save_data_to_file("finish_feed")
-
- def on_error_clicked(self):
- """点击“生产异常”:向服务端发送异常指令"""
- print("🔘 点击「生产异常」按钮")
- self._send_tcp_request("production_error")
- self._save_data_to_file("production_error")
-
- def on_cancel_clicked(self):
- """点击“生产取消”:向服务端发送取消指令"""
- print("🔘 点击「生产取消」按钮")
- self._send_tcp_request("cancel_feed")
- self._save_data_to_file("cancel_feed")
-
-if __name__ == "__main__":
- app = QApplication(sys.argv)
- window = StatusMonitor()
- window.show()
- sys.exit(app.exec())
diff --git a/zjsh_ui_sysytem/main2.py b/zjsh_ui_sysytem/main2.py
deleted file mode 100644
index f6a5916..0000000
--- a/zjsh_ui_sysytem/main2.py
+++ /dev/null
@@ -1,569 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-'''
-# @Time : 2025/10/31 14:39
-# @Author : reenrr
-# @Description : 通过tcp连接获取信息,并显示在界面上(版本2)
-# @File : main2.py
-'''
-import sys
-from PySide6.QtWidgets import (
- QApplication, QWidget, QVBoxLayout, QHBoxLayout,
- QLabel, QFrame, QSizePolicy, QPushButton
-)
-from PySide6.QtCore import Qt, QTimer, QPoint, QSize, Slot
-from PySide6.QtGui import QFont, QPainter, QColor, QPen, QIcon
-from datetime import datetime
-from PySide6.QtNetwork import QTcpSocket, QAbstractSocket
-import json
-import os
-
-
-# -----------
-# 参数配置
-# -----------
-tcp_server_host = "127.0.0.1"
-tcp_server_port = 8888
-
-# 数据保存目录
-SAVE_DIR = "operation_records"
-
-class StatusMonitor(QWidget):
- """
- 中交三航精准布料浇筑要料系统 - 主界面类(深色主题)
- 使用TCP进行数据传输(客户端模型,与TCP服务器通信)
- """
-
- def __init__(self, parent=None):
- """构造函数:初始化主界面的UI布局、控件和定时器"""
- super().__init__(parent=parent)
- self.is_running = False # 系统运行状态标记
- self.current_datetime = self.get_current_time() # 当前日期时间
- # 缓存服务端发送的最新JSON数据(统一变量名,避免保存时出错)
- self.latest_server_data = {}
-
- # ---------------
- # TCP客户端核心配置
- # ---------------
- self.tcp_socket = QTcpSocket(self) # TCP socket实例
- self.tcp_server_host = tcp_server_host
- self.tcp_server_port = tcp_server_port
- self.is_tcp_connected = False # TCP连接状态标记
-
- # 绑定TCP信号与槽(事件驱动)
- self._bind_tcp_signals()
-
- # 窗口基础设置
- self.setWindowTitle("中交三航精准布料浇筑要料系统")
- self.setGeometry(100, 100, 850, 500) # 设置窗口位置和大小
- self.setStyleSheet("background-color: #121212;") # 窗口背景设为深黑色
-
- # 初始化主布局(垂直布局)
- self.mainLayout = QVBoxLayout(self)
- self.mainLayout.setContentsMargins(10, 40, 10, 10) # 上边距留空用于显示日期
- self.mainLayout.setSpacing(10) # 相邻控件的间距
-
- # 初始化界面组件
- self._init_title_label()
- self._init_status_container()
- self._init_timers()
-
- # ----------------
- # 客户端自动连接服务端
- # ----------------
- print(f"客户端启动,自动连接服务端{self.tcp_server_host}:{self.tcp_server_port}...")
- self.tcp_socket.connectToHost(self.tcp_server_host, self.tcp_server_port)
-
- def _bind_tcp_signals(self):
- """绑定TCP socket的核心信号(连接、断开、接收数据、错误)"""
- # 连接成功信号
- self.tcp_socket.connected.connect(self._on_tcp_connected)
- # 断开连接信号
- self.tcp_socket.disconnected.connect(self._on_tcp_disconnected)
- # 接收数据信号(有新数据时触发)
- self.tcp_socket.readyRead.connect(self._on_tcp_data_received)
- # 错误信号(连接/通信出错时触发)
- self.tcp_socket.errorOccurred.connect(self._on_tcp_error)
-
- # ----------------
- # 界面初始化函数
- # ----------------
- def _init_title_label(self):
- """初始化系统标题标签"""
- titleLabel = QLabel("中交三航精准布料浇筑要料系统")
- titleLabel.setStyleSheet("""
- QLabel {
- color: #00FF9D;
- font-size: 20px;
- font-weight: bold;
- }
- """)
- titleLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
- titleLabel.setFont(QFont("Microsoft YaHei", 24, QFont.Bold))
- self.mainLayout.addWidget(titleLabel)
-
- def _init_status_container(self):
- """初始化核心状态监控容器(包含状态组和操作按钮)"""
- self.bigContainer = QFrame()
- self.bigContainer.setStyleSheet("""
- QFrame {
- background-color: #1E1E1E;
- border: 2px solid #333333;
- border-radius: 8px;
- }
- """)
- self.bigContainer.setSizePolicy(
- QSizePolicy.Policy.Expanding,
- QSizePolicy.Policy.Expanding
- )
-
- containerLayout = QVBoxLayout(self.bigContainer)
- containerLayout.setContentsMargins(20, 20, 20, 20)
-
- self._init_status_groups(containerLayout)
- self._init_operation_buttons(containerLayout) # 操作按钮包含新增的3个状态按钮
-
- self.mainLayout.addWidget(self.bigContainer, 1)
-
- def _init_status_groups(self, parent_layout):
- """初始化左右信息(各包含3个状态项)"""
- statusWidget = QWidget()
- statusLayout = QHBoxLayout(statusWidget)
- statusLayout.setContentsMargins(0, 0, 0, 0)
- statusLayout.setSpacing(30) # 减小中间空白间距
-
- leftGroup = QWidget()
- leftLayout = QVBoxLayout(leftGroup)
- leftLayout.setSpacing(15)
- leftLayout.setContentsMargins(30, 0, 0, 0) # 左边组左内边距
-
- rightGroup = QWidget()
- rightLayout = QVBoxLayout(rightGroup)
- rightLayout.setSpacing(15)
- rightLayout.setContentsMargins(0, 0, 30, 0) # 右边组右内边距
-
- # 左边状态项
- leftStatusInfo = [
- {"name": "任务单号", "value": "", "api_field": "task_id"},
- {"name": "工程名称", "value": "", "api_field": "project_name"},
- {"name": "配比号", "value": "", "api_field": "produce_mix_id"}
- ]
- # 右边状态项
- rightStatusInfo = [
- {"name": "要料状态", "value": "", "api_field": "flag"},
- {"name": "砼强度", "value": "", "api_field": "beton_grade"},
- {"name": "要料方量", "value": "", "api_field": "adjusted_volume"},
- ]
- self.statusWidgets = []
-
- # 处理左边状态项
- for info in leftStatusInfo:
- statusItem = self._create_status_item(info)
- leftLayout.addWidget(statusItem)
-
- # 处理右边状态项
- for info in rightStatusInfo:
- statusItem = self._create_status_item(info)
- rightLayout.addWidget(statusItem)
-
- statusLayout.addWidget(leftGroup)
- statusLayout.addStretch(0)
- statusLayout.addWidget(rightGroup)
-
- parent_layout.addWidget(statusWidget)
-
- def _create_status_item(self, info):
- """创建单个状态项"""
- statusItem = QFrame()
- statusItem.setStyleSheet("""
- QFrame {
- background-color: #2D2D2D;
- border: 1px solid #444444;
- border-radius: 6px;
- padding: 10px;
- }
- """)
- statusItem.setFixedHeight(80)
- statusItem.setFixedWidth(320) # 统一状态项宽度
-
- itemLayout = QHBoxLayout(statusItem)
- itemLayout.setContentsMargins(10, 5, 10, 5)
-
- # 状态指示灯
- indicator = QLabel()
- indicator.setFixedSize(20, 20)
- indicator.setStyleSheet("""
- QLabel {
- background-color: #9E9E9E;
- border-radius: 10px;
- border: 2px solid #555555;
- }
- """)
-
- # 状态名称标签
- nameLabel = QLabel(info["name"])
- nameLabel.setFixedWidth(100)
- nameLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
- nameLabel.setStyleSheet("font-size: 14px; color: #FFFFFF;")
- nameLabel.setFont(QFont("Microsoft YaHei", 12))
-
- # 状态值标签
- valueLabel = QLabel(info["value"])
- valueLabel.setStyleSheet("""
- QLabel {
- font-size: 16px;
- font-weight: bold;
- color: #FFFFFF;
- background-color: #2D2D2D;
- border: none;
- padding: 0px;
- }
- """)
- valueLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
- valueLabel.setMinimumWidth(150)
-
- itemLayout.addWidget(indicator)
- itemLayout.addSpacing(10)
- itemLayout.addWidget(nameLabel)
- itemLayout.addStretch()
- itemLayout.addWidget(valueLabel)
-
- self.statusWidgets.append({
- 'indicator': indicator,
- 'nameLabel': nameLabel,
- 'valueLabel': valueLabel,
- 'status': False,
- 'initial_value': info["value"],
- 'api_field': info["api_field"]
- })
-
- return statusItem
-
- def _init_operation_buttons(self, parent_layout):
- """初始化操作按钮(新增未下料/下料中/下料完成 + 原有生产异常/生产取消)"""
- buttonContainer = QWidget()
- buttonLayout = QHBoxLayout(buttonContainer)
- buttonLayout.setContentsMargins(0, 20, 0, 0)
- buttonLayout.setSpacing(20) # 按钮间距(适配5个按钮,避免拥挤)
-
- # 按钮图标(复用现有图标路径,可根据需求替换)
- status_icon_path = "img.png" # 状态类按钮(未下料/下料中/下料完成)共用图标
- error_icon_path = "img.png"
- cancel_icon_path = "img.png"
-
- self.notFeedingBtn = QPushButton("未下料") # 未下料按钮
- self.feedingBtn = QPushButton("下料中") # 下料中按钮
- self.feedFinishBtn = QPushButton("下料完成")# 下料完成按钮
- self.errorButton = QPushButton("生产异常")
- self.cancelButton = QPushButton("生产取消")
-
- # 设置按钮设置(图标、大小、样式)
- status_buttons = [self.notFeedingBtn, self.feedingBtn, self.feedFinishBtn]
- for btn in status_buttons:
- btn.setIcon(QIcon(status_icon_path))
- btn.setIconSize(QSize(20, 20))
- btn.setFont(QFont("Microsoft YaHei", 12, QFont.Bold))
- self.errorButton.setIcon(QIcon(error_icon_path))
- self.cancelButton.setIcon(QIcon(cancel_icon_path))
- self.errorButton.setIconSize(QSize(20, 20))
- self.cancelButton.setIconSize(QSize(20, 20))
- self.errorButton.setFont(QFont("Microsoft YaHei", 12, QFont.Bold))
- self.cancelButton.setFont(QFont("Microsoft YaHei", 12, QFont.Bold))
-
- # 按钮基础样式(统一风格)
- button_base_style = """
- QPushButton {
- font-size: 16px;
- font-weight: bold;
- padding: 10px 15px; /* 缩小内边距,适配5个按钮布局 */
- border-radius: 15px;
- border: 1px solid;
- min-width: 90px; /* 缩小最小宽度 */
- }
- QPushButton:hover {
- opacity: 0.9;
- }
- QPushButton:pressed {
- opacity: 0.8;
- }
- """
-
- # 单个按钮样式(不同颜色区分状态)
- self.notFeedingBtn.setStyleSheet(button_base_style + """
- QPushButton {
- background-color: #616161; /* 灰色:未开始状态 */
- color: white;
- border-color: #424242;
- }
- """)
- self.feedingBtn.setStyleSheet(button_base_style + """
- QPushButton {
- background-color: #2196F3; /* 蓝色:进行中状态 */
- color: white;
- border-color: #1976D2;
- }
- """)
- self.feedFinishBtn.setStyleSheet(button_base_style + """
- QPushButton {
- background-color: #4CAF50; /* 绿色:完成状态 */
- color: white;
- border-color: #388E3C;
- }
- """)
-
- self.errorButton.setStyleSheet(button_base_style + """
- QPushButton {
- background-color: #E65100;
- color: white;
- border-color: #BF360C;
- }
- """)
- self.cancelButton.setStyleSheet(button_base_style + """
- QPushButton {
- background-color: #C62828;
- color: white;
- border-color: #8E0000;
- }
- """)
-
- # ---------------- 绑定按钮点击事件 ----------------
- self.notFeedingBtn.clicked.connect(self.on_not_feeding_clicked)
- self.feedingBtn.clicked.connect(self.on_feeding_clicked)
- self.feedFinishBtn.clicked.connect(self.on_feed_finish_clicked)
- self.errorButton.clicked.connect(self.on_error_clicked)
- self.cancelButton.clicked.connect(self.on_cancel_clicked)
-
- # ---------------- 初始禁用所有按钮(TCP连接后启用) ----------------
- all_buttons = status_buttons + [self.errorButton, self.cancelButton]
- for btn in all_buttons:
- btn.setDisabled(True)
-
- # ---------------- 按钮布局(5个按钮横向排列) ----------------
- buttonLayout.addStretch(1)
- buttonLayout.addWidget(self.notFeedingBtn)
- buttonLayout.addWidget(self.feedingBtn)
- buttonLayout.addWidget(self.feedFinishBtn)
- buttonLayout.addWidget(self.errorButton)
- buttonLayout.addWidget(self.cancelButton)
- buttonLayout.addStretch(1)
-
- parent_layout.addWidget(buttonContainer)
-
- def _init_timers(self):
- """初始化定时器(时间更新+状态模拟)"""
- # 时间更新定时器(每秒更新一次)
- self.time_timer = QTimer()
- self.time_timer.timeout.connect(self.update_time)
- self.time_timer.start(1000)
-
- def get_current_time(self):
- """获取格式化的当前时间"""
- return datetime.now().strftime('%Y-%m-%d %H:%M:%S')
-
- def get_timestamp(self):
- """获取当前时间戳(秒级)"""
- return datetime.now().strftime('%Y%m%d_%H%M%S_%f')[:-3]
-
- def update_time(self):
- """更新时间显示并触发重绘"""
- self.current_datetime = self.get_current_time()
- self.update() # 触发paintEvent重绘
-
- def paintEvent(self, event):
- """重写绘画事件,在右上角绘制日期时间文本"""
- super().paintEvent(event) # 调用父类方法保持原有绘制
-
- # 创建QPainter对象
- painter = QPainter(self)
- painter.setRenderHint(QPainter.RenderHint.TextAntialiasing) # 文本抗锯齿
-
- # 设置字体
- font = QFont("Arial", 12, QFont.Bold)
- painter.setFont(font)
-
- # 设置文本颜色
- painter.setPen(QColor("#00FF9D"))
-
- # 计算文本位置(右上角,留出边距)
- text = f"🕒 {self.current_datetime}"
- text_rect = painter.boundingRect(self.rect(), Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTop, text)
- x = self.width() - text_rect.width() - 15 # 右边距15px
- y = 15 # 上边距15px
-
- # 绘制文本
- painter.drawText(x, y + text_rect.height(), text)
-
- # --------------------
- # 清空界面信息的通用方法
- # --------------------
- def _clear_ui_info(self):
- """清空所有状态项的显示内容,并并设置指示灯颜色"""
- for widget in self.statusWidgets:
- widget['valueLabel'].setText("")
- # 指示灯设为初始灰色(与_create_status_item中初始样式一致)
- widget['indicator'].setStyleSheet("""
- QLabel {
- background-color: #9E9E9E;
- border-radius: 10px;
- border: 2px solid #555555;
- }
- """)
- print("ℹ️ 界面信息已清空")
-
- # ------------------
- # TCP客户端核心功能
- # ------------------
- @Slot()
- def _on_tcp_connected(self):
- """TCP连接成功回调:启用所有操作按钮"""
- self.is_tcp_connected = True
- self.is_running = True
- print(f"TCP连接成功:{self.tcp_server_host}:{self.tcp_server_port}")
-
- # 连接成功后,向服务器发送“请求初始数据”指令
- self._send_tcp_request("get_initial_data")
-
- # 启用所有操作按钮(新增的3个状态按钮+原有2个功能按钮)
- all_buttons = [self.notFeedingBtn, self.feedingBtn, self.feedFinishBtn, self.errorButton, self.cancelButton]
- for btn in all_buttons:
- btn.setDisabled(False)
-
- @Slot()
- def _on_tcp_disconnected(self):
- """TCP连接断开回调:禁用所有操作按钮"""
- self.is_tcp_connected = False
- self.is_running = False
- print(f"TCP连接断开:{self.tcp_server_host}:{self.tcp_server_port}")
-
- # 禁用所有操作按钮
- all_buttons = [self.notFeedingBtn, self.feedingBtn, self.feedFinishBtn, self.errorButton, self.cancelButton]
- for btn in all_buttons:
- btn.setDisabled(True)
-
- # 重置状态指示灯为“未连接”状态
- for widget in self.statusWidgets:
- widget['indicator'].setStyleSheet("""
- QLabel {
- background-color: #9E9E9E;
- border-radius: 10px;
- border: 2px solid #555555;
- }
- """)
-
- @Slot()
- def _on_tcp_data_received(self):
- """TCP数据接收回调(服务器发送数据时触发)"""
- tcp_data = self.tcp_socket.readAll().data().decode("utf-8").strip()
- print(f"TCP数据接收:{tcp_data}")
-
- # 解析数据
- try:
- status_data = json.loads(tcp_data)
- self.latest_server_data = status_data
- self._update_ui_from_data(status_data)
- except json.JSONDecodeError as e:
- print(f"TCP数据解析失败(非JSON格式):{e}, 原始数据:{tcp_data}")
- except Exception as e:
- print(f"TCP数据处理异常:{e}")
-
- @Slot(QAbstractSocket.SocketError)
- def _on_tcp_error(self, error):
- """TCP错误回调:禁用所有操作按钮"""
- error_str = self.tcp_socket.errorString()
- print(f"TCP错误:{error_str}")
- self.is_tcp_connected = False
- self.is_running = False
-
- # 禁用所有操作按钮
- all_buttons = [self.notFeedingBtn, self.feedingBtn, self.feedFinishBtn, self.errorButton, self.cancelButton]
- for btn in all_buttons:
- btn.setDisabled(True)
-
- def _send_tcp_request(self, request_cmd="get_status"):
- """向TCP服务器发送请求指令"""
- if not self.is_tcp_connected:
- print("TCP连接未建立,无法发送请求")
- return
-
- # 构造请求数据
- request_data = json.dumps({
- "cmd": request_cmd,
- "timestamp": self.get_current_time(),
- "client_info": "布料系统客户端"
- }) + "\n" # 增加换行符作为数据结束标识
-
- # 发送请求数据
- self.tcp_socket.write(request_data.encode("utf-8"))
- print(f"TCP请求发送:{request_data.strip()}")
-
- def _update_ui_from_data(self, data):
- """根据TCP获取的数据更新界面状态"""
- for widget in self.statusWidgets:
- api_field = widget['api_field']
- if api_field in data:
- new_value = str(data[api_field])
- widget['valueLabel'].setText(new_value)
- self.set_indicator_status(widget, new_value)
-
- # ------------------
- # 状态指示灯逻辑
- # ------------------
- def set_indicator_status(self, widget, value):
- """根据值设置状态指示灯颜色"""
- if value and value != "未知" and value != "" and value != "None":
- # 有效数据:绿色指示灯
- widget['indicator'].setStyleSheet("""
- QLabel {
- background-color: #00E676;
- border-radius: 10px;
- border: 2px solid #00796B;
- }
- """)
- else:
- # 无效数据:红色指示灯
- widget['indicator'].setStyleSheet("""
- QLabel {
- background-color: #FF5252;
- border-radius: 10px;
- border: 2px solid #C62828;
- }
- """)
-
- # ------------------
- # 按钮点击事件
- # ------------------
- def on_not_feeding_clicked(self):
- """点击“未下料”:向服务端发送“未下料”状态指令"""
- print("🔘 点击「未下料」按钮")
- self._clear_ui_info()
- self._send_tcp_request("not_feeding") # 指令名可根据服务端需求修改
-
- def on_feeding_clicked(self):
- """点击“下料中”:向服务端发送“下料中”状态指令"""
- print("🔘 点击「下料中」按钮")
- self._clear_ui_info()
- self._send_tcp_request("feeding") # 指令名可根据服务端需求修改
-
- def on_feed_finish_clicked(self):
- """点击“下料完成”:向服务端发送“下料完成”状态指令"""
- print("🔘 点击「下料完成」按钮")
- self._clear_ui_info()
- self._send_tcp_request("feed_finish") # 指令名可根据服务端需求修改
-
- def on_error_clicked(self):
- """点击“生产异常”:向服务端发送异常指令"""
- print("🔘 点击「生产异常」按钮")
- self._clear_ui_info()
- self._send_tcp_request("production_error")
-
- def on_cancel_clicked(self):
- """点击“生产取消”:向服务端发送取消指令"""
- print("🔘 点击「生产取消」按钮")
- self._clear_ui_info()
- self._send_tcp_request("cancel_feed")
-
-if __name__ == "__main__":
- app = QApplication(sys.argv)
- window = StatusMonitor()
- window.show()
- sys.exit(app.exec())
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/operation_records/operation_record_20250919_205501_791.json b/zjsh_ui_sysytem/operation_records/operation_record_20250919_205501_791.json
deleted file mode 100644
index 6c2182f..0000000
--- a/zjsh_ui_sysytem/operation_records/operation_record_20250919_205501_791.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "opration_button": "finish_feed",
- "save_time": "2025-09-19 20:55:01",
- "server_data": {
- "task_id": "20250706-01",
- "project_name": "18号线二期工程",
- "section": "停车场工作井上行",
- "slump": "50~70 mm",
- "mix_ratio_id": "P2022=001",
- "request_status": "请求中",
- "material_grade": "C50P12",
- "volume": "2m³",
- "request_time": "10分钟后",
- "car_status": "移动后",
- "timestamp": "2025-09-19 20:54:55"
- }
-}
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/operation_records/operation_record_20250930_095113_723.json b/zjsh_ui_sysytem/operation_records/operation_record_20250930_095113_723.json
deleted file mode 100644
index af1c026..0000000
--- a/zjsh_ui_sysytem/operation_records/operation_record_20250930_095113_723.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "opration_button": "finish_feed",
- "save_time": "2025-09-30 09:51:13",
- "server_data": {
- "task_id": "20250706-01",
- "project_name": "18号线二期工程",
- "section": "停车场工作井上行",
- "slump": "50~70 mm",
- "mix_ratio_id": "P2022=001",
- "request_status": "请求中",
- "material_grade": "C50P12",
- "volume": "2m³",
- "request_time": "10分钟后",
- "car_status": "移动后",
- "timestamp": "2025-09-30 09:50:58"
- }
-}
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/operation_records/operation_record_20251029_110426_514.json b/zjsh_ui_sysytem/operation_records/operation_record_20251029_110426_514.json
deleted file mode 100644
index d7da5cb..0000000
--- a/zjsh_ui_sysytem/operation_records/operation_record_20251029_110426_514.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "opration_button": "production_error",
- "save_time": "2025-10-29 11:04:26",
- "server_data": {
- "task_id": "20250706-01",
- "project_name": "18号线二期工程",
- "section": "停车场工作井上行",
- "slump": "50~70 mm",
- "mix_ratio_id": "P2022=001",
- "request_status": "请求中",
- "material_grade": "C50P12",
- "volume": "2m³",
- "request_time": "10分钟后",
- "car_status": "移动后",
- "timestamp": "2025-10-29 11:02:19"
- }
-}
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/operation_records/operation_record_20251029_202725_958.json b/zjsh_ui_sysytem/operation_records/operation_record_20251029_202725_958.json
deleted file mode 100644
index 650d487..0000000
--- a/zjsh_ui_sysytem/operation_records/operation_record_20251029_202725_958.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "opration_button": "production_error",
- "save_time": "2025-10-29 20:27:25",
- "server_data": {
- "task_id": "20250706-01",
- "project_name": "18号线二期工程",
- "section": "停车场工作井上行",
- "slump": "50~70 mm",
- "mix_ratio_id": "P2022=001",
- "request_status": "请求中",
- "material_grade": "C50P12",
- "volume": "2m³",
- "request_time": "10分钟后",
- "car_status": "移动后",
- "timestamp": "2025-10-29 20:27:12"
- }
-}
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/operation_records/operation_record_20251030_105441_898.json b/zjsh_ui_sysytem/operation_records/operation_record_20251030_105441_898.json
deleted file mode 100644
index 9723132..0000000
--- a/zjsh_ui_sysytem/operation_records/operation_record_20251030_105441_898.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "opration_button": "production_error",
- "save_time": "2025-10-30 10:54:41",
- "server_data": {
- "task_id": "20250706-01",
- "project_name": "18号线二期工程",
- "section": "停车场工作井上行",
- "slump": "50~70 mm",
- "mix_ratio_id": "P2022=001",
- "request_status": "请求中",
- "material_grade": "C50P12",
- "volume": "2m³",
- "request_time": "10分钟后",
- "car_status": "移动后",
- "timestamp": "2025-10-30 10:54:40"
- }
-}
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/operation_records/operation_record_20251030_105520_002.json b/zjsh_ui_sysytem/operation_records/operation_record_20251030_105520_002.json
deleted file mode 100644
index b411941..0000000
--- a/zjsh_ui_sysytem/operation_records/operation_record_20251030_105520_002.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "opration_button": "production_error",
- "save_time": "2025-10-30 10:55:20",
- "server_data": {
- "task_id": "20250706-01",
- "project_name": "18号线二期工程",
- "section": "停车场工作井上行",
- "slump": "50~70 mm",
- "mix_ratio_id": "P2022=001",
- "request_status": "请求中",
- "material_grade": "C50P12",
- "volume": "2m³",
- "request_time": "10分钟后",
- "car_status": "移动后",
- "timestamp": "2025-10-30 10:55:18"
- }
-}
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/operation_records/operation_record_20251030_105523_098.json b/zjsh_ui_sysytem/operation_records/operation_record_20251030_105523_098.json
deleted file mode 100644
index 6bb41c3..0000000
--- a/zjsh_ui_sysytem/operation_records/operation_record_20251030_105523_098.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "opration_button": "cancel_feed",
- "save_time": "2025-10-30 10:55:23",
- "server_data": {
- "task_id": "20250706-01",
- "project_name": "18号线二期工程",
- "section": "停车场工作井上行",
- "slump": "50~70 mm",
- "mix_ratio_id": "P2022=001",
- "request_status": "请求中",
- "material_grade": "C50P12",
- "volume": "2m³",
- "request_time": "10分钟后",
- "car_status": "移动后",
- "timestamp": "2025-10-30 10:55:18"
- }
-}
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/operation_records/operation_record_20251030_170942_670.json b/zjsh_ui_sysytem/operation_records/operation_record_20251030_170942_670.json
deleted file mode 100644
index 1cf9e4e..0000000
--- a/zjsh_ui_sysytem/operation_records/operation_record_20251030_170942_670.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "opration_button": "production_error",
- "save_time": "2025-10-30 17:09:42",
- "server_data": {
- "erp_id": 82728,
- "status": "数据已接收"
- }
-}
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/operation_records/operation_record_20251030_171000_812.json b/zjsh_ui_sysytem/operation_records/operation_record_20251030_171000_812.json
deleted file mode 100644
index 473e13e..0000000
--- a/zjsh_ui_sysytem/operation_records/operation_record_20251030_171000_812.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "opration_button": "production_error",
- "save_time": "2025-10-30 17:10:00",
- "server_data": {
- "erp_id": 82728,
- "status": "数据已接收"
- }
-}
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/operation_records/operation_record_20251030_171004_403.json b/zjsh_ui_sysytem/operation_records/operation_record_20251030_171004_403.json
deleted file mode 100644
index a1c9c40..0000000
--- a/zjsh_ui_sysytem/operation_records/operation_record_20251030_171004_403.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "opration_button": "production_error",
- "save_time": "2025-10-30 17:10:04",
- "server_data": {
- "erp_id": 82728,
- "status": "数据已接收"
- }
-}
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/operation_records/operation_record_20251030_171008_419.json b/zjsh_ui_sysytem/operation_records/operation_record_20251030_171008_419.json
deleted file mode 100644
index 98730f1..0000000
--- a/zjsh_ui_sysytem/operation_records/operation_record_20251030_171008_419.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "opration_button": "production_error",
- "save_time": "2025-10-30 17:10:08",
- "server_data": {
- "erp_id": 82728,
- "status": "数据已接收"
- }
-}
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/operation_records/operation_record_20251030_171022_493.json b/zjsh_ui_sysytem/operation_records/operation_record_20251030_171022_493.json
deleted file mode 100644
index 57cb891..0000000
--- a/zjsh_ui_sysytem/operation_records/operation_record_20251030_171022_493.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "opration_button": "production_error",
- "save_time": "2025-10-30 17:10:22",
- "server_data": {
- "erp_id": 82728,
- "status": "数据已接收"
- }
-}
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/operation_records/operation_record_20251030_171024_108.json b/zjsh_ui_sysytem/operation_records/operation_record_20251030_171024_108.json
deleted file mode 100644
index edc6cec..0000000
--- a/zjsh_ui_sysytem/operation_records/operation_record_20251030_171024_108.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "opration_button": "production_error",
- "save_time": "2025-10-30 17:10:24",
- "server_data": {
- "erp_id": 82728,
- "status": "数据已接收"
- }
-}
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/operation_records/operation_record_20251030_182057_822.json b/zjsh_ui_sysytem/operation_records/operation_record_20251030_182057_822.json
deleted file mode 100644
index ac4a7d1..0000000
--- a/zjsh_ui_sysytem/operation_records/operation_record_20251030_182057_822.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "opration_button": "production_error",
- "save_time": "2025-10-30 18:20:57",
- "server_data": {
- "erp_id": 82729,
- "status": "数据已接收"
- }
-}
\ No newline at end of file
diff --git a/zjsh_ui_sysytem/test.py b/zjsh_ui_sysytem/test.py
deleted file mode 100644
index aa87988..0000000
--- a/zjsh_ui_sysytem/test.py
+++ /dev/null
@@ -1,586 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-'''
-# @Time : 2025/9/10 11:29
-# @Author : reenrr
-# @Description : 在main函数的基础上添加了重连机制(为连接成功)
-# @File : test.py
-'''
-import sys
-from PySide6.QtWidgets import (
- QApplication, QWidget, QVBoxLayout, QHBoxLayout,
- QLabel, QFrame, QSizePolicy, QPushButton
-)
-from PySide6.QtCore import Qt, QTimer, QPoint, QSize, Slot
-from PySide6.QtGui import QFont, QPainter, QColor, QPen, QIcon
-from datetime import datetime
-from PySide6.QtNetwork import QTcpSocket, QAbstractSocket
-import json
-import os
-
-
-# -----------
-# 参数配置
-# -----------
-tcp_server_host = "127.0.0.1"
-tcp_server_port = 8888
-
-# 数据保存目录
-SAVE_DIR = "operation_records"
-MAX_RECONNECT = 3 # 最大重连次数
-RECONNECT_INTERVAL = 2000 # 重连间隔(毫秒)
-
-class StatusMonitor(QWidget):
- """
- 中交三航精准布料浇筑要料系统 - 主界面类(深色主题)
- 使用TCP进行数据传输(客户端模型,与TCP服务器通信)
- """
- def __init__(self, parent=None):
- """构造函数:初始化主界面的UI布局、控件和定时器"""
- super().__init__(parent=parent)
- self.is_running = False # 系统运行状态标记
- self.current_datetime = self.get_current_time() # 当前日期时间
- # 缓存服务端发送的最新JSON数据
- self.latest_json_data = {}
-
- # ---------------
- # TCP客户端核心配置
- # ---------------
- self.tcp_socket = QTcpSocket(self) # TCP socket实例
- self.tcp_server_host = tcp_server_host
- self.tcp_server_port = tcp_server_port
- self.is_tcp_connected = False # TCP连接状态标记
- self.has_connected_once = False # 连接至服务器至少一次标记(区别首次连接和断开后重连)
- self.reconnect_count = 0 # 重连次数计数器
- # 重连定时器,每隔RECONNECT_INTERVAL毫秒重连一次
- self.reconnect_timer = QTimer(self)
- self.reconnect_timer.setInterval(RECONNECT_INTERVAL)
- self.reconnect_timer.timeout.connect(self._reconnect_to_server) # 绑定重连函数
-
- # 绑定TCP信号与槽(事件驱动)
- self._bind_tcp_signals()
-
- # 窗口基础设置
- self.setWindowTitle("中交三航精准布料浇筑要料系统")
- self.setGeometry(100, 100, 850, 500) # 设置窗口位置和大小
- self.setStyleSheet("background-color: #121212;") # 窗口背景设为深黑色
-
- # 初始化主布局(垂直布局)
- self.mainLayout = QVBoxLayout(self)
- self.mainLayout.setContentsMargins(10, 40, 10, 10) # 上边距留空用于显示日期
- self.mainLayout.setSpacing(10) # 相邻控件的间距
-
- # 初始化界面组件
- self._init_title_label()
- self._init_status_container()
- self._init_timers()
- self._init_save_dir()
-
- # ----------------
- # 客户端自动后自动连接服务端
- # ----------------
- print(f"客户端启动,自动连接服务端{self.tcp_server_host}:{self.tcp_server_port}...")
- self._connect_to_server()
-
- def _connect_to_server(self):
- """主动发起连接(仅在未连接状态下有效"""
- if not self.is_tcp_connected:
- self.tcp_socket.abort() # 终止现有连接
- self.tcp_socket.connectToHost(self.tcp_server_host, self.tcp_server_port)
-
- def _reconnect_to_server(self):
- """重连执行函数:仅在未连接且未达最大次数时触发"""
- if not self.is_tcp_connected and self.reconnect_count < MAX_RECONNECT:
- self.reconnect_count += 1
- print(f"第{self.reconnect_count}次重连(共{MAX_RECONNECT}次尝试)...")
- self._connect_to_server()
- elif self.reconnect_count >= MAX_RECONNECT:
- self.reconnect_timer.stop() # 停止重连定时器
- print(f"已达最大重连次数({MAX_RECONNECT}次),停止重连,请检查服务端状态")
-
- def _init_save_dir(self):
- """初始化数据保存目录"""
- if not os.path.exists(SAVE_DIR):
- os.makedirs(SAVE_DIR)
- print(f"已创建数据保存目录:{os.path.abspath(SAVE_DIR)}")
- else:
- print(f"数据保存目录已存在:{os.path.abspath(SAVE_DIR)}")
-
- def _bind_tcp_signals(self):
- """绑定TCP socket的核心信号(连接、断开、接收数据、错误)"""
- # 连接成功信号
- self.tcp_socket.connected.connect(self._on_tcp_connected)
- # 断开连接信号
- self.tcp_socket.disconnected.connect(self._on_tcp_disconnected)
- # 接收数据信号(有新数据时触发)
- self.tcp_socket.readyRead.connect(self._on_tcp_data_received)
- # 错误信号(连接/通信出错时触发)
- self.tcp_socket.errorOccurred.connect(self._on_tcp_error)
-
- # ------------------
- # 界面初始化函数
- # ------------------
- def _init_title_label(self):
- """初始化系统标题标签"""
- titleLabel = QLabel("中交三航精准布料浇筑要料系统")
- titleLabel.setStyleSheet("""
- QLabel {
- color: #00FF9D;
- font-size: 20px;
- font-weight: bold;
- }
- """)
- titleLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
- titleLabel.setFont(QFont("Microsoft YaHei", 24, QFont.Bold))
- self.mainLayout.addWidget(titleLabel)
-
- def _init_status_container(self):
- """初始化核心状态监控容器(包含状态组和操作按钮)"""
- self.bigContainer = QFrame()
- self.bigContainer.setStyleSheet("""
- QFrame {
- background-color: #1E1E1E;
- border: 2px solid #333333;
- border-radius: 8px;
- }
- """)
- self.bigContainer.setSizePolicy(
- QSizePolicy.Policy.Expanding,
- QSizePolicy.Policy.Expanding
- )
-
- containerLayout = QVBoxLayout(self.bigContainer)
- containerLayout.setContentsMargins(20, 20, 20, 20)
-
- self._init_status_groups(containerLayout)
- self._init_operation_buttons(containerLayout)
-
- self.mainLayout.addWidget(self.bigContainer, 1)
-
- def _init_status_groups(self, parent_layout):
- """初始化左右信息(各包含3个状态项)"""
- statusWidget = QWidget()
- statusLayout = QHBoxLayout(statusWidget)
- statusLayout.setContentsMargins(0, 0, 0, 0)
- statusLayout.setSpacing(30) # 减小中间空白间距(原30)
-
- leftGroup = QWidget()
- leftLayout = QVBoxLayout(leftGroup)
- leftLayout.setSpacing(15)
- leftLayout.setContentsMargins(30, 0, 0, 0) # 左边组左内边距设为20,增加左边留白
-
- rightGroup = QWidget()
- rightLayout = QVBoxLayout(rightGroup)
- rightLayout.setSpacing(15)
- rightLayout.setContentsMargins(0, 0, 30, 0) # 右边组右内边距设为20,增加右边留白(若需左边也留白,可设左内边距)
-
- # 左边5个状态项及对应初始值
- leftStatusInfo = [
- {"name": "任务单号", "value": "", "api_field": "task_id"},
- {"name": "工程名称", "value": "", "api_field": "project_name"},
- {"name": "配比号", "value": "", "api_field": "produce_mix_id"}
- ]
- # 右边5个状态项及对应初始值
- rightStatusInfo = [
- {"name": "要料状态", "value": "", "api_field": "flag"},
- {"name": "砼强度", "value": "", "api_field": "beton_grade"},
- {"name": "要料方量", "value": "", "api_field": "adjusted_volume"},
- ]
- self.statusWidgets = []
-
- # 处理左边状态项
- for info in leftStatusInfo:
- statusItem = self._create_status_item(info)
- leftLayout.addWidget(statusItem)
-
- # 处理右边状态项
- for info in rightStatusInfo:
- statusItem = self._create_status_item(info)
- rightLayout.addWidget(statusItem)
-
- statusLayout.addWidget(leftGroup)
- statusLayout.addStretch(0) # 减小中间空白比例(原1)
- statusLayout.addWidget(rightGroup)
-
- parent_layout.addWidget(statusWidget)
-
- def _create_status_item(self, info):
- """创建单个状态项"""
- statusItem = QFrame()
- statusItem.setStyleSheet("""
- QFrame {
- background-color: #2D2D2D;
- border: 1px solid #444444;
- border-radius: 6px;
- padding: 10px;
- }
- """)
- statusItem.setFixedHeight(80)
- statusItem.setFixedWidth(320) # 统一加长状态项宽度(原无固定宽度)
-
- itemLayout = QHBoxLayout(statusItem)
- itemLayout.setContentsMargins(10, 5, 10, 5)
-
- # 状态指示灯
- indicator = QLabel()
- indicator.setFixedSize(20, 20)
- indicator.setStyleSheet("""
- QLabel {
- background-color: #9E9E9E;
- border-radius: 10px;
- border: 2px solid #555555;
- }
- """)
-
- # 状态名称标签
- nameLabel = QLabel(info["name"])
- nameLabel.setFixedWidth(100) # 加宽名称标签(原90)
- nameLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
- nameLabel.setStyleSheet("font-size: 14px; color: #FFFFFF;")
- nameLabel.setFont(QFont("Microsoft YaHei", 12))
-
- # 状态值标签
- valueLabel = QLabel(info["value"])
- valueLabel.setStyleSheet("""
- QLabel {
- font-size: 16px;
- font-weight: bold;
- color: #FFFFFF;
- background-color: #2D2D2D;
- border: none;
- padding: 0px;
- }
- """)
- valueLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
- valueLabel.setMinimumWidth(150) # 加宽值标签(原80)
-
- itemLayout.addWidget(indicator)
- itemLayout.addSpacing(10)
- itemLayout.addWidget(nameLabel)
- itemLayout.addStretch()
- itemLayout.addWidget(valueLabel)
-
- self.statusWidgets.append({
- 'indicator': indicator,
- 'nameLabel': nameLabel,
- 'valueLabel': valueLabel,
- 'status': False,
- 'initial_value': info["value"],
- 'api_field': info["api_field"]
- })
-
- return statusItem
-
- def _init_operation_buttons(self, parent_layout):
- """初始化操作按钮(下料完成/生产异常/生产取消)"""
- buttonContainer = QWidget()
- buttonLayout = QHBoxLayout(buttonContainer)
- buttonLayout.setContentsMargins(0, 20, 0, 0)
- buttonLayout.setSpacing(30)
-
- # 按钮图标(需替换为实际图标路径)
- error_icon_path = "img.png"
- cancel_icon_path = "img.png"
-
- self.errorButton = QPushButton("生产异常")
- self.cancelButton = QPushButton("生产取消")
-
- # 设置按钮图标
- self.errorButton.setIcon(QIcon(error_icon_path))
- self.cancelButton.setIcon(QIcon(cancel_icon_path))
-
- # 设置图标大小
- self.errorButton.setIconSize(QSize(20, 20))
- self.cancelButton.setIconSize(QSize(20, 20))
-
- button_base_style = """
- QPushButton {
- font-size: 16px;
- font-weight: bold;
- padding: 10px 20px;
- border-radius: 15px;
- border: 1px solid;
- min-width: 100px;
- }
- QPushButton:hover {
- opacity: 0.9;
- }
- QPushButton:pressed {
- opacity: 0.8;
- }
- """
- self.errorButton.setStyleSheet(button_base_style + """
- QPushButton {
- background-color: #E65100;
- color: white;
- border-color: #BF360C;
- }
- """)
-
- self.cancelButton.setStyleSheet(button_base_style + """
- QPushButton {
- background-color: #C62828;
- color: white;
- border-color: #8E0000;
- }
- """)
-
- button_font = QFont("Microsoft YaHei", 12, QFont.Bold)
- self.errorButton.setFont(button_font)
- self.cancelButton.setFont(button_font)
-
- self.errorButton.clicked.connect(self.on_error_clicked)
- self.cancelButton.clicked.connect(self.on_cancel_clicked)
-
- # 初始禁用“停止”和“异常”按钮(未连接时不可用)
- self.errorButton.setDisabled(True)
- self.cancelButton.setDisabled(True)
-
- buttonLayout.addStretch(1)
- buttonLayout.addWidget(self.errorButton)
- buttonLayout.addWidget(self.cancelButton)
- buttonLayout.addStretch(1)
-
- parent_layout.addWidget(buttonContainer)
-
- def _init_timers(self):
- """初始化定时器(时间更新+状态模拟)"""
- # 时间更新定时器(每秒更新一次)
- self.time_timer = QTimer()
- self.time_timer.timeout.connect(self.update_time)
- self.time_timer.start(1000)
-
- def get_current_time(self):
- """获取格式化的当前时间"""
- return datetime.now().strftime('%Y-%m-%d %H:%M:%S')
-
- def get_timestamp(self):
- """获取当前时间戳(秒级)"""
- return datetime.now().strftime('%Y%m%d_%H%M%S_%f')[:-3]
-
- def update_time(self):
- """更新时间显示并触发重绘"""
- self.current_datetime = self.get_current_time()
- self.update() # 触发paintEvent重绘
-
- def paintEvent(self, event):
- """重写绘画事件,在右上角绘制日期时间文本"""
- super().paintEvent(event) # 调用父类方法保持原有绘制
-
- # 创建QPainter对象
- painter = QPainter(self)
- painter.setRenderHint(QPainter.RenderHint.TextAntialiasing) # 文本抗锯齿
-
- # 设置字体
- font = QFont("Arial", 12, QFont.Bold)
- painter.setFont(font)
-
- # 设置文本颜色
- painter.setPen(QColor("#00FF9D"))
-
- # 计算文本位置(右上角,留出边距)
- text = f"🕒 {self.current_datetime}"
- text_rect = painter.boundingRect(self.rect(), Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTop, text)
- x = self.width() - text_rect.width() - 15 # 右边距15px
- y = 15 # 上边距15px
-
- # 绘制文本
- painter.drawText(x, y + text_rect.height(), text)
-
- # ------------------
- # 数据保存
- # ------------------
- def _save_data_to_file(self, button_name):
- """
- 将服务端数据+按钮操作信息保存到JSON文件
-
- 参数:button_name:点击的按钮名称
- """
- # 1、检查是否有服务端数据
- if not self.latest_server_data:
- print(f"⚠️ 未收到服务端数据,无法保存「{button_name}」操作记录")
- return
-
- # 2、构建完整数据(服务端数据+按钮操作信息+存档时间)
- save_data = {
- "opration_button": button_name,
- "save_time": self.get_current_time(),
- "server_data":self.latest_server_data
- }
-
- # 3、生成唯一文件名(按时间戳命名)
- file_name = f"operation_record_{self.get_timestamp()}.json"
- file_path = os.path.join(SAVE_DIR, file_name)
-
- # 4、写入JSON文件
- try:
- with open(file_path, "w", encoding="utf-8") as f:
- json.dump(save_data, f, ensure_ascii=False, indent=4)
- print(f"💾 保存「{button_name}」操作记录成功:{os.path.abspath(file_path)}")
- except Exception as e:
- print(f"💾 保存「{button_name}」操作记录失败:{str(e)}")
-
- # --------------------
- # 清空界面信息的通用方法
- # --------------------
- def _clear_ui_info(self):
- """清空所有状态项的显示内容,并并设置指示灯颜色"""
- for widget in self.statusWidgets:
- widget['valueLabel'].setText("")
- # 指示灯设为初始灰色(与_create_status_item中初始样式一致)
- widget['indicator'].setStyleSheet("""
- QLabel {
- background-color: #9E9E9E;
- border-radius: 10px;
- border: 2px solid #555555;
- }
- """)
- print("ℹ️ 界面信息已清空")
-
- # ------------------
- # TCP客户端核心功能
- # ------------------
- @Slot()
- def _on_tcp_connected(self):
- """TCP连接成功回调"""
- self.is_tcp_connected = True
- self.has_connected_once = True
- self.reconnect_timer.stop() # 停止重连定时器
- self.reconnect_count = 0 # 重连计数器清零
- self.is_running = True
- print(f"TCP连接成功:{self.tcp_server_host}:{self.tcp_server_port}")
-
- # 连接成功后,向服务器发送“请求初始数据”指令
- self._send_tcp_request("get_initial_data")
-
- # 更新按钮状态:启用“生产异常”“生产取消”
- self.errorButton.setDisabled(False)
- self.cancelButton.setDisabled(False)
-
- @Slot()
- def _on_tcp_disconnected(self):
- """TCP连接断开回调"""
- self.is_tcp_connected = False
- self.is_running = False
- print(f"TCP连接断开:{self.tcp_server_host}:{self.tcp_server_port}")
-
- # 启用/禁用按钮
- self.errorButton.setDisabled(True)
- self.cancelButton.setDisabled(True)
-
- # 重置状态指示灯为“未连接”状态
- for widget in self.statusWidgets:
- widget['indicator'].setStyleSheet("""
- QLabel {
- background-color: #9E9E9E;
- border-radius: 10px;
- border: 2px solid #555555;
- }
- """)
-
- @Slot()
- def _on_tcp_data_received(self):
- """TCP数据接收回调(服务器发送数据时触发)"""
- tcp_data = self.tcp_socket.readAll().data().decode("utf-8").strip()
- print(f"TCP数据接收:{tcp_data}")
-
- # 解析数据
- try:
- status_data = json.loads(tcp_data)
- print(status_data)
- self.latest_server_data = status_data
- self._update_ui_from_data(status_data)
- except json.JSONDecodeError as e:
- print(f"TCP数据解析失败(非JSON格式):{e}, 原始数据:{tcp_data}")
- except Exception as e:
- print(f"TCP数据处理异常:{e}")
-
- @Slot(QAbstractSocket.SocketError)
- def _on_tcp_error(self, error):
- """TCP错误回调"""
- if not self.is_tcp_connected:
- error_str = self.tcp_socket.errorString()
- print(f"TCP错误:{error_str}")
- self.is_tcp_connected = False
- self.is_running = False
-
- # 启用/禁用按钮
- self.errorButton.setDisabled(True)
- self.cancelButton.setDisabled(True)
-
- # 首次连接失败时,启动重连定时器
- if not self.has_connected_once and self.reconnect_count == 0:
- print(f"将在{RECONNECT_INTERVAL / 1000}秒后启动重连(最多{MAX_RECONNECT}次)")
- self.reconnect_timer.start()
-
- def _send_tcp_request(self, request_cmd="get_status"):
- """向TCP服务器发送请求指令"""
- if not self.is_tcp_connected:
- print("TCP连接未建立,无法发送请求")
- return
-
- # 构造请求数据
- request_data = json.dumps({
- "cmd": request_cmd,
- "timestamp": self.get_current_time(),
- "client_info": "布料系统客户端",
- "erp_id": self.latest_server_data.get('erp_id')
- }) + "\n" # 增加换行符作为数据结束标识
-
- # 发送请求数据
- self.tcp_socket.write(request_data.encode("utf-8"))
- print(f"TCP请求发送:{request_data.strip()}")
-
- def _update_ui_from_data(self, data):
- """根据TCP获取的数据更新界面状态"""
- for widget in self.statusWidgets:
- api_field = widget['api_field']
- if api_field in data:
- new_value = str(data[api_field])
- widget['valueLabel'].setText(new_value)
- self.set_indicator_status(widget, new_value)
-
- # ------------------
- # 状态指示灯逻辑
- # ------------------
- def set_indicator_status(self, widget, value):
- """根据值设置状态指示灯颜色"""
- if value and value != "未知" and value != "" and value != "None":
- # 有效数据:绿色指示灯
- widget['indicator'].setStyleSheet("""
- QLabel {
- background-color: #00E676;
- border-radius: 10px;
- border: 2px solid #00796B;
- }
- """)
- else:
- # 无效数据:红色指示灯
- widget['indicator'].setStyleSheet("""
- QLabel {
- background-color: #FF5252;
- border-radius: 10px;
- border: 2px solid #C62828;
- }
- """)
-
- # ------------------
- # 按钮点击事件
- # ------------------
- def on_error_clicked(self):
- """点击“生产异常”:向服务端发送异常指令"""
- print("🔘 点击「生产异常」按钮")
- self._clear_ui_info()
- self._send_tcp_request("production_error")
-
- def on_cancel_clicked(self):
- """点击“生产取消”:向服务端发送取消指令"""
- print("🔘 点击「生产取消」按钮")
- self._clear_ui_info()
- self._send_tcp_request("cancel_feed")
-
-if __name__ == "__main__":
- app = QApplication(sys.argv)
- window = StatusMonitor()
- window.show()
- sys.exit(app.exec())
\ No newline at end of file