首页 > Python资料 博客日记

数据库应用课程设计:航班管理及售票系统(SQL Server+Python)

2025-01-04 06:00:05Python资料围观157

文章数据库应用课程设计:航班管理及售票系统(SQL Server+Python)分享给大家,欢迎收藏Python资料网,专注分享技术知识

目录

1 项目描述

2系统需求分析

3 数据库的概念结构设计

4 数据库的逻辑设计和物理设计

5 创建数据库

6程序实现及性能评测

7 课程设计总结

8.附录:源代码


1 项目描述

一、问题背景与开发意义:

随着社会经济的持续发展和人民生活水平的提升,飞机已成为大众出行的重要方式之一。然而,传统的航班售票系统在面对日益增长的旅客需求和对服务便捷性的高期望时,显得力不从心,尤其是在信息查询速度、预订效率及航班管理灵活性上存在明显不足。因此,开发一套先进的航班管理和售票系统,不仅能够有效提升航空公司的运营效率和服务质量,也能极大地改善旅客的购票体验,增强机场的航班管理能力,是当前民航业现代化进程中的迫切需求。

二、技术要求:

本项目要求采用SQL Server数据库技术,构建一个高性能、高可用且安全稳定的航班管理和售票系统。系统应具备快速响应的查询引擎,支持大数据量处理,确保在高峰期也能提供流畅的用户体验。同时,系统设计需遵循模块化原则,以便于维护和扩展。

三、数据特征及处理需求:

数据涉及航班信息(如航班号、起降时间、起降地、票价、余票)、乘客信息(姓名、身份证号、联系方式)等,要求系统能高效存储、检索和更新这些数据。此外,系统还需处理航班数据添加功能。

四、外部影响因素:

(1)技术标准体系:需遵循国际民航组织(ICAO)及地区民航管理局的技术规范,确保数据交换和信息安全的标准化。

(2)法律法规:遵守《中华人民共和国个人信息保护法》、《网络安全法》等相关法律,严格保护用户隐私。

2系统需求分析

一、应用环境与设计目标:

本系统旨在构建一个覆盖航空公司、机场及终端用户的全方位航班管理和售票平台。设计目标是实现机票的快速查询与预订、航班信息的高效管理和实时更新、以及提供便捷的用户账户管理功能。

二、数据收集需求:

(1)航班信息:需实时同步航空公司发布的航班计划,包括航班时刻表、机型、票价等,要求数据更新迅速且准确。

(2)用户信息:收集并安全存储用户注册信息,确保信息加密存储,遵守数据保护法规。

(3)订单管理:记录每笔订单的详细信息,包括乘客列表、座位选择等,需设计高效的索引策略以加快查询速度。

三、用户功能需求:

(1)用户模块:支持快速注册与登录,提供友好的机票查询界面,允许按多个条件(如出发地、目的地、航班号)筛选航班,实现一键购票及乘客信息便捷输入。

(2)航空公司模块:航空公司可录入和管理航班及航线信息,对进出港航班信息进行监控和调整,快速响应航班变动,管理客户订单状态。

3 数据库的概念结构设计

一、抽象出实体

根据数据库的需要,可以抽象出下面实体:

(1)航班信息

(2)乘客信息

(3)用户信息

二、ER图

4 数据库的逻辑设计和物理设计

一、逻辑结构设计

关系模式如下:

(1)航班信息:航班号,航空公司,飞机机型,出发时间,出发机场,到达机场,是否延迟,价格,余票。

(2)乘客信息:乘客姓名,证件号,座位号,预定时间。

(3)用户信息:姓名,账号,密码,性别,年龄,电话号码。

二、物理结构设计

1.表结构概述:

(1)PassengerInfo(乘客信息表):

PassengerName: 乘客姓名,类型为可变长度字符串,最大长度50,不允许为空。

IDNumber: 证件号码,唯一标识,类型为可变长度字符串,最大长度20,不允许为空,作为主键。

SeatNumber: 座位号,类型为可变长度字符串,最大长度10。

ReservationTime: 预订时间,类型为日期时间。

(2)FlightInfo(航班信息表):

FlightNumber: 航班号,类型为可变长度字符串,最大长度10,不允许为空,作为主键。

AirlineCompany: 航空公司名称,类型为可变长度字符串,最大长度50。

