diff --git a/Project/Manager/data_source/airports/airports.sql b/Project/Manager/data_source/airports/airports.sql index e0eb444..4f54354 100644 --- a/Project/Manager/data_source/airports/airports.sql +++ b/Project/Manager/data_source/airports/airports.sql @@ -1,4 +1,4 @@ -INSERT INTO Airports (`ID`, `Name`, City) VALUES +INSERT INTO ServiceDatabase.Airports (`ID`, `Name`, City) VALUES ('NAY', '北京南苑机场', '北京'), ('PEK', '北京首都国际机场', '北京'), ('TSN', '天津滨海国际机场', '天津'), diff --git a/Project/Manager/data_source/db_user.sql b/Project/Manager/data_source/db_user.sql index e69de29..c6854c0 100644 --- a/Project/Manager/data_source/db_user.sql +++ b/Project/Manager/data_source/db_user.sql @@ -0,0 +1,17 @@ +DROP USER IF EXISTS 'serviceAgent'@'%'; +DROP USER IF EXISTS 'managerAgent'@'%'; +CREATE USER 'serviceAgent'@'%' IDENTIFIED BY 'password123'; +CREATE USER 'managerAgent'@'%' IDENTIFIED BY 'password123'; + +GRANT SELECT ON ManagerDatabase.Managers TO 'managerAgent'@'%'; +GRANT ALL PRIVILEGES ON ServiceDatabase.Flights TO 'managerAgent'@'%'; + +GRANT ALL PRIVILEGES ON ServiceDatabase.Passengers TO 'serviceAgent'@'%'; +GRANT ALL PRIVILEGES ON ServiceDatabase.Orders TO 'serviceAgent'@'%'; +GRANT ALL PRIVILEGES ON ServiceDatabase.Users TO 'serviceAgent'@'%'; +GRANT ALL PRIVILEGES ON ServiceDatabase.Airports TO 'serviceAgent'@'%'; +GRANT ALL PRIVILEGES ON ServiceDatabase.Tickets TO 'serviceAgent'@'%'; +GRANT SELECT, UPDATE (First_class_seats_remaining, Business_class_seats_remaining, Economy_class_seats_remaining) +ON ServiceDatabase.Flights TO 'serviceAgent'@'%'; + +FLUSH PRIVILEGES; \ No newline at end of file diff --git a/Project/Manager/data_source/flights/add.csv b/Project/Manager/data_source/flights/add.csv new file mode 100644 index 0000000..3b5dc0e --- /dev/null +++ b/Project/Manager/data_source/flights/add.csv @@ -0,0 +1,3 @@ +ID,Airline,Departure_airport,Arrival_airport,Departure_time,Arrival_time,First_class_seats_remaining,Business_class_seats_remaining,Economy_class_seats_remaining,First_class_price,Business_class_price,Economy_class_price,Status +FL321,AirlineE,PEK,PVG,2024-06-16 11:00:00,2024-06-16 12:30:00,5,10,100,2000.00,1000.00,500.00,未知 +FL421,AirlineG,PEK,PVG,2024-06-16 11:00:00,2024-06-16 12:30:00,3,10,100,2000.00,1000.00,500.00,未知 \ No newline at end of file diff --git a/Project/Manager/data_source/flights/flights.sql b/Project/Manager/data_source/flights/flights.sql index ce3320d..f33acb3 100644 --- a/Project/Manager/data_source/flights/flights.sql +++ b/Project/Manager/data_source/flights/flights.sql @@ -1,4 +1,4 @@ -INSERT INTO Flights (ID, Airline, Departure_airport, Arrival_airport, Departure_time, Arrival_time, First_class_seats_remaining, Business_class_seats_remaining, Economy_class_seats_remaining, First_class_price, Business_class_price, Economy_class_price, `Status`) VALUES +INSERT INTO ServiceDatabase.Flights (ID, Airline, Departure_airport, Arrival_airport, Departure_time, Arrival_time, First_class_seats_remaining, Business_class_seats_remaining, Economy_class_seats_remaining, First_class_price, Business_class_price, Economy_class_price, `Status`) VALUES ('FL001', 'AirlineA', 'PEK', 'SHA', '2024-06-14 08:00:00', '2024-06-14 10:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '已降落'), ('FL002', 'AirlineB', 'TSN', 'PVG', '2024-06-14 09:00:00', '2024-06-14 11:00:00', 3, 15, 80, 2100.00, 1100.00, 600.00, '已降落'), ('FL003', 'AirlineC', 'SHA', 'SZX', '2024-06-14 07:00:00', '2024-06-14 09:00:00', 2, 12, 70, 2200.00, 1200.00, 550.00, '已降落'), diff --git a/Project/Manager/data_source/init_manager_db.sql b/Project/Manager/data_source/init_manager_db.sql index 053349a..9fd6896 100644 --- a/Project/Manager/data_source/init_manager_db.sql +++ b/Project/Manager/data_source/init_manager_db.sql @@ -1,9 +1,13 @@ -DROP TABLE IF EXISTS Managers; +DROP DATABASE IF EXISTS ManagerDatabase; +CREATE DATABASE ManagerDatabase; +ALTER DATABASE ManagerDatabase CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; -CREATE TABLE Managers ( +DROP TABLE IF EXISTS ManagerDatabase.Managers; + +CREATE TABLE ManagerDatabase.Managers ( ID VARCHAR(255) PRIMARY KEY, `Password` VARCHAR(255) NOT NULL ); -INSERT INTO Managers +INSERT INTO ManagerDatabase.Managers VALUES ('Admin', 'e10adc3949ba59abbe56e057f20f883e'); \ No newline at end of file diff --git a/Project/Manager/data_source/init_service_db.sql b/Project/Manager/data_source/init_service_db.sql index 803a8ec..e5e23ad 100644 --- a/Project/Manager/data_source/init_service_db.sql +++ b/Project/Manager/data_source/init_service_db.sql @@ -1,11 +1,15 @@ -DROP TABLE IF EXISTS Tickets; -DROP TABLE IF EXISTS Orders; -DROP TABLE IF EXISTS Users; -DROP TABLE IF EXISTS Flights; -DROP TABLE IF EXISTS Airports; -DROP TABLE IF EXISTS Passengers; +DROP DATABASE IF EXISTS ServiceDatabase; +CREATE DATABASE ServiceDatabase; +ALTER DATABASE ServiceDatabase CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; -CREATE TABLE Passengers ( +DROP TABLE IF EXISTS ServiceDatabase.Tickets; +DROP TABLE IF EXISTS ServiceDatabase.Orders; +DROP TABLE IF EXISTS ServiceDatabase.Users; +DROP TABLE IF EXISTS ServiceDatabase.Flights; +DROP TABLE IF EXISTS ServiceDatabase.Airports; +DROP TABLE IF EXISTS ServiceDatabase.Passengers; + +CREATE TABLE ServiceDatabase.Passengers ( ID VARCHAR(18) PRIMARY KEY, `Name` VARCHAR(255) NOT NULL, Phone_number BIGINT NOT NULL, @@ -13,20 +17,20 @@ CREATE TABLE Passengers ( CHECK (REGEXP_LIKE(Phone_number, '^\\d{11}$')) ); -CREATE TABLE Users ( +CREATE TABLE ServiceDatabase.Users ( Phone_number BIGINT PRIMARY KEY, Username VARCHAR(255) NOT NULL, `Password` VARCHAR(255) NOT NULL, CHECK (REGEXP_LIKE(Phone_number, '^\\d{11}$')) ); -CREATE TABLE Airports ( +CREATE TABLE ServiceDatabase.Airports ( ID VARCHAR(3) PRIMARY KEY, -- 机场三字码 `Name` VARCHAR(255) UNIQUE NOT NULL, City VARCHAR(255) NOT NULL ); -CREATE TABLE Flights ( +CREATE TABLE ServiceDatabase.Flights ( ID VARCHAR(255) PRIMARY KEY, Airline VARCHAR(255) NOT NULL, Departure_airport VARCHAR(3) NOT NULL, @@ -45,7 +49,7 @@ CREATE TABLE Flights ( CHECK (Departure_time < Arrival_time) ); -CREATE TABLE Orders ( +CREATE TABLE ServiceDatabase.Orders ( ID INT AUTO_INCREMENT PRIMARY KEY, Order_time DATETIME NOT NULL, Paid TINYINT NOT NULL, @@ -53,7 +57,7 @@ CREATE TABLE Orders ( FOREIGN KEY (User_phone_number) REFERENCES Users(Phone_number) ON DELETE CASCADE ); -CREATE TABLE Tickets ( +CREATE TABLE ServiceDatabase.Tickets ( ID INT AUTO_INCREMENT PRIMARY KEY, Price DECIMAL(7, 2) NOT NULL, FlightID VARCHAR(255) NOT NULL, diff --git a/Project/Manager/func/__pycache__/config.cpython-311.pyc b/Project/Manager/func/__pycache__/config.cpython-311.pyc new file mode 100644 index 0000000..d7c779a Binary files /dev/null and b/Project/Manager/func/__pycache__/config.cpython-311.pyc differ diff --git a/Project/Manager/func/__pycache__/index.cpython-311.pyc b/Project/Manager/func/__pycache__/index.cpython-311.pyc new file mode 100644 index 0000000..acbb2fb Binary files /dev/null and b/Project/Manager/func/__pycache__/index.cpython-311.pyc differ diff --git a/Project/Manager/func/__pycache__/login.cpython-311.pyc b/Project/Manager/func/__pycache__/login.cpython-311.pyc new file mode 100644 index 0000000..0487ae4 Binary files /dev/null and b/Project/Manager/func/__pycache__/login.cpython-311.pyc differ diff --git a/Project/Manager/func/config.py b/Project/Manager/func/config.py index 5b82243..852dc20 100644 --- a/Project/Manager/func/config.py +++ b/Project/Manager/func/config.py @@ -1,8 +1,8 @@ db = { 'host':'localhost', - 'user':'kejingfan', - 'password':'KJF2811879', - 'database':'TESTDB' + 'user':'managerAgent', + 'password':'password123', + 'database':'ServiceDatabase' } SECRET_KEY = 'ILOVEDATABASETECH' diff --git a/Project/Manager/func/index.py b/Project/Manager/func/index.py index c511859..3a7fb44 100644 --- a/Project/Manager/func/index.py +++ b/Project/Manager/func/index.py @@ -1,6 +1,8 @@ -from flask import render_template, request, g, redirect, url_for, session +from flask import render_template, request, g, redirect, url_for, session, jsonify from .config import db import pymysql +import csv +import io def index(): if request.method == 'GET': @@ -8,25 +10,132 @@ def index(): return redirect(url_for("login")) flightID = request.args.get('flightID') - conn = pymysql.connect(**db) - cursor = conn.cursor(pymysql.cursors.DictCursor) - - search_sql = """ """ - cursor.execute(search_sql, (flightID, )) - flights = cursor.fetchall() - cursor.close() - conn.close() - - return render_template( - 'search.html', - flights=flights, - username=g.user - ) - -def logout(): - session.clear() - session.pop('user_id', None) - return redirect(url_for('login')) + if flightID: + conn = pymysql.connect(**db) + cursor = conn.cursor(pymysql.cursors.DictCursor) + + search_sql = """SELECT * FROM Flights WHERE ID = %s""" + cursor.execute(search_sql, (flightID, )) + flight = cursor.fetchone() + cursor.close() + conn.close() + + return render_template( + 'index.html', + flight=flight, + username=g.user + ) + else: + return render_template('index.html', username=g.user) def modify(): - pass + if request.method == 'POST': + flight_id = request.form.get('flightID') + first_class_change = int(request.form.get('first_class_change', 0)) + business_class_change = int(request.form.get('business_class_change', 0)) + economy_class_change = int(request.form.get('economy_class_change', 0)) + + first_class_price = float(request.form.get('first_class_price', 0)) + business_class_price = float(request.form.get('business_class_price', 0)) + economy_class_price = float(request.form.get('economy_class_price', 0)) + + status = request.form.get('status', '未知') + + conn = pymysql.connect(**db) + cursor = conn.cursor(pymysql.cursors.DictCursor) + + try: + # 查询当前座位数 + cursor.execute("SELECT First_class_seats_remaining, Business_class_seats_remaining, Economy_class_seats_remaining FROM Flights WHERE ID = %s", (flight_id,)) + current_seats = cursor.fetchone() + + new_first_class_seats = current_seats['First_class_seats_remaining'] + first_class_change + new_business_class_seats = current_seats['Business_class_seats_remaining'] + business_class_change + new_economy_class_seats = current_seats['Economy_class_seats_remaining'] + economy_class_change + + # 检查余座数是否为负值 + if new_first_class_seats < 0 or new_business_class_seats < 0 or new_economy_class_seats < 0: + return jsonify({'message': '座位变化后余座数不能为负值'}), 400 + + # 更新座位数和价格 + update_sql = """ + UPDATE Flights + SET First_class_seats_remaining = %s, Business_class_seats_remaining = %s, Economy_class_seats_remaining = %s, + First_class_price = %s, Business_class_price = %s, Economy_class_price = %s, Status = %s + WHERE ID = %s + """ + cursor.execute(update_sql, (new_first_class_seats, new_business_class_seats, new_economy_class_seats, + first_class_price, business_class_price, economy_class_price, status, flight_id)) + conn.commit() + except Exception as e: + print(e) + conn.rollback() + return jsonify({'message': '数据库错误,请稍后再试'}), 500 + finally: + cursor.close() + conn.close() + + return jsonify({'message': '座位数、价格和状态更新成功'}), 200 + + +def delete_flight(): + if request.method == 'DELETE': + flight_id = request.args.get('flightID') + + conn = pymysql.connect(**db) + cursor = conn.cursor() + + try: + delete_sql = "DELETE FROM Flights WHERE ID = %s" + cursor.execute(delete_sql, (flight_id,)) + conn.commit() + except Exception as e: + print(e) + conn.rollback() + return jsonify({'message': '数据库错误,请稍后再试', 'success': False}), 500 + finally: + cursor.close() + conn.close() + + return jsonify({'message': '航班删除成功', 'success': True}), 200 + +from flask import flash, redirect, url_for, jsonify, request +import pymysql +import csv +import io +from .config import db + +def upload_csv(): + if request.method == 'POST': + file = request.files['file'] + if not file: + flash('没有文件上传', 'error') + return redirect(url_for('index')) + + conn = pymysql.connect(**db) + cursor = conn.cursor() + + try: + stream = io.StringIO(file.stream.read().decode("UTF8"), newline=None) + csv_input = csv.reader(stream) + next(csv_input) # 跳过表头 + + for row in csv_input: + cursor.execute(""" + INSERT INTO Flights (ID, Airline, Departure_airport, Arrival_airport, Departure_time, Arrival_time, + First_class_seats_remaining, Business_class_seats_remaining, Economy_class_seats_remaining, + First_class_price, Business_class_price, Economy_class_price, Status) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) + """, row) + conn.commit() + flash('航班批量添加成功', 'success') + except Exception as e: + print(e) + conn.rollback() + flash(f'文件处理错误:{e}', 'error') + finally: + cursor.close() + conn.close() + + return redirect(url_for('index')) + diff --git a/Project/Manager/func/login.py b/Project/Manager/func/login.py index ac54ca4..c5936a5 100644 --- a/Project/Manager/func/login.py +++ b/Project/Manager/func/login.py @@ -1,4 +1,4 @@ -from flask import request, jsonify, session, url_for, render_template +from flask import request, jsonify, session, url_for, render_template, redirect from .config import db import pymysql @@ -31,4 +31,9 @@ def login(): return jsonify({'redirect': url_for('index')}) except Exception as e: print(e) - return jsonify({'message': '数据库错误,请稍后再试'}), 500 \ No newline at end of file + return jsonify({'message': '数据库错误,请稍后再试'}), 500 + +def logout(): + session.clear() + session.pop('user_id', None) + return redirect(url_for('login')) \ No newline at end of file diff --git a/Project/Manager/main.py b/Project/Manager/main.py index 44d35df..571eadc 100644 --- a/Project/Manager/main.py +++ b/Project/Manager/main.py @@ -39,7 +39,15 @@ def login(): @app.route('/logout') def logout(): - return func.index.logout() + return func.login.logout() + +@app.route("/delete_flight", methods=['DELETE']) +def delete_flight(): + return func.index.delete_flight() + +@app.route("/upload_csv", methods=['POST']) +def upload_csv(): + return func.index.upload_csv() if __name__ == "__main__": app.run( diff --git a/Project/Manager/static/css/index.css b/Project/Manager/static/css/index.css index e2c6cdd..fdd6749 100644 --- a/Project/Manager/static/css/index.css +++ b/Project/Manager/static/css/index.css @@ -81,7 +81,7 @@ header { min-width: 160px; box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); z-index: 1; - right: 0; /* 确保下拉菜单靠右对齐 */ + right: 0; } .dropdown-content a { @@ -130,6 +130,21 @@ th { background-color: #f2f2f2; } +.flight-row { + transition: transform 0.3s ease, box-shadow 0.3s ease, border-radius 0.3s ease; +} + +.flight-row:hover { + transform: scale(1.02); + box-shadow: 0 0 10px rgba(28, 108, 178, 0.5); + border-radius: 10px; +} + +.flight-info th, .flight-info td { + padding: 10px; + border: 1px solid #ccc; +} + .no-results { text-align: center; color: red; @@ -144,7 +159,7 @@ footer { padding: 10px 0; width: 100%; position: relative; - margin-top: auto; /* 将footer推到页面底部 */ + margin-top: auto; } .content { @@ -153,70 +168,28 @@ footer { border-radius: 10px; text-align: center; width: 80%; - max-width: 800px; margin: 20px auto; position: relative; } -.tabcontent { - display: block; - padding: 20px; -} - -.form-row { - display: flex; - justify-content: flex-start; /* Left-align the form items */ +.form-group { margin-bottom: 15px; + text-align: left; } -.form-row label { - flex: 0 0 120px; /* Fixed width for labels */ - margin-right: 10px; - text-align: right; - line-height: 32px; +.form-group label { + display: block; + margin-bottom: 5px; } -.form-row input, -.form-row select { - flex: 1; +.form-group input { + width: 100%; padding: 8px; font-size: 16px; border: 1px solid #ccc; border-radius: 5px; } -.form-row.form-row-center { - justify-content: center; /* Center-align the button */ -} - -.passenger-input { - display: flex; - align-items: center; - gap: 5px; -} - -.passenger-input button { - padding: 5px 10px; - font-size: 18px; - background-color: #1c6cb2; - color: white; - border: none; - border-radius: 5px; - cursor: pointer; -} - -.passenger-input button:hover { - background-color: #155a8c; -} - -.passenger-input input { - width: 50px; - text-align: center; - font-size: 16px; - border: 1px solid #ccc; - border-radius: 5px; -} - .btn { padding: 10px 20px; background-color: #1c6cb2; @@ -231,21 +204,3 @@ footer { .btn:hover { background-color: #155a8c; } - -.error-message { - color: red; - font-size: 12px; - margin-top: 5px; - text-align: left; -} - -/* Add animations for flight rows */ -.flight-row { - transition: transform 0.3s ease, box-shadow 0.3s ease, border-radius 0.3s ease; -} - -.flight-row:hover { - transform: scale(1.02); - box-shadow: 0 0 10px rgba(28, 108, 178, 0.5); - border-radius: 10px; -} diff --git a/Project/Manager/static/js/index.js b/Project/Manager/static/js/index.js index 10e2492..e385121 100644 --- a/Project/Manager/static/js/index.js +++ b/Project/Manager/static/js/index.js @@ -1,16 +1,3 @@ -function validateForm() { - var departure = document.getElementById('departure').value; - var destination = document.getElementById('destination').value; - var warning = document.getElementById('destination-warning'); - if (departure === destination) { - warning.textContent = '出发地和目的地不能相同'; - return false; - } else { - warning.textContent = ''; - } - return true; -} - function increment() { var passengers = document.getElementById("passengers"); var value = parseInt(passengers.value, 10); @@ -26,17 +13,3 @@ function decrement() { passengers.value = value - 1; } } - -document.addEventListener('DOMContentLoaded', function() { - // Set default date to tomorrow - var departureDate = document.getElementById('departure-date'); - if (!departureDate.value) { - var today = new Date(); - var tomorrow = new Date(today); - tomorrow.setDate(tomorrow.getDate() + 1); - var month = ('0' + (tomorrow.getMonth() + 1)).slice(-2); - var day = ('0' + tomorrow.getDate()).slice(-2); - var year = tomorrow.getFullYear(); - departureDate.value = `${year}-${month}-${day}`; - } -}); diff --git a/Project/Manager/templates/index.html b/Project/Manager/templates/index.html index e82183d..505cdf2 100644 --- a/Project/Manager/templates/index.html +++ b/Project/Manager/templates/index.html @@ -5,8 +5,19 @@ KJF航班订票 - - +
@@ -14,14 +25,12 @@
{{ username }} @@ -29,118 +38,182 @@
-
- -
-
-
-
- - -
-
- - -
-
-
- - -
-
-
- + +
+ + +
+ + + + {% if flight %} +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
航班号航空公司出发机场到达机场出发时间到达时间头等舱剩余座位商务舱剩余座位经济舱剩余座位头等舱价格商务舱价格经济舱价格状态
{{ flight.ID }}{{ flight.Airline }}{{ flight.Departure_airport }}{{ flight.Arrival_airport }}{{ flight.Departure_time }}{{ flight.Arrival_time }}{{ flight.First_class_seats_remaining }}{{ flight.Business_class_seats_remaining }}{{ flight.Economy_class_seats_remaining }}{{ flight.First_class_price }}{{ flight.Business_class_price }}{{ flight.Economy_class_price }}{{ flight.Status }}
+
+ +
+

修改座位数、价格及状态

+
+ +
+
- - - + + +
-
- +
+ +
+ + + +
+
+ +
+ + + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+

其他操作

+ +
+ + +
+
+ {% endif %}
- diff --git a/Project/Service/func/__pycache__/config.cpython-311.pyc b/Project/Service/func/__pycache__/config.cpython-311.pyc index 2bfd9d7..ab665cd 100644 Binary files a/Project/Service/func/__pycache__/config.cpython-311.pyc and b/Project/Service/func/__pycache__/config.cpython-311.pyc differ diff --git a/Project/Service/func/config.py b/Project/Service/func/config.py index 8e3c745..ab4a8e9 100644 --- a/Project/Service/func/config.py +++ b/Project/Service/func/config.py @@ -1,8 +1,8 @@ db = { 'host':'localhost', - 'user':'kejingfan', - 'password':'KJF2811879', - 'database':'TESTDB' + 'user':'serviceAgent', + 'password':'password123', + 'database':'ServiceDatabase' } SECRET_KEY = 'ILOVEDATABASETECH'