完成大作业服务端代码,新建管理端,管理端不可用

This commit is contained in:
Jingfan Ke 2024-06-14 14:53:50 +08:00
parent ad767a806b
commit cfbaf585a7
80 changed files with 3563 additions and 128 deletions

View File

@ -0,0 +1,208 @@
ID,Name,City
NAY,北京南苑机场,北京
PEK,北京首都国际机场,北京
TSN,天津滨海国际机场,天津
ZQZ,张家口宁远机场,张家口
HDG,邯郸机场,邯郸
SHP,秦皇岛山海关机场,秦皇岛
TVS,唐山三女河机场,唐山
XNT,邢台褡裢机场,邢台
SJW,石家庄正定国际机场,石家庄
TYN,太原武宿国际机场,太原
LLV,吕梁机场,吕梁
CIH,长治王村机场,长治
DAT,大同云冈机场,大同
YCU,运城机场,运城
AXF,阿拉善左旗巴彦浩特机场,阿拉善左旗
RHT,阿拉善右旗巴丹吉林机场,阿拉善右旗
BAV,包头二里半机场,包头
CIF,赤峰玉龙机场,赤峰
DSN,鄂尔多斯伊金霍洛机场,鄂尔多斯
EJN,额济纳旗桃来机场,额济纳旗
ERL,二连浩特赛乌苏机场,二连浩特
NZH,满洲里西郊机场,满洲里
WUA,乌海机场,乌海
YIE,阿尔山伊尔施机场,阿尔山
RLK,巴彦淖尔天吉泰机场,巴彦淖尔
HET,呼和浩特白塔国际机场,呼和浩特
HLD,呼伦贝尔海拉尔机场,呼伦贝尔
TGO,通辽机场,通辽
HLH,乌兰浩特机场,乌兰浩特
XIL,锡林浩特机场,锡林浩特
AOG,鞍山腾鳌机场,鞍山
CNI,长海大长山岛机场,长海
CHG,朝阳机场,朝阳
DLC,大连周水子国际机场,大连
DDG,丹东浪头机场,丹东
JNZ,锦州小岭子机场,锦州
SHE,沈阳桃仙国际机场,沈阳
TNH,通化三源浦机场,通化
NBS,长白山机场,白山
YNJ,延吉朝阳川机场,延边
CGQ,长春龙嘉国际机场,长春
JXA,鸡西兴凯湖机场,鸡西
JMU,佳木斯东郊机场,佳木斯
MDG,牡丹江海浪机场,牡丹江
LDS,伊春林都机场,伊春
HEK,黑河机场,黑河
DQA,大庆萨尔图机场,大庆
JGD,加格达奇机场,大兴安岭
HRB,哈尔滨太平国际机场,哈尔滨
OHE,漠河古莲机场,漠河
NDG,齐齐哈尔三家子机场,齐齐哈尔
SHA,上海虹桥国际机场,上海
PVG,上海浦东国际机场,上海
HIA,淮安涟水机场,淮安
NTG,南通兴东机场,南通
YNZ,盐城南洋机场,盐城
YTY,扬州泰州机场,扬州
NKG,南京禄口国际机场,南京
XUZ,徐州观音机场,徐州
LYG,连云港白塔埠机场,连云港
CZX,常州奔牛机场,常州
WUX,苏南硕放国际机场,无锡
WNZ,温州龙湾国际机场,温州
JUZ,衢州机场,衢州
HYN,台州路桥机场,台州
HSN,舟山普陀山机场,舟山
HGH,杭州萧山国际机场,杭州
YIW,义乌机场,金华
NGB,宁波栎社国际机场,宁波
AQG,安庆天柱山机场,安庆
JUH,池州九华山机场,池州
TXN,黄山屯溪机场,黄山
HFE,合肥新桥国际机场,合肥
FUG,阜阳西关机场,阜阳
FOC,福州长乐国际机场,福州
SQJ,三明沙县机场,沙县
LCX,连城冠豸山机场,龙岩
JJN,泉州晋江机场,泉州
WUS,武夷山机场,南平
XMN,厦门高崎国际机场,厦门
KOW,赣州黄金机场,赣州
JGS,井冈山机场,吉安
YIC,宜春明月山机场,宜春
KHN,南昌昌北国际机场,南昌
JDZ,景德镇罗家机场,景德镇
JIU,九江庐山机场,九江
JNG,济宁曲阜机场,济宁
WEF,潍坊机场,潍坊
TAO,青岛流亭国际机场,青岛
TNA,济南遥墙国际机场,济南
LYI,临沂沭埠岭机场,临沂
YNT,烟台莱山国际机场,烟台
DOY,东营胜利机场,东营
WEH,威海国际机场,威海
LYA,洛阳北郊机场,洛阳
CGO,郑州新郑国际机场,郑州
NNY,南阳姜营机场,南阳
WUH,武汉天河国际机场,武汉
YIH,宜昌三峡机场,宜昌
ENH,恩施许家坪机场,恩施
XFN,襄阳刘集机场,襄阳
CGD,常德桃花源机场,常德
HJJ,怀化芷江机场,怀化
DYG,张家界荷花国际机场,张家界
CSX,长沙黄花国际机场,长沙
LLF,永州零陵机场,永州
DGM,东莞机场,东莞
SZX,深圳宝安国际机场,深圳
HUZ,惠州机场,惠州
MXZ,梅县长岗岌机场,梅州
SWA,揭阳潮汕机场,揭阳
ZHA,湛江机场,湛江
FUO,佛山机场,佛山
HSC,韶关桂头机场,韶关
ZUH,珠海金湾机场,珠海
CAN,广州白云国际机场,广州
LZH,柳州白莲机场,柳州
AEB,百色巴马机场,百色
BHY,北海福成机场,北海
NNG,南宁吴圩国际机场,南宁
WUZ,梧州长洲岛机场,梧州
KWL,桂林两江国际机场,桂林
HAK,海口美兰国际机场,海口
SYX,三亚凤凰国际机场,三亚
CKG,重庆江北国际机场,重庆
WXN,万州五桥机场,万州
JIQ,黔江武陵山机场,黔江
DAX,达州河市机场,达州
DCY,稻城亚丁机场,稻城
JZH,九寨黄龙机场,九寨沟
NAO,南充高坪机场,南充
PZI,攀枝花保安营机场,攀枝花
CTU,成都双流国际机场,成都
SUN,遂宁机场,遂宁
GYS,广元盘龙机场,广元
KGT,甘孜康定机场,康定
MIG,绵阳南郊机场,绵阳
LZO,泸州蓝田机场,泸州
XIC,西昌青山机场,西昌
YBP,宜宾菜坝机场,宜宾
AVA,安顺黄果树机场,安顺
BFJ,毕节飞雄机场,毕节
KWE,贵阳龙洞堡国际机场,贵阳
ACX,兴义机场,黔西南
HZH,黎平机场,黎平
KJH,凯里黄平机场,黔东南
LLB,荔波机场,黔南
TEN,铜仁凤凰机场,铜仁
ZYI,遵义新舟机场,遵义
SYM,普洱思茅机场,普洱
TCZ,腾冲驼峰机场,腾冲
LNJ,临沧机场,临沧
JHG,西双版纳嘎洒国际机场,西双版纳
LJG,丽江三义机场,丽江
ZAT,昭通机场,昭通
BSD,保山云瑞机场,隆阳
DLU,大理机场,大理
LUM,德宏芒市机场,德宏
DIG,迪庆香格里拉机场,迪庆
KMG,昆明长水国际机场,昆明
WNH,文山普者黑机场,文山
NGQ,阿里昆莎机场,阿里
BPX,昌都邦达机场,昌都
RKZ,日喀则和平机场,日喀则
LXA,拉萨贡嘎机场,拉萨
LZY,林芝米林机场,林芝
XIY,西安咸阳国际机场,西安
UYN,榆林榆阳机场,榆林
HZG,汉中西关机场,汉中
AKA,安康五里铺机场,安康
ENY,延安二十里堡机场,延安
GXH,甘南夏河机场,甘南
JIC,金昌金川机场,金昌
YZY,张掖甘州机场,张掖
DNH,敦煌机场,敦煌
JGN,嘉峪关机场,嘉峪关
LHW,兰州中川机场,兰州
IQN,庆阳机场,庆阳
THQ,天水麦积山机场,天水
XNN,西宁曹家堡机场,西宁
GOQ,格尔木机场,格尔木
YUS,玉树巴塘机场,玉树
GYU,固原六盘山机场,固原
INC,银川河东国际机场,银川
ZHY,中卫沙坡头机场,中卫
AKU,阿克苏机场,阿克苏
AAT,阿勒泰机场,阿勒泰
FYN,富蕴机场,富蕴
HMI,哈密机场,哈密
HTN,和田机场,和田
KRL,库尔勒机场,库尔勒
IQM,且末机场,且末
TLQ,吐鲁番交河机场,吐鲁番
URC,乌鲁木齐地窝堡国际机场,乌鲁木齐
BPL,博乐阿拉山口机场,博尔塔拉
KJI,布尔津喀纳斯机场,布尔津
KHG,喀什机场,喀什
KRY,克拉玛依机场,克拉玛依
KCA,库车龟兹机场,库车
TCG,塔城机场,塔城
YIN,伊宁机场,伊宁
NLT,新源那拉提机场,新源
HKG,香港国际机场,香港
MFM,澳门国际机场,澳门
TSA,台北松山机场,台北
TPE,桃园国际机场,桃园
KHH,高雄国际机场,高雄
1 ID Name City
2 NAY 北京南苑机场 北京
3 PEK 北京首都国际机场 北京
4 TSN 天津滨海国际机场 天津
5 ZQZ 张家口宁远机场 张家口
6 HDG 邯郸机场 邯郸
7 SHP 秦皇岛山海关机场 秦皇岛
8 TVS 唐山三女河机场 唐山
9 XNT 邢台褡裢机场 邢台
10 SJW 石家庄正定国际机场 石家庄
11 TYN 太原武宿国际机场 太原
12 LLV 吕梁机场 吕梁
13 CIH 长治王村机场 长治
14 DAT 大同云冈机场 大同
15 YCU 运城机场 运城
16 AXF 阿拉善左旗巴彦浩特机场 阿拉善左旗
17 RHT 阿拉善右旗巴丹吉林机场 阿拉善右旗
18 BAV 包头二里半机场 包头
19 CIF 赤峰玉龙机场 赤峰
20 DSN 鄂尔多斯伊金霍洛机场 鄂尔多斯
21 EJN 额济纳旗桃来机场 额济纳旗
22 ERL 二连浩特赛乌苏机场 二连浩特
23 NZH 满洲里西郊机场 满洲里
24 WUA 乌海机场 乌海
25 YIE 阿尔山伊尔施机场 阿尔山
26 RLK 巴彦淖尔天吉泰机场 巴彦淖尔
27 HET 呼和浩特白塔国际机场 呼和浩特
28 HLD 呼伦贝尔海拉尔机场 呼伦贝尔
29 TGO 通辽机场 通辽
30 HLH 乌兰浩特机场 乌兰浩特
31 XIL 锡林浩特机场 锡林浩特
32 AOG 鞍山腾鳌机场 鞍山
33 CNI 长海大长山岛机场 长海
34 CHG 朝阳机场 朝阳
35 DLC 大连周水子国际机场 大连
36 DDG 丹东浪头机场 丹东
37 JNZ 锦州小岭子机场 锦州
38 SHE 沈阳桃仙国际机场 沈阳
39 TNH 通化三源浦机场 通化
40 NBS 长白山机场 白山
41 YNJ 延吉朝阳川机场 延边
42 CGQ 长春龙嘉国际机场 长春
43 JXA 鸡西兴凯湖机场 鸡西
44 JMU 佳木斯东郊机场 佳木斯
45 MDG 牡丹江海浪机场 牡丹江
46 LDS 伊春林都机场 伊春
47 HEK 黑河机场 黑河
48 DQA 大庆萨尔图机场 大庆
49 JGD 加格达奇机场 大兴安岭
50 HRB 哈尔滨太平国际机场 哈尔滨
51 OHE 漠河古莲机场 漠河
52 NDG 齐齐哈尔三家子机场 齐齐哈尔
53 SHA 上海虹桥国际机场 上海
54 PVG 上海浦东国际机场 上海
55 HIA 淮安涟水机场 淮安
56 NTG 南通兴东机场 南通
57 YNZ 盐城南洋机场 盐城
58 YTY 扬州泰州机场 扬州
59 NKG 南京禄口国际机场 南京
60 XUZ 徐州观音机场 徐州
61 LYG 连云港白塔埠机场 连云港
62 CZX 常州奔牛机场 常州
63 WUX 苏南硕放国际机场 无锡
64 WNZ 温州龙湾国际机场 温州
65 JUZ 衢州机场 衢州
66 HYN 台州路桥机场 台州
67 HSN 舟山普陀山机场 舟山
68 HGH 杭州萧山国际机场 杭州
69 YIW 义乌机场 金华
70 NGB 宁波栎社国际机场 宁波
71 AQG 安庆天柱山机场 安庆
72 JUH 池州九华山机场 池州
73 TXN 黄山屯溪机场 黄山
74 HFE 合肥新桥国际机场 合肥
75 FUG 阜阳西关机场 阜阳
76 FOC 福州长乐国际机场 福州
77 SQJ 三明沙县机场 沙县
78 LCX 连城冠豸山机场 龙岩
79 JJN 泉州晋江机场 泉州
80 WUS 武夷山机场 南平
81 XMN 厦门高崎国际机场 厦门
82 KOW 赣州黄金机场 赣州
83 JGS 井冈山机场 吉安
84 YIC 宜春明月山机场 宜春
85 KHN 南昌昌北国际机场 南昌
86 JDZ 景德镇罗家机场 景德镇
87 JIU 九江庐山机场 九江
88 JNG 济宁曲阜机场 济宁
89 WEF 潍坊机场 潍坊
90 TAO 青岛流亭国际机场 青岛
91 TNA 济南遥墙国际机场 济南
92 LYI 临沂沭埠岭机场 临沂
93 YNT 烟台莱山国际机场 烟台
94 DOY 东营胜利机场 东营
95 WEH 威海国际机场 威海
96 LYA 洛阳北郊机场 洛阳
97 CGO 郑州新郑国际机场 郑州
98 NNY 南阳姜营机场 南阳
99 WUH 武汉天河国际机场 武汉
100 YIH 宜昌三峡机场 宜昌
101 ENH 恩施许家坪机场 恩施
102 XFN 襄阳刘集机场 襄阳
103 CGD 常德桃花源机场 常德
104 HJJ 怀化芷江机场 怀化
105 DYG 张家界荷花国际机场 张家界
106 CSX 长沙黄花国际机场 长沙
107 LLF 永州零陵机场 永州
108 DGM 东莞机场 东莞
109 SZX 深圳宝安国际机场 深圳
110 HUZ 惠州机场 惠州
111 MXZ 梅县长岗岌机场 梅州
112 SWA 揭阳潮汕机场 揭阳
113 ZHA 湛江机场 湛江
114 FUO 佛山机场 佛山
115 HSC 韶关桂头机场 韶关
116 ZUH 珠海金湾机场 珠海
117 CAN 广州白云国际机场 广州
118 LZH 柳州白莲机场 柳州
119 AEB 百色巴马机场 百色
120 BHY 北海福成机场 北海
121 NNG 南宁吴圩国际机场 南宁
122 WUZ 梧州长洲岛机场 梧州
123 KWL 桂林两江国际机场 桂林
124 HAK 海口美兰国际机场 海口
125 SYX 三亚凤凰国际机场 三亚
126 CKG 重庆江北国际机场 重庆
127 WXN 万州五桥机场 万州
128 JIQ 黔江武陵山机场 黔江
129 DAX 达州河市机场 达州
130 DCY 稻城亚丁机场 稻城
131 JZH 九寨黄龙机场 九寨沟
132 NAO 南充高坪机场 南充
133 PZI 攀枝花保安营机场 攀枝花
134 CTU 成都双流国际机场 成都
135 SUN 遂宁机场 遂宁
136 GYS 广元盘龙机场 广元
137 KGT 甘孜康定机场 康定
138 MIG 绵阳南郊机场 绵阳
139 LZO 泸州蓝田机场 泸州
140 XIC 西昌青山机场 西昌
141 YBP 宜宾菜坝机场 宜宾
142 AVA 安顺黄果树机场 安顺
143 BFJ 毕节飞雄机场 毕节
144 KWE 贵阳龙洞堡国际机场 贵阳
145 ACX 兴义机场 黔西南
146 HZH 黎平机场 黎平
147 KJH 凯里黄平机场 黔东南
148 LLB 荔波机场 黔南
149 TEN 铜仁凤凰机场 铜仁
150 ZYI 遵义新舟机场 遵义
151 SYM 普洱思茅机场 普洱
152 TCZ 腾冲驼峰机场 腾冲
153 LNJ 临沧机场 临沧
154 JHG 西双版纳嘎洒国际机场 西双版纳
155 LJG 丽江三义机场 丽江
156 ZAT 昭通机场 昭通
157 BSD 保山云瑞机场 隆阳
158 DLU 大理机场 大理
159 LUM 德宏芒市机场 德宏
160 DIG 迪庆香格里拉机场 迪庆
161 KMG 昆明长水国际机场 昆明
162 WNH 文山普者黑机场 文山
163 NGQ 阿里昆莎机场 阿里
164 BPX 昌都邦达机场 昌都
165 RKZ 日喀则和平机场 日喀则
166 LXA 拉萨贡嘎机场 拉萨
167 LZY 林芝米林机场 林芝
168 XIY 西安咸阳国际机场 西安
169 UYN 榆林榆阳机场 榆林
170 HZG 汉中西关机场 汉中
171 AKA 安康五里铺机场 安康
172 ENY 延安二十里堡机场 延安
173 GXH 甘南夏河机场 甘南
174 JIC 金昌金川机场 金昌
175 YZY 张掖甘州机场 张掖
176 DNH 敦煌机场 敦煌
177 JGN 嘉峪关机场 嘉峪关
178 LHW 兰州中川机场 兰州
179 IQN 庆阳机场 庆阳
180 THQ 天水麦积山机场 天水
181 XNN 西宁曹家堡机场 西宁
182 GOQ 格尔木机场 格尔木
183 YUS 玉树巴塘机场 玉树
184 GYU 固原六盘山机场 固原
185 INC 银川河东国际机场 银川
186 ZHY 中卫沙坡头机场 中卫
187 AKU 阿克苏机场 阿克苏
188 AAT 阿勒泰机场 阿勒泰
189 FYN 富蕴机场 富蕴
190 HMI 哈密机场 哈密
191 HTN 和田机场 和田
192 KRL 库尔勒机场 库尔勒
193 IQM 且末机场 且末
194 TLQ 吐鲁番交河机场 吐鲁番
195 URC 乌鲁木齐地窝堡国际机场 乌鲁木齐
196 BPL 博乐阿拉山口机场 博尔塔拉
197 KJI 布尔津喀纳斯机场 布尔津
198 KHG 喀什机场 喀什
199 KRY 克拉玛依机场 克拉玛依
200 KCA 库车龟兹机场 库车
201 TCG 塔城机场 塔城
202 YIN 伊宁机场 伊宁
203 NLT 新源那拉提机场 新源
204 HKG 香港国际机场 香港
205 MFM 澳门国际机场 澳门
206 TSA 台北松山机场 台北
207 TPE 桃园国际机场 桃园
208 KHH 高雄国际机场 高雄

