更新 Simple_Enterprise_Warehouse_Management.py
This commit is contained in:
		@@ -265,7 +265,7 @@ class InventoryUI:
 | 
				
			|||||||
        page_size_combo.bind("<<ComboboxSelected>>", self.on_page_size_change)
 | 
					        page_size_combo.bind("<<ComboboxSelected>>", self.on_page_size_change)
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        # 统计信息
 | 
					        # 统计信息
 | 
				
			||||||
        self.query_stats_label = tk.Label(bottom_frame, text="总重量: 360.0kg    总价: 11680.00元")
 | 
					        self.query_stats_label = tk.Label(bottom_frame, text="查询结果: 0条记录    净重量: 0.00kg    总价值: 0.00元")
 | 
				
			||||||
        self.query_stats_label.pack(side=tk.RIGHT)
 | 
					        self.query_stats_label.pack(side=tk.RIGHT)
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        # 返回按钮
 | 
					        # 返回按钮
 | 
				
			||||||
@@ -299,8 +299,8 @@ class InventoryUI:
 | 
				
			|||||||
                
 | 
					                
 | 
				
			||||||
                self.product_tree.insert("", tk.END, values=(
 | 
					                self.product_tree.insert("", tk.END, values=(
 | 
				
			||||||
                    product_name,
 | 
					                    product_name,
 | 
				
			||||||
                    f"{weight:.8f}",
 | 
					                    f"{weight:.2f}",
 | 
				
			||||||
                    f"{price:.8f}",
 | 
					                    f"{price:.2f}",
 | 
				
			||||||
                    "详情"
 | 
					                    "详情"
 | 
				
			||||||
                ))
 | 
					                ))
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
@@ -827,6 +827,7 @@ class InventoryUI:
 | 
				
			|||||||
        # 计算全部记录的统计信息
 | 
					        # 计算全部记录的统计信息
 | 
				
			||||||
        all_total_weight = 0
 | 
					        all_total_weight = 0
 | 
				
			||||||
        all_total_value = 0
 | 
					        all_total_value = 0
 | 
				
			||||||
 | 
					        if self.filtered_transactions:  # 只有当有筛选结果时才计算
 | 
				
			||||||
            for transaction in self.filtered_transactions:
 | 
					            for transaction in self.filtered_transactions:
 | 
				
			||||||
                weight = float(transaction["weight"])
 | 
					                weight = float(transaction["weight"])
 | 
				
			||||||
                price = float(transaction["price"])
 | 
					                price = float(transaction["price"])
 | 
				
			||||||
@@ -859,7 +860,7 @@ class InventoryUI:
 | 
				
			|||||||
        try:
 | 
					        try:
 | 
				
			||||||
            self.page_size = int(self.page_size_var.get())
 | 
					            self.page_size = int(self.page_size_var.get())
 | 
				
			||||||
            self.current_page = 1  # 重置到第一页
 | 
					            self.current_page = 1  # 重置到第一页
 | 
				
			||||||
            if hasattr(self, 'filtered_transactions') and self.filtered_transactions:
 | 
					            if hasattr(self, 'filtered_transactions'):
 | 
				
			||||||
                self._display_current_page()
 | 
					                self._display_current_page()
 | 
				
			||||||
        except ValueError:
 | 
					        except ValueError:
 | 
				
			||||||
             pass
 | 
					             pass
 | 
				
			||||||
@@ -972,7 +973,7 @@ class InventoryUI:
 | 
				
			|||||||
        return True
 | 
					        return True
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    def print_query_results(self):
 | 
					    def print_query_results(self):
 | 
				
			||||||
        """打印查询结果"""
 | 
					        """生成HTML文件并用浏览器打开打印"""
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            # 获取当前查询结果
 | 
					            # 获取当前查询结果
 | 
				
			||||||
            results = []
 | 
					            results = []
 | 
				
			||||||
