二手拍卖系统-Python tkinter图形化界面+mysql项目实战【附带源码】

二手拍卖系统设计方案【完整版】

​系统概述​
基于Python Tkinter + MySQL的图形化界面二手拍卖系统,提供完整的在线拍卖功能,包括用户注册登录、商品管理、竞拍交易和后台管理。


功能模块详细设计

1. 用户认证模块

1.1 用户注册
  • 首次使用需提供用户名、密码、真实姓名、联系方式等基本信息
  • 密码需加密存储(使用SHA-256哈希+盐值)
  • 用户名唯一性验证
  • 邮箱/手机号验证(可选)
1.2 用户登录
  • 使用注册的用户名和密码登录
  • 内置管理员账号:admin/admin123
  • 登录失败次数限制(3次失败后锁定账户15分钟)
  • 记住登录状态(Cookie/Session机制)

2. 商品管理模块

2.1 商品操作
  • ​发布商品​​:上传商品图片、填写标题、描述、起拍价、拍卖截止时间
  • ​编辑商品​​:修改未开始拍卖的商品信息
  • ​下架商品​​:手动结束拍卖或标记为已售出
  • ​商品分类​​:支持多级分类(如电子产品、服装、家居等)
2.2 商品状态管理
  • 上架/下架状态
  • 拍卖中/已结束/已售出状态
  • 违规商品标记(如虚假描述)

3. 拍卖交易模块

3.1 竞拍功能
  • 出价功能:用户可对拍卖中的商品出价
  • 自动出价代理:设置最高限价,系统自动出价
  • 出价记录:实时显示当前最高出价和出价人
  • 拍卖倒计时:显示剩余拍卖时间
3.2 交易流程
  • ​保证金​​:竞拍前需支付保证金(可配置比例)
  • ​成交确认​​:拍卖结束后自动确认最高出价者
  • ​支付​​:支持模拟支付(或集成第三方支付接口)
  • ​发货/收货​​:买卖双方确认交易状态
  • ​评价​​:交易完成后双方互评

4. 查询功能模块

4.1 商品查询
  • 按关键词搜索
  • 按分类筛选
  • 按价格区间筛选
  • 按拍卖状态筛选(进行中/即将开始/已结束)
4.2 订单查询
  • 我的竞拍记录
  • 我的购买记录
  • 我的销售记录
  • 交易状态筛选
4.3 管理员查询
  • 查看所有用户
  • 查看所有商品
  • 查看所有交易记录
  • 异常交易监控

5. 个人信息管理

  • 查看和修改个人信息
  • 修改登录密码(需验证原密码)
  • 绑定/解绑支付方式(模拟)
  • 查看个人信用评分

6. 管理员功能模块

6.1 用户管理
  • 添加新用户
  • 编辑用户信息
  • 删除用户(需确认)
  • 用户封禁/解封
6.2 商品管理
  • 查看所有商品
  • 强制下架违规商品
  • 商品审核(防止虚假信息)
6.3 交易管理
  • 查看所有交易记录
  • 处理交易纠纷
  • 生成交易报表
6.4 系统管理
  • 系统参数配置(如佣金比例、保证金比例)
  • 公告管理
  • 统计报表
    • 用户活跃度分析
    • 商品交易量统计
    • 收入统计

二手拍卖系统功能界面:

 数据库添加数据:auctionSystem.sql


CREATE DATABASE IF NOT EXISTS auction_system;
USE auction_system;

