完成大作业服务端代码,新建管理端,管理端不可用
This commit is contained in:
281
Project/Service/templates/book.html
Normal file
281
Project/Service/templates/book.html
Normal file
@@ -0,0 +1,281 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>航班预定</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/book.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="header-content">
|
||||
<div class="logo">KJF航班订票</div>
|
||||
<div class="nav-buttons">
|
||||
<a href="{{ url_for('index') }}">首页</a>
|
||||
<a href="{{ url_for('order_list') }}">我的订单</a>
|
||||
</div>
|
||||
<div class="user-menu">
|
||||
<span>{{ username }}</span>
|
||||
<div class="dropdown">
|
||||
<button class="dropbtn">▼</button>
|
||||
<div class="dropdown-content">
|
||||
<a href="{{ url_for('modify') }}">修改账户信息</a>
|
||||
<a href="{{ url_for('logout') }}">退出登录</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<main>
|
||||
<h2>预定航班</h2>
|
||||
<div class="flight-info">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>航班号</th>
|
||||
<th>航空公司</th>
|
||||
<th>出发机场</th>
|
||||
<th>到达机场</th>
|
||||
<th>出发时间</th>
|
||||
<th>到达时间</th>
|
||||
<th>头等舱剩余座位</th>
|
||||
<th>商务舱剩余座位</th>
|
||||
<th>经济舱剩余座位</th>
|
||||
<th>头等舱价格</th>
|
||||
<th>商务舱价格</th>
|
||||
<th>经济舱价格</th>
|
||||
<th>状态</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="flight-row">
|
||||
<td>{{ flight.ID }}</td>
|
||||
<td>{{ flight.Airline }}</td>
|
||||
<td>{{ flight.Departure_airport_name }}</td>
|
||||
<td>{{ flight.Arrival_airport_name }}</td>
|
||||
<td>{{ flight.Departure_time }}</td>
|
||||
<td>{{ flight.Arrival_time }}</td>
|
||||
<td id="first-class-seats">{{ flight.First_class_seats_remaining }}</td>
|
||||
<td id="business-class-seats">{{ flight.Business_class_seats_remaining }}</td>
|
||||
<td id="economy-class-seats">{{ flight.Economy_class_seats_remaining }}</td>
|
||||
<td id="first-class-price">{{ flight.First_class_price }}</td>
|
||||
<td id="business-class-price">{{ flight.Business_class_price }}</td>
|
||||
<td id="economy-class-price">{{ flight.Economy_class_price }}</td>
|
||||
<td>{{ flight.Status }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<form id="booking-form" method="post" action="{{ url_for('book', flight_id=flight.ID) }}" onsubmit="return validateBookingForm()">
|
||||
<div id="passenger-list">
|
||||
<div class="passenger" data-index="0">
|
||||
<h3>乘机人 1</h3>
|
||||
<button type="button" class="delete-btn" onclick="removePassenger(this)">删除</button>
|
||||
<div class="form-row">
|
||||
<label for="card-code-0">身份证号:</label>
|
||||
<input type="text" id="card-code-0" name="passengers[0][card_code]" oninput="validateCardCode(this)">
|
||||
<div class="error-message" id="card-code-error-0"></div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="name-0">真实姓名:</label>
|
||||
<input type="text" id="name-0" name="passengers[0][name]">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="phone-number-0">手机号:</label>
|
||||
<input type="text" id="phone-number-0" name="passengers[0][phone_number]" oninput="validatePhoneNumber(this)">
|
||||
<div class="error-message" id="phone-number-error-0"></div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="seat-class-0">座位级别:</label>
|
||||
<select id="seat-class-0" name="passengers[0][seat_class]" onchange="updateSeatCount(this)">
|
||||
<option value="" disabled selected>请选择座位级别</option>
|
||||
<option value="First Class">头等舱</option>
|
||||
<option value="Business Class">商务舱</option>
|
||||
<option value="Economy Class">经济舱</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="total-price">
|
||||
总价: <span id="total-price">0</span> 元
|
||||
</div>
|
||||
<button type="button" class="btn" onclick="addPassenger()">添加乘机人</button>
|
||||
<button type="submit" class="btn">预定</button>
|
||||
</form>
|
||||
</main>
|
||||
<footer>
|
||||
<p>© 2024 KJF航班订票. 保留所有权利。</p>
|
||||
</footer>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Initialize seat counts
|
||||
var passengerCount = 1;
|
||||
var firstClassSeats = {{ flight.First_class_seats_remaining }};
|
||||
var businessClassSeats = {{ flight.Business_class_seats_remaining }};
|
||||
var economyClassSeats = {{ flight.Economy_class_seats_remaining }};
|
||||
var firstClassPrice = parseFloat(document.getElementById("first-class-price").textContent);
|
||||
var businessClassPrice = parseFloat(document.getElementById("business-class-price").textContent);
|
||||
var economyClassPrice = parseFloat(document.getElementById("economy-class-price").textContent);
|
||||
|
||||
window.addPassenger = function() {
|
||||
passengerCount++;
|
||||
const passengerList = document.getElementById('passenger-list');
|
||||
const passengerDiv = document.createElement('div');
|
||||
passengerDiv.classList.add('passenger');
|
||||
passengerDiv.setAttribute('data-index', passengerCount - 1);
|
||||
|
||||
const disabledFirstClass = firstClassSeats <= 0 ? 'disabled' : '';
|
||||
const disabledBusinessClass = businessClassSeats <= 0 ? 'disabled' : '';
|
||||
const disabledEconomyClass = economyClassSeats <= 0 ? 'disabled' : '';
|
||||
|
||||
passengerDiv.innerHTML = `
|
||||
<h3>乘机人 ${passengerCount}</h3>
|
||||
<button type="button" class="delete-btn" onclick="removePassenger(this)">删除</button>
|
||||
<div class="form-row">
|
||||
<label for="card-code-${passengerCount - 1}">身份证号:</label>
|
||||
<input type="text" id="card-code-${passengerCount - 1}" name="passengers[${passengerCount - 1}][card_code]" oninput="validateCardCode(this)">
|
||||
<div class="error-message" id="card-code-error-${passengerCount - 1}"></div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="name-${passengerCount - 1}">真实姓名:</label>
|
||||
<input type="text" id="name-${passengerCount - 1}" name="passengers[${passengerCount - 1}][name]">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="phone-number-${passengerCount - 1}">手机号:</label>
|
||||
<input type="text" id="phone-number-${passengerCount - 1}" name="passengers[${passengerCount - 1}][phone_number]" oninput="validatePhoneNumber(this)">
|
||||
<div class="error-message" id="phone-number-error-${passengerCount - 1}"></div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="seat-class-${passengerCount - 1}">座位级别:</label>
|
||||
<select id="seat-class-${passengerCount - 1}" name="passengers[${passengerCount - 1}][seat_class]" onchange="updateSeatCount(this)">
|
||||
<option value="" disabled selected>请选择座位级别</option>
|
||||
<option value="First Class" ${disabledFirstClass}>头等舱</option>
|
||||
<option value="Business Class" ${disabledBusinessClass}>商务舱</option>
|
||||
<option value="Economy Class" ${disabledEconomyClass}>经济舱</option>
|
||||
</select>
|
||||
</div>
|
||||
`;
|
||||
|
||||
passengerList.appendChild(passengerDiv);
|
||||
};
|
||||
|
||||
window.removePassenger = function(button) {
|
||||
const passengerDiv = button.parentElement;
|
||||
const index = passengerDiv.getAttribute('data-index');
|
||||
const seatClassSelect = document.getElementById(`seat-class-${index}`);
|
||||
const seatClass = seatClassSelect.value;
|
||||
|
||||
if (seatClass === 'First Class') firstClassSeats++;
|
||||
else if (seatClass === 'Business Class') businessClassSeats++;
|
||||
else if (seatClass === 'Economy Class') economyClassSeats++;
|
||||
|
||||
passengerDiv.remove();
|
||||
updateSeatDisplay();
|
||||
calculateTotalPrice();
|
||||
};
|
||||
|
||||
window.validateCardCode = function(input) {
|
||||
const regexCardCode = /^([1-6][1-9]|50)\d{4}(18|19|20)\d{2}((0[1-9])|10|11|12)(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
|
||||
const errorDiv = document.getElementById(`card-code-error-${input.id.split('-')[2]}`);
|
||||
if (!regexCardCode.test(input.value)) {
|
||||
errorDiv.textContent = '身份证号格式不正确';
|
||||
} else {
|
||||
errorDiv.textContent = '';
|
||||
}
|
||||
};
|
||||
|
||||
window.validatePhoneNumber = function(input) {
|
||||
const regexMobileNo = /^1[3-9]\d{9}$/;
|
||||
const errorDiv = document.getElementById(`phone-number-error-${input.id.split('-')[2]}`);
|
||||
if (!regexMobileNo.test(input.value)) {
|
||||
errorDiv.textContent = '手机号格式不正确';
|
||||
} else {
|
||||
errorDiv.textContent = '';
|
||||
}
|
||||
};
|
||||
|
||||
window.updateSeatCount = function(select) {
|
||||
const index = select.id.split('-')[2];
|
||||
const previousClass = select.getAttribute("data-previous-class");
|
||||
const newClass = select.value;
|
||||
|
||||
if (previousClass) {
|
||||
if (previousClass === 'First Class') firstClassSeats++;
|
||||
else if (previousClass === 'Business Class') businessClassSeats++;
|
||||
else if (previousClass === 'Economy Class') economyClassSeats++;
|
||||
}
|
||||
|
||||
if (newClass === 'First Class') {
|
||||
if (firstClassSeats <= 0) {
|
||||
alert("头等舱座位已满");
|
||||
select.value = "";
|
||||
return;
|
||||
}
|
||||
firstClassSeats--;
|
||||
} else if (newClass === 'Business Class') {
|
||||
if (businessClassSeats <= 0) {
|
||||
alert("商务舱座位已满");
|
||||
select.value = "";
|
||||
return;
|
||||
}
|
||||
businessClassSeats--;
|
||||
} else if (newClass === 'Economy Class') {
|
||||
if (economyClassSeats <= 0) {
|
||||
alert("经济舱座位已满");
|
||||
select.value = "";
|
||||
return;
|
||||
}
|
||||
economyClassSeats--;
|
||||
}
|
||||
|
||||
select.setAttribute("data-previous-class", newClass);
|
||||
updateSeatDisplay();
|
||||
calculateTotalPrice();
|
||||
};
|
||||
|
||||
function updateSeatDisplay() {
|
||||
document.getElementById("first-class-seats").textContent = firstClassSeats;
|
||||
document.getElementById("business-class-seats").textContent = businessClassSeats;
|
||||
document.getElementById("economy-class-seats").textContent = economyClassSeats;
|
||||
}
|
||||
|
||||
function calculateTotalPrice() {
|
||||
let totalPrice = 0;
|
||||
const seatClassSelects = document.querySelectorAll("select[id^='seat-class-']");
|
||||
seatClassSelects.forEach(select => {
|
||||
if (select.value === 'First Class') totalPrice += firstClassPrice;
|
||||
else if (select.value === 'Business Class') totalPrice += businessClassPrice;
|
||||
else if (select.value === 'Economy Class') totalPrice += economyClassPrice;
|
||||
});
|
||||
document.getElementById("total-price").textContent = totalPrice.toFixed(2);
|
||||
}
|
||||
|
||||
window.validateBookingForm = function() {
|
||||
// Validate seat availability
|
||||
if (firstClassSeats < 0 || businessClassSeats < 0 || economyClassSeats < 0) {
|
||||
alert("预定的座位数不能超过余座数");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate all card codes and phone numbers
|
||||
const cardCodes = document.querySelectorAll("input[id^='card-code-']");
|
||||
const phoneNumbers = document.querySelectorAll("input[id^='phone-number-']");
|
||||
for (let cardCode of cardCodes) {
|
||||
validateCardCode(cardCode);
|
||||
if (document.getElementById(`card-code-error-${cardCode.id.split('-')[2]}`).textContent !== '') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (let phoneNumber of phoneNumbers) {
|
||||
validatePhoneNumber(phoneNumber);
|
||||
if (document.getElementById(`phone-number-error-${phoneNumber.id.split('-')[2]}`).textContent !== '') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
146
Project/Service/templates/index.html
Normal file
146
Project/Service/templates/index.html
Normal file
@@ -0,0 +1,146 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>KJF航班订票</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/index.css') }}">
|
||||
<script src="{{ url_for('static', filename='js/index.js') }}" defer></script>
|
||||
<script src="https://cdn.bootcss.com/blueimp-md5/2.12.0/js/md5.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="header-content">
|
||||
<div class="logo">KJF航班订票</div>
|
||||
<div class="nav-buttons">
|
||||
<a href="{{ url_for('index') }}">首页</a>
|
||||
<a href="{{ url_for('order_list') }}">我的订单</a>
|
||||
</div>
|
||||
<div class="user-menu">
|
||||
<span>{{ username }}</span>
|
||||
<div class="dropdown">
|
||||
<button class="dropbtn">▼</button>
|
||||
<div class="dropdown-content">
|
||||
<a href="{{ url_for('modify') }}">修改账户信息</a>
|
||||
<a href="{{ url_for('logout') }}">退出登录</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<main>
|
||||
<div class="slides">
|
||||
<ul id="slide-container">
|
||||
{% for image in images %}
|
||||
<li>
|
||||
<a href="{{ image.link }}" target="_blank">
|
||||
<img src="{{ image.src }}">
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div id="ticket" class="tabcontent" style="display: block;">
|
||||
<form action="{{ url_for('search') }}" method="get" class="search-form" onsubmit="return validateForm()">
|
||||
<div class="form-row">
|
||||
<label for="departure">出发地:</label>
|
||||
<select id="departure" name="departure">
|
||||
{% for city in cities %}
|
||||
<option value="{{ city }}" {% if city == "北京" %}selected{% endif %}>{{ city }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="destination">目的地:</label>
|
||||
<select id="destination" name="destination">
|
||||
{% for city in cities %}
|
||||
<option value="{{ city }}" {% if city == "上海" %}selected{% endif %}>{{ city }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<div id="destination-warning" class="error-message"></div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="departure-date">出发日期:</label>
|
||||
<input type="date" id="departure-date" name="departure-date" required>
|
||||
<div id="date-warning" class="error-message"></div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="passengers">乘客人数:</label>
|
||||
<div class="passenger-input">
|
||||
<button type="button" onclick="decrement()">-</button>
|
||||
<input type="number" id="passengers" name="passengers" value="1" min="1" max="50">
|
||||
<button type="button" onclick="increment()">+</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row form-row-center">
|
||||
<button type="submit" class="btn">立即查询</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer>
|
||||
<p>© 2024 KJF航班订票. 保留所有权利。</p>
|
||||
</footer>
|
||||
<script src="{{ url_for('static', filename='js/slideshow.js') }}"></script>
|
||||
<script>
|
||||
function validateForm() {
|
||||
var departure = document.getElementById('departure').value;
|
||||
var destination = document.getElementById('destination').value;
|
||||
var warning = document.getElementById('destination-warning');
|
||||
var dateWarning = document.getElementById('date-warning');
|
||||
var departureDate = document.getElementById('departure-date').value;
|
||||
|
||||
var today = new Date();
|
||||
var selectedDate = new Date(departureDate);
|
||||
today.setHours(0, 0, 0, 0); // Ensure time comparison is not affected
|
||||
|
||||
if (departure === destination) {
|
||||
warning.textContent = '出发地和目的地不能相同';
|
||||
return false;
|
||||
} else {
|
||||
warning.textContent = '';
|
||||
}
|
||||
|
||||
if (selectedDate < today) {
|
||||
dateWarning.textContent = '出发日期不能早于今天';
|
||||
return false;
|
||||
} else {
|
||||
dateWarning.textContent = '';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function increment() {
|
||||
var passengers = document.getElementById("passengers");
|
||||
var value = parseInt(passengers.value, 10);
|
||||
if (value < 50) {
|
||||
passengers.value = value + 1;
|
||||
}
|
||||
}
|
||||
|
||||
function decrement() {
|
||||
var passengers = document.getElementById("passengers");
|
||||
var value = parseInt(passengers.value, 10);
|
||||
if (value > 1) {
|
||||
passengers.value = value - 1;
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Set default date to tomorrow
|
||||
var departureDate = document.getElementById('departure-date');
|
||||
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}`;
|
||||
departureDate.setAttribute('min', `${year}-${month}-${day}`);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
47
Project/Service/templates/login.html
Normal file
47
Project/Service/templates/login.html
Normal file
@@ -0,0 +1,47 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>我的航班订票官网</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/login.css') }}">
|
||||
<script src="{{ url_for('static', filename='js/login.js') }}" defer></script>
|
||||
<script src="https://cdn.bootcss.com/blueimp-md5/2.12.0/js/md5.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>KJF航班订票</h1>
|
||||
</header>
|
||||
<main>
|
||||
<div class="slides">
|
||||
<ul id="slide-container">
|
||||
{% for image in images %}
|
||||
<li>
|
||||
<a href="{{ image.link }}" target="_blank">
|
||||
<img src="{{ image.src }}">
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="content">
|
||||
<h2>尽享精彩出行服务</h2>
|
||||
<div class="login-form">
|
||||
<input type="text" id="mobileNo" placeholder="手机号">
|
||||
<div id="mobileNoError" class="error-message"></div>
|
||||
<input type="password" id="password" placeholder="密码">
|
||||
<div id="loginError" class="error-message"></div>
|
||||
<input type="hidden" id="encryptedPassword">
|
||||
<div class="buttons">
|
||||
<button onclick="submitForm()">登录</button>
|
||||
<a class="btn" href="{{ url_for('signup') }}">注册</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer>
|
||||
<p>© 2024 KJF航班订票. 保留所有权利。</p>
|
||||
</footer>
|
||||
<script src="{{ url_for('static', filename='js/slideshow.js') }}"></script>
|
||||
</body>
|
||||
</html>
|
||||
133
Project/Service/templates/modify.html
Normal file
133
Project/Service/templates/modify.html
Normal file
@@ -0,0 +1,133 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>修改账户</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/modify.css') }}">
|
||||
<script src="https://cdn.bootcss.com/blueimp-md5/2.12.0/js/md5.min.js"></script>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
{% with messages = get_flashed_messages() %}
|
||||
{% if messages %}
|
||||
var message = "";
|
||||
{% for msg in messages %}
|
||||
message += "{{ msg }}\n";
|
||||
{% endfor %}
|
||||
alert(message);
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<div class="header-content">
|
||||
<a href="{{ url_for('index') }}" class="btn-back">返回主页</a>
|
||||
<h1>KJF航班订票</h1>
|
||||
<div class="header-spacer"></div>
|
||||
</div>
|
||||
</header>
|
||||
<main>
|
||||
<div class="content">
|
||||
<h2>修改账户信息</h2>
|
||||
<form action="#" method="post" id="modify-form">
|
||||
<div class="tab">
|
||||
<button type="button" class="tablinks active" onclick="openTab(event, 'deleteAccount')">删除账户</button>
|
||||
<button type="button" class="tablinks" onclick="openTab(event, 'modifyPassword')">修改密码</button>
|
||||
<button type="button" class="tablinks" onclick="openTab(event, 'modifyPhone')">修改手机号</button>
|
||||
<button type="button" class="tablinks" onclick="openTab(event, 'modifyUsername')">修改用户名</button>
|
||||
</div>
|
||||
<input type="hidden" id="modifyType" name="modifyType" value="删除账户">
|
||||
<div class="form-group">
|
||||
<div>登陆密码:</div>
|
||||
<input type="password" id="password" placeholder="请输入您的密码" required>
|
||||
<input id="encryptedPassword" name="encryptedPassword" type="hidden">
|
||||
</div>
|
||||
<div id="deleteAccount" class="tabcontent">
|
||||
<p>删除账户将无法恢复,请确认。</p>
|
||||
</div>
|
||||
<div id="modifyPassword" class="tabcontent" style="display:none">
|
||||
<div class="form-group">
|
||||
<div>新密码:</div>
|
||||
<input type="password" id="newPassword" placeholder="6-20位字母、数字或符号">
|
||||
<input id="encryptedNewPassword" name="encryptedNewPassword" type="hidden">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div>确认密码:</div>
|
||||
<input type="password" id="confirmPassword" placeholder="再次输入您的新密码">
|
||||
</div>
|
||||
</div>
|
||||
<div id="modifyPhone" class="tabcontent" style="display:none">
|
||||
<p>原手机号为:{{ current_user_phone }}</p>
|
||||
<div class="form-group">
|
||||
<div>新手机号:</div>
|
||||
<input type="text" id="mobileNo" name="mobileNo" value title="手机号码" aria-label="手机号码" maxlength="11" placeholder="11位手机号">
|
||||
</div>
|
||||
</div>
|
||||
<div id="modifyUsername" class="tabcontent" style="display:none">
|
||||
<p>原用户名为:{{ current_username }}</p>
|
||||
<div class="form-group">
|
||||
<div>新用户名:</div>
|
||||
<input type="text" id="username" name="username" placeholder="请输入新的用户名">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" onclick="return submitForm()">确认</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</main>
|
||||
<footer>
|
||||
<p>© 2024 KJF航班订票. 保留所有权利。</p>
|
||||
</footer>
|
||||
|
||||
<script src="{{ url_for('static', filename='js/checkInfo.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/modify.js') }}"></script>
|
||||
<script>
|
||||
function submitForm() {
|
||||
document.getElementById('encryptedPassword').value = md5(
|
||||
document.getElementById('password').value
|
||||
);
|
||||
|
||||
let modifyType = document.querySelector('.tablinks.active').textContent;
|
||||
document.getElementById('modifyType').value = modifyType;
|
||||
|
||||
if (modifyType === '删除账户') {
|
||||
return true;
|
||||
} else if (modifyType === '修改密码') {
|
||||
document.getElementById('encryptedNewPassword').value = md5(
|
||||
document.getElementById('newPassword').value
|
||||
);
|
||||
return checkInfo.checkNewPassword();
|
||||
} else if (modifyType === '修改手机号') {
|
||||
return checkInfo.checkMobileNo();
|
||||
} else if (modifyType === '修改用户名') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function openTab(evt, tabName) {
|
||||
var i, tabcontent, tablinks;
|
||||
tabcontent = document.getElementsByClassName("tabcontent");
|
||||
for (i = 0; i < tabcontent.length; i++) {
|
||||
tabcontent[i].style.display = "none";
|
||||
}
|
||||
tablinks = document.getElementsByClassName("tablinks");
|
||||
for (i = 0; i < tablinks.length; i++) {
|
||||
tablinks[i].className = tablinks[i].className.replace(" active", "");
|
||||
}
|
||||
document.getElementById(tabName).style.display = "block";
|
||||
evt.currentTarget.className += " active";
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
let activeTab = document.querySelector('.tablinks.active');
|
||||
if (activeTab) {
|
||||
openTab({currentTarget: activeTab}, activeTab.getAttribute('onclick').split("'")[1]);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
83
Project/Service/templates/order.html
Normal file
83
Project/Service/templates/order.html
Normal file
@@ -0,0 +1,83 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>订单详情</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/order.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="header-content">
|
||||
<div class="logo">KJF航班订票</div>
|
||||
<div class="nav-buttons">
|
||||
<a href="{{ url_for('index') }}">首页</a>
|
||||
<a href="{{ url_for('order_list') }}">我的订单</a>
|
||||
</div>
|
||||
<div class="user-menu">
|
||||
<span>{{ username }}</span>
|
||||
<div class="dropdown">
|
||||
<button class="dropbtn">▼</button>
|
||||
<div class="dropdown-content">
|
||||
<a href="{{ url_for('modify') }}">修改账户信息</a>
|
||||
<a href="{{ url_for('logout') }}">退出登录</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<main>
|
||||
<button onclick="location.href='{{ url_for('order_list') }}'" class="back-btn">返回订单列表</button>
|
||||
<h2>订单详情</h2>
|
||||
<div class="order-info">
|
||||
<h3>航班信息</h3>
|
||||
<p>航班号: {{ order.FlightID }}</p>
|
||||
<p>航空公司: {{ order.Airline }}</p>
|
||||
<p>出发机场: {{ order.Departure_airport_name }}</p>
|
||||
<p>到达机场: {{ order.Arrival_airport_name }}</p>
|
||||
<p>出发时间: {{ order.Departure_time }}</p>
|
||||
<p>状态: {{ order.Status }}</p>
|
||||
</div>
|
||||
<div class="passenger-info">
|
||||
<h3>乘机人信息</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>身份证号</th>
|
||||
<th>姓名</th>
|
||||
<th>手机号</th>
|
||||
<th>座位级别</th>
|
||||
<th>票价</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for ticket in tickets %}
|
||||
<tr>
|
||||
<td>{{ ticket.PassengerID }}</td>
|
||||
<td>{{ ticket.Name }}</td>
|
||||
<td>{{ ticket.Phone_number }}</td>
|
||||
<td>{{ ticket.Seat_class }}</td>
|
||||
<td>{{ ticket.Price }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="order-summary">
|
||||
<p>订单总价: {{ total_price }}</p>
|
||||
<p>支付状态: {% if order.Paid %}已支付{% else %}未支付{% endif %}</p>
|
||||
</div>
|
||||
<form method="post" action="{{ url_for('cancel_order', order_id=order.ID) }}">
|
||||
<button type="submit" class="btn cancel-btn">取消订单</button>
|
||||
</form>
|
||||
{% if not order.Paid %}
|
||||
<form method="post" action="{{ url_for('pay_confirm', order_id=order.ID) }}">
|
||||
<button type="submit" class="btn pay-btn">支付订单</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</main>
|
||||
<footer>
|
||||
<p>© 2024 KJF航班订票. 保留所有权利。</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
72
Project/Service/templates/order_list.html
Normal file
72
Project/Service/templates/order_list.html
Normal file
@@ -0,0 +1,72 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>我的订单</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/order_list.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="header-content">
|
||||
<div class="logo">KJF航班订票</div>
|
||||
<div class="nav-buttons">
|
||||
<a href="{{ url_for('index') }}">首页</a>
|
||||
<a href="{{ url_for('order_list') }}">我的订单</a>
|
||||
</div>
|
||||
<div class="user-menu">
|
||||
<span>{{ username }}</span>
|
||||
<div class="dropdown">
|
||||
<button class="dropbtn">▼</button>
|
||||
<div class="dropdown-content">
|
||||
<a href="{{ url_for('modify') }}">修改账户信息</a>
|
||||
<a href="{{ url_for('logout') }}">退出登录</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<main>
|
||||
<h2>我的订单</h2>
|
||||
<div class="order-list">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>航班号</th>
|
||||
<th>航空公司</th>
|
||||
<th>出发机场</th>
|
||||
<th>到达机场</th>
|
||||
<th>出发时间</th>
|
||||
<th>状态</th>
|
||||
<th>乘机人</th>
|
||||
<th>订单总价</th>
|
||||
<th>支付状态</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for order in orders %}
|
||||
<tr class="order-row" onclick="location.href='{{ url_for('order', order_id=order.OrderID) }}'">
|
||||
<td>{{ order.FlightID }}</td>
|
||||
<td>{{ order.Airline }}</td>
|
||||
<td>{{ order.Departure_airport_name }}</td>
|
||||
<td>{{ order.Arrival_airport_name }}</td>
|
||||
<td>{{ order.Departure_time }}</td>
|
||||
<td>{{ order.Status }}</td>
|
||||
<td>
|
||||
{% for passenger in order.Passengers %}
|
||||
{{ passenger }}<br>
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td>{{ order.TotalPrice }}</td>
|
||||
<td>{% if order.Paid %}已支付{% else %}未支付{% endif %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</main>
|
||||
<footer>
|
||||
<p>© 2024 KJF航班订票. 保留所有权利。</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
179
Project/Service/templates/search.html
Normal file
179
Project/Service/templates/search.html
Normal file
@@ -0,0 +1,179 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>航班搜索结果</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/search.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="header-content">
|
||||
<div class="logo">KJF航班订票</div>
|
||||
<div class="nav-buttons">
|
||||
<a href="{{ url_for('index') }}">首页</a>
|
||||
<a href="{{ url_for('order_list') }}">我的订单</a>
|
||||
</div>
|
||||
<div class="user-menu">
|
||||
<span>{{ username }}</span>
|
||||
<div class="dropdown">
|
||||
<button class="dropbtn">▼</button>
|
||||
<div class="dropdown-content">
|
||||
<a href="{{ url_for('modify') }}">修改账户信息</a>
|
||||
<a href="{{ url_for('logout') }}">退出登录</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<main>
|
||||
<div class="content">
|
||||
<div id="ticket" class="tabcontent" style="display: block;">
|
||||
<form action="{{ url_for('search') }}" method="get" class="search-form" onsubmit="return validateForm()">
|
||||
<div class="form-row">
|
||||
<label for="departure">出发地:</label>
|
||||
<select id="departure" name="departure">
|
||||
{% for city in cities %}
|
||||
<option value="{{ city }}" {% if city == request.args.get('departure') %}selected{% endif %}>{{ city }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="destination">目的地:</label>
|
||||
<select id="destination" name="destination">
|
||||
{% for city in cities %}
|
||||
<option value="{{ city }}" {% if city == request.args.get('destination') %}selected{% endif %}>{{ city }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<div id="destination-warning" class="error-message"></div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="departure-date">出发日期:</label>
|
||||
<input type="date" id="departure-date" name="departure-date" value="{{ request.args.get('departure-date', '') }}" required>
|
||||
<div id="date-warning" class="error-message"></div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="passengers">乘客人数:</label>
|
||||
<div class="passenger-input">
|
||||
<button type="button" onclick="decrement()">-</button>
|
||||
<input type="number" id="passengers" name="passengers" value="{{ request.args.get('passengers', 1) }}" min="1" max="50">
|
||||
<button type="button" onclick="increment()">+</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row form-row-center">
|
||||
<button type="submit" class="btn">立即查询</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>航班搜索结果</h2>
|
||||
{% if flights %}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>航班号</th>
|
||||
<th>航空公司</th>
|
||||
<th>出发机场</th>
|
||||
<th>到达机场</th>
|
||||
<th>出发时间</th>
|
||||
<th>到达时间</th>
|
||||
<th>头等舱剩余座位</th>
|
||||
<th>商务舱剩余座位</th>
|
||||
<th>经济舱剩余座位</th>
|
||||
<th>头等舱价格</th>
|
||||
<th>商务舱价格</th>
|
||||
<th>经济舱价格</th>
|
||||
<th>状态</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for flight in flights %}
|
||||
<tr class="flight-row" onclick="window.location.href='{{ url_for('book', flight_id=flight.ID) }}'">
|
||||
<td>{{ flight.ID }}</td>
|
||||
<td>{{ flight.Airline }}</td>
|
||||
<td>{{ flight.Departure_airport_name }}</td>
|
||||
<td>{{ flight.Arrival_airport_name }}</td>
|
||||
<td>{{ flight.Departure_time }}</td>
|
||||
<td>{{ flight.Arrival_time }}</td>
|
||||
<td>{{ flight.First_class_seats_remaining }}</td>
|
||||
<td>{{ flight.Business_class_seats_remaining }}</td>
|
||||
<td>{{ flight.Economy_class_seats_remaining }}</td>
|
||||
<td>{{ flight.First_class_price }}</td>
|
||||
<td>{{ flight.Business_class_price }}</td>
|
||||
<td>{{ flight.Economy_class_price }}</td>
|
||||
<td>{{ flight.Status }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p class="no-results">没有找到符合条件的航班。</p>
|
||||
{% endif %}
|
||||
</main>
|
||||
<footer>
|
||||
<p>© 2024 KJF航班订票. 保留所有权利。</p>
|
||||
</footer>
|
||||
<script src="{{ url_for('static', filename='js/search.js') }}"></script>
|
||||
<script>
|
||||
function validateForm() {
|
||||
var departure = document.getElementById('departure').value;
|
||||
var destination = document.getElementById('destination').value;
|
||||
var warning = document.getElementById('destination-warning');
|
||||
var dateWarning = document.getElementById('date-warning');
|
||||
var departureDate = document.getElementById('departure-date').value;
|
||||
|
||||
var today = new Date();
|
||||
var selectedDate = new Date(departureDate);
|
||||
today.setHours(0, 0, 0, 0); // Ensure time comparison is not affected
|
||||
|
||||
if (departure === destination) {
|
||||
warning.textContent = '出发地和目的地不能相同';
|
||||
return false;
|
||||
} else {
|
||||
warning.textContent = '';
|
||||
}
|
||||
|
||||
if (selectedDate < today) {
|
||||
dateWarning.textContent = '出发日期不能早于今天';
|
||||
return false;
|
||||
} else {
|
||||
dateWarning.textContent = '';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function increment() {
|
||||
var passengers = document.getElementById("passengers");
|
||||
var value = parseInt(passengers.value, 10);
|
||||
if (value < 50) {
|
||||
passengers.value = value + 1;
|
||||
}
|
||||
}
|
||||
|
||||
function decrement() {
|
||||
var passengers = document.getElementById("passengers");
|
||||
var value = parseInt(passengers.value, 10);
|
||||
if (value > 1) {
|
||||
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}`;
|
||||
departureDate.setAttribute('min', `${year}-${month}-${day}`);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
51
Project/Service/templates/signup.html
Normal file
51
Project/Service/templates/signup.html
Normal file
@@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>注册 - KJF航班订票</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/signup.css') }}">
|
||||
<script src="https://cdn.bootcss.com/blueimp-md5/2.12.0/js/md5.min.js"></script>
|
||||
<script src="{{ url_for('static', filename='js/checkInfo.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/signup.js') }}"></script>
|
||||
</head>
|
||||
<body>
|
||||
<form action="#" method="post" id="signupForm">
|
||||
<ul>
|
||||
<li>
|
||||
<div>
|
||||
<div>用户名:</div>
|
||||
<input type="text" id="username" name="username" placeholder="请输入用户名" required>
|
||||
<div class="error-message">{{ errors.username }}</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
<div>手机号:</div>
|
||||
<input type="text" id="mobileNo" name="mobileNo" placeholder="请输入手机号" maxlength="11" required>
|
||||
<div class="error-message" id="mobileNoError">{{ errors.mobileNo }}</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
<div>登录密码:</div>
|
||||
<input type="password" id="password" placeholder="6-20位字母、数字或符号" required>
|
||||
<input id="encryptedPassword" name="encryptedPassword" type="hidden">
|
||||
<div class="error-message" id="passwordError">{{ errors.password }}</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
<div>确认密码:</div>
|
||||
<input type="password" id="confirmPassword" placeholder="再次输入您的登录密码" required>
|
||||
<input id="encryptedConfirmPassword" name="encryptedConfirmPassword" type="hidden">
|
||||
<div class="error-message" id="confirmPasswordError">{{ errors.confirmPassword }}</div>
|
||||
</div>
|
||||
</li>
|
||||
<div>
|
||||
<button type="submit" onclick="return submitForm()">注册</button>
|
||||
</div>
|
||||
</ul>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user