AircraftModel: 机型,类型为可变长度字符串,最大长度50。

DepartureAirport: 出发机场,类型为可变长度字符串,最大长度50。

ArrivalAirport: 到达机场,类型为可变长度字符串,最大长度50。

IsDelayed: 是否延误,类型为BIT(布尔型),存储0或1。

DepartureTime: 起飞时间,类型为日期时间。

Price: 价格,类型为十进制数,小数点后保留两位。

RemainingTickets: 剩余票数,类型为整型。

(3)UserInfo(用户信息表):

UserName: 用户名,类型为可变长度字符串,最大长度50,不允许为空。

Account: 账户,唯一标识,类型为可变长度字符串,最大长度50,不允许为空,作为主键。

Password: 密码,类型为可变长度字符串,最大长度100,不允许为空。

Gender: 性别,类型为单个字符,通常用'M'表示男性,'F'表示女性等。

Age: 年龄,类型为TINYINT,即一个字节的有符号整数。

PhoneNumber: 电话号码,类型为可变长度字符串,最大长度15。

2.物理结构设计图解说明:

实体关系图(ERD):

PassengerInfo 和 FlightInfo 表之间存在关联,乘客信息表中的SeatNumber与航班信息表中的某个航班相关联。在实际设计中,需要在PassengerInfo表中加入指向FlightInfo表的外键,例如FlightNumber,以明确每个乘客预订的航班。

UserInfo 表独立,没有直接与其他表建立联系,它主要用来存储用户登录和基本信息。

3.索引策略:

在PassengerInfo表中,IDNumber由于是唯一标识,已经作为主键自动建立了索引。

在FlightInfo表中,FlightNumber作为主键也有索引。

在UserInfo表中,Account作为唯一标识且不允许重复,也是主键索引。

可能需要考虑在FlightInfo的DepartureTime、RemainingTickets等常用查询字段上建立索引,以加速查询。

4.存储分配:

各个表根据数据量和访问频率合理分配存储空间,考虑到FlightInfo和UserInfo可能数据量较大,而PassengerInfo则随时间增长,因此需预留足够的空间并适时调整。

5 创建数据库

1.创建数据库

CREATE DATABASE FlightDB;

2.创建航班信息表(FlightInfo)

CREATE TABLE FlightInfo (

    FlightNumber VARCHAR(10) NOT NULL,

    AirlineCompany VARCHAR(50),

    AircraftModel VARCHAR(50),

    DepartureAirport VARCHAR(50),

    ArrivalAirport VARCHAR(50),

    IsDelayed BIT,

DepartureTime DATETIME,

    Price DECIMAL(10, 2),

    RemainingTickets INT,

    PRIMARY KEY (FlightNumber)

);

3.创建乘客信息表(PassengerInfo)

CREATE TABLE PassengerInfo (

    PassengerName VARCHAR(50) NOT NULL,

    IDNumber VARCHAR(20) UNIQUE NOT NULL,

    SeatNumber VARCHAR(10),

    ReservationTime DATETIME,

    PRIMARY KEY (IDNumber)

);

4.创建用户信息表(UserInfo)

CREATE TABLE UserInfo (

    UserName VARCHAR(50) NOT NULL,

    Account VARCHAR(50) UNIQUE NOT NULL,

    Password VARCHAR(100) NOT NULL,

    Gender CHAR(1), -- 'M' for Male, 'F' for Female, etc.

    Age TINYINT,

    PhoneNumber VARCHAR(15),

    PRIMARY KEY (Account)

);

6程序实现及性能评测

一、程序的模块结构

程序是一个基于Tkinter GUI库构建的机场管理系统,主要由以下几个模块组成,每个模块负责系统的不同功能部分:

1. 主界面模块 (MainMenu类)

(1)功能: 系统的入口点,提供用户登录、航班管理和退出系统的功能。

(2)实现: 使用Tkinter创建图形界面,包括标题设置、窗口大小调整以及放置用户交互按钮。

(3)测试: 可通过启动程序验证窗口是否正确显示,按钮点击后是否能触发相应的功能调用。

2. 用户登录模块 (LoginWindow类)

(1)功能: 实现用户的登录验证,包括账号密码输入、登录按钮处理逻辑及注册按钮跳转。

