From 58605b1f92b483ea77aba873227f8edb514f0243 Mon Sep 17 00:00:00 2001 From: liangweihao <734499798@qq.com> Date: Tue, 23 Dec 2025 12:35:07 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BC=96=E8=BE=91=E6=AC=BE=E5=BC=8F=E4=B8=8B?= =?UTF-8?q?=E6=8B=89=E6=A1=86=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- database.py | 47 ++-- fabric_library.db | Bin 45056 -> 98304 bytes fabric_manager_pro.py | 39 +++- garment_dialogs.py | 459 +++++++++++++++++++++++++-------------- main.py | 13 +- purchase_order_dialog.py | 13 +- raw_material_dialog.py | 56 ++--- 7 files changed, 399 insertions(+), 228 deletions(-) diff --git a/database.py b/database.py index 135a587..05f95aa 100644 --- a/database.py +++ b/database.py @@ -32,6 +32,7 @@ class DatabaseManager: CREATE TABLE IF NOT EXISTS fabrics ( model TEXT PRIMARY KEY, category TEXT DEFAULT '未分类', + fabric_type TEXT, supplier TEXT, color TEXT, width REAL, @@ -47,6 +48,7 @@ class DatabaseManager: # 为fabrics表添加索引 conn.execute('CREATE INDEX IF NOT EXISTS idx_fabrics_category ON fabrics(category)') + conn.execute('CREATE INDEX IF NOT EXISTS idx_fabrics_fabric_type ON fabrics(fabric_type)') conn.execute('CREATE INDEX IF NOT EXISTS idx_fabrics_supplier ON fabrics(supplier)') # 衣服款号表 @@ -66,6 +68,7 @@ class DatabaseManager: style_number TEXT, category TEXT, fabric_type TEXT, + model TEXT, usage_per_piece REAL, unit TEXT DEFAULT '米', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, @@ -77,12 +80,21 @@ class DatabaseManager: # 为garment_materials表添加索引 conn.execute('CREATE INDEX IF NOT EXISTS idx_garment_materials_style ON garment_materials(style_number)') conn.execute('CREATE INDEX IF NOT EXISTS idx_garment_materials_category ON garment_materials(category)') + conn.execute('CREATE INDEX IF NOT EXISTS idx_garment_materials_model ON garment_materials(model)') # 添加新字段(如果不存在) try: conn.execute("ALTER TABLE garment_materials ADD COLUMN fabric_type TEXT") except: pass + try: + conn.execute("ALTER TABLE garment_materials ADD COLUMN model TEXT") + except: + pass + try: + conn.execute("ALTER TABLE fabrics ADD COLUMN fabric_type TEXT") + except: + pass try: conn.execute("ALTER TABLE fabrics ADD COLUMN created_at DATETIME DEFAULT CURRENT_TIMESTAMP") except: @@ -131,6 +143,21 @@ class DatabaseManager: conn.execute("ALTER TABLE fabric_consumption ADD COLUMN updated_at DATETIME DEFAULT CURRENT_TIMESTAMP") except: pass + + # 数据迁移:将fabrics表中category字段的"类目-类型"格式拆分成两个字段 + try: + cursor = conn.execute("SELECT model, category FROM fabrics WHERE category LIKE '%-%' AND (fabric_type IS NULL OR fabric_type = '')") + rows = cursor.fetchall() + for model, category in rows: + if '-' in category: + parts = category.split('-', 1) + new_category = parts[0] + new_fabric_type = parts[1] + conn.execute("UPDATE fabrics SET category = ?, fabric_type = ? WHERE model = ?", + (new_category, new_fabric_type, model)) + conn.commit() + except: + pass # 管理员设置表 conn.execute(''' @@ -246,14 +273,10 @@ def get_fabric_categories(db_path): try: with get_db_connection(db_path) as conn: cursor = conn.execute(""" - SELECT DISTINCT - CASE - WHEN category LIKE '%-%' THEN SUBSTR(category, 1, INSTR(category, '-') - 1) - ELSE category - END as major_category + SELECT DISTINCT category FROM fabrics WHERE category IS NOT NULL AND category != '' - ORDER BY major_category + ORDER BY category """) categories = set() for row in cursor.fetchall(): @@ -272,19 +295,15 @@ def get_fabric_types_by_category(db_path, category): try: with get_db_connection(db_path) as conn: cursor = conn.execute(""" - SELECT DISTINCT - CASE - WHEN category LIKE '%-%' THEN SUBSTR(category, INSTR(category, '-') + 1) - ELSE '默认类型' - END as fabric_type + SELECT DISTINCT fabric_type FROM fabrics - WHERE category LIKE ? OR category = ? + WHERE category = ? AND fabric_type IS NOT NULL AND fabric_type != '' ORDER BY fabric_type - """, (f"{category}-%", category)) + """, (category,)) types = [] for row in cursor.fetchall(): - if row[0] and row[0] != '默认类型': + if row[0] and row[0].strip(): types.append(row[0]) return types except: diff --git a/fabric_library.db b/fabric_library.db index c870d1d30308268a30c0594f954d969289066081..7451beaf62d089546a36b88fa1647284c2588cd5 100644 GIT binary patch literal 98304 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 0: + # super().setCurrentIndex(0) def update_completer(self): """更新自动完成列表""" @@ -111,6 +130,22 @@ class SearchableComboBox(QComboBox): 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): """服装库管理对话框""" @@ -355,40 +390,12 @@ class GarmentEditDialog(QDialog): """加载材料列表""" try: with self.get_conn() as conn: - cursor = conn.execute("SELECT category, fabric_type, usage_per_piece, unit FROM garment_materials WHERE style_number = ? ORDER BY id", (self.style_number,)) - for category, fabric_type, usage, unit in cursor.fetchall(): - display_category = "" - display_type = "" - display_model = "" - - # category字段可能存储型号或类目-类型组合 - if category: - # 首先检查是否是型号(在fabrics表中查找) - fabric_cursor = conn.execute("SELECT category, model FROM fabrics WHERE model = ?", (category,)) - fabric_row = fabric_cursor.fetchone() - - if fabric_row: - # 是型号,从fabrics表获取类目信息 - fabric_category, model = fabric_row - display_model = model - if fabric_category and "-" in fabric_category: - parts = fabric_category.split("-", 1) - display_category = parts[0] - display_type = parts[1] - else: - display_category = fabric_category or "" - else: - # 不是型号,按类目-类型格式解析 - if "-" in category: - parts = category.split("-", 1) - display_category = parts[0] - display_type = parts[1] - else: - display_category = category - - # 如果有单独的fabric_type字段,优先使用 - if fabric_type: - display_type = fabric_type + 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: @@ -408,32 +415,24 @@ class GarmentEditDialog(QDialog): # 列0: 类目下拉框 cat_combo = QComboBox() - cat_combo.setEditable(True) + cat_combo.setEditable(False) # 最后添加自定义选项 cat_combo.addItem("—— 自定义类目 ——") # 先添加所有类目选项 try: with self.get_conn() as conn: - # 只获取纯类目(提取"-"前面的部分) cursor = conn.execute(""" - SELECT DISTINCT - CASE - WHEN category LIKE '%-%' THEN SUBSTR(category, 1, INSTR(category, '-') - 1) - ELSE category - END as major_category + SELECT DISTINCT category FROM fabrics WHERE category IS NOT NULL AND category != '' - ORDER BY major_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]) - # 添加默认类目 - categories.update(["布料", "辅料", "其他"]) - for cat in sorted(categories): cat_combo.addItem(cat) except: @@ -445,53 +444,57 @@ class GarmentEditDialog(QDialog): if category: cat_combo.setCurrentText(category) else: - # 如果没有指定类目,默认选择第一个实际类目而不是"自定义类目" - if cat_combo.count() > 1: - cat_combo.setCurrentIndex(0) + # 如果没有指定类目,默认选择"—— 自定义类目 ——"(索引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) - cat_combo.currentTextChanged.connect(lambda text, r=row: self.on_category_changed(text, r)) self.material_table.setCellWidget(row, 0, cat_combo) # 列1: 类型下拉框 type_combo = QComboBox() - type_combo.setEditable(True) - + type_combo.setEditable(False) + # 最后添加选择提示 + type_combo.addItem("—— 选择类型 ——") # 先添加所有类型选项 try: with self.get_conn() as conn: cursor = conn.execute(""" - SELECT DISTINCT - CASE - WHEN category LIKE '%-%' THEN SUBSTR(category, INSTR(category, '-') + 1) - ELSE '默认类型' - END as fabric_type + SELECT DISTINCT fabric_type FROM fabrics - WHERE category IS NOT NULL AND category != '' + 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] != '默认类型': + if type_row[0] and type_row[0].strip(): type_combo.addItem(type_row[0]) except: pass - # 最后添加选择提示 - type_combo.addItem("—— 选择类型 ——") if fabric_type: type_combo.setCurrentText(fabric_type) else: - # 如果没有指定类型,默认选择第一个实际类型而不是"选择类型" - if type_combo.count() > 1: - type_combo.setCurrentIndex(0) + # 如果没有指定类型,默认选择"—— 选择类型 ——"(索引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) - type_combo.currentTextChanged.connect(lambda text, r=row: self.on_type_changed(text, r)) self.material_table.setCellWidget(row, 1, type_combo) - # 列2: 型号下拉框(支持模糊搜索) - model_combo = SearchableComboBox() + # 列2: 型号下拉框 + model_combo = QComboBox() + model_combo.setEditable(False) model_combo.addItem("—— 选择型号 ——") # 初始化时加载所有型号 @@ -513,10 +516,18 @@ class GarmentEditDialog(QDialog): except Exception as e: pass - # 确保默认选中第一项("—— 选择型号 ——") - model_combo.setCurrentIndex(0) - - model_combo.currentTextChanged.connect(lambda text, r=row: self.on_model_selected(text, r)) + 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: 单件用量 @@ -539,38 +550,37 @@ class GarmentEditDialog(QDialog): self.material_table.setCellWidget(row, 5, del_btn) # 初始化类型和型号选项 - self.on_category_changed(cat_combo.currentText(), row) + # self.on_category_changed(cat_combo.currentText(), row) # 如果没有选择具体类目,初始化时显示全部型号 - if cat_combo.currentText() == "—— 自定义类目 ——": - self.on_type_changed("—— 选择类型 ——", 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) + # if model: + # # 先设置类型(如果有的话) + # if fabric_type: + # type_combo.setCurrentText(fabric_type) + # self.on_type_changed(fabric_type, row) - # 然后设置型号 - 使用SearchableComboBox的setCurrentText方法 - model_combo = self.material_table.cellWidget(row, 2) - if isinstance(model_combo, SearchableComboBox): - # 确保型号在选项列表中 - 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 - - # 如果没找到,直接设置文本(SearchableComboBox支持) - if not found: - model_combo.setCurrentText(model) - + # # 然后设置型号 + # 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) @@ -578,51 +588,55 @@ class GarmentEditDialog(QDialog): 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: # 加载所有类型 - cursor = conn.execute(""" - SELECT DISTINCT - CASE - WHEN category LIKE '%-%' THEN SUBSTR(category, INSTR(category, '-') + 1) - ELSE '默认类型' - END as fabric_type - FROM fabrics - WHERE category IS NOT NULL AND category != '' - ORDER BY fabric_type - """) - - # 如果选择了具体类目,则过滤 if category_text and category_text != "—— 自定义类目 ——": + # 如果选择了具体类目,则过滤 cursor = conn.execute(""" - SELECT DISTINCT - CASE - WHEN category LIKE '%-%' THEN SUBSTR(category, INSTR(category, '-') + 1) - ELSE '默认类型' - END as fabric_type + SELECT DISTINCT fabric_type FROM fabrics - WHERE category LIKE ? OR category = ? + WHERE category = ? AND fabric_type IS NOT NULL AND fabric_type != '' ORDER BY fabric_type - """, (f"{category_text}-%", category_text)) + """, (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] != '默认类型': + 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)) - # 加载所有型号到型号下拉框 - cursor = conn.execute(""" - SELECT DISTINCT model, color, unit - FROM fabrics - ORDER BY model - """) + # 加载该类目下的所有型号到型号下拉框 + 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 @@ -636,25 +650,89 @@ class GarmentEditDialog(QDialog): 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 hasattr(model_combo, 'clear'): - model_combo.clear() + 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: - cursor = conn.execute(""" - SELECT DISTINCT model, color, unit - FROM fabrics - ORDER BY model - """) + # 获取当前选择的类目(可能已经更新) + 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 @@ -663,22 +741,55 @@ class GarmentEditDialog(QDialog): 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 + + # 确保默认选中第一项("—— 选择型号 ——") + model_combo.setCurrentIndex(0) + model_combo.blockSignals(False) def on_model_selected(self, model_text, row): """当型号选择时,自动设置单位并填充类目和类型""" - if not model_text or model_text == "—— 选择型号 ——": - return - + 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: @@ -686,36 +797,48 @@ class GarmentEditDialog(QDialog): if model: try: with self.get_conn() as conn: - cursor = conn.execute("SELECT category, unit FROM fabrics WHERE model = ?", (model,)) + cursor = conn.execute("SELECT category, fabric_type, unit FROM fabrics WHERE model = ?", (model,)) row_db = cursor.fetchone() if row_db: - category, unit = row_db + category, fabric_type, unit = row_db # 自动填充单位 if unit: unit_combo.setCurrentText(unit) - # 自动填充类目和类型 + # 自动填充类目和类型,阻止信号以避免触发默认更新逻辑 if category: - # 解析类目信息,可能是"类目-类型"格式或单独的类目 - if '-' in category: - parts = category.split('-', 1) - cat_text = parts[0] - type_text = parts[1] if len(parts) > 1 else "" - - # 设置类目 - cat_combo.setCurrentText(cat_text) - - # 更新类型下拉框选项 - self.on_category_changed(cat_text, row) - - # 设置类型 - if type_text: - type_combo.setCurrentText(type_text) - else: - # 只有类目,没有类型 - cat_combo.setCurrentText(category) - self.on_category_changed(category, row) + # 阻止类目、类型和型号的信号,避免触发默认更新逻辑 + 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 @@ -764,11 +887,9 @@ class GarmentEditDialog(QDialog): usage = usage_widget.value() unit = unit_widget.currentText().strip() or "米" - # 分别存储类目、类型和型号信息 - material_identifier = final_model if final_model else (f"{category}-{fabric_type}" if fabric_type else category) - - conn.execute("INSERT INTO garment_materials (style_number, category, fabric_type, usage_per_piece, unit) VALUES (?, ?, ?, ?, ?)", - (style_number, material_identifier, fabric_type, usage, unit)) + # 分别存储类目、类型和型号到对应字段 + 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, "成功", "保存完成") diff --git a/main.py b/main.py index 1b1234e..a353fe5 100644 --- a/main.py +++ b/main.py @@ -335,12 +335,17 @@ class FabricManager(QMainWindow): text = f"款号: {style_number}\n生产件数: {qty}\n损耗率: {self.loss_input.value()}%\n\n" try: with self.get_conn() as conn: - cursor = conn.execute("SELECT category, fabric_type, usage_per_piece, unit FROM garment_materials WHERE style_number = ? ORDER BY id", (style_number,)) - for category, fabric_type, usage, unit in cursor.fetchall(): + cursor = conn.execute("SELECT category, fabric_type, model, usage_per_piece, unit FROM garment_materials WHERE style_number = ? ORDER BY id", (style_number,)) + for category, fabric_type, model, usage, unit in cursor.fetchall(): if usage: total = usage * qty * (1 + loss) - # 显示材料名称(如果有类型则显示类目-类型,否则只显示类目) - material_name = f"{category}-{fabric_type}" if fabric_type else category + # 显示材料名称:优先显示型号,否则显示类目-类型,最后只显示类目 + if model: + material_name = model + elif fabric_type: + material_name = f"{category}-{fabric_type}" if category else fabric_type + else: + material_name = category or "未命名材料" text += f"{material_name}\n单件: {usage:.3f} {unit}\n总用量: {total:.3f} {unit}\n\n" except Exception as e: text += "计算失败: " + str(e) diff --git a/purchase_order_dialog.py b/purchase_order_dialog.py index e9f69ff..fcbc182 100644 --- a/purchase_order_dialog.py +++ b/purchase_order_dialog.py @@ -76,17 +76,22 @@ class PurchaseOrderDialog(QDialog): try: with self.get_conn() as conn: cursor = conn.execute(''' - SELECT category, fabric_type, usage_per_piece, unit + SELECT category, fabric_type, model, usage_per_piece, unit FROM garment_materials WHERE style_number = ? AND usage_per_piece > 0 ORDER BY id ''', (self.style_number,)) rows = cursor.fetchall() - for category, fabric_type, usage_per_piece, unit in rows: + for category, fabric_type, model, usage_per_piece, unit in rows: total_usage = usage_per_piece * self.quantity * (1 + self.loss_rate) - # 显示材料名称(如果有类型则显示类目-类型,否则只显示类目) - material_name = f"{category}-{fabric_type}" if fabric_type else category + # 显示材料名称:优先显示型号,否则显示类目-类型,最后只显示类目 + if model: + material_name = model + elif fabric_type: + material_name = f"{category}-{fabric_type}" if category else fabric_type + else: + material_name = category or "未命名材料" text += f"材料:{material_name}\n" text += f" 单件用量:{usage_per_piece:.3f} {unit}\n" text += f" 总需采购:{total_usage:.3f} {unit}\n\n" diff --git a/raw_material_dialog.py b/raw_material_dialog.py index 7dc96d4..23efa68 100644 --- a/raw_material_dialog.py +++ b/raw_material_dialog.py @@ -246,7 +246,7 @@ class RawMaterialLibraryDialog(QDialog): """加载主类目""" try: with self.get_conn() as conn: - cursor = conn.execute("SELECT DISTINCT CASE WHEN category LIKE '%-%' THEN SUBSTR(category, 1, INSTR(category, '-') - 1) ELSE category END FROM fabrics") + cursor = conn.execute("SELECT DISTINCT category FROM fabrics WHERE category IS NOT NULL AND category != ''") majors = set(row[0] for row in cursor.fetchall() if row[0]) majors.update({"布料", "辅料", "其他"}) @@ -263,7 +263,7 @@ class RawMaterialLibraryDialog(QDialog): """加载添加界面的主类目""" try: with self.get_conn() as conn: - cursor = conn.execute("SELECT DISTINCT CASE WHEN category LIKE '%-%' THEN SUBSTR(category, 1, INSTR(category, '-') - 1) ELSE category END FROM fabrics") + cursor = conn.execute("SELECT DISTINCT category FROM fabrics WHERE category IS NOT NULL AND category != ''") majors = set(row[0] for row in cursor.fetchall() if row[0]) majors.update({"布料", "辅料", "其他"}) @@ -292,20 +292,12 @@ class RawMaterialLibraryDialog(QDialog): try: with self.get_conn() as conn: if major in ("全部类目", ""): - cursor = conn.execute("SELECT DISTINCT category FROM fabrics WHERE category LIKE '%-%'") - subs = set() - for row in cursor.fetchall(): - cat = row[0] - if '-' in cat: - subs.add(cat.split('-', 1)[1]) + cursor = conn.execute("SELECT DISTINCT fabric_type FROM fabrics WHERE fabric_type IS NOT NULL AND fabric_type != ''") + subs = [row[0] for row in cursor.fetchall() if row[0]] self.sub_combo.addItems(sorted(subs)) else: - cursor = conn.execute("SELECT category FROM fabrics WHERE category LIKE ? OR category = ?", (major + "-%", major)) - subs = set() - for row in cursor.fetchall(): - cat = row[0] - if '-' in cat: - subs.add(cat.split('-', 1)[1]) + cursor = conn.execute("SELECT DISTINCT fabric_type FROM fabrics WHERE category = ? AND fabric_type IS NOT NULL AND fabric_type != ''", (major,)) + subs = [row[0] for row in cursor.fetchall() if row[0]] self.sub_combo.addItems(sorted(subs)) except: pass @@ -337,7 +329,7 @@ class RawMaterialLibraryDialog(QDialog): """加载原料表格数据""" try: with self.get_conn() as conn: - query = "SELECT category, model, supplier, color, width, gsm, unit, retail_price, bulk_price FROM fabrics" + query = "SELECT category, fabric_type, model, supplier, color, width, gsm, unit, retail_price, bulk_price FROM fabrics" params = [] conditions = [] @@ -346,11 +338,11 @@ class RawMaterialLibraryDialog(QDialog): sub = self.sub_combo.currentText() if major != "全部类目" and major: if sub != "全部类型" and sub: - conditions.append("category = ?") - params.append(major + "-" + sub) + conditions.append("category = ? AND fabric_type = ?") + params.append(major) + params.append(sub) else: - conditions.append("(category LIKE ? OR category = ?)") - params.append(major + "-%") + conditions.append("category = ?") params.append(major) # 供应商过滤 @@ -377,9 +369,9 @@ class RawMaterialLibraryDialog(QDialog): self.table.setRowCount(len(rows)) self.table.clearContents() - for row_idx, (category, model, supplier, color, width, gsm, unit, retail, bulk) in enumerate(rows): - major = category.split('-', 1)[0] if '-' in category else category - sub = category.split('-', 1)[1] if '-' in category else "" + for row_idx, (category, fabric_type, model, supplier, color, width, gsm, unit, retail, bulk) in enumerate(rows): + major = category or "" + sub = fabric_type or "" self.table.setItem(row_idx, 0, QTableWidgetItem(major)) self.table.setItem(row_idx, 1, QTableWidgetItem(sub)) @@ -433,16 +425,16 @@ class RawMaterialLibraryDialog(QDialog): """编辑原料""" try: with self.get_conn() as conn: - cursor = conn.execute("SELECT category, supplier, color, width, gsm, unit, retail_price, bulk_price FROM fabrics WHERE model = ?", (model,)) + cursor = conn.execute("SELECT category, fabric_type, supplier, color, width, gsm, unit, retail_price, bulk_price FROM fabrics WHERE model = ?", (model,)) row = cursor.fetchone() if not row: QMessageBox.warning(self, "提示", "原料不存在或已被删除") return - category, supplier, color, width, gsm, unit, retail, bulk = row + category, fabric_type, supplier, color, width, gsm, unit, retail, bulk = row - major = category.split('-', 1)[0] if '-' in category else category - sub = category.split('-', 1)[1] if '-' in category else "" + major = category or "" + sub = fabric_type or "" self.add_major_category.setCurrentText(major) self.add_sub_category.setText(sub) @@ -493,10 +485,8 @@ class RawMaterialLibraryDialog(QDialog): if "胸杯" in sub: major = "辅料" - if major and sub: - category = major + "-" + sub - else: - category = sub or major + category = major or "" + fabric_type = sub or "" supplier = self.add_supplier.currentText().strip() color = self.add_color.text().strip() @@ -506,9 +496,9 @@ class RawMaterialLibraryDialog(QDialog): with self.get_conn() as conn: conn.execute(''' INSERT OR REPLACE INTO fabrics - (model, category, supplier, color, width, gsm, retail_price, bulk_price, unit, timestamp) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - ''', (model, category, supplier, color, + (model, category, fabric_type, supplier, color, width, gsm, retail_price, bulk_price, unit, timestamp) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ''', (model, category, fabric_type, supplier, color, self.add_width.value() or None, self.add_gsm.value() or None, self.add_retail.value() or None, self.add_bulk.value() or None, unit, datetime.now().strftime('%Y-%m-%d %H:%M:%S')))