@@ -984,68 +985,184 @@ class InventoryUI:
 | 
				
			|||||||
                messagebox.showwarning("提示", "没有查询结果可以打印")
 | 
					                messagebox.showwarning("提示", "没有查询结果可以打印")
 | 
				
			||||||
                return
 | 
					                return
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            # 创建打印预览窗口
 | 
					            # 生成HTML内容
 | 
				
			||||||
            print_window = tk.Toplevel(self.root)
 | 
					 | 
				
			||||||
            print_window.title("打印预览")
 | 
					 | 
				
			||||||
            print_window.geometry("800x600")
 | 
					 | 
				
			||||||
            print_window.resizable(True, True)
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            # 创建文本框显示打印内容
 | 
					 | 
				
			||||||
            text_frame = tk.Frame(print_window)
 | 
					 | 
				
			||||||
            text_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            text_widget = tk.Text(text_frame, wrap=tk.NONE, font=("Courier", 10))
 | 
					 | 
				
			||||||
            scrollbar_y = tk.Scrollbar(text_frame, orient=tk.VERTICAL, command=text_widget.yview)
 | 
					 | 
				
			||||||
            scrollbar_x = tk.Scrollbar(text_frame, orient=tk.HORIZONTAL, command=text_widget.xview)
 | 
					 | 
				
			||||||
            text_widget.config(yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set)
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            scrollbar_y.pack(side=tk.RIGHT, fill=tk.Y)
 | 
					 | 
				
			||||||
            scrollbar_x.pack(side=tk.BOTTOM, fill=tk.X)
 | 
					 | 
				
			||||||
            text_widget.pack(fill=tk.BOTH, expand=True)
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            # 生成打印内容
 | 
					 | 
				
			||||||
            from datetime import datetime
 | 
					            from datetime import datetime
 | 
				
			||||||
 | 
					            import os
 | 
				
			||||||
 | 
					            import webbrowser
 | 
				
			||||||
 | 
					            import tempfile
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
            current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
 | 
					            current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
 | 
				
			||||||
 | 
					            stats_text = self.query_stats_label.cget("text")
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            print_content = f"""库存管理系统 - 查询结果报表
 | 
					            html_content = f"""<!DOCTYPE html>
 | 
				
			||||||
