فهرست منبع

航班量统计图表页面

zhongxiaoyu 2 سال پیش
والد
کامیت
a3f8c127f5

+ 1 - 0
src/layout/components/Sidebar/SidebarItem.vue

@@ -328,6 +328,7 @@ export default {
       no-repeat;
   }
 }
+.flightStatistics,
 .arrival {
   background: url("../../../assets/nav/ic_list_nav_arrive_default.png")
     no-repeat;

+ 1 - 0
src/layout/components/Sidebar/index.vue

@@ -151,6 +151,7 @@ export default {
       background: url("../../../assets/nav/ic_list_nav_transit_check.png")
         no-repeat;
     }
+    .flightStatistics,
     .arrival {
       background: url("../../../assets/nav/ic_list_nav_arrive_check.png")
         no-repeat;

+ 2 - 0
src/layout/index.vue

@@ -90,10 +90,12 @@ export default {
         document.getElementById("sidebar-containers").style.width = "208px";
         document.getElementById("main-containers").style.paddingLeft = "208px";
         document.getElementById("navbar_lowers").style.paddingLeft = "208px";
+        this.$store.dispatch('app/expandSidebar', true)
       } else {
         document.getElementById("sidebar-containers").style.width = "56px";
         document.getElementById("main-containers").style.paddingLeft = "56px";
         document.getElementById("navbar_lowers").style.paddingLeft = "56px";
+        this.$store.dispatch('app/expandSidebar', false)
       }
     },
     // eveclk() {

+ 3 - 1
src/router/index.js

@@ -19,6 +19,8 @@ import routesTwo from './routes/routes-file-two'
 import routesThree from './routes/routes-file-three'
 import routesFileFour from './routes/routes-file-four'
 import routesFive from './routes/routes-file-five'
+import routesFileSix from './routes/routes-file-six'
+
 /**
  * Note: sub-menu only appear when route children.length >= 1
  * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
@@ -68,7 +70,7 @@ export const constantRoutes = [
 // 动态路由
 export const asyncRoutes = []
 // 插入路由
-routesPush([...routesOne, ...routesTwo, ...routesThree, ...routesFileFour, ...routesFive], asyncRoutes)
+routesPush([...routesOne, ...routesTwo, ...routesThree, ...routesFileFour, ...routesFive, ...routesFileSix], asyncRoutes)
 // asyncRoutes.push({ path: '/', component: () => import('@/views/noPower'), hidden: true })
 asyncRoutes.push({
   path: '*',

+ 28 - 0
src/router/routes/routes-file-six.js

@@ -0,0 +1,28 @@
+import Layout from '@/layout'
+
+const filghtCountRoutes = {
+  path: '/flightStatistics',
+  component: Layout,
+  children: [
+    {
+      path: '/flightStatistics',
+      redirect: 'charts',
+      component: () => import('@/views/flightStatistics'),
+      meta: {
+        title: '航班统计',
+        imgstyle: 'ic_list_nav_arrive_default.png',
+        imgstyleup: 'ic_list_nav_arrive_check.png'
+      },
+      children: [
+        {
+          path: 'charts',
+          name: 'FlightStatisticsCharts',
+          component: () => import('@/views/flightStatistics/views/flightStatisticsCharts'),
+          meta: { title: '航班量统计' }
+        }
+      ]
+    }
+  ]
+}
+
+export default [filghtCountRoutes]

+ 8 - 1
src/store/modules/app.js

@@ -11,7 +11,8 @@ import Cookies from 'js-cookie'
 const state = {
   sidebar: {
     opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true,
-    withoutAnimation: false
+    withoutAnimation: false,
+    expand: false
   },
   device: 'desktop',
   dialog: Cookies.get('dialogStatus') === 'true',
@@ -59,6 +60,9 @@ const mutations = {
   SET_QUERY_FORM(state, form) {
     state.queryForm = form
     sessionStorage.setItem('queryForm', JSON.stringify(form))
+  },
+  EXPAND_SIDEBAR: (state, expandFlag) => {
+    state.sidebar.expand = expandFlag
   }
 }
 
@@ -89,6 +93,9 @@ const actions = {
   },
   setQueryForm({ commit }, form) {
     commit('SET_QUERY_FORM', form)
+  },
+  expandSidebar({ commit }, expandFlag) {
+    commit('EXPAND_SIDEBAR', expandFlag)
   }
 }
 

+ 325 - 0
src/views/flightStatistics/components/flightStatisticsHeader.vue

@@ -0,0 +1,325 @@
+<template>
+  <div class="flight-statistics-header">
+    <template v-if="title">
+      <div class="title">{{ title }}</div>
+    </template>
+    <el-form
+      ref="form"
+      class="form"
+      :model="formData"
+    >
+      <el-form-item
+        v-for="item in formItems"
+        :key="item.prop"
+        :prop="item.prop"
+        :label="item.label"
+      >
+        <template v-if="item.inputType === 'input'">
+          <el-input
+            v-model="formData[item.prop]"
+            :size="item.size || 'small'"
+            :placeholder="item.placeholder || '请输入'"
+            :clearable="item.clearable"
+          />
+        </template>
+        <template v-if="item.inputType === 'select'">
+          <el-select
+            v-model="formData[item.prop]"
+            :size="item.size || 'small'"
+            :placeholder="item.placeholder || '请选择'"
+            :multiple="item.multiple"
+            :clearable="item.clearable"
+            :disabled="item.disabled"
+            @change="value => { item.changeHandler && item.changeHandler(value) }"
+          >
+            <el-option
+              v-for="option in item.options"
+              :key="option.value"
+              :value="option.value"
+              :label="option.label"
+            />
+          </el-select>
+        </template>
+        <template v-if="item.inputType === 'cascader'">
+          <el-cascader
+            v-model="formData[item.prop]"
+            :size="item.size || 'small'"
+            :placeholder="item.placeholder || '请选择'"
+            :options="item.options"
+            :props="item.props"
+            :clearable="item.clearable"
+            :disabled="item.disabled"
+          />
+        </template>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'FlightStatisticsHeader',
+  props: {
+    title: {
+      type: String,
+      default: ''
+    },
+    items: {
+      type: Array,
+      default: () => []
+    },
+    data: {
+      type: Object,
+      default: undefined
+    }
+  },
+  data() {
+    const that = this
+    return {
+      formData: {
+        range: 'all',
+        inOrOut: 'all',
+        interval: 'month',
+        airline: '',
+        area: '',
+        airport: '',
+        terminal: ''
+      },
+      formItems: [
+        {
+          prop: 'range',
+          inputType: 'select',
+          placeholder: '请选择统计范围',
+          options: [
+            {
+              value: 'all',
+              label: '全部统计范围'
+            },
+            {
+              value: 'airline',
+              label: '航线'
+            },
+            {
+              value: 'area',
+              label: '大区'
+            },
+            {
+              value: 'airport',
+              label: '航站'
+            },
+            {
+              value: 'terminal',
+              label: '航站楼'
+            }
+          ],
+          changeHandler(value) {
+            that.formData.airline = ''
+            that.formData.area = ''
+            that.formData.airport = ''
+            that.formData.terminal = ''
+            that.formItems[3].disabled = true
+            that.formItems[4].disabled = true
+            that.formItems[5].disabled = true
+            that.formItems[6].disabled = true
+            switch (value) {
+              case 'airline':
+                that.formItems[3].disabled = false
+                break
+              case 'area':
+                that.formItems[4].disabled = false
+                break
+              case 'airport':
+                that.formItems[5].disabled = false
+                break
+              case 'terminal':
+                that.formItems[6].disabled = false
+                break
+              default:
+                break
+            }
+          }
+        },
+        {
+          prop: 'inOrOut',
+          inputType: 'select',
+          placeholder: '请选择进离港',
+          options: [
+            {
+              value: 'all',
+              label: '全部进离港'
+            },
+            {
+              value: 'arrival',
+              label: '进港'
+            },
+            {
+              value: 'departure',
+              label: '离港'
+            },
+            {
+              value: 'transfer',
+              label: '中转'
+            }
+          ]
+        },
+        {
+          prop: 'interval',
+          inputType: 'select',
+          placeholder: '',
+          options: [
+            {
+              value: 'sevenDays',
+              label: '最近七天'
+            },
+            {
+              value: 'month',
+              label: '按月统计'
+            },
+            {
+              value: 'quarter',
+              label: '按季统计'
+            },
+            {
+              value: 'year',
+              label: '按月统计'
+            },
+            {
+              value: 'custom',
+              label: '自定义时间段'
+            }
+          ]
+        },
+        {
+          prop: 'airline',
+          inputType: 'select',
+          placeholder: '航线选择',
+          clearable: true,
+          disabled: true,
+          options: []
+        },
+        {
+          prop: 'area',
+          inputType: 'select',
+          placeholder: '大区选择',
+          clearable: true,
+          disabled: true,
+          options: []
+        },
+        {
+          prop: 'airport',
+          inputType: 'select',
+          placeholder: '航站选择',
+          clearable: true,
+          multiple: true,
+          disabled: true,
+          options: [
+            {
+              value: 'PEK',
+              label: 'PEK'
+            },
+            {
+              value: 'CTU',
+              label: 'CTU'
+            }
+          ]
+        },
+        {
+          prop: 'terminal',
+          inputType: 'cascader',
+          placeholder: '航站楼选择',
+          props: {
+            multiple: true
+          },
+          clearable: true,
+          disabled: true,
+          options: []
+        }
+      ]
+    }
+  },
+  watch: {
+    items: {
+      handler(val) {
+        val?.length && (this.formItems = val)
+      },
+      deep: true,
+      immediate: true
+    },
+    data: {
+      handler(val) {
+        val && (this.formData = val)
+      },
+      deep: true,
+      immediate: true
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.flight-statistics-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: flex-start;
+  .title {
+    margin-right: 24px;
+    padding-left: 16px;
+    // min-width: 176px;
+    height: 32px;
+    line-height: 32px;
+    font-size: 20px;
+    font-family: Helvetica, 'Microsoft YaHei';
+    font-weight: bold;
+    position: relative;
+    &::before {
+      content: '';
+      width: 4px;
+      height: 20px;
+      background: #2d67e3;
+      position: absolute;
+      top: 0;
+      bottom: 0;
+      left: 0;
+      margin: auto;
+    }
+  }
+  ::v-deep .form {
+    display: flex;
+    flex-wrap: wrap;
+    > .el-form-item {
+      margin-bottom: 24px;
+      &:not(:last-child) {
+        margin-right: 8px;
+      }
+      .el-form-item__content {
+        height: 32px;
+        line-height: 30px;
+        .el-input .el-input__inner {
+          border-radius: 4px;
+          font-family: Helvetica, 'Microsoft YaHei';
+          color: #303133;
+          border-color: #ffffff;
+          &:hover {
+            border-color: #c0c4cc;
+          }
+          &:focus {
+            border-color: #409eff;
+          }
+        }
+        .el-select,
+        .el-cascader {
+          .el-input:not(.is-disabled) {
+            .el-icon-arrow-up::before {
+              content: '\e78f';
+            }
+            .el-input__icon,
+            .el-input__inner::-webkit-input-placeholder {
+              color: #303133;
+            }
+          }
+        }
+      }
+    }
+  }
+}
+</style>

+ 3 - 0
src/views/flightStatistics/index.vue

@@ -0,0 +1,3 @@
+<template>
+  <router-view />
+</template>

+ 256 - 0
src/views/flightStatistics/views/flightStatisticsCharts.vue

@@ -0,0 +1,256 @@
+<template>
+  <div class="statstics-wrapper">
+    <div
+      ref="headerWrapper"
+      class="statstics-header"
+    >
+      <FlightStatisticsHeader title="航班量统计" />
+    </div>
+    <div class="statstics-content">
+      <div
+        id="chart"
+        class="flight-statistics-chart"
+        :style="{ height: chartHeight }"
+      />
+    </div>
+  </div>
+</template>
+
+<script>
+import FlightStatisticsHeader from '../components/flightStatisticsHeader.vue'
+import { mapGetters } from 'vuex'
+
+export default {
+  name: 'FlightStatisticsCharts',
+  components: { FlightStatisticsHeader },
+  data() {
+    return {
+      myChart: null,
+      debounceTime: 300,
+      chartHeight: '70vh',
+      options: {
+        backgroundColor: '#fff',
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            type: 'cross',
+            crossStyle: {
+              color: '#999'
+            }
+          }
+        },
+        legend: {
+          top: '5%',
+          right: '5%',
+          data: ['航班量数量', '航班量同比', '航班量环比'],
+          textStyle: {
+            fontFamily: 'Helvetica, "Microsoft YaHei"',
+            color: '#101116'
+          }
+        },
+        grid: {
+          top: '10%',
+          left: '5%',
+          right: '5%',
+          bottom: '5%'
+        },
+        xAxis: {
+          data: [
+            '2020.01',
+            '2020.02',
+            '2020.03',
+            '2020.04',
+            '2020.05',
+            '2020.06',
+            '2020.07',
+            '2020.08',
+            '2020.09',
+            '2020.10',
+            '2020.11',
+            '2020.12',
+            '2021.01',
+            '2021.02',
+            '2021.03',
+            '2021.04'
+          ],
+          axisLine: {
+            show: true,
+            lineStyle: {
+              color: '#000000'
+            }
+          },
+          axisTick: {
+            show: false // 隐藏X轴刻度
+          },
+          axisLabel: {
+            fontFamily: 'Helvetica, "Microsoft YaHei"',
+            color: '#101116'
+          },
+          axisPointer: {
+            type: 'shadow'
+          }
+        },
+        yAxis: [
+          {
+            min: 0,
+            max: 60000,
+            interval: 5000,
+            splitLine: {
+              lineStyle: {
+                type: 'dashed',
+                color: '#B0B3C3',
+                opacity: 0.5
+              }
+            },
+            axisPointer: {
+              label: {
+                formatter: ({ value }) => value.toFixed()
+              }
+            },
+            axisLabel: {
+              fontFamily: 'Helvetica, "Microsoft YaHei"',
+              color: '#101116'
+            }
+          },
+          {
+            min: -0.3,
+            max: 0.5,
+            interval: 0.1,
+            axisLabel: {
+              formatter: value => (value * 100).toFixed(2) + '%',
+              fontFamily: 'Helvetica, "Microsoft YaHei"',
+              color: '#101116'
+            },
+            axisPointer: {
+              label: {
+                formatter: ({ value }) => (value * 100).toFixed(2) + '%'
+              }
+            },
+            splitLine: {
+              show: false
+            }
+          }
+        ],
+        series: [
+          {
+            name: '航班量数量',
+            type: 'bar',
+            z: 2,
+            itemStyle: {
+              color: '#6682B5'
+            },
+            barWidth: 40,
+            data: [
+              54000, 54000, 54000, 54000, 54000, 54000, 54000, 54000, 54000, 54000, 54000, 54000, 54000, 54000, 54000,
+              54000
+            ]
+          },
+          {
+            name: '航班量同比',
+            type: 'line',
+            z: 4,
+            yAxisIndex: 1,
+            symbol: 'circle',
+            itemStyle: {
+              color: '#F2B849',
+              borderColor: '#ffffff',
+              borderWidth: 4
+            },
+            lineStyle: {
+              width: 4,
+              color: '#F2B849'
+            },
+            symbolSize: 32,
+            tooltip: {
+              valueFormatter: value => (value * 100).toFixed(2) + '%'
+            },
+            data: [0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3]
+          },
+          {
+            name: '航班量环比',
+            type: 'line',
+            z: 3,
+            yAxisIndex: 1,
+            symbol: 'circle',
+            itemStyle: {
+              color: '#E33D3D',
+              borderColor: '#ffffff',
+              borderWidth: 4
+            },
+            lineStyle: {
+              width: 4,
+              color: '#E33D3D'
+            },
+            symbolSize: 32,
+            tooltip: {
+              valueFormatter: value => (value * 100).toFixed(2) + '%'
+            },
+            data: [0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2]
+          }
+        ]
+      }
+    }
+  },
+  computed: {
+    ...mapGetters(['sidebar'])
+  },
+  watch: {
+    // 监听数据变化 重绘图形
+    options: {
+      handler(obj) {
+        this.myChart.setOption(obj)
+      },
+      deep: true
+    },
+    'sidebar.expand'() {
+      this.resizeHandler()
+    }
+  },
+  mounted() {
+    this.setChartHeight()
+    this.myChart = this.$echarts.init(document.getElementById('chart'))
+    this.myChart.setOption(this.options)
+    // 监听页面缩放
+    window.addEventListener('resize', this.setChartHeight)
+    window.addEventListener('resize', this._.debounce(this.resizeHandler, this.debounceTime))
+    this.$nextTick(() => {
+      this.resizeHandler()
+    })
+  },
+  beforeDestroy() {
+    // 销毁实例和移除监听
+    window.removeEventListener('resize', this.setChartHeight)
+    if (this.myChart) {
+      this.myChart.dispose()
+      window.removeEventListener('resize', this.resizeHandler)
+      this.myChart = null
+    }
+  },
+  methods: {
+    setChartHeight() {
+      const topBarHeight = 80
+      const headerHeight = this.$refs['headerWrapper'].offsetHeight
+      const footerBlackHeight = 24
+      this.chartHeight = `calc(100vh - ${topBarHeight + headerHeight + footerBlackHeight}px)`
+    },
+    resizeHandler() {
+      if (this.myChart) {
+        this.myChart.resize()
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.statstics-wrapper {
+  padding-left: 24px;
+  padding-right: 36px;
+  .statstics-header {
+    padding-top: 16px;
+  }
+  .flight-statistics-chart {
+    width: 100%;
+  }
+}
+</style>