From 9894eef859d805ca38359f029211a8c607c358c8 Mon Sep 17 00:00:00 2001 From: spdis Date: Sun, 27 Jul 2025 13:40:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20Simple=5FEnterprise=5FWare?= =?UTF-8?q?house=5FManagement.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Simple_Enterprise_Warehouse_Management.py | 194 ++++++++++++++++++---- 1 file changed, 160 insertions(+), 34 deletions(-) diff --git a/Simple_Enterprise_Warehouse_Management.py b/Simple_Enterprise_Warehouse_Management.py index 74f86b0..f7620d4 100644 --- a/Simple_Enterprise_Warehouse_Management.py +++ b/Simple_Enterprise_Warehouse_Management.py @@ -9,7 +9,7 @@ class InventoryUI: self.root = tk.Tk() self.root.title("出入库管理系统") self.root.geometry("800x600") - self.root.resizable(False, False) + self.root.resizable(True, True) # 初始化库存管理器 self.manager = InventoryManager("inventory_data.json") @@ -51,6 +51,15 @@ class InventoryUI: # 绑定双击事件 self.product_tree.bind("", self.on_product_select) + # 绑定拖拽事件(使用右键拖拽避免与双击冲突) + self.product_tree.bind("", self.on_drag_start) + self.product_tree.bind("", self.on_drag_motion) + self.product_tree.bind("", self.on_drag_end) + + # 拖拽相关变量 + self.drag_item = None + self.drag_start_y = 0 + # 底部统计信息 stats_frame = tk.Frame(self.root) stats_frame.pack(fill=tk.X, padx=10, pady=5) @@ -276,39 +285,7 @@ class InventoryUI: for widget in self.root.winfo_children(): widget.destroy() - def load_products(self): - """加载产品列表""" - try: - with open("inventory_data.json", "r", encoding="utf-8") as f: - data = json.load(f) - - # 清空现有数据 - for item in self.product_tree.get_children(): - self.product_tree.delete(item) - - total_value = 0 - total_weight = 0 - - for product_name, product_data in data["products"].items(): - weight = float(product_data["total_weight"]) - price = float(product_data["avg_price"]) - value = weight * price - - total_weight += weight - total_value += value - - self.product_tree.insert("", tk.END, values=( - product_name, - f"{weight:.2f}", - f"{price:.2f}", - "详情" - )) - - # 更新统计信息 - self.stats_label.config(text=f"库存总价值: {total_value:.2f} 元 库存总重: {total_weight:.2f} kg") - - except Exception as e: - messagebox.showerror("错误", f"加载产品数据失败: {str(e)}") + def load_transactions(self, product_name): """加载指定产品的交易记录""" @@ -1164,6 +1141,155 @@ class InventoryUI: except Exception as e: messagebox.showerror("错误", f"生成HTML报表失败: {str(e)}") + def on_drag_start(self, event): + """开始拖拽(右键)""" + # 获取点击的项目 + item = self.product_tree.identify_row(event.y) + if item: + self.drag_item = item + self.drag_start_y = event.y + # 高亮显示被拖拽的项目 + self.product_tree.selection_set(item) + + def on_drag_motion(self, event): + """拖拽移动""" + if self.drag_item: + # 获取当前鼠标位置的项目 + target_item = self.product_tree.identify_row(event.y) + if target_item and target_item != self.drag_item: + # 高亮显示目标位置 + self.product_tree.selection_set(target_item) + + def on_drag_end(self, event): + """结束拖拽""" + if self.drag_item: + # 获取目标位置 + target_item = self.product_tree.identify_row(event.y) + + if target_item and target_item != self.drag_item: + # 获取产品名称用于确认 + source_values = self.product_tree.item(self.drag_item)["values"] + target_values = self.product_tree.item(target_item)["values"] + source_name = source_values[0] + target_name = target_values[0] + + # 确认移动操作 + if messagebox.askyesno("确认移动", f"是否将 '{source_name}' 移动到 '{target_name}' 的位置?"): + # 执行移动操作 + self.move_product_item(self.drag_item, target_item) + + # 重置拖拽状态 + self.drag_item = None + self.drag_start_y = 0 + + def move_product_item(self, source_item, target_item): + """移动产品项目""" + try: + # 获取源项目和目标项目的信息 + source_values = self.product_tree.item(source_item)["values"] + target_values = self.product_tree.item(target_item)["values"] + + source_product = source_values[0] + target_product = target_values[0] + + # 获取所有项目的顺序 + all_items = [] + for item in self.product_tree.get_children(): + values = self.product_tree.item(item)["values"] + all_items.append(values[0]) # 产品名 + + # 计算新的顺序 + source_index = all_items.index(source_product) + target_index = all_items.index(target_product) + + # 修复移动逻辑:先移除源项目,然后根据调整后的索引插入 + all_items.pop(source_index) + # 如果目标位置在源位置之后,需要调整目标索引 + if target_index > source_index: + target_index -= 1 + all_items.insert(target_index, source_product) + + # 更新JSON文件中的产品顺序 + self.save_product_order(all_items) + + # 重新加载产品列表并刷新界面 + self.load_products() + self.product_tree.update() + self.root.update_idletasks() + + messagebox.showinfo("成功", f"已将 '{source_product}' 移动到 '{target_product}' 的位置") + + except Exception as e: + messagebox.showerror("错误", f"移动产品失败: {str(e)}") + + def save_product_order(self, product_order): + """保存产品顺序到JSON文件""" + try: + with open("inventory_data.json", "r", encoding="utf-8") as f: + data = json.load(f) + + # 创建新的有序产品字典 + old_products = data["products"] + new_products = {} + + # 统一将产品顺序转换为字符串类型 + product_order = [str(item) for item in product_order] + + # 第一步:按顺序添加存在的老产品 + for product_name in product_order: + if product_name in old_products: + new_products[product_name] = old_products[product_name] + + # 第二步:添加顺序列表中没有但存在于老产品中的项目 + for product_name in old_products: + if product_name not in new_products: + new_products[product_name] = old_products[product_name] + + # 更新数据 + data["products"] = new_products + + # 保存文件,确保字典顺序被保持 + with open("inventory_data.json", "w", encoding="utf-8") as f: + json.dump(data, f, indent=2, ensure_ascii=False) + + except Exception as e: + raise Exception(f"保存产品顺序失败: {str(e)}") + + def load_products(self): + """加载产品列表(保持JSON中的顺序)""" + try: + with open("inventory_data.json", "r", encoding="utf-8") as f: + data = json.load(f) + + # 清空现有数据 + for item in self.product_tree.get_children(): + self.product_tree.delete(item) + + total_value = 0 + total_weight = 0 + + # 按照JSON中的顺序加载产品 + for product_name, product_data in data["products"].items(): + weight = float(product_data["total_weight"]) + price = float(product_data["avg_price"]) + value = weight * price + + total_weight += weight + total_value += value + + self.product_tree.insert("", tk.END, values=( + product_name, + f"{weight:.2f}", + f"{price:.2f}", + "详情" + )) + + # 更新统计信息 + self.stats_label.config(text=f"库存总价值: {total_value:.2f} 元 库存总重: {total_weight:.2f} kg") + + except Exception as e: + messagebox.showerror("错误", f"加载产品数据失败: {str(e)}") + def run(self): """运行应用""" self.root.mainloop()