当前位置:   article > 正文

阶段三:项目开发---民航功能模块实现:任务18:指挥航空公司架次与延误率占比

阶段三:项目开发---民航功能模块实现:任务18:指挥航空公司架次与延误率占比

任务描述

内 容:在前面的“使用Spark清洗统计业务数据并保存到数据库”任务中,已经通过Spark Streaming 清洗程序,将Kafka中Topic为“task_Aftn”的报文数据,经过数据清洗后,保存到了MySQL数据库中;本节任务内容,通过统计查询,计算总架次数和延误架次数的一个比例,即指挥航空公司架次与延误率占比。

学  时:6学时

知识点:Vue和iView熟悉,内部推送和邮件推送处理

重点: 熟悉ECharts双Y轴展示,赋值

任务指导

通过统计查询,计算总架次数和延误架次数的一个比例,即指挥航空公司架次与延误率占比。使用ECharts展示柱状图、设置双Y轴,并绑定数据,展示即可:

1、打开前端kongguan_web项目,继续编写前端代码

  • 柱状图与折线图叠加,设置双Y轴

2、打开后端BigData-KongGuan项目,继续编写后端代码

3、前后端整合

  • 从后台请求数据,赋值展示

展示效果如下:

任务实现

1、打开前端Vue项目kongguan_web,创建前端 src/components/Delay.vue 页面,并添加柱状图与折线图叠加,设置双Y轴。

  • 页面div设计,代码如下:
  1. <template>
  2. <div>
  3. <div class="home">
  4. <div id="map-chart-06"></div>
  5. </div>
  6. </div>
  7. </template>
  8. ... 接下页 ...
  • 引入 ECharts 插件,代码如下:
  1. ... 接上页 ...
  2. <script>
  3. import echarts from "echarts";
  4. import {getFindCompanyDelay} from "../api/user/api.js";
  5. ... 接下页 ...
  • 初始化ECharts,代码如下:
  1. ... 接上页 ...
  2. export default {
  3. name: "Home",
  4. data() {
  5. return {
  6. chart: null,
  7. geoCoordMap: {},
  8. xData: [], //x轴数值
  9. delayData: [], //延误率
  10. sortieData: [] //架次
  11. };
  12. },
  13. mounted() {
  14. this.loadData();
  15. },
  16. methods: {
  17. initChart() {
  18. const option = {
  19. title: {
  20. text: '指挥航空公司架次与延误率占比',
  21. top: 18,
  22. left: 26,
  23. },
  24. tooltip: {
  25. trigger: 'axis',
  26. axisPointer: {
  27. type: 'cross',
  28. crossStyle: {
  29. color: '#999'
  30. }
  31. }
  32. },
  33. grid: {
  34. left: '3%',
  35. right: '8%',
  36. bottom: '3%',
  37. top: '15%',
  38. containLabel: true
  39. },
  40. ... 接下页 ...
  • X轴配置,代码如下:
  1. ... 接上页 ...
  2. xAxis: [
  3. {
  4. type: 'category',
  5. data: this.xData,
  6. axisLabel: {
  7. color: '#bdcad3',
  8. interval: 0,
  9. rotate: 40
  10. },
  11. axisTick: {
  12. show: false
  13. },
  14. axisLine: {
  15. lineStyle: {
  16. color: '#bdcad3'
  17. },
  18. show: false
  19. },
  20. axisPointer: {
  21. type: 'shadow'
  22. }
  23. }
  24. ],
  25. ... 接下页 ...
  • 双Y轴配置,代码如下:
  1. ... 接上页 ...
  2. yAxis: [
  3. {
  4. type: 'value',
  5. name: '',
  6. min: 0,
  7. max: 120,
  8. interval: 12,
  9. axisLabel: {
  10. formatter: '{value}',
  11. color: '#bdcad3'
  12. },
  13. show: true,
  14. axisTick: {
  15. show: false
  16. },
  17. axisLine: {
  18. lineStyle: {
  19. color: '#bdcad3'
  20. },
  21. show: false
  22. }
  23. },
  24. {
  25. type: 'value',
  26. name: '',
  27. min: 0,
  28. max: 100,
  29. interval: 10,
  30. axisLabel: {
  31. formatter: '{value} %'
  32. },
  33. show: true,
  34. axisTick: {
  35. show: false
  36. },
  37. axisLine: {
  38. lineStyle: {
  39. color: '#bdcad3'
  40. },
  41. show: false
  42. }
  43. }
  44. ],
  45. ... 接下页 ...
  • 数据配置,代码如下:
  1. ... 接上页 ...
  2. series: [
  3. {
  4. name: '架次',
  5. type: 'bar',
  6. itemStyle: {
  7. normal: {
  8. color: '#5fcec3'
  9. }
  10. },
  11. barWidth: 20,
  12. data: this.sortieData
  13. },
  14. {
  15. name: '延误率',
  16. type: 'line',
  17. itemStyle: {
  18. normal: {
  19. color: '#f88f2f'
  20. }
  21. },
  22. yAxisIndex: 1,
  23. data: this.delayData
  24. }
  25. ]
  26. ... 接下页 ...
  • 获取数据,并拼装数据,代码如下:
  1. ... 接上页 ...
  2. loadData() {
  3. getFindCompanyDelay().then(data => {
  4. if (data.isSuccess) {
  5. var res = data.result;
  6. for (var i = 0; i < res.length; i++) {
  7. this.xData[i] = res[i]['companyName'];
  8. this.sortieData[i] = res[i]['count'];
  9. this.delayData[i] = res[i]['delayCount'];
  10. }
  11. this.initChart();
  12. } else {
  13. this.$message.error("数据获取失败");
  14. }
  15. });
  16. }
  17. ... 接下页 ...
  • Delay.vue页面的完整代码如下:
  1. <template>
  2. <div>
  3. <div class="home">
  4. <div id="map-chart-06"></div>
  5. </div>
  6. </div>
  7. </template>
  8. <script>
  9. import echarts from "echarts";
  10. import {getFindCompanyDelay} from "../api/user/api.js";
  11. export default {
  12. name: "Home",
  13. data() {
  14. return {
  15. chart: null,
  16. geoCoordMap: {},
  17. xData: [], //x轴数值
  18. delayData: [], //延误率
  19. sortieData: [] //架次
  20. };
  21. },
  22. mounted() {
  23. this.loadData();
  24. },
  25. methods: {
  26. initChart() {
  27. const option = {
  28. title: {
  29. text: '指挥航空公司架次与延误率占比',
  30. top: 18,
  31. left: 26,
  32. },
  33. tooltip: {
  34. trigger: 'axis',
  35. axisPointer: {
  36. type: 'cross',
  37. crossStyle: {
  38. color: '#999'
  39. }
  40. }
  41. },
  42. grid: {
  43. left: '3%',
  44. right: '8%',
  45. bottom: '3%',
  46. top: '15%',
  47. containLabel: true
  48. },
  49. xAxis: [
  50. {
  51. type: 'category',
  52. data: this.xData,
  53. axisLabel: {
  54. color: '#bdcad3',
  55. interval: 0,
  56. rotate: 40
  57. },
  58. axisTick: {
  59. show: false
  60. },
  61. axisLine: {
  62. lineStyle: {
  63. color: '#bdcad3'
  64. },
  65. show: false
  66. },
  67. axisPointer: {
  68. type: 'shadow'
  69. }
  70. }
  71. ],
  72. yAxis: [
  73. {
  74. type: 'value',
  75. name: '',
  76. min: 0,
  77. max: 120,
  78. interval: 12,
  79. axisLabel: {
  80. formatter: '{value}',
  81. color: '#bdcad3'
  82. },
  83. show: true,
  84. axisTick: {
  85. show: false
  86. },
  87. axisLine: {
  88. lineStyle: {
  89. color: '#bdcad3'
  90. },
  91. show: false
  92. }
  93. },
  94. {
  95. type: 'value',
  96. name: '',
  97. min: 0,
  98. max: 100,
  99. interval: 10,
  100. axisLabel: {
  101. formatter: '{value} %'
  102. },
  103. show: true,
  104. axisTick: {
  105. show: false
  106. },
  107. axisLine: {
  108. lineStyle: {
  109. color: '#bdcad3'
  110. },
  111. show: false
  112. }
  113. }
  114. ],
  115. series: [
  116. {
  117. name: '架次',
  118. type: 'bar',
  119. itemStyle: {
  120. normal: {
  121. color: '#5fcec3'
  122. }
  123. },
  124. barWidth: 20,
  125. data: this.sortieData
  126. },
  127. {
  128. name: '延误率',
  129. type: 'line',
  130. itemStyle: {
  131. normal: {
  132. color: '#f88f2f'
  133. }
  134. },
  135. yAxisIndex: 1,
  136. data: this.delayData
  137. }
  138. ]
  139. };
  140. this.chart = echarts.init(document.getElementById("map-chart-06"));
  141. this.chart.setOption(option);
  142. },
  143. loadData() {
  144. getFindCompanyDelay().then(data => {
  145. if (data.isSuccess) {
  146. var res = data.result;
  147. for (var i = 0; i < res.length; i++) {
  148. this.xData[i] = res[i]['companyName'];
  149. this.sortieData[i] = res[i]['count'];
  150. this.delayData[i] = res[i]['delayCount'];
  151. }
  152. this.initChart();
  153. } else {
  154. this.$message.error("数据获取失败");
  155. }
  156. });
  157. }
  158. }
  159. };
  160. </script>
  161. <style>
  162. .home {
  163. height: 490px;
  164. margin: 0 auto;
  165. background-color: #ffffff;
  166. border: 1px solid #ebedf2;
  167. border-radius: 10px;
  168. box-shadow: 3px 3px 3px 3px #ebedf2;
  169. }
  170. #map-chart-06 {
  171. height: 490px;
  172. margin: 0 auto;
  173. }
  174. </style>
  • 修改src/api/user/api.js,添加getFindCompanyDelay方法,用于访问服务器端获取数据,内容如下:
  1. import request from '../../utils/request'
  2. const baseUrl="/api"
  3. //
  4. //… 其他 function,略。 …
  5. //
  6. //获取指挥航空公司架次与延误率占比
  7. export function getFindCompanyDelay(data){
  8. return request({
  9. url:baseUrl+"/company/findCompanyDelay",
  10. method:"get",
  11. data:data
  12. })
  13. }
  14. //获取各扇区航班数
  15. export function getSectionVal(data){
  16. return request({
  17. url:baseUrl+"/atc/findSectorSortie",
  18. method:"get",
  19. data:data
  20. })
  21. }

2、后端数据获取,打开后端项目BigData-KongGuan

  • 编写关于航空公司的数据操作和存储的实体类com.qrsoft.entity.Commpany,内容如下:
  1. package com.qrsoft.entity;
  2. import com.baomidou.mybatisplus.annotation.IdType;
  3. import com.baomidou.mybatisplus.annotation.TableField;
  4. import com.baomidou.mybatisplus.annotation.TableId;
  5. import com.baomidou.mybatisplus.annotation.TableName;
  6. import io.swagger.models.auth.In;
  7. import lombok.AllArgsConstructor;
  8. import lombok.Data;
  9. import lombok.NoArgsConstructor;
  10. import java.io.Serializable;
  11. @Data
  12. @AllArgsConstructor
  13. @NoArgsConstructor
  14. @TableName("company_number")
  15. public class Company implements Serializable {
  16. @TableId(value = "id",type = IdType.AUTO)
  17. private Integer id;
  18. @TableField(value = "acid")
  19. private String acid;
  20. @TableField(value = "company_code3")
  21. private String companyCode3;
  22. @TableField(value = "company_name")
  23. private String companyName;
  24. @TableField(value = "delay_count")
  25. private String delayCount;
  26. @TableField(exist = false)
  27. private String count;
  28. @TableField(exist = false)
  29. private Double companyCount;
  30. }
  • 编写数据访问接口BigData-KongGuan/src/main/java/com/qrsoft/mapper/CompanyMapper.java,继承自BaseMapper,内容如下:
  1. package com.qrsoft.mapper;
  2. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  3. import com.qrsoft.entity.Company;
  4. import org.apache.ibatis.annotations.Mapper;
  5. import org.apache.ibatis.annotations.Select;
  6. import java.util.List;
  7. @Mapper
  8. public interface CompanyMapper extends BaseMapper<Company> {
  9. @Select("SELECT company_name,COUNT(*) as count,SUM(delay_count) as delayCount FROM company_number GROUP BY company_name ORDER BY COUNT(*) DESC LIMIT 19;")
  10. List<Company> findCompanyDelay();
  11. }
  • 编写数据服务接口BigData-KongGuan/src/main/java/com/qrsoft/service/CompanyService.java,使用baseMapper.findCompanyDelay()方法查询指挥航空公司航班数和航班延误数,内容如下:
  1. package com.qrsoft.service;
  2. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  3. import com.qrsoft.common.Result;
  4. import com.qrsoft.common.ResultConstants;
  5. import com.qrsoft.entity.Company;
  6. import com.qrsoft.mapper.CompanyMapper;
  7. import org.springframework.stereotype.Service;
  8. import java.util.List;
  9. @Service
  10. public class CompanyService extends ServiceImpl<CompanyMapper, Company> {
  11. /**
  12. * 查询指挥航空公司航班数,和航班延误数
  13. */
  14. public Result findCompanyDelay() {
  15. List<Company> companyDelay = baseMapper.findCompanyDelay();
  16. for (Company c : companyDelay) {
  17. double dcount = Double.parseDouble(c.getDelayCount());
  18. double count = Double.parseDouble(c.getCount());
  19. Double rest = dcount / count * 100;
  20. c.setDelayCount(String.format("%.2f", rest));
  21. }
  22. return new Result(ResultConstants.SUCCESS, ResultConstants.C_SUCCESS, companyDelay);
  23. }
  24. /**
  25. * 查询指挥航空公司占比
  26. */
  27. public Result findCompanyByCompanyAll() {
  28. List<Company> companyDelay = baseMapper.findCompanyDelay();
  29. double sum = 0;
  30. for (Company c : companyDelay) {
  31. double count = Double.parseDouble(c.getCount());
  32. sum+=count;
  33. }
  34. for (Company c : companyDelay) {
  35. double count = Double.parseDouble(c.getCount());
  36. c.setCompanyCount((count!=0)?sum/count:0);
  37. }
  38. return new Result(ResultConstants.SUCCESS, ResultConstants.C_SUCCESS, companyDelay);
  39. }
  40. /**
  41. * 机场负荷统计
  42. */
  43. public Result findAirportCount(){
  44. List<Company> companyDelay = baseMapper.findCompanyDelay();
  45. double sum = 0;
  46. for (Company c : companyDelay) {
  47. double count = Double.parseDouble(c.getCount());
  48. sum+=count;
  49. }
  50. for (Company c : companyDelay) {
  51. double count = Double.parseDouble(c.getCount());
  52. c.setCompanyCount((count!=0)?sum/count:0);
  53. }
  54. return new Result(ResultConstants.SUCCESS, ResultConstants.C_SUCCESS, companyDelay);
  55. }
  56. }
  • 编写BigData-KongGuan/src/main/java/com/qrsoft/controller/CompanyController.java控制器类,处理前端的请求,请求后台地址:/company/findCompanyDelay,使用get方式,内容如下:
  1. @Api(tags = "航空公司航班数,和航班延误数")
  2. @RestController
  3. @RequestMapping("/api/company")
  4. public class CompanyController {
  5. @Autowired
  6. private CompanyService service;
  7. /**
  8. * 查询指挥航空公司航班数,和航班延误数
  9. */
  10. @ApiOperation(value = "查询指挥航空公司航班数,和航班延误数")
  11. @GetMapping("/findCompanyDelay")
  12. public Result findCompanyDelay(){
  13. return service.findCompanyDelay();
  14. }
  15. @ApiOperation(value = "查询指挥航空公司架次数占比")
  16. @GetMapping("/findCompanyByCompanyAll")
  17. public Result findCompanyByCompanyAll(){
  18. return service.findCompanyByCompanyAll();
  19. }
  20. }

3、完成前端Index.vue页面,展示“指挥航空公司架次与延误率占比”

  • 在src/views/Home/Index.vue页面引入Delay.vue组件,代码如下:
import Delay from "../../components/Delay";
  • 声明组件,代码如下:
components: {AirLine, Section, Delay},
  • 展示,代码如下:
  1. <el-row :gutter="30" v-show="isShow('/flight/delay')">
  2. <el-col :span="16" align="center">
  3. <Delay/>
  4. </el-col>
  5. <el-col :span="8" align="center">
  6. <year-warning-chart/>
  7. </el-col>
  8. </el-row>

注意:在上面代码中【 v-show="isShow('/flight/delay')" 】属性的作用是判断当前登录的用户是否有权限显示当前内容,如果当前登录的用户没有权限,则不会显示当前内容,新用户的权限需要到MySQL数据库中进行设置。

这里有两种方式,可以显示当前内容:

1)去掉【 v-show="isShow('/flight/delay')" 】属性,即不判断是否有权限显示。

2)需要使用有权限的用户登录才能显示,或到数据库中分配权限。

参照任务“动态航线图”进行设置。

例如我们前面使用的用户admin,该用户没有权限显示,所以使用admin用户登录系统时是不会显示当前内容的,如果要进行权限设置,可以进入MySQL安装节点(node3节点),然后进入数据库,为admin用户授权。

[root@node3 ~]# mysql -uroot -p123456
mysql> use kongguan;

先查看角色表中,“管理员”的ID:

修改sys_auth表,添加一个【/flight/delay】权限:

mysql> insert into sys_auth(auth_name,auth_code,menu_url) values('show delay','/flight/delay','/flight/delay');

修改role_auth表,将权限授权给“管理员”角色:

mysql>insert into role_auth(role_id,auth_id) values(3,196);

  • Index.vue页面的完整代码如下:
  1. <template>
  2. <div class="index">
  3. <el-row :gutter="30" v-show="isShow('/flight/section')">
  4. <el-col :span="24" align="center">
  5. <Section/>
  6. </el-col>
  7. </el-row>
  8. <el-row :gutter="30" v-show="isShow('/flight/airline')">
  9. <el-col :span=24 align="center">
  10. <AirLine/>
  11. </el-col>
  12. </el-row>
  13. <el-row :gutter="30" v-show="isShow('/flight/delay')">
  14. <el-col :span="16" align="center">
  15. <Delay/>
  16. </el-col>
  17. <el-col :span="8" align="center">
  18. <year-warning-chart/>
  19. </el-col>
  20. </el-row>
  21. </div>
  22. </template>
  23. <script>
  24. import AirLine from "../../components/AirLine";
  25. import Section from "../../components/Section";
  26. import Delay from "../../components/Delay";
  27. import {hasPermission} from "../../utils/permission";
  28. export default {
  29. data() {
  30. return {
  31. };
  32. },
  33. mounted() {
  34. },
  35. components: {AirLine, Section, Delay},
  36. methods: {
  37. isShow(permission){
  38. return hasPermission(permission);
  39. }
  40. }
  41. };
  42. </script>
  43. <style scoped>
  44. .index {
  45. height: 100%;
  46. overflow: auto;
  47. padding-left: 44px;
  48. padding-right: 44px
  49. }
  50. .index::-webkit-scrollbar {
  51. display: none;
  52. }
  53. .caseClass {
  54. background: url('../../assets/images/index-bg.png') no-repeat;
  55. background-size: cover;
  56. margin-top: 20px;
  57. height: 284px;
  58. }
  59. .el-button {
  60. background: transparent;
  61. }
  62. </style>
  • 确保Hadoop、Spark、Kafka、Redis、MySQL等服务均已经正常启动,如果没有正常启动,请参照前面的安装部署任务,完成这些服务的启动。

例如:查看MySQL是否正常启动。

  • 启动后端项目 BigData-KongGuan

  • 启动前端项目 kongguan_web

  • 页面展示效果:

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/811698
推荐阅读
相关标签
  

闽ICP备14008679号