# ticket
**Repository Path**: lm379/ticket
## Basic Information
- **Project Name**: ticket
- **Description**: 基于Java Swing + MySQL+Node.js开发的机票订票管理系统
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2024-06-13
- **Last Updated**: 2025-03-07
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 基于Java Swing+MySQL+Node.js的机票售票管理系统
本项目基于Java Swing框架构建,搭配[Flatlaf主题](https://github.com/JFormDesigner/FlatLaf)实现现代风格的UI
## 功能描述
- [X] 登录/注册
- [X] 乘客信息管理
- [X] 航班信息管理
- [X] 航班销售统计
- [X] 订票
- [X] 退票
- [X] 多级菜单
## 需求分析
- 基于Java Swing GUI提供一个用户友好的界面,使得售票员能够快速有效地处理机票销售。
- 实现航班信息的管理,包括航班添加、修改和删除功能。
- 实现乘客信息管理,包括乘客添加、查询和更新功能。
- 提供销售统计功能,以便管理层能够监控销售情况并做出战略决策。
## 项目开发环境
`OpenJDK 21.0.2` `MySQL 8.0.37` `Node.js v20.14.0`
## 开发工具
`VS Code` `Navicat`
---
## 前端描述
### 项目结构
入口文件:`TicketManangeSystem.java `
乘客管理:`PassengerManageForm.java`
销售统计:`SalesQueryForm.java`
航班管理:`FlightsAddForm.java` `FlightsDeleteForm.java` `FlightsUpdateForm.java` `FlightsQueryForm.java` `FilghtsSelectForm.java`
注册登录:`LoginForm.java`
### 核心代码
前端核心代码是以GET和POST的方法向后端发送JSON数据
#### POST方式
```java
try {
var request = HttpRequest.newBuilder().uri(URI.create(apiAddress + apiEndpoint))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonInputString)).build();
var client = HttpClient.newHttpClient();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
} catch (Exception e) {
// 异常处理
}
```
对应的JSON数据处理示例
```java
// 调用外部库org.json实现JSON格式数据的处理
JSONObject json = new JSONObject();
json.put("TflightNumber", TflightNumber);
json.put("TicketNumber", TicketNumber);
json.put("Price", Price);
json.put("Condition", Condition);
json.put("discount", discount);
String jsonInputString = json.toString();
```
#### GET方式
```java
// 使用URI + toURL方法构建请求URL
URI uri = new URI(apiAddress + apiEndpoint);
URL url = uri.toURL();
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
```
#### 事件监听
```java
// 点击按钮后的触发
Button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 点击后的触发逻辑
}
});
```
```java
// 从身份证号中提取性别和出生日期
passengerIdTextField.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
String idNumber = passengerIdTextField.getText();
if (idNumber.length() == 18) {
// 提取出生日期
String birthDate = idNumber.substring(6, 10) + "-" + idNumber.substring(10, 12) + "-"
+ idNumber.substring(12, 14);
passengerBirthTextField.setText(birthDate);
// 提取性别,身份证倒数第二位为奇数表示男,偶数表示女
char genderCode = idNumber.charAt(16);
int sexIndex = (genderCode % 2 == 0) ? 1 : 0; // 0为男,1为女
passengerSexComboBox.setSelectedIndex(sexIndex);
} else {
JOptionPane.showMessageDialog(null, "身份证号码必须为18位", "输入错误", JOptionPane.ERROR_MESSAGE);
}
}
});
```
### 前端项目截图及展示
数据库测试账号:
> 管理员 账号:admin 密码:admin
>
> 普通用户 账号:user 密码:123
1. 注册登录
2. 非管理员账号登入只能进入购票页面
3. 管理员账号登录会显示主界面
4. 主界面三个二级菜单展示

其中销售统计按钮点击会直接触发,另外两个还有三级菜单
5. 乘客信息管理菜单展示
1. 通过姓名或身份证号查询乘客详细信息

2. 订票系统
其中性别选项和出生日期可以自动从身份证号中获取,获取后也能自行修改,且身份证号必须位18位,否则程序将报错
3. 退票管理
可通过乘客姓名、身份证号、电话号码对乘客进行退款,退款后才能删除乘客信息
退款成功后将无法通过上面的查询接口查询到乘客信息
4. 修改乘客信息
可通过乘客的姓名、证件号修改相应的姓名、证件号、电话号码、票号
票号对应飞机航班信息

6. 航班管理菜单展示
1. 筛选航班
通过起止城市或航班号查询对应的航班

2. 查询所有航班

3. 增加航班

4. 删除航班

5. 修改航班信息

## 后端接口描述
由于项目使用Node.js作为后端API,所以需要自行安装Node.js
[Node.js — 在任何地方运行 JavaScript (nodejs.org)](https://nodejs.org/zh-cn)
然后先前往项目目录下执行下面的命令安装依赖,否则项目无法运行
```bash
npm install express cors body-parser mysql2 bcrypt --save
```
再执行
```bash
node app.js
```
就会启动后端API接口了
默认接口地址:http://localhost:15379/
### 后端核心代码
```javascript
// 数据库配置
const dbConfig = {
host: 'mysql.example.com', // 数据库地址
user: 'root', //用户名
password: 'password', // 密码
database: 'ticket', // 表名
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
};
// 数据库连接
const pool = mysql.createPool(dbConfig);
// 用于简化数据库查询的函数
function executeQuery(sql, data, callback) {
pool.getConnection((err, connection) => {
if (err) {
return callback(err, null);
} else {
connection.query(sql, data, (error, results) => {
connection.release();
if (error) {
return callback(error, null);
}
return callback(null, results);
});
}
});
}
```
```js
// get路由示例
app.get('/queryTickets', (req, res) => {
const { 请求体 } = req.query;
const sql = `SQL语句`;
executeQuery(sql, [请求体], (err, results) => {
if (err) {
res.status(500).json({ message: '查询乘客信息时发生错误', error: err });
} else {
if (results.length > 0) {
res.json(results);
} else {
res.json({ message: `未找到${PName}的乘客信息` });
}
}
});
});
```
> 后端接收和返回的数据均为JSON格式
**后端接口一览表**
| 接口 | 请求参数 | 请求方式 | 描述 |
| -------------------- | ------------------------------------------------------------------------------------ | -------- | :--------------------------- |
| queryTickets | PName | get | 通过乘客姓名查询乘客信息 |
| queryTicketsById | PassengerIdentity | get | 通过乘客身份证号查询乘客信息 |
| calculateFlightSales | 无 | get | 统计当前总销售额 |
| queryAllFlights | 无 | get | 查询当前所有航班 |
| queryFlights | fromCity & toCity | get | 根据起始城市查询航班 |
| queryFlightByNumber | FlightNumber | get | 根据航班号查询航班 |
| addPassenger | PName gender IdentityStyle
PassengerIdentity birthday PTele
PTicketNumber | post | 添加乘客 |
| updatePaymentState | Pinfo selectField | post | 变更乘客支付状态 |
| deletePassenger | Pinfo selectField | post | 删除乘客数据 |
| updatePassenger | oldPinfo newPinfo
oldSelectField newSelectField | post | 修改乘客信息 |
| addFlight | TflightNumber, TicketNumber,
Price, Condition,
discount, worker | post | 增加航班 |
| deleteFlight | TicketNumber | post | 删除航班 |
| updateFlight | newTinfo TicketNumber SelectTField | post | 修改航班信息 |
| register | account password | post | 注册 |
| login | account password | post | 登录 |
其中注册和登录使用 `bcrypt`库对密码进行加密
如两个测试账号再数据库中显示为如下

### API调用示例
```
GET http://localhost:15379/queryFlightByNumber?FlightNumber=MU294
```
返回数据
```json
[
{
"FlightNumber": "MU294",
"TicketNumber": 13,
"FlightName": "空客320",
"fromCity": "上海",
"toCity": "成都",
"mileAge": 2800,
"departureTime": "11:15:00",
"Price": 546,
"discount": 0.3
}
]
```
## 数据库描述
### 表结构