生成时间: {current_time}
 | 
					<html lang="zh-CN">
 | 
				
			||||||
{'='*80}
 | 
					<head>
 | 
				
			||||||
 | 
					    <meta charset="UTF-8">
 | 
				
			||||||
 | 
					    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
				
			||||||
 | 
					    <title>库存管理系统 - 查询结果报表</title>
 | 
				
			||||||
 | 
					    <style>
 | 
				
			||||||
 | 
					        body {{
 | 
				
			||||||
 | 
					            font-family: 'Microsoft YaHei', Arial, sans-serif;
 | 
				
			||||||
 | 
					            margin: 20px;
 | 
				
			||||||
 | 
					            background-color: #f5f5f5;
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        .container {{
 | 
				
			||||||
 | 
					            max-width: 1200px;
 | 
				
			||||||
 | 
					            margin: 0 auto;
 | 
				
			||||||
 | 
					            background-color: white;
 | 
				
			||||||
 | 
					            padding: 30px;
 | 
				
			||||||
 | 
					            border-radius: 8px;
 | 
				
			||||||
 | 
					            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        .header {{
 | 
				
			||||||
 | 
					            text-align: center;
 | 
				
			||||||
 | 
					            margin-bottom: 30px;
 | 
				
			||||||
 | 
					            border-bottom: 2px solid #4CAF50;
 | 
				
			||||||
 | 
					            padding-bottom: 20px;
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        .header h1 {{
 | 
				
			||||||
 | 
					            color: #2c3e50;
 | 
				
			||||||
 | 
					            margin: 0;
 | 
				
			||||||
 | 
					            font-size: 28px;
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        .header .time {{
 | 
				
			||||||
 | 
					            color: #7f8c8d;
 | 
				
			||||||
 | 
					            margin-top: 10px;
 | 
				
			||||||
 | 
					            font-size: 14px;
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        table {{
 | 
				
			||||||
 | 
					            width: 100%;
 | 
				
			||||||
 | 
					            border-collapse: collapse;
 | 
				
			||||||
 | 
					            margin: 20px 0;
 | 
				
			||||||
 | 
					            font-size: 14px;
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        th, td {{
 | 
				
			||||||
 | 
					            border: 1px solid #ddd;
 | 
				
			||||||
 | 
					            padding: 12px 8px;
 | 
				
			||||||
 | 
					            text-align: center;
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        th {{
 | 
				
			||||||
 | 
					            background-color: #4CAF50;
 | 
				
			||||||
 | 
					            color: white;
 | 
				
			||||||
 | 
					            font-weight: bold;
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        tr:nth-child(even) {{
 | 
				
			||||||
 | 
					            background-color: #f9f9f9;
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        tr:hover {{
 | 
				
			||||||
 | 
					            background-color: #f5f5f5;
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        .inbound {{
 | 
				
			||||||
 | 
					            background-color: #e8f5e8 !important;
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        .outbound {{
 | 
				
			||||||
 | 
					            background-color: #ffe8e8 !important;
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        .stats {{
 | 
				
			||||||
 | 
					            margin-top: 30px;
 | 
				
			||||||
 | 
					            padding: 20px;
 | 
				
			||||||
 | 
					            background-color: #ecf0f1;
 | 
				
			||||||
 | 
					            border-radius: 5px;
 | 
				
			||||||
 | 
					            border-left: 4px solid #3498db;
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        .stats h3 {{
 | 
				
			||||||
 | 
					            margin: 0 0 10px 0;
 | 
				
			||||||
 | 
					            color: #2c3e50;
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        .print-btn {{
 | 
				
			||||||
 | 
					            position: fixed;
 | 
				
			||||||
 | 
					            top: 20px;
 | 
				
			||||||
 | 
					            right: 20px;
 | 
				
			||||||
 | 
					            background-color: #4CAF50;
 | 
				
			||||||
 | 
					            color: white;
 | 
				
			||||||
 | 
					            border: none;
 | 
				
			||||||
 | 
					            padding: 12px 24px;
 | 
				
			||||||
 | 
					            border-radius: 5px;
 | 
				
			||||||
 | 
					            cursor: pointer;
 | 
				
			||||||
 | 
					            font-size: 16px;
 | 
				
			||||||
 | 
					            box-shadow: 0 2px 5px rgba(0,0,0,0.2);
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        .print-btn:hover {{
 | 
				
			||||||
 | 
					            background-color: #45a049;
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        @media print {{
 | 
				
			||||||
 | 
					            body {{
 | 
				
			||||||
 | 
					                background-color: white;
 | 
				
			||||||
 | 
					                margin: 0;
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            .container {{
 | 
				
			||||||
 | 
					                box-shadow: none;
 | 
				
			||||||
 | 
					                margin: 0;
 | 
				
			||||||
 | 
					                padding: 20px;
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            .print-btn {{
 | 
				
			||||||
 | 
					                display: none;
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					    </style>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					    <button class="print-btn" onclick="window.print()">打印</button>
 | 
				
			||||||
 | 
					    <div class="container">
 | 
				
			||||||
 | 
					        <div class="header">
 | 
				
			||||||
 | 
					            <h1>库存管理系统 - 查询结果报表</h1>
 | 
				
			||||||
 | 
					            <div class="time">生成时间: {current_time}</div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        <table>
 | 
				
			||||||
 | 
					            <thead>
 | 
				
			||||||
 | 
					                <tr>
 | 
				
			||||||
 | 
					                    <th>时间</th>
 | 
				
			||||||
 | 
					                    <th>产品名</th>
 | 
				
			||||||
 | 
					                    <th>类型</th>
 | 
				
			||||||
 | 
					                    <th>重量(kg)</th>
 | 
				
			||||||
 | 
					                    <th>价格(元/kg)</th>
 | 
				
			||||||
 | 
					                    <th>总价(元)</th>
 | 
				
			||||||
 | 
					                    <th>备注</th>
 | 
				
			||||||
 | 
					                </tr>
 | 
				
			||||||
 | 
					            </thead>
 | 
				
			||||||
 | 
					            <tbody>"""
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            # 添加数据行
 | 
				
			||||||
 | 
					            for values in results:
 | 
				
			||||||
 | 
					                row_class = "inbound" if values[2] == "入库" else "outbound"
 | 
				
			||||||
 | 
					                html_content += f"""                <tr class="{row_class}">
 | 
				
			||||||
 | 
					                    <td>{values[0]}</td>
 | 
				
			||||||
 | 
					                    <td>{values[1]}</td>
 | 
				
			||||||
 | 
					                    <td>{values[2]}</td>
 | 
				
			||||||
 | 
					                    <td>{values[3]}</td>
 | 
				
			||||||
 | 
					                    <td>{values[4]}</td>
 | 
				
			||||||
 | 
					                    <td>{values[5]}</td>
 | 
				
			||||||
 | 
					                    <td>{values[6]}</td>
 | 
				
			||||||
 | 
					                </tr>
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            # 表头
 | 
					            html_content += f"""            </tbody>
 | 
				
			||||||
            header = f"{'时间':<20} {'产品名':<15} {'类型':<8} {'重量(kg)':<10} {'价格(元/kg)':<12} {'总价(元)':<12} {'备注':<20}"
 | 
					        </table>
 | 
				
			||||||
            print_content += header + "\n"
 | 
					 | 
				
			||||||
            print_content += "-" * 80 + "\n"
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
            # 数据行
 | 
					        <div class="stats">
 | 
				
			||||||
            for values in results:
 | 
					            <h3>统计信息</h3>
 | 
				
			||||||
                line = f"{values[0]:<20} {values[1]:<15} {values[2]:<8} {values[3]:<10} {values[4]:<12} {values[5]:<12} {values[6]:<20}"
 | 
					            <p>{stats_text}</p>
 | 
				
			||||||
                print_content += line + "\n"
 | 
					            <p>记录总数: {len(results)}条</p>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>"""
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            # 统计信息
 | 
					            # 创建HTML文件到软件根目录
 | 
				
			||||||
            stats_text = self.query_stats_label.cget("text")
 | 
					            current_dir = os.path.dirname(os.path.abspath(__file__))
 | 
				
			||||||
            print_content += "\n" + "="*80 + "\n"
 | 
					            html_file = os.path.join(current_dir, f"{datetime.now().strftime('%Y%m%d')}_{len(results)}条.html")
 | 
				
			||||||
            print_content += f"统计信息: {stats_text}\n"
 | 
					 | 
				
			||||||
            print_content += f"记录总数: {len(results)}条\n"
 | 
					 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            text_widget.insert(tk.END, print_content)
 | 
					            with open(html_file, 'w', encoding='utf-8') as f:
 | 
				
			||||||
            text_widget.config(state=tk.DISABLED)
 | 
					                f.write(html_content)
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            # 按钮框架
 | 
					            # 用浏览器打开HTML文件
 | 
				
			||||||
            button_frame = tk.Frame(print_window)
 | 
					            webbrowser.open(f'file:///{html_file.replace(os.sep, "/")}')
 | 
				
			||||||
            button_frame.pack(pady=10)
 | 
					 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            def copy_to_clipboard():
 | 
					            messagebox.showinfo("成功", f"报表已生成并在浏览器中打开\n文件位置: {html_file}")
 | 
				
			||||||
                print_window.clipboard_clear()
 | 
					 | 
				
			||||||
                print_window.clipboard_append(print_content)
 | 
					 | 
				
			||||||
                messagebox.showinfo("成功", "内容已复制到剪贴板")
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            tk.Button(button_frame, text="复制到剪贴板", command=copy_to_clipboard, bg="lightblue").pack(side=tk.LEFT, padx=5)
 | 
					 | 
				
			||||||
            tk.Button(button_frame, text="关闭", command=print_window.destroy).pack(side=tk.LEFT, padx=5)
 | 
					 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
        except Exception as e:
 | 
					        except Exception as e:
 | 
				
			||||||
            messagebox.showerror("错误", f"生成打印预览失败: {str(e)}")
 | 
					            messagebox.showerror("错误", f"生成HTML报表失败: {str(e)}")
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    def run(self):
 | 
					    def run(self):
 | 
				
			||||||
        """运行应用"""
 | 
					        """运行应用"""
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user