View File

@ -0,0 +1,208 @@
INSERT INTO Airports (`ID`, `Name`, City) VALUES
('NAY', '北京南苑机场', '北京'),
('PEK', '北京首都国际机场', '北京'),
('TSN', '天津滨海国际机场', '天津'),
('ZQZ', '张家口宁远机场', '张家口'),
('HDG', '邯郸机场', '邯郸'),
('SHP', '秦皇岛山海关机场', '秦皇岛'),
('TVS', '唐山三女河机场', '唐山'),
('XNT', '邢台褡裢机场', '邢台'),
('SJW', '石家庄正定国际机场', '石家庄'),
('TYN', '太原武宿国际机场', '太原'),
('LLV', '吕梁机场', '吕梁'),
('CIH', '长治王村机场', '长治'),
('DAT', '大同云冈机场', '大同'),
('YCU', '运城机场', '运城'),
('AXF', '阿拉善左旗巴彦浩特机场', '阿拉善左旗'),
('RHT', '阿拉善右旗巴丹吉林机场', '阿拉善右旗'),
('BAV', '包头二里半机场', '包头'),
('CIF', '赤峰玉龙机场', '赤峰'),
('DSN', '鄂尔多斯伊金霍洛机场', '鄂尔多斯'),
('EJN', '额济纳旗桃来机场', '额济纳旗'),
('ERL', '二连浩特赛乌苏机场', '二连浩特'),
('NZH', '满洲里西郊机场', '满洲里'),
('WUA', '乌海机场', '乌海'),
('YIE', '阿尔山伊尔施机场', '阿尔山'),
('RLK', '巴彦淖尔天吉泰机场', '巴彦淖尔'),
('HET', '呼和浩特白塔国际机场', '呼和浩特'),
('HLD', '呼伦贝尔海拉尔机场', '呼伦贝尔'),
('TGO', '通辽机场', '通辽'),
('HLH', '乌兰浩特机场', '乌兰浩特'),
('XIL', '锡林浩特机场', '锡林浩特'),
('AOG', '鞍山腾鳌机场', '鞍山'),
('CNI', '长海大长山岛机场', '长海'),
('CHG', '朝阳机场', '朝阳'),
('DLC', '大连周水子国际机场', '大连'),
('DDG', '丹东浪头机场', '丹东'),
('JNZ', '锦州小岭子机场', '锦州'),
('SHE', '沈阳桃仙国际机场', '沈阳'),
('TNH', '通化三源浦机场', '通化'),
('NBS', '长白山机场', '白山'),
('YNJ', '延吉朝阳川机场', '延边'),
('CGQ', '长春龙嘉国际机场', '长春'),
('JXA', '鸡西兴凯湖机场', '鸡西'),
('JMU', '佳木斯东郊机场', '佳木斯'),
('MDG', '牡丹江海浪机场', '牡丹江'),
('LDS', '伊春林都机场', '伊春'),
('HEK', '黑河机场', '黑河'),
('DQA', '大庆萨尔图机场', '大庆'),
('JGD', '加格达奇机场', '大兴安岭'),
('HRB', '哈尔滨太平国际机场', '哈尔滨'),
('OHE', '漠河古莲机场', '漠河'),
('NDG', '齐齐哈尔三家子机场', '齐齐哈尔'),
('SHA', '上海虹桥国际机场', '上海'),
('PVG', '上海浦东国际机场', '上海'),
('HIA', '淮安涟水机场', '淮安'),
('NTG', '南通兴东机场', '南通'),
('YNZ', '盐城南洋机场', '盐城'),
('YTY', '扬州泰州机场', '扬州'),
('NKG', '南京禄口国际机场', '南京'),
('XUZ', '徐州观音机场', '徐州'),
('LYG', '连云港白塔埠机场', '连云港'),
('CZX', '常州奔牛机场', '常州'),
('WUX', '苏南硕放国际机场', '无锡'),
('WNZ', '温州龙湾国际机场', '温州'),
('JUZ', '衢州机场', '衢州'),
('HYN', '台州路桥机场', '台州'),
('HSN', '舟山普陀山机场', '舟山'),
('HGH', '杭州萧山国际机场', '杭州'),
('YIW', '义乌机场', '金华'),
('NGB', '宁波栎社国际机场', '宁波'),
('AQG', '安庆天柱山机场', '安庆'),
('JUH', '池州九华山机场', '池州'),
('TXN', '黄山屯溪机场', '黄山'),
('HFE', '合肥新桥国际机场', '合肥'),
('FUG', '阜阳西关机场', '阜阳'),
('FOC', '福州长乐国际机场', '福州'),
('SQJ', '三明沙县机场', '沙县'),
('LCX', '连城冠豸山机场', '龙岩'),
('JJN', '泉州晋江机场', '泉州'),
('WUS', '武夷山机场', '南平'),
('XMN', '厦门高崎国际机场', '厦门'),
('KOW', '赣州黄金机场', '赣州'),
('JGS', '井冈山机场', '吉安'),
('YIC', '宜春明月山机场', '宜春'),
('KHN', '南昌昌北国际机场', '南昌'),
('JDZ', '景德镇罗家机场', '景德镇'),
('JIU', '九江庐山机场', '九江'),
('JNG', '济宁曲阜机场', '济宁'),
('WEF', '潍坊机场', '潍坊'),
('TAO', '青岛流亭国际机场', '青岛'),
('TNA', '济南遥墙国际机场', '济南'),
('LYI', '临沂沭埠岭机场', '临沂'),
('YNT', '烟台莱山国际机场', '烟台'),
('DOY', '东营胜利机场', '东营'),
('WEH', '威海国际机场', '威海'),
('LYA', '洛阳北郊机场', '洛阳'),
('CGO', '郑州新郑国际机场', '郑州'),
('NNY', '南阳姜营机场', '南阳'),
('WUH', '武汉天河国际机场', '武汉'),
('YIH', '宜昌三峡机场', '宜昌'),
('ENH', '恩施许家坪机场', '恩施'),
('XFN', '襄阳刘集机场', '襄阳'),
('CGD', '常德桃花源机场', '常德'),
('HJJ', '怀化芷江机场', '怀化'),
('DYG', '张家界荷花国际机场', '张家界'),
('CSX', '长沙黄花国际机场', '长沙'),
('LLF', '永州零陵机场', '永州'),
('DGM', '东莞机场', '东莞'),
('SZX', '深圳宝安国际机场', '深圳'),
('HUZ', '惠州机场', '惠州'),
('MXZ', '梅县长岗岌机场', '梅州'),
('SWA', '揭阳潮汕机场', '揭阳'),
('ZHA', '湛江机场', '湛江'),
('FUO', '佛山机场', '佛山'),
('HSC', '韶关桂头机场', '韶关'),
('ZUH', '珠海金湾机场', '珠海'),
('CAN', '广州白云国际机场', '广州'),
('LZH', '柳州白莲机场', '柳州'),
('AEB', '百色巴马机场', '百色'),
('BHY', '北海福成机场', '北海'),
('NNG', '南宁吴圩国际机场', '南宁'),
('WUZ', '梧州长洲岛机场', '梧州'),
('KWL', '桂林两江国际机场', '桂林'),
('HAK', '海口美兰国际机场', '海口'),
('SYX', '三亚凤凰国际机场', '三亚'),
('CKG', '重庆江北国际机场', '重庆'),
('WXN', '万州五桥机场', '万州'),
('JIQ', '黔江武陵山机场', '黔江'),
('DAX', '达州河市机场', '达州'),
('DCY', '稻城亚丁机场', '稻城'),
('JZH', '九寨黄龙机场', '九寨沟'),
('NAO', '南充高坪机场', '南充'),
('PZI', '攀枝花保安营机场', '攀枝花'),
('CTU', '成都双流国际机场', '成都'),
('SUN', '遂宁机场', '遂宁'),
('GYS', '广元盘龙机场', '广元'),
('KGT', '甘孜康定机场', '康定'),
('MIG', '绵阳南郊机场', '绵阳'),
('LZO', '泸州蓝田机场', '泸州'),
('XIC', '西昌青山机场', '西昌'),
('YBP', '宜宾菜坝机场', '宜宾'),
('AVA', '安顺黄果树机场', '安顺'),
('BFJ', '毕节飞雄机场', '毕节'),
('KWE', '贵阳龙洞堡国际机场', '贵阳'),
('ACX', '兴义机场', '黔西南'),
('HZH', '黎平机场', '黎平'),
('KJH', '凯里黄平机场', '黔东南'),
('LLB', '荔波机场', '黔南'),
('TEN', '铜仁凤凰机场', '铜仁'),
('ZYI', '遵义新舟机场', '遵义'),
('SYM', '普洱思茅机场', '普洱'),
('TCZ', '腾冲驼峰机场', '腾冲'),
('LNJ', '临沧机场', '临沧'),
('JHG', '西双版纳嘎洒国际机场', '西双版纳'),
('LJG', '丽江三义机场', '丽江'),
('ZAT', '昭通机场', '昭通'),
('BSD', '保山云瑞机场', '隆阳'),
('DLU', '大理机场', '大理'),
('LUM', '德宏芒市机场', '德宏'),
('DIG', '迪庆香格里拉机场', '迪庆'),
('KMG', '昆明长水国际机场', '昆明'),
('WNH', '文山普者黑机场', '文山'),
('NGQ', '阿里昆莎机场', '阿里'),
('BPX', '昌都邦达机场', '昌都'),
('RKZ', '日喀则和平机场', '日喀则'),
('LXA', '拉萨贡嘎机场', '拉萨'),
('LZY', '林芝米林机场', '林芝'),
('XIY', '西安咸阳国际机场', '西安'),
('UYN', '榆林榆阳机场', '榆林'),
('HZG', '汉中西关机场', '汉中'),
('AKA', '安康五里铺机场', '安康'),
('ENY', '延安二十里堡机场', '延安'),
('GXH', '甘南夏河机场', '甘南'),
('JIC', '金昌金川机场', '金昌'),
('YZY', '张掖甘州机场', '张掖'),
('DNH', '敦煌机场', '敦煌'),
('JGN', '嘉峪关机场', '嘉峪关'),
('LHW', '兰州中川机场', '兰州'),
('IQN', '庆阳机场', '庆阳'),
('THQ', '天水麦积山机场', '天水'),
('XNN', '西宁曹家堡机场', '西宁'),
('GOQ', '格尔木机场', '格尔木'),
('YUS', '玉树巴塘机场', '玉树'),
('GYU', '固原六盘山机场', '固原'),
('INC', '银川河东国际机场', '银川'),
('ZHY', '中卫沙坡头机场', '中卫'),
('AKU', '阿克苏机场', '阿克苏'),
('AAT', '阿勒泰机场', '阿勒泰'),
('FYN', '富蕴机场', '富蕴'),
('HMI', '哈密机场', '哈密'),
('HTN', '和田机场', '和田'),
('KRL', '库尔勒机场', '库尔勒'),
('IQM', '且末机场', '且末'),
('TLQ', '吐鲁番交河机场', '吐鲁番'),
('URC', '乌鲁木齐地窝堡国际机场', '乌鲁木齐'),
('BPL', '博乐阿拉山口机场', '博尔塔拉'),
('KJI', '布尔津喀纳斯机场', '布尔津'),
('KHG', '喀什机场', '喀什'),
('KRY', '克拉玛依机场', '克拉玛依'),
('KCA', '库车龟兹机场', '库车'),
('TCG', '塔城机场', '塔城'),
('YIN', '伊宁机场', '伊宁'),
('NLT', '新源那拉提机场', '新源'),
('HKG', '香港国际机场', '香港'),
('MFM', '澳门国际机场', '澳门'),
('TSA', '台北松山机场', '台北'),
('TPE', '桃园国际机场', '桃园'),
('KHH', '高雄国际机场', '高雄');

