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()
浙公网安备 33010602011771号