|
|
import tkinter as tk
|
|
|
from tkinter import messagebox, simpledialog
|
|
|
from datetime import datetime
|
|
|
import mysql.connector
|
|
|
|
|
|
conn = mysql.connector.connect(
|
|
|
host="localhost",
|
|
|
user="root",
|
|
|
password="root",
|
|
|
database="sys"
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
class ParkingLotManager:
|
|
|
def __init__(self):
|
|
|
self.conn = mysql.connector.connect(
|
|
|
host="localhost",
|
|
|
user="root",
|
|
|
password="root",
|
|
|
database="sys"
|
|
|
)
|
|
|
self.cursor = self.conn.cursor()
|
|
|
|
|
|
# 初始化时从数据库加载定价规则
|
|
|
self.load_pricing_rules_from_db()
|
|
|
self.parked_vehicles = {} # 本地缓存,用于快速查询
|
|
|
|
|
|
def load_parked_vehicles_from_db(self):
|
|
|
"""从数据库加载已停车辆"""
|
|
|
self.cursor.execute("SELECT license_plate, vehicle_type, entry_time FROM parked_vehicles")
|
|
|
parked_data = self.cursor.fetchall()
|
|
|
for plate, vehicle_type, entry_time in parked_data:
|
|
|
self.parked_vehicles[plate] = {
|
|
|
'vehicle': Vehicle(plate, vehicle_type),
|
|
|
'entry_time': datetime.strptime(entry_time, "%Y-%m-%d %H:%M:%S")
|
|
|
}
|
|
|
|
|
|
# 添加一个新方法用于初始化App时加载数据
|
|
|
def initialize_data_on_login(self):
|
|
|
self.load_parked_vehicles_from_db()
|
|
|
# 在ParkingSystemApp的__init__方法中调用加载数据的方法
|
|
|
|
|
|
def open_main_system(parking_manager):
|
|
|
main_system_window = tk.Toplevel(login_window)
|
|
|
main_system_window.title("停车场管理系统 - 主功能")
|
|
|
|
|
|
# 在创建ParkingSystemApp实例前,先初始化数据
|
|
|
parking_manager.initialize_data_on_login()
|
|
|
|
|
|
app = ParkingSystemApp(main_system_window, parking_manager)
|
|
|
|
|
|
main_system_window.protocol("WM_DELETE_WINDOW", lambda: [main_system_window.destroy(), login_window.destroy()])
|
|
|
def __init__(self, master, parking_manager):
|
|
|
# ...其他初始化代码...
|
|
|
parking_manager.load_parked_vehicles_from_db()
|
|
|
self.update_ui_vehicles()
|
|
|
|
|
|
def park_vehicle(self, vehicle):
|
|
|
# 除了现有逻辑,还需要在数据库中记录入场时间
|
|
|
sql = "INSERT INTO parked_vehicles (license_plate, vehicle_type, entry_time) VALUES (%s, %s, %s)"
|
|
|
val = (vehicle.get_license_plate(), vehicle.get_vehicle_type(), datetime.now())
|
|
|
self.cursor.execute(sql, val)
|
|
|
self.conn.commit()
|
|
|
self.parked_vehicles[vehicle.get_license_plate()] = {'vehicle': vehicle, 'entry_time': datetime.now()}
|
|
|
|
|
|
def unpark_vehicle(self, license_plate):
|
|
|
# 除了现有逻辑,更新数据库中的出场时间和费用
|
|
|
vehicle_info = self.parked_vehicles.get(license_plate)
|
|
|
if vehicle_info:
|
|
|
exit_time = datetime.now()
|
|
|
hours_parked = (exit_time - vehicle_info['entry_time']).total_seconds() / 3600
|
|
|
vehicle_type = vehicle_info['vehicle'].get_vehicle_type()
|
|
|
fee = self.pricing_rules[vehicle_type].calculate_fee(hours_parked)
|
|
|
|
|
|
sql_update = "UPDATE parked_vehicles SET exit_time=%s, total_fee=%s WHERE license_plate=%s"
|
|
|
val = (exit_time, fee, license_plate)
|
|
|
self.cursor.execute(sql_update, val)
|
|
|
self.conn.commit()
|
|
|
|
|
|
del self.parked_vehicles[license_plate]
|
|
|
return fee
|
|
|
else:
|
|
|
raise ValueError("Vehicle not found in the system.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PricingRule:
|
|
|
def __init__(self, vehicle_type, hourly_rate, max_daily_rate=None):
|
|
|
self.vehicle_type = vehicle_type
|
|
|
self.hourly_rate = hourly_rate
|
|
|
self.max_daily_rate = max_daily_rate or float('inf')
|
|
|
|
|
|
def calculate_fee(self, hours_parked):
|
|
|
fee = hours_parked * self.hourly_rate
|
|
|
if self.max_daily_rate and fee > self.max_daily_rate:
|
|
|
return self.max_daily_rate
|
|
|
return fee
|
|
|
|
|
|
class Vehicle:
|
|
|
def __init__(self, license_plate, vehicle_type):
|
|
|
self.license_plate = license_plate
|
|
|
self.vehicle_type = vehicle_type
|
|
|
|
|
|
def get_license_plate(self):
|
|
|
return self.license_plate
|
|
|
|
|
|
def get_vehicle_type(self):
|
|
|
return self.vehicle_type
|
|
|
|
|
|
class ParkingLotManager:
|
|
|
def __init__(self):
|
|
|
self.pricing_rules = {}
|
|
|
self.parked_vehicles = {}
|
|
|
|
|
|
def add_pricing_rule(self, vehicle_type, hourly_rate, max_daily_rate=None):
|
|
|
self.pricing_rules[vehicle_type] = PricingRule(vehicle_type, hourly_rate, max_daily_rate)
|
|
|
|
|
|
def park_vehicle(self, vehicle):
|
|
|
self.parked_vehicles[vehicle.get_license_plate()] = {'vehicle': vehicle, 'entry_time': datetime.now()}
|
|
|
|
|
|
def unpark_vehicle(self, license_plate):
|
|
|
entry_time = self.parked_vehicles[license_plate]['entry_time']
|
|
|
parked_hours = (datetime.now() - entry_time).total_seconds() / 3600
|
|
|
vehicle_type = self.parked_vehicles[license_plate]['vehicle'].get_vehicle_type()
|
|
|
|
|
|
if vehicle_type in self.pricing_rules:
|
|
|
fee = self.pricing_rules[vehicle_type].calculate_fee(parked_hours)
|
|
|
del self.parked_vehicles[license_plate]
|
|
|
return fee
|
|
|
else:
|
|
|
raise ValueError("No pricing rule for this vehicle type.")
|
|
|
|
|
|
class ParkingSystemApp:
|
|
|
def __init__(self, master, parking_manager):
|
|
|
self.master = master
|
|
|
self.parking_manager = parking_manager
|
|
|
master.title("停车场管理系统")
|
|
|
|
|
|
self.vehicle_listbox = tk.Listbox(master, width=50)
|
|
|
self.vehicle_listbox.pack(pady=10)
|
|
|
|
|
|
self.search_entry = tk.Entry(master)
|
|
|
self.search_entry.pack(pady=5)
|
|
|
|
|
|
tk.Button(master, text="查询车辆", command=self.search_vehicle).pack(side=tk.LEFT, padx=5)
|
|
|
tk.Button(master, text="录入入场", command=self.add_vehicle).pack(side=tk.LEFT, padx=5)
|
|
|
tk.Button(master, text="删除出场", command=self.remove_vehicle).pack(side=tk.LEFT, padx=5)
|
|
|
tk.Button(master, text="退出系统", command=self.quit_app).pack(side=tk.RIGHT, padx=5)
|
|
|
|
|
|
# 示例数据,实际应用中应从数据库读取
|
|
|
self.vehicles = ["ABC123", "XYZ789", "CDE456"]
|
|
|
self.update_ui_vehicles()
|
|
|
|
|
|
def update_ui_vehicles(self):
|
|
|
self.vehicle_listbox.delete(0, tk.END)
|
|
|
for plate in self.parking_manager.parked_vehicles.keys():
|
|
|
self.vehicle_listbox.insert(tk.END, plate)
|
|
|
|
|
|
def search_vehicle(self):
|
|
|
query = self.search_entry.get().strip()
|
|
|
if query:
|
|
|
self.vehicle_listbox.delete(0, tk.END)
|
|
|
for plate in self.parking_manager.parked_vehicles.keys():
|
|
|
if query.lower() in plate.lower():
|
|
|
self.vehicle_listbox.insert(tk.END, plate)
|
|
|
|
|
|
def add_vehicle(self):
|
|
|
new_vehicle = simpledialog.askstring("录入车辆", "请输入车牌号:")
|
|
|
if new_vehicle and new_vehicle not in self.vehicles:
|
|
|
car = Vehicle(new_vehicle, "car")
|
|
|
parking_manager.park_vehicle(car) # 假设park_vehicle方法已更新数据库
|
|
|
self.update_ui_vehicles() # 添加车辆后立即刷新UI
|
|
|
|
|
|
def remove_vehicle(self):
|
|
|
selected = self.vehicle_listbox.curselection()
|
|
|
if selected:
|
|
|
plate = self.vehicle_listbox.get(selected[0])
|
|
|
fee = parking_manager.unpark_vehicle(plate)
|
|
|
messagebox.showinfo("停车费用", f"车辆 {plate} 的停车费用为:{fee}元")
|
|
|
self.update_ui_vehicles() # 移除车辆后刷新UI
|
|
|
|
|
|
def quit_app(self):
|
|
|
self.master.destroy()
|
|
|
|
|
|
def login_success(username_entry, password_entry, parking_manager):
|
|
|
expected_username = "1"
|
|
|
expected_password = "1" # 这里设置具体的密码
|
|
|
|
|
|
entered_username = username_entry.get().strip()
|
|
|
entered_password = password_entry.get().strip()
|
|
|
|
|
|
if entered_username == expected_username and entered_password == expected_password:
|
|
|
login_window.withdraw()
|
|
|
open_main_system(parking_manager)
|
|
|
else:
|
|
|
messagebox.showerror("登录失败", "用户名或密码错误,请重试。")
|
|
|
|
|
|
def open_main_system(parking_manager):
|
|
|
main_system_window = tk.Toplevel(login_window)
|
|
|
main_system_window.title("停车场管理系统 - 主功能")
|
|
|
app = ParkingSystemApp(main_system_window, parking_manager)
|
|
|
|
|
|
main_system_window.protocol("WM_DELETE_WINDOW", lambda: [main_system_window.destroy(), login_window.destroy()])
|
|
|
|
|
|
# 初始化停车场管理器
|
|
|
parking_manager = ParkingLotManager()
|
|
|
parking_manager.add_pricing_rule("car", 2, 20) # 小型车每小时2元,每日最高20元
|
|
|
|
|
|
# 登录界面
|
|
|
login_window = tk.Tk()
|
|
|
login_window.title("停车场管理系统 - 登录")
|
|
|
|
|
|
label_username = tk.Label(login_window, text="用户名:")
|
|
|
label_username.pack()
|
|
|
entry_username = tk.Entry(login_window)
|
|
|
entry_username.pack()
|
|
|
|
|
|
label_password = tk.Label(login_window, text="密码:")
|
|
|
label_password.pack()
|
|
|
entry_password = tk.Entry(login_window, show="*")
|
|
|
entry_password.pack()
|
|
|
|
|
|
button_login = tk.Button(login_window, text="登录", command=lambda: login_success(entry_username, entry_password, parking_manager))
|
|
|
button_login.pack(pady=10)
|
|
|
|
|
|
login_window.mainloop() |