View File

@ -0,0 +1,32 @@
import pandas as pd
# 读取并处理数据
with open("./raw.txt", "r") as f:
data_list = f.readlines()
data_list = [data.strip() for data in data_list]
data = []
for line in data_list:
l = line.split('\t')
if len(l) < 2:
continue
data.append((l[1], l[3], l[0])) # Code, Airport, City
# 将数据转换为DataFrame
columns = ['ID', 'Name', 'City']
df = pd.DataFrame(data, columns=columns)
# 保存为CSV文件
df.to_csv('airports.csv', index=False)
# 生成SQL插入语句
insert_statements = 'INSERT INTO Airports (`ID`, `Name`, City) VALUES\n'
insert_statements += ',\n'.join([
f"('{row.ID}', '{row.Name}', '{row.City}')"
for row in df.itertuples(index=False)
])
insert_statements += ';'
# 保存SQL插入语句到文件
with open('airports.sql', 'w') as f:
f.write(insert_statements)

View File

@ -0,0 +1,241 @@
北京市
北京 NAY ZBNY 北京南苑机场 NANYUAN
北京 PEK ZBAA 北京首都国际机场 BEIJING
天津市
天津 TSN ZBTJ 天津滨海国际机场 TIANJIN
河北省
张家口 ZQZ ZBZJ 张家口宁远机场 ZHANGJIAKOU
邯郸 HDG ZBHD 邯郸机场 HANDAN
秦皇岛 SHP ZBSH 秦皇岛山海关机场 QINHUANGDAO
唐山 TVS ZBTS 唐山三女河机场 TANGSHAN
邢台 XNT ZBXT 邢台褡裢机场 SHAHE
石家庄 SJW ZBSJ 石家庄正定国际机场 SHIJIAZHUANG
山西省
太原 TYN ZBYN 太原武宿国际机场 TAIYUAN
吕梁 LLV ZBLL 吕梁机场 LVLIANG
长治 CIH ZBCZ 长治王村机场 CHANGZHI
大同 DAT ZBDT 大同云冈机场 DATONG
运城 YCU ZBYC 运城机场 YUNCHENG
内蒙古自治区
阿拉善左旗 AXF 阿拉善左旗巴彦浩特机场 BAYANHAOTE
阿拉善右旗 RHT 阿拉善右旗巴丹吉林机场 BADANJILIN
包头 BAV ZBOW 包头二里半机场 BAOTOU
赤峰 CIF ZBCF 赤峰玉龙机场 CHIFENG
鄂尔多斯 DSN ZBDS 鄂尔多斯伊金霍洛机场 ORDOS
额济纳旗 EJN 额济纳旗桃来机场 ERJINA
二连浩特 ERL ZBER 二连浩特赛乌苏机场 ERLIANHOT
满洲里 NZH ZBMZ 满洲里西郊机场 MANZHOULI
乌海 WUA ZBUH 乌海机场 WUHAI
阿尔山 YIE ZBES 阿尔山伊尔施机场 ARXAN
巴彦淖尔 RLK ZBYZ 巴彦淖尔天吉泰机场 BAYANNUR
呼和浩特 HET ZBHH 呼和浩特白塔国际机场 HOHHOT
呼伦贝尔 HLD ZBLA 呼伦贝尔海拉尔机场 HAILAR
通辽 TGO ZBTL 通辽机场 TONGLIAO
乌兰浩特 HLH ZBUL 乌兰浩特机场 ULANHOT
锡林浩特 XIL ZBXH 锡林浩特机场 XILINHOT
辽宁省
鞍山 AOG ZYAS 鞍山腾鳌机场 ANSHAN
长海 CNI ZYCH 长海大长山岛机场 CHANGHAI
朝阳 CHG ZYCY 朝阳机场 CHAOYANG
大连 DLC ZYTL 大连周水子国际机场 DALIAN
丹东 DDG ZYDD 丹东浪头机场 DANDONG
锦州 JNZ ZYJZ 锦州小岭子机场 JINZHOU
沈阳 SHE ZYTX 沈阳桃仙国际机场 SHENYANG
吉林省
通化 TNH ZYTN 通化三源浦机场 TONGHUA
白山 NBS ZYBS 长白山机场 CHANGBAISHAN
延边 YNJ ZYYJ 延吉朝阳川机场 YANJI
长春 CGQ ZYCC 长春龙嘉国际机场 CHANGCHUN
黑龙江省
鸡西 JXA ZYJX 鸡西兴凯湖机场 JIXI
佳木斯 JMU ZYJM 佳木斯东郊机场 JIAMUSI
牡丹江 MDG ZYMD 牡丹江海浪机场 MUDANJIANG
伊春 LDS ZYLD 伊春林都机场 YICHUN
黑河 HEK ZYHE 黑河机场 HEIHE
大庆 DQA ZYDQ 大庆萨尔图机场 DAQING
大兴安岭 JGD ZYJD 加格达奇机场 JIAGEDAQI
哈尔滨 HRB ZYHB 哈尔滨太平国际机场 HARBIN
漠河 OHE ZYMH 漠河古莲机场 MOHE
齐齐哈尔 NDG ZYQQ 齐齐哈尔三家子机场 QIQIHAER
上海市
上海 SHA ZSSS 上海虹桥国际机场 HONGQIAO
上海 PVG ZSPD 上海浦东国际机场 PUDONG
江苏省
淮安 HIA ZSSH 淮安涟水机场 HUAIAN
南通 NTG ZSNT 南通兴东机场 NANTONG
盐城 YNZ ZSYN 盐城南洋机场 YANCHENG
扬州 YTY ZSYA 扬州泰州机场 YANGZHOU
南京 NKG ZSNJ 南京禄口国际机场 NANJING
徐州 XUZ ZSXZ 徐州观音机场 XUZHOU
连云港 LYG ZSLG 连云港白塔埠机场 LIANYUNGANG
常州 CZX ZSCG 常州奔牛机场 CHANGZHOU
无锡 WUX ZSWX 苏南硕放国际机场 WUXI
浙江省
温州 WNZ ZSWZ 温州龙湾国际机场 WENZHOU
衢州 JUZ ZSJU 衢州机场 QUZHOU
台州 HYN ZSLQ 台州路桥机场 TAIZHOU
舟山 HSN ZSZS 舟山普陀山机场 ZHOUSHAN
杭州 HGH ZSHC 杭州萧山国际机场 HANGZHOU
金华 YIW ZSYW 义乌机场 YIWU
宁波 NGB ZSNB 宁波栎社国际机场 NINGBO
安徽省
安庆 AQG ZSAQ 安庆天柱山机场 ANQING
池州 JUH ZSJH 池州九华山机场 CHIZHOU
黄山 TXN ZSTX 黄山屯溪机场 HUANGSHAN
合肥 HFE ZSOF 合肥新桥国际机场 HEFEI
阜阳 FUG ZSFY 阜阳西关机场 FUYANG
福建省
福州 FOC ZSFZ 福州长乐国际机场 FUZHOU
沙县 SQJ 三明沙县机场 SANMING
龙岩 LCX ZSLD 连城冠豸山机场 LONGYAN
泉州 JJN ZSQZ 泉州晋江机场 QUANZHOU
南平 WUS ZSWY 武夷山机场 WUYISHAN
厦门 XMN ZSAM 厦门高崎国际机场 XIAMEN
江西省
赣州 KOW ZSGZ 赣州黄金机场 GANZHOU
吉安 JGS ZSGS 井冈山机场 JINGGANGSHAN
宜春 YIC ZSYC 宜春明月山机场 YICHUN
南昌 KHN ZSCN 南昌昌北国际机场 NANCHANG
景德镇 JDZ ZSJD 景德镇罗家机场 JINGDEZHEN
九江 JIU ZSJJ 九江庐山机场 JIUJIANG
山东省
济宁 JNG ZSJG 济宁曲阜机场 JINING
潍坊 WEF ZSWF 潍坊机场 WEIFANG
青岛 TAO ZSQD 青岛流亭国际机场 QINGDAO
济南 TNA ZSJN 济南遥墙国际机场 JINAN
临沂 LYI ZSLY 临沂沭埠岭机场 LINYI
烟台 YNT ZSYT 烟台莱山国际机场 YANTAI
东营 DOY ZSDY 东营胜利机场 DONGYING
威海 WEH ZSWH 威海国际机场 WEIHAI
河南省
洛阳 LYA ZHLY 洛阳北郊机场 LUOYANG
郑州 CGO ZHCC 郑州新郑国际机场 ZHENGZHOU
南阳 NNY ZHNY 南阳姜营机场 NANYANG
湖北省
武汉 WUH ZHHH 武汉天河国际机场 WUHAN
宜昌 YIH ZHYC 宜昌三峡机场 YICHANG
恩施 ENH ZHES 恩施许家坪机场 ENSHI
襄阳 XFN ZHXF 襄阳刘集机场 XIANGYANG
湖南省
常德 CGD ZGCD 常德桃花源机场 CHANGDE
怀化 HJJ ZGCJ 怀化芷江机场 HUAIHUA
张家界 DYG ZGDY 张家界荷花国际机场 ZHANGJIAJIE
长沙 CSX ZGHA 长沙黄花国际机场 CHANGSHA
永州 LLF ZGLG 永州零陵机场 YONGZHOU
广东省
东莞 DGM 东莞机场 DONGGUAN
深圳 SZX ZGSZ 深圳宝安国际机场 SHENZHEN
惠州 HUZ ZGHZ 惠州机场 HUIZHOU
梅州 MXZ ZGMX 梅县长岗岌机场 MEIXIAN
揭阳 SWA ZGOW 揭阳潮汕机场 JIEYANG
湛江 ZHA ZGZJ 湛江机场 ZHANJIANG
佛山 FUO ZGFS 佛山机场 FOSHAN
韶关 HSC 韶关桂头机场 SHAOGUAN
珠海 ZUH ZGSD 珠海金湾机场 ZHUHAI
广州 CAN ZGGG 广州白云国际机场 GUANGZHOU
广西壮族自治区
柳州 LZH ZGZH 柳州白莲机场 LIUZHOU
百色 AEB ZGBS 百色巴马机场 BAISE
北海 BHY ZGBH 北海福成机场 BEIHAI
南宁 NNG ZGNN 南宁吴圩国际机场 NANNING
梧州 WUZ ZGWZ 梧州长洲岛机场 WUZHOU
桂林 KWL ZGKL 桂林两江国际机场 GUILIN
海南省
海口 HAK ZJHK 海口美兰国际机场 HAIKOU
三亚 SYX ZJSY 三亚凤凰国际机场 SANYA
重庆市
重庆 CKG ZUCK 重庆江北国际机场 CHONGQING
万州 WXN ZUWX 万州五桥机场 WANZHOU
黔江 JIQ ZUQJ 黔江武陵山机场 ZHOUBAI
四川省
达州 DAX ZUDX 达州河市机场 DAZHOU
稻城 DCY ZUDC 稻城亚丁机场 DAOCHENG
九寨沟 JZH ZUJZ 九寨黄龙机场 JIUZHAIGOU
南充 NAO ZUNC 南充高坪机场 NANCHONG
攀枝花 PZI ZUZI 攀枝花保安营机场 PANZHIHUA
成都 CTU ZUUU 成都双流国际机场 CHENGDU
遂宁 SUN ZNSU 遂宁机场 SUINING
广元 GYS ZUGU 广元盘龙机场 GUANGYUAN
康定 KGT ZUKD 甘孜康定机场 KANGDING
绵阳 MIG ZUMY 绵阳南郊机场 MIANYANG
泸州 LZO ZULZ 泸州蓝田机场 LUZHOU
西昌 XIC ZUXC 西昌青山机场 XICHANG
宜宾 YBP ZUYB 宜宾菜坝机场 YIBIN
贵州省
安顺 AVA ZUAS 安顺黄果树机场 ANSHUN
毕节 BFJ ZUBJ 毕节飞雄机场 BIJIE
贵阳 KWE ZUGY 贵阳龙洞堡国际机场 GUIYANG
黔西南 ACX ZUYI 兴义机场 XINGYI
黎平 HZH ZUNP 黎平机场 LIPING
黔东南 KJH ZUKJ 凯里黄平机场 KAILI
黔南 LLB ZULB 荔波机场 LIBO
铜仁 TEN ZUTR 铜仁凤凰机场 TONGREN
遵义 ZYI ZUZY 遵义新舟机场 ZUNYI
云南省
普洱 SYM ZPSM 普洱思茅机场 PUER
腾冲 TCZ ZUTC 腾冲驼峰机场 TENGCHONG
临沧 LNJ ZPLC 临沧机场 LINCANG
西双版纳 JHG ZPJH 西双版纳嘎洒国际机场 JINGHONG
丽江 LJG ZPLJ 丽江三义机场 LIJIANG
昭通 ZAT ZPZT 昭通机场 ZHAOTONG
隆阳 BSD ZPBS 保山云瑞机场 BAOSHAN
大理 DLU ZPDL 大理机场 DALIXIAGUAN
德宏 LUM ZPMS 德宏芒市机场 MANGSHI
迪庆 DIG ZPDQ 迪庆香格里拉机场 DIQING
昆明 KMG ZPPP 昆明长水国际机场 KUNMING
文山 WNH ZPWS 文山普者黑机场 WENSHAN
西藏自治区
阿里 NGQ ZUAL 阿里昆莎机场 SHIQUANHE
昌都 BPX ZUBD 昌都邦达机场 CHAMDO
日喀则 RKZ ZURK 日喀则和平机场 RIKAZE
拉萨 LXA ZULS 拉萨贡嘎机场 LHASA
林芝 LZY ZUNZ 林芝米林机场 NYINGCHI
陕西省
西安 XIY ZLXY 西安咸阳国际机场 XIAN
榆林 UYN ZLYL 榆林榆阳机场 YULIN
汉中 HZG ZLHZ 汉中西关机场 HANZHONG
安康 AKA ZLAK 安康五里铺机场 ANKANG
延安 ENY ZLYA 延安二十里堡机场 YANAN
甘肃省
甘南 GXH ZLXH 甘南夏河机场 XIAHE
金昌 JIC ZLJC 金昌金川机场 JINCHANG
张掖 YZY ZLZY 张掖甘州机场 ZHANGYE
敦煌 DNH ZLDH 敦煌机场 DUNHUANG
嘉峪关 JGN ZLJQ 嘉峪关机场 JIAYUGUAN
兰州 LHW ZLLL 兰州中川机场 LANZHOU
庆阳 IQN ZLQY 庆阳机场 QINGYANG
天水 THQ ZLTS 天水麦积山机场 TIANSHUI
青海省
西宁 XNN ZLXN 西宁曹家堡机场 XINING
格尔木 GOQ ZLGM 格尔木机场 GOLMUD
玉树 YUS ZLYS 玉树巴塘机场 YUSHU
宁夏回族自治区
固原 GYU ZLGY 固原六盘山机场 GUYUAN
银川 INC ZLIC 银川河东国际机场 YINCHUAN
中卫 ZHY ZLZW 中卫沙坡头机场 ZHONGWEI
新疆维吾尔自治区
阿克苏 AKU ZWAK 阿克苏机场 AKSU
阿勒泰 AAT ZWAT 阿勒泰机场 ALTAY
富蕴 FYN ZWFY 富蕴机场 FUYUN
哈密 HMI ZWHM 哈密机场 HAMI
和田 HTN ZWTN 和田机场 HETIAN
库尔勒 KRL ZWKL 库尔勒机场 KORLA
且末 IQM ZWCM 且末机场 QIEMO
吐鲁番 TLQ ZWTP 吐鲁番交河机场 TULUFAN
乌鲁木齐 URC ZWWW 乌鲁木齐地窝堡国际机场 URUMQI
博尔塔拉 BPL ZWBL 博乐阿拉山口机场 BOLE
布尔津 KJI ZWKN 布尔津喀纳斯机场 BUERJIN
喀什 KHG ZWSH 喀什机场 KASHGAR
克拉玛依 KRY ZWKM 克拉玛依机场 KARAMAY
库车 KCA ZWKC 库车龟兹机场 KUQA
塔城 TCG ZWTC 塔城机场 TACHENG
伊宁 YIN ZWYN 伊宁机场 YINING
新源 NLT ZWNL 新源那拉提机场 NALATI
香港特别行政区
香港 HKG VHHH 香港国际机场 HONG KONG
澳门特别行政区
澳门 MFM VMMC 澳门国际机场 MACAU
台湾省
台北 TSA RCSS 台北松山机场 TAIBEI
桃园 TPE RCTP 桃园国际机场 TAOYUAN
高雄 KHH RCKH 高雄国际机场 GAOXIONG

