python大作业:在线商城

源代码:

import tkinter as tk
from tkinter import ttk, messagebox, simpledialog
import json
import os

# 文件路径配置
USERS_FILE = "users.json"
PRODUCTS_FILE = "products.json"
ORDERS_FILE = "orders.json"


# 初始化数据文件
def init_file(file_path, initial_data=[]):
    if not os.path.exists(file_path):
        with open(file_path, "w") as f:
            json.dump(initial_data, f)


init_file(USERS_FILE, [{"username": "admin", "password": "admin", "role": "admin"}])
init_file(PRODUCTS_FILE)
init_file(ORDERS_FILE)


class LoginWindow:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("商城登录")
        self.window.geometry("300x200")

        tk.Label(self.window, text="用户名:").grid(row=0, column=0, padx=10, pady=5)
        self.username = tk.Entry(self.window)
        self.username.grid(row=0, column=1, padx=10, pady=5)

        tk.Label(self.window, text="密码:").grid(row=1, column=0, padx=10, pady=5)
        self.password = tk.Entry(self.window, show="*")
        self.password.grid(row=1, column=1, padx=10, pady=5)

        tk.Label(self.window, text="角色:").grid(row=2, column=0, padx=10, pady=5)
        self.role = ttk.Combobox(self.window, values=["admin", "user"], state="readonly")
        self.role.current(0)
        self.role.grid(row=2, column=1, padx=10, pady=5)

        tk.Button(self.window, text="登录", command=self.login).grid(row=3, column=1, pady=10)

    def login(self):
        username = self.username.get()
        password = self.password.get()
        role = self.role.get()

        with open(USERS_FILE, "r") as f:
            users = json.load(f)

        for user in users:
            if user["username"] == username and user["password"] == password and user["role"] == role:
                self.window.destroy()
                if role == "admin":
                    AdminDashboard()
                else:
                    UserDashboard(username)
                return
        messagebox.showerror("错误", "用户名或密码错误")

    def run(self):
        self.window.mainloop()


class AdminDashboard:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("管理员后台")
        self.window.geometry("800x400")

        # 商品列表
        self.tree = ttk.Treeview(self.window, columns=("id", "name", "category", "price", "stock"), show="headings")
        self.tree.heading("id", text="ID")
        self.tree.heading("name", text="商品名称")
        self.tree.heading("category", text="分类")
        self.tree.heading("price", text="价格")
        self.tree.heading("stock", text="库存")
        self.tree.pack(fill=tk.BOTH, expand=True)

        # 操作按钮
        btn_frame = tk.Frame(self.window)
        btn_frame.pack(pady=10)

        tk.Button(btn_frame, text="添加商品", command=self.add_product).grid(row=0, column=0, padx=5)
        tk.Button(btn_frame, text="删除商品", command=self.delete_product).grid(row=0, column=1, padx=5)
        tk.Button(btn_frame, text="修改库存", command=self.update_stock).grid(row=0, column=2, padx=5)
        tk.Button(btn_frame, text="查看订单", command=self.view_orders).grid(row=0, column=3, padx=5)

        self.load_products()

    def load_products(self):
        # 清空现有数据
        for item in self.tree.get_children():
            self.tree.delete(item)

        with open(PRODUCTS_FILE, "r") as f:
            products = json.load(f)

        for product in products:
            self.tree.insert("", "end", values=(
                product["id"],
                product["name"],
                product["category"],
                product["price"],
                product["stock"]
            ))

    def add_product(self):
        add_window = tk.Toplevel()
        add_window.title("添加商品")

        tk.Label(add_window, text="商品名称:").grid(row=0, column=0, padx=5, pady=5)
        name_entry = tk.Entry(add_window)
        name_entry.grid(row=0, column=1, padx=5, pady=5)

        tk.Label(add_window, text="分类:").grid(row=1, column=0, padx=5, pady=5)
        category_entry = tk.Entry(add_window)
        category_entry.grid(row=1, column=1, padx=5, pady=5)

        tk.Label(add_window, text="价格:").grid(row=2, column=0, padx=5, pady=5)
        price_entry = tk.Entry(add_window)
        price_entry.grid(row=2, column=1, padx=5, pady=5)

        tk.Label(add_window, text="库存:").grid(row=3, column=0, padx=5, pady=5)
        stock_entry = tk.Entry(add_window)
        stock_entry.grid(row=3, column=1, padx=5, pady=5)

        def save_product():
            with open(PRODUCTS_FILE, "r") as f:
                products = json.load(f)

            new_id = max(p["id"] for p in products) + 1 if products else 1

            products.append({
                "id": new_id,
                "name": name_entry.get(),
                "category": category_entry.get(),
                "price": float(price_entry.get()),
                "stock": int(stock_entry.get())
            })

            with open(PRODUCTS_FILE, "w") as f:
                json.dump(products, f)

            add_window.destroy()
            self.load_products()

        tk.Button(add_window, text="保存", command=save_product).grid(row=4, columnspan=2, pady=10)

    def delete_product(self):
        selected = self.tree.selection()
        if not selected:
            messagebox.showwarning("警告", "请先选择要删除的商品")
            return

        item = self.tree.item(selected[0])
        product_id = item["values"][0]

        with open(PRODUCTS_FILE, "r") as f:
            products = json.load(f)

        products = [p for p in products if p["id"] != product_id]

        with open(PRODUCTS_FILE, "w") as f:
            json.dump(products, f)

        self.load_products()

    def update_stock(self):
        selected = self.tree.selection()
        if not selected:
            messagebox.showwarning("警告", "请先选择要修改的商品")
            return

        item = self.tree.item(selected[0])
        product_id = item["values"][0]

        new_stock = simpledialog.askinteger("修改库存", "输入新的库存量:")
        if new_stock is None:
            return

        with open(PRODUCTS_FILE, "r") as f:
            products = json.load(f)

        for product in products:
            if product["id"] == product_id:
                product["stock"] = new_stock
                break

        with open(PRODUCTS_FILE, "w") as f:
            json.dump(products, f)

        self.load_products()

    def view_orders(self):
        # 查看订单功能
        orders_window = tk.Toplevel()
        orders_window.title("订单列表")
        orders_window.geometry("600x400")

        tree = ttk.Treeview(orders_window, columns=("order_id", "username", "products", "total", "time"),
                            show="headings")
        tree.heading("order_id", text="订单ID")
        tree.heading("username", text="用户名")
        tree.heading("products", text="商品")
        tree.heading("total", text="总价")
        tree.heading("time", text="时间")
        tree.pack(fill=tk.BOTH, expand=True)

        with open(ORDERS_FILE, "r") as f:
            orders = json.load(f)

        for order in orders:
            tree.insert("", "end", values=(
                order["order_id"],
                order["username"],
                ", ".join([f"{p['name']} x{p['quantity']}" for p in order["products"]]),
                order["total"],
                order["time"]
            ))

    def run(self):
        self.window.mainloop()