(2)实现: 通过文本输入框获取用户输入的账号密码,使用SQL查询语句验证数据库中的用户信息,根据验证结果展示登录成功或失败的消息框,并相应跳转至航班查询或注册界面。

(3)测试: 输入正确的账号密码验证登录成功路径,输入错误信息验证登录失败路径,同时测试注册按钮是否能正确跳转。

3.注册界面模块 (RegisterWindow类)

(1)功能: 收集新用户的信息,包括账号、密码、姓名、电话、性别和年龄,并完成用户注册。

(2)实现: 通过一系列输入框和单选按钮收集用户输入信息,使用SQL INSERT语句将用户信息存入数据库。

(3)测试: 输入完整的用户信息进行注册,验证数据库中是否新增了相应的记录,同时测试输入格式错误或信息不完整时的错误处理。

4. 机票查询界面模块(FlightSearchWindow类)

(1)功能: 用户输入出发城市、到达城市和航班号这三项中的任意一项,点击查询按钮可以查询符合条件的航班,如果上面都不输入则查找所有的航班,可以实现模糊查询。

(2)实现: 创建输入框用于用户输入,使用ttk.Entry和ttk.Button组件。查询航班逻辑: 绑定查询按钮的command属性到查询航班的方法,如query_flight。在该方法中,从输入框获取用户输入,构建SQL查询语句,使用pyodbc执行查询以获取航班信息。结果显示: 将查询结果展示在一个tk.Listbox组件中,每一行代表一个航班,展示航班号、航空公司、起飞时间等信息。

(3)测试: 单元测试: 对query_flight方法进行单元测试,检查是否能正确构造SQL查询语句,以及在无数据、有数据和异常数据情况下是否能正确处理。集成测试: 测试整个机票查询流程,包括输入数据、点击查询按钮后能否正确显示航班信息。界面测试: 确认UI布局合理,输入框和按钮功能正常,列表框能够正确展示查询结果。

(4)结果:

​​​​​

5. 订单页面模块(OrderWindow类)

(1)功能: 用户输入乘客姓名、证件号和座位号,最后点击完成预订后弹出一个预定成功窗口,即可完成订票。

(2)实现: 展示选定航班的基本信息,并提供输入框供用户输入乘客姓名、证件号和座位号,最后有一个完成预订的按钮。当用户点击“完成预订”按钮时,收集乘客信息,执行SQL语句将预订信息保存至数据库。

(3)测试: 从航班查询界面选择航班后进入订单界面,输入合法的乘客信息完成预订,检查数据库中是否生成了相应的预订记录。

6.航班管理模块 (FlightManagement类)

(1)功能: 查询航班信息,包括提供输入框查询特定航班、展示查询结果的列表框,以及修改和删除航班的功能。

(2)实现: 用户输入航班号后,执行SQL查询获取航班信息并展示,提供修改和删除按钮以对查询结果进行操作。

(3)测试: 输入已知航班号验证查询功能,尝试修改和删除操作检查数据库是否正确响应。

(4)结果:

7.修改航班信息模块 (ModifyFlightWindow类)

(1)功能: 允许管理员修改已存在的航班信息。

(2)实现: 弹出窗口显示当前航班信息,允许编辑并提交修改,提交后更新数据库中的航班信息。

(3)测试: 选择一个航班进行修改,验证修改后的信息是否正确反映在数据库中。

8.添加航班信息模块(AddFlightWindow类)

(1)功能: 在输入框内输入航班号、航空公司、机型、出发机场、是否延误、起飞时间和价格、余票后点击确认添加按钮即可实现添加航班信息功能。

(2)实现: 通过一系列输入框和单选按钮收集航班输入信息,使用SQL INSERT语句将航班信息存入数据库。

(3)测试: 输入完整的航班信息进行注册,验证数据库中是否新增了相应的记录,同时测试输入格式错误或信息不完整时的错误处理。

7 课程设计总结

1.成果亮点

成功设计了一套高效、安全且易于维护的数据库结构,涵盖了航班信息、乘客信息、用户信息三大核心模块。通过SQL Server技术的运用,确保了数据处理的高性能和安全性。逻辑与物理设计的合理性得到了充分论证,特别是通过合理设置索引,显著提升了查询效率。

我开发了包含用户登录、航班查询、机票预订、航班管理等在内的核心功能模块。使用Tkinter库构建的GUI界面友好、操作便捷,有效地提升了用户体验。通过pyodbc库实现了与数据库的无缝对接,保证了数据操作的准确性和实时性。