-- 用户表
CREATE TABLE users (
    user_id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL UNIQUE,
    password VARCHAR(100) NOT NULL,
    email VARCHAR(100) NOT NULL UNIQUE,
    phone VARCHAR(20),
    address TEXT,
    is_admin BOOLEAN DEFAULT FALSE,
    last_login VARCHAR(100) NOT NULL UNIQUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 商品表
CREATE TABLE products (
    product_id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    description TEXT,
    category VARCHAR(50),
    base_price DECIMAL(10, 2) NOT NULL,
    current_price DECIMAL(10, 2) NOT NULL,
    price DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT '商品价格',
    start_time DATETIME NOT NULL,
    end_time DATETIME NOT NULL,
    status ENUM('pending', 'active', 'sold', 'expired') DEFAULT 'pending',
    seller_id INT NOT NULL,
    image_path VARCHAR(255),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (seller_id) REFERENCES users(user_id)
);

-- 订单表
CREATE TABLE orders (
    order_id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    total_amount DECIMAL(10,2) NOT NULL,
    product_id INT NOT NULL,
    buyer_id INT NOT NULL,
    price DECIMAL(10, 2) NOT NULL,
    current_price DECIMAL(10, 2) NOT NULL,
    status ENUM('pending', 'paid', 'shipped', 'completed', 'cancelled') DEFAULT 'pending',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    payment_time TIMESTAMP NULL DEFAULT NULL COMMENT '支付时间',
    shipping_time  TIMESTAMP NULL DEFAULT NULL COMMENT '订单完成时间',
    completion_time TIMESTAMP NULL DEFAULT NULL COMMENT '订单完成时间',
    FOREIGN KEY (product_id) REFERENCES products(product_id),
    FOREIGN KEY (buyer_id) REFERENCES users(user_id)
);

-- 创建订单商品表
CREATE TABLE IF NOT EXISTS order_items (
    item_id INT AUTO_INCREMENT PRIMARY KEY,
    order_id INT NOT NULL,
    product_id INT NOT NULL,
    quantity INT NOT NULL DEFAULT 1,
    price DECIMAL(10,2) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (order_id) REFERENCES orders(order_id),
    FOREIGN KEY (product_id) REFERENCES products(product_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 竞拍记录表
CREATE TABLE bids (
    bid_id INT AUTO_INCREMENT PRIMARY KEY,
    product_id INT NOT NULL,
    user_id INT NOT NULL,
    amount DECIMAL(10, 2) NOT NULL,
    bid_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (product_id) REFERENCES products(product_id),
    FOREIGN KEY (user_id) REFERENCES users(user_id)
);


CREATE TABLE login_attempts (
    attempt_id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    attempt_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    success BOOLEAN NOT NULL
);

数据库连接模块: db.py

# db.py
import pymysql
from pymysql.cursors import DictCursor


class Database:
    def __init__(self):
        self.connection = pymysql.connect(
            host='localhost',
            user='root',         #换成你的数据库用户
            password='123456',   #换成你的数据库密码
            database='auction_system',
            charset='utf8mb4',
            cursorclass=DictCursor
        )

    def execute_query(self, query, params=None, fetch_one=False):
        """
        执行SQL查询
        :param query: SQL语句
        :param params: 查询参数(tuple/list/dict)
        :param fetch_one: 是否只获取一条记录
        :return: 查询结果
        """
        with self.connection.cursor() as cursor:
            cursor.execute(query, params or ())
            result = cursor.fetchone() if fetch_one else cursor.fetchall()
            self.connection.commit()
            return result

    def close(self):
        """关闭数据库连接"""
        if hasattr(self, 'connection'):
            self.connection.close()


# 创建全局数据库实例
db = Database()

登录模块:login.py

from db import db  # 直接使用db.execute_query()

import tkinter as tk
from tkinter import messagebox
import ttkbootstrap as tb
from ttkbootstrap.constants import *
import hashlib


class LoginWindow:
    def __init__(self, root, app):
        self.root = root
        self.app = app
        
        self.create_widgets()
    
    def create_widgets(self):
        # 主框架
        main_frame = tb.Frame(self.root)
        main_frame.pack(expand=True, fill='both', padx=50, pady=50)
        
        # 标题
        title_label = tb.Label(
            main_frame,
            text="\n\n\n\n用户登录系统",
            font=('Helvetica', 25, 'bold'),
            bootstyle=PRIMARY
        )
        title_label.pack(pady=20)
        
        # 登录表单框架
        form_frame = tb.Frame(main_frame)
        form_frame.pack(pady=20)
        
        # 用户名
        tb.Label(form_frame, text="用户名:", bootstyle=PRIMARY).grid(row=1, column=1, padx=5, pady=5, sticky='e')
        self.username_entry = tb.Entry(form_frame, bootstyle=PRIMARY)
        self.username_entry.grid(row=1, column=2, padx=5, pady=5)
        
        # 密码
        tb.Label(form_frame, text="密码:", bootstyle=PRIMARY).grid(row=2, column=1, padx=5, pady=5, sticky='e')
        self.password_entry = tb.Entry(form_frame, show="*", bootstyle=PRIMARY)
        self.password_entry.grid(row=2, column=2, padx=5, pady=5)
        
        # 登录按钮
        login_btn = tb.Button(
            main_frame,
            text=" 登   录 ",
            bootstyle=SUCCESS,
            command=self.login
        )
        login_btn.pack(pady=10)
        

        # 版权信息
        tb.Label(
            main_frame,
            text="\n\n     海南平安网络科技有限公司 \n\n版权所有©郭平安 二手拍卖系统 v1.0",
            bootstyle="secondary",
            font=('TkDefaultFont', 10)
        ).pack(side='bottom', pady=20)

        # 注册链接(兼容实现)
        self._create_register_link(main_frame)

    def _create_register_link(self, parent):
        """创建注册链接(兼容所有版本)"""
        link_frame = tb.Frame(parent)
        link_frame.pack()
    
        tb.Label(link_frame, text="没有账号?").pack(side='left')
    
        register_link = tb.Label(
            link_frame,
            text="立即注册",
            foreground="#1a73e8",  # 蓝色
            font=('TkDefaultFont', 10, 'underline'),
            cursor="hand2"
        )
        register_link.pack(side='left', padx=5)
    
        # 事件绑定
        register_link.bind("<Button-1>", lambda e: self.app.show_register())
    
        # 悬停效果
        register_link.bind("<Enter>", lambda e: register_link.config(foreground="#0d47a1"))
        register_link.bind("<Leave>", lambda e: register_link.config(foreground="#1a73e8"))

    def login(self):
        username = self.username_entry.get()
        password = self.password_entry.get()

        if not username or not password:
            messagebox.showerror("错误", "用户名和密码不能为空!")
            return

        query = "SELECT * FROM users WHERE username = %s AND password = %s"
        user = db.execute_query(query, (username, password), fetch_one=True)

        if user:
            self.app.current_user = user
            if user['is_admin']:
                self.app.show_admin_dashboard()
            else:
                self.app.show_user_dashboard()
        else:
            messagebox.showerror("错误", "用户名或密码错误!")

注册模块:register.py


from db import db  # 直接使用db.execute_query()

import tkinter as tk
from tkinter import messagebox
import ttkbootstrap as tb
from ttkbootstrap.constants import *


class RegisterWindow:
    def __init__(self, root, app):
        self.root = root
        self.app = app
        
        self.create_widgets()
    
    def create_widgets(self):
        # 主框架
        main_frame = tb.Frame(self.root)
        main_frame.pack(expand=True, fill='both', padx=50, pady=50)
        
        # 标题
        title_label = tb.Label(
            main_frame,
            text="\n\n\n用户注册系统",
            font=('Helvetica', 20, 'bold'),
            bootstyle=PRIMARY
        )
        title_label.pack(pady=20)
        
        # 注册表单框架
        form_frame = tb.Frame(main_frame)
        form_frame.pack(pady=20)
        
        # 用户名
        tb.Label(form_frame, text="用户名:", bootstyle=PRIMARY).grid(row=0, column=0, padx=5, pady=5, sticky='e')
        self.username_entry = tb.Entry(form_frame, bootstyle=PRIMARY)
        self.username_entry.grid(row=0, column=1, padx=5, pady=5)
        
        # 密码
        tb.Label(form_frame, text="密码:", bootstyle=PRIMARY).grid(row=1, column=0, padx=5, pady=5, sticky='e')
        self.password_entry = tb.Entry(form_frame, show="*", bootstyle=PRIMARY)
        self.password_entry.grid(row=1, column=1, padx=5, pady=5)
        
        # 确认密码
        tb.Label(form_frame, text="确认密码:", bootstyle=PRIMARY).grid(row=2, column=0, padx=5, pady=5, sticky='e')
        self.confirm_password_entry = tb.Entry(form_frame, show="*", bootstyle=PRIMARY)
        self.confirm_password_entry.grid(row=2, column=1, padx=5, pady=5)
        
        # 邮箱
        tb.Label(form_frame, text="邮箱:", bootstyle=PRIMARY).grid(row=3, column=0, padx=5, pady=5, sticky='e')
        self.email_entry = tb.Entry(form_frame, bootstyle=PRIMARY)
        self.email_entry.grid(row=3, column=1, padx=5, pady=5)
        
        # 电话
        tb.Label(form_frame, text="电话:", bootstyle=PRIMARY).grid(row=4, column=0, padx=5, pady=5, sticky='e')
        self.phone_entry = tb.Entry(form_frame, bootstyle=PRIMARY)
        self.phone_entry.grid(row=4, column=1, padx=5, pady=5)
        
        # 地址
        tb.Label(form_frame, text="地址:", bootstyle=PRIMARY).grid(row=5, column=0, padx=5, pady=5, sticky='e')
        self.address_entry = tb.Entry(form_frame, bootstyle=PRIMARY)
        self.address_entry.grid(row=5, column=1, padx=5, pady=5)
        
        # 注册按钮
        register_btn = tb.Button(
            main_frame,
            text="  注    册  ",
            bootstyle=SUCCESS,
            command=self.register
        )
        register_btn.pack(pady=10)

        # 版权信息
        tb.Label(
            main_frame,
            text="\n\n     海南平安网络科技有限公司 \n\n版权所有©郭平安 二手拍卖系统 v1.0",
            bootstyle="secondary",
            font=('TkDefaultFont', 10)
        ).pack(side='bottom', pady=20)

        # 登录链接(兼容实现)
        self._create_login_link(main_frame)

    def _create_login_link(self, parent):
        """创建注册链接(兼容所有版本)"""
        link_frame = tb.Frame(parent)
        link_frame.pack()
    
        tb.Label(link_frame, text="已有帐号?").pack(side='left')
    
        login_link = tb.Label(
            link_frame,
            text="直接登录",
            foreground="#1a73e8",  # 蓝色
            font=('TkDefaultFont', 10, 'underline'),
            cursor="hand2"
        )
        login_link.pack(side='left', padx=5)
    
        # 事件绑定
        login_link.bind("<Button-1>", lambda e: self.app.show_login())
    
        # 悬停效果
        login_link.bind("<Enter>", lambda e: login_link.config(foreground="#0d47a1"))
        login_link.bind("<Leave>", lambda e: login_link.config(foreground="#1a73e8"))
        
    
    def register(self):
        username = self.username_entry.get()
        password = self.password_entry.get()
        confirm_password = self.confirm_password_entry.get()
        email = self.email_entry.get()
        phone = self.phone_entry.get()
        address = self.address_entry.get()
        
        if not username or not password or not confirm_password or not email:
            messagebox.showerror("错误", "必填字段不能为空")
            return
        
        if password != confirm_password:
            messagebox.showerror("错误", "两次输入的密码不一致")
            return
        
        # 检查用户名是否已存在
        query = "SELECT * FROM users WHERE username = %s"
        if db.execute_query(query, (username,), fetch_one=True):
            messagebox.showerror("错误", "用户名已存在")
            return
        
        # 检查邮箱是否已存在
        query = "SELECT * FROM users WHERE email = %s"
        if db.execute_query(query, (email,), fetch_one=True):
            messagebox.showerror("错误", "邮箱已被注册")
            return
        
        # 插入新用户
        query = """
        INSERT INTO users (username, password, email, phone, address, is_admin)
        VALUES (%s, %s, %s, %s, %s, %s)
        """
        db.execute_query(query, (username, password, email, phone, address, False))
        
        messagebox.showinfo("成功", "注册成功!请登录")
        self.app.show_login()

用户模块:user.py

from typing import List, Dict

from distlib import logger
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

import db
import pit

""""用户界面"""

import tkinter as tk
from tkinter import messagebox, ttk, filedialog
import ttkbootstrap as tb
from ttkbootstrap.constants import *
from datetime import datetime, timedelta
from PIL import Image, ImageTk
import os
from datetime import datetime, timedelta  # 添加timedelta导入
from db import db  # 从db模块导入db实例
from pytz import timezone  # 需要安装:pip install pytz
from tkcalendar import DateEntry  # 需要安装:pip install tkcalendar
import logging

logging.basicConfig(filename='app.log', level=logging.INFO)


class UserDashboard:
    def __init__(self, root, app):
        self.root = root
        self.app = app
        self.current_user = app.current_user
        
        self.create_widgets()
        self.load_products()
        self.load_my_products()
        self.load_my_orders()
        self.load_my_bids()

    def load_users(self):
        """加载用户数据"""
        try:
            query = "SELECT user_id, username, email, is_admin FROM users"
            users = db.execute_query(query)  # 使用全局db实例
        
            # 清空现有数据
            for item in self.user_tree.get_children():
                self.user_tree.delete(item)
        
            # 添加新数据
            for user in users:
                self.user_tree.insert('', 'end', values=(
                    user['user_id'],
                    user['username'],
                    user['email'],
                    '是' if user['is_admin'] else '否'
                ))
        except Exception as e:
            messagebox.showerror("数据库错误", f"加载用户失败: {str(e)}!")

    def place_bid(self):
        """处理用户出价逻辑"""
        selected_item = self.product_tree.selection()
        if not selected_item:
            messagebox.showwarning("警告", "请先选择一个商品!")
            return
    
        # 获取选中商品信息
        item = self.product_tree.item(selected_item[0])
        product_id = item['values'][0]
        current_price = float(item['values'][3].replace('¥', ''))
    
        # 创建出价对话框
        bid_window = tb.Toplevel(self.root)
        bid_window.title("出价")

        # 主窗口居中
        self.width = 500
        self.height = 400

        # 获取窗口屏幕尺寸参数
        self.screenwidth = self.root.winfo_screenwidth()
        self.screenheight = self.root.winfo_screenheight()
        self.screen_geo = "%dx%d+%d+%d" % (
        self.width, self.height, (self.screenwidth - self.width) / 2, (self.screenheight - self.height) / 2)

        bid_window.geometry(self.screen_geo)

        # 设置主窗口不可拉伸
        bid_window.resizable(False, False)
        # bid_window.geometry("300x200")
    
        # 当前价格显示
        tb.Label(
            bid_window,
            text=f"当前价格: ¥{current_price:.2f}",
            font=('Helvetica', 12)
        ).pack(pady=10)
    
        # 出价输入框
        bid_frame = tb.Frame(bid_window)
        bid_frame.pack(pady=10)
    
        tb.Label(bid_frame, text="您的出价:").pack(side='left')
        self.bid_amount_entry = tb.Entry(bid_frame)
        self.bid_amount_entry.pack(side='left', padx=5)
        tb.Label(bid_frame, text="元").pack(side='left')
    
        # 出价按钮
        tb.Button(
            bid_window,
            text="确认出价",
            bootstyle=SUCCESS,
            command=lambda: self._submit_bid(product_id, current_price, bid_window)
        ).pack(pady=20)

    def _submit_bid(self, product_id, current_price, window):
        """提交出价到数据库"""
        try:
            bid_amount = float(self.bid_amount_entry.get())
            if bid_amount <= current_price:
                messagebox.showerror("错误", "出价必须高于当前价格!")
                return
        
            # 执行数据库操作
            db.execute_query(
                "UPDATE products SET current_price = %s WHERE product_id = %s",
                (bid_amount, product_id)
            )
        
            # 记录竞拍记录
            db.execute_query(
                "INSERT INTO bids (product_id, user_id, amount) VALUES (%s, %s, %s)",
                (product_id, self.current_user['user_id'], bid_amount)
            )
        
            messagebox.showinfo("成功", "出价成功!")
            window.destroy()
            self.load_products()  # 刷新商品列表
        except ValueError:
            messagebox.showerror("错误", "请输入有效的金额!")
        except Exception as e:
            messagebox.showerror("数据库错误", f"出价失败: {str(e)}!")
    
    
    def create_widgets(self):
        # 主框架
        self.main_frame = tb.Frame(self.root)
        self.main_frame.pack(fill='both', expand=True)
        
        # 侧边栏
        self.sidebar = tb.Frame(self.main_frame, bootstyle=SECONDARY, width=200)
        self.sidebar.pack(side='left', fill='y')
        
        # 顶部栏
        self.topbar = tb.Frame(self.main_frame, bootstyle=PRIMARY, height=50)
        self.topbar.pack(side='top', fill='x')
        
        # 内容区域
        self.content = tb.Frame(self.main_frame)
        self.content.pack(side='right', fill='both', expand=True)
        
        # 侧边栏内容
        tb.Label(
            self.sidebar,
            text="用户面板",
            font=('Helvetica', 12, 'bold'),
            bootstyle=INVERSE
        ).pack(pady=20)
        
        # 导航按钮
        nav_buttons = [
            ("浏览商品", self.show_products),
            ("我的商品", self.show_my_products),
            ("我的订单", self.show_my_orders),
            ("我的竞拍", self.show_my_bids),
            ("发布商品", self.show_add_product),
            ("账户设置", self.show_account_settings),
            ("退出登录", self.logout)
        ]
        
        for text, command in nav_buttons:
            btn = tb.Button(
                self.sidebar,
                text=text,
                bootstyle=(OUTLINE, LIGHT),
                command=command
            )
            btn.pack(fill='x', padx=10, pady=5)
        
        # 顶部栏内容
        tb.Label(
            self.topbar,
            text=f"欢迎, {self.current_user['username']}",
            font=('Helvetica', 12),
            bootstyle=INVERSE
        ).pack(side='left', padx=20)
        
        # 默认显示商品浏览
        self.show_products()
    
    def show_products(self):
        self.clear_content()

        # 操作按钮框架
        button_frame = tb.Frame(self.content)
        button_frame.pack(pady=10)

        tb.Button(
            button_frame,
            text="出价",
            bootstyle=SUCCESS,
            command=self.place_bid  # 确保使用正确的方法名
        ).pack(side='left', padx=5)
        
        
        # 商品浏览标题
        tb.Label(
            self.content,
            text="浏览商品",
            font=('Helvetica', 16, 'bold'),
            bootstyle=PRIMARY
        ).pack(pady=10)
        
        # 搜索框
        search_frame = tb.Frame(self.content)
        search_frame.pack(fill='x', padx=10, pady=5)
        
        self.product_search_entry = tb.Entry(search_frame, bootstyle=PRIMARY)
        self.product_search_entry.pack(side='left', padx=5, expand=True, fill='x')
        
        tb.Button(
            search_frame,
            text="搜索",
            bootstyle=INFO,
            command=self.search_products
        ).pack(side='left', padx=5)
        
        # 类别筛选
        category_frame = tb.Frame(self.content)
        category_frame.pack(fill='x', padx=10, pady=5)
        
        tb.Label(category_frame, text="类别:", bootstyle=PRIMARY).pack(side='left', padx=5)
        
        self.category_combobox = tb.Combobox(
            category_frame,
            values=['全部', '电子产品', '家居用品', '服装', '书籍', '其他']
        )
        self.category_combobox.pack(side='left', padx=5)
        self.category_combobox.set('全部')
        
        tb.Button(
            category_frame,
            text="筛选",
            bootstyle=INFO,
            command=self.filter_products
        ).pack(side='left', padx=5)
        
        # 商品表格
        columns = ('id', 'name', 'category', 'current_price', 'status', 'seller', 'end_time')
        self.product_tree = ttk.Treeview(
            self.content,
            columns=columns,
            show='headings',
            height=15
        )
        
        # 设置列
        self.product_tree.heading('id', text='ID', anchor='center')
        self.product_tree.heading('name', text='商品名称', anchor='center')
        self.product_tree.heading('category', text='类别', anchor='center')
        self.product_tree.heading('current_price', text='当前价', anchor='center')
        self.product_tree.heading('status', text='状态', anchor='center')
        self.product_tree.heading('seller', text='卖家', anchor='center')
        self.product_tree.heading('end_time', text='结束时间', anchor='center')
        
        # 设置列宽
        self.product_tree.column('id', width=50, anchor='center')
        self.product_tree.column('name', width=120, anchor='center')
        self.product_tree.column('category', width=80, anchor='center')
        self.product_tree.column('current_price', width=80, anchor='center')
        self.product_tree.column('status', width=80, anchor='center')
        self.product_tree.column('seller', width=100, anchor='center')
        self.product_tree.column('end_time', width=120, anchor='center')
        
        self.product_tree.pack(fill='both', expand=True, padx=10, pady=5)
        
        # 操作按钮
        button_frame = tb.Frame(self.content)
        button_frame.pack(pady=10)
        
        tb.Button(
            button_frame,
            text="查看详情",
            bootstyle=INFO,
            command=self.view_product_details
        ).pack(side='left', padx=5)
        
        tb.Button(
            button_frame,
            text="参与竞拍",
            bootstyle=SUCCESS,
            command=self.place_bid
        ).pack(side='left', padx=5)
    
    def show_my_products(self):
        self.clear_content()
        
        # 我的商品标题
        tb.Label(
            self.content,
            text="我的商品",
            font=('Helvetica', 16, 'bold'),
            bootstyle=PRIMARY
        ).pack(pady=10)
        
        # 我的商品表格
        columns = ('id', 'name', 'category', 'current_price', 'status', 'start_time', 'end_time')
        self.my_product_tree = ttk.Treeview(
            self.content,
            columns=columns,
            show='headings',
            height=15
        )
        
        # 设置列
        self.my_product_tree.heading('id', text='ID', anchor='center')
        self.my_product_tree.heading('name', text='商品名称', anchor='center')
        self.my_product_tree.heading('category', text='类别', anchor='center')
        self.my_product_tree.heading('current_price', text='当前价', anchor='center')
        self.my_product_tree.heading('status', text='状态', anchor='center')
        self.my_product_tree.heading('start_time', text=' 开始时间 ', anchor='center')
        self.my_product_tree.heading('end_time', text=' 结束时间 ')
        
        # 设置列宽
        self.my_product_tree.column('id', width=50, anchor='center')
        self.my_product_tree.column('name', width=120, anchor='center')
        self.my_product_tree.column('category', width=80, anchor='center')
        self.my_product_tree.column('current_price', width=80, anchor='center')
        self.my_product_tree.column('status', width=80, anchor='center')
        self.my_product_tree.column('start_time', width=120, anchor='center')
        self.my_product_tree.column('end_time', width=120, anchor='center')
        
        self.my_product_tree.pack(fill='both', expand=True, padx=10, pady=5)
        
        # 操作按钮
        button_frame = tb.Frame(self.content)
        button_frame.pack(pady=10)

        # 在 show_my_products 方法中确保这样绑定
        tb.Button(
            button_frame,
            text="查看详情",
            bootstyle=INFO,
            command=self.view_my_product_details  # 确保方法名一致
        ).pack(side='left', padx=5)
        
        tb.Button(
            button_frame,
            text="编辑商品",
            bootstyle=WARNING,
            command=self.edit_product
        ).pack(side='left', padx=5)
        
        tb.Button(
            button_frame,
            text="删除商品",
            bootstyle=DANGER,
            command=self.delete_product
        ).pack(side='left', padx=5)
        
        # 加载我的商品数据
        self.load_my_products()
        
        
    #删除商品
    def delete_product(self):
        """删除选中的商品"""
        selected_item = self.my_product_tree.selection()
        if not selected_item:
            messagebox.showwarning("警告", "请先选择一个商品!")
            return
    
        # 获取选中商品信息
        item = self.my_product_tree.item(selected_item[0])
        product_id = item['values'][0]
        product_name = item['values'][1]
    
        # 确认对话框
        if not messagebox.askyesno(
                "确认删除",
                f"确定要删除商品 [{product_name}] 吗?\n此操作不可撤销!"
        ):
            return
    
        try:
            # 检查商品状态
            product = db.execute_query(
                "SELECT status FROM products WHERE product_id = %s ORDER BY product_id"
                (product_id,),
                fetch_one=True
            )
        
            if not product:
                raise ValueError("商品不存在!")
        
            if product['status'] == 'sold':
                raise ValueError("已售出商品不能删除!")
        
            # 执行删除操作
            db.execute_query(
                "DELETE FROM products WHERE product_id = %s",
                (product_id,)
            )
        
            # 删除关联的竞拍记录
            db.execute_query(
                "DELETE FROM bids WHERE product_id = %s",
                (product_id,)
            )
        
            messagebox.showinfo("成功", "商品已删除!")
            self.load_my_products()  # 刷新商品列表
        except Exception as e:
            messagebox.showerror("删除失败!", str(e))
        
        
    #编辑商品
    def edit_product(self):
        """编辑选中的商品"""
        selected_item = self.my_product_tree.selection()
        if not selected_item:
            messagebox.showwarning("警告", "请先选择一个商品!")
            return
    
        # 获取选中商品ID
        item = self.my_product_tree.item(selected_item[0])
        product_id = item['values'][0]
    
        # 查询商品详细信息
        product = db.execute_query(
            "SELECT * FROM products WHERE product_id = %s",
            (product_id,),
            fetch_one=True
        )
    
        if not product:
            messagebox.showerror("错误", "未找到商品信息!")
            return
    
        # 创建编辑窗口
        self.edit_window = tb.Toplevel(self.root)
        self.edit_window.title("编辑商品")

        # 主窗口居中
        self.width = 800
        self.height = 800

        # 获取窗口屏幕尺寸参数
        self.screenwidth = self.root.winfo_screenwidth()
        self.screenheight = self.root.winfo_screenheight()
        self.screen_geo = "%dx%d+%d+%d" % (self.width, self.height, (self.screenwidth - self.width) / 2, (self.screenheight - self.height) / 2)

        self.edit_window.geometry(self.screen_geo)

        # 设置主窗口不可拉伸
        self.edit_window.resizable(False, False)
        # self.edit_window.geometry("600x700")
    
        # 表单框架
        form_frame = tb.Frame(self.edit_window)
        form_frame.pack(pady=20, padx=30, fill='both', expand=True)
    
        # 商品名称
        tb.Label(form_frame, text="商品名称:").grid(row=0, column=0, padx=5, pady=5, sticky='e')
        self.edit_name_entry = tb.Entry(form_frame)
        self.edit_name_entry.grid(row=0, column=1, padx=5, pady=5, sticky='ew')
        self.edit_name_entry.insert(0, product['name'])
    
        # 商品描述
        tb.Label(form_frame, text="商品描述:").grid(row=1, column=0, padx=5, pady=5, sticky='ne')
        self.edit_desc_text = tk.Text(form_frame, height=5, width=30)
        self.edit_desc_text.grid(row=1, column=1, padx=5, pady=5, sticky='ew')
        self.edit_desc_text.insert('1.0', product['description'])
    
        # 商品类别
        tb.Label(form_frame, text="商品类别:").grid(row=2, column=0, padx=5, pady=5, sticky='e')
        self.edit_category_combobox = tb.Combobox(
            form_frame,
            values=['电子产品', '家居用品', '服装', '书籍', '其他']
        )
        self.edit_category_combobox.grid(row=2, column=1, padx=5, pady=5, sticky='ew')
        self.edit_category_combobox.set(product['category'])
    
        # 起拍价
        tb.Label(form_frame, text="起拍价:").grid(row=3, column=0, padx=5, pady=5, sticky='e')
        self.edit_base_price_entry = tb.Entry(form_frame)
        self.edit_base_price_entry.grid(row=3, column=1, padx=5, pady=5, sticky='ew')
        self.edit_base_price_entry.insert(0, str(product['base_price']))
    
        # 结束时间
        tb.Label(form_frame, text="结束时间:").grid(row=4, column=0, padx=5, pady=5, sticky='e')
        self.edit_end_time_entry = tb.Entry(form_frame)
        self.edit_end_time_entry.grid(row=4, column=1, padx=5, pady=5, sticky='ew')
        self.edit_end_time_entry.insert(0, product['end_time'].strftime('%Y-%m-%d %H:%M:%S'))
    
        # 商品图片
        tb.Label(form_frame, text="商品图片:").grid(row=5, column=0, padx=5, pady=5, sticky='e')
        self.edit_image_path_entry = tb.Entry(form_frame)
        self.edit_image_path_entry.grid(row=5, column=1, padx=5, pady=5, sticky='ew')
        self.edit_image_path_entry.insert(0, product['image_path'] or "")
    
        tb.Button(
            form_frame,
            text="选择图片",
            bootstyle=INFO,
            command=self._select_edit_image
        ).grid(row=5, column=2, padx=5, pady=5)
    
        # 图片预览
        self.edit_image_preview = tb.Label(form_frame)
        self.edit_image_preview.grid(row=6, column=1, pady=5)
        if product['image_path']:
            self._show_image_preview(product['image_path'], self.edit_image_preview)
    
        # 按钮框架
        button_frame = tb.Frame(self.edit_window)
        button_frame.pack(pady=20)
    
        # 保存按钮
        tb.Button(
            button_frame,
            text="保存修改",
            bootstyle=SUCCESS,
            command=lambda: self._save_product_changes(product_id)
        ).pack(side='left', padx=10)
    
        # 取消按钮
        tb.Button(
            button_frame,
            text="取消",
            bootstyle=DANGER,
            command=self.edit_window.destroy
        ).pack(side='left', padx=10)

    def _select_edit_image(self):
        """选择新的商品图片"""
        file_path = filedialog.askopenfilename(
            title="选择商品图片",
            filetypes=[("Image Files", "*.png *.jpg *.jpeg")]
        )
        if file_path:
            self.edit_image_path_entry.delete(0, tk.END)
            self.edit_image_path_entry.insert(0, file_path)
            self._show_image_preview(file_path, self.edit_image_preview)

    def _show_image_preview(self, image_path, label_widget):
        """显示图片预览"""
        try:
            from PIL import Image, ImageTk
            image = Image.open(image_path)
            image.thumbnail((200, 200))
            photo = ImageTk.PhotoImage(image)
        
            label_widget.config(image=photo)
            label_widget.image = photo  # 保持引用
        except Exception as e:
            messagebox.showerror("错误", f"无法加载图片: {str(e)}")

    def _save_product_changes(self, product_id):
        """保存商品修改到数据库"""
        try:
            # 获取表单数据
            name = self.edit_name_entry.get()
            description = self.edit_desc_text.get("1.0", tk.END).strip()
            category = self.edit_category_combobox.get()
            base_price = float(self.edit_base_price_entry.get())
            end_time = self.edit_end_time_entry.get()
            image_path = self.edit_image_path_entry.get()
        
            # 数据验证
            if not all([name, description, category, base_price > 0]):
                raise ValueError("必填字段不能为空且价格必须大于0")
        
            # 更新数据库
            query = """
            UPDATE products
            SET name = %s,
                description = %s,
                category = %s,
                base_price = %s,
                end_time = %s,
                image_path = %s
            WHERE product_id = %s
            ORDER BY product_id
            """
            db.execute_query(
                query,
                (name, description, category, base_price, end_time, image_path, product_id)
            )
        
            messagebox.showinfo("成功", "商品信息已更新")
            self.edit_window.destroy()
            self.load_my_products()  # 刷新商品列表
        except ValueError as e:
            messagebox.showerror("输入错误", str(e))
        except Exception as e:
            messagebox.showerror("数据库错误", f"更新失败: {str(e)}")

    
    """我的竞拍界面"""
    
    def show_my_bids(self):
        self.clear_content()
        
        # 我的竞拍标题
        tb.Label(
            self.content,
            text="我的竞拍",
            font=('Helvetica', 16, 'bold'),
            bootstyle=PRIMARY
        ).pack(pady=10)
        
        # 我的竞拍表格
        columns = ('id', 'product', 'amount', 'bid_time', 'status')
        self.my_bid_tree = ttk.Treeview(
            self.content,
            columns=columns,
            show='headings',
            height=15
        )
        
        # 设置列
        self.my_bid_tree.heading('id', text='ID', anchor='center')
        self.my_bid_tree.heading('product', text='商品', anchor='center')
        self.my_bid_tree.heading('amount', text='出价', anchor='center')
        self.my_bid_tree.heading('bid_time', text='出价时间', anchor='center')
        self.my_bid_tree.heading('status', text='状态', anchor='center')
        
        # 设置列宽
        self.my_bid_tree.column('id', width=50, anchor='center')
        self.my_bid_tree.column('product', width=150, anchor='center')
        self.my_bid_tree.column('amount', width=80, anchor='center')
        self.my_bid_tree.column('bid_time', width=120, anchor='center')
        self.my_bid_tree.column('status', width=80, anchor='center')
        
        self.my_bid_tree.pack(fill='both', expand=True, padx=10, pady=5)
        
        # 加载我的竞拍数据
        self.load_my_bids()
    
    def show_add_product(self):
        self.clear_content()
        
        # 添加商品标题
        tb.Label(
            self.content,
            text="发布新商品",
            font=('Helvetica', 16, 'bold'),
            bootstyle=PRIMARY
        ).pack(pady=10)
        
        # 表单框架
        form_frame = tb.Frame(self.content)
        form_frame.pack(pady=10)
        
        # 商品名称
        tb.Label(form_frame, text="商品名称:", bootstyle=PRIMARY).grid(row=0, column=0, padx=5, pady=5, sticky='e')
        self.product_name_entry = tb.Entry(form_frame, bootstyle=PRIMARY)
        self.product_name_entry.grid(row=0, column=1, padx=5, pady=5)
        
        # 商品描述
        tb.Label(form_frame, text="商品描述:", bootstyle=PRIMARY).grid(row=1, column=0, padx=5, pady=5, sticky='e')
        self.product_desc_entry = tb.Text(form_frame, height=5, width=30)
        self.product_desc_entry.grid(row=1, column=1, padx=5, pady=5)
        
        # 商品类别
        tb.Label(form_frame, text="商品类别:", bootstyle=PRIMARY).grid(row=2, column=0, padx=5, pady=5, sticky='e')
        self.product_category_combobox = tb.Combobox(form_frame, values=['电子产品', '家居用品', '服装', '书籍', '其他'])
        self.product_category_combobox.grid(row=2, column=1, padx=5, pady=5)
        
        # 起拍价
        tb.Label(form_frame, text="起拍价:", bootstyle=PRIMARY).grid(row=3, column=0, padx=5, pady=5, sticky='e')
        self.base_price_entry = tb.Entry(form_frame, bootstyle=PRIMARY)
        self.base_price_entry.grid(row=3, column=1, padx=5, pady=5)

        # 开始时间(当前时间)
        tb.Label(form_frame, text="开始时间:").grid(row=4, column=0, padx=5, pady=5, sticky='e')
        self.start_time_entry = tb.Entry(form_frame, bootstyle=PRIMARY)
        self.start_time_entry.grid(row=4, column=1, padx=5, pady=5)
        self.start_time_entry.insert(0, datetime.now().strftime('%Y-%m-%d %H:%M:%S'))

        # 结束时间(默认7天后)
        tb.Label(form_frame, text="结束时间:").grid(row=5, column=0, padx=5, pady=5, sticky='e')
        self.end_time_entry = tb.Entry(form_frame, bootstyle=PRIMARY)
        self.end_time_entry.grid(row=5, column=1, padx=5, pady=5)
        self.end_time_entry.insert(0, (datetime.now() + timedelta(days=7)).strftime('%Y-%m-%d %H:%M:%S'))
        
        # 商品图片
        tb.Label(form_frame, text="商品图片:", bootstyle=PRIMARY).grid(row=6, column=0, padx=5, pady=5, sticky='e')
        self.image_path_entry = tb.Entry(form_frame, bootstyle=PRIMARY)
        self.image_path_entry.grid(row=6, column=1, padx=5, pady=5)
        
        tb.Button(
            form_frame,
            text="选择图片",
            bootstyle=INFO,
            command=self.select_image
        ).grid(row=6, column=2, padx=5, pady=5)
        
        # 预览图片
        self.image_preview_label = tb.Label(form_frame)
        self.image_preview_label.grid(row=7, column=1, pady=5)
        
        # 提交按钮
        tb.Button(
            self.content,
            text="发布商品",
            bootstyle=SUCCESS,
            command=self.add_product
        ).pack(pady=10)
        
        
        #时区
        tz = timezone('Asia/Shanghai')
        now = datetime.now(tz)

        # 使用统一的时间格式常量
        TIME_FORMAT = '%Y-%m-%d %H:%M:%S'
        now_str = datetime.now().strftime(TIME_FORMAT)

        # 定义时间格式常量
        TIME_FORMAT = '%Y-%m-%d %H:%M:%S'

        def reset_times(self):
            """重置时间为默认值"""
            self._set_default_times()

        def _set_default_times(self):
            """设置默认的开始和结束时间"""
            now = datetime.now()
    
            # 开始时间默认为当前时间
            self.start_time_entry.delete(0, 'end')
            self.start_time_entry.insert(0, now.strftime(self.TIME_FORMAT))
    
            # 结束时间默认为7天后
            self.end_time_entry.delete(0, 'end')
            self.end_time_entry.insert(0, (now + timedelta(days=7)).strftime(self.TIME_FORMAT))

        def validate_times(self):
            """验证时间输入的有效性"""
            try:
                start_time = datetime.strptime(self.start_time_entry.get(), self.TIME_FORMAT)
                end_time = datetime.strptime(self.end_time_entry.get(), self.TIME_FORMAT)
        
                if end_time <= start_time:
                    raise ValueError("结束时间必须晚于开始时间!")
                if (end_time - start_time).days > 30:
                    raise ValueError("拍卖持续时间不能超过30天!")
        
                return True
            except ValueError as e:
                messagebox.showerror("时间错误", str(e))
                return False
    
    
    def show_account_settings(self):
        self.clear_content()
        
        # 账户设置标题
        tb.Label(
            self.content,
            text="账户设置",
            font=('Helvetica', 16, 'bold'),
            bootstyle=PRIMARY
        ).pack(pady=10)
        
        # 表单框架
        form_frame = tb.Frame(self.content)
        form_frame.pack(pady=10)
        
        # 用户名
        tb.Label(form_frame, text="用户名:", bootstyle=PRIMARY).grid(row=0, column=0, padx=5, pady=5, sticky='e')
        self.username_entry = tb.Entry(form_frame, bootstyle=PRIMARY)
        self.username_entry.grid(row=0, column=1, padx=5, pady=5)
        self.username_entry.insert(0, self.current_user['username'])
        self.username_entry.config(state='readonly')
        
        # 邮箱
        tb.Label(form_frame, text="邮箱:", bootstyle=PRIMARY).grid(row=1, column=0, padx=5, pady=5, sticky='e')
        self.email_entry = tb.Entry(form_frame, bootstyle=PRIMARY)
        self.email_entry.grid(row=1, column=1, padx=5, pady=5)
        self.email_entry.insert(0, self.current_user['email'])
        
        # 电话
        tb.Label(form_frame, text="电话:", bootstyle=PRIMARY).grid(row=2, column=0, padx=5, pady=5, sticky='e')
        self.phone_entry = tb.Entry(form_frame, bootstyle=PRIMARY)
        self.phone_entry.grid(row=2, column=1, padx=5, pady=5)
        self.phone_entry.insert(0, self.current_user['phone'] or '')
        
        # 地址
        tb.Label(form_frame, text="地址:", bootstyle=PRIMARY).grid(row=3, column=0, padx=5, pady=5, sticky='e')
        self.address_entry = tb.Entry(form_frame, bootstyle=PRIMARY)
        self.address_entry.grid(row=3, column=1, padx=5, pady=5)
        self.address_entry.insert(0, self.current_user['address'] or '')
        
        # 密码修改
        tb.Label(form_frame, text="新密码:", bootstyle=PRIMARY).grid(row=4, column=0, padx=5, pady=5, sticky='e')
        self.new_password_entry = tb.Entry(form_frame, show="*", bootstyle=PRIMARY)
        self.new_password_entry.grid(row=4, column=1, padx=5, pady=5)
        
        tb.Label(form_frame, text="确认密码:", bootstyle=PRIMARY).grid(row=5, column=0, padx=5, pady=5, sticky='e')
        self.confirm_password_entry = tb.Entry(form_frame, show="*", bootstyle=PRIMARY)
        self.confirm_password_entry.grid(row=5, column=1, padx=5, pady=5)
        
        # 保存按钮
        tb.Button(
            self.content,
            text="保存更改",
            bootstyle=SUCCESS,
            command=self.update_account
        ).pack(pady=10)
    
    def select_image(self):
        file_path = filedialog.askopenfilename(
            title="选择商品图片",
            filetypes=[("Image Files", "*.png *.jpg *.jpeg")]
        )
        if file_path:
            self.image_path_entry.delete(0, tk.END)
            self.image_path_entry.insert(0, file_path)
            
            # 显示预览
            self.show_image_preview(file_path)
    
    def show_image_preview(self, image_path):
        try:
            image = Image.open(image_path)
            image.thumbnail((200, 200))
            photo = ImageTk.PhotoImage(image)
            
            self.image_preview_label.config(image=photo)
            self.image_preview_label.image = photo  # 保持引用
        except Exception as e:
            messagebox.showerror("错误", f"无法加载图片: {str(e)}")
    
    def load_products(self):
        query = """
        SELECT p.product_id as id, p.name, p.category, p.base_price, p.current_price, p.status,
               u.username as seller, p.end_time
        FROM products p
        JOIN users u ON p.seller_id = u.user_id
        WHERE p.status = 'active'
        ORDER BY p.product_id
        """
        products = db.execute_query(query)
        
        if hasattr(self, 'product_tree'):
            for item in self.product_tree.get_children():
                self.product_tree.delete(item)
            
            for product in products:
                self.product_tree.insert('', 'end', values=(
                    product['id'],
                    product['name'],
                    product['category'],
                    f"¥{product['current_price']:.2f}",
                    self.get_status_text(product['status']),
                    product['seller'],
                    product['end_time'].strftime('%Y-%m-%d %H:%M:%S')
                ))
    
    def load_my_products(self):
        query = """
        SELECT product_id as id, name, category, current_price, status, start_time, end_time
        FROM products
        WHERE seller_id = %s
        ORDER BY seller_id
        """
        products = db.execute_query(query, (self.current_user['user_id'],))
        
        if hasattr(self, 'my_product_tree'):
            for item in self.my_product_tree.get_children():
                self.my_product_tree.delete(item)
            
            for product in products:
                self.my_product_tree.insert('', 'end', values=(
                    product['id'],
                    product['name'],
                    product['category'],
                    f"¥{product['current_price']:.2f}",
                    self.get_status_text(product['status']),
                    product['start_time'].strftime('%Y-%m-%d %H:%M:%S'),
                    product['end_time'].strftime('%Y-%m-%d %H:%M:%S')
                ))
                

    """订单数据函数"""

    def show_my_orders(self):
        self.clear_content()
    
        # 我的商品标题
        tb.Label(
            self.content,
            text="我的订单",
            font=('Helvetica', 16, 'bold'),
            bootstyle=PRIMARY
        ).pack(pady=10)
    
        # 我的商品表格
        columns = ('order_id', 'product_name', 'price', 'status', 'created_at', 'payment_time', 'completion_time')
        self.my_orders_tree = ttk.Treeview(
            self.content,
            columns=columns,
            show='headings',
            height=15
        )
    
        # 设置列
        self.my_orders_tree.heading('order_id', text='订单ID', anchor='center')
        self.my_orders_tree.heading('product_name', text='商品名称', anchor='center')
        self.my_orders_tree.heading('price', text='价格', anchor='center')
        self.my_orders_tree.heading('status', text='状态', anchor='center')
        self.my_orders_tree.heading('created_at', text='创建时间', anchor='center')
        self.my_orders_tree.heading('payment_time', text=' 支付时间 ', anchor='center')
        self.my_orders_tree.heading('completion_time', text=' 完成时间 ', anchor='center')
    
        # 设置列宽
        self.my_orders_tree.column('order_id', width=50, anchor='center')
        self.my_orders_tree.column('product_name', width=120, anchor='center')
        self.my_orders_tree.column('price', width=80, anchor='center')
        self.my_orders_tree.column('status', width=80, anchor='center')
        self.my_orders_tree.column('created_at', width=80, anchor='center')
        self.my_orders_tree.column('payment_time', width=120, anchor='center')
        self.my_orders_tree.column('completion_time', width=120, anchor='center')
    
        self.my_orders_tree.pack(fill='both', expand=True, padx=10, pady=5)

        # 加载我的订单数据
        self.load_my_orders()

    def load_my_orders(self):
    
        query = """
                    SELECT o.order_id, p.name as product_name, o.price, o.status,
                           o.created_at, o.payment_time, o.completion_time
                    FROM orders o
                    JOIN products p ON o.product_id = p.product_id
                    WHERE o.buyer_id = %s
                    ORDER BY o.created_at
                """
        orders = db.execute_query(query, (self.current_user['user_id'],))
    
        if hasattr(self, 'my_orders_tree'):
            for item in self.my_orders_tree.get_children():
                self.my_orders_tree.delete(item)
        
            for order in orders:
                self.my_orders_tree.insert('', 'end', values=(
                    order['order_id'],
                    order['name as product_name'],
                    order['price'],
                    # f"¥{order['current_price']:.2f}",
                    self.get_status_text(order['status']),
                    order['created_at'].strftime('%Y-%m-%d %H:%M:%S'),
                    order['payment_time'].strftime('%Y-%m-%d %H:%M:%S'),
                    order['completion_time'].strftime('%Y-%m-%d %H:%M:%S')
                ))
        
    
    """我的竞品"""
    def load_my_bids(self):
        query = """
        SELECT b.bid_id as id, p.name as product, b.amount, b.bid_time,
               CASE
                   WHEN p.status = 'sold' AND b.amount = p.current_price THEN '中标'
                   WHEN p.status = 'sold' THEN '未中标'
                   WHEN p.status = 'active' THEN '竞拍中'
                   ELSE '已结束'
               END as status
        FROM bids b
        JOIN products p ON b.product_id = p.product_id
        WHERE b.user_id = %s
        ORDER BY b.bid_time
        """
        bids = db.execute_query(query, (self.current_user['user_id'],))
        
        if hasattr(self, 'my_bid_tree'):
            for item in self.my_bid_tree.get_children():
                self.my_bid_tree.delete(item)
            
            for bid in bids:
                self.my_bid_tree.insert('', 'end', values=(
                    bid['id'],
                    bid['product'],
                    f"¥{bid['amount']:.2f}",
                    bid['bid_time'].strftime('%Y-%m-%d %H:%M:%S'),
                    bid['status']
                ))
                
    
    """搜索商品"""
    def search_products(self):
        keyword = self.product_search_entry.get()
        query = """
        SELECT p.product_id as id, p.name, p.category, p.base_price,p.current_price, p.status,
               u.username as seller, p.end_time
        FROM products p
        JOIN users u ON p.seller_id = u.user_id
        WHERE p.status = 'active' AND (p.name LIKE %s OR p.category LIKE %s OR u.username LIKE %s)
        """
        products = db.execute_query(query, (f"%{keyword}%", f"%{keyword}%", f"%{keyword}%"))
        
        for item in self.product_tree.get_children():
            self.product_tree.delete(item)
        
        for product in products:
            self.product_tree.insert('', 'end', values=(
                product['id'],
                product['name'],
                product['category'],
                f"¥{product['current_price']:.2f}",
                self.get_status_text(product['status']),
                product['seller'],
                product['end_time'].strftime('%Y-%m-%d %H:%M:%S')
            ))
    
    def filter_products(self):
        category = self.category_combobox.get()
        if category == '全部':
            self.load_products()
            return
        
        query = """
        SELECT p.product_id as id, p.name, p.category, p.base_price,p.current_price, p.status,
               u.username as seller, p.end_time
        FROM products p
        JOIN users u ON p.seller_id = u.user_id
        WHERE p.status = 'active' AND p.category = %s
        ORDER BY u.user_id
        """
        products = db.execute_query(query, (category,))
        
        for item in self.product_tree.get_children():
            self.product_tree.delete(item)
        
        for product in products:
            self.product_tree.insert('', 'end', values=(
                product['id'],
                product['name'],
                product['category'],
                f"¥{product['current_price']:.2f}",
                self.get_status_text(product['status']),
                product['seller'],
                product['end_time'].strftime('%Y-%m-%d %H:%M:%S')
            ))
    
    def view_product_details(self):
        selected_item = self.product_tree.selection()
        if not selected_item:
            messagebox.showwarning("警告", "请先选择一个商品!")
            return
        
        item = self.product_tree.item(selected_item[0])
        product_id = item['values'][0]
        
        query = """
        SELECT p.*, u.username as seller_name
        FROM products p
        JOIN users u ON p.seller_id = u.user_id
        WHERE p.product_id = %s
        ORDER BY u.user_id
        """
        product = db.execute_query(query, (product_id,), fetch_one=True)
        
        if not product:
            messagebox.showerror("错误", "未找到商品信息!")
            return
        
        # 创建详情窗口
        detail_window = tb.Toplevel(self.root)
        detail_window.title(f"商品详情 - {product['name']}")

        # 主窗口居中
        self.width = 800
        self.height = 800

        # 获取窗口屏幕尺寸参数
        self.screenwidth = self.root.winfo_screenwidth()
        self.screenheight = self.root.winfo_screenheight()
        self.screen_geo = "%dx%d+%d+%d" % (
            self.width, self.height, (self.screenwidth - self.width) / 2, (self.screenheight - self.height) / 2)

        detail_window.geometry(self.screen_geo)

        # 设置主窗口不可拉伸
        detail_window.resizable(False, False)
        # detail_window.geometry("600x600")
        
        # 商品名称
        tb.Label(
            detail_window,
            text=product['name'],
            font=('Helvetica', 16, 'bold'),
            bootstyle=PRIMARY
        ).pack(pady=10)
        
        # 图片显示
        if product['image_path'] and os.path.exists(product['image_path']):
            try:
                image = Image.open(product['image_path'])
                image.thumbnail((300, 300))
                photo = ImageTk.PhotoImage(image)
                
                image_label = tb.Label(detail_window, image=photo)
                image_label.image = photo  # 保持引用
                image_label.pack(pady=5)
            except Exception as e:
                tb.Label(detail_window, text="无法加载图片", bootstyle=DANGER).pack()
        else:
            tb.Label(detail_window, text="无图片", bootstyle=SECONDARY).pack()
        
        # 商品信息
        info_frame = tb.Frame(detail_window)
        info_frame.pack(pady=10, padx=20, fill='x')
        
        # 卖家信息
        tb.Label(info_frame, text=f"卖家: {product['seller_name']}", bootstyle=PRIMARY).pack(anchor='w')
        
        # 价格信息
        tb.Label(info_frame, text=f"起拍价: ¥{product['base_price']:.2f}", bootstyle=PRIMARY).pack(anchor='w')
        tb.Label(info_frame, text=f"当前价: ¥{product['current_price']:.2f}", bootstyle=PRIMARY).pack(anchor='w')
        
        # 时间信息
        tb.Label(info_frame, text=f"开始时间: {product['start_time'].strftime('%Y-%m-%d %H:%M:%S')}",
                 bootstyle=PRIMARY).pack(anchor='w')
        tb.Label(info_frame, text=f"结束时间: {product['end_time'].strftime('%Y-%m-%d %H:%M:%S')}", bootstyle=PRIMARY).pack(
            anchor='w')
        
        # 状态
        tb.Label(info_frame, text=f"状态: {self.get_status_text(product['status'])}", bootstyle=PRIMARY).pack(anchor='w')
        
        # 类别
        tb.Label(info_frame, text=f"类别: {product['category']}", bootstyle=PRIMARY).pack(anchor='w')
        
        # 描述
        desc_frame = tb.Frame(detail_window)
        desc_frame.pack(pady=10, padx=20, fill='both', expand=True)
        
        tb.Label(desc_frame, text="商品描述:", bootstyle=PRIMARY).pack(anchor='w')
        desc_text = tk.Text(desc_frame, height=5, wrap='word')
        desc_text.insert('1.0', product['description'])
        desc_text.config(state='disabled')
        desc_text.pack(fill='both', expand=True)
        
        # 竞拍按钮
        if product['status'] == 'active':
            bid_frame = tb.Frame(detail_window)
            bid_frame.pack(pady=10)
            
            tb.Label(bid_frame, text="出价金额:", bootstyle=PRIMARY).pack(side='left', padx=5)
            self.bid_amount_entry = tb.Entry(bid_frame, bootstyle=PRIMARY)
            self.bid_amount_entry.pack(side='left', padx=5)
            
            tb.Button(
                bid_frame,
                text="确认出价",
                bootstyle=SUCCESS,
                command=lambda: self.place_bid_for_product(product['product_id'])
            ).pack(side='left', padx=5)
    
    def place_bid_for_product(self, product_id):
        try:
            amount = float(self.bid_amount_entry.get())
        except ValueError:
            messagebox.showerror("错误", "请输入有效的金额!")
            return
        
        query = "SELECT current_price FROM products WHERE product_id = %s ORDER BY product_id"
        product = db.execute_query(query, (product_id,), fetch_one=True)
        
        if not product:
            messagebox.showerror("错误", "商品不存在!")
            return
        
        if amount <= product['current_price']:
            messagebox.showerror("错误", "出价必须高于当前价格!")
            return
        
        # 更新商品当前价格
        update_query = "UPDATE products SET current_price = %s WHERE product_id = %s"
        db.execute_query(update_query, (amount, product_id))
        
        # 添加竞拍记录
        bid_query = "INSERT INTO bids (product_id, user_id, amount) VALUES (%s, %s, %s)"
        db.execute_query(bid_query, (product_id, self.current_user['user_id'], amount))
        
        messagebox.showinfo("成功", "出价成功!")
        self.load_products()

    def show_bid_history(self, product_id):
        bids = db.execute_query(
            "SELECT u.username, b.amount, b.bid_time "
            "FROM bids b JOIN users u ON b.user_id = u.user_id "
            "WHERE b.product_id = %s ORDER BY b.bid_time",
            (product_id,)
        )
    
    
    
    def add_product(self):
        name = self.product_name_entry.get()
        description = self.product_desc_entry.get("1.0", tk.END).strip()
        category = self.product_category_combobox.get()
        base_price = self.base_price_entry.get()
        start_time = self.start_time_entry.get()
        end_time = self.end_time_entry.get()
        image_path = self.image_path_entry.get()
        
        if not name or not description or not category or not base_price:
            messagebox.showerror("错误", "必填字段不能为空!")
            return
        
        try:
            base_price = float(base_price)
            if base_price <= 0:
                raise ValueError("价格必须大于0!")
        except ValueError:
            messagebox.showerror("错误", "请输入有效的价格!")
            return
        
        try:
            datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S')
            datetime.strptime(end_time, '%Y-%m-%d %H:%M:%S')
        except ValueError:
            messagebox.showerror("错误", "日期格式应为 YYYY-MM-DD HH:MM:SS")
            return
        
        # 保存图片到服务器目录
        if image_path:
            try:
                if not os.path.exists('images'):
                    os.makedirs('images')
                
                ext = os.path.splitext(image_path)[1]
                new_filename = f"product_{datetime.now().strftime('%Y%m%d%H%M%S')}{ext}"
                new_path = os.path.join('images', new_filename)
                
                import shutil
                shutil.copy(image_path, new_path)
                image_path = new_path
            except Exception as e:
                messagebox.showerror("错误", f"图片保存失败: {str(e)}")
                return
        
        query = """
        INSERT INTO products (name, description, category, base_price, current_price, start_time, end_time, status, seller_id, image_path)
        VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
        """
        db.execute_query(query, (
            name, description, category, base_price, base_price,
            start_time, end_time, 'pending', self.current_user['user_id'], image_path
        ))
        
        messagebox.showinfo("成功", "商品已提交审核!")
        self.show_my_products()
    
    def update_account(self):
        email = self.email_entry.get()
        phone = self.phone_entry.get()
        address = self.address_entry.get()
        new_password = self.new_password_entry.get()
        confirm_password = self.confirm_password_entry.get()
        
        if not email:
            messagebox.showerror("错误", "邮箱不能为空!")
            return
        
        if new_password and new_password != confirm_password:
            messagebox.showerror("错误", "两次输入的密码不一致!")
            return
        
        # 检查邮箱是否已被其他用户使用
        query = "SELECT user_id FROM users WHERE email = %s AND user_id != %s ORDER BY user_id"
        existing_user = db.execute_query(query, (email, self.current_user['user_id']), fetch_one=True)
        if existing_user:
            messagebox.showerror("错误", "该邮箱已被其他用户使用!")
            return
        
        # 更新用户信息
        update_fields = []
        update_values = []
        
        if new_password:
            update_fields.append("password = %s")
            update_values.append(new_password)
        
        update_fields.append("email = %s")
        update_values.append(email)
        
        if phone:
            update_fields.append("phone = %s")
            update_values.append(phone)
        else:
            update_fields.append("phone = NULL")
        
        if address:
            update_fields.append("address = %s")
            update_values.append(address)
        else:
            update_fields.append("address = NULL")
        
        update_values.append(self.current_user['user_id'])
        
        query = f"UPDATE users SET {', '.join(update_fields)} WHERE user_id = %s"
        db.execute_query(query, tuple(update_values))
        
        # 更新当前用户信息
        self.current_user['email'] = email
        self.current_user['phone'] = phone or None
        self.current_user['address'] = address or None
        
        messagebox.showinfo("成功", "账户信息已更新!")
        self.show_account_settings()
    
    def get_status_text(self, status):
        status_map = {
            'pending': '待审核',
            'active': '进行中',
            'sold': '已售出',
            'expired': '已过期'
        }
        return status_map.get(status, status)
    
    def get_order_status_text(self, status):
        status_map = {
            'pending': '待支付',
            'paid': '已支付',
            'shipped': '已发货',
            'completed': '已完成',
            'cancelled': '已取消'
        }
        return status_map.get(status, status)
    
    def clear_content(self):
        for widget in self.content.winfo_children():
            widget.destroy()
    
    def logout(self):
        self.app.current_user = None
        self.app.show_login()

    def view_my_product_details(self):
        """查看当前用户商品的详细信息"""
        selected_item = self.my_product_tree.selection()
        if not selected_item:
            messagebox.showwarning("警告", "请先选择一个商品!")
            return
    
        # 获取选中商品的ID
        item = self.my_product_tree.item(selected_item[0])
        product_id = item['values'][0]
    
        # 查询数据库获取商品详情
        query = """
        SELECT p.*, u.username as seller_name
        FROM products p
        JOIN users u ON p.seller_id = u.user_id
        WHERE p.product_id = %s
        ORDER BY p.product_id
        """
        product = db.execute_query(query, (product_id,), fetch_one=True)
    
        if not product:
            messagebox.showerror("错误", "未找到商品信息!")
            return
    
        # 创建详情窗口
        detail_window = tb.Toplevel(self.root)
        detail_window.title(f"商品详情 - {product['name']}")
        # 主窗口居中
        self.width = 800
        self.height = 800

        # 获取窗口屏幕尺寸参数
        self.screenwidth = self.root.winfo_screenwidth()
        self.screenheight = self.root.winfo_screenheight()
        self.screen_geo = "%dx%d+%d+%d" % (self.width, self.height, (self.screenwidth - self.width) / 2, (self.screenheight - self.height) / 2)

        detail_window.geometry(self.screen_geo)

        # 设置主窗口不可拉伸
        detail_window.resizable(False, False)
        
        # detail_window.geometry("600x500")
    
        # 商品名称
        tb.Label(
            detail_window,
            text=product['name'],
            font=('Helvetica', 16, 'bold'),
            bootstyle=PRIMARY
        ).pack(pady=10)
    
        # 图片显示(如果有)
        if product.get('image_path'):
            try:
                from PIL import Image, ImageTk
                image = Image.open(product['image_path'])
                image.thumbnail((300, 300))
                photo = ImageTk.PhotoImage(image)
            
                image_label = tb.Label(detail_window, image=photo)
                image_label.image = photo  # 保持引用
                image_label.pack(pady=5)
            except Exception as e:
                tb.Label(detail_window, text="图片加载失败", bootstyle=DANGER).pack()
    
        # 商品信息框架
        info_frame = tb.Frame(detail_window)
        info_frame.pack(pady=10, padx=20, fill='x')
    
        # 显示商品信息
        info_items = [
            ("商品ID:", product['product_id']),
            ("卖家:", product['seller_name']),
            ("类别:", product['category']),
            ("起拍价:", f"¥{product['base_price']:.2f}"),
            ("当前价:", f"¥{product['current_price']:.2f}"),
            ("状态:", self._get_status_text(product['status'])),
            ("开始时间:", product['start_time'].strftime('%Y-%m-%d %H:%M:%S')),
            ("结束时间:", product['end_time'].strftime('%Y-%m-%d %H:%M:%S'))
        ]
    
        for text, value in info_items:
            row_frame = tb.Frame(info_frame)
            row_frame.pack(fill='x', pady=2)
            tb.Label(row_frame, text=text, width=10, bootstyle=PRIMARY).pack(side='left')
            tb.Label(row_frame, text=value, bootstyle=SECONDARY).pack(side='left')
    
        # 商品描述
        desc_frame = tb.Frame(detail_window)
        desc_frame.pack(pady=10, padx=20, fill='both', expand=True)
    
        tb.Label(desc_frame, text="商品描述:", bootstyle=PRIMARY).pack(anchor='w')
        desc_text = tk.Text(desc_frame, height=5, wrap='word')
        desc_text.insert('1.0', product['description'])
        desc_text.config(state='disabled')
        desc_text.pack(fill='both', expand=True)

    def _get_status_text(self, status):
        """转换状态码为可读文本"""
        status_map = {
            'pending': '待审核',
            'active': '进行中',
            'sold': '已售出',
            'expired': '已过期'
        }
        return status_map.get(status, status)


    def register(self, username):
        try:
            # 注册逻辑...
            logging.info(f"新用户注册: {username}!")
        except Exception as e:
            logging.error(f"注册失败: {str(e)}!")
            raise

管理员模块:admin.py

"""管理员界面"""

from db import db

import tkinter as tk
from tkinter import messagebox, ttk, filedialog
import ttkbootstrap as tb
from ttkbootstrap.constants import *
from datetime import datetime, timedelta
from PIL import Image, ImageTk
import os


class AdminDashboard:
    def __init__(self, root, app):
        self.root = root
        self.app = app
        self.current_user = app.current_user
        
        self.create_widgets()
        self.load_users()
        self.load_orders()

        # 初始化界面组件
        self._init_product_tree()  # 新增商品树初始化
        self.load_products()  # 加载商品数据

    def _init_product_tree(self):
        """初始化商品列表Treeview"""
        # 创建Frame容器
        tree_frame = ttk.Frame(self.content)
        tree_frame.pack(fill='both', expand=True, padx=10, pady=10)
    
        # 创建Treeview
        self.product_tree = ttk.Treeview(
            tree_frame,
            columns=('id', 'name', 'category', 'price', 'status', 'seller', 'time'),
            show='headings',
            height=15
        )
    
        # 配置列
        columns = [
            ('id', 'ID', 50),
            ('name', '商品名称', 150),
            ('category', '类别', 100),
            ('price', '价格', 80),
            ('status', '状态', 80),
            ('seller', '卖家', 100),
            ('time', '发布时间', 120)
        ]
    
        for col, text, width in columns:
            self.product_tree.heading(col, text=text)
            self.product_tree.column(col, width=width, anchor='center')
    
        # 添加滚动条
        scrollbar = ttk.Scrollbar(
            tree_frame,
            orient="vertical",
            command=self.product_tree.yview
        )
        self.product_tree.configure(yscrollcommand=scrollbar.set)
    
        # 布局
        self.product_tree.pack(side='left', fill='both', expand=True)
        scrollbar.pack(side='right', fill='y')

        # 添加右键菜单
        self.product_menu = tk.Menu(self.root, tearoff=0)
        self.product_menu.add_command(label="上架商品", command=self._approve_product)
        self.product_menu.add_command(label="下架商品", command=self._reject_product)

        # 绑定事件
        self.product_tree.bind("<Button-3>", self._show_product_menu)

    def _show_product_menu(self, event):
        """显示商品操作菜单"""
        item = self.product_tree.identify_row(event.y)
        if item:
            self.product_tree.selection_set(item)
            self.product_menu.post(event.x_root, event.y_root)

    def _approve_product(self):
        """上架选中的商品"""
        selected = self._get_selected_product()
        if not selected:
            return
    
        try:
            db.execute_query(
                "UPDATE products SET status = 'active' WHERE product_id = %s",
                (selected['id'],)
            )
            messagebox.showinfo("成功", "商品已上架!")
            self.refresh_products()
        except Exception as e:
            messagebox.showerror("错误", f"上架失败: {str(e)}!")

        # 记录操作日志
        db.execute_query(
            "INSERT INTO product_logs (product_id, action, admin_id) VALUES (%s, %s, %s)",
            (selected['id'], 'approve', self.app.current_user['user_id'])
        )

    def _reject_product(self):
        """下架选中的商品"""
        selected = self._get_selected_product()
        if not selected:
            return
    
        try:
            db.execute_query(
                "UPDATE products SET status = 'inactive' WHERE product_id = %s",
                (selected['id'],)
            )
            messagebox.showinfo("成功", "商品已下架!")
            self.refresh_products()
        except Exception as e:
            messagebox.showerror("错误", f"下架失败: {str(e)}!")

    def _get_selected_product(self):
        """获取当前选中的商品"""
        selected = self.product_tree.selection()
        if not selected:
            messagebox.showwarning("警告", "请先选择一个商品!")
            return None
    
        item = self.product_tree.item(selected[0])
        return {
            'id': item['values'][0],
            'name': item['values'][1]
        }
    
    
    def create_widgets(self):
        # 主框架
        self.main_frame = tb.Frame(self.root)
        self.main_frame.pack(fill='both', expand=True)
        
        # 侧边栏
        self.sidebar = tb.Frame(self.main_frame, bootstyle=SECONDARY, width=200)
        self.sidebar.pack(side='left', fill='y')
        
        # 顶部栏
        self.topbar = tb.Frame(self.main_frame, bootstyle=PRIMARY, height=50)
        self.topbar.pack(side='top', fill='x')
        
        # 内容区域
        self.content = tb.Frame(self.main_frame)
        self.content.pack(side='right', fill='both', expand=True)
        
        # 侧边栏内容
        tb.Label(
            self.sidebar,
            text="管理员面板",
            font=('Helvetica', 12, 'bold'),
            bootstyle=INVERSE
        ).pack(pady=20)
        
        # 导航按钮
        nav_buttons = [
            ("用户管理", self.show_user_management),
            ("商品管理", self.show_product_management),
            ("订单管理", self.show_order_management),
            ("发布商品", self.show_add_product),
            ("退出登录", self.logout)
        ]
        
        
        for text, command in nav_buttons:
            btn = tb.Button(
                self.sidebar,
                text=text,
                bootstyle=(OUTLINE, LIGHT),
                command=command
            )
            btn.pack(fill='x', padx=10, pady=5)
        
        # 顶部栏内容
        tb.Label(
            self.topbar,
            text=f"欢迎, {self.current_user['username']} (超级管理员)",
            font=('Helvetica', 12),
            bootstyle=INVERSE
        ).pack(side='left', padx=20)
        
        # 默认显示用户管理
        self.show_user_management()
    
    def show_user_management(self):
        self.clear_content()
        
        # 用户管理标题
        tb.Label(
            self.content,
            text="用户管理",
            font=('Helvetica', 16, 'bold'),
            bootstyle=PRIMARY
        ).pack(pady=10)
        
        # 搜索框
        search_frame = tb.Frame(self.content)
        search_frame.pack(fill='x', padx=10, pady=5)
        
        self.user_search_entry = tb.Entry(search_frame, bootstyle=PRIMARY)
        self.user_search_entry.pack(side='left', padx=5, expand=True, fill='x')
        
        tb.Button(
            search_frame,
            text="搜索",
            bootstyle=INFO,
            command=self.search_users
        ).pack(side='left', padx=5)
        
        # 用户表格
        columns = ('id', 'username', 'email', 'phone', 'is_admin', 'created_at')
        self.user_tree = ttk.Treeview(
            self.content,
            columns=columns,
            show='headings',
            height=15
        )
        
        # 设置列
        self.user_tree.heading('id', text='ID', anchor='center')
        self.user_tree.heading('username', text='用户名', anchor='center')
        self.user_tree.heading('email', text='邮箱', anchor='center')
        self.user_tree.heading('phone', text='电话', anchor='center')
        self.user_tree.heading('is_admin', text='管理员', anchor='center')
        self.user_tree.heading('created_at', text='注册时间', anchor='center')
        
        # 设置列宽
        self.user_tree.column('id', width=50, anchor='center')
        self.user_tree.column('username', width=100, anchor='center')
        self.user_tree.column('email', width=150, anchor='center')
        self.user_tree.column('phone', width=100, anchor='center')
        self.user_tree.column('is_admin', width=80, anchor='center')
        self.user_tree.column('created_at', width=120, anchor='center')
        
        self.user_tree.pack(fill='both', expand=True, padx=10, pady=5)
        
        # 操作按钮
        button_frame = tb.Frame(self.content)
        button_frame.pack(pady=10)
        
        tb.Button(
            button_frame,
            text="设为管理员",
            bootstyle=WARNING,
            command=self.set_as_admin
        ).pack(side='left', padx=5)
        
        tb.Button(
            button_frame,
            text="删除用户",
            bootstyle=DANGER,
            command=self.delete_user
        ).pack(side='left', padx=5)
    
    def show_product_management(self):
        self.clear_content()
        
        # 商品管理标题
        tb.Label(
            self.content,
            text="商品管理",
            font=('Helvetica', 16, 'bold'),
            bootstyle=PRIMARY
        ).pack(pady=10)
        
        # 搜索框
        search_frame = tb.Frame(self.content)
        search_frame.pack(fill='x', padx=10, pady=5)
        
        self.product_search_entry = tb.Entry(search_frame, bootstyle=PRIMARY)
        self.product_search_entry.pack(side='left', padx=5, expand=True, fill='x')
        
        tb.Button(
            search_frame,
            text="搜索",
            bootstyle=INFO,
            command=self.search_products
        ).pack(side='left', padx=5)
        
        # 商品表格
        columns = (
        'id', 'name', 'category', 'base_price', 'current_price', 'status', 'seller', 'start_time', 'end_time')
        self.product_tree = ttk.Treeview(
            self.content,
            columns=columns,
            show='headings',
            height=15
        )
        
        # 设置列
        self.product_tree.heading('id', text='ID', anchor='center')
        self.product_tree.heading('name', text='商品名称', anchor='center')
        self.product_tree.heading('category', text='类别', anchor='center')
        self.product_tree.heading('base_price', text='起拍价', anchor='center')
        self.product_tree.heading('current_price', text='当前价', anchor='center')
        self.product_tree.heading('status', text='状态', anchor='center')
        self.product_tree.heading('seller', text='卖家', anchor='center')
        self.product_tree.heading('start_time', text='开始时间', anchor='center')
        self.product_tree.heading('end_time', text='结束时间', anchor='center')
        
        # 设置列宽
        self.product_tree.column('id', width=50, anchor='center')
        self.product_tree.column('name', width=120, anchor='center')
        self.product_tree.column('category', width=80, anchor='center')
        self.product_tree.column('base_price', width=80, anchor='center')
        self.product_tree.column('current_price', width=80, anchor='center')
        self.product_tree.column('status', width=80, anchor='center')
        self.product_tree.column('seller', width=100, anchor='center')
        self.product_tree.column('start_time', width=120, anchor='center')
        self.product_tree.column('end_time', width=120, anchor='center')
        
        self.product_tree.pack(fill='both', expand=True, padx=10, pady=5)
        
        # 操作按钮
        button_frame = tb.Frame(self.content)
        button_frame.pack(pady=10)
        
        tb.Button(
            button_frame,
            text="上架商品",
            bootstyle=SUCCESS,
            command=self.approve_product
        ).pack(side='left', padx=5)
        
        tb.Button(
            button_frame,
            text="下架商品",
            bootstyle=DANGER,
            command=self.reject_product
        ).pack(side='left', padx=5)
        
        tb.Button(
            button_frame,
            text="查看详情",
            bootstyle=INFO,
            command=self.view_product_details
        ).pack(side='left', padx=5)
    
    def show_order_management(self):
        self.clear_content()
        
        # 订单管理标题
        tb.Label(
            self.content,
            text="订单管理",
            font=('Helvetica', 16, 'bold'),
            bootstyle=PRIMARY
        ).pack(pady=10)
        
        # 搜索框
        search_frame = tb.Frame(self.content)
        search_frame.pack(fill='x', padx=10, pady=5)
        
        self.order_search_entry = tb.Entry(search_frame, bootstyle=PRIMARY)
        self.order_search_entry.pack(side='left', padx=5, expand=True, fill='x')
        
        tb.Button(
            search_frame,
            text="搜索",
            bootstyle=INFO,
            command=self.search_orders
        ).pack(side='left', padx=5)
        
        # 订单表格
        columns = ('id', 'product', 'buyer', 'price', 'status', 'created_at')
        self.order_tree = ttk.Treeview(
            self.content,
            columns=columns,
            show='headings',
            height=15
        )
        
        # 设置列
        self.order_tree.heading('id', text='ID', anchor='center')
        self.order_tree.heading('product', text='商品', anchor='center')
        self.order_tree.heading('buyer', text='买家', anchor='center')
        self.order_tree.heading('price', text='价格', anchor='center')
        self.order_tree.heading('status', text='状态', anchor='center')
        self.order_tree.heading('created_at', text='创建时间', anchor='center')
        
        # 设置列宽
        self.order_tree.column('id', width=50, anchor='center')
        self.order_tree.column('product', width=150, anchor='center')
        self.order_tree.column('buyer', width=100, anchor='center')
        self.order_tree.column('price', width=80, anchor='center')
        self.order_tree.column('status', width=80, anchor='center')
        self.order_tree.column('created_at', width=120, anchor='center')
        
        self.order_tree.pack(fill='both', expand=True, padx=10, pady=5)
        
        # 操作按钮
        button_frame = tb.Frame(self.content)
        button_frame.pack(pady=10)
        
        tb.Button(
            button_frame,
            text="标记为已支付",
            bootstyle=SUCCESS,
            command=lambda: self.update_order_status('paid')
        ).pack(side='left', padx=5)
        
        tb.Button(
            button_frame,
            text="标记为已发货",
            bootstyle=INFO,
            command=lambda: self.update_order_status('shipped')
        ).pack(side='left', padx=5)
        
        tb.Button(
            button_frame,
            text="标记为已完成",
            bootstyle=PRIMARY,
            command=lambda: self.update_order_status('completed')
        ).pack(side='left', padx=5)
        
        tb.Button(
            button_frame,
            text="取消订单",
            bootstyle=DANGER,
            command=lambda: self.update_order_status('cancelled')
        ).pack(side='left', padx=5)
    
    def show_add_product(self):
        self.clear_content()
        
        # 添加商品标题
        tb.Label(
            self.content,
            text="发布新商品",
            font=('Helvetica', 16, 'bold'),
            bootstyle=PRIMARY
        ).pack(pady=10)
        
        # 表单框架
        form_frame = tb.Frame(self.content)
        form_frame.pack(pady=10)
        
        # 商品名称
        tb.Label(form_frame, text="商品名称:", bootstyle=PRIMARY).grid(row=0, column=0, padx=5, pady=5, sticky='e')
        self.product_name_entry = tb.Entry(form_frame, bootstyle=PRIMARY)
        self.product_name_entry.grid(row=0, column=1, padx=5, pady=5)
        
        # 商品描述
        tb.Label(form_frame, text="商品描述:", bootstyle=PRIMARY).grid(row=1, column=0, padx=5, pady=5, sticky='e')
        self.product_desc_entry = tb.Text(form_frame, height=5, width=30)
        self.product_desc_entry.grid(row=1, column=1, padx=5, pady=5)
        
        # 商品类别
        tb.Label(form_frame, text="商品类别:", bootstyle=PRIMARY).grid(row=2, column=0, padx=5, pady=5, sticky='e')
        self.product_category_combobox = tb.Combobox(form_frame, values=['电子产品', '家居用品', '服装', '书籍', '其他'])
        self.product_category_combobox.grid(row=2, column=1, padx=5, pady=5)
        
        # 起拍价
        tb.Label(form_frame, text="起拍价:", bootstyle=PRIMARY).grid(row=3, column=0, padx=5, pady=5, sticky='e')
        self.base_price_entry = tb.Entry(form_frame, bootstyle=PRIMARY)
        self.base_price_entry.grid(row=3, column=1, padx=5, pady=5)
        
        # 开始时间
        tb.Label(form_frame, text="开始时间:", bootstyle=PRIMARY).grid(row=4, column=0, padx=5, pady=5, sticky='e')
        self.start_time_entry = tb.Entry(form_frame, bootstyle=PRIMARY)
        self.start_time_entry.grid(row=4, column=1, padx=5, pady=5)
        self.start_time_entry.insert(0, datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
        
        # 结束时间
        tb.Label(form_frame, text="结束时间:", bootstyle=PRIMARY).grid(row=5, column=0, padx=5, pady=5, sticky='e')
        self.end_time_entry = tb.Entry(form_frame, bootstyle=PRIMARY)
        self.end_time_entry.grid(row=5, column=1, padx=5, pady=5)
        self.end_time_entry.insert(0, (datetime.now() + timedelta(days=7)).strftime('%Y-%m-%d %H:%M:%S'))
        
        # 商品图片
        tb.Label(form_frame, text="商品图片:", bootstyle=PRIMARY).grid(row=6, column=0, padx=5, pady=5, sticky='e')
        self.image_path_entry = tb.Entry(form_frame, bootstyle=PRIMARY)
        self.image_path_entry.grid(row=6, column=1, padx=5, pady=5)
        
        tb.Button(
            form_frame,
            text="选择图片",
            bootstyle=INFO,
            command=self.select_image
        ).grid(row=6, column=2, padx=5, pady=5)
        
        # 预览图片
        self.image_preview_label = tb.Label(form_frame)
        self.image_preview_label.grid(row=7, column=1, pady=5)
        
        # 提交按钮
        tb.Button(
            self.content,
            text="发布商品",
            bootstyle=SUCCESS,
            command=self.add_product
        ).pack(pady=10)
    
    def select_image(self):
        file_path = filedialog.askopenfilename(
            title="选择商品图片",
            filetypes=[("Image Files", "*.png *.jpg *.jpeg")]
        )
        if file_path:
            self.image_path_entry.delete(0, tk.END)
            self.image_path_entry.insert(0, file_path)
            
            # 显示预览
            self.show_image_preview(file_path)
    
    def show_image_preview(self, image_path):
        try:
            image = Image.open(image_path)
            image.thumbnail((200, 200))
            photo = ImageTk.PhotoImage(image)
            
            self.image_preview_label.config(image=photo)
            self.image_preview_label.image = photo  # 保持引用
        except Exception as e:
            messagebox.showerror("错误", f"无法加载图片: {str(e)}")
    
    def add_product(self):
        name = self.product_name_entry.get()
        description = self.product_desc_entry.get("1.0", tk.END).strip()
        category = self.product_category_combobox.get()
        base_price = self.base_price_entry.get()
        start_time = self.start_time_entry.get()
        end_time = self.end_time_entry.get()
        image_path = self.image_path_entry.get()
        
        if not name or not description or not category or not base_price:
            messagebox.showerror("错误", "必填字段不能为空!")
            return
        
        try:
            base_price = float(base_price)
            if base_price <= 0:
                raise ValueError("价格必须大于0!")
        except ValueError:
            messagebox.showerror("错误", "请输入有效的价格")
            return
        
        try:
            datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S')
            datetime.strptime(end_time, '%Y-%m-%d %H:%M:%S')
        except ValueError:
            messagebox.showerror("错误", "日期格式应为 YYYY-MM-DD HH:MM:SS")
            return
        
        # 保存图片到服务器目录
        if image_path:
            try:
                # 创建images目录如果不存在
                if not os.path.exists('images'):
                    os.makedirs('images')
                
                # 生成唯一文件名
                ext = os.path.splitext(image_path)[1]
                new_filename = f"product_{datetime.now().strftime('%Y%m%d%H%M%S')}{ext}"
                new_path = os.path.join('images', new_filename)
                
                # 复制文件
                import shutil
                shutil.copy(image_path, new_path)
                image_path = new_path
            except Exception as e:
                messagebox.showerror("错误", f"图片保存失败: {str(e)}!")
                return
        
        query = """
        INSERT INTO products (name, description, category, base_price, current_price, start_time, end_time, status, seller_id, image_path)
        VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
        """
        db.execute_query(query, (
            name, description, category, base_price, base_price,
            start_time, end_time, 'active', self.current_user['user_id'], image_path
        ))
        
        messagebox.showinfo("成功", "商品发布成功!")
        self.show_product_management()

    def load_users(self):
        """加载并显示用户列表(优化版)"""
        try:
            # 1. 执行查询获取用户数据
            query = """
            SELECT
                user_id AS id,
                username,
                email,
                phone,
                is_admin,
                created_at,
                last_login
            FROM users
            ORDER BY user_id
            """
            users = db.execute_query(query)
        
            # 2. 检查Treeview组件是否存在
            if not hasattr(self, 'user_tree'):
                self._init_user_tree()
        
            # 3. 清空现有数据
            self._clear_user_tree()
        
            # 4. 填充数据
            for user in users:
                self.user_tree.insert('', 'end', values=(
                    user['id'],
                    user['username'],
                    user['email'],
                    user['phone'] or '未填写',
                    '✅' if user['is_admin'] else '❌',
                    user['created_at'].strftime('%Y-%m-%d %H:%M'),
                    user['last_login'].strftime('%Y-%m-%d %H:%M') if user['last_login'] else '从未登录'
                ))
        
            # 5. 更新状态栏
            self._update_status_bar(f"加载完成,共 {len(users)} 位用户")
    
        except Exception as e:
            self._show_error_message(f"加载用户失败: {str(e)}!")

    def _init_user_tree(self):
        """初始化用户列表Treeview"""
        self.user_tree = ttk.Treeview(
            self.content_frame,
            columns=('id', 'username', 'email', 'phone', 'is_admin', 'created_at', 'last_login'),
            show='headings',
            height=15,
            selectmode='browse'
        )
    
        # 配置列
        columns_config = [
            ('id', 'ID', 50),
            ('username', '用户名', 120),
            ('email', '邮箱', 180),
            ('phone', '电话', 100),
            ('is_admin', '超级管理员', 80),
            ('created_at', '注册时间', 150),
            ('last_login', '最后登录', 150)
        ]
    
        for col, text, width in columns_config:
            self.user_tree.heading(col, text=text)
            self.user_tree.column(col, width=width, anchor='center')
    
        # 添加滚动条
        scrollbar = ttk.Scrollbar(
            self.content_frame,
            orient="vertical",
            command=self.user_tree.yview
        )
        self.user_tree.configure(yscrollcommand=scrollbar.set)
    
        # 布局
        self.user_tree.pack(side='left', fill='both', expand=True)
        scrollbar.pack(side='right', fill='y')

    def _clear_user_tree(self):
        """清空用户列表"""
        for item in self.user_tree.get_children():
            self.user_tree.delete(item)

    def _update_status_bar(self, message):
        """更新状态栏信息"""
        if hasattr(self, 'status_bar'):
            self.status_bar.config(text=message)

    def _show_error_message(self, message):
        """显示错误信息"""
        messagebox.showerror("错误", message)
        if hasattr(self, 'status_bar'):
            self.status_bar.config(text=message)

    def load_products(self):
        """加载商品数据到Treeview"""
        try:
            # 确保product_tree存在
            if not hasattr(self, 'product_tree'):
                self._init_product_tree()
        
            # 清空现有数据
            for item in self.product_tree.get_children():
                self.product_tree.delete(item)
            # 查询商品数据
            query = """
                SELECT
                    p.product_id as id,
                    p.name,
                    p.category,
                    p.current_price AS price,  # 使用正确的字段名
                    # p.current_price,
                    p.status,
                    u.username as seller,
                    p.created_at as time
                FROM products p
                JOIN users u ON p.seller_id = u.user_id
            """
            products = db.execute_query(query)
        
            # 添加数据到Treeview
            for product in products:
                self.product_tree.insert('', 'end', values=(
                    product['id'],
                    product['name'],
                    product['category'],
                    f"¥{product['price']:.2f}",
                    # f"¥{product['current_price']:.2f}",
                    self._get_product_status(product['status']),
                    product['seller'],
                    product['time'].strftime('%Y-%m-%d %H:%M')
                ))
    
        except Exception as e:
            messagebox.showerror("错误", f"加载商品失败: {str(e)}")

    def _get_product_status(self, status):
        """转换商品状态为可读文本"""
        status_map = {
            'pending': '待审核',
            'active': '进行中',
            'sold': '已售出',
            'expired': '已过期'
        }
        return status_map.get(status, status)
            
    
    def load_orders(self):
        query = """
        SELECT o.order_id as id, p.name as product, u.username as buyer, o.price, o.status, o.created_at
        FROM orders o
        JOIN products p ON o.product_id = p.product_id
        JOIN users u ON o.buyer_id = u.user_id
        ORDER BY p.product_id
        """
        orders = db.execute_query(query)
        
        if hasattr(self, 'order_tree'):
            for item in self.order_tree.get_children():
                self.order_tree.delete(item)
            
            for order in orders:
                self.order_tree.insert('', 'end', values=(
                    order['id'],
                    order['product'],
                    order['buyer'],
                    f"¥{order['price']:.2f}",
                self.get_order_status_text(order['status']),
                    order['created_at'].strftime('%Y-%m-%d %H:%M:%S')
                ))
    
    def search_users(self):
        keyword = self.user_search_entry.get()
        query = """
        SELECT user_id as id, username, email, phone, is_admin, created_at
        FROM users
        WHERE username LIKE %s OR email LIKE %s OR phone LIKE %s
        ORDER BY created_at
        """
        users = db.execute_query(query, (f"%{keyword}%", f"%{keyword}%", f"%{keyword}%"))
        
        for item in self.user_tree.get_children():
            self.user_tree.delete(item)
        
        for user in users:
            self.user_tree.insert('', 'end', values=(
                user['id'],
                user['username'],
                user['email'],
                user['phone'],
                '是' if user['is_admin'] else '否',
                user['created_at'].strftime('%Y-%m-%d %H:%M:%S')
            ))
    
    def search_products(self):
        keyword = self.product_search_entry.get()
        query = """
        SELECT p.product_id as id, p.name, p.category, p.base_price, p.current_price, p.status,
               u.username as seller, p.start_time, p.end_time
        FROM products p
        JOIN users u ON p.seller_id = u.user_id
        WHERE p.name LIKE %s OR p.category LIKE %s OR u.username LIKE %s
        ORDER BY id
        """
        products = db.execute_query(query, (f"%{keyword}%", f"%{keyword}%", f"%{keyword}%"))
        
        for item in self.product_tree.get_children():
            self.product_tree.delete(item)
        
        for product in products:
            self.product_tree.insert('', 'end', values=(
                product['id'],
                product['name'],
                product['category'],
                f"¥{product['base_price']:.2f}",
                f"¥{product['current_price']:.2f}",
                self.get_status_text(product['status']),
                product['seller'],
                product['start_time'].strftime('%Y-%m-%d %H:%M:%S'),
                product['end_time'].strftime('%Y-%m-%d %H:%M:%S')
            ))
    
    def search_orders(self):
        keyword = self.order_search_entry.get()
        query = """
        SELECT o.order_id as id, p.name as product, u.username as buyer, o.price, o.status, o.created_at
        FROM orders o
        JOIN products p ON o.product_id = p.product_id
        JOIN users u ON o.buyer_id = u.user_id
        WHERE p.name LIKE %s OR u.username LIKE %s
        ORDER BY o.created_at
        """
        orders = db.execute_query(query, (f"%{keyword}%", f"%{keyword}%"))
        
        for item in self.order_tree.get_children():
            self.order_tree.delete(item)
        
        for order in orders:
            self.order_tree.insert('', 'end', values=(
                order['id'],
                order['product'],
                order['buyer'],
                f"¥{order['price']:.2f}",
                self.get_order_status_text(order['status']),
                order['created_at'].strftime('%Y-%m-%d %H:%M:%S')
            ))
    
    def set_as_admin(self):
        selected_item = self.user_tree.selection()
        if not selected_item:
            messagebox.showwarning("警告", "请先选择一个用户!")
            return
        
        item = self.user_tree.item(selected_item[0])
        user_id = item['values'][0]
        
        query = "UPDATE users SET is_admin = NOT is_admin WHERE user_id = %s"
        db.execute_query(query, (user_id,))
        
        messagebox.showinfo("成功", "用户权限已更新!")
        self.load_users()
    
    def delete_user(self):
        selected_item = self.user_tree.selection()
        if not selected_item:
            messagebox.showwarning("警告", "请先选择一个用户!")
            return
        
        item = self.user_tree.item(selected_item[0])
        user_id = item['values'][0]
        username = item['values'][1]
        
        if messagebox.askyesno("确认", f"确定要删除用户 {username} 吗?"):
            query = "DELETE FROM users WHERE user_id = %s"
            db.execute_query(query, (user_id,))
            
            messagebox.showinfo("成功", "用户已删除!")
            self.load_users()
    
    def approve_product(self):
        selected_item = self.product_tree.selection()
        if not selected_item:
            messagebox.showwarning("警告", "请先选择一个商品!")
            return
        
        item = self.product_tree.item(selected_item[0])
        product_id = item['values'][0]
        
        query = "UPDATE products SET status = 'active' WHERE product_id = %s"
        db.execute_query(query, (product_id,))
        
        messagebox.showinfo("成功", "商品已上架!")
        self.load_products()
    
    def reject_product(self):
        selected_item = self.product_tree.selection()
        if not selected_item:
            messagebox.showwarning("警告", "请先选择一个商品!")
            return
        
        item = self.product_tree.item(selected_item[0])
        product_id = item['values'][0]
        
        query = "UPDATE products SET status = 'expired' WHERE product_id = %s"
        db.execute_query(query, (product_id,))
        
        messagebox.showinfo("成功", "商品已下架!")
        self.load_products()
    
    def view_product_details(self):
        selected_item = self.product_tree.selection()
        if not selected_item:
            messagebox.showwarning("警告", "请先选择一个商品!")
            return
        
        item = self.product_tree.item(selected_item[0])
        product_id = item['values'][0]
        
        query = """
        SELECT p.*, u.username as seller_name
        FROM products p
        JOIN users u ON p.seller_id = u.user_id
        WHERE p.product_id = %s
        ORDER BY p.product_id
        """
        product = db.execute_query(query, (product_id,), fetch_one=True)
        
        if not product:
            messagebox.showerror("错误", "未找到商品信息!")
            return
        
        # 创建详情窗口
        detail_window = tb.Toplevel(self.root)
        detail_window.title(f"商品详情 - {product['name']}")

        # 主窗口居中
        self.width = 1000
        self.height = 900

        # 获取窗口屏幕尺寸参数
        self.screenwidth = self.root.winfo_screenwidth()
        self.screenheight = self.root.winfo_screenheight()
        self.screen_geo = "%dx%d+%d+%d" % (self.width, self.height, (self.screenwidth - self.width) / 2, (self.screenheight - self.height) / 2)

        detail_window.geometry(self.screen_geo)

        # 设置主窗口不可拉伸
        detail_window.resizable(False, False)
        # detail_window.geometry("600x500")
        
        # 商品名称
        tb.Label(
            detail_window,
            text=product['name'],
            font=('Helvetica', 16, 'bold'),
            bootstyle=PRIMARY
        ).pack(pady=10)
        
        # 图片显示
        if product['image_path'] and os.path.exists(product['image_path']):
            try:
                image = Image.open(product['image_path'])
                image.thumbnail((300, 300))
                photo = ImageTk.PhotoImage(image)
                
                image_label = tb.Label(detail_window, image=photo)
                image_label.image = photo  # 保持引用
                image_label.pack(pady=5)
            except Exception as e:
                tb.Label(detail_window, text="无法加载图片", bootstyle=DANGER).pack()
        else:
            tb.Label(detail_window, text="无图片", bootstyle=SECONDARY).pack()
        
        # 商品信息
        info_frame = tb.Frame(detail_window)
        info_frame.pack(pady=10, padx=20, fill='x')
        
        # 卖家信息
        tb.Label(info_frame, text=f"卖家: {product['seller_name']}", bootstyle=PRIMARY).pack(anchor='w')
        
        # 价格信息
        tb.Label(info_frame, text=f"起拍价: ¥{product['base_price']:.2f}", bootstyle=PRIMARY).pack(anchor='w')
        tb.Label(info_frame, text=f"当前价: ¥{product['current_price']:.2f}", bootstyle=PRIMARY).pack(anchor='w')
        
        # 时间信息
        tb.Label(info_frame, text=f"开始时间: {product['start_time'].strftime('%Y-%m-%d %H:%M:%S')}",
                 bootstyle=PRIMARY).pack(anchor='w')
        tb.Label(info_frame, text=f"结束时间: {product['end_time'].strftime('%Y-%m-%d %H:%M:%S')}", bootstyle=PRIMARY).pack(
            anchor='w')
        
        # 状态
        tb.Label(info_frame, text=f"状态: {self.get_status_text(product['status'])}", bootstyle=PRIMARY).pack(anchor='w')
        
        # 类别
        tb.Label(info_frame, text=f"类别: {product['category']}", bootstyle=PRIMARY).pack(anchor='w')
        
        # 描述
        desc_frame = tb.Frame(detail_window)
        desc_frame.pack(pady=10, padx=20, fill='both', expand=True)
        
        tb.Label(desc_frame, text="商品描述:", bootstyle=PRIMARY).pack(anchor='w')
        desc_text = tk.Text(desc_frame, height=5, wrap='word')
        desc_text.insert('1.0', product['description'])
        desc_text.config(state='disabled')
        desc_text.pack(fill='both', expand=True)
    
    def update_order_status(self, status):
        selected_item = self.order_tree.selection()
        if not selected_item:
            messagebox.showwarning("警告", "请先选择一个订单!")
            return
        
        item = self.order_tree.item(selected_item[0])
        order_id = item['values'][0]
        
        query = "UPDATE orders SET status = %s WHERE order_id = %s ORDER BY order_id"
        db.execute_query(query, (status, order_id))
        
        messagebox.showinfo("成功", "订单状态已更新!")
        self.load_orders()
    
    def get_status_text(self, status):
        status_map = {
            'pending': '待审核',
            'active': '进行中',
            'sold': '已售出',
            'expired': '已过期'
        }
        return status_map.get(status, status)
    
    def get_order_status_text(self, status):
        status_map = {
            'pending': '待支付',
            'paid': '已支付',
            'shipped': '已发货',
            'completed': '已完成',
            'cancelled': '已取消'
        }
        return status_map.get(status, status)
    
    def clear_content(self):
        for widget in self.content.winfo_children():
            widget.destroy()
    
    def logout(self):
        self.app.current_user = None
        self.app.show_login()

系统主程序入口:

"""二手拍卖商城系统"""

from db import db

import tkinter as tk
from tkinter import ttk
import ttkbootstrap as tb
from ttkbootstrap.constants import *
from db import db
from login import LoginWindow
from register import RegisterWindow
from admin import AdminDashboard
from user import UserDashboard


class AuctionSystemApp:
    def __init__(self):
        self.root = tb.Window(themename="minty")
        self.root.title("二手拍卖系统")

        # 主窗口居中
        self.width = 1920
        self.height = 1280

        # 获取窗口屏幕尺寸参数
        self.screenwidth = self.root.winfo_screenwidth()
        self.screenheight = self.root.winfo_screenheight()
        self.screen_geo = "%dx%d+%d+%d" % (
            self.width, self.height, (self.screenwidth - self.width) / 2, (self.screenheight - self.height) / 2)

        self.root.geometry(self.screen_geo)

        # 设置主窗口不可拉伸
        self.root.resizable(False, False)
        # self.root.geometry("1000x700")
        
        self.current_user = None
        self.show_login()
        
        self.root.protocol("WM_DELETE_WINDOW", self.on_close)
    
    def show_login(self):
        self.clear_window()
        LoginWindow(self.root, self)
    
    def show_register(self):
        self.clear_window()
        RegisterWindow(self.root, self)
    
    def show_admin_dashboard(self):
        self.clear_window()
        AdminDashboard(self.root, self)
    
    def show_user_dashboard(self):
        self.clear_window()
        UserDashboard(self.root, self)
    
    def clear_window(self):
        for widget in self.root.winfo_children():
            widget.destroy()
    
    def on_close(self):
        db.close()
        self.root.destroy()


if __name__ == "__main__":
    app = AuctionSystemApp()
    app.root.mainloop()

项目打包:

# 打包说明
"""
1. 安装PyInstaller: pip install pyinstaller
2. 创建打包命令: pyinstaller --onefile --windowed --icon=auction.ico app.py
3. 将images文件夹、数据库配置文件和图标文件放入dist目录
4. 测试运行生成的exe文件
"""

若项目启动和项目打包有什么问题,可在评论区留言!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值