生产数据管理系统说明

系统概述
这是一个基于PyQt5和pyodbc开发的生产数据管理系统,主要用于管理生产过程中的物料绑定和查询操作。系统提供了上料绑定和下料查询功能,支持与SQL Server数据库交互,实现数据的插入、查询、更新和删除操作。界面采用标签页设计,操作流程清晰,反馈明确,适合生产环境使用。
主要功能模块
系统包含以下核心模块:
-
数据库管理模块(DatabaseManager)
- 负责与SQL Server数据库建立连接和交互
- 实现数据插入、查询、更新和删除操作
- 提供表和列的存在性检查功能
- 记录数据库操作日志
-
上料绑定模块(MaterialBindingWidget)
- 常温上料绑定
- 高温上料插管座绑定
- 高温上料拔管座绑定
- 支持扫码信息和批次信息录入
- 数据查询和结果展示
- 右键删除记录功能
-
下料查询模块(QueryWidget)
- 扫码查询下料记录
- 结果以表格形式展示
- 按时间由近到远排序
- 无结果时显示友好提示
-
日志管理模块(Logger)
- 全局日志记录
- 带时间戳的日志消息
- 日志自动清理功能
- 日志显示在主界面底部
界面设计特点
-
标签页布局
- 四个主要功能标签页:常温上料绑定、高温上料插管座绑定、高温上料拔管座绑定、下料查询
- 界面整洁,功能分区明确
-
按钮设计
- 绿色提交按钮(#4CAF50)表示正向操作
- 黄色按钮表示中间状态
- 红色按钮表示错误状态
- 按钮悬停和按下状态有视觉反馈
-
结果展示
- 表格形式展示查询结果
- 列宽自动适应内容
- 支持右键删除记录
-
操作反馈
- 提交操作后显示明确的状态提示
- 操作过程中按钮状态变化
- 日志区域实时记录操作信息
数据库操作流程
-
数据插入流程
- 先更新原有数据状态
- 再插入新数据
- 提交事务
- 记录操作日志
-
数据查询流程
- 构建查询条件
- 执行SQL查询
- 按时间降序排列结果
- 填充到表格中展示
-
数据删除流程
- 右键选择记录
- 确认删除操作
- 执行删除SQL
- 提交事务
- 重新查询刷新结果
颜色说明
-
绿色(#4CAF50)
- 用于表示成功状态
- 提交按钮背景色
- 成功提示文字颜色
-
黄色(#FFC107)
- 用于表示执行中状态
- 中间状态按钮背景色
-
红色(#F44336)
- 用于表示错误状态
- 失败提示文字和按钮颜色
-
绿色(#008000)
- 用于标题文字
- 表示正常状态
特殊功能说明
-
状态提示按钮
- 提交操作时按钮状态变化:初始 -> 执行中 -> 成功/失败
- 视觉反馈清晰,操作状态一目了然
-
自动清空日志
- 当日志行数超过10行且滚动条在底部时自动清空
- 保留最新的日志记录
-
扫码规则检查
- 自动检查扫码信息长度
- 长度小于10时提示不符合规则
-
日期范围查询
- 默认为最近7天的数据
- 支持自定义日期范围查询
使用说明
-
数据库配置
- 在MainWindow类中修改db_config字典中的服务器地址、数据库名称、用户名和密码
-
上料绑定
- 输入扫码信息和批次信息
- 点击"提交"按钮绑定数据
- 按钮状态显示操作结果
- 可在查询区域查询历史记录
-
下料查询
- 输入扫码信息
- 点击"查询"按钮
- 结果显示在表格中,按时间由近到远排列
-
日志查看
- 主界面底部显示系统操作日志
- 包含时间戳和操作详情
技术要点
-
数据库连接管理
- 使用pyodbc连接SQL Server
- 自动重连机制
- 事务管理确保数据一致性
-
界面交互
- 使用信号与槽机制
- 表格组件的上下文菜单
- 输入框回车提交功能
-
代码结构
- 面向对象设计,模块职责明确
- 日志系统独立封装
- 界面组件继承复用
这个生产数据管理系统适合在生产环境中使用,提供了完整的物料绑定和查询功能,界面友好,操作简单,同时具备完善的日志记录和错误处理机制。
import sys
import traceback
import pyodbc
from PyQt5.QtWidgets import (QApplication, QMainWindow, QTabWidget, QWidget, QVBoxLayout,
QHBoxLayout, QLabel, QLineEdit, QPushButton, QTextEdit,
QMessageBox, QGroupBox, QTableWidget, QTableWidgetItem,
QHeaderView, QMenu, QAction, QInputDialog, QDateEdit)
from PyQt5.QtCore import Qt, pyqtSignal, QObject, QDate, QDateTime
from PyQt5.QtGui import QFont, QColor, QPalette
import datetime
class Logger(QObject):
"""全局日志管理器,通过信号传递日志消息"""
log_message = pyqtSignal(str)
def log(self, message):
"""发送带时间戳的日志消息到信号"""
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3] # 生成时间戳,精确到毫秒
timestamped_message = f"[{timestamp}] {message}"
self.log_message.emit(timestamped_message)
class LogSignal(QObject):
"""数据库操作日志信号类"""
log_message = pyqtSignal(str)
class DatabaseManager:
"""数据库管理类,负责与SQL Server交互"""
def __init__(self, server, database, username, password, logger=None):
self.server = server
self.database = database
self.username = username
self.password = password
self.connection = None
self.logger = logger
self.db_log_signal = LogSignal()
def get_connection_string(self):
"""获取数据库连接字符串"""
return (
f'DRIVER={
{
ODBC Driver 17 for SQL Server}};'
f'SERVER={self.server};'
f'DATABASE={self.database};'
f'UID={self.username};'
f'PWD={self.password}'
)
def connect(self):
"""连接到SQL Server数据库"""
try:
connection_string = self.get_connection_string()
self.log_message(f"[数据库] 尝试连接: {connection_string}")
self.connection = pyodbc.connect(connection_string)
self.log_message("[数据库] 连接成功")
return True
except Exception as e:
error_msg = f"数据库连接错误: {str(e)}"
self.log_message(f"[错误] {error_msg}")
return False
def disconnect(self):
"""断开数据库连接"""
if self.connection:
try:
self.connection.close()
self.log_message("[数据库] 连接已断开")
except Exception as e:
self.log_message(f"[错误] 断开数据库连接时出错: {str(e)}")
finally:
self.connection = None
def execute_query(self, query, params=None):
"""执行SQL查询"""
if not self.connection:
if not self.connect():
raise Exception("无法建立数据库连接")
try:
cursor = self.connection.cursor()
query_str = query
if params:
query_str = f"{query} (参数: {params})"
self.log_message(f"[SQL] 执行查询: {query_str}")
cursor.execute(query, params)
return cursor
except Exception as e:
error_msg = f"SQL执行错误: {str(e)}"
self.log_message(f"[错误] {error_msg}")
raise
def commit(self):
"""提交事务"""
if self.connection:
try:
self.connection.commit()
self.log_message("[数据库] 事务已提交")
except Exception as e:
error_msg = f"提交事务时出错: {str(e)}"
self.log_message(f"[错误] {error_msg}")
raise
def update_data(self, table_name, barcode):
"""更新指定条码的状态为1"""
query = f"UPDATE {table_name} SET state = 1 WHERE barcode = ?"
try:
cursor = self.execute_query(query, (barcode,))
if cursor:
affected_rows = cursor.rowcount # 获取受影响的行数
self.commit()
self.log_message(f"[成功] 已更新 {table_name} 表中 {affected_rows} 条记录的状态")
return True
return False
except Exception as e:
error_msg = f"更新数据时出错: {str(e)}"
self.log_message(f"[错误] {error_msg}")
raise
def insert_data(self, table_name, barcode, batch):
"""插入数据到指定表,插入前先更新原有数据状态"""
try:
# 先更新原有数据状态
self.update_data(table_name, barcode)
# 再插入新数据
query = f"INSERT INTO {table_name} (barcode, batch, STATE) VALUES (?, ?, 0)"
cursor = self.execute_query(query, (barcode, batch))
if cursor:
self.commit()
self.log_message(f"[成功] 数据已成功插入到 {table_name} 表")
return True
return False
except Exception as e:
error_msg = f"插入数据时出错: {str(e)}"
self.log_message(f"[错误] {error_msg}")
raise
def query_data(self, table_name, barcode=None, start_date=None, end_date=None):
"""从指定表查询数据,结果按时间由近到远排序"""
params = []
query = f"SELECT barcode, batch, TIME FROM {table_name} WHERE 1=1"
if barcode:
query += " AND barcode = ?"
params.append(barcode)
if start_date:
query += " AND TIME >= ?"
params.append(start_date)
if end_date:
query += " AND TIME <= ?"
params.append(end_date)
query += " ORDER BY TIME DESC" # 按时间降序排列,最新时间在前
try:
cursor = self.execute_query(query, params)
if cursor:
results = []
for row_num, row in enumerate(cursor.fetchall(), 1): # 从1开始编号
results.append({
'id': row_num, # 本地自增ID,用于显示序号
'barcode': row.barcode,
'batch': row.batch,
'TIME': row.TIME
})
return results
return []
except Exception as e:
error_msg

最低0.47元/天 解锁文章
995

被折叠的 条评论
为什么被折叠?