class UserDashboard:
    def __init__(self, username):
        self.username = username
        self.cart = []  # 用户购物车

        self.window = tk.Tk()
        self.window.title(f"用户前台 - {username}")
        self.window.geometry("800x400")

        # 商品列表
        self.tree = ttk.Treeview(self.window, columns=("id", "name", "category", "price", "stock"), show="headings")
        self.tree.heading("id", text="ID")
        self.tree.heading("name", text="商品名称")
        self.tree.heading("category", text="分类")
        self.tree.heading("price", text="价格")
        self.tree.heading("stock", text="库存")
        self.tree.pack(fill=tk.BOTH, expand=True)

        # 操作按钮
        btn_frame = tk.Frame(self.window)
        btn_frame.pack(pady=10)

        tk.Button(btn_frame, text="加入购物车", command=self.add_to_cart).grid(row=0, column=0, padx=5)
        tk.Button(btn_frame, text="查看购物车", command=self.view_cart).grid(row=0, column=1, padx=5)

        self.load_products()

    def load_products(self):
        for item in self.tree.get_children():
            self.tree.delete(item)

        with open(PRODUCTS_FILE, "r") as f:
            products = json.load(f)

        for product in products:
            self.tree.insert("", "end", values=(
                product["id"],
                product["name"],
                product["category"],
                product["price"],
                product["stock"]
            ))

    def add_to_cart(self):
        selected = self.tree.selection()
        if not selected:
            messagebox.showwarning("警告", "请先选择要添加的商品")
            return

        item = self.tree.item(selected[0])
        product_id = item["values"][0]
        product_name = item["values"][1]
        product_price = float(item["values"][3])
        product_stock = int(item["values"][4])

        # 检查商品是否已在购物车中
        for cart_item in self.cart:
            if cart_item["id"] == product_id:
                if cart_item["quantity"] >= product_stock:
                    messagebox.showwarning("警告", "商品库存不足")
                    return
                cart_item["quantity"] += 1
                messagebox.showinfo("成功", f"{product_name} 已添加到购物车")
                return

        # 添加新商品到购物车
        self.cart.append({
            "id": product_id,
            "name": product_name,
            "price": product_price,
            "quantity": 1
        })
        messagebox.showinfo("成功", f"{product_name} 已添加到购物车")

    def view_cart(self):
        if not self.cart:
            messagebox.showinfo("购物车", "购物车为空")
            return

        cart_window = tk.Toplevel()
        cart_window.title("购物车")
        cart_window.geometry("600x400")

        # 购物车商品列表
        cart_tree = ttk.Treeview(cart_window, columns=("id", "name", "price", "quantity", "subtotal"), show="headings")
        cart_tree.heading("id", text="ID")
        cart_tree.heading("name", text="商品名称")
        cart_tree.heading("price", text="单价")
        cart_tree.heading("quantity", text="数量")
        cart_tree.heading("subtotal", text="小计")
        cart_tree.pack(fill=tk.BOTH, expand=True)

        total = 0
        for item in self.cart:
            subtotal = item["price"] * item["quantity"]
            cart_tree.insert("", "end", values=(
                item["id"],
                item["name"],
                item["price"],
                item["quantity"],
                subtotal
            ))
            total += subtotal

        # 显示总价
        tk.Label(cart_window, text=f"总价: ¥{total:.2f}").pack(anchor=tk.E, padx=10, pady=5)

        # 操作按钮
        cart_btn_frame = tk.Frame(cart_window)
        cart_btn_frame.pack(pady=10)

        tk.Button(cart_btn_frame, text="增加数量",
                  command=lambda: self.update_quantity(cart_tree, cart_window, 1)).pack(side=tk.LEFT, padx=5)
        tk.Button(cart_btn_frame, text="减少数量",
                  command=lambda: self.update_quantity(cart_tree, cart_window, -1)).pack(side=tk.LEFT, padx=5)
        tk.Button(cart_btn_frame, text="删除商品", command=lambda: self.remove_from_cart(cart_tree, cart_window)).pack(
            side=tk.LEFT, padx=5)
        tk.Button(cart_btn_frame, text="结算", command=lambda: self.checkout(cart_window)).pack(side=tk.LEFT, padx=5)

    def update_quantity(self, tree, window, change):
        selected = tree.selection()
        if not selected:
            messagebox.showwarning("警告", "请先选择要修改的商品")
            return

        item = tree.item(selected[0])
        product_id = item["values"][0]
        current_quantity = int(item["values"][3])

        # 找到购物车中的对应商品
        for cart_item in self.cart:
            if cart_item["id"] == product_id:
                # 检查库存
                with open(PRODUCTS_FILE, "r") as f:
                    products = json.load(f)

                product_stock = next((p["stock"] for p in products if p["id"] == product_id), 0)

                if change > 0 and current_quantity >= product_stock:
                    messagebox.showwarning("警告", "商品库存不足")
                    return

                # 更新数量
                new_quantity = current_quantity + change
                if new_quantity < 1:
                    new_quantity = 1

                cart_item["quantity"] = new_quantity
                break

        # 关闭并重新打开购物车窗口以刷新数据
        window.destroy()
        self.view_cart()

    def remove_from_cart(self, tree, window):
        selected = tree.selection()
        if not selected:
            messagebox.showwarning("警告", "请先选择要删除的商品")
            return

        item = tree.item(selected[0])
        product_id = item["values"][0]

        # 从购物车中移除商品
        self.cart = [item for item in self.cart if item["id"] != product_id]

        # 关闭并重新打开购物车窗口以刷新数据
        window.destroy()
        self.view_cart()

    def checkout(self, window):
        if not self.cart:
            messagebox.showwarning("警告", "购物车为空,无法结算")
            return

        # 检查库存
        with open(PRODUCTS_FILE, "r") as f:
            products = json.load(f)

        for cart_item in self.cart:
            product = next((p for p in products if p["id"] == cart_item["id"]), None)
            if not product or cart_item["quantity"] > product["stock"]:
                messagebox.showwarning("警告", f"{cart_item['name']} 库存不足,无法结算")
                return

        # 计算总价
        total = sum(item["price"] * item["quantity"] for item in self.cart)

        # 确认结算
        if messagebox.askyesno("确认结算", f"总价: ¥{total:.2f}\n是否确认结算?"):
            # 更新库存
            for cart_item in self.cart:
                for product in products:
                    if product["id"] == cart_item["id"]:
                        product["stock"] -= cart_item["quantity"]
                        break

            with open(PRODUCTS_FILE, "w") as f:
                json.dump(products, f)

            # 保存订单
            import datetime
            with open(ORDERS_FILE, "r") as f:
                orders = json.load(f)

            order_id = len(orders) + 1
            order = {
                "order_id": order_id,
                "username": self.username,
                "products": self.cart,
                "total": total,
                "time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            }

            orders.append(order)
            with open(ORDERS_FILE, "w") as f:
                json.dump(orders, f)

            # 清空购物车
            self.cart = []
            window.destroy()
            messagebox.showinfo("成功", "结算成功!订单已生成")

    def run(self):
        self.window.mainloop()


if __name__ == "__main__":
    login = LoginWindow()
    login.run()

posted @ 2025-05-24 16:13  茆伟昊  阅读(29)  评论(0)    收藏  举报