Files
cangku/garment_dialogs.py

898 lines
38 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
服装管理模块 - 处理服装款式和材料用量管理
"""
import os
from datetime import datetime
from PIL import Image
from PyQt5.QtWidgets import (
QDialog, QVBoxLayout, QHBoxLayout, QGridLayout, QLabel, QLineEdit,
QPushButton, QComboBox, QTableWidget, QTableWidgetItem, QHeaderView,
QMessageBox, QFileDialog, QDoubleSpinBox, QWidget, QCompleter
)
from PyQt5.QtCore import Qt, QStringListModel, QTimer
from PyQt5.QtGui import QPixmap
from database import get_db_connection
class SearchableComboBox(QComboBox):
"""支持模糊搜索的下拉框"""
def __init__(self, parent=None):
super().__init__(parent)
self.setEditable(True)
self.setInsertPolicy(QComboBox.NoInsert)
# 存储所有选项
self.all_items = []
self.all_data = []
self.is_filtering = False
# 设置自动完成
self.completer = QCompleter(self)
self.completer.setCompletionMode(QCompleter.PopupCompletion)
self.completer.setCaseSensitivity(Qt.CaseInsensitive)
self.completer.setFilterMode(Qt.MatchContains)
self.setCompleter(self.completer)
# 连接信号
self.lineEdit().textChanged.connect(self.on_text_changed)
def addItem(self, text, userData=None):
"""添加选项"""
# 临时断开信号连接防止textChanged触发on_text_changed
try:
self.lineEdit().textChanged.disconnect()
except TypeError:
# 信号未连接或已被断开,忽略错误
pass
super().addItem(text, userData)
if text not in self.all_items:
self.all_items.append(text)
self.all_data.append(userData)
self.update_completer()
# 重新连接信号
try:
self.lineEdit().textChanged.connect(self.on_text_changed)
except:
# 如果连接失败,忽略错误
pass
def addItems(self, texts):
"""批量添加选项"""
for text in texts:
self.addItem(text)
def clear(self):
"""清空所有选项"""
if not self.is_filtering:
super().clear()
self.all_items.clear()
self.all_data.clear()
self.update_completer()
def reset_items(self):
"""重置所有选项"""
# 临时断开信号连接防止textChanged触发on_text_changed
try:
self.lineEdit().textChanged.disconnect()
except TypeError:
# 信号未连接或已被断开,忽略错误
pass
self.is_filtering = True
super().clear()
for i, item in enumerate(self.all_items):
super().addItem(item, self.all_data[i] if i < len(self.all_data) else None)
self.is_filtering = False
# 重新连接信号
try:
self.lineEdit().textChanged.connect(self.on_text_changed)
except:
# 如果连接失败,忽略错误
pass
# # 确保当前索引设置为0第一项
# if self.count() > 0:
# super().setCurrentIndex(0)
def update_completer(self):
"""更新自动完成列表"""
model = QStringListModel(self.all_items)
self.completer.setModel(model)
def on_text_changed(self, text):
"""文本改变时的处理"""
if self.is_filtering:
return
if not text or text in ["—— 选择型号 ——"]:
self.reset_items()
# 如果获得焦点且有选项,显示下拉列表
if self.hasFocus() and self.count() > 0:
self.showPopup()
return
# 模糊搜索匹配
filtered_items = []
filtered_data = []
for i, item in enumerate(self.all_items):
if text.lower() in item.lower():
filtered_items.append(item)
filtered_data.append(self.all_data[i] if i < len(self.all_data) else None)
# 更新下拉列表
self.is_filtering = True
super().clear()
for i, item in enumerate(filtered_items):
super().addItem(item, filtered_data[i])
self.is_filtering = False
# 如果有匹配项且获得焦点,显示下拉列表
if filtered_items and self.hasFocus():
self.showPopup()
def setDefaultText(self, text):
"""设置默认文本"""
# 临时断开信号连接防止textChanged触发on_text_changed
try:
self.lineEdit().textChanged.disconnect()
except TypeError:
# 信号未连接或已被断开,忽略错误
pass
self.lineEdit().setText(text)
self.update_completer()
# 重新连接信号
try:
self.lineEdit().textChanged.connect(self.on_text_changed)
except:
# 如果连接失败,忽略错误
pass
class GarmentLibraryDialog(QDialog):
"""服装库管理对话框"""
def __init__(self, db_path):
super().__init__()
self.db_path = db_path
self.setWindowTitle("衣服款号管理")
self.resize(1300, 750)
self.setup_ui()
self.load_garments()
def setup_ui(self):
"""设置用户界面"""
layout = QVBoxLayout(self)
# 操作按钮区域
op_layout = QHBoxLayout()
op_layout.addWidget(QLabel("搜索款号:"))
self.search_input = QLineEdit()
self.search_input.textChanged.connect(self.load_garments)
op_layout.addWidget(self.search_input)
add_btn = QPushButton("新增/编辑款号")
add_btn.clicked.connect(self.edit_garment)
op_layout.addWidget(add_btn)
del_btn = QPushButton("删除选中款号")
del_btn.clicked.connect(self.delete_garment)
op_layout.addWidget(del_btn)
refresh_btn = QPushButton("刷新")
refresh_btn.clicked.connect(self.load_garments)
op_layout.addWidget(refresh_btn)
layout.addLayout(op_layout)
# 服装表格
self.garment_table = QTableWidget()
self.garment_table.setColumnCount(3)
self.garment_table.setHorizontalHeaderLabels(["款号", "类目数量", "款式图预览"])
self.garment_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.garment_table.itemDoubleClicked.connect(self.edit_garment_from_table)
layout.addWidget(self.garment_table)
def get_conn(self):
"""获取数据库连接"""
return get_db_connection(self.db_path)
def load_garments(self):
"""加载服装列表"""
keyword = self.search_input.text().strip()
try:
with self.get_conn() as conn:
query = "SELECT style_number, image_path FROM garments"
params = []
if keyword:
query += " WHERE style_number LIKE ?"
params = ["%" + keyword + "%"]
query += " ORDER BY style_number"
cursor = conn.execute(query, params)
rows = cursor.fetchall()
self.garment_table.setRowCount(len(rows))
for i in range(len(rows)):
self.garment_table.setRowHeight(i, 140)
for row_idx, (style_number, image_path) in enumerate(rows):
self.garment_table.setItem(row_idx, 0, QTableWidgetItem(style_number))
# 查询材料数量
with self.get_conn() as conn:
cursor2 = conn.execute("SELECT COUNT(*) FROM garment_materials WHERE style_number = ?", (style_number,))
count = cursor2.fetchone()[0]
self.garment_table.setItem(row_idx, 1, QTableWidgetItem(str(count)))
# 显示图片预览
image_item = QTableWidgetItem()
image_item.setTextAlignment(Qt.AlignCenter)
if image_path and os.path.exists(image_path):
try:
pixmap = QPixmap(image_path).scaled(130, 130, Qt.KeepAspectRatio, Qt.SmoothTransformation)
image_item.setData(Qt.DecorationRole, pixmap)
except:
image_item.setText("加载失败")
else:
image_item.setText("无图片")
self.garment_table.setItem(row_idx, 2, image_item)
except Exception as e:
QMessageBox.critical(self, "加载失败", "错误: " + str(e))
def edit_garment_from_table(self):
"""从表格编辑服装"""
row = self.garment_table.currentRow()
if row >= 0:
style_number = self.garment_table.item(row, 0).text()
self.edit_garment(style_number)
def edit_garment(self, style_number=None):
"""编辑服装"""
dialog = GarmentEditDialog(self.db_path, style_number)
if dialog.exec_():
self.load_garments()
def delete_garment(self):
"""删除服装"""
row = self.garment_table.currentRow()
if row < 0:
QMessageBox.warning(self, "提示", "请先选中一款号")
return
style_number = self.garment_table.item(row, 0).text()
reply = QMessageBox.question(self, "确认", f"删除款号 '{style_number}' 及其所有信息?")
if reply == QMessageBox.Yes:
try:
with self.get_conn() as conn:
conn.execute("DELETE FROM garment_materials WHERE style_number = ?", (style_number,))
conn.execute("DELETE FROM garments WHERE style_number = ?", (style_number,))
conn.commit()
self.load_garments()
QMessageBox.information(self, "成功", "删除完成")
except Exception as e:
QMessageBox.critical(self, "错误", "删除失败: " + str(e))
class GarmentEditDialog(QDialog):
"""服装编辑对话框"""
def __init__(self, db_path, style_number=None):
super().__init__()
self.db_path = db_path
self.style_number = style_number
self.current_image_path = None
self.setWindowTitle("编辑款号" if style_number else "新增款号")
self.resize(1300, 850)
self.setup_ui()
if style_number:
self.load_garment_data()
def setup_ui(self):
"""设置用户界面"""
layout = QVBoxLayout(self)
# 基本信息区域
basic_layout = QGridLayout()
basic_layout.addWidget(QLabel("款号:"), 0, 0, Qt.AlignRight)
self.style_input = QLineEdit()
if self.style_number:
self.style_input.setText(self.style_number)
self.style_input.setEnabled(not self.style_number)
basic_layout.addWidget(self.style_input, 0, 1)
basic_layout.addWidget(QLabel("款式图:"), 1, 0, Qt.AlignRight)
self.image_label = QLabel("无图片")
self.image_label.setFixedSize(300, 300)
self.image_label.setStyleSheet("border: 1px solid gray;")
self.image_label.setAlignment(Qt.AlignCenter)
self.image_label.setScaledContents(True)
basic_layout.addWidget(self.image_label, 1, 1, 5, 1)
upload_btn = QPushButton("上传/更换图片")
upload_btn.clicked.connect(self.upload_image)
basic_layout.addWidget(upload_btn, 1, 2)
layout.addLayout(basic_layout)
# 材料用量区域
layout.addWidget(QLabel("材料用量(单件):"))
self.material_table = QTableWidget()
self.material_table.setColumnCount(6)
self.material_table.setHorizontalHeaderLabels(["类目", "类型", "型号", "单件用量", "单位", "删除"])
self.material_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
layout.addWidget(self.material_table)
# 按钮区域
btn_layout = QHBoxLayout()
add_default_btn = QPushButton("快速添加标准类目")
add_default_btn.clicked.connect(self.add_default_categories)
btn_layout.addWidget(add_default_btn)
add_custom_btn = QPushButton("添加自定义类目")
add_custom_btn.clicked.connect(lambda: self.add_material_row())
btn_layout.addWidget(add_custom_btn)
layout.addLayout(btn_layout)
# 保存/取消按钮
buttons = QHBoxLayout()
save_btn = QPushButton("保存")
save_btn.clicked.connect(self.save_garment)
buttons.addWidget(save_btn)
cancel_btn = QPushButton("取消")
cancel_btn.clicked.connect(self.reject)
buttons.addWidget(cancel_btn)
layout.addLayout(buttons)
def get_conn(self):
"""获取数据库连接"""
return get_db_connection(self.db_path)
def upload_image(self):
"""上传图片"""
file_path, _ = QFileDialog.getOpenFileName(self, "选择图片", "", "Images (*.png *.jpg *.jpeg *.bmp)")
if file_path:
try:
img = Image.open(file_path).convert("RGB")
img.thumbnail((800, 800))
os.makedirs("images", exist_ok=True)
filename = os.path.basename(file_path)
save_path = os.path.join("images", filename)
img.save(save_path, "JPEG", quality=85)
self.current_image_path = save_path
pixmap = QPixmap(save_path).scaled(300, 300, Qt.KeepAspectRatio, Qt.SmoothTransformation)
self.image_label.setPixmap(pixmap)
except Exception as e:
QMessageBox.critical(self, "错误", "上传图片失败: " + str(e))
def load_garment_data(self):
"""加载服装数据"""
try:
with self.get_conn() as conn:
cursor = conn.execute("SELECT image_path FROM garments WHERE style_number = ?", (self.style_number,))
row = cursor.fetchone()
if row and row[0] and os.path.exists(row[0]):
self.current_image_path = row[0]
pixmap = QPixmap(row[0]).scaled(300, 300, Qt.KeepAspectRatio, Qt.SmoothTransformation)
self.image_label.setPixmap(pixmap)
self.load_materials()
except Exception as e:
QMessageBox.critical(self, "错误", "加载失败: " + str(e))
def load_materials(self):
"""加载材料列表"""
try:
with self.get_conn() as conn:
cursor = conn.execute("SELECT category, fabric_type, model, usage_per_piece, unit FROM garment_materials WHERE style_number = ? ORDER BY id", (self.style_number,))
for category, fabric_type, model, usage, unit in cursor.fetchall():
# 直接使用数据库中的三个字段
display_category = category or ""
display_type = fabric_type or ""
display_model = model or ""
self.add_material_row(display_category, display_type, usage or 0, unit or "", display_model)
except Exception as e:
QMessageBox.critical(self, "错误", "加载材料失败: " + str(e))
def add_default_categories(self):
"""添加默认类目"""
defaults = [("A料", "", ""), ("B料", "", ""), ("C料", "", ""), ("D料", "", ""),
("花边", "", ""), ("胸杯", "", "一对"), ("拉链", "", ""), ("辅料", "", "")]
for cat, fabric_type, unit in defaults:
self.add_material_row(cat, fabric_type, 0, unit)
def add_material_row(self, category="", fabric_type="", usage=0.0, unit="", model=""):
"""添加材料行"""
row = self.material_table.rowCount()
self.material_table.insertRow(row)
# 列0: 类目下拉框
cat_combo = QComboBox()
cat_combo.setEditable(False)
# 最后添加自定义选项
cat_combo.addItem("—— 自定义类目 ——")
# 先添加所有类目选项
try:
with self.get_conn() as conn:
cursor = conn.execute("""
SELECT DISTINCT category
FROM fabrics
WHERE category IS NOT NULL AND category != ''
ORDER BY category
""")
categories = set()
for cat_row in cursor.fetchall():
if cat_row[0] and cat_row[0].strip():
categories.add(cat_row[0])
for cat in sorted(categories):
cat_combo.addItem(cat)
except:
# 如果查询失败,使用默认类目
cat_combo.addItem("布料")
cat_combo.addItem("辅料")
cat_combo.addItem("其他")
if category:
cat_combo.setCurrentText(category)
else:
# 如果没有指定类目,默认选择"—— 自定义类目 ——"索引0
print("没有指定类目,默认选择'—— 自定义类目 ——'索引0")
print(cat_combo.count())
print(cat_combo.currentIndex())
# 打印所有选项
for i in range(cat_combo.count()):
print(cat_combo.itemText(i))
cat_combo.setCurrentIndex(0)
self.material_table.setCellWidget(row, 0, cat_combo)
# 列1: 类型下拉框
type_combo = QComboBox()
type_combo.setEditable(False)
# 最后添加选择提示
type_combo.addItem("—— 选择类型 ——")
# 先添加所有类型选项
try:
with self.get_conn() as conn:
cursor = conn.execute("""
SELECT DISTINCT fabric_type
FROM fabrics
WHERE fabric_type IS NOT NULL AND fabric_type != ''
ORDER BY fabric_type
""")
types = cursor.fetchall()
for type_row in types:
if type_row[0] and type_row[0].strip():
type_combo.addItem(type_row[0])
except:
pass
if fabric_type:
type_combo.setCurrentText(fabric_type)
else:
# 如果没有指定类型,默认选择"—— 选择类型 ——"索引0
print("没有指定类型,默认选择'—— 选择类型 ——'索引0")
print(type_combo.count())
print(type_combo.currentIndex())
# 打印所有选项
for i in range(type_combo.count()):
print(type_combo.itemText(i))
type_combo.setCurrentIndex(0)
self.material_table.setCellWidget(row, 1, type_combo)
# 列2: 型号下拉框
model_combo = QComboBox()
model_combo.setEditable(False)
model_combo.addItem("—— 选择型号 ——")
# 初始化时加载所有型号
try:
with self.get_conn() as conn:
cursor = conn.execute("""
SELECT DISTINCT model, color, unit
FROM fabrics
ORDER BY model
""")
models = cursor.fetchall()
for model_row in models:
model, color, unit = model_row
# 显示格式:型号-颜色(如果有颜色的话)
display_text = model
if color and color.strip():
display_text = f"{model}-{color}"
model_combo.addItem(display_text, model)
except Exception as e:
pass
if fabric_type:
model_combo.setCurrentText(fabric_type)
else:
# 如果没有指定类型,默认选择"—— 选择类型 ——"索引0
print("没有指定类型,默认选择'—— 选择类型 ——'索引0")
print(model_combo.count())
print(model_combo.currentIndex())
# 打印所有选项
for i in range(model_combo.count()):
print(model_combo.itemText(i))
model_combo.setCurrentIndex(0)
self.material_table.setCellWidget(row, 2, model_combo)
# 列3: 单件用量
usage_spin = QDoubleSpinBox()
usage_spin.setRange(0, 1000)
usage_spin.setValue(usage)
usage_spin.setDecimals(3)
self.material_table.setCellWidget(row, 3, usage_spin)
# 列4: 单位
unit_combo = QComboBox()
unit_combo.setEditable(True)
unit_combo.addItems(["", "", "公斤", "一对", "", ""])
unit_combo.setCurrentText(unit)
self.material_table.setCellWidget(row, 4, unit_combo)
# 列5: 删除按钮
del_btn = QPushButton("删除")
del_btn.clicked.connect(lambda _, r=row: self.material_table.removeRow(r))
self.material_table.setCellWidget(row, 5, del_btn)
# 初始化类型和型号选项
# self.on_category_changed(cat_combo.currentText(), row)
# 如果没有选择具体类目,初始化时显示全部型号
# if cat_combo.currentText() == "—— 自定义类目 ——":
# self.on_type_changed("—— 选择类型 ——", row)
# 如果有指定的型号,需要在初始化完成后设置
# if model:
# # 先设置类型(如果有的话)
# if fabric_type:
# type_combo.setCurrentText(fabric_type)
# self.on_type_changed(fabric_type, row)
# # 然后设置型号
# model_combo = self.material_table.cellWidget(row, 2)
# if model_combo:
# # 确保型号在选项列表中
# found = False
# for i in range(model_combo.count()):
# item_data = model_combo.itemData(i)
# item_text = model_combo.itemText(i)
# if item_data == model or item_text == model:
# model_combo.setCurrentIndex(i)
# found = True
# break
cat_combo.currentTextChanged.connect(lambda text, r=row: self.on_category_changed(text, r))
type_combo.currentTextChanged.connect(lambda text, r=row: self.on_type_changed(text, r))
model_combo.currentTextChanged.connect(lambda text, r=row: self.on_model_selected(text, r))
def on_category_changed(self, category_text, row):
"""当类目改变时,更新类型下拉框"""
print("on_category_changed", category_text, row)
type_combo = self.material_table.cellWidget(row, 1)
model_combo = self.material_table.cellWidget(row, 2)
# 清空类型下拉框
type_combo.clear()
type_combo.addItem("—— 选择类型 ——")
# 重新初始化型号下拉框显示所有型号阻止信号防止触发on_model_selected
model_combo.blockSignals(True)
model_combo.clear()
model_combo.addItem("—— 选择型号 ——")
try:
with self.get_conn() as conn:
# 加载所有类型
if category_text and category_text != "—— 自定义类目 ——":
# 如果选择了具体类目,则过滤
cursor = conn.execute("""
SELECT DISTINCT fabric_type
FROM fabrics
WHERE category = ? AND fabric_type IS NOT NULL AND fabric_type != ''
ORDER BY fabric_type
""", (category_text,))
else:
# 加载所有类型
cursor = conn.execute("""
SELECT DISTINCT fabric_type
FROM fabrics
WHERE fabric_type IS NOT NULL AND fabric_type != ''
ORDER BY fabric_type
""")
types = cursor.fetchall()
for type_row in types:
if type_row[0] and type_row[0].strip():
type_combo.addItem(type_row[0])
# 连接类型改变事件
type_combo.currentTextChanged.connect(lambda text, r=row: self.on_type_changed(text, r))
# 加载该类目下的所有型号到型号下拉框
if category_text and category_text != "—— 自定义类目 ——":
# 如果选择了具体类目,则只加载该类目下的型号
cursor = conn.execute("""
SELECT DISTINCT model, color, unit
FROM fabrics
WHERE category = ?
ORDER BY model
""", (category_text,))
else:
# 如果是自定义类目,加载所有型号
cursor = conn.execute("""
SELECT DISTINCT model, color, unit
FROM fabrics
ORDER BY model
""")
models = cursor.fetchall()
for model_row in models:
model, color, unit = model_row
# 显示格式:型号-颜色(如果有颜色的话)
display_text = model
if color and color.strip():
display_text = f"{model}-{color}"
model_combo.addItem(display_text, model)
# 确保默认选中第一项("—— 选择型号 ——"
model_combo.setCurrentIndex(0)
except Exception as e:
pass
finally:
# 恢复信号
model_combo.blockSignals(False)
def on_type_changed(self, type_text, row):
"""当类型改变时,更新类目和型号下拉框"""
print("on_type_changed", type_text, row)
cat_combo = self.material_table.cellWidget(row, 0)
model_combo = self.material_table.cellWidget(row, 2)
if not model_combo:
return
# 如果选择了具体类型,自动选中该类型对应的类目
if cat_combo and type_text and type_text != "—— 选择类型 ——":
try:
with self.get_conn() as conn:
# 查询该类型对应的类目
cursor = conn.execute("""
SELECT DISTINCT category
FROM fabrics
WHERE fabric_type = ? AND category IS NOT NULL AND category != ''
ORDER BY category
LIMIT 1
""", (type_text,))
row = cursor.fetchone()
if row and row[0]:
category = row[0].strip()
# 在类目下拉框中查找并选中该类目
index = cat_combo.findText(category)
if index >= 0:
cat_combo.blockSignals(True)
cat_combo.setCurrentIndex(index)
cat_combo.blockSignals(False)
except Exception as e:
pass
# 重新初始化型号下拉框,显示该类型下的所有型号
model_combo.blockSignals(True)
model_combo.clear()
model_combo.addItem("—— 选择型号 ——")
# 根据类型和类目过滤型号
try:
with self.get_conn() as conn:
# 获取当前选择的类目(可能已经更新)
category_text = cat_combo.currentText() if cat_combo else ""
# 构建查询条件
if type_text and type_text != "—— 选择类型 ——":
# 如果选择了具体类型
if category_text and category_text != "—— 自定义类目 ——":
# 同时根据类目和类型过滤
cursor = conn.execute("""
SELECT DISTINCT model, color, unit
FROM fabrics
WHERE category = ? AND fabric_type = ?
ORDER BY model
""", (category_text, type_text))
else:
# 只根据类型过滤
cursor = conn.execute("""
SELECT DISTINCT model, color, unit
FROM fabrics
WHERE fabric_type = ?
ORDER BY model
""", (type_text,))
else:
# 如果没有选择类型,根据类目过滤(如果有类目)
if category_text and category_text != "—— 自定义类目 ——":
cursor = conn.execute("""
SELECT DISTINCT model, color, unit
FROM fabrics
WHERE category = ?
ORDER BY model
""", (category_text,))
else:
# 显示所有型号
cursor = conn.execute("""
SELECT DISTINCT model, color, unit
FROM fabrics
ORDER BY model
""")
models = cursor.fetchall()
for model_row in models:
model, color, unit = model_row
# 显示格式:型号-颜色(如果有颜色的话)
display_text = model
if color and color.strip():
display_text = f"{model}-{color}"
model_combo.addItem(display_text, model)
except Exception as e:
pass
# 确保默认选中第一项("—— 选择型号 ——"
model_combo.setCurrentIndex(0)
model_combo.blockSignals(False)
def on_model_selected(self, model_text, row):
"""当型号选择时,自动设置单位并填充类目和类型"""
print("on_model_selected", model_text, row)
# 先获取所有需要的控件
cat_combo = self.material_table.cellWidget(row, 0)
type_combo = self.material_table.cellWidget(row, 1)
model_combo = self.material_table.cellWidget(row, 2)
unit_combo = self.material_table.cellWidget(row, 4)
if not model_text or model_text == "—— 选择型号 ——":
# 获取当前类目和类型下的所有型号,阻止信号防止死循环
model_combo.blockSignals(True)
try:
model_combo.clear()
model_combo.addItem("—— 选择型号 ——")
try:
with self.get_conn() as conn:
if cat_combo.currentText() != "—— 自定义类目 ——" and type_combo.currentText() != "—— 选择类型 ——":
cursor = conn.execute("SELECT DISTINCT model, color, unit FROM fabrics WHERE category = ? AND fabric_type = ? ORDER BY model", (cat_combo.currentText(), type_combo.currentText()))
elif cat_combo.currentText() != "—— 自定义类目 ——" and type_combo.currentText() == "—— 选择类型 ——":
cursor = conn.execute("SELECT DISTINCT model, color, unit FROM fabrics WHERE category = ? ORDER BY model", (cat_combo.currentText(),))
else:
cursor = conn.execute("SELECT DISTINCT model, color, unit FROM fabrics ORDER BY model")
models = cursor.fetchall()
for model_row in models:
model, color, unit = model_row
# 显示格式:型号-颜色(如果有颜色的话)
display_text = model
if color and color.strip():
display_text = f"{model}-{color}"
model_combo.addItem(display_text, model)
except Exception as e:
pass
model_combo.setCurrentIndex(0)
finally:
# 恢复信号
model_combo.blockSignals(False)
return
# 获取选中项的数据
current_index = model_combo.currentIndex()
if current_index > 0:
model = model_combo.itemData(current_index)
if model:
try:
with self.get_conn() as conn:
cursor = conn.execute("SELECT category, fabric_type, unit FROM fabrics WHERE model = ?", (model,))
row_db = cursor.fetchone()
if row_db:
category, fabric_type, unit = row_db
# 自动填充单位
if unit:
unit_combo.setCurrentText(unit)
# 自动填充类目和类型,阻止信号以避免触发默认更新逻辑
if category:
# 阻止类目、类型和型号的信号,避免触发默认更新逻辑
cat_combo.blockSignals(True)
type_combo.blockSignals(True)
model_combo.blockSignals(True)
# 设置类目
cat_combo.setCurrentText(category)
# 更新类型下拉框选项(直接调用,不会触发信号因为已经阻止了)
self.on_category_changed(category, row)
# 重新阻止信号因为on_category_changed在finally中恢复了信号
# 这可以防止死循环
model_combo.blockSignals(True)
# 重新设置选中的型号因为on_category_changed会清空并重新加载型号下拉框
# 查找并选中对应的型号
for i in range(model_combo.count()):
item_data = model_combo.itemData(i)
if item_data == model:
model_combo.setCurrentIndex(i)
break
# 设置类型
if fabric_type:
type_combo.setCurrentText(fabric_type)
# 恢复信号
cat_combo.blockSignals(False)
type_combo.blockSignals(False)
model_combo.blockSignals(False)
except:
pass
def save_garment(self):
"""保存服装"""
style_number = self.style_input.text().strip()
if not style_number:
QMessageBox.warning(self, "错误", "请输入款号")
return
try:
with self.get_conn() as conn:
conn.execute('INSERT OR REPLACE INTO garments (style_number, image_path) VALUES (?, ?)',
(style_number, self.current_image_path))
conn.execute("DELETE FROM garment_materials WHERE style_number = ?", (style_number,))
for row in range(self.material_table.rowCount()):
# 获取各列的值
category_widget = self.material_table.cellWidget(row, 0) # 类目
type_widget = self.material_table.cellWidget(row, 1) # 类型
model_widget = self.material_table.cellWidget(row, 2) # 型号
usage_widget = self.material_table.cellWidget(row, 3) # 单件用量
unit_widget = self.material_table.cellWidget(row, 4) # 单位
category = category_widget.currentText().strip()
fabric_type = type_widget.currentText().strip()
model = model_widget.currentText().strip()
# 处理类目和类型
if category == "—— 自定义类目 ——":
category = ""
if fabric_type == "—— 选择类型 ——":
fabric_type = ""
# 如果选择了具体型号,获取型号的实际值
final_model = ""
if model and model != "—— 选择型号 ——":
model_data = model_widget.itemData(model_widget.currentIndex())
final_model = model_data if model_data else model
# 至少需要有类目或型号
if not category and not final_model:
continue
usage = usage_widget.value()
unit = unit_widget.currentText().strip() or ""
# 分别存储类目、类型和型号到对应字段
conn.execute("INSERT INTO garment_materials (style_number, category, fabric_type, model, usage_per_piece, unit) VALUES (?, ?, ?, ?, ?, ?)",
(style_number, category, fabric_type, final_model, usage, unit))
conn.commit()
QMessageBox.information(self, "成功", "保存完成")
self.accept()
except Exception as e:
QMessageBox.critical(self, "错误", "保存失败: " + str(e))