Files
cangku/garment_dialogs.py
liangweihao 6322cb0caa 实现原料逻辑删除功能
- 为fabrics表添加is_deleted字段用于标记删除状态
- 修改delete_raw方法实现逻辑删除而非物理删除
- 更新所有查询语句过滤已删除的原料数据
- 更新库存视图过滤已删除的原料和相关记录
- 保留历史数据,支持数据恢复

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 19:09:16 +08:00

753 lines
32 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, QTimer, QSortFilterProxyModel
from PyQt5.QtGui import QPixmap
from database import get_db_connection
class SearchableComboBox(QComboBox):
"""支持模糊搜索的下拉框 - 基于 QSortFilterProxyModel 和 QCompleter"""
def __init__(self, parent=None):
super(SearchableComboBox, self).__init__(parent)
self.setFocusPolicy(Qt.StrongFocus)
self.setEditable(True)
self.setInsertPolicy(QComboBox.NoInsert)
# 添加过滤模型来过滤匹配项
self.pFilterModel = QSortFilterProxyModel(self)
self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
self.pFilterModel.setSourceModel(self.model())
# 添加自动完成器,使用过滤模型
self.completer = QCompleter(self.pFilterModel, self)
# 始终显示所有(过滤后的)完成项
self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
self.setCompleter(self.completer)
# 连接信号
self.lineEdit().textEdited.connect(self.pFilterModel.setFilterFixedString)
self.completer.activated.connect(self.on_completer_activated)
# 当从自动完成器中选择项时,从组合框中选择对应的项
def on_completer_activated(self, text):
if text:
index = self.findText(text)
self.setCurrentIndex(index)
self.activated[str].emit(self.itemText(index))
# 当模型改变时,同时更新过滤器和自动完成器的模型
def setModel(self, model):
super(SearchableComboBox, self).setModel(model)
self.pFilterModel.setSourceModel(model)
self.completer.setModel(self.pFilterModel)
# 当模型列改变时,同时更新过滤器和自动完成器的模型列
def setModelColumn(self, column):
self.completer.setCompletionColumn(column)
self.pFilterModel.setFilterKeyColumn(column)
super(SearchableComboBox, self).setModelColumn(column)
def setDefaultText(self, text):
"""设置默认文本 - 兼容方法"""
line_edit = self.lineEdit()
if line_edit:
line_edit.blockSignals(True)
line_edit.setText(text)
line_edit.blockSignals(False)
# 尝试找到匹配的项
index = self.findText(text)
if index >= 0:
self.setCurrentIndex(index)
else:
self.setCurrentIndex(-1)
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=""):
"""添加材料行"""
print("add_material_row", category, fabric_type, usage, 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 = SearchableComboBox()
model_combo.addItem("—— 选择型号 ——")
# 先将下拉框添加到表格中这样update_model_combo_range才能获取到类目和类型
self.material_table.setCellWidget(row, 2, model_combo)
# 初始化时根据类目和类型加载对应的型号
self.update_model_combo_range(model_combo, row)
# 列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.activated[str].connect(lambda text, r=row: self.on_model_selected(text, r))
def update_model_combo_range(self, model_combo, row):
print("update_model_combo_range", model_combo, row)
"""更新型号下拉框的搜索范围"""
cat_combo = self.material_table.cellWidget(row, 0)
type_combo = self.material_table.cellWidget(row, 1)
category_text = cat_combo.currentText() if cat_combo else ""
type_text = type_combo.currentText() if type_combo else ""
# 阻止信号防止触发on_model_selected
model_combo.blockSignals(True)
line_edit = model_combo.lineEdit()
if line_edit:
line_edit.blockSignals(True)
try:
with self.get_conn() as conn:
# 根据类目和类型构建查询条件
if category_text and category_text != "—— 自定义类目 ——" and type_text and type_text != "—— 选择类型 ——":
# 同时根据类目和类型过滤
cursor = conn.execute("""
SELECT DISTINCT model, color, unit
FROM fabrics
WHERE category = ? AND fabric_type = ?
ORDER BY model
""", (category_text, type_text))
elif category_text and category_text != "—— 自定义类目 ——":
# 只根据类目过滤
cursor = conn.execute("""
SELECT DISTINCT model, color, unit
FROM fabrics
WHERE category = ?
ORDER BY model
""", (category_text,))
elif type_text and type_text != "—— 选择类型 ——":
# 只根据类型过滤
cursor = conn.execute("""
SELECT DISTINCT model, color, unit
FROM fabrics
WHERE fabric_type = ?
ORDER BY model
""", (type_text,))
else:
# 显示所有型号
cursor = conn.execute("""
SELECT DISTINCT model, color, unit
FROM fabrics
ORDER BY model
""")
# 保存当前用户输入的文本(如果有)
current_text = line_edit.text() if line_edit else ""
cursor_position = line_edit.cursorPosition() if line_edit else 0
print("current_text", current_text)
print("cursor_position", cursor_position)
# 清空并重新填充型号下拉框
model_combo.clear()
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)
# 恢复用户输入的文本,如果没有输入则设置默认文本
if line_edit:
if current_text and current_text != "—— 选择型号 ——":
line_edit.setText(current_text)
line_edit.setCursorPosition(cursor_position)
else:
if isinstance(model_combo, SearchableComboBox):
model_combo.setDefaultText("—— 选择型号 ——")
else:
model_combo.setCurrentIndex(0)
except Exception as e:
pass
finally:
if line_edit:
line_edit.blockSignals(False)
model_combo.blockSignals(False)
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("—— 选择类型 ——")
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))
# 更新型号下拉框的搜索范围
self.update_model_combo_range(model_combo, row)
except Exception as e:
pass
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_db = cursor.fetchone()
if row_db and row_db[0]:
category = row_db[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
# 更新型号下拉框的搜索范围
self.update_model_combo_range(model_combo, row)
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 == "—— 选择型号 ——":
# 空选择,不做联动
return
# 从显示文本中解析真实型号(例如 "M001-红" -> "M001"
display_text = model_text.strip()
base_model = display_text.split("-", 1)[0] if "-" in display_text else display_text
try:
with self.get_conn() as conn:
cursor = conn.execute(
"SELECT category, fabric_type, unit FROM fabrics WHERE model = ? AND (is_deleted IS NULL OR is_deleted = 0)",
(base_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内部可能恢复了信号
model_combo.blockSignals(True)
# 设置类型
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))