实现检验配置功能,支持动态配置检验项目;修复表格表头布局错位问题
This commit is contained in:
parent
5977b29a9c
commit
f31871b4f5
2
.gitignore
vendored
2
.gitignore
vendored
@ -22,7 +22,7 @@ __pycache__/
|
||||
Thumbs.db
|
||||
|
||||
# 缓存文件
|
||||
__pycache__/
|
||||
*__pycache__/
|
||||
.pytest_cache/
|
||||
.coverage
|
||||
htmlcov/
|
||||
|
||||
327
dao/inspection_dao.py
Normal file
327
dao/inspection_dao.py
Normal file
@ -0,0 +1,327 @@
|
||||
import json
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from utils.sql_utils import SQLUtils
|
||||
|
||||
class InspectionDAO:
|
||||
"""检验项目配置和数据访问对象"""
|
||||
|
||||
def __init__(self):
|
||||
"""初始化数据访问对象"""
|
||||
self.db = SQLUtils('sqlite', database='db/jtDB.db')
|
||||
|
||||
def __del__(self):
|
||||
"""析构函数,确保数据库连接关闭"""
|
||||
if hasattr(self, 'db'):
|
||||
self.db.close()
|
||||
|
||||
def get_all_inspection_configs(self, include_disabled=False):
|
||||
"""获取所有检验项目配置
|
||||
|
||||
Args:
|
||||
include_disabled: 是否包含禁用的项目
|
||||
|
||||
Returns:
|
||||
list: 检验项目配置列表
|
||||
"""
|
||||
try:
|
||||
if include_disabled:
|
||||
sql = """
|
||||
SELECT id, position, name, display_name, enabled, required,
|
||||
data_type, min_value, max_value, enum_values, unit, sort_order
|
||||
FROM inspection_config
|
||||
WHERE is_deleted = FALSE
|
||||
ORDER BY sort_order, position
|
||||
"""
|
||||
params = ()
|
||||
else:
|
||||
sql = """
|
||||
SELECT id, position, name, display_name, enabled, required,
|
||||
data_type, min_value, max_value, enum_values, unit, sort_order
|
||||
FROM inspection_config
|
||||
WHERE is_deleted = FALSE AND enabled = TRUE
|
||||
ORDER BY sort_order, position
|
||||
"""
|
||||
params = ()
|
||||
|
||||
self.db.cursor.execute(sql, params)
|
||||
results = self.db.cursor.fetchall()
|
||||
|
||||
configs = []
|
||||
for row in results:
|
||||
config = {
|
||||
'id': row[0],
|
||||
'position': row[1],
|
||||
'name': row[2],
|
||||
'display_name': row[3],
|
||||
'enabled': bool(row[4]),
|
||||
'required': bool(row[5]),
|
||||
'data_type': row[6],
|
||||
'min_value': row[7],
|
||||
'max_value': row[8],
|
||||
'enum_values': json.loads(row[9]) if row[9] else None,
|
||||
'unit': row[10],
|
||||
'sort_order': row[11]
|
||||
}
|
||||
configs.append(config)
|
||||
|
||||
return configs
|
||||
except Exception as e:
|
||||
logging.error(f"获取检验项目配置失败: {str(e)}")
|
||||
return []
|
||||
|
||||
def get_enabled_inspection_configs(self):
|
||||
"""获取已启用的检验项目配置
|
||||
|
||||
Returns:
|
||||
list: 已启用的检验项目配置列表
|
||||
"""
|
||||
return self.get_all_inspection_configs(include_disabled=False)
|
||||
|
||||
def get_inspection_config_by_position(self, position):
|
||||
"""根据位置获取检验项目配置
|
||||
|
||||
Args:
|
||||
position: 位置序号 (1-6)
|
||||
|
||||
Returns:
|
||||
dict: 检验项目配置, 未找到则返回None
|
||||
"""
|
||||
try:
|
||||
sql = """
|
||||
SELECT id, position, name, display_name, enabled, required,
|
||||
data_type, min_value, max_value, enum_values, unit, sort_order
|
||||
FROM inspection_config
|
||||
WHERE position = ? AND is_deleted = FALSE
|
||||
"""
|
||||
params = (position,)
|
||||
|
||||
self.db.cursor.execute(sql, params)
|
||||
row = self.db.cursor.fetchone()
|
||||
|
||||
if row:
|
||||
config = {
|
||||
'id': row[0],
|
||||
'position': row[1],
|
||||
'name': row[2],
|
||||
'display_name': row[3],
|
||||
'enabled': bool(row[4]),
|
||||
'required': bool(row[5]),
|
||||
'data_type': row[6],
|
||||
'min_value': row[7],
|
||||
'max_value': row[8],
|
||||
'enum_values': json.loads(row[9]) if row[9] else None,
|
||||
'unit': row[10],
|
||||
'sort_order': row[11]
|
||||
}
|
||||
return config
|
||||
else:
|
||||
return None
|
||||
except Exception as e:
|
||||
logging.error(f"获取检验项目配置失败: {str(e)}")
|
||||
return None
|
||||
|
||||
def update_inspection_config(self, config_id, data, username='system'):
|
||||
"""更新检验项目配置
|
||||
|
||||
Args:
|
||||
config_id: 配置ID
|
||||
data: 更新数据
|
||||
username: 操作用户
|
||||
|
||||
Returns:
|
||||
bool: 更新是否成功
|
||||
"""
|
||||
try:
|
||||
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# 构建更新SQL
|
||||
update_fields = []
|
||||
params = []
|
||||
|
||||
# 可更新的字段
|
||||
allowed_fields = [
|
||||
'name', 'display_name', 'enabled', 'required',
|
||||
'data_type', 'min_value', 'max_value', 'unit',
|
||||
'sort_order', 'enum_values'
|
||||
]
|
||||
|
||||
for field in allowed_fields:
|
||||
if field in data:
|
||||
# 特殊处理enum_values字段,确保存储为JSON字符串
|
||||
if field == 'enum_values' and data[field] is not None:
|
||||
if isinstance(data[field], list):
|
||||
update_fields.append(f"{field} = ?")
|
||||
params.append(json.dumps(data[field]))
|
||||
elif isinstance(data[field], str):
|
||||
# 如果已经是字符串,检查是否有效的JSON
|
||||
try:
|
||||
json.loads(data[field])
|
||||
update_fields.append(f"{field} = ?")
|
||||
params.append(data[field])
|
||||
except:
|
||||
logging.warning(f"无效的JSON: {data[field]}")
|
||||
continue
|
||||
else:
|
||||
update_fields.append(f"{field} = ?")
|
||||
params.append(data[field])
|
||||
|
||||
# 添加更新时间和更新人
|
||||
update_fields.append("update_time = ?")
|
||||
params.append(current_time)
|
||||
update_fields.append("update_by = ?")
|
||||
params.append(username)
|
||||
|
||||
# 添加配置ID到参数列表
|
||||
params.append(config_id)
|
||||
|
||||
# 构建SQL
|
||||
sql = f"""
|
||||
UPDATE inspection_config
|
||||
SET {', '.join(update_fields)}
|
||||
WHERE id = ?
|
||||
"""
|
||||
|
||||
self.db.execute_update(sql, params)
|
||||
return True
|
||||
except Exception as e:
|
||||
logging.error(f"更新检验项目配置失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def toggle_inspection_config(self, position, enabled, username='system'):
|
||||
"""启用或禁用检验项目配置
|
||||
|
||||
Args:
|
||||
position: 位置序号 (1-6)
|
||||
enabled: 是否启用
|
||||
username: 操作用户
|
||||
|
||||
Returns:
|
||||
bool: 操作是否成功
|
||||
"""
|
||||
try:
|
||||
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
sql = """
|
||||
UPDATE inspection_config
|
||||
SET enabled = ?, update_time = ?, update_by = ?
|
||||
WHERE position = ? AND is_deleted = FALSE
|
||||
"""
|
||||
params = (enabled, current_time, username, position)
|
||||
|
||||
self.db.execute_update(sql, params)
|
||||
return True
|
||||
except Exception as e:
|
||||
logging.error(f"更新检验项目启用状态失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def save_inspection_data(self, order_id, data, username='system'):
|
||||
"""保存检验数据
|
||||
|
||||
Args:
|
||||
order_id: 工程号
|
||||
data: 检验数据列表,格式: [{'position': 1, 'config_id': 1, 'value': '合格'}, ...]
|
||||
username: 操作用户
|
||||
|
||||
Returns:
|
||||
bool: 保存是否成功
|
||||
"""
|
||||
try:
|
||||
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
self.db.begin_transaction()
|
||||
|
||||
for item in data:
|
||||
position = item.get('position')
|
||||
config_id = item.get('config_id')
|
||||
value = item.get('value')
|
||||
status = item.get('status', 'pass')
|
||||
remark = item.get('remark', '')
|
||||
|
||||
# 检查是否已存在该工程号和位置的记录
|
||||
check_sql = """
|
||||
SELECT id FROM inspection_data
|
||||
WHERE order_id = ? AND position = ? AND is_deleted = FALSE
|
||||
"""
|
||||
check_params = (order_id, position)
|
||||
|
||||
self.db.cursor.execute(check_sql, check_params)
|
||||
existing = self.db.cursor.fetchone()
|
||||
|
||||
if existing:
|
||||
# 更新已有记录
|
||||
update_sql = """
|
||||
UPDATE inspection_data
|
||||
SET config_id = ?, value = ?, status = ?, remark = ?,
|
||||
update_time = ?, update_by = ?
|
||||
WHERE id = ?
|
||||
"""
|
||||
update_params = (
|
||||
config_id, value, status, remark,
|
||||
current_time, username, existing[0]
|
||||
)
|
||||
self.db.cursor.execute(update_sql, update_params)
|
||||
else:
|
||||
# 插入新记录
|
||||
insert_sql = """
|
||||
INSERT INTO inspection_data (
|
||||
order_id, position, config_id, value, status, remark,
|
||||
create_time, create_by, is_deleted
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, FALSE)
|
||||
"""
|
||||
insert_params = (
|
||||
order_id, position, config_id, value, status, remark,
|
||||
current_time, username
|
||||
)
|
||||
self.db.cursor.execute(insert_sql, insert_params)
|
||||
|
||||
self.db.commit_transaction()
|
||||
return True
|
||||
except Exception as e:
|
||||
self.db.rollback_transaction()
|
||||
logging.error(f"保存检验数据失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def get_inspection_data_by_order(self, order_id):
|
||||
"""根据工程号获取检验数据
|
||||
|
||||
Args:
|
||||
order_id: 工程号
|
||||
|
||||
Returns:
|
||||
list: 检验数据列表
|
||||
"""
|
||||
try:
|
||||
sql = """
|
||||
SELECT d.id, d.position, d.config_id, d.value, d.status, d.remark,
|
||||
c.name, c.display_name, c.data_type, c.unit
|
||||
FROM inspection_data d
|
||||
JOIN inspection_config c ON d.config_id = c.id
|
||||
WHERE d.order_id = ? AND d.is_deleted = FALSE
|
||||
ORDER BY d.position
|
||||
"""
|
||||
params = (order_id,)
|
||||
|
||||
self.db.cursor.execute(sql, params)
|
||||
results = self.db.cursor.fetchall()
|
||||
|
||||
data_list = []
|
||||
for row in results:
|
||||
data = {
|
||||
'id': row[0],
|
||||
'position': row[1],
|
||||
'config_id': row[2],
|
||||
'value': row[3],
|
||||
'status': row[4],
|
||||
'remark': row[5],
|
||||
'name': row[6],
|
||||
'display_name': row[7],
|
||||
'data_type': row[8],
|
||||
'unit': row[9]
|
||||
}
|
||||
data_list.append(data)
|
||||
|
||||
return data_list
|
||||
except Exception as e:
|
||||
logging.error(f"获取检验数据失败: {str(e)}")
|
||||
return []
|
||||
55
db/schema.sql
Normal file
55
db/schema.sql
Normal file
@ -0,0 +1,55 @@
|
||||
-- 创建检验项目配置表
|
||||
CREATE TABLE IF NOT EXISTS inspection_config (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
position INTEGER NOT NULL, -- 位置序号 (1-6)
|
||||
name VARCHAR(50) NOT NULL, -- 检验项目名称
|
||||
display_name VARCHAR(50) NOT NULL, -- 显示名称
|
||||
enabled BOOLEAN DEFAULT TRUE, -- 是否启用
|
||||
required BOOLEAN DEFAULT FALSE, -- 是否必填
|
||||
data_type VARCHAR(20) DEFAULT 'text', -- 数据类型: text, number, enum
|
||||
min_value FLOAT, -- 最小值 (用于number类型)
|
||||
max_value FLOAT, -- 最大值 (用于number类型)
|
||||
enum_values TEXT, -- 枚举值 (用于enum类型, JSON格式存储)
|
||||
unit VARCHAR(20), -- 单位
|
||||
sort_order INTEGER NOT NULL, -- 排序顺序
|
||||
create_time TIMESTAMP NOT NULL,
|
||||
create_by VARCHAR(50) NOT NULL,
|
||||
update_time TIMESTAMP,
|
||||
update_by VARCHAR(50),
|
||||
is_deleted BOOLEAN DEFAULT FALSE,
|
||||
UNIQUE(position, is_deleted) -- 确保同一位置只有一个激活的配置
|
||||
);
|
||||
|
||||
-- 创建检验数据记录表
|
||||
CREATE TABLE IF NOT EXISTS inspection_data (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
order_id VARCHAR(50) NOT NULL, -- 关联的工程号
|
||||
position INTEGER NOT NULL, -- 位置序号
|
||||
config_id INTEGER NOT NULL, -- 关联的配置ID
|
||||
value TEXT NOT NULL, -- 检验值 (所有类型都用TEXT存储)
|
||||
status VARCHAR(20) DEFAULT 'pass', -- 状态: pass, fail, warning
|
||||
remark TEXT, -- 备注
|
||||
create_time TIMESTAMP NOT NULL,
|
||||
create_by VARCHAR(50) NOT NULL,
|
||||
update_time TIMESTAMP,
|
||||
update_by VARCHAR(50),
|
||||
is_deleted BOOLEAN DEFAULT FALSE,
|
||||
FOREIGN KEY(config_id) REFERENCES inspection_config(id)
|
||||
);
|
||||
|
||||
-- 创建默认检验项目数据
|
||||
INSERT OR IGNORE INTO inspection_config (
|
||||
position, name, display_name, enabled, required, data_type,
|
||||
min_value, max_value, unit, sort_order, create_time, create_by
|
||||
) VALUES
|
||||
(1, 'appearance', '外观', TRUE, TRUE, 'enum', NULL, NULL, '', 1, CURRENT_TIMESTAMP, 'system'),
|
||||
(2, 'diameter', '线径', TRUE, TRUE, 'number', 0, 100, 'mm', 2, CURRENT_TIMESTAMP, 'system'),
|
||||
(3, 'resistance', '电阻', TRUE, FALSE, 'number', 0, 1000, 'Ω', 3, CURRENT_TIMESTAMP, 'system'),
|
||||
(4, 'hardness', '硬度', FALSE, FALSE, 'number', 0, 100, 'HRC', 4, CURRENT_TIMESTAMP, 'system'),
|
||||
(5, 'strength', '强度', FALSE, FALSE, 'number', 0, 1000, 'MPa', 5, CURRENT_TIMESTAMP, 'system'),
|
||||
(6, 'custom', '自定义', FALSE, FALSE, 'text', NULL, NULL, '', 6, CURRENT_TIMESTAMP, 'system');
|
||||
|
||||
-- 为外观检验项设置枚举值
|
||||
UPDATE inspection_config
|
||||
SET enum_values = '["合格", "不合格", "需要重检"]'
|
||||
WHERE name = 'appearance';
|
||||
Binary file not shown.
Binary file not shown.
216
ui/inspection_settings_ui.py
Normal file
216
ui/inspection_settings_ui.py
Normal file
@ -0,0 +1,216 @@
|
||||
from PySide6.QtWidgets import (
|
||||
QWidget, QVBoxLayout, QHBoxLayout, QFormLayout, QLabel,
|
||||
QLineEdit, QCheckBox, QComboBox, QPushButton, QGroupBox,
|
||||
QTableWidget, QTableWidgetItem, QHeaderView, QAbstractItemView,
|
||||
QSpinBox, QDoubleSpinBox, QFrame, QScrollArea
|
||||
)
|
||||
from PySide6.QtGui import QFont, QBrush, QColor
|
||||
from PySide6.QtCore import Qt, Signal
|
||||
|
||||
class InspectionSettingsUI(QWidget):
|
||||
"""检验设置UI"""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.parent = parent
|
||||
self.init_ui()
|
||||
|
||||
def init_ui(self):
|
||||
"""初始化UI"""
|
||||
# 设置字体
|
||||
self.title_font = QFont("微软雅黑", 14, QFont.Bold)
|
||||
self.normal_font = QFont("微软雅黑", 11)
|
||||
self.small_font = QFont("微软雅黑", 9)
|
||||
|
||||
# 设置背景颜色,便于识别
|
||||
self.setStyleSheet("background-color: #f5f5f5;")
|
||||
|
||||
# 创建主布局
|
||||
self.main_layout = QVBoxLayout(self)
|
||||
self.main_layout.setContentsMargins(20, 20, 20, 20)
|
||||
self.main_layout.setSpacing(15)
|
||||
|
||||
# 标题
|
||||
self.title_label = QLabel("检验项目配置")
|
||||
self.title_label.setFont(self.title_font)
|
||||
self.title_label.setAlignment(Qt.AlignCenter)
|
||||
self.title_label.setStyleSheet("color: #1a237e; padding: 10px;")
|
||||
self.main_layout.addWidget(self.title_label)
|
||||
|
||||
# 说明文本
|
||||
self.desc_label = QLabel("配置检验二级菜单项目,至少1项,最多6项。启用的项目将显示在微丝产线表格的检验区域。")
|
||||
self.desc_label.setWordWrap(True)
|
||||
self.desc_label.setStyleSheet("color: #666666; padding: 0px 10px 10px 10px;")
|
||||
self.main_layout.addWidget(self.desc_label)
|
||||
|
||||
# 创建滚动区域
|
||||
self.scroll_area = QScrollArea()
|
||||
self.scroll_area.setWidgetResizable(True)
|
||||
self.scroll_area.setFrameShape(QFrame.NoFrame)
|
||||
|
||||
# 创建滚动区域的内容部件
|
||||
self.scroll_widget = QWidget()
|
||||
self.scroll_layout = QVBoxLayout(self.scroll_widget)
|
||||
self.scroll_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.scroll_layout.setSpacing(15)
|
||||
|
||||
# 创建6个检验项目配置组
|
||||
self.config_groups = []
|
||||
for i in range(6):
|
||||
group = self.create_config_group(i + 1)
|
||||
self.scroll_layout.addWidget(group)
|
||||
self.config_groups.append(group)
|
||||
|
||||
# 设置滚动区域的部件
|
||||
self.scroll_area.setWidget(self.scroll_widget)
|
||||
self.main_layout.addWidget(self.scroll_area, 1)
|
||||
|
||||
# 底部按钮区域
|
||||
self.button_layout = QHBoxLayout()
|
||||
self.button_layout.setContentsMargins(0, 10, 0, 0)
|
||||
|
||||
self.save_button = QPushButton("保存配置")
|
||||
self.save_button.setFont(self.normal_font)
|
||||
self.save_button.setFixedSize(120, 40)
|
||||
self.save_button.setStyleSheet("""
|
||||
QPushButton {
|
||||
background-color: #4caf50;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
QPushButton:pressed {
|
||||
background-color: #3d8b40;
|
||||
}
|
||||
""")
|
||||
|
||||
self.reset_button = QPushButton("重置")
|
||||
self.reset_button.setFont(self.normal_font)
|
||||
self.reset_button.setFixedSize(120, 40)
|
||||
self.reset_button.setStyleSheet("""
|
||||
QPushButton {
|
||||
background-color: #f44336;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background-color: #e53935;
|
||||
}
|
||||
QPushButton:pressed {
|
||||
background-color: #d32f2f;
|
||||
}
|
||||
""")
|
||||
|
||||
self.button_layout.addStretch()
|
||||
self.button_layout.addWidget(self.reset_button)
|
||||
self.button_layout.addSpacing(20)
|
||||
self.button_layout.addWidget(self.save_button)
|
||||
|
||||
self.main_layout.addLayout(self.button_layout)
|
||||
|
||||
def create_config_group(self, position):
|
||||
"""创建检验项目配置组
|
||||
|
||||
Args:
|
||||
position: 位置序号 (1-6)
|
||||
|
||||
Returns:
|
||||
QGroupBox: 配置组
|
||||
"""
|
||||
group = QGroupBox(f"检验项目 {position}")
|
||||
group.setFont(self.normal_font)
|
||||
group.setCheckable(True)
|
||||
group.setChecked(position <= 3) # 默认前3个启用
|
||||
|
||||
group_layout = QFormLayout(group)
|
||||
group_layout.setContentsMargins(15, 25, 15, 15)
|
||||
group_layout.setSpacing(10)
|
||||
|
||||
# 名称
|
||||
name_label = QLabel("项目名称:")
|
||||
name_label.setFont(self.normal_font)
|
||||
name_input = QLineEdit()
|
||||
name_input.setFont(self.normal_font)
|
||||
name_input.setObjectName(f"name_input_{position}")
|
||||
group_layout.addRow(name_label, name_input)
|
||||
|
||||
# 显示名称
|
||||
display_name_label = QLabel("显示名称:")
|
||||
display_name_label.setFont(self.normal_font)
|
||||
display_name_input = QLineEdit()
|
||||
display_name_input.setFont(self.normal_font)
|
||||
display_name_input.setObjectName(f"display_name_input_{position}")
|
||||
group_layout.addRow(display_name_label, display_name_input)
|
||||
|
||||
# 数据类型
|
||||
data_type_label = QLabel("数据类型:")
|
||||
data_type_label.setFont(self.normal_font)
|
||||
data_type_combo = QComboBox()
|
||||
data_type_combo.setFont(self.normal_font)
|
||||
data_type_combo.setObjectName(f"data_type_combo_{position}")
|
||||
data_type_combo.addItem("文本", "text")
|
||||
data_type_combo.addItem("数值", "number")
|
||||
data_type_combo.addItem("枚举", "enum")
|
||||
group_layout.addRow(data_type_label, data_type_combo)
|
||||
|
||||
# 单位 (用于数值类型)
|
||||
unit_label = QLabel("单位:")
|
||||
unit_label.setFont(self.normal_font)
|
||||
unit_input = QLineEdit()
|
||||
unit_input.setFont(self.normal_font)
|
||||
unit_input.setObjectName(f"unit_input_{position}")
|
||||
group_layout.addRow(unit_label, unit_input)
|
||||
|
||||
# 最小值 (用于数值类型)
|
||||
min_value_label = QLabel("最小值:")
|
||||
min_value_label.setFont(self.normal_font)
|
||||
min_value_spin = QDoubleSpinBox()
|
||||
min_value_spin.setFont(self.normal_font)
|
||||
min_value_spin.setObjectName(f"min_value_spin_{position}")
|
||||
min_value_spin.setRange(-999999, 999999)
|
||||
min_value_spin.setDecimals(2)
|
||||
min_value_spin.setSingleStep(0.1)
|
||||
group_layout.addRow(min_value_label, min_value_spin)
|
||||
|
||||
# 最大值 (用于数值类型)
|
||||
max_value_label = QLabel("最大值:")
|
||||
max_value_label.setFont(self.normal_font)
|
||||
max_value_spin = QDoubleSpinBox()
|
||||
max_value_spin.setFont(self.normal_font)
|
||||
max_value_spin.setObjectName(f"max_value_spin_{position}")
|
||||
max_value_spin.setRange(-999999, 999999)
|
||||
max_value_spin.setDecimals(2)
|
||||
max_value_spin.setSingleStep(0.1)
|
||||
max_value_spin.setValue(100)
|
||||
group_layout.addRow(max_value_label, max_value_spin)
|
||||
|
||||
# 枚举值 (用于枚举类型)
|
||||
enum_values_label = QLabel("枚举值:")
|
||||
enum_values_label.setFont(self.normal_font)
|
||||
enum_values_input = QLineEdit()
|
||||
enum_values_input.setFont(self.normal_font)
|
||||
enum_values_input.setObjectName(f"enum_values_input_{position}")
|
||||
enum_values_input.setPlaceholderText("用逗号分隔,如: 合格,不合格,需重检")
|
||||
group_layout.addRow(enum_values_label, enum_values_input)
|
||||
|
||||
# 是否必填
|
||||
required_check = QCheckBox("必填项")
|
||||
required_check.setFont(self.normal_font)
|
||||
required_check.setObjectName(f"required_check_{position}")
|
||||
group_layout.addRow("", required_check)
|
||||
|
||||
# 保存位置信息
|
||||
group.setProperty("position", position)
|
||||
|
||||
return group
|
||||
|
||||
def set_form_enabled(self, enabled):
|
||||
"""设置表单是否可编辑"""
|
||||
for group in self.config_groups:
|
||||
group.setEnabled(enabled)
|
||||
self.save_button.setEnabled(enabled)
|
||||
self.reset_button.setEnabled(enabled)
|
||||
@ -84,26 +84,14 @@ class MainWindowUI(QMainWindow):
|
||||
self.project_table = QTableWidget(4, 4)
|
||||
self.project_table.setHorizontalHeaderLabels(["用电", "数量", "产量", "开机率"])
|
||||
self.project_table.setVerticalHeaderLabels(["当日", "当月", "当年", "累计"])
|
||||
#设置字体
|
||||
self.project_table.setFont(self.normal_font)
|
||||
# 设置垂直表头宽度
|
||||
self.project_table.verticalHeader().setFixedWidth(60)
|
||||
self.project_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
||||
self.project_table.verticalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
||||
self.project_table.setEditTriggers(QTableWidget.NoEditTriggers) # 设置为不可编辑
|
||||
|
||||
# 设置表格样式
|
||||
self.project_table.setStyleSheet("""
|
||||
QTableWidget {
|
||||
border: none;
|
||||
gridline-color: #dddddd;
|
||||
}
|
||||
QHeaderView::section {
|
||||
background-color: #f0f0f0;
|
||||
padding: 4px;
|
||||
border: 1px solid #cccccc;
|
||||
font-weight: bold;
|
||||
}
|
||||
""")
|
||||
|
||||
self.project_layout.addWidget(self.project_table)
|
||||
|
||||
self.left_layout.addWidget(self.project_frame)
|
||||
|
||||
# 任务信息区域 - 使用QFrame包裹,添加边框
|
||||
@ -162,7 +150,7 @@ class MainWindowUI(QMainWindow):
|
||||
|
||||
# 订单行
|
||||
self.order_layout = QHBoxLayout()
|
||||
self.order_label = QLabel("订单")
|
||||
self.order_label = QLabel("工程号")
|
||||
self.order_label.setFont(QFont("微软雅黑", 12, QFont.Bold))
|
||||
self.order_label.setFixedHeight(35)
|
||||
self.order_label.setStyleSheet("padding: 0 5px; color: #333333;")
|
||||
@ -463,9 +451,9 @@ class MainWindowUI(QMainWindow):
|
||||
self.process_content_layout.setSpacing(0)
|
||||
|
||||
# 创建表格 - 支持动态配置检验列数
|
||||
self.inspection_columns = 3 # 默认3列,可动态配置
|
||||
# TODO:后续从数据库中读取
|
||||
self.inspection_headers = ["外观", "线径", "电阻", "硬度", "强度"] # 默认检验标题
|
||||
self.inspection_columns = 1 # 默认至少显示1列
|
||||
# 默认检验标题,实际运行时将通过InspectionConfigManager获取
|
||||
self.inspection_headers = ["检验项"]
|
||||
total_columns = 2 + self.inspection_columns + 2 # 上料2列 + 检验N列 + 包装2列
|
||||
|
||||
self.process_table = QTableWidget(8, total_columns) # 8行:1行标题区域 + 1行列标题 + 6行数据
|
||||
@ -486,9 +474,7 @@ class MainWindowUI(QMainWindow):
|
||||
|
||||
# 创建表头 - 合并单元格
|
||||
self.create_process_table_headers()
|
||||
|
||||
# 填充表格内容
|
||||
self.fill_process_table_cells()
|
||||
|
||||
|
||||
# 添加表格到布局
|
||||
self.process_content_layout.addWidget(self.process_table)
|
||||
@ -540,9 +526,7 @@ class MainWindowUI(QMainWindow):
|
||||
|
||||
# 添加表格到布局
|
||||
self.record_layout.addWidget(self.record_table)
|
||||
|
||||
# 填充表格内容
|
||||
self.fill_record_table_cells()
|
||||
|
||||
|
||||
# 添加一个通用的单元格创建方法
|
||||
def create_cell_item(self, text, alignment=Qt.AlignCenter):
|
||||
@ -559,61 +543,6 @@ class MainWindowUI(QMainWindow):
|
||||
item.setTextAlignment(alignment)
|
||||
return item
|
||||
|
||||
def fill_process_table_cells(self):
|
||||
"""填充微丝产线表格单元格"""
|
||||
# 工序工程数据
|
||||
process_data = ["拉丝", "退火", "检验", "包装", "入库", "出库"]
|
||||
|
||||
# 填充工序数据
|
||||
for row in range(6):
|
||||
# 设置序号
|
||||
self.process_table.setItem(row + 2, 0, self.create_cell_item(row + 1))
|
||||
|
||||
# 设置工序工程名称
|
||||
self.process_table.setItem(row + 2, 1, self.create_cell_item(process_data[row]))
|
||||
|
||||
# 只为前3行设置数据
|
||||
if row < 3:
|
||||
# 检验区域 - 动态列
|
||||
inspection_data = ["合格", f"{0.5 + row * 0.1:.1f}", f"{10 + row * 5}", f"{80 + row * 5}", f"{90 + row * 2}"]
|
||||
for i in range(min(self.inspection_columns, len(inspection_data))):
|
||||
self.process_table.setItem(row + 2, 2 + i, self.create_cell_item(inspection_data[i]))
|
||||
|
||||
# 包装区域 - 贴标和称重
|
||||
packaging_start_col = 2 + self.inspection_columns
|
||||
|
||||
self.process_table.setItem(row + 2, packaging_start_col, self.create_cell_item("已完成"))
|
||||
self.process_table.setItem(row + 2, packaging_start_col + 1, self.create_cell_item(f"{50 + row * 10}"))
|
||||
|
||||
def fill_record_table_cells(self):
|
||||
"""填充包装记录表格单元格"""
|
||||
# 填充序号列
|
||||
for row in range(12):
|
||||
self.record_table.setItem(row + 1, 0, self.create_cell_item(row + 1))
|
||||
|
||||
# 填充示例数据
|
||||
record_data = [
|
||||
["ORD-2025-001", "不锈钢", "0.5mm", "T001", "A001", "50kg"],
|
||||
["ORD-2025-001", "不锈钢", "0.6mm", "T001", "A002", "55kg"],
|
||||
["ORD-2025-001", "不锈钢", "0.7mm", "T001", "A003", "60kg"],
|
||||
]
|
||||
|
||||
# 只填充前3行
|
||||
for row in range(3):
|
||||
for col, value in enumerate(record_data[row]):
|
||||
self.record_table.setItem(row + 1, col + 1, self.create_cell_item(value))
|
||||
|
||||
# 设置合计行
|
||||
self.record_table.setItem(13, 0, self.create_header_item("合计"))
|
||||
|
||||
# 轴数
|
||||
self.record_table.setItem(13, 3, self.create_header_item("轴数"))
|
||||
self.record_table.setItem(13, 4, self.create_cell_item("0"))
|
||||
|
||||
# 重量
|
||||
self.record_table.setItem(13, 5, self.create_header_item("重量"))
|
||||
self.record_table.setItem(13, 6, self.create_cell_item("0.0"))
|
||||
|
||||
def set_inspection_columns(self, columns, headers=None):
|
||||
"""设置检验列数和标题
|
||||
|
||||
@ -621,6 +550,9 @@ class MainWindowUI(QMainWindow):
|
||||
columns: 检验列数量
|
||||
headers: 检验列标题列表,如果为None则使用默认标题
|
||||
"""
|
||||
# 确保列数在1-6之间
|
||||
columns = max(1, min(6, columns))
|
||||
|
||||
# 保存旧的列数
|
||||
old_column_count = self.process_table.columnCount()
|
||||
|
||||
@ -636,18 +568,30 @@ class MainWindowUI(QMainWindow):
|
||||
if item_r1:
|
||||
del item_r1
|
||||
|
||||
# 清除所有单元格合并
|
||||
for row in range(2):
|
||||
for col in range(old_column_count):
|
||||
try:
|
||||
self.process_table.setSpan(row, col, 1, 1)
|
||||
except:
|
||||
pass # 忽略错误,可能有些单元格没有合并
|
||||
|
||||
# 更新检验列数
|
||||
self.inspection_columns = columns
|
||||
|
||||
# 更新检验标题
|
||||
if headers is not None and len(headers) >= columns:
|
||||
self.inspection_headers = headers
|
||||
self.inspection_headers = headers[:columns] # 只使用前N个标题
|
||||
elif len(self.inspection_headers) < columns:
|
||||
# 如果当前标题不足,扩展标题列表
|
||||
current_len = len(self.inspection_headers)
|
||||
for i in range(current_len, columns):
|
||||
self.inspection_headers.append(f"检验项{i+1}")
|
||||
|
||||
# 截断多余的标题
|
||||
if len(self.inspection_headers) > columns:
|
||||
self.inspection_headers = self.inspection_headers[:columns]
|
||||
|
||||
# 计算总列数
|
||||
total_columns = 2 + self.inspection_columns + 2 # 上料2列 + 检验N列 + 包装2列
|
||||
self.process_table.setColumnCount(total_columns)
|
||||
@ -657,9 +601,6 @@ class MainWindowUI(QMainWindow):
|
||||
|
||||
# 重新创建表头
|
||||
self.create_process_table_headers()
|
||||
|
||||
# 重新填充数据
|
||||
self.fill_process_table_cells()
|
||||
|
||||
def create_process_table_headers(self):
|
||||
"""创建微丝产线表格的表头,实现合并单元格"""
|
||||
@ -680,7 +621,7 @@ class MainWindowUI(QMainWindow):
|
||||
|
||||
# 第二行:列标题
|
||||
# 上料区域列标题
|
||||
material_headers = ["序号", "工序工程"]
|
||||
material_headers = ["序号", "工程号"]
|
||||
for col, header in enumerate(material_headers):
|
||||
self.process_table.setItem(1, col, self.create_header_item(header))
|
||||
|
||||
@ -703,7 +644,7 @@ class MainWindowUI(QMainWindow):
|
||||
"""设置微丝产线表格的列宽 - 支持动态配置检验列"""
|
||||
# 上料区域列宽
|
||||
self.process_table.setColumnWidth(0, 70) # 序号
|
||||
self.process_table.setColumnWidth(1, 190) # 工序工程
|
||||
self.process_table.setColumnWidth(1, 190) # 工程号
|
||||
|
||||
# 检验区域列宽
|
||||
for i in range(self.inspection_columns):
|
||||
@ -714,40 +655,41 @@ class MainWindowUI(QMainWindow):
|
||||
self.process_table.setColumnWidth(packaging_start_col, 140) # 贴标
|
||||
self.process_table.setColumnWidth(packaging_start_col + 1, 140) # 称重
|
||||
|
||||
def create_process_table_headers(self):
|
||||
"""创建微丝产线表格的表头,实现合并单元格"""
|
||||
# 第一行:上料、检验、包装标题区域
|
||||
|
||||
# 上料区域(2列)
|
||||
self.process_table.setSpan(0, 0, 1, 2)
|
||||
self.process_table.setItem(0, 0, self.create_header_item("上料"))
|
||||
|
||||
# 检验区域(动态列数)
|
||||
self.process_table.setSpan(0, 2, 1, self.inspection_columns)
|
||||
self.process_table.setItem(0, 2, self.create_header_item("检验"))
|
||||
|
||||
# 包装区域(2列)
|
||||
packaging_start_col = 2 + self.inspection_columns
|
||||
self.process_table.setSpan(0, packaging_start_col, 1, 2)
|
||||
self.process_table.setItem(0, packaging_start_col, self.create_header_item("包装"))
|
||||
|
||||
# 第二行:列标题
|
||||
# 上料区域列标题
|
||||
material_headers = ["序号", "工序工程"]
|
||||
for col, header in enumerate(material_headers):
|
||||
self.process_table.setItem(1, col, self.create_header_item(header))
|
||||
|
||||
# 检验区域列标题 - 可动态配置
|
||||
for i in range(self.inspection_columns):
|
||||
header_text = ""
|
||||
if i < len(self.inspection_headers):
|
||||
header_text = self.inspection_headers[i]
|
||||
else:
|
||||
header_text = f"检验项{i+1}" # 如果没有定义足够的标题,使用默认标题
|
||||
|
||||
self.process_table.setItem(1, 2 + i, self.create_header_item(header_text))
|
||||
|
||||
# 包装区域列标题
|
||||
packaging_headers = ["贴标", "称重"]
|
||||
for i, header in enumerate(packaging_headers):
|
||||
self.process_table.setItem(1, packaging_start_col + i, self.create_header_item(header))
|
||||
# 删除这个重复的方法,下面的是重复定义
|
||||
# def create_process_table_headers(self):
|
||||
# """创建微丝产线表格的表头,实现合并单元格"""
|
||||
# # 第一行:上料、检验、包装标题区域
|
||||
#
|
||||
# # 上料区域(2列)
|
||||
# self.process_table.setSpan(0, 0, 1, 2)
|
||||
# self.process_table.setItem(0, 0, self.create_header_item("上料"))
|
||||
#
|
||||
# # 检验区域(动态列数)
|
||||
# self.process_table.setSpan(0, 2, 1, self.inspection_columns)
|
||||
# self.process_table.setItem(0, 2, self.create_header_item("检验"))
|
||||
#
|
||||
# # 包装区域(2列)
|
||||
# packaging_start_col = 2 + self.inspection_columns
|
||||
# self.process_table.setSpan(0, packaging_start_col, 1, 2)
|
||||
# self.process_table.setItem(0, packaging_start_col, self.create_header_item("包装"))
|
||||
#
|
||||
# # 第二行:列标题
|
||||
# # 上料区域列标题
|
||||
# material_headers = ["序号", "工序工程"]
|
||||
# for col, header in enumerate(material_headers):
|
||||
# self.process_table.setItem(1, col, self.create_header_item(header))
|
||||
#
|
||||
# # 检验区域列标题 - 可动态配置
|
||||
# for i in range(self.inspection_columns):
|
||||
# header_text = ""
|
||||
# if i < len(self.inspection_headers):
|
||||
# header_text = self.inspection_headers[i]
|
||||
# else:
|
||||
# header_text = f"检验项{i+1}" # 如果没有定义足够的标题,使用默认标题
|
||||
#
|
||||
# self.process_table.setItem(1, 2 + i, self.create_header_item(header_text))
|
||||
#
|
||||
# # 包装区域列标题
|
||||
# packaging_headers = ["贴标", "称重"]
|
||||
# for i, header in enumerate(packaging_headers):
|
||||
# self.process_table.setItem(1, packaging_start_col + i, self.create_header_item(header))
|
||||
@ -36,6 +36,7 @@ class SettingsUI(QWidget):
|
||||
# 创建各个选项卡
|
||||
self.create_camera_tab()
|
||||
self.create_database_tab()
|
||||
self.create_inspection_tab()
|
||||
self.create_plc_tab()
|
||||
self.create_push_tab()
|
||||
self.create_auth_tab()
|
||||
@ -293,6 +294,24 @@ class SettingsUI(QWidget):
|
||||
|
||||
self.tab_widget.addTab(self.database_tab, "数据源设置")
|
||||
|
||||
def create_inspection_tab(self):
|
||||
"""创建检验配置选项卡"""
|
||||
# 检验配置选项卡
|
||||
self.inspection_tab = QWidget()
|
||||
self.inspection_layout = QVBoxLayout(self.inspection_tab)
|
||||
self.inspection_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.inspection_layout.setSpacing(0)
|
||||
|
||||
# 添加一个临时提示标签,表示此处将由InspectionSettingsWidget替换
|
||||
self.inspection_placeholder = QLabel("正在加载检验配置...")
|
||||
self.inspection_placeholder.setFont(self.normal_font)
|
||||
self.inspection_placeholder.setAlignment(Qt.AlignCenter)
|
||||
self.inspection_placeholder.setStyleSheet("color: #888888; padding: 20px;")
|
||||
self.inspection_layout.addWidget(self.inspection_placeholder)
|
||||
|
||||
# 添加到选项卡
|
||||
self.tab_widget.addTab(self.inspection_tab, "检验配置")
|
||||
|
||||
def create_plc_tab(self):
|
||||
# PLC设置选项卡
|
||||
self.plc_tab = QWidget()
|
||||
|
||||
@ -1,44 +1,62 @@
|
||||
from sql_utils import SQLUtils
|
||||
from utils.sql_utils import SQLUtils
|
||||
import datetime
|
||||
import os
|
||||
import logging
|
||||
|
||||
def init_database():
|
||||
db = SQLUtils('sqlite', database='db/jtDB.db')
|
||||
|
||||
# 创建用户表
|
||||
create_table_sql = """
|
||||
CREATE TABLE IF NOT EXISTS user (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username VARCHAR(50) NOT NULL UNIQUE,
|
||||
password VARCHAR(100) NOT NULL,
|
||||
create_time TIMESTAMP NOT NULL,
|
||||
create_by VARCHAR(50) NOT NULL,
|
||||
update_time TIMESTAMP,
|
||||
update_by VARCHAR(50),
|
||||
is_deleted BOOLEAN DEFAULT FALSE
|
||||
);
|
||||
"""
|
||||
|
||||
# 获取当前时间
|
||||
current_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# 插入系统用户
|
||||
insert_system_user_sql = """
|
||||
INSERT OR IGNORE INTO user (
|
||||
username, password, create_time, create_by, is_deleted
|
||||
) VALUES (
|
||||
'system', '123456', ?, 'system', FALSE
|
||||
);
|
||||
"""
|
||||
|
||||
try:
|
||||
db.begin_transaction()
|
||||
db.execute_query(create_table_sql)
|
||||
|
||||
# 创建用户表
|
||||
create_user_table_sql = """
|
||||
CREATE TABLE IF NOT EXISTS user (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username VARCHAR(50) NOT NULL UNIQUE,
|
||||
password VARCHAR(100) NOT NULL,
|
||||
create_time TIMESTAMP NOT NULL,
|
||||
create_by VARCHAR(50) NOT NULL,
|
||||
update_time TIMESTAMP,
|
||||
update_by VARCHAR(50),
|
||||
is_deleted BOOLEAN DEFAULT FALSE
|
||||
);
|
||||
"""
|
||||
db.execute_query(create_user_table_sql)
|
||||
|
||||
# 获取当前时间
|
||||
current_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# 插入系统用户
|
||||
insert_system_user_sql = """
|
||||
INSERT OR IGNORE INTO user (
|
||||
username, password, create_time, create_by, is_deleted
|
||||
) VALUES (
|
||||
'system', '123456', ?, 'system', FALSE
|
||||
);
|
||||
"""
|
||||
db.execute_query(insert_system_user_sql, (current_time,))
|
||||
|
||||
# 检查是否存在schema.sql文件,如果存在则执行其中的SQL
|
||||
schema_file = 'db/schema.sql'
|
||||
if os.path.exists(schema_file):
|
||||
with open(schema_file, 'r', encoding='utf-8') as f:
|
||||
schema_sql = f.read()
|
||||
|
||||
# 按语句分割并执行SQL
|
||||
statements = schema_sql.split(';')
|
||||
for statement in statements:
|
||||
statement = statement.strip()
|
||||
if statement: # 跳过空语句
|
||||
db.execute_query(statement)
|
||||
|
||||
logging.info("已执行schema.sql中的数据库初始化脚本")
|
||||
|
||||
db.commit_transaction()
|
||||
print("Database initialized successfully!")
|
||||
logging.info("数据库初始化成功!")
|
||||
except Exception as e:
|
||||
db.rollback_transaction()
|
||||
print(f"Error initializing database: {str(e)}")
|
||||
logging.error(f"数据库初始化失败: {str(e)}")
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
155
utils/inspection_config_manager.py
Normal file
155
utils/inspection_config_manager.py
Normal file
@ -0,0 +1,155 @@
|
||||
import logging
|
||||
from dao.inspection_dao import InspectionDAO
|
||||
|
||||
class InspectionConfigManager:
|
||||
"""检验配置管理器,用于管理检验项目配置"""
|
||||
|
||||
_instance = None
|
||||
|
||||
@classmethod
|
||||
def get_instance(cls):
|
||||
"""获取单例实例"""
|
||||
if cls._instance is None:
|
||||
cls._instance = InspectionConfigManager()
|
||||
return cls._instance
|
||||
|
||||
def __init__(self):
|
||||
"""初始化检验配置管理器"""
|
||||
self.dao = InspectionDAO()
|
||||
self.configs = []
|
||||
self.reload_configs()
|
||||
|
||||
def reload_configs(self):
|
||||
"""重新加载检验配置"""
|
||||
try:
|
||||
self.configs = self.dao.get_all_inspection_configs(include_disabled=True)
|
||||
logging.info(f"已加载{len(self.configs)}个检验项目配置")
|
||||
return True
|
||||
except Exception as e:
|
||||
logging.error(f"加载检验配置失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def get_configs(self, include_disabled=False):
|
||||
"""获取检验配置列表
|
||||
|
||||
Args:
|
||||
include_disabled: 是否包含禁用的项目
|
||||
|
||||
Returns:
|
||||
list: 检验配置列表
|
||||
"""
|
||||
if include_disabled:
|
||||
return self.configs
|
||||
else:
|
||||
return [config for config in self.configs if config['enabled']]
|
||||
|
||||
def get_enabled_configs(self):
|
||||
"""获取已启用的检验配置列表
|
||||
|
||||
Returns:
|
||||
list: 已启用的检验配置列表
|
||||
"""
|
||||
return self.get_configs(include_disabled=False)
|
||||
|
||||
def get_enabled_count(self):
|
||||
"""获取已启用的检验项目数量
|
||||
|
||||
Returns:
|
||||
int: 已启用的检验项目数量
|
||||
"""
|
||||
return len(self.get_enabled_configs())
|
||||
|
||||
def get_config_by_position(self, position):
|
||||
"""根据位置获取检验配置
|
||||
|
||||
Args:
|
||||
position: 位置序号 (1-6)
|
||||
|
||||
Returns:
|
||||
dict: 检验配置,未找到则返回None
|
||||
"""
|
||||
for config in self.configs:
|
||||
if config['position'] == position:
|
||||
return config
|
||||
return None
|
||||
|
||||
def toggle_config(self, position, enabled, username='system'):
|
||||
"""启用或禁用检验配置
|
||||
|
||||
Args:
|
||||
position: 位置序号 (1-6)
|
||||
enabled: 是否启用
|
||||
username: 操作用户
|
||||
|
||||
Returns:
|
||||
bool: 操作是否成功
|
||||
"""
|
||||
result = self.dao.toggle_inspection_config(position, enabled, username)
|
||||
if result:
|
||||
self.reload_configs()
|
||||
return result
|
||||
|
||||
def update_config(self, config_id, data, username='system'):
|
||||
"""更新检验配置
|
||||
|
||||
Args:
|
||||
config_id: 配置ID
|
||||
data: 更新数据
|
||||
username: 操作用户
|
||||
|
||||
Returns:
|
||||
bool: 更新是否成功
|
||||
"""
|
||||
result = self.dao.update_inspection_config(config_id, data, username)
|
||||
if result:
|
||||
self.reload_configs()
|
||||
return result
|
||||
|
||||
def get_inspection_headers(self):
|
||||
"""获取检验表头,用于UI显示
|
||||
|
||||
Returns:
|
||||
list: 检验表头列表
|
||||
"""
|
||||
enabled_configs = self.get_enabled_configs()
|
||||
headers = []
|
||||
|
||||
# 按位置排序
|
||||
enabled_configs.sort(key=lambda x: x['position'])
|
||||
|
||||
for config in enabled_configs:
|
||||
headers.append(config['display_name'])
|
||||
|
||||
return headers
|
||||
|
||||
def get_inspection_column_count(self):
|
||||
"""获取检验列数量
|
||||
|
||||
Returns:
|
||||
int: 检验列数量
|
||||
"""
|
||||
return len(self.get_enabled_configs())
|
||||
|
||||
def save_inspection_data(self, order_id, data, username='system'):
|
||||
"""保存检验数据
|
||||
|
||||
Args:
|
||||
order_id: 工程号
|
||||
data: 检验数据列表
|
||||
username: 操作用户
|
||||
|
||||
Returns:
|
||||
bool: 保存是否成功
|
||||
"""
|
||||
return self.dao.save_inspection_data(order_id, data, username)
|
||||
|
||||
def get_inspection_data(self, order_id):
|
||||
"""获取检验数据
|
||||
|
||||
Args:
|
||||
order_id: 工程号
|
||||
|
||||
Returns:
|
||||
list: 检验数据列表
|
||||
"""
|
||||
return self.dao.get_inspection_data_by_order(order_id)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
384
widgets/inspection_settings_widget.py
Normal file
384
widgets/inspection_settings_widget.py
Normal file
@ -0,0 +1,384 @@
|
||||
import logging
|
||||
import json
|
||||
from PySide6.QtWidgets import QMessageBox, QLabel
|
||||
from PySide6.QtCore import QObject, Signal
|
||||
from PySide6.QtCore import Qt
|
||||
|
||||
from ui.inspection_settings_ui import InspectionSettingsUI
|
||||
from utils.inspection_config_manager import InspectionConfigManager
|
||||
from dao.inspection_dao import InspectionDAO
|
||||
|
||||
class InspectionSettingsWidget(InspectionSettingsUI):
|
||||
"""检验设置部件"""
|
||||
|
||||
# 定义信号
|
||||
signal_configs_changed = Signal() # 配置变更信号
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.parent = parent
|
||||
|
||||
# 添加一个明显的标签,方便测试
|
||||
self.test_label = QLabel("检验配置已加载", self)
|
||||
self.test_label.setStyleSheet("color: green; font-size: 16px; font-weight: bold; background-color: #e0f7e0; padding: 5px; border-radius: 5px;")
|
||||
self.test_label.setAlignment(Qt.AlignCenter)
|
||||
self.main_layout.insertWidget(0, self.test_label)
|
||||
|
||||
# 初始化检验配置管理器
|
||||
self.inspection_manager = InspectionConfigManager.get_instance()
|
||||
|
||||
# 保存配置ID
|
||||
self.config_ids = [None] * 6
|
||||
|
||||
# 连接信号和槽
|
||||
self.connect_signals()
|
||||
|
||||
# 加载配置
|
||||
self.load_configs()
|
||||
|
||||
def connect_signals(self):
|
||||
"""连接信号和槽"""
|
||||
# 保存按钮
|
||||
self.save_button.clicked.connect(self.save_configs)
|
||||
|
||||
# 重置按钮
|
||||
self.reset_button.clicked.connect(self.load_configs)
|
||||
|
||||
# 数据类型下拉框
|
||||
for i in range(6):
|
||||
position = i + 1
|
||||
combo = self.findChild(QObject, f"data_type_combo_{position}")
|
||||
if combo:
|
||||
combo.currentIndexChanged.connect(lambda idx, pos=position: self.update_form_by_data_type(pos))
|
||||
|
||||
def load_configs(self):
|
||||
"""加载检验配置"""
|
||||
try:
|
||||
# 设置表单禁用,避免加载过程中的错误操作
|
||||
self.set_form_enabled(False)
|
||||
|
||||
# 重新加载配置
|
||||
self.inspection_manager.reload_configs()
|
||||
|
||||
# 获取所有配置(包括禁用的)
|
||||
configs = self.inspection_manager.get_configs(include_disabled=True)
|
||||
|
||||
# 添加详细日志用于调试
|
||||
logging.info(f"加载检验配置成功,共 {len(configs)} 项: {[c.get('name', 'unknown') for c in configs]}")
|
||||
self.test_label.setText(f"检验配置已加载({len(configs)}项)")
|
||||
|
||||
# 清空当前配置ID
|
||||
self.config_ids = [None] * 6
|
||||
|
||||
# 按位置加载配置
|
||||
for config in configs:
|
||||
position = config.get('position')
|
||||
if 1 <= position <= 6:
|
||||
self.config_ids[position - 1] = config.get('id')
|
||||
self.load_config_to_form(position, config)
|
||||
|
||||
# 恢复表单可用
|
||||
self.set_form_enabled(True)
|
||||
|
||||
logging.info("已加载检验配置")
|
||||
except Exception as e:
|
||||
logging.error(f"加载检验配置失败: {str(e)}")
|
||||
self.test_label.setText(f"加载检验配置失败: {str(e)}")
|
||||
self.test_label.setStyleSheet("color: red; font-size: 16px; font-weight: bold; background-color: #ffe0e0; padding: 5px; border-radius: 5px;")
|
||||
QMessageBox.critical(self, "错误", f"加载检验配置失败: {str(e)}")
|
||||
# 恢复表单可用
|
||||
self.set_form_enabled(True)
|
||||
|
||||
def load_config_to_form(self, position, config):
|
||||
"""将配置加载到表单
|
||||
|
||||
Args:
|
||||
position: 位置序号 (1-6)
|
||||
config: 配置数据
|
||||
"""
|
||||
# 获取分组
|
||||
group = self.config_groups[position - 1]
|
||||
|
||||
# 设置启用状态
|
||||
group.setChecked(config.get('enabled', False))
|
||||
|
||||
# 设置表单值
|
||||
# 名称
|
||||
name_input = self.findChild(QObject, f"name_input_{position}")
|
||||
if name_input:
|
||||
name_input.setText(config.get('name', ''))
|
||||
|
||||
# 显示名称
|
||||
display_name_input = self.findChild(QObject, f"display_name_input_{position}")
|
||||
if display_name_input:
|
||||
display_name_input.setText(config.get('display_name', ''))
|
||||
|
||||
# 数据类型
|
||||
data_type_combo = self.findChild(QObject, f"data_type_combo_{position}")
|
||||
if data_type_combo:
|
||||
data_type = config.get('data_type', 'text')
|
||||
index = data_type_combo.findData(data_type)
|
||||
if index >= 0:
|
||||
data_type_combo.setCurrentIndex(index)
|
||||
|
||||
# 单位
|
||||
unit_input = self.findChild(QObject, f"unit_input_{position}")
|
||||
if unit_input:
|
||||
unit_input.setText(config.get('unit', ''))
|
||||
|
||||
# 最小值
|
||||
min_value_spin = self.findChild(QObject, f"min_value_spin_{position}")
|
||||
if min_value_spin:
|
||||
min_value = config.get('min_value')
|
||||
if min_value is not None:
|
||||
min_value_spin.setValue(float(min_value))
|
||||
else:
|
||||
min_value_spin.setValue(0)
|
||||
|
||||
# 最大值
|
||||
max_value_spin = self.findChild(QObject, f"max_value_spin_{position}")
|
||||
if max_value_spin:
|
||||
max_value = config.get('max_value')
|
||||
if max_value is not None:
|
||||
max_value_spin.setValue(float(max_value))
|
||||
else:
|
||||
max_value_spin.setValue(100)
|
||||
|
||||
# 枚举值
|
||||
enum_values_input = self.findChild(QObject, f"enum_values_input_{position}")
|
||||
if enum_values_input:
|
||||
enum_values = config.get('enum_values')
|
||||
if enum_values:
|
||||
if isinstance(enum_values, list):
|
||||
enum_values_input.setText(','.join(enum_values))
|
||||
elif isinstance(enum_values, str):
|
||||
try:
|
||||
values = json.loads(enum_values)
|
||||
if isinstance(values, list):
|
||||
enum_values_input.setText(','.join(values))
|
||||
else:
|
||||
enum_values_input.setText(str(enum_values))
|
||||
except:
|
||||
enum_values_input.setText(str(enum_values))
|
||||
else:
|
||||
enum_values_input.setText('')
|
||||
|
||||
# 是否必填
|
||||
required_check = self.findChild(QObject, f"required_check_{position}")
|
||||
if required_check:
|
||||
required_check.setChecked(config.get('required', False))
|
||||
|
||||
# 根据数据类型更新表单
|
||||
self.update_form_by_data_type(position)
|
||||
|
||||
def update_form_by_data_type(self, position):
|
||||
"""根据数据类型更新表单项的可用性
|
||||
|
||||
Args:
|
||||
position: 位置序号 (1-6)
|
||||
"""
|
||||
# 获取数据类型
|
||||
data_type_combo = self.findChild(QObject, f"data_type_combo_{position}")
|
||||
if not data_type_combo:
|
||||
return
|
||||
|
||||
data_type = data_type_combo.currentData()
|
||||
|
||||
# 获取相关控件
|
||||
unit_input = self.findChild(QObject, f"unit_input_{position}")
|
||||
min_value_spin = self.findChild(QObject, f"min_value_spin_{position}")
|
||||
max_value_spin = self.findChild(QObject, f"max_value_spin_{position}")
|
||||
enum_values_input = self.findChild(QObject, f"enum_values_input_{position}")
|
||||
|
||||
# 根据数据类型设置控件可用性
|
||||
if data_type == 'number':
|
||||
# 数值类型:启用单位、最小值、最大值,禁用枚举值
|
||||
if unit_input:
|
||||
unit_input.setEnabled(True)
|
||||
if min_value_spin:
|
||||
min_value_spin.setEnabled(True)
|
||||
if max_value_spin:
|
||||
max_value_spin.setEnabled(True)
|
||||
if enum_values_input:
|
||||
enum_values_input.setEnabled(False)
|
||||
enum_values_input.setText('')
|
||||
elif data_type == 'enum':
|
||||
# 枚举类型:禁用单位、最小值、最大值,启用枚举值
|
||||
if unit_input:
|
||||
unit_input.setEnabled(False)
|
||||
unit_input.setText('')
|
||||
if min_value_spin:
|
||||
min_value_spin.setEnabled(False)
|
||||
min_value_spin.setValue(0)
|
||||
if max_value_spin:
|
||||
max_value_spin.setEnabled(False)
|
||||
max_value_spin.setValue(0)
|
||||
if enum_values_input:
|
||||
enum_values_input.setEnabled(True)
|
||||
else: # text 或其他
|
||||
# 文本类型:禁用所有特殊字段
|
||||
if unit_input:
|
||||
unit_input.setEnabled(False)
|
||||
unit_input.setText('')
|
||||
if min_value_spin:
|
||||
min_value_spin.setEnabled(False)
|
||||
min_value_spin.setValue(0)
|
||||
if max_value_spin:
|
||||
max_value_spin.setEnabled(False)
|
||||
max_value_spin.setValue(0)
|
||||
if enum_values_input:
|
||||
enum_values_input.setEnabled(False)
|
||||
enum_values_input.setText('')
|
||||
|
||||
def get_form_data(self, position):
|
||||
"""获取表单数据
|
||||
|
||||
Args:
|
||||
position: 位置序号 (1-6)
|
||||
|
||||
Returns:
|
||||
dict: 表单数据
|
||||
"""
|
||||
# 获取分组
|
||||
group = self.config_groups[position - 1]
|
||||
|
||||
# 获取控件
|
||||
name_input = self.findChild(QObject, f"name_input_{position}")
|
||||
display_name_input = self.findChild(QObject, f"display_name_input_{position}")
|
||||
data_type_combo = self.findChild(QObject, f"data_type_combo_{position}")
|
||||
unit_input = self.findChild(QObject, f"unit_input_{position}")
|
||||
min_value_spin = self.findChild(QObject, f"min_value_spin_{position}")
|
||||
max_value_spin = self.findChild(QObject, f"max_value_spin_{position}")
|
||||
enum_values_input = self.findChild(QObject, f"enum_values_input_{position}")
|
||||
required_check = self.findChild(QObject, f"required_check_{position}")
|
||||
|
||||
# 获取数据
|
||||
enabled = group.isChecked()
|
||||
name = name_input.text() if name_input else ''
|
||||
display_name = display_name_input.text() if display_name_input else ''
|
||||
data_type = data_type_combo.currentData() if data_type_combo else 'text'
|
||||
unit = unit_input.text() if unit_input and data_type == 'number' else ''
|
||||
min_value = min_value_spin.value() if min_value_spin and data_type == 'number' else None
|
||||
max_value = max_value_spin.value() if max_value_spin and data_type == 'number' else None
|
||||
|
||||
# 处理枚举值
|
||||
enum_values = None
|
||||
if enum_values_input and data_type == 'enum':
|
||||
enum_text = enum_values_input.text().strip()
|
||||
if enum_text:
|
||||
enum_values = [v.strip() for v in enum_text.split(',') if v.strip()]
|
||||
|
||||
required = required_check.isChecked() if required_check else False
|
||||
|
||||
# 构建数据
|
||||
data = {
|
||||
'position': position,
|
||||
'name': name,
|
||||
'display_name': display_name,
|
||||
'enabled': enabled,
|
||||
'data_type': data_type,
|
||||
'required': required,
|
||||
'sort_order': position
|
||||
}
|
||||
|
||||
# 根据数据类型添加特定字段
|
||||
if data_type == 'number':
|
||||
data['min_value'] = min_value
|
||||
data['max_value'] = max_value
|
||||
data['unit'] = unit
|
||||
elif data_type == 'enum':
|
||||
data['enum_values'] = enum_values
|
||||
|
||||
return data
|
||||
|
||||
def validate_form(self):
|
||||
"""验证表单数据
|
||||
|
||||
Returns:
|
||||
bool: 验证是否通过
|
||||
"""
|
||||
# 检查是否至少启用一个检验项
|
||||
enabled_count = 0
|
||||
for group in self.config_groups:
|
||||
if group.isChecked():
|
||||
enabled_count += 1
|
||||
|
||||
if enabled_count == 0:
|
||||
QMessageBox.warning(self, "验证失败", "请至少启用一个检验项目!")
|
||||
return False
|
||||
|
||||
# 检查每个启用的检验项是否填写了必要信息
|
||||
for i in range(6):
|
||||
position = i + 1
|
||||
group = self.config_groups[i]
|
||||
|
||||
if group.isChecked():
|
||||
# 获取控件
|
||||
name_input = self.findChild(QObject, f"name_input_{position}")
|
||||
display_name_input = self.findChild(QObject, f"display_name_input_{position}")
|
||||
data_type_combo = self.findChild(QObject, f"data_type_combo_{position}")
|
||||
enum_values_input = self.findChild(QObject, f"enum_values_input_{position}")
|
||||
|
||||
# 验证名称和显示名称
|
||||
if not name_input.text().strip():
|
||||
QMessageBox.warning(self, "验证失败", f"检验项目 {position} 的项目名称不能为空!")
|
||||
return False
|
||||
|
||||
if not display_name_input.text().strip():
|
||||
QMessageBox.warning(self, "验证失败", f"检验项目 {position} 的显示名称不能为空!")
|
||||
return False
|
||||
|
||||
# 验证枚举类型的枚举值
|
||||
data_type = data_type_combo.currentData()
|
||||
if data_type == 'enum' and not enum_values_input.text().strip():
|
||||
QMessageBox.warning(self, "验证失败", f"检验项目 {position} 是枚举类型,枚举值不能为空!")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def save_configs(self):
|
||||
"""保存检验配置"""
|
||||
try:
|
||||
# 验证表单
|
||||
if not self.validate_form():
|
||||
return
|
||||
|
||||
# 设置表单禁用,避免保存过程中的错误操作
|
||||
self.set_form_enabled(False)
|
||||
|
||||
# 收集更新数据
|
||||
for i in range(6):
|
||||
position = i + 1
|
||||
config_id = self.config_ids[i]
|
||||
|
||||
# 获取表单数据
|
||||
data = self.get_form_data(position)
|
||||
|
||||
# 检查配置ID是否存在
|
||||
if config_id is not None:
|
||||
# 更新已有配置
|
||||
result = self.inspection_manager.update_config(config_id, data)
|
||||
if not result:
|
||||
raise Exception(f"更新检验项目 {position} 失败")
|
||||
else:
|
||||
# 新建配置(不应该进入这个分支,因为默认已经创建了6个配置)
|
||||
logging.warning(f"检验项目 {position} 不存在,需要在初始化时创建")
|
||||
|
||||
# 重新加载配置
|
||||
self.inspection_manager.reload_configs()
|
||||
|
||||
# 恢复表单可用
|
||||
self.set_form_enabled(True)
|
||||
|
||||
# 显示成功消息
|
||||
QMessageBox.information(self, "保存成功", "检验配置已保存成功!")
|
||||
|
||||
# 发送配置变更信号
|
||||
self.signal_configs_changed.emit()
|
||||
|
||||
logging.info("已保存检验配置")
|
||||
except Exception as e:
|
||||
logging.error(f"保存检验配置失败: {str(e)}")
|
||||
QMessageBox.critical(self, "错误", f"保存检验配置失败: {str(e)}")
|
||||
# 恢复表单可用
|
||||
self.set_form_enabled(True)
|
||||
@ -16,6 +16,9 @@ from ui.main_window_ui import MainWindowUI
|
||||
from widgets.camera_display_widget import CameraDisplayWidget
|
||||
from widgets.camera_settings_widget import CameraSettingsWidget
|
||||
|
||||
# 导入检验配置管理器
|
||||
from utils.inspection_config_manager import InspectionConfigManager
|
||||
|
||||
|
||||
class MainWindow(MainWindowUI):
|
||||
"""主窗口"""
|
||||
@ -36,6 +39,9 @@ class MainWindow(MainWindowUI):
|
||||
self.config = self.load_config()
|
||||
self.camera_enabled = self.config.get('camera', {}).get('enabled', False)
|
||||
|
||||
# 初始化检验配置管理器
|
||||
self.inspection_manager = InspectionConfigManager.get_instance()
|
||||
|
||||
# 只有在相机启用时创建相机显示组件
|
||||
if self.camera_enabled:
|
||||
# 创建相机显示组件并添加到上料区
|
||||
@ -74,8 +80,8 @@ class MainWindow(MainWindowUI):
|
||||
# 初始化数据
|
||||
self.initialize_data()
|
||||
|
||||
# 配置检验列为5列
|
||||
self.set_inspection_columns(5)
|
||||
# 配置检验列 - 使用检验配置管理器获取启用的列数和标题
|
||||
self.update_inspection_columns()
|
||||
|
||||
logging.info(f"主窗口已创建,用户: {user_name}")
|
||||
|
||||
@ -96,6 +102,9 @@ class MainWindow(MainWindowUI):
|
||||
self.main_action.triggered.connect(self.show_main_page)
|
||||
self.settings_action.triggered.connect(self.show_settings_page)
|
||||
|
||||
# 工程号输入框回车事件
|
||||
self.order_edit.returnPressed.connect(self.handle_order_enter)
|
||||
|
||||
# 连接按钮事件
|
||||
self.input_button.clicked.connect(self.handle_input)
|
||||
self.output_button.clicked.connect(self.handle_output)
|
||||
@ -134,9 +143,36 @@ class MainWindow(MainWindowUI):
|
||||
item.setTextAlignment(Qt.AlignCenter) # 设置文本居中对齐
|
||||
self.task_table.setItem(2, col, item)
|
||||
|
||||
def update_inspection_columns(self):
|
||||
"""更新检验列配置 - 使用检验配置管理器获取启用的列数和标题"""
|
||||
try:
|
||||
# 获取已启用的检验配置
|
||||
enabled_configs = self.inspection_manager.get_enabled_configs()
|
||||
|
||||
# 获取启用的列数
|
||||
column_count = len(enabled_configs)
|
||||
if column_count == 0:
|
||||
# 如果没有启用的列,至少显示一列
|
||||
column_count = 1
|
||||
headers = ["检验项"]
|
||||
else:
|
||||
# 如果有启用的列,使用配置的标题
|
||||
headers = [config['display_name'] for config in enabled_configs]
|
||||
|
||||
# 设置检验列
|
||||
self.set_inspection_columns(column_count, headers)
|
||||
logging.info(f"已更新检验列配置:{column_count}列, 标题: {headers}")
|
||||
except Exception as e:
|
||||
logging.error(f"更新检验列配置失败: {str(e)}")
|
||||
# 如果更新失败,使用默认配置
|
||||
self.set_inspection_columns(1, ["检验项"])
|
||||
|
||||
def show_main_page(self):
|
||||
self.stacked_widget.setCurrentWidget(self.central_widget)
|
||||
|
||||
# 更新检验列配置
|
||||
self.update_inspection_columns()
|
||||
|
||||
# 只有在相机启用时处理相机显示
|
||||
if self.camera_enabled and hasattr(self, 'camera_display'):
|
||||
# 如果相机已连接,直接开始显示相机画面
|
||||
@ -147,24 +183,15 @@ class MainWindow(MainWindowUI):
|
||||
logging.info("显示主页面")
|
||||
|
||||
def show_settings_page(self):
|
||||
# 只有在相机启用时才创建相机设置组件
|
||||
if self.camera_enabled:
|
||||
# 延迟创建相机设置组件
|
||||
if self.camera_settings is None:
|
||||
self.camera_settings = CameraSettingsWidget()
|
||||
# 连接相机设置信号
|
||||
self.camera_settings.signal_camera_connection.connect(self.handle_camera_connection)
|
||||
self.camera_settings.signal_camera_params_changed.connect(self.handle_camera_params_changed)
|
||||
self.camera_settings.signal_camera_error.connect(self.handle_camera_error)
|
||||
# 添加到堆叠部件
|
||||
self.stacked_widget.addWidget(self.camera_settings)
|
||||
|
||||
# 切换到设置页面
|
||||
self.stacked_widget.setCurrentWidget(self.camera_settings)
|
||||
else:
|
||||
# 如果相机未启用,显示提示信息
|
||||
QMessageBox.information(self, "设置", "相机功能已在配置文件中禁用,无法打开相机设置页面。")
|
||||
"""显示设置页面"""
|
||||
# 延迟创建设置组件
|
||||
if not hasattr(self, 'settings_widget'):
|
||||
from widgets.settings_widget import SettingsWidget
|
||||
self.settings_widget = SettingsWidget(self)
|
||||
self.stacked_widget.addWidget(self.settings_widget)
|
||||
|
||||
# 切换到设置页面
|
||||
self.stacked_widget.setCurrentWidget(self.settings_widget)
|
||||
logging.info("显示设置页面")
|
||||
|
||||
def handle_input(self):
|
||||
@ -245,4 +272,21 @@ class MainWindow(MainWindowUI):
|
||||
self.camera_display.stop_display()
|
||||
|
||||
# 接受关闭事件
|
||||
event.accept()
|
||||
event.accept()
|
||||
|
||||
def handle_order_enter(self):
|
||||
"""处理工程号输入框按下回车事件"""
|
||||
logging.info("工程号输入框按下回车事件")
|
||||
# 获取当前输入的工程号
|
||||
order_text = self.order_edit.text().strip()
|
||||
|
||||
if order_text:
|
||||
logging.info(f"输入的工程号: {order_text}")
|
||||
QMessageBox.information(self, "工程号确认", f"您输入的工程号是: {order_text}")
|
||||
# 这里可以添加其他工程号处理逻辑
|
||||
else:
|
||||
logging.warning("工程号为空")
|
||||
QMessageBox.warning(self, "输入提示", "请输入有效的工程号")
|
||||
|
||||
# 处理完后可以清除焦点,让输入框失去焦点
|
||||
self.central_widget.setFocus()
|
||||
@ -1,19 +1,44 @@
|
||||
from PySide6.QtWidgets import QMessageBox
|
||||
from PySide6.QtWidgets import QMessageBox, QVBoxLayout
|
||||
import logging
|
||||
from ui.settings_ui import SettingsUI
|
||||
from utils.sql_utils import SQLUtils
|
||||
from widgets.inspection_settings_widget import InspectionSettingsWidget
|
||||
|
||||
class SettingsWidget(SettingsUI):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.parent = parent
|
||||
|
||||
logging.info("正在初始化SettingsWidget")
|
||||
|
||||
# 创建检验设置部件
|
||||
logging.info("创建InspectionSettingsWidget实例")
|
||||
self.inspection_settings = InspectionSettingsWidget()
|
||||
|
||||
# 移除临时占位符标签并添加检验设置部件
|
||||
if hasattr(self, 'inspection_placeholder'):
|
||||
logging.info("移除临时占位符")
|
||||
self.inspection_layout.removeWidget(self.inspection_placeholder)
|
||||
self.inspection_placeholder.hide()
|
||||
self.inspection_placeholder.deleteLater()
|
||||
else:
|
||||
logging.warning("未找到临时占位符标签")
|
||||
|
||||
# 检查布局是否可用
|
||||
if hasattr(self, 'inspection_layout'):
|
||||
logging.info("添加检验设置部件到布局")
|
||||
self.inspection_layout.addWidget(self.inspection_settings)
|
||||
else:
|
||||
logging.error("无法找到inspection_layout布局")
|
||||
|
||||
# 连接信号和槽
|
||||
self.connect_signals()
|
||||
|
||||
# 初始化数据库类型UI状态
|
||||
self.update_db_ui_state()
|
||||
|
||||
logging.info("SettingsWidget初始化完成")
|
||||
|
||||
def connect_signals(self):
|
||||
# 数据库类型选择
|
||||
self.sqlite_radio.toggled.connect(self.update_db_ui_state)
|
||||
@ -23,6 +48,9 @@ class SettingsWidget(SettingsUI):
|
||||
# 按钮动作
|
||||
self.test_conn_button.clicked.connect(self.test_connection)
|
||||
self.save_db_button.clicked.connect(self.save_db_settings)
|
||||
|
||||
# 检验配置变更信号
|
||||
self.inspection_settings.signal_configs_changed.connect(self.handle_inspection_configs_changed)
|
||||
|
||||
def update_db_ui_state(self):
|
||||
"""根据选择的数据库类型更新UI状态"""
|
||||
@ -98,25 +126,18 @@ class SettingsWidget(SettingsUI):
|
||||
# 创建数据库连接
|
||||
db = SQLUtils(db_type, **params)
|
||||
|
||||
# 尝试执行简单查询
|
||||
if db_type == "sqlite":
|
||||
db.execute_query("SELECT sqlite_version();")
|
||||
elif db_type == "pgsql":
|
||||
db.execute_query("SELECT version();")
|
||||
elif db_type == "mysql":
|
||||
db.execute_query("SELECT version();")
|
||||
# 测试连接
|
||||
db.cursor.execute("SELECT 1")
|
||||
|
||||
result = db.fetchone()
|
||||
# 关闭连接
|
||||
db.close()
|
||||
|
||||
# 显示成功消息
|
||||
QMessageBox.information(self, "连接成功", f"数据库连接测试成功!\n数据库版本: {result[0]}")
|
||||
|
||||
logging.info(f"数据库连接测试成功,类型: {db_type}, 版本: {result[0]}")
|
||||
|
||||
QMessageBox.information(self, "连接成功", "数据库连接测试成功!")
|
||||
logging.info(f"数据库连接测试成功,类型: {db_type}")
|
||||
except Exception as e:
|
||||
# 显示错误消息
|
||||
QMessageBox.critical(self, "连接失败", f"数据库连接测试失败!\n错误: {str(e)}")
|
||||
QMessageBox.critical(self, "连接失败", f"数据库连接测试失败!\n\n错误: {str(e)}")
|
||||
logging.error(f"数据库连接测试失败,类型: {db_type}, 错误: {str(e)}")
|
||||
|
||||
def save_db_settings(self):
|
||||
@ -137,4 +158,11 @@ class SettingsWidget(SettingsUI):
|
||||
settings_info += f"说明: {desc}"
|
||||
|
||||
QMessageBox.information(self, "设置已保存", f"数据库设置已保存!\n\n{settings_info}")
|
||||
logging.info(f"数据库设置已保存,类型: {db_type}")
|
||||
logging.info(f"数据库设置已保存,类型: {db_type}")
|
||||
|
||||
def handle_inspection_configs_changed(self):
|
||||
"""处理检验配置变更"""
|
||||
logging.info("检验配置已更新")
|
||||
# 如果有父窗口,通知父窗口更新检验配置
|
||||
if self.parent and hasattr(self.parent, 'update_inspection_columns'):
|
||||
self.parent.update_inspection_columns()
|
||||
Loading…
Reference in New Issue
Block a user