2.不足与改进方向

用户体验:尽管系统功能完善,但在用户界面的友好度和易用性上仍有提升空间。未来可以进一步优化GUI设计,如减少不必要的界面重绘,提高操作流畅度。

并发处理能力:虽然我们进行了并发处理的优化,但在极端高并发场景下,系统的响应速度和稳定性仍有待加强。考虑引入更先进的缓存策略和技术,如分布式缓存,以减轻数据库压力。

模块化与扩展性:虽然遵循了模块化设计原则,但随着系统的扩展,模块间的耦合度可能增加。未来应更精细地划分模块,提升系统的可维护性和扩展性。

8.附录:源代码
 

import tkinter as tk
import pyodbc
from tkinter import messagebox,ttk,PhotoImage
from datetime import datetime
from decimal import Decimal, InvalidOperation

#主页面
class MainMenu(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("机场管理系统 - 主界面")
        self.geometry("500x250")

        # 用户登录按钮
        tk.Button(self, text="用户登录", command=self.open_login_window).pack(pady=10)

        # 航班管理按钮
        tk.Button(self, text="航班管理", command=self.open_flight_management).pack(pady=10)
        
        # 退出系统按钮
        tk.Button(self, text="退出系统", command=self.quit_app).pack(pady=10)
        
    def open_login_window(self):
        """跳转到用户登录界面"""
        LoginWindow(self)
        
    def open_flight_management(self):
        """跳转到航班管理界面"""
        FlightManagement(self)
        
    def quit_app(self):
        """退出应用程序"""
        conn.close()
        print("数据库连接已关闭。")
        self.destroy()

# 登录界面类
class LoginWindow(tk.Toplevel):
    def __init__(self, master=None):
        super().__init__(master)
        self.master = master
        self.title("用户登录")
        self.geometry("1000x500")

        # 用户名标签和输入框
        tk.Label(self, text="账号:").pack()
        self.username_entry = tk.Entry(self)
        self.username_entry.pack()

        # 密码标签和输入框
        tk.Label(self, text="密码:").pack()
        self.password_entry = tk.Entry(self, show="*")  # 显示星号隐藏密码
        self.password_entry.pack()

        # 登录按钮
        tk.Button(self, text="登录", command=self.login).pack(pady=10)

        # 注册按钮,点击跳转到注册界面
        tk.Button(self, text="注册", command=self.to_register).pack()

    def login(self):
        #登录逻辑,连接数据库验证
        username = self.username_entry.get()
        password = self.password_entry.get()
        query = "SELECT COUNT(*) FROM UserInfo WHERE Account=? AND Password=?"
        cursor.execute(query, (username, password))
        # 获取查询结果
        count = cursor.fetchone()[0]
        if count > 0:
            #messagebox.showinfo("登录提示", "登录成功!")
            self.destroy()
            #跳转到航班查询界面
            FlightSearchWindow(self.master)
        else:
            messagebox.showinfo("登录提示", "登录失败,用户名或密码错误")

    def to_register(self):
        #关闭登录窗口,打开注册窗口
        self.destroy()
        RegisterWindow(self.master)

# 注册界面类
class RegisterWindow(tk.Toplevel):
    def __init__(self, master=None):
        super().__init__(master)
        self.master = master
        self.title("用户注册")
        self.geometry("1000x500")

        # 各种输入框和标签
        tk.Label(self, text="账号:").pack()
        self.reg_username_entry = tk.Entry(self)
        self.reg_username_entry.pack()

        tk.Label(self, text="密码:").pack()
        self.reg_password_entry = tk.Entry(self, show="*")
        self.reg_password_entry.pack()

        tk.Label(self, text="姓名:").pack()
        self.name_entry = tk.Entry(self)
        self.name_entry.pack()

        tk.Label(self, text="电话:").pack()
        self.phone_entry = tk.Entry(self)
        self.phone_entry.pack()

        tk.Label(self, text="性别:").pack()
        self.gender_var = tk.StringVar(value="M")
        tk.Radiobutton(self, text="男", variable=self.gender_var, value="M").pack()
        tk.Radiobutton(self, text="女", variable=self.gender_var, value="F").pack()

        tk.Label(self, text="年龄:").pack()
        self.age_entry = tk.Entry(self)
        self.age_entry.pack()

        # 注册按钮
        tk.Button(self, text="注册", command=self.register).pack(pady=10)

        # 返回登录按钮
        tk.Button(self, text="返回登录", command=self.to_login).pack()

    def register(self):
        #注册逻辑
        username = self.reg_username_entry.get()
        password = self.reg_password_entry.get()
        name = self.name_entry.get()
        phone = self.phone_entry.get()
        gender = self.gender_var.get()
        age = self.age_entry.get()
        users_data = [(name,username,password,gender,age,phone)]
         
        try:
            for user in users_data:
                query = """
                    INSERT INTO UserInfo (UserName, Account, Password, Gender, Age, PhoneNumber)
                    VALUES (?, ?, ?, ?, ?, ?)
                """
                cursor.execute(query, user)  
            # 提交事务
            conn.commit()
            messagebox.showinfo("注册提示","注册成功")
        except pyodbc.Error as e:
            # 如果发生错误,回滚事务
            conn.rollback()
            print(f"数据插入失败: {e}")

    def to_login(self):
        #关闭注册窗口,回到登录界面
        self.destroy()
        LoginWindow(self.master)

#机票查询界面
class FlightSearchWindow(tk.Toplevel):
    def __init__(self, master=None, flight_data=None):
        super().__init__(master)
        self.master = master
        self.title("机票查询")
        self.geometry("1000x500")

        tk.Label(self, text="出发城市").pack()
        self.departure = tk.Entry(self)
        self.departure.pack()
        
        tk.Label(self, text="到达城市").pack()
        self.arrival = tk.Entry(self)
        self.arrival.pack()

        # 输入框和查询按钮
        tk.Label(self, text="航班号").pack()
        self.flight_number_entry = ttk.Entry(self)
        self.flight_number_entry.pack(pady=10)
        
        self.query_button = ttk.Button(self, text="查询航班", command=self.query_flight)
        self.query_button.pack(pady=5)
        
        # 显示航班信息的列表框
        self.flight_listbox = tk.Listbox(self, width=100, height=10)
        self.flight_listbox.pack(pady=10)
        
        self.modify_button = ttk.Button(self, text="选择并预订", command=self.order_flight, state=tk.DISABLED)
        self.modify_button.pack(pady=5)
        
        self.flight_info = None

    def query_flight(self):
        departure_city = self.departure.get()
        arrival_city = self.arrival.get()
        flight_number = self.flight_number_entry.get().strip() + "%" if self.flight_number_entry.get().strip() else "%"
        # 构建查询条件
        conditions = []
        params = []
        if departure_city:
            conditions.append("DepartureAirport LIKE ?")
            params.append("%" + departure_city + "%")
        if arrival_city:
            conditions.append("ArrivalAirport LIKE ?")
            params.append("%" + arrival_city + "%")
        if flight_number != "%":
            conditions.append("FlightNumber LIKE ?")
            params.append(flight_number)

        # 构建完整的SQL查询语句
        query_conditions = " AND ".join(conditions)
        query = f"""SELECT * FROM FlightInfo WHERE {query_conditions if query_conditions else '1=1'}"""

        cursor.execute(query, tuple(params))
        self.flight_info = cursor.fetchall()
        self.update_flight_list()
        if self.flight_info:
            self.modify_button.config(state=tk.NORMAL)

    def update_flight_list(self):
        self.flight_listbox.delete(0, tk.END)
        for flight in self.flight_info:
            info_str = ', '.join(str(item) for item in flight)
            self.flight_listbox.insert(tk.END, info_str)

    def order_flight(self):
        selected_index = self.flight_listbox.curselection()
        if selected_index:
            # 获取选中行的索引
            selected_index = selected_index[0]
            # 确保所选索引在查询结果范围内
            if 0 <= selected_index < len(self.flight_info):
                selected_flight = self.flight_info[selected_index]
                flight_number = selected_flight[0]
                # 确保字段顺序与数据库列顺序一致
                flight_data_columns = [
                    "FlightNumber", "AirlineCompany", "AircraftModel", "DepartureAirport",
                    "ArrivalAirport", "IsDelayed", "DepartureTime", "Price", "RemainingTickets"
                ]
                # 使用zip确保字段名与值一一对应
                flight_data_dict = dict(zip(flight_data_columns, selected_flight))
                # 确保传递给ModifyFlightWindow的字典包含实际的数据库值
                OrderWindow(self, flight_data_dict, flight_number=flight_number)
            else:
                tk.messagebox.showerror("错误", "未选择有效的航班。")
        else:
            tk.messagebox.showinfo("提示", "请先选择一个航班进行预定。")


#订单界面
class OrderWindow(tk.Toplevel):
    def __init__(self, master, initial_flight_data, flight_number):
        super().__init__(master)
        self.master = master
        self.title("订单界面")
        self.geometry("1000x500")
        self.initial_flight_data = initial_flight_data
        self.flight_number = flight_number

        # 显示航班信息
        self.display_flight_info(initial_flight_data)

        # 乘客信息输入
        tk.Label(self, text="乘客姓名:").pack()
        self.passenger_name_entry = tk.Entry(self)
        self.passenger_name_entry.pack()

        tk.Label(self, text="证件号:").pack()
        self.id_number_entry = tk.Entry(self)
        self.id_number_entry.pack()

        tk.Label(self, text="座位号:").pack()
        self.seat_number_entry = tk.Entry(self)
        self.seat_number_entry.pack()

        # 完成预定按钮
        tk.Button(self, text="完成预定", command=self.complete_order).pack(pady=10)

    def display_flight_info(self, flight_info):
        """显示航班信息的简化示例"""
        info_text = f"航班信息:\n出发日期:{flight_info['DepartureTime']}\n出发城市:{flight_info['DepartureAirport']}\n到达城市:{flight_info['ArrivalAirport']}"
        tk.Label(self, text=info_text, justify=tk.LEFT, padx=20, pady=20).pack()

    def complete_order(self):
        """模拟完成预定操作,然后返回查询界面"""
        passenger_name = self.passenger_name_entry.get()
        id_number = self.id_number_entry.get()
        seat_number = self.seat_number_entry.get()
        passenger_data =[(passenger_name,id_number,seat_number)]
        try:
            for passenger in passenger_data:
                query = """
                    INSERT INTO PassengerInfo (PassengerName,IDNumber, SeatNumber,ReservationTime)
                    VALUES (?, ?, ?,GETDATE())
                """
                cursor.execute(query, passenger)  
            # 提交事务
            conn.commit()
            messagebox.showinfo("预定成功", f"乘客:{passenger_name},预定成功!\n证件号:{id_number}\n座位号:{seat_number}")
        except pyodbc.Error as e:
            # 如果发生错误,回滚事务
            conn.rollback()
            print(f"数据插入失败: {e}")
        self.destroy()


class ModifyFlightWindow(tk.Toplevel):
    """修改航班信息的弹出窗口"""
    def __init__(self, master, initial_flight_data, flight_number):
        super().__init__(master)
        self.title("修改航班信息")
        self.geometry("800x600")
        self.initial_flight_data = initial_flight_data
        self.flight_number = flight_number

        # 构建表单输入
        self.form_frame = ttk.Frame(self)
        self.form_frame.pack(padx=20, pady=20, fill=tk.BOTH)
        
        self.inputs = {}
        for field in initial_flight_data.keys():
            label = ttk.Label(self.form_frame, text=field.capitalize())
            label.grid(row=len(self.inputs), column=0, padx=5, pady=5, sticky='w')
            
            var = tk.StringVar(value=initial_flight_data[field])
            entry = ttk.Entry(self.form_frame, textvariable=var)
            entry.grid(row=len(self.inputs), column=1, padx=5, pady=5)
            self.inputs[field] = (label, entry)
            
        # 提交按钮
        self.submit_button = ttk.Button(self, text="提交修改", command=self.submit_modification)
        self.submit_button.pack(pady=10)

    def submit_modification(self):
        """收集表单数据并更新数据库"""
        updated_data = {field: entry.get() for field, (label, entry) in self.inputs.items()}
        update_flight_in_db(self.flight_number, updated_data)
        self.destroy()
        tk.messagebox.showinfo("成功", "航班信息已成功修改!")

def update_flight_in_db(flight_id, updated_data):
    """更新数据库中的航班信息"""
    set_clauses = ', '.join([f"{col} = ?" for col in updated_data.keys()])
    query = f"UPDATE FlightInfo SET {set_clauses} WHERE FlightNumber = ?"
    values = list(updated_data.values()) + [flight_id]
    cursor.execute(query, values)
    conn.commit()


class AddFlightWindow(tk.Toplevel):
    """添加航班信息的弹出窗口"""
    def __init__(self, master):
        super().__init__(master)
        self.title("添加航班信息")
        self.geometry("800x600")
        # 各种输入框和标签
        tk.Label(self, text="航班号:").pack()
        self.FlightNumber_entry = tk.Entry(self)
        self.FlightNumber_entry.pack()

        tk.Label(self, text="航空公司:").pack()
        self.AirlineCompany_entry = tk.Entry(self)
        self.AirlineCompany_entry.pack()

        tk.Label(self, text="机型:").pack()
        self.AircraftModel_entry = tk.Entry(self)
        self.AircraftModel_entry.pack()

        tk.Label(self, text="出发机场:").pack()
        self.DepartureAirport_entry = tk.Entry(self)
        self.DepartureAirport_entry.pack()

        tk.Label(self, text="是否延误:").pack()
        self.IsDelayed_var = tk.StringVar(value="True")
        tk.Radiobutton(self, text="是", variable=self.IsDelayed_var, value="True").pack()
        tk.Radiobutton(self, text="否", variable=self.IsDelayed_var, value="False").pack()

        tk.Label(self, text="起飞时间:").pack()
        self.DepartureTime_entry = tk.Entry(self)
        self.DepartureTime_entry.pack()

        tk.Label(self, text="价格:").pack()
        self.Price_entry = tk.Entry(self)
        self.Price_entry.pack()

        tk.Label(self, text="余票:").pack()
        self.RemainingTickets_entry = tk.Entry(self)
        self.RemainingTickets_entry.pack()

        # 插入按钮
        tk.Button(self, text="确认添加", command=self.addflight).pack(pady=10)

        # 退出按钮
        tk.Button(self, text="退出", command=self.to_management).pack()

    def addflight(self):
        #注册逻辑
        FlightNumber = self.FlightNumber_entry.get()
        AirlineCompany = self.AirlineCompany_entry.get()
        AircraftModel = self.AircraftModel_entry.get()
        DepartureAirport = self.DepartureAirport_entry.get()
        IsDelayed = self.IsDelayed_var.get()
        DepartureTime = self.DepartureTime_entry.get()
        Price = self.Price_entry.get()
        RemainingTickets = self.RemainingTickets_entry.get()
        flight_data = [(FlightNumber,AirlineCompany,AircraftModel,DepartureAirport,IsDelayed,DepartureTime,Price,RemainingTickets)]
        
        try:
            for user in flight_data:
                query = """
                    INSERT INTO FlightInfo (FlightNumber,AirlineCompany,AircraftModel,DepartureAirport,IsDelayed,DepartureTime,Price,RemainingTickets)
                    VALUES (?, ?, ?, ?, ?, ?, ?, ?)
                """
                cursor.execute(query, user)  
            # 提交事务
            conn.commit()
            messagebox.showinfo("添加提示","添加成功")
        except pyodbc.Error as e:
            # 如果发生错误,回滚事务
            conn.rollback()
            print(f"数据插入失败: {e}")

    def to_management(self):
        #关闭插入窗口,回到管理界面
        self.destroy()
        FlightManagement(self.master)



class FlightManagement(tk.Toplevel):
    def __init__(self, master=None, flights=None):
        super().__init__(master)
        self.master = master
        self.title("查询班次")
        self.geometry("1000x600")
        
        # 输入框和查询按钮
        self.flight_number_entry = ttk.Entry(self)
        self.flight_number_entry.pack(pady=10)
        
        self.query_button = ttk.Button(self, text="查询航班", command=self.query_flight)
        self.query_button.pack(pady=5)
        
        # 显示航班信息的列表框
        self.flight_listbox = tk.Listbox(self, width=100, height=20)
        self.flight_listbox.pack(pady=10)
        
        # 修改按钮
        self.modify_button = ttk.Button(self, text="修改选中航班", command=self.modify_flight, state=tk.DISABLED)
        self.modify_button.pack(pady=5)

        # 删除按钮
        self.delete_button = ttk.Button(self, text="删除选中航班", command=self.delete_flight, state=tk.DISABLED)
        self.delete_button.pack(pady=5)

        # 添加按钮
        self.add_button = ttk.Button(self, text="添加航班数据", command=self.add_flight, state=tk.NORMAL)
        self.add_button.pack(pady=5)
        
        self.flight_info = None
    
    def add_flight(self):
        """打开窗口以添加新的航班信息"""
        AddFlightWindow(self)

    def query_flight(self):
        flight_number = self.flight_number_entry.get()

        query = """SELECT * FROM FlightInfo WHERE FlightNumber like ?"""
        flight_number=flight_number+"%"
        cursor.execute(query,flight_number)
        self.flight_info = cursor.fetchall()
        self.update_flight_list()
        if self.flight_info:
            self.modify_button.config(state=tk.NORMAL)
            self.delete_button.config(state=tk.NORMAL)  # 添加这行来启用删除按钮
        else:
            self.modify_button.config(state=tk.DISABLED)
            self.delete_button.config(state=tk.DISABLED)
            
    def update_flight_list(self):
        self.flight_listbox.delete(0, tk.END)
        for flight in self.flight_info:
            info_str = ', '.join(str(item) for item in flight)
            self.flight_listbox.insert(tk.END, info_str)
    
    def delete_flight(self):
        selected_index = self.flight_listbox.curselection()
        if selected_index:
            # 获取选中行的索引
            selected_index = selected_index[0]
            # 确保所选索引在查询结果范围内
            if 0 <= selected_index < len(self.flight_info):
                # 确认用户是否真的想删除该航班
                confirm = tk.messagebox.askyesno("确认删除", "确定要删除此航班吗?")
                if confirm:
                    selected_flight = self.flight_info[selected_index]
                    flight_number = selected_flight[0]

                    # 执行删除操作
                    delete_query = "DELETE FROM FlightInfo WHERE FlightNumber = ?"
                    cursor.execute(delete_query, (flight_number,))
                    conn.commit()  # 提交删除操作到数据库
                    
                    # 更新UI
                    tk.messagebox.showinfo("删除成功", f"航班{flight_number}已成功删除。")
                    self.update_flight_list()  # 刷新航班列表
                    self.modify_button.config(state=tk.DISABLED)  # 删除后禁用修改按钮
                    self.delete_button.config(state=tk.DISABLED)  # 同时禁用删除按钮
            else:
                tk.messagebox.showerror("错误", "未选择有效的航班记录。")
        else:
            tk.messagebox.showinfo("提示", "请先选择一个航班进行删除。")

    def modify_flight(self):
        selected_index = self.flight_listbox.curselection()
        if selected_index:
            # 获取选中行的索引
            selected_index = selected_index[0]
            # 确保所选索引在查询结果范围内
            if 0 <= selected_index < len(self.flight_info):
                selected_flight = self.flight_info[selected_index]
                flight_number = selected_flight[0]
                # 确保字段顺序与数据库列顺序一致
                flight_data_columns = [
                    "FlightNumber", "AirlineCompany", "AircraftModel", "DepartureAirport",
                    "ArrivalAirport", "IsDelayed", "DepartureTime", "Price", "RemainingTickets"
                ]
                # 使用zip确保字段名与值一一对应
                flight_data_dict = dict(zip(flight_data_columns, selected_flight))
                # 确保传递给ModifyFlightWindow的字典包含实际的数据库值
                ModifyFlightWindow(self, flight_data_dict, flight_number=flight_number)
            else:
                tk.messagebox.showerror("错误", "未选择有效的航班记录。")
        else:
            tk.messagebox.showinfo("提示", "请先选择一个航班进行修改。")

# 主程序启动
if __name__ == "__main__":
    #连接数据库
    conn_str = (
    'DRIVER={ODBC Driver 17 for SQL Server};'
    'SERVER=127.0.0.1;'
    'DATABASE=FlightDB;'
    'UID=sa;'
    'PWD=123456;'
    )

    try:
        # 尝试建立到SQL Server的连接
        conn = pyodbc.connect(conn_str)
        print("数据库连接成功!")
        # 创建游标
        cursor = conn.cursor()
    except pyodbc.Error as e:
        # 如果连接过程中发生错误,打印错误信息
        print(f"数据库连接时发生错误: {e}")

    root = tk.Tk()
    root.withdraw()
    app = MainMenu()
    app.mainloop()


版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!

标签:

相关文章

本站推荐