模仿12306的全国火车票务管理系统

大二萌新时期做的数据库 Project。第一次用 Flask,第一次写前端。现在回头看满满是槽点啊……

大学生活过去一半,课程Project一点没少。上个月我和队友H一起攻坚克难,做出了一个像模像样的火车订票系统。这个系统拥有查票、中转、订票、余票查询、线路管理等等功能。乍一看是普普通通的数据库大作业。不过在奇怪的地方,颇有些亮点。

# ORM

其实像票务系统这种表关系复杂的数据库,我个人是不赞同过多使用ORM框架的。在查询复杂度高的时候,调试代码和调整架构就是一场灾难。但是我们总觉得把SQL写在某处,再加载进程序的方法很不优雅。所以用ORM把整个表操作写完了。其中还涉及一些CTE递归查询。这里我放一段代码感受一下。

def fuzzy_query(dep_place, arv_place, dg_only, session):
dep_train_info = session.query(Interval.train_id, Interval.dep_station) \
.join(Station, Interval.dep_station == Station.station_id) \
.filter(Station.station_name.like(dep_place),
Station.available == True,
Interval.available == True) \
.subquery()
arv_train_info = session.query(Interval.train_id, Interval.arv_station) \
.join(Station, Interval.arv_station == Station.station_id) \
.filter(Station.station_name.like(arv_place),
Station.available == True,
Interval.available == True) \
.subquery()
raw_train_info = session.query(Interval.train_id, Train.train_name,
func.min(Interval.interval_id).label('first_interval'),
func.max(Interval.interval_id).label('last_interval')) \
.join(Train, Train.train_id == Interval.train_id) \
.join(dep_train_info, Interval.train_id == dep_train_info.c.train_id) \
.join(arv_train_info, Interval.train_id == arv_train_info.c.train_id) \
.filter(or_(Interval.dep_station == dep_train_info.c.dep_station,
Interval.arv_station == arv_train_info.c.arv_station),
Train.available == True) \
.group_by(Interval.train_id, Train.train_name) \
.subquery()
dep_i = aliased(Interval, name='dep_i')
arv_i = aliased(Interval, name='arv_i')
dep_s = aliased(Station, name='dep_s')
arv_s = aliased(Station, name='arv_s')
train_info_list = session.query(raw_train_info.c.train_name,
raw_train_info.c.first_interval, raw_train_info.c.last_interval,
dep_s.station_name.label('dep_station'),
func.cast(dep_i.dep_datetime, String).label('dep_time'),
arv_s.station_name.label('arv_station'),
func.cast(arv_i.arv_datetime, String).label('arv_time')) \
.join(dep_i, dep_i.interval_id == raw_train_info.c.first_interval) \
.join(arv_i, arv_i.interval_id == raw_train_info.c.last_interval) \
.join(dep_s, dep_s.station_id == dep_i.dep_station) \
.join(arv_s, arv_s.station_id == arv_i.arv_station) \
.filter(dep_s.station_name.like(dep_place), arv_s.station_name.like(arv_place),
dep_s.available == True, arv_s.available == True,
dep_i.available == True, arv_i.available == True) \
.order_by(dep_i.dep_datetime) \
.all()
return list(filter(lambda x: x['train_name'][0] in 'DG' if dg_only else True,
map(lambda x: dict(zip(x.keys(), x)), train_info_list)))

# 前端

作为上大学之前只写过算法的弱鸡,我对前端是没有什么研究的。之前写课程表越权查询和WannaAC(TestJudege)的时候涉及过一点点,不过它们都是单页面应用,也就是一张表格、一个输入框的难度。这次我花了点时间在研究Vue框架上。

必须推荐很漂亮的ElementUI,和我的审美很搭。

我平常比较喜欢简单整洁的界面,这次用ElementUI实现的网页样式就是我心仪的设计风格。

对了,我还参照一位设计师的设计,在订票系统上放上「真的火车票」。比起显示一堆文字,这样感觉上非常直观。不过好不好看就仁者见仁了。

听大佬讲,前端好像是鄙视链靠底端的开发岗位…Anyway,这次尝试很有趣,值得写一篇博客记录一下。