1。系统概述
2。要求分析
2.1系统功能分析
2.2系统数据分析
2.3系统非功能分析
iii。系统设计
3.1应用程序设计
3.2数据库设计
3.2.1概念设计
3.2.2逻辑设计
iv。系统实现
4.1实施关键技术
4.2功能实现
V.系统测试
6。问题记录
1。系统概述
空气票销售系统分为两个角色,系统管理员和用户
系统管理员:诸如查询航班,添加航班,取消航班,查询订单信息等功能等功能等。
用户:询问航班,预订票,添加乘客信息,删除乘客信息,查看付费/退款订单,更改,退款,支票账单和其他功能
2。要求分析2.1系统功能分析
空气票销售系统分为两个角色,系统管理员和用户
系统管理员:
①您可以检查航班和空中票相关的信息,包括起始地点,时间,价格,折扣,剩余的票等。
可以添加范围
航班
④可以查询订单信息
用户:
①您可以检查航班。每次航班都有各种折扣的多种机票,不同的折扣与不同的价格和机舱空间相对应。
②您可以预订机票。预订机票时,您可以选择输入新的乘客信息或检查现有的乘客信息。
您可以在个人页面上添加乘客信息并删除乘客信息。
您可以在个人页面上查看付费/退款订单。
⑤可以更改或退还订单页面上的订单。
⑥可以查看账单
2.2系统数据分析
(i)登录系统时,需要一个用户帐户
需要一个表来保存用户信息
(2)查询航班时,该页面需要以指定的日期和指定的起点显示航班。目前,它需要显示航班的起始位置,日期,时间,最低价格和其他相关信息。飞行后单击“预订”按钮,然后以当前航班中包含的所有价格跳到空中票证界面。
需要一个表来保存与飞行相关的信息。包括开始和最终地点,日期,时间,原价等。
需要一张桌子来存储航班中包含的所有飞行票信息。包括折扣,总票,剩余的选票等。
联系人:每次航班对应于各种不同的折扣飞行票
(3)处理最短的公交问题时,有必要根据不同城市的位置选择过境城市,以实现最短的距离运输。在处理国际时差时,需要根据不同城市所在国家 /地区的时间差进行时差转换。
需要一张桌子来保存与城市相关的信息。
联系人:有关城市的开始和末端的信息在城市桌上。
(iv)预订机票时,会形成订单。订单包括票证ID,订单时间,订单金额,订单属性(直接或运输),付款状态(已付款或退款),订单所属用户的用户ID以及订单所属的乘客的ID号。
⑤需要一个表来保存与订单相关的信息。
联系人:机票可能属于多个订单,订单可能包含一个以上的机票(例如:运输订单)。
用户可能有多个订单。
乘客可以使用多个订单。
(v)在用户的个人中心,您可以查看已保存的乘客信息
需要一个表来保存与乘客相关的信息。
联系人:用户可以保存有关多个乘客的信息,并且乘客的信息也可以保存在多个用户的帐户中。
(vi)在取消航班时,将向用户发出取消飞行通知。
需要表格来保存通知的相关信息。
联系人:用户可能会收到多次通知。
(7)帐单中记录了每个用户的收入和支出。
⑧需要一个表来保存计费信息。
联系人:用户可能具有多个收入和支出记录。
2.3系统非功能分析
(i)系统性能:合理建立索引,加快数据查询。
(ii)安全性:前端使用JS进行数据验证,而非法输入和请求不能成功传输到
后端设置为提醒用户输入正确的法律输入。
(iii)可用性:前端采用一个简单清晰的接口,用户易于使用。
iii。系统设计3.1应用设计
①架构:采用B/S架构,使用SSM+VUE技术,并与前端和后端分开。
②前端:VUE显示接口,通过调用接口从后端获取数据。
③后端:数据库用作持久性层框架,后端Java使用该框架,并添加了一个框架以统一的方式处理请求和响应。同时将其用于项目管理。
④前端交流:
前端:通过发送请求并将数据接收到后端,
后端:(1)该图层接收前端数据并返回页面请求信息。
(2)该图层接受业务处理和逻辑判断的图层信息。用于处理业务逻辑,它将称为该层的API;
(3)该层用于与数据库进行交互。如果要访问数据库并操作,则只能通过层将SQL语句发送到数据库,通过接口将这些结果传递给图层,然后在数据库上执行数据持久性操作。
3.2数据库设计3.2.1概念设计
3.2.2逻辑设计
(航班号,出发城,起飞机场,出发日期,出发时间,终点城市,到达机场,到达日期,到达时间,飞行价格,存在,存在)
②航空票(票证号,航班号,折扣,票数总数,剩余的票数)
③订单(订单号,属性,总金额,付款状态,完成时间,用户ID,乘客ID号)
④订单空气票(订单号,票证号)
⑤用户(用户ID,用户名,用户密码)
⑥乘客(ID号,名称,电话号码)
⑦用户乘客(用户ID,乘客ID号)
⑧通知(通知号,用户ID,航班号,通知时间)
⑨bill(账单号,用户ID,收入和支出金额,事件描述,时间)
⑩城市(城市ID,城市名称,水平坐标,垂直坐标,地理位置,时间)
iv。系统实施4.1关键技术实施
框架:前端和后端分开,前端使用VUE框架,并且数据库用作持久层框架。
后端Java使用框架并添加架构来做出请求和响应
统一处理。同时将其用于项目管理。
MVC体系结构层次结构的主要功能是将其解次输入。使用层次结构的好处通常被
统一分层有利于系统维护和系统扩展。它是为了增强系统的维护和可扩展性
扩展您的角色。
(1)该图层接收前景数据并返回页面请求信息。
(2)该图层接受业务处理和逻辑判断的图层信息。用于处理业务逻辑,它将称为该层的API;
(3)该层用于与数据库进行交互。如果要访问数据库并操作,则只能通过层将SQL语句发送到数据库,通过接口将这些结果传递给图层,然后在数据库上执行数据持久性操作。
插件:由于使用项目管理,可以通过在pom.xml文件中配置一些插件,例如:插件
通过导入一些依赖项,您可以使用相应的工具。
例如:这是一个可以将Java对象转换为JSON网格的Java库
,当然也可以将JSON字符串转换为Java对象。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
导入的依赖项可直接用于生成类,方法和构造函数。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
导入,您可以测试
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
4.2功能实现
1。功能实施最短的传输
在查询某个航班时,前端将出发城市的城市名称和终点城市的城市名称传递到相应的后端界面,查询城市桌上所有城市的坐标位置,并获得城市之间的距离矩阵。
然后执行复杂性为0(n)的遍历,并找到k(dik+dkj)的最小值。与K相对应的城市是最短的过境城市。
当找到合适的过境飞行时,还必须考虑时间差,限制第二次飞行的出发时间减去第一次飞行在两个小时之间的到达时间。
源代码:
①前端将起步城市和终点城市的城市名称传递到相应的后端界面,后端首次对其进行处理,然后转发要处理的请求。
//获取转移城的名称
@RequestMapping ( value = "/transit" , method = RequestMethod.POST )
public String transit ( HttpServletRequest req ) throws IOException {
//获得对象
BufferedReader reader = new BufferedReader ( new InputStreamReader ( req.getInputStream ( ) ) ) ;
String s = reader.readLine ( ) ;
String str=s.substring ( 8 , s.length ( ) -1 ) ;
Plane f_plane= JSON.parseObject ( str , Plane.class , Feature.InitStringFieldAsEmpty ) ;
//解码
try {
f_plane.setStart_city ( java.net.URLDecoder.decode ( f_plane.getStart_city ( ) , "UTF-8" ) ) ;
f_plane.setEnd_city ( java.net.URLDecoder.decode ( f_plane.getEnd_city ( ) , "UTF-8" ) ) ;
} catch ( UnsupportedEncodingException e ) {
e.printStackTrace ( ) ;
}

System.out.println ( f_plane.getStart_city ( ) +" "+f_plane.getEnd_city ( ) +" "+f_plane.getStart_day ( ) ) ;
//获得中转城市名称
Map<String , Object> map=new HashMap<> ( ) ;
String transitCity=cityService.getTransitCity ( map , f_plane.getStart_city ( ) , f_plane.getEnd_city ( ) ) ;
req.setAttribute ( "transit_city" , transitCity ) ;
req.setAttribute ( "start_city" , f_plane.getStart_city ( ) ) ;
req.setAttribute ( "end_city" , f_plane.getEnd_city ( ) ) ;
req.setAttribute ( "start_day" , f_plane.getStart_day ( ) ) ;
return "forward:/search3" ;
}
致电从过境城市获得服务,也就是说
↓
①获得转移城市:
public String getTransitCity ( Map map , String start_city , String end_city ) {
List<City> cities= cityMapper.getCityList ( map ) ;
int s=cities.size ( ) ;
int[][] distance=new int[s][s] ;
for ( int i = 0 ; i < s ; i++ ) {
for ( int j = 0 ; j < s ; j++ ) {
int xi=cities.get ( i ) .getX ( ) ;
int yi=cities.get ( i ) .getY ( ) ;
int xj=cities.get ( j ) .getX ( ) ;
int yj=cities.get ( j ) .getY ( ) ;
distance[i][j]=Math.abs ( xj-xi ) *Math.abs ( xj-xi ) +Math.abs ( yj-yi ) *Math.abs ( yj-yi )
}
}
Map<String , Object> startM=new HashMap ( ) ;
startM.put ( "city_name" , start_city ) ;
List<City> cc=cityMapper.getCityList ( startM ) ;
Map<String , Object> endM=new HashMap ( ) ;
endM.put ( "city_name" , end_city ) ;
List<City> ccc=cityMapper.getCityList ( endM ) ;
int end=ccc.get ( 0 ) .getCity_id ( ) ;
if ( cc.size ( ) >0&&ccc.size ( ) >0 ) {
int start=cc.get ( 0 ) .getCity_id ( ) ;
for ( int i = 0 ; i < s ; i++ ) {
if ( cities.get ( i ) .getCity_id ( ) ==start ) {
start=i ;
break ;
}
}
for ( int i = 0 ; i < s ; i++ ) {
if ( cities.get ( i ) .getCity_id ( ) ==end ) {
end=i ;
break ;
}
}
int minD=1000000 ;
int flag=0 ;
for ( int i = 0 ; i < s ; i++ ) {
if ( cities.get ( i ) .getLocation ( ) .equals ( "china" ) &&i!=start&&i!=end ) {
if ( distance[start][i]+distance[i][end]<minD ) {
minD=distance[start][i]+distance[i][end] ;
flag=i ;
}
}
}
return cities.get ( flag ) .getCity_name ( ) ;
}
else return "?" ;
}
获得转移城市后,请求将转发到呼叫以获取转移的第一和第二路线的航班信息。飞行信息包括航班的最低价格,最低的价格是通过桌子和桌子连接表查询获得的。
//找到合适的转运飞行,转移时间大于1h,小于12h,在同一机场
List<Planes2> mm=new ArrayList<> ( ) ;
SimpleDateFormat sdf1= new SimpleDateFormat ( "yyyy-MM-dd HH:mm:ss" ) ;
for ( int i = 0 ; i < planes1. size ( ) ; i++ ) {
for ( int j = 0 ; j < planes2. size ( ) ; j++ ) {
if ( !planes1. get ( i). getArrival_airfield ( ). equals ( planes2. get ( j ). getDeparture_airfield ( ))){
continue ;
}
System. out. println ( 1 ) ;
String day1=planes1. get ( i ) . getStart_day ( )+" "+planes1. get ( i ) . getEnd_time ( ) ;
String day2=planes2. get ( j ) . getStart_day ( )+" "+planes2. get ( j ) . getStart_time ( ) ;
System. out. println ( day1 ) ;
System. out. println ( day2 ) ;
long ms=sdf1. parse ( day2). getTime ( )-sdf1. parse ( day1). getTime ( ) ;
System. out. println ( ms ) ;
if ( ms >= 3600000 && ms <= 43200000) {
Planes2 pp=new Planes2 ( planes1. get ( i ),planes2. get ( j ) ) ;
mm. add ( pp ) ;
break ;
}
}
}
在xml文件中映射接口
<select id="getPlaneListWithLowestPrice" parameterType="map" resultType="ds . pojo . Plane">
select e . plane_id , e . start_time , e . end_time , e . start_city , e . end_city , e . start_day , e . end_day ,
e . departure_airfield , e . arrival_airfield , lowest_price
from
( select a . plane_id,min ( price*coun ) lowest_price
from (
select * from planes_system . plane where
start_city = #{ start_city }
and end_city = #{ end_city }
and start_day = #{ start_day }) a,
planes_system . ticket b
where a . plane_id = b . plane_id
group by a . plane_id) d,planes_system . plane e
where d . plane_id = e . plane_id and e . exist= 'YES'
order by start_time asc
</select>
功能演示:
2。功能实现 - 更改标志
①在桌子中,删除原始机票和订单之间的绑定,然后添加改良的飞机
机票与订单的约束。
②需要更新订单的价格。重新签名的价格更新的一般原则是在没有退款或更少薪酬的情况下赚更多的钱。
③在更新价格时,请考虑直接订单和公交订单之间存在一定的差异。
④更新的门票数量。
直接:重新签署的空中票价和原始航空票价 +机场建设费和燃油费较高
作为重新品牌后的价格。
转移:如果更改后的价格高于原始价格,则原始订单价格是原始的空中票价 +重命名的航空票价。
源代码:
当订单性质不同(“直接”或“转移”)时,前端发送的数据是不同的。
change ( deal, plane, ticket, index ) {
console . log ( deal ) ;
if ( deal . attribute === 'direct' ) {
if ( ( ticket . coun*plane . price/100+190 ) > deal . price ) {
axios . post ( '/addDealRecord', {
data:{
amount:encodeURI ( '-' . concat ( ( ticket . coun*plane . price/100+190 ) -deal . price ) ) ,
id:encodeURI ( sessionStorage . getItem ( "id" ) ) ,
description:encodeURI ( "改签" ) ,
time:new Date ( ) . Format ( "yyyy-MM-dd hh:mm:ss" )
}
} ) . then ( ( response ) => {
console . log ( response . data ) ;
} ) . catch ( function ( error ) {
console . log ( error ) ;
} ) ;
}
axios . post ( '/change', {
data:{
price: ( ticket . coun*plane . price/100+190 ) >deal . price? ( ticket . coun*plane . price/100+190 ) :deal . price,
old_ticket_id:deal . tickets[index] . ticket_id,

new_ticket_id:ticket . ticket_id,
deal_id:deal . deal_id
}
} ) . then ( ( response ) => {
if ( response . data ) {
this . $alert ( '改签成功', '信息', {
confirmButtonText: '确定'
} ) ;
this . $router . push ( { path:"/dealPaid" } ) ;
}
} ) . catch ( function ( error ) {
console . log ( error ) ;
} ) ;
}else if ( deal . attribute==='transit' ) {
if ( ( ticket . coun*plane . price ) >deal . tickets[index] . coun*deal . tickets[index] . plane . price ) {
axios . post ( '/addDealRecord', {
data:{
amount:encodeURI ( '-' . concat ( ( ticket . coun*plane . price ) /100-deal . tickets[index] . coun*deal . tickets[index] . plane . price/100 ) ) ,
id:encodeURI ( sessionStorage . getItem ( "id" ) ) ,
description:encodeURI ( "改签" ) ,
time:new Date ( ) . Format ( "yyyy-MM-dd hh:mm:ss" )
}
} ) . then ( ( response ) => {
console . log ( response . data ) ;
} ) . catch ( function ( error ) {
console . log ( error ) ;
} ) ;
}
axios . post ( '/change', {
data:{
price: ( ticket . coun*plane . price ) >deal . tickets[index] . coun*deal . tickets[index] . plane . price ?
( deal . price-deal . tickets[index] . coun*deal . tickets[index] . plane . price/100
+ticket . coun*plane . price/100 ) :deal . price,
old_ticket_id:deal . tickets[index] . ticket_id,
new_ticket_id:ticket . ticket_id,
deal_id:deal . deal_id
}
} ) . then ( ( response ) => {
if ( response . data ) {
this . $alert ( '改签成功', '信息', {
confirmButtonText: '确定'
} ) ;
this . $router . push ( { path:"/dealPaid" } ) ;
}
} ) . catch ( function ( error ) {
console . log ( error ) ;
} ) ;
}
}
由于主要过程仍然是数据的前端传输,因此后端接收,并且处理相应的调用方法,因此后端仅分析关键代码。
首先执行以下操作:
//更新品牌后更新订单的价格。更名的一般原则是:如果添加越多,则不退款或更少的补偿。
HashMap<String, Object> map = new HashMap<String, Object> () ;
map.put ("deal_id", deal.getDeal_id () ) ;
map.put ("price", deal.getPrice () ) ;
dealService.updateDeal (map) ;
//删除其中的原始绑定并添加新的绑定
JSONObject oo= JSON.parseObject (str) ;
String old_ticket_id=JSON.toJSONString (oo.get ("old_ticket_id") ) ;
String new_ticket_id=JSON.toJSONString (oo.get ("new_ticket_id") ) ;
HashMap<String, Object> map1 = new HashMap<String, Object> () ;
map1.put ("ticket_id", Integer.parseInt (old_ticket_id) ) ;
map1.put ("deal_id", deal.getDeal_id () ) ;
dealService.deleteDealTicket (map1) ;
deal.setTicket_id (Integer.parseInt (new_ticket_id) ) ;
dealService.addDealTicket (deal) ;
req.setAttribute ("old_ticket_id", Integer.parseInt ( old_ticket_id ) ) ;
req.setAttribute ("new_ticket_id", Integer.parseInt ( new_ticket_id ) ) ;
return "forward:ticketChange";
再转发请求到TicketController中更新票的数量
int ticket_id1 = (int) req.getAttribute ( "old_ticket_id" ) ;
int ticket_id2 = (int) req.getAttribute ( "new_ticket_id" ) ;
HashMap<String, Object> map = new HashMap <String, Object> () ;
map.put ("ticket_id", ticket_id1) ;
ticketService.updateTicketAdd1 (map) ;
HashMap<String, Object> map1 = new HashMap <String, Object> () ;
map1.put ( "ticket_id", ticket_id2 ) ;
ticketService.updateTicketMinus1 (map1) ;
功能演示:
更改是成功的,价格变化以及空中票时间变化。
3.功能可以实现退款
转移:
①前端将寄回,在交易表中找到订单,然后将订单的付款状态更改为“否”
②如果您获得通过此订单绑定的订单,请在桌子中找到相应的空气票,然后将剩余的票证添加到一个。
非转移:
①从当前退款的航班票中减去订单的价格,然后将机场建设费和燃油费作为新订单的新价格。
②删除了原始订单的绑定和表格中的退款票。
③在桌子上,添加与退款票相对应的另外一个空气票号。
④创建一个具有“否”付款状态的新订单,该订单与桌子中的退款票有关。
源代码:
相同的操作用于根据步骤添加,删除,修改和搜索数据。它与上面的结构相同,只是操作对象是不同的,并且执行的操作是不同的,因此代码不再粘贴。
功能演示:
4。功能实施 - 取消航班
①在桌子中,将飞行的存在状态更改为“否”
②连接多个表,并处理复杂查询
收到的门票将退还。
③将在交易表中找到的用户ID与相关用户进行飞行取消
源代码:
相同的操作用于根据步骤添加,删除,修改和搜索数据。它与上面的结构相同,只是操作对象是不同的,并且执行的操作是不同的,因此代码不再粘贴。
功能演示:
然后,您可以在预订此航班的用户界面中接收取消飞行取消的通知。
V.系统测试
除了表明上几点中提到的几个功能外,还有诸如交易记录,国际时差转换和添加飞行等功能。
交易历史记录:
您可以看到取消飞行,票务退款,门票和其他原因的收入和支出记录。
国际时差转换:
该航班显示默认北京时间,单击以切换本地时间和本地时间
添加航班:
单击按钮可以减少/添加票务类型
您可以找到刚刚添加的航班
订单查询:
最后写:
项目源代码已上传到CSDN资源,可以在需要时下载。
您还可以发送私人消息以获取项目源代码 +数据库文件 +项目设计报告 +项目PPT
版权声明:本文为 “博览广文网” 原创文章,转载请附上原文出处链接及本声明;
工作时间:8:00-18:00
客服电话
0755-88186625
电子邮件
admin@lanyu.com
扫码二维码
获取最新动态