View File

@ -0,0 +1,105 @@
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
('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, '已降落'),
('FL004', 'AirlineD', 'PVG', 'CAN', '2024-06-14 06:00:00', '2024-06-14 08:00:00', 4, 8, 90, 2300.00, 1300.00, 600.00, '已降落'),
('FL005', 'AirlineE', 'SZX', 'CTU', '2024-06-14 10:00:00', '2024-06-14 12:00:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '已降落'),
('FL006', 'AirlineF', 'CAN', 'KWE', '2024-06-14 11:00:00', '2024-06-14 13:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '已降落'),
('FL007', 'AirlineG', 'CTU', 'XIY', '2024-06-14 12:00:00', '2024-06-14 14:00:00', 3, 15, 80, 2100.00, 1100.00, 600.00, '已降落'),
('FL008', 'AirlineH', 'KWE', 'LHW', '2024-06-14 13:00:00', '2024-06-14 15:00:00', 2, 12, 70, 2200.00, 1200.00, 550.00, '已降落'),
('FL009', 'AirlineI', 'XIY', 'PEK', '2024-06-14 14:00:00', '2024-06-14 16:00:00', 4, 8, 90, 2300.00, 1300.00, 600.00, '已降落'),
('FL010', 'AirlineJ', 'LHW', 'TSN', '2024-06-14 15:00:00', '2024-06-14 17:00:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '已降落'),
('FL210', 'AirlineJ', 'LHW', 'TSN', '2024-06-14 21:00:00', '2024-06-14 23:50:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '开始检票'),
('FL011', 'AirlineA', 'PEK', 'CAN', '2024-06-15 08:00:00', '2024-06-15 10:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '候机中'),
('FL012', 'AirlineB', 'TSN', 'CTU', '2024-06-15 09:00:00', '2024-06-15 11:00:00', 3, 15, 80, 2100.00, 1100.00, 600.00, '延误'),
('FL013', 'AirlineC', 'SHA', 'KWE', '2024-06-15 07:00:00', '2024-06-15 09:00:00', 2, 12, 70, 2200.00, 1200.00, 550.00, '候机中'),
('FL014', 'AirlineD', 'PVG', 'XIY', '2024-06-15 06:00:00', '2024-06-15 08:00:00', 4, 8, 90, 2300.00, 1300.00, 600.00, '候机中'),
('FL015', 'AirlineE', 'SZX', 'LHW', '2024-06-15 10:00:00', '2024-06-15 12:00:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '延误'),
('FL016', 'AirlineF', 'CAN', 'PEK', '2024-06-15 11:00:00', '2024-06-15 13:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '候机中'),
('FL017', 'AirlineG', 'CTU', 'TSN', '2024-06-15 12:00:00', '2024-06-15 14:00:00', 3, 15, 80, 2100.00, 1100.00, 600.00, '候机中'),
('FL018', 'AirlineH', 'KWE', 'SHA', '2024-06-15 13:00:00', '2024-06-15 15:00:00', 2, 12, 70, 2200.00, 1200.00, 550.00, '延误'),
('FL019', 'AirlineI', 'XIY', 'PVG', '2024-06-15 14:00:00', '2024-06-15 16:00:00', 4, 8, 90, 2300.00, 1300.00, 600.00, '候机中'),
('FL020', 'AirlineJ', 'LHW', 'SZX', '2024-06-15 15:00:00', '2024-06-15 17:00:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '候机中'),
('FL021', 'AirlineA', 'PEK', 'SHA', '2024-06-16 08:00:00', '2024-06-16 10:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '延误'),
('FL121', 'AirlineB', 'NAY', 'SHA', '2024-06-16 09:00:00', '2024-06-16 12:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '未知'),
('FL221', 'AirlineC', 'PEK', 'PVG', '2024-06-16 11:00:00', '2024-06-16 12:30:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '未知'),
('FL022', 'AirlineB', 'TSN', 'PVG', '2024-06-16 09:00:00', '2024-06-16 11:00:00', 3, 15, 80, 2100.00, 1100.00, 600.00, '延误'),
('FL023', 'AirlineC', 'SHA', 'SZX', '2024-06-16 07:00:00', '2024-06-16 09:00:00', 2, 12, 70, 2200.00, 1200.00, 550.00, '延误'),
('FL024', 'AirlineD', 'PVG', 'CAN', '2024-06-16 06:00:00', '2024-06-16 08:00:00', 4, 8, 90, 2300.00, 1300.00, 600.00, '延误'),
('FL025', 'AirlineE', 'SZX', 'CTU', '2024-06-16 10:00:00', '2024-06-16 12:00:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '延误'),
('FL026', 'AirlineF', 'CAN', 'KWE', '2024-06-16 11:00:00', '2024-06-16 13:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '延误'),
('FL027', 'AirlineG', 'CTU', 'XIY', '2024-06-16 12:00:00', '2024-06-16 14:00:00', 3, 15, 80, 2100.00, 1100.00, 600.00, '未知'),
('FL028', 'AirlineH', 'KWE', 'LHW', '2024-06-16 13:00:00', '2024-06-16 15:00:00', 2, 12, 70, 2200.00, 1200.00, 550.00, '未知'),
('FL029', 'AirlineI', 'XIY', 'PEK', '2024-06-16 14:00:00', '2024-06-16 16:00:00', 4, 8, 90, 2300.00, 1300.00, 600.00, '未知'),
('FL030', 'AirlineJ', 'LHW', 'TSN', '2024-06-16 15:00:00', '2024-06-16 17:00:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '未知'),
('FL031', 'AirlineA', 'PEK', 'CAN', '2024-06-17 08:00:00', '2024-06-17 10:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '未知'),
('FL032', 'AirlineB', 'TSN', 'CTU', '2024-06-17 09:00:00', '2024-06-17 11:00:00', 3, 15, 80, 2100.00, 1100.00, 600.00, '未知'),
('FL033', 'AirlineC', 'SHA', 'KWE', '2024-06-17 07:00:00', '2024-06-17 09:00:00', 2, 12, 70, 2200.00, 1200.00, 550.00, '未知'),
('FL034', 'AirlineD', 'PVG', 'XIY', '2024-06-17 06:00:00', '2024-06-17 08:00:00', 4, 8, 90, 2300.00, 1300.00, 600.00, '未知'),
('FL035', 'AirlineE', 'SZX', 'LHW', '2024-06-17 10:00:00', '2024-06-17 12:00:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '未知'),
('FL036', 'AirlineF', 'CAN', 'PEK', '2024-06-17 11:00:00', '2024-06-17 13:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '未知'),
('FL037', 'AirlineG', 'CTU', 'TSN', '2024-06-17 12:00:00', '2024-06-17 14:00:00', 3, 15, 80, 2100.00, 1100.00, 600.00, '未知'),
('FL038', 'AirlineH', 'KWE', 'SHA', '2024-06-17 13:00:00', '2024-06-17 15:00:00', 2, 12, 70, 2200.00, 1200.00, 550.00, '未知'),
('FL039', 'AirlineI', 'XIY', 'PVG', '2024-06-17 14:00:00', '2024-06-17 16:00:00', 4, 8, 90, 2300.00, 1300.00, 600.00, '未知'),
('FL040', 'AirlineJ', 'LHW', 'SZX', '2024-06-17 15:00:00', '2024-06-17 17:00:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '未知'),
('FL041', 'AirlineA', 'PEK', 'SHA', '2024-06-18 08:00:00', '2024-06-18 10:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '未知'),
('FL042', 'AirlineB', 'TSN', 'PVG', '2024-06-18 09:00:00', '2024-06-18 11:00:00', 3, 15, 80, 2100.00, 1100.00, 600.00, '未知'),
('FL043', 'AirlineC', 'SHA', 'SZX', '2024-06-18 07:00:00', '2024-06-18 09:00:00', 2, 12, 70, 2200.00, 1200.00, 550.00, '未知'),
('FL044', 'AirlineD', 'PVG', 'CAN', '2024-06-18 06:00:00', '2024-06-18 08:00:00', 4, 8, 90, 2300.00, 1300.00, 600.00, '未知'),
('FL045', 'AirlineE', 'SZX', 'CTU', '2024-06-18 10:00:00', '2024-06-18 12:00:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '未知'),
('FL046', 'AirlineF', 'CAN', 'KWE', '2024-06-18 11:00:00', '2024-06-18 13:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '未知'),
('FL047', 'AirlineG', 'CTU', 'XIY', '2024-06-18 12:00:00', '2024-06-18 14:00:00', 3, 15, 80, 2100.00, 1100.00, 600.00, '未知'),
('FL048', 'AirlineH', 'KWE', 'LHW', '2024-06-18 13:00:00', '2024-06-18 15:00:00', 2, 12, 70, 2200.00, 1200.00, 550.00, '未知'),
('FL049', 'AirlineI', 'XIY', 'PEK', '2024-06-18 14:00:00', '2024-06-18 16:00:00', 4, 8, 90, 2300.00, 1300.00, 600.00, '未知'),
('FL050', 'AirlineJ', 'LHW', 'TSN', '2024-06-18 15:00:00', '2024-06-18 17:00:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '未知'),
('FL051', 'AirlineA', 'PEK', 'CAN', '2024-06-19 08:00:00', '2024-06-19 10:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '未知'),
('FL052', 'AirlineB', 'TSN', 'CTU', '2024-06-19 09:00:00', '2024-06-19 11:00:00', 3, 15, 80, 2100.00, 1100.00, 600.00, '未知'),
('FL053', 'AirlineC', 'SHA', 'KWE', '2024-06-19 07:00:00', '2024-06-19 09:00:00', 2, 12, 70, 2200.00, 1200.00, 550.00, '未知'),
('FL054', 'AirlineD', 'PVG', 'XIY', '2024-06-19 06:00:00', '2024-06-19 08:00:00', 4, 8, 90, 2300.00, 1300.00, 600.00, '未知'),
('FL055', 'AirlineE', 'SZX', 'LHW', '2024-06-19 10:00:00', '2024-06-19 12:00:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '未知'),
('FL056', 'AirlineF', 'CAN', 'PEK', '2024-06-19 11:00:00', '2024-06-19 13:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '未知'),
('FL057', 'AirlineG', 'CTU', 'TSN', '2024-06-19 12:00:00', '2024-06-19 14:00:00', 3, 15, 80, 2100.00, 1100.00, 600.00, '未知'),
('FL058', 'AirlineH', 'KWE', 'SHA', '2024-06-19 13:00:00', '2024-06-19 15:00:00', 2, 12, 70, 2200.00, 1200.00, 550.00, '未知'),
('FL059', 'AirlineI', 'XIY', 'PVG', '2024-06-19 14:00:00', '2024-06-19 16:00:00', 4, 8, 90, 2300.00, 1300.00, 600.00, '未知'),
('FL060', 'AirlineJ', 'LHW', 'SZX', '2024-06-19 15:00:00', '2024-06-19 17:00:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '未知'),
('FL061', 'AirlineA', 'PEK', 'SHA', '2024-06-20 08:00:00', '2024-06-20 10:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '未知'),
('FL062', 'AirlineB', 'TSN', 'PVG', '2024-06-20 09:00:00', '2024-06-20 11:00:00', 3, 15, 80, 2100.00, 1100.00, 600.00, '未知'),
('FL063', 'AirlineC', 'SHA', 'SZX', '2024-06-20 07:00:00', '2024-06-20 09:00:00', 2, 12, 70, 2200.00, 1200.00, 550.00, '未知'),
('FL064', 'AirlineD', 'PVG', 'CAN', '2024-06-20 06:00:00', '2024-06-20 08:00:00', 4, 8, 90, 2300.00, 1300.00, 600.00, '未知'),
('FL065', 'AirlineE', 'SZX', 'CTU', '2024-06-20 10:00:00', '2024-06-20 12:00:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '未知'),
('FL066', 'AirlineF', 'CAN', 'KWE', '2024-06-20 11:00:00', '2024-06-20 13:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '未知'),
('FL067', 'AirlineG', 'CTU', 'XIY', '2024-06-20 12:00:00', '2024-06-20 14:00:00', 3, 15, 80, 2100.00, 1100.00, 600.00, '未知'),
('FL068', 'AirlineH', 'KWE', 'LHW', '2024-06-20 13:00:00', '2024-06-20 15:00:00', 2, 12, 70, 2200.00, 1200.00, 550.00, '未知'),
('FL069', 'AirlineI', 'XIY', 'PEK', '2024-06-20 14:00:00', '2024-06-20 16:00:00', 4, 8, 90, 2300.00, 1300.00, 600.00, '未知'),
('FL070', 'AirlineJ', 'LHW', 'TSN', '2024-06-20 15:00:00', '2024-06-20 17:00:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '未知'),
('FL071', 'AirlineA', 'PEK', 'CAN', '2024-06-21 08:00:00', '2024-06-21 10:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '未知'),
('FL072', 'AirlineB', 'TSN', 'CTU', '2024-06-21 09:00:00', '2024-06-21 11:00:00', 3, 15, 80, 2100.00, 1100.00, 600.00, '未知'),
('FL073', 'AirlineC', 'SHA', 'KWE', '2024-06-21 07:00:00', '2024-06-21 09:00:00', 2, 12, 70, 2200.00, 1200.00, 550.00, '未知'),
('FL074', 'AirlineD', 'PVG', 'XIY', '2024-06-21 06:00:00', '2024-06-21 08:00:00', 4, 8, 90, 2300.00, 1300.00, 600.00, '未知'),
('FL075', 'AirlineE', 'SZX', 'LHW', '2024-06-21 10:00:00', '2024-06-21 12:00:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '未知'),
('FL076', 'AirlineF', 'CAN', 'PEK', '2024-06-21 11:00:00', '2024-06-21 13:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '未知'),
('FL077', 'AirlineG', 'CTU', 'TSN', '2024-06-21 12:00:00', '2024-06-21 14:00:00', 3, 15, 80, 2100.00, 1100.00, 600.00, '未知'),
('FL078', 'AirlineH', 'KWE', 'SHA', '2024-06-21 13:00:00', '2024-06-21 15:00:00', 2, 12, 70, 2200.00, 1200.00, 550.00, '未知'),
('FL079', 'AirlineI', 'XIY', 'PVG', '2024-06-21 14:00:00', '2024-06-21 16:00:00', 4, 8, 90, 2300.00, 1300.00, 600.00, '未知'),
('FL080', 'AirlineJ', 'LHW', 'SZX', '2024-06-21 15:00:00', '2024-06-21 17:00:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '未知'),
('FL081', 'AirlineA', 'PEK', 'SHA', '2024-06-22 08:00:00', '2024-06-22 10:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '未知'),
('FL082', 'AirlineB', 'TSN', 'PVG', '2024-06-22 09:00:00', '2024-06-22 11:00:00', 3, 15, 80, 2100.00, 1100.00, 600.00, '未知'),
('FL083', 'AirlineC', 'SHA', 'SZX', '2024-06-22 07:00:00', '2024-06-22 09:00:00', 2, 12, 70, 2200.00, 1200.00, 550.00, '未知'),
('FL084', 'AirlineD', 'PVG', 'CAN', '2024-06-22 06:00:00', '2024-06-22 08:00:00', 4, 8, 90, 2300.00, 1300.00, 600.00, '未知'),
('FL085', 'AirlineE', 'SZX', 'CTU', '2024-06-22 10:00:00', '2024-06-22 12:00:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '未知'),
('FL086', 'AirlineF', 'CAN', 'KWE', '2024-06-22 11:00:00', '2024-06-22 13:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '未知'),
('FL087', 'AirlineG', 'CTU', 'XIY', '2024-06-22 12:00:00', '2024-06-22 14:00:00', 3, 15, 80, 2100.00, 1100.00, 600.00, '未知'),
('FL088', 'AirlineH', 'KWE', 'LHW', '2024-06-22 13:00:00', '2024-06-22 15:00:00', 2, 12, 70, 2200.00, 1200.00, 550.00, '未知'),
('FL089', 'AirlineI', 'XIY', 'PEK', '2024-06-22 14:00:00', '2024-06-22 16:00:00', 4, 8, 90, 2300.00, 1300.00, 600.00, '未知'),
('FL090', 'AirlineJ', 'LHW', 'TSN', '2024-06-22 15:00:00', '2024-06-22 17:00:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '未知'),
('FL091', 'AirlineA', 'PEK', 'SHA', '2024-06-23 08:00:00', '2024-06-23 10:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '未知'),
('FL092', 'AirlineB', 'TSN', 'PVG', '2024-06-23 09:00:00', '2024-06-23 11:00:00', 3, 15, 80, 2100.00, 1100.00, 600.00, '未知'),
('FL093', 'AirlineC', 'SHA', 'SZX', '2024-06-23 07:00:00', '2024-06-23 09:00:00', 2, 12, 70, 2200.00, 1200.00, 550.00, '未知'),
('FL094', 'AirlineD', 'PVG', 'CAN', '2024-06-23 06:00:00', '2024-06-23 08:00:00', 4, 8, 90, 2300.00, 1300.00, 600.00, '未知'),
('FL095', 'AirlineE', 'SZX', 'CTU', '2024-06-23 10:00:00', '2024-06-23 12:00:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '未知'),
('FL096', 'AirlineF', 'CAN', 'KWE', '2024-06-23 11:00:00', '2024-06-23 13:00:00', 5, 10, 100, 2000.00, 1000.00, 500.00, '未知'),
('FL097', 'AirlineG', 'CTU', 'XIY', '2024-06-23 12:00:00', '2024-06-23 14:00:00', 3, 15, 80, 2100.00, 1100.00, 600.00, '未知'),
('FL098', 'AirlineH', 'KWE', 'LHW', '2024-06-23 13:00:00', '2024-06-23 15:00:00', 2, 12, 70, 2200.00, 1200.00, 550.00, '未知'),
('FL099', 'AirlineI', 'XIY', 'PEK', '2024-06-23 14:00:00', '2024-06-23 16:00:00', 4, 8, 90, 2300.00, 1300.00, 600.00, '未知'),
('FL100', 'AirlineJ', 'LHW', 'TSN', '2024-06-23 15:00:00', '2024-06-23 17:00:00', 1, 10, 60, 2400.00, 1400.00, 650.00, '未知');

View File

@ -0,0 +1,9 @@
DROP TABLE IF EXISTS Managers;
CREATE TABLE Managers (
ID VARCHAR(255) PRIMARY KEY,
`Password` VARCHAR(255) NOT NULL
);
INSERT INTO Managers
VALUES ('Admin', 'e10adc3949ba59abbe56e057f20f883e');

View File

@ -1,14 +1,15 @@
DROP TABLE IF EXISTS Tickets; DROP TABLE IF EXISTS Tickets;
DROP TABLE IF EXISTS Orders;
DROP TABLE IF EXISTS Users;
DROP TABLE IF EXISTS Flights; DROP TABLE IF EXISTS Flights;
DROP TABLE IF EXISTS Airports; DROP TABLE IF EXISTS Airports;
DROP TABLE IF EXISTS Users;
DROP TABLE IF EXISTS Passengers; DROP TABLE IF EXISTS Passengers;
CREATE TABLE Passengers ( CREATE TABLE Passengers (
ID BIGINT PRIMARY KEY, ID VARCHAR(18) PRIMARY KEY,
`Name` VARCHAR(255) NOT NULL, `Name` VARCHAR(255) NOT NULL,
Phone_number BIGINT NOT NULL, Phone_number BIGINT NOT NULL,
CHECK (REGEXP_LIKE(ID, '^\\d{18}$')), CHECK (REGEXP_LIKE(ID, '^[1-9]\\d{5}(19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[1-2]\\d|3[0-1])\\d{3}([0-9]|x)$')),
CHECK (REGEXP_LIKE(Phone_number, '^\\d{11}$')) CHECK (REGEXP_LIKE(Phone_number, '^\\d{11}$'))
); );
@ -20,17 +21,16 @@ CREATE TABLE Users (
); );
CREATE TABLE Airports ( CREATE TABLE Airports (
ID INT AUTO_INCREMENT PRIMARY KEY, ID VARCHAR(3) PRIMARY KEY, -- 机场三字码
`Name` VARCHAR(255) UNIQUE NOT NULL, `Name` VARCHAR(255) UNIQUE NOT NULL,
Country VARCHAR(255) NOT NULL,
City VARCHAR(255) NOT NULL City VARCHAR(255) NOT NULL
); );
CREATE TABLE Flights ( CREATE TABLE Flights (
ID VARCHAR(255) PRIMARY KEY, ID VARCHAR(255) PRIMARY KEY,
Airline VARCHAR(255) NOT NULL, Airline VARCHAR(255) NOT NULL,
Departure_airport INT NOT NULL, Departure_airport VARCHAR(3) NOT NULL,
Arrival_airport INT NOT NULL, Arrival_airport VARCHAR(3) NOT NULL,
Departure_time DATETIME NOT NULL, Departure_time DATETIME NOT NULL,
Arrival_time DATETIME NOT NULL, Arrival_time DATETIME NOT NULL,
First_class_seats_remaining INT NOT NULL, -- 头等舱剩余座位 First_class_seats_remaining INT NOT NULL, -- 头等舱剩余座位
@ -39,20 +39,29 @@ CREATE TABLE Flights (
First_class_price DECIMAL(7, 2) NOT NULL, -- 头等舱价格 First_class_price DECIMAL(7, 2) NOT NULL, -- 头等舱价格
Business_class_price DECIMAL(7, 2) NOT NULL, -- 商务舱价格 Business_class_price DECIMAL(7, 2) NOT NULL, -- 商务舱价格
Economy_class_price DECIMAL(7, 2) NOT NULL, -- 经济舱价格 Economy_class_price DECIMAL(7, 2) NOT NULL, -- 经济舱价格
`Status` VARCHAR(255) NOT NULL CHECK (`Status` IN ('候机中', '延误', '已起飞', '已降落', '开始检票')), -- 航班状态 `Status` VARCHAR(255) NOT NULL CHECK (`Status` IN ('候机中', '延误', '已起飞', '已降落', '开始检票', '未知')), -- 航班状态
FOREIGN KEY (Departure_airport) REFERENCES Airports(ID) ON DELETE CASCADE, FOREIGN KEY (Departure_airport) REFERENCES Airports(ID) ON DELETE CASCADE,
FOREIGN KEY (Arrival_airport) REFERENCES Airports(ID) ON DELETE CASCADE, FOREIGN KEY (Arrival_airport) REFERENCES Airports(ID) ON DELETE CASCADE,
CHECK (Departure_time < Arrival_time) CHECK (Departure_time < Arrival_time)
); );
CREATE TABLE Orders (
ID INT AUTO_INCREMENT PRIMARY KEY,
Order_time DATETIME NOT NULL,
Paid TINYINT NOT NULL,
User_phone_number BIGINT NOT NULL,
FOREIGN KEY (User_phone_number) REFERENCES Users(Phone_number) ON DELETE CASCADE
);
CREATE TABLE Tickets ( CREATE TABLE Tickets (
ID INT AUTO_INCREMENT PRIMARY KEY, ID INT AUTO_INCREMENT PRIMARY KEY,
Price DECIMAL(7, 2) NOT NULL, Price DECIMAL(7, 2) NOT NULL,
FlightID VARCHAR(255) NOT NULL, FlightID VARCHAR(255) NOT NULL,
Seat_class VARCHAR(255) NOT NULL, -- 级别信息 Seat_class VARCHAR(255) NOT NULL, -- 级别信息
PassengerID BIGINT NOT NULL, PassengerID VARCHAR(18) NOT NULL,
Paid TINYINT NOT NULL, OrderID INT NOT NULL,
FOREIGN KEY (FlightID) REFERENCES Flights(ID) ON DELETE CASCADE, FOREIGN KEY (FlightID) REFERENCES Flights(ID) ON DELETE CASCADE,
FOREIGN KEY (PassengerID) REFERENCES Passengers(ID) ON DELETE CASCADE, FOREIGN KEY (PassengerID) REFERENCES Passengers(ID) ON DELETE CASCADE,
FOREIGN KEY (OrderID) REFERENCES Orders(ID) ON DELETE CASCADE,
CHECK (Seat_class IN ('First Class', 'Business Class', 'Economy Class')) CHECK (Seat_class IN ('First Class', 'Business Class', 'Economy Class'))
); );

View File

@ -0,0 +1,9 @@
db = {
'host':'localhost',
'user':'kejingfan',
'password':'KJF2811879',
'database':'TESTDB'
}
SECRET_KEY = 'ILOVEDATABASETECH'

View File

@ -0,0 +1,32 @@
from flask import render_template, request, g, redirect, url_for, session
from .config import db
import pymysql
def index():
if request.method == 'GET':
if not g.user:
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'))
def modify():
pass

View File

@ -0,0 +1,34 @@
from flask import request, jsonify, session, url_for, render_template
from .config import db
import pymysql
def connect(managerID, encrypted_password):
conn = pymysql.connect(**db)
cursor = conn.cursor(pymysql.cursors.DictCursor)
args = (managerID, encrypted_password)
verify_sql = "SELECT COUNT(*) FROM Managers WHERE ID = %s AND `Password` = %s;"
cursor.execute(verify_sql, args)
verified = cursor.fetchone()
cursor.close()
conn.close()
return verified['COUNT(*)'] > 0
def login():
if request.method == 'GET':
return render_template('login.html')
if request.method == 'POST':
session.pop('user_id', None)
managerID = request.json.get('username')
encrypted_password = request.json.get('password')
try:
user = connect(managerID, encrypted_password)
if not user:
return jsonify({'message': '账号或密码错误'}), 401
session['user_id'] = managerID
session.modified = True
return jsonify({'redirect': url_for('index')})
except Exception as e:
print(e)
return jsonify({'message': '数据库错误,请稍后再试'}), 500

49
Project/Manager/main.py Normal file
View File

@ -0,0 +1,49 @@
from flask import Flask, redirect, url_for, session, g
from flask_httpauth import HTTPTokenAuth
from flask_cors import CORS
from func.config import SECRET_KEY
import func.login
import func.index
app = Flask(__name__)
app.config["SECRET_KEY"] = SECRET_KEY
app.config["JSON_AS_ASCII"] = False
app.config['SESSION_COOKIE_HTTPONLY'] = True
app.config['SESSION_COOKIE_SECURE'] = False
app.config['SESSION_COOKIE_SAMESITE'] = 'Lax'
CORS(app, supports_credentials=True)
auth = HTTPTokenAuth(scheme='Bearer')
@app.before_request
def before_request():
g.user = None
if 'user_id' in session:
g.user = session.get('user_id')
@app.route("/")
def home():
return redirect(url_for('index'))
@app.route("/index", methods=['GET'])
def index():
return func.index.index()
@app.route("/modify", methods=['POST'])
def modify():
return func.index.modify()
@app.route("/login", methods=['GET', 'POST'])
def login():
return func.login.login()
@app.route('/logout')
def logout():
return func.index.logout()
if __name__ == "__main__":
app.run(
host="0.0.0.0",
port=8889,
debug=True
)

View File

@ -0,0 +1,251 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
min-height: 100vh;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
background-color: rgba(28, 108, 178, 0.9);
color: white;
padding: 20px;
width: 100%;
position: fixed;
top: 0;
z-index: 1000;
}
.header-content {
display: flex;
align-items: center;
width: 100%;
justify-content: space-between;
}
.logo {
font-size: 24px;
font-weight: bold;
margin-left: 20px;
}
.nav-buttons {
display: flex;
gap: 20px;
}
.nav-buttons a {
color: white;
text-decoration: none;
font-size: 16px;
padding: 10px;
border-radius: 5px;
}
.nav-buttons a:hover {
background-color: #155a8c;
}
.user-menu {
position: relative;
display: flex;
align-items: center;
margin-right: 20px;
}
.user-menu span {
margin-right: 10px;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropbtn {
background-color: rgba(28, 108, 178, 0.9);
color: white;
border: none;
cursor: pointer;
font-size: 16px;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
right: 0; /* 确保下拉菜单靠右对齐 */
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown-content a:hover {
background-color: #f1f1f1;
}
.dropdown:hover .dropdown-content {
display: block;
}
main {
flex: 1;
width: 80%;
margin: 20px auto;
padding-top: 80px; /* 给主内容增加顶部填充,以避免被固定导航栏遮挡 */
}
h2 {
text-align: center;
color: #1c6cb2;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
table, th, td {
border: 1px solid #ccc;
}
th, td {
padding: 10px;
text-align: center;
}
th {
background-color: #f2f2f2;
}
.no-results {
text-align: center;
color: red;
font-size: 18px;
margin-top: 20px;
}
footer {
background-color: rgba(28, 108, 178, 0.9);
color: white;
text-align: center;
padding: 10px 0;
width: 100%;
position: relative;
margin-top: auto; /* 将footer推到页面底部 */
}
.content {
background-color: rgba(255, 255, 255, 0.8);
padding: 20px;
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 */
margin-bottom: 15px;
}
.form-row label {
flex: 0 0 120px; /* Fixed width for labels */
margin-right: 10px;
text-align: right;
line-height: 32px;
}
.form-row input,
.form-row select {
flex: 1;
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;
color: white;
border: none;
border-radius: 5px;
text-decoration: none;
display: inline-block;
cursor: pointer;
}
.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;
}

View File

@ -0,0 +1,93 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #ffffff;
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
}
header {
background-color: rgba(28, 108, 178, 0.9);
color: white;
padding: 20px 0;
text-align: center;
width: 100%;
}
main {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
position: relative;
}
.content {
background-color: rgba(255, 255, 255, 0.8);
padding: 20px;
border-radius: 10px;
text-align: center;
position: absolute;
}
h2 {
color: #1c6cb2;
}
.login-form {
margin-bottom: 20px;
}
.login-form input {
display: block;
margin: 10px auto;
padding: 10px;
font-size: 16px;
width: 80%;
max-width: 300px;
margin-bottom: 20px; /* 增加外边距 */
}
.buttons {
display: flex;
justify-content: center;
gap: 10px;
}
.login-form button,
.btn {
padding: 10px 20px;
background-color: #1c6cb2;
color: white;
border: none;
border-radius: 5px;
text-decoration: none;
display: inline-block;
line-height: 20px;
cursor: pointer;
}
.login-form button:hover,
.btn:hover {
background-color: #155a8c;
}
footer {
background-color: rgba(28, 108, 178, 0.9);
color: white;
text-align: center;
padding: 10px 0;
width: 100%;
}
.error-message {
color: red;
font-size: 12px;
text-align: left;
margin-top: -10px;
margin-bottom: 10px;
}

View File

@ -0,0 +1,42 @@
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);
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}`;
}
});

View File

@ -0,0 +1,80 @@
window.onload = function() {
autoLogin();
};
var checkInfo = {};
checkInfo.checkUsername = function() {
let username = document.getElementById('username').value;
if (username.length < 1) {
document.getElementById('usernameError').textContent = '用户名不能为空';
return false;
}
document.getElementById('usernameError').textContent = '';
return true;
}
checkInfo.checkPassword = function() {
let password = document.getElementById('password').value;
let regexPassword = /^[A-Za-z0-9\W_]{6,20}$/;
if (!regexPassword.test(password)) {
document.getElementById('loginError').textContent = "密码须为长度为6-20位字母、数字或符号";
return false;
}
document.getElementById('loginError').textContent = '';
return true;
}
function submitForm() {
if (checkInfo.checkUsername() && checkInfo.checkPassword()) {
document.getElementById('encryptedPassword').value = md5(
document.getElementById('password').value
);
login();
return true;
}
return false;
}
// 登录函数
async function login() {
const username = document.getElementById('username').value;
const encryptedPassword = document.getElementById('encryptedPassword').value;
try {
const response = await fetch('/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ username: username, password: encryptedPassword }),
credentials: 'include' // 确保请求包含凭据cookies
});
const data = await response.json();
if (response.ok) {
alert('登录成功');
// 自动跳转到主页
window.location.href = data.redirect;
} else {
document.getElementById('loginError').textContent = data.message;
}
} catch (error) {
alert('数据库错误,请稍后再试');
}
}
// 自动登录函数
async function autoLogin() {
const token = localStorage.getItem('token');
if (token) {
const response = await fetch('/index', {
headers: {
'Authorization': 'Bearer ' + token
}
});
if (response.ok) {
document.getElementById('content').innerText = '已自动登录';
} else {
document.getElementById('content').innerText = '自动登录失败';
}
}
}

View File

@ -14,7 +14,7 @@
<div class="logo">KJF航班订票</div> <div class="logo">KJF航班订票</div>
<div class="nav-buttons"> <div class="nav-buttons">
<a href="{{ url_for('index') }}">首页</a> <a href="{{ url_for('index') }}">首页</a>
<a href="{{ url_for('orders') }}">我的订单</a> <a href="{{ url_for('order_list') }}">我的订单</a>
</div> </div>
<div class="user-menu"> <div class="user-menu">
<span>{{ username }}</span> <span>{{ username }}</span>
@ -46,23 +46,24 @@
<div class="form-row"> <div class="form-row">
<label for="departure">出发地:</label> <label for="departure">出发地:</label>
<select id="departure" name="departure"> <select id="departure" name="departure">
<option value="北京">北京</option> {% for city in cities %}
<option value="上海">上海</option> <option value="{{ city }}" {% if city == "北京" %}selected{% endif %}>{{ city }}</option>
<option value="广州">广州</option> {% endfor %}
</select> </select>
</div> </div>
<div class="form-row"> <div class="form-row">
<label for="destination">目的地:</label> <label for="destination">目的地:</label>
<select id="destination" name="destination"> <select id="destination" name="destination">
<option value="北京">北京</option> {% for city in cities %}
<option value="上海">上海</option> <option value="{{ city }}" {% if city == "上海" %}selected{% endif %}>{{ city }}</option>
<option value="广州">广州</option> {% endfor %}
</select> </select>
<div id="destination-warning" class="error-message"></div> <div id="destination-warning" class="error-message"></div>
</div> </div>
<div class="form-row"> <div class="form-row">
<label for="departure-date">出发日期:</label> <label for="departure-date">出发日期:</label>
<input type="date" id="departure-date" name="departure-date"> <input type="date" id="departure-date" name="departure-date" required>
<div id="date-warning" class="error-message"></div>
</div> </div>
<div class="form-row"> <div class="form-row">
<label for="passengers">乘客人数:</label> <label for="passengers">乘客人数:</label>
@ -72,7 +73,7 @@
<button type="button" onclick="increment()">+</button> <button type="button" onclick="increment()">+</button>
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row form-row-center">
<button type="submit" class="btn">立即查询</button> <button type="submit" class="btn">立即查询</button>
</div> </div>
</form> </form>
@ -88,27 +89,28 @@
var departure = document.getElementById('departure').value; var departure = document.getElementById('departure').value;
var destination = document.getElementById('destination').value; var destination = document.getElementById('destination').value;
var warning = document.getElementById('destination-warning'); 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) { if (departure === destination) {
warning.textContent = '出发地和目的地不能相同'; warning.textContent = '出发地和目的地不能相同';
return false; return false;
} else { } else {
warning.textContent = ''; warning.textContent = '';
} }
return true;
}
function openTab(evt, tabName) { if (selectedDate < today) {
var i, tabcontent, tablinks; dateWarning.textContent = '出发日期不能早于今天';
tabcontent = document.getElementsByClassName("tabcontent"); return false;
for (i = 0; i < tabcontent.length; i++) { } else {
tabcontent[i].style.display = "none"; dateWarning.textContent = '';
} }
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) { return true;
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
document.getElementById(tabName).style.display = "block";
evt.currentTarget.className += " active";
} }
function increment() { function increment() {
@ -126,6 +128,19 @@
passengers.value = 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> </script>
</body> </body>
</html> </html>

View File

@ -0,0 +1,34 @@
<!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/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="content">
<h2>管理员登录</h2>
<div class="login-form">
<input type="text" id="username" placeholder="用户名">
<div id="usernameError" 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>
</div>
</div>
</div>
</main>
<footer>
<p>&copy; 2024 KJF航班订票. 保留所有权利。</p>
</footer>
</body>
</html>

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,92 @@
from flask import render_template, request, redirect, url_for, g, flash, session
from .config import db
import pymysql
from datetime import datetime
def book():
flight_id = request.args.get('flight_id')
if request.method == 'GET':
if not g.user:
return redirect(url_for("login"))
conn = pymysql.connect(**db)
cursor = conn.cursor(pymysql.cursors.DictCursor)
flight_sql = """
SELECT f.*, d.Name as Departure_airport_name, a.Name as Arrival_airport_name
FROM Flights f
JOIN Airports d ON f.Departure_airport = d.ID
JOIN Airports a ON f.Arrival_airport = a.ID
WHERE f.ID = %s;
"""
cursor.execute(flight_sql, (flight_id,))
flight = cursor.fetchone()
cursor.close()
conn.close()
return render_template('book.html', flight=flight, username=g.name)
if request.method == 'POST':
passengers = []
passenger_keys = ['card_code', 'name', 'phone_number', 'seat_class']
for i in range(len(request.form) // len(passenger_keys)):
passenger = {}
for key in passenger_keys:
passenger[key] = request.form.get(f'passengers[{i}][{key}]')
passengers.append(passenger)
conn = pymysql.connect(**db)
cursor = conn.cursor()
try:
# 插入订单记录
insert_order_sql = """
INSERT INTO Orders (Order_time, Paid, User_phone_number)
VALUES (%s, 0, %s)
"""
cursor.execute(insert_order_sql, (datetime.now(), g.user))
order_id = cursor.lastrowid
for passenger in passengers:
passenger_id = passenger['card_code']
name = passenger['name']
phone_number = passenger['phone_number']
seat_class = passenger['seat_class']
price_field = f"{seat_class.replace(' ', '_').lower()}_price"
price_sql = f"SELECT {price_field} FROM Flights WHERE ID = %s"
cursor.execute(price_sql, (flight_id,))
price = cursor.fetchone()[0]
insert_passenger_sql = """
INSERT INTO Passengers (ID, Name, Phone_number)
VALUES (%s, %s, %s)
ON DUPLICATE KEY UPDATE Name=VALUES(Name), Phone_number=VALUES(Phone_number);
"""
cursor.execute(insert_passenger_sql, (passenger_id, name, phone_number))
update_seat_sql = f"""
UPDATE Flights
SET {seat_class.replace(' ', '_').lower()}_seats_remaining = {seat_class.replace(' ', '_').lower()}_seats_remaining - 1
WHERE ID = %s
"""
cursor.execute(update_seat_sql, (flight_id,))
insert_ticket_sql = """
INSERT INTO Tickets (Price, FlightID, Seat_class, PassengerID, OrderID)
VALUES (%s, %s, %s, %s, %s)
"""
cursor.execute(insert_ticket_sql, (price, flight_id, seat_class, passenger_id, order_id))
conn.commit()
return redirect(url_for('order', order_id=order_id))
except Exception as e:
conn.rollback()
print(e)
flash("订票失败", "error")
return redirect(url_for('search'))
finally:
cursor.close()
conn.close()

View File

@ -0,0 +1,51 @@
from flask import request, redirect, url_for, g
from .config import db
import pymysql
def cancel_order():
order_id = request.args.get('order_id')
if not g.user:
return redirect(url_for("login"))
conn = pymysql.connect(**db)
cursor = conn.cursor(pymysql.cursors.DictCursor)
# 检查订单是否存在
check_order_sql = "SELECT ID FROM Orders WHERE ID = %s"
cursor.execute(check_order_sql, (order_id,))
order_exists = cursor.fetchone()
if not order_exists:
cursor.close()
conn.close()
return redirect(url_for("order_list"))
# 查询订单中所有机票的航班ID和座位级别
tickets_sql = "SELECT FlightID, Seat_class FROM Tickets WHERE OrderID = %s"
cursor.execute(tickets_sql, (order_id,))
tickets = cursor.fetchall()
# 恢复航班的对应余座数
for ticket in tickets:
flight_id = ticket['FlightID']
seat_class = ticket['Seat_class']
seat_column = seat_class.replace(' ', '_').lower() + "_seats_remaining"
update_seat_sql = f"""
UPDATE Flights
SET {seat_column} = {seat_column} + 1
WHERE ID = %s
"""
cursor.execute(update_seat_sql, (flight_id,))
# 删除对应的机票
delete_tickets_sql = "DELETE FROM Tickets WHERE OrderID = %s"
cursor.execute(delete_tickets_sql, (order_id,))
# 删除订单
delete_order_sql = "DELETE FROM Orders WHERE ID = %s"
cursor.execute(delete_order_sql, (order_id,))
conn.commit()
cursor.close()
conn.close()
return redirect(url_for('order_list'))

View File

@ -1,13 +1,16 @@
from flask import render_template, request, g, redirect, url_for, session from flask import render_template, request, g, redirect, url_for, session
from .config import slideshow_images from .config import slideshow_images
from .utils import get_cities
def index(): def index():
if request.method == 'GET': if request.method == 'GET':
if not g.user: if not g.user:
return redirect(url_for("login")) return redirect(url_for("login"))
username = g.name
images = slideshow_images images = slideshow_images
return render_template('index.html', images=images, username=username) return render_template(
'index.html', cities=get_cities(),
images=images, username=g.name
)
def logout(): def logout():
session.clear() session.clear()

View File

@ -1,12 +1,8 @@
from flask import render_template, request, flash, redirect, url_for, session from flask import render_template, request, flash, redirect, url_for, session, g
from typing import Dict from typing import Dict
from pymysql.cursors import Cursor from pymysql.cursors import Cursor
from .get_db import get_db import pymysql
from .config import db
def get_current_user(cursor: Cursor, phone_number: str):
sql = "SELECT Username FROM Users WHERE Phone_number = %s"
cursor.execute(sql, (phone_number,))
return cursor.fetchone()
def verify_user(cursor: Cursor, phone_number: str, password: str) -> str: def verify_user(cursor: Cursor, phone_number: str, password: str) -> str:
sql = """ sql = """
@ -23,7 +19,6 @@ def verify_user(cursor: Cursor, phone_number: str, password: str) -> str:
class ModifyInfo: class ModifyInfo:
def __init__(self, form: Dict[str, str], user_phone: str): def __init__(self, form: Dict[str, str], user_phone: str):
self.phone_number = user_phone self.phone_number = user_phone
print(form)
modifyType = form['modifyType'] modifyType = form['modifyType']
self.new_password = form.get('encryptedNewPassword', None) self.new_password = form.get('encryptedNewPassword', None)
self.new_phone_number = form.get('mobileNo', None) self.new_phone_number = form.get('mobileNo', None)
@ -74,20 +69,17 @@ class ModifyInfo:
def modify(): def modify():
if request.method == 'GET': if request.method == 'GET':
if not g.user:
return redirect(url_for("login"))
user_phone = session.get('user_id') user_phone = session.get('user_id')
db = get_db() return render_template('modify.html', current_user_phone=user_phone, current_username=g.name)
cursor = db.cursor()
current_user = get_current_user(cursor, user_phone)
if not current_user:
session.clear()
return redirect(url_for('login'))
return render_template('modify.html', current_user_phone=user_phone, current_username=current_user[0])
if request.method == 'POST': if request.method == 'POST':
user_phone = session.get('user_id') user_phone = session.get('user_id')
password = request.form['encryptedPassword'] password = request.form['encryptedPassword']
db = get_db() conn = pymysql.connect(**db)
cursor = db.cursor() cursor = conn.cursor(pymysql.cursors.DictCursor)
verify_info = verify_user(cursor, user_phone, password) verify_info = verify_user(cursor, user_phone, password)
if verify_info == "NO_USER": if verify_info == "NO_USER":
@ -95,7 +87,7 @@ def modify():
return redirect(url_for('login')) return redirect(url_for('login'))
elif verify_info == "WRONG_PASSWORD": elif verify_info == "WRONG_PASSWORD":
flash("密码错误") flash("密码错误")
db.close() conn.close()
return redirect(url_for('modify')) return redirect(url_for('modify'))
modifyInfo = ModifyInfo(request.form, user_phone) modifyInfo = ModifyInfo(request.form, user_phone)
@ -105,14 +97,14 @@ def modify():
cursor.execute(check_sql, (modifyInfo.new_phone_number,)) cursor.execute(check_sql, (modifyInfo.new_phone_number,))
if cursor.fetchone()[0] > 0: if cursor.fetchone()[0] > 0:
flash("手机号已存在,请使用其他手机号") flash("手机号已存在,请使用其他手机号")
db.close() conn.close()
return redirect(url_for('modify')) return redirect(url_for('modify'))
try: try:
cursor.execute(modifyInfo.get_sql(), modifyInfo.get_args()) cursor.execute(modifyInfo.get_sql(), modifyInfo.get_args())
db.commit() conn.commit()
flash(modifyInfo.get_ok_message()) flash(modifyInfo.get_ok_message())
db.close() conn.close()
if modifyInfo.command in ['modify Phone_Number', 'modify Password', 'delete account']: if modifyInfo.command in ['modify Phone_Number', 'modify Password', 'delete account']:
session.clear() session.clear()
session.pop("user_id", None) session.pop("user_id", None)
@ -120,8 +112,8 @@ def modify():
elif modifyInfo.command == 'modify Username': elif modifyInfo.command == 'modify Username':
return redirect(url_for('modify')) return redirect(url_for('modify'))
except Exception as e: except Exception as e:
db.rollback() conn.rollback()
print(e) print(e)
flash(modifyInfo.get_fail_message()) flash(modifyInfo.get_fail_message())
db.close() conn.close()
return redirect(url_for('modify')) return redirect(url_for('modify'))

View File

@ -0,0 +1,47 @@
from flask import render_template, request, redirect, url_for, g
from .config import db
import pymysql
def order():
order_id = request.args.get('order_id')
if not g.user:
return redirect(url_for("login"))
conn = pymysql.connect(**db)
cursor = conn.cursor(pymysql.cursors.DictCursor)
# 查询订单信息和航班信息
order_sql = """
SELECT o.*, f.*, d.Name as Departure_airport_name, a.Name as Arrival_airport_name
FROM Orders o
JOIN Tickets t ON o.ID = t.OrderID
JOIN Flights f ON t.FlightID = f.ID
JOIN Airports d ON f.Departure_airport = d.ID
JOIN Airports a ON f.Arrival_airport = a.ID
WHERE o.ID = %s
"""
cursor.execute(order_sql, (order_id,))
order_info = cursor.fetchone()
# 如果订单信息不存在,返回订单列表页面
if not order_info:
cursor.close()
conn.close()
return redirect(url_for("order_list"))
# 查询乘客信息和票据信息
tickets_sql = """
SELECT t.*, p.Name, p.Phone_number
FROM Tickets t
JOIN Passengers p ON t.PassengerID = p.ID
WHERE t.OrderID = %s
"""
cursor.execute(tickets_sql, (order_id,))
tickets = cursor.fetchall()
cursor.close()
conn.close()
total_price = sum(ticket['Price'] for ticket in tickets)
return render_template('order.html', order=order_info, tickets=tickets, total_price=total_price, username=g.name)

View File

@ -0,0 +1,54 @@
from flask import render_template, request, redirect, url_for, g
from .config import db
import pymysql
def order_list():
if not g.user:
return redirect(url_for("login"))
conn = pymysql.connect(**db)
cursor = conn.cursor(pymysql.cursors.DictCursor)
# 查询用户关联的所有订单信息
orders_sql = """
SELECT o.ID as OrderID, o.Order_time, o.Paid, f.ID as FlightID, f.Airline,
d.Name as Departure_airport_name, a.Name as Arrival_airport_name,
f.Departure_time, f.Status, p.Name as PassengerName, t.Price
FROM Orders o
JOIN Tickets t ON o.ID = t.OrderID
JOIN Flights f ON t.FlightID = f.ID
JOIN Airports d ON f.Departure_airport = d.ID
JOIN Airports a ON f.Arrival_airport = a.ID
JOIN Passengers p ON t.PassengerID = p.ID
WHERE o.User_phone_number = %s
"""
cursor.execute(orders_sql, (g.user,))
orders = cursor.fetchall()
cursor.close()
conn.close()
# 整理订单信息
order_dict = {}
for order in orders:
order_id = order['OrderID']
if order_id not in order_dict:
order_dict[order_id] = {
'OrderID': order_id,
'Order_time': order['Order_time'],
'Paid': order['Paid'],
'FlightID': order['FlightID'],
'Airline': order['Airline'],
'Departure_airport_name': order['Departure_airport_name'],
'Arrival_airport_name': order['Arrival_airport_name'],
'Departure_time': order['Departure_time'],
'Status': order['Status'],
'Passengers': [],
'TotalPrice': 0
}
order_dict[order_id]['Passengers'].append(order['PassengerName'])
order_dict[order_id]['TotalPrice'] += order['Price']
order_list = list(order_dict.values())
return render_template('order_list.html', orders=order_list, username=g.name)

View File

@ -0,0 +1,30 @@
from flask import redirect, url_for, g, request
from .config import db
import pymysql
def pay_confirm():
order_id = request.args.get('order_id')
if not g.user:
return redirect(url_for("login"))
conn = pymysql.connect(**db)
cursor = conn.cursor()
# 检查订单是否存在
check_order_sql = "SELECT ID FROM Orders WHERE ID = %s"
cursor.execute(check_order_sql, (order_id,))
order_exists = cursor.fetchone()
if not order_exists:
cursor.close()
conn.close()
return redirect(url_for("order_list"))
update_order_sql = "UPDATE Orders SET Paid = 1 WHERE ID = %s"
cursor.execute(update_order_sql, (order_id,))
conn.commit()
cursor.close()
conn.close()
return redirect(url_for('order_list', order_id=order_id))

View File

@ -0,0 +1,49 @@
from flask import render_template, request, g, abort, redirect, url_for
from .config import db
from .utils import get_cities
import pymysql
import datetime
def search():
if not g.user:
return redirect(url_for("login"))
departure_city = request.args.get('departure')
destination_city = request.args.get('destination')
departure_date = request.args.get('departure-date')
passengers = int(request.args.get('passengers', 1))
# Date validation
try:
departure_date_obj = datetime.datetime.strptime(departure_date, '%Y-%m-%d').date()
if departure_date_obj < datetime.date.today():
abort(400, description="Departure date cannot be in the past.")
except ValueError:
abort(400, description="Invalid date format.")
conn = pymysql.connect(**db)
cursor = conn.cursor(pymysql.cursors.DictCursor)
search_sql = """
SELECT f.*, d.Name as Departure_airport_name, a.Name as Arrival_airport_name
FROM Flights f
JOIN Airports d ON f.Departure_airport = d.ID
JOIN Airports a ON f.Arrival_airport = a.ID
WHERE d.City = %s AND a.City = %s
AND DATE(f.Departure_time) = %s
AND (f.First_class_seats_remaining + f.Business_class_seats_remaining + f.Economy_class_seats_remaining) >= %s
AND f.Status NOT IN ('已起飞', '已降落');
"""
cursor.execute(search_sql, (departure_city, destination_city, departure_date, passengers))
flights = cursor.fetchall()
cursor.close()
conn.close()
return render_template(
'search.html',
cities=get_cities(),
flights=flights,
username=g.name
)

View File

@ -1,6 +1,7 @@
from flask import render_template, request, redirect, url_for from flask import render_template, request, redirect, url_for
from .get_db import get_db from .config import db
import re import re
import pymysql
def signup(): def signup():
error_messages = { error_messages = {
@ -34,8 +35,8 @@ def signup():
if any(error_messages.values()): if any(error_messages.values()):
return render_template('signup.html', errors=error_messages) return render_template('signup.html', errors=error_messages)
db = get_db() conn = pymysql.connect(**db)
cursor = db.cursor() cursor = conn.cursor(pymysql.cursors.DictCursor)
# 检查已有用户 # 检查已有用户
sql = """ sql = """
@ -44,7 +45,7 @@ def signup():
""" """
try: try:
cursor.execute(sql, (phone_number,)) cursor.execute(sql, (phone_number,))
phone_exist = cursor.fetchall()[0][0] phone_exist = cursor.fetchall()[0]['COUNT(*)']
except Exception as e: except Exception as e:
error_messages['mobileNo'] = "数据库异常,查询失败" error_messages['mobileNo'] = "数据库异常,查询失败"
print(e) print(e)
@ -52,7 +53,7 @@ def signup():
if phone_exist != 0: if phone_exist != 0:
error_messages['mobileNo'] = "该手机号已注册,请勿重复注册" error_messages['mobileNo'] = "该手机号已注册,请勿重复注册"
db.close() conn.close()
return render_template('signup.html', errors=error_messages) return render_template('signup.html', errors=error_messages)
# 插入 # 插入
@ -62,12 +63,12 @@ def signup():
''' '''
try: try:
cursor.execute(sql, (phone_number, username, password)) cursor.execute(sql, (phone_number, username, password))
db.commit() conn.commit()
return redirect(url_for('index')) return redirect(url_for('index'))
except Exception as e: except Exception as e:
db.rollback() conn.rollback()
print(e) print(e)
error_messages['mobileNo'] = "数据库异常,注册失败" error_messages['mobileNo'] = "数据库异常,注册失败"
return render_template('signup.html', errors=error_messages) return render_template('signup.html', errors=error_messages)
finally: finally:
db.close() conn.close()

View File

@ -0,0 +1,20 @@
from .config import db
import pymysql
from xpinyin import Pinyin
from pymysql.cursors import Cursor
def get_cities():
conn = pymysql.connect(**db)
cursor = conn.cursor(pymysql.cursors.DictCursor)
cursor.execute("SELECT DISTINCT City FROM Airports")
cities = [row['City'] for row in cursor.fetchall()]
cursor.close()
conn.close()
p = Pinyin()
cities = [
(row, p.get_pinyin(row).replace("-", ""))
for row in cities
]
cities = sorted(cities, key=lambda x: x[1])
cities = [row[0] for row in cities]
return cities

View File

@ -1,13 +1,19 @@
from flask import Flask, redirect, url_for, session, render_template, request, g from flask import Flask, redirect, url_for, session, g
from flask_httpauth import HTTPTokenAuth from flask_httpauth import HTTPTokenAuth
from flask_cors import CORS from flask_cors import CORS
from func.config import db, SECRET_KEY, slideshow_images from func.config import db, SECRET_KEY
import pymysql import pymysql
import func.login import func.login
import func.signup import func.signup
import func.modify import func.modify
import func.index import func.index
import func.search
import func.book
import func.pay_confirm
import func.cancel_order
import func.order
import func.order_list
app = Flask(__name__) app = Flask(__name__)
app.config["SECRET_KEY"] = SECRET_KEY app.config["SECRET_KEY"] = SECRET_KEY
@ -26,14 +32,14 @@ def before_request():
conn = pymysql.connect(**db) conn = pymysql.connect(**db)
cursor = conn.cursor(pymysql.cursors.DictCursor) cursor = conn.cursor(pymysql.cursors.DictCursor)
args = (session.get('user_id'),) args = (session.get('user_id'),)
verify_sql = "SELECT Phone_number, Username FROM Users WHERE Phone_number = %s;" verify_sql = "SELECT Username FROM Users WHERE Phone_number = %s;"
cursor.execute(verify_sql, args) cursor.execute(verify_sql, args)
res = cursor.fetchone() res = cursor.fetchone()
if not res: if not res:
g.user = None g.user = None
g.name = None g.name = None
else: else:
g.user = res['Phone_number'] g.user = session.get('user_id')
g.name = res['Username'] g.name = res['Username']
@app.route("/") @app.route("/")
@ -58,23 +64,35 @@ def signup():
@app.route("/modify", methods=['GET', 'POST']) @app.route("/modify", methods=['GET', 'POST'])
def modify(): def modify():
if request.method == 'GET':
if not g.user:
return redirect(url_for("login"))
return func.modify.modify() return func.modify.modify()
@app.route("/search", methods=['GET']) @app.route("/search", methods=['GET'])
def search(): def search():
# 处理搜索逻辑 return func.search.search()
return "搜索结果"
@app.route("/orders", methods=['GET', 'POST']) @app.route("/book", methods=['GET', 'POST'])
def orders(): def book():
return "我的订单" return func.book.book()
@app.route("/order", methods=['GET'])
def order():
return func.order.order()
@app.route('/cancel_order', methods=['POST'])
def cancel_order():
return func.cancel_order.cancel_order()
@app.route('/pay_confirm', methods=['POST'])
def pay_confirm():
return func.pay_confirm.pay_confirm()
@app.route("/order_list", methods=['GET', 'POST'])
def order_list():
return func.order_list.order_list()
if __name__ == "__main__": if __name__ == "__main__":
app.run( app.run(
host="0.0.0.0", host="0.0.0.0",
port=5000, port=8888,
debug=True debug=True
) )

View File

@ -0,0 +1,238 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
min-height: 100vh;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
background-color: rgba(28, 108, 178, 0.9);
color: white;
padding: 20px;
width: 100%;
position: fixed;
top: 0;
z-index: 1000;
}
.header-content {
display: flex;
align-items: center;
width: 100%;
justify-content: space-between;
}
.logo {
font-size: 24px;
font-weight: bold;
margin-left: 20px;
}
.nav-buttons {
display: flex;
gap: 20px;
}
.nav-buttons a {
color: white;
text-decoration: none;
font-size: 16px;
padding: 10px;
border-radius: 5px;
}
.nav-buttons a:hover {
background-color: #155a8c;
}
.user-menu {
position: relative;
display: flex;
align-items: center;
margin-right: 20px;
}
.user-menu span {
margin-right: 10px;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropbtn {
background-color: rgba(28, 108, 178, 0.9);
color: white;
border: none;
cursor: pointer;
font-size: 16px;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
right: 0; /* 确保下拉菜单靠右对齐 */
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown-content a:hover {
background-color: #f1f1f1;
}
.dropdown:hover .dropdown-content {
display: block;
}
main {
flex: 1;
width: 80%;
margin: 20px auto;
padding-top: 80px; /* 给主内容增加顶部填充,以避免被固定导航栏遮挡 */
}
h2 {
text-align: center;
color: #1c6cb2;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
table, th, td {
border: 1px solid #ccc;
}
th, td {
padding: 10px;
text-align: center;
}
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;
}
form {
background-color: rgba(255, 255, 255, 0.8);
padding: 20px;
border-radius: 10px;
margin-bottom: 20px;
}
.passenger {
margin-bottom: 20px;
transition: transform 0.3s ease, box-shadow 0.3s ease, border-radius 0.3s ease;
}
.passenger:hover {
transform: scale(1.02);
box-shadow: 0 0 10px rgba(28, 108, 178, 0.5);
border-radius: 10px;
}
.passenger h3 {
margin-top: 0;
}
.delete-btn {
background-color: #ff4d4d;
color: white;
border: none;
cursor: pointer;
padding: 5px 10px;
border-radius: 5px;
float: left;
}
.form-row {
display: flex;
justify-content: space-between;
margin-bottom: 15px;
}
label {
flex: 1;
margin-right: 10px;
text-align: right;
line-height: 32px;
}
input, select {
flex: 2;
padding: 8px;
font-size: 16px;
border: 1px solid #ccc;
border-radius: 5px;
}
.error-message {
color: red;
font-size: 12px;
margin-top: 5px;
}
.total-price {
font-size: 18px;
font-weight: bold;
margin-top: 20px;
margin-bottom: 20px;
}
.btn {
padding: 10px 20px;
background-color: #1c6cb2;
color: white;
border: none;
border-radius: 5px;
text-decoration: none;
display: inline-block;
cursor: pointer;
margin-top: 10px;
}
.btn:hover {
background-color: #155a8c;
}
footer {
background-color: rgba(28, 108, 178, 0.9);
color: white;
text-align: center;
padding: 10px 0;
width: 100%;
position: relative;
margin-top: auto; /* 将footer推到页面底部 */
}

View File

@ -2,12 +2,9 @@ body {
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
margin: 0; margin: 0;
padding: 0; padding: 0;
background-color: #ffffff;
height: 100vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; min-height: 100vh;
overflow-x: hidden; /* 防止出现水平滚动条 */
} }
header { header {
@ -18,6 +15,9 @@ header {
color: white; color: white;
padding: 20px; padding: 20px;
width: 100%; width: 100%;
position: fixed;
top: 0;
z-index: 1000;
} }
.header-content { .header-content {
@ -99,10 +99,17 @@ header {
display: block; display: block;
} }
main {
flex: 1;
width: 100%;
margin: 20px auto;
padding-top: 80px; /* 给主内容增加顶部填充,以避免被固定导航栏遮挡 */
}
.slides { .slides {
position: relative; position: relative;
width: 100%; width: 100%;
height: 400px; height: 620px;
overflow: hidden; overflow: hidden;
} }
@ -134,7 +141,7 @@ header {
text-align: center; text-align: center;
width: 80%; width: 80%;
max-width: 800px; max-width: 800px;
margin: -50px auto 20px; margin: -170px auto 20px;
position: relative; position: relative;
} }
@ -145,12 +152,12 @@ header {
.form-row { .form-row {
display: flex; display: flex;
justify-content: space-between; justify-content: flex-start; /* Left-align the form items */
margin-bottom: 15px; margin-bottom: 15px;
} }
.form-row label { .form-row label {
flex: 1; flex: 0 0 120px; /* Fixed width for labels */
margin-right: 10px; margin-right: 10px;
text-align: right; text-align: right;
line-height: 32px; line-height: 32px;
@ -158,13 +165,17 @@ header {
.form-row input, .form-row input,
.form-row select { .form-row select {
flex: 2; flex: 1;
padding: 8px; padding: 8px;
font-size: 16px; font-size: 16px;
border: 1px solid #ccc; border: 1px solid #ccc;
border-radius: 5px; border-radius: 5px;
} }
.form-row.form-row-center {
justify-content: center; /* Center-align the button */
}
.passenger-input { .passenger-input {
display: flex; display: flex;
align-items: center; align-items: center;
@ -208,18 +219,19 @@ header {
background-color: #155a8c; background-color: #155a8c;
} }
.error-message {
color: red;
font-size: 12px;
margin-top: 5px;
text-align: left;
}
footer { footer {
background-color: rgba(28, 108, 178, 0.9); background-color: rgba(28, 108, 178, 0.9);
color: white; color: white;
text-align: center; text-align: center;
padding: 10px 0; padding: 10px 0;
width: 100%; width: 100%;
margin-top: auto; position: relative;
} margin-top: auto; /* 将footer推到页面底部 */
.error-message {
color: red;
font-size: 12px;
text-align: left;
margin-top: 5px;
} }

View File

@ -2,18 +2,22 @@ body {
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
margin: 0; margin: 0;
padding: 0; padding: 0;
background-color: #ffffff;
height: 100vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; min-height: 100vh;
} }
header { header {
display: flex;
justify-content: space-between;
align-items: center;
background-color: rgba(28, 108, 178, 0.9); background-color: rgba(28, 108, 178, 0.9);
color: white; color: white;
padding: 20px 0; padding: 20px;
width: 100%; width: 100%;
position: fixed;
top: 0;
z-index: 1000;
} }
.header-content { .header-content {
@ -50,11 +54,9 @@ header {
main { main {
flex: 1; flex: 1;
display: flex; width: 80%;
align-items: center; margin: 20px auto;
justify-content: center; padding-top: 80px; /* 给主内容增加顶部填充,以避免被固定导航栏遮挡 */
width: 100%;
position: relative;
} }
.content { .content {
@ -64,6 +66,7 @@ main {
text-align: center; text-align: center;
width: 400px; width: 400px;
position: relative; position: relative;
margin: auto;
} }
h2 { h2 {
@ -141,4 +144,6 @@ footer {
text-align: center; text-align: center;
padding: 10px 0; padding: 10px 0;
width: 100%; width: 100%;
position: relative;
margin-top: auto; /* 将footer推到页面底部 */
} }

View File

@ -0,0 +1,191 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
min-height: 100vh;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
background-color: rgba(28, 108, 178, 0.9);
color: white;
padding: 20px;
width: 100%;
position: fixed;
top: 0;
z-index: 1000;
}
.header-content {
display: flex;
align-items: center;
width: 100%;
justify-content: space-between;
}
.logo {
font-size: 24px;
font-weight: bold;
margin-left: 20px;
}
.nav-buttons {
display: flex;
gap: 20px;
}
.nav-buttons a {
color: white;
text-decoration: none;
font-size: 16px;
padding: 10px;
border-radius: 5px;
}
.nav-buttons a:hover {
background-color: #155a8c;
}
.user-menu {
position: relative;
display: flex;
align-items: center;
margin-right: 20px;
}
.user-menu span {
margin-right: 10px;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropbtn {
background-color: rgba(28, 108, 178, 0.9);
color: white;
border: none;
cursor: pointer;
font-size: 16px;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
right: 0;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown-content a:hover {
background-color: #f1f1f1;
}
.dropdown:hover .dropdown-content {
display: block;
}
main {
flex: 1;
width: 80%;
margin: 20px auto;
padding-top: 80px; /* 给主内容增加顶部填充,以避免被固定导航栏遮挡 */
}
h2 {
text-align: center;
color: #1c6cb2;
}
.order-info, .passenger-info, .order-summary {
background-color: rgba(255, 255, 255, 0.8);
padding: 20px;
border-radius: 10px;
margin-bottom: 20px;
}
.order-info p, .order-summary p {
margin: 5px 0;
}
table {
width: 100%;
border-collapse: collapse;
}
table, th, td {
border: 1px solid #ccc;
}
th, td {
padding: 10px;
text-align: center;
}
th {
background-color: #f2f2f2;
}
.btn {
padding: 10px 20px;
background-color: #1c6cb2;
color: white;
border: none;
border-radius: 5px;
text-decoration: none;
display: inline-block;
cursor: pointer;
margin-top: 10px;
}
.btn:hover {
background-color: #155a8c;
}
.cancel-btn {
background-color: #ff4d4d;
}
.cancel-btn:hover {
background-color: #cc0000;
}
.back-btn {
background-color: #f2f2f2;
color: black;
border: none;
border-radius: 5px;
padding: 10px 20px;
cursor: pointer;
text-decoration: none;
display: inline-block;
margin: 10px 0;
}
.back-btn:hover {
background-color: #d9d9d9;
}
footer {
background-color: rgba(28, 108, 178, 0.9);
color: white;
text-align: center;
padding: 10px 0;
width: 100%;
position: relative;
margin-top: auto; /* 将footer推到页面底部 */
}

View File

@ -0,0 +1,151 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
min-height: 100vh;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
background-color: rgba(28, 108, 178, 0.9);
color: white;
padding: 20px;
width: 100%;
position: fixed;
top: 0;
z-index: 1000;
}
.header-content {
display: flex;
align-items: center;
width: 100%;
justify-content: space-between;
}
.logo {
font-size: 24px;
font-weight: bold;
margin-left: 20px;
}
.nav-buttons {
display: flex;
gap: 20px;
}
.nav-buttons a {
color: white;
text-decoration: none;
font-size: 16px;
padding: 10px;
border-radius: 5px;
}
.nav-buttons a:hover {
background-color: #155a8c;
}
.user-menu {
position: relative;
display: flex;
align-items: center;
margin-right: 20px;
}
.user-menu span {
margin-right: 10px;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropbtn {
background-color: rgba(28, 108, 178, 0.9);
color: white;
border: none;
cursor: pointer;
font-size: 16px;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
right: 0;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown-content a:hover {
background-color: #f1f1f1;
}
.dropdown:hover .dropdown-content {
display: block;
}
main {
flex: 1;
width: 80%;
margin: 20px auto;
padding-top: 80px; /* 给主内容增加顶部填充,以避免被固定导航栏遮挡 */
}
h2 {
text-align: center;
color: #1c6cb2;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
table, th, td {
border: 1px solid #ccc;
}
th, td {
padding: 10px;
text-align: center;
}
th {
background-color: #f2f2f2;
}
footer {
background-color: rgba(28, 108, 178, 0.9);
color: white;
text-align: center;
padding: 10px 0;
width: 100%;
position: relative;
margin-top: auto; /* 将footer推到页面底部 */
}
.order-row {
transition: transform 0.3s ease, box-shadow 0.3s ease, border-radius 0.3s ease;
}
.order-row:hover {
transform: scale(1.02);
box-shadow: 0 0 10px rgba(28, 108, 178, 0.5);
border-radius: 10px;
}

View File

@ -0,0 +1,251 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
min-height: 100vh;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
background-color: rgba(28, 108, 178, 0.9);
color: white;
padding: 20px;
width: 100%;
position: fixed;
top: 0;
z-index: 1000;
}
.header-content {
display: flex;
align-items: center;
width: 100%;
justify-content: space-between;
}
.logo {
font-size: 24px;
font-weight: bold;
margin-left: 20px;
}
.nav-buttons {
display: flex;
gap: 20px;
}
.nav-buttons a {
color: white;
text-decoration: none;
font-size: 16px;
padding: 10px;
border-radius: 5px;
}
.nav-buttons a:hover {
background-color: #155a8c;
}
.user-menu {
position: relative;
display: flex;
align-items: center;
margin-right: 20px;
}
.user-menu span {
margin-right: 10px;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropbtn {
background-color: rgba(28, 108, 178, 0.9);
color: white;
border: none;
cursor: pointer;
font-size: 16px;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
right: 0; /* 确保下拉菜单靠右对齐 */
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown-content a:hover {
background-color: #f1f1f1;
}
.dropdown:hover .dropdown-content {
display: block;
}
main {
flex: 1;
width: 80%;
margin: 20px auto;
padding-top: 80px; /* 给主内容增加顶部填充,以避免被固定导航栏遮挡 */
}
h2 {
text-align: center;
color: #1c6cb2;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
table, th, td {
border: 1px solid #ccc;
}
th, td {
padding: 10px;
text-align: center;
}
th {
background-color: #f2f2f2;
}
.no-results {
text-align: center;
color: red;
font-size: 18px;
margin-top: 20px;
}
footer {
background-color: rgba(28, 108, 178, 0.9);
color: white;
text-align: center;
padding: 10px 0;
width: 100%;
position: relative;
margin-top: auto; /* 将footer推到页面底部 */
}
.content {
background-color: rgba(255, 255, 255, 0.8);
padding: 20px;
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 */
margin-bottom: 15px;
}
.form-row label {
flex: 0 0 120px; /* Fixed width for labels */
margin-right: 10px;
text-align: right;
line-height: 32px;
}
.form-row input,
.form-row select {
flex: 1;
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;
color: white;
border: none;
border-radius: 5px;
text-decoration: none;
display: inline-block;
cursor: pointer;
}
.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;
}

View File

@ -0,0 +1,42 @@
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);
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}`;
}
});

View 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>&copy; 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>

View 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>&copy; 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>

View 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>&copy; 2024 KJF航班订票. 保留所有权利。</p>
</footer>
</body>
</html>

View 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>&copy; 2024 KJF航班订票. 保留所有权利。</p>
</footer>
</body>
</html>

View 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>&copy; 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>

View File

@ -1,7 +0,0 @@
import pymysql
def get_db():
return pymysql.connect(
host='localhost', user='kejingfan',
password='KJF2811879', database='TESTDB'
)

View File

@ -1,17 +0,0 @@
import pymysql
db = pymysql.connect(
host='localhost', user='kejingfan',
password='KJF2811879', database='TESTDB'
)
cursor = db.cursor()
with open('db.sql', 'r') as f:
sql_commands = f.read().split(';')
for command in sql_commands:
if command.strip(): # 确保不执行空命令
cursor.execute(command)
db.close()