<template>
  <div class="dashboard">
    <div class="dashboard-scrollbar">
      <div
        v-loading="loading"
        element-loading-text="拼命加载中"
        element-loading-spinner="el-icon-loading"
        element-loading-background="rgba(0, 0, 0, 0.3)"
        class="dashboard-wrapper"
      >
        <div class="dashboard-card">
          <div class="dashboard-card-wrapper">
            <div class="dashboard-card-title">当日进港航班数</div>
            <div class="dashboard-card-content">
              <CountBox
                :count-number="arrivalFlightCount"
                :count-length="9"
              />
            </div>
          </div>
          <div class="dashboard-card-wrapper">
            <div class="dashboard-card-title">当日出港航班数</div>
            <div class="dashboard-card-content">
              <CountBox
                :count-number="departureFlightCount"
                :count-length="9"
              />
            </div>
          </div>
        </div>
        <div class="dashboard-card">
          <div class="dashboard-card-wrapper">
            <div class="dashboard-card-title">航司行李量排行</div>
          </div>
          <div
            v-if="companyData.length"
            class="dashboard-card-content"
          >
            <vue-seamless-scroll
              class="scroll-table"
              :class-option="defaultOption"
            >
              <div
                v-for="item in companyData"
                :key="item.name"
                class="company-baggage-item"
              >
                <div class="company-name">{{ item.name }}</div>
                <div class="company-progress">
                  <el-progress
                    :percentage="item.percentage"
                    :color="customColor"
                    :show-text="false"
                    :stroke-width="8"
                  ></el-progress>
                </div>
                <div class="company-count">{{ item.count }}</div>
              </div>
            </vue-seamless-scroll>
          </div>
        </div>
        <div class="dashboard-card">
          <div class="dashboard-card-wrapper">
            <div class="dashboard-card-title">
              <span class="title-text">航站选择</span>
              <el-select
                v-model="currentAirport"
                placeholder="请选择航站"
                filterable
                default-first-option
              >
                <el-option
                  v-for="option in aiportOptions"
                  :key="option.value"
                  :label="option.label"
                  :value="option.value"
                />
              </el-select>
            </div>
          </div>
        </div>
        <div class="dashboard-card">
          <div class="dashboard-card-wrapper">
            <div class="dashboard-card-title">当日行李量统计</div>
            <div class="dashboard-card-content">
              <div
                v-for="item in baggageCountItems"
                :key="item.title"
                class="baggage-count-item"
              >
                <div class="baggage-count-num">{{ item.num }}</div>
                <div class="baggage-count-title">{{ item.title }}</div>
              </div>
            </div>
          </div>
        </div>
        <div class="dashboard-card">
          <div class="dashboard-card-wrapper">
            <div class="dashboard-card-title">当日行李目的地分布图</div>
          </div>
          <div class="dashboard-card-content">
            <MapCharts
              id="box-map"
              :option="boxMap"
            />
          </div>
        </div>
        <div class="dashboard-card">
          <div class="dashboard-card-wrapper">
            <div class="dashboard-card-title">每日小时行李处理量 - 进港</div>
          </div>
          <div class="dashboard-card-content">
            <BarCharts
              id="inHour"
              :option="inHourDataOption"
            />
          </div>
        </div>
        <div class="dashboard-card">
          <div class="dashboard-card-wrapper">
            <div class="dashboard-card-title">每日小时行李处理量 - 出港</div>
          </div>
          <div class="dashboard-card-content">
            <BarCharts
              id="outHour"
              :option="outHourDataOption"
            />
          </div>
        </div>
        <div class="dashboard-card">
          <div class="dashboard-card-wrapper">
            <div class="dashboard-card-title">每日小时行李处理量 - 中转</div>
          </div>
          <div class="dashboard-card-content">
            <BarCharts
              id="transHour"
              :option="transHourDataOption"
            />
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import CountBox from '@/components/CountBox/index.vue'
import BarCharts from '@/layout/components/Echarts/commonChartsBar.vue'
import MapCharts from '@/layout/components/Echarts/commonChartsChinaMap.vue'
import VueSeamlessScroll from 'vue-seamless-scroll'
import { Query } from '@/api/webApi'
import { parseTime } from '@/utils'
import { getAuthData } from '@/utils/validate'

const defaultDate = parseTime(new Date(), '{y}-{m}-{d}')
// const defaultDate = '2023-06-19'
const barOption = {
  tooltip: {
    trigger: 'axis',
    axisPointer: {
      type: 'shadow',
    },
  },
  grid: {
    left: '3%',
    right: '4%',
    bottom: '3%',
    containLabel: true,
  },
  xAxis: {
    type: 'category',
    data: [],
    axisLabel: {
      color: '#8897BC',
    },
    axisTick: {
      alignWithLabel: true,
    },
  },
  yAxis: {
    type: 'value',
    axisLabel: {
      color: '#8897BC',
    },
  },
  series: [
    {
      data: [],
      type: 'bar',
      barWidth: '16px',
    },
  ],
}

export default {
  name: 'Dashboard',
  components: {
    CountBox,
    BarCharts,
    MapCharts,
    VueSeamlessScroll,
  },
  data() {
    return {
      loading: false,
      arrivalFlightCount: 0,
      departureFlightCount: 0,
      currentAirport: '',
      aiportOptions: [],
      companyData: [],
      customColor: '#478BE7',
      baggageCountItems: [
        {
          title: '行李总数',
          num: 0,
        },
        {
          title: '进港行李数',
          num: 0,
        },
        {
          title: '出港行李数',
          num: 0,
        },
        {
          title: '中转行李数',
          num: 0,
        },
      ],
      boxMap: {
        tooltip: {
          trigger: 'item',
          formatter: function (item) {
            if (item.data && item.data.index) {
              const html = `<div>
              <div>TOP ${item.data.index}</div>
              <div>${item.data.name} ${item.data.value}</div>
            </div>`
              return html
            } else {
              return '<div>暂无数据</div>'
            }
          },
        },
        legend: {
          show: false,
        },
        grid: {
          left: 0,
          right: 0,
          top: 0,
          bottom: 0,
        },
        visualMap: {
          type: 'continuous',
          text: ['高', '低'],
          min: 0,
          max: 20000,
          seriesIndex: [0, 2],
          dimension: 0,
          realtime: false,
          left: 0,
          bottom: '30%',
          itemWidth: 8,
          itemHeight: 93,
          calculable: true,
          inRange: {
            color: ['#869CBC', 'yellow'],
            symbolSize: [100, 100],
          },
          textStyle: {
            color: '#fff',
          },
          outOfRange: {
            color: ['orange'],
            symbolSize: [100, 100],
          },
        },
        toolbox: {
          show: false,
        },
        xAxis: {
          show: false,
        },
        yAxis: {
          show: false,
        },
        series: [
          {
            name: '行李数',
            type: 'map',
            mapType: 'china',
            // left: '100',
            // width: '40%',
            roam: 'move',
            mapValueCalculation: 'sum',
            zoom: 1,
            selectedMode: false,
            showLegendSymbol: false,
            left: '10%',
            top: '10%',
            width: '80%',
            label: {
              normal: {
                textStyle: {
                  color: '#666666',
                },
              },
              emphasis: {
                textStyle: {
                  color: '#234EA5',
                },
              },
            },
            itemStyle: {
              normal: {
                areaColor: '#fff',
                borderColor: '#666666',
              },
              emphasis: {
                areaColor: '#E5F39B',
              },
            },
            data: [],
          },
        ],
      },
      inHourDataOption: this._.cloneDeep(barOption),
      outHourDataOption: this._.cloneDeep(barOption),
      transHourDataOption: this._.cloneDeep(barOption),
      authId: null,
      queryId: null,
    }
  },
  computed: {
    defaultOption() {
      return {
        step: 0.5, // 数值越大速度滚动越快
        limitMoveNum: 2, // 开始无缝滚动的数据量  //this.fourDatata.length
        hoverStop: true, // 是否开启鼠标悬停stop
        direction: 1, // 0向下 1向上 2向左 3向右
        openWatch: true, // 开启数据实时监控刷新dom
        singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
        singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
        waitTime: 1000, // 单步运动停止的时间(默认值1000ms)
      }
    },
  },
  watch: {
    currentAirport(val) {
      if (val) {
        this.getAllData()
      }
    },
  },
  created() {
    this.inHourDataOption.series[0].color = '#3FC9D5'
    this.outHourDataOption.series[0].color = '#527CF5'
    this.transHourDataOption.series[0].color = '#F5C871'
  },
  mounted() {
    const { auth_id } = this.$route.meta
    if (auth_id) {
      const { arrs } = getAuthData(auth_id)
      if (arrs && arrs.length) {
        const obj = arrs[0]
        this.authId = obj.auth_id
        this.queryId = obj.queryTemplateID
      }
    }
    this.getAiportList()
  },
  methods: {
    // 航站列表
    async getAiportList() {
      this.loading = true
      try {
        let params = {
          serviceId: SERVICE_ID.AirportIds,
          dataContent: [],
          pageSize: 9999,
        }
        if (this.queryId) {
          params = {
            ...params,
            authId: this.authId,
            serviceId: this.queryId,
          }
        }
        const {
          code,
          returnData: { listValues },
          message,
        } = await Query(params)
        if (String(code) !== '0') {
          throw new Error(message || '失败')
        }
        this.aiportOptions = listValues.map(aiport => ({
          label: aiport.code3,
          value: aiport.code3,
        }))
        this.currentAirport = 'CAN'
      } catch (error) {
        console.error(error)
      }
      this.loading = false
    },
    // 当日数量和小时数量
    async getDateData(serviceId) {
      try {
        const {
          code,
          returnData: listValues,
          message,
        } = await Query({
          serviceId,
          dataContent: [
            {
              fd1: defaultDate,
              fd2: defaultDate,
              airport: this.currentAirport,
            },
          ],
          pageSize: 9999,
        })
        if (String(code) !== '0') {
          throw new Error(message || '失败')
        }
        return listValues
      } catch (error) {
        console.error(error)
        return []
      }
    },
    // 航司行李量排行
    async getCompanyData() {
      try {
        this.companyData = []
        const {
          code,
          returnData: listValues,
          message,
        } = await Query({
          serviceId: SERVICE_ID.dashboardCompanyData,
          dataContent: [
            {
              airport: this.currentAirport,
              fd1: defaultDate,
              fd2: defaultDate,
            },
          ],
          pageSize: 9999,
        })
        if (String(code) !== '0') {
          throw new Error(message || '失败')
        }
        const max = Math.max(...listValues.map(item => Number(item.bags)))
        this.companyData = listValues.map(item => ({
          name: item.iata_code,
          count: Number(item.bags),
          percentage: max ? (Number(item.bags) / max).toFixed(2) * 100 : 0,
        }))
      } catch (error) {
        console.error(error)
      }
    },
    // 当日行李分布
    async getMap() {
      try {
        const {
          code,
          returnData: listValues,
          message,
        } = await Query({
          serviceId: SERVICE_ID.dashboardMap,
          dataContent: [
            {
              airport: this.currentAirport,
              fd1: defaultDate,
              fd2: defaultDate,
            },
          ],
          pageSize: 9999,
        })
        if (String(code) !== '0') {
          this.boxMap.series[0].data = []
          throw new Error(message || '失败')
        }
        listValues.sort((a, b) => b.bags - a.bags)
        this.boxMap.series[0].data = listValues.map((item, index) => {
          item.name = item.in_province
          item.value = item.bags
          item.index = index + 1
          return item
        })
      } catch (error) {
        console.error(error)
      }
    },
    async getAllData() {
      this.loading = true
      try {
        const serviceIdList = [
          SERVICE_ID.dashboardDateFlightData,
          SERVICE_ID.dashboardDateBaggageData,
          SERVICE_ID.dashboardHourBaggageIn,
          SERVICE_ID.dashboardHourBaggageOut,
          SERVICE_ID.dashboardHourBaggageTrans,
        ]
        const [
          [dateFlightData],
          [dateBaggageData],
          inHourData,
          outHourData,
          transHourData,
        ] = await Promise.all([
          ...serviceIdList.map(id => this.getDateData(id)),
          this.getCompanyData(),
          this.getMap(),
        ])
        this.arrivalFlightCount = Number(dateFlightData?.flights_in ?? 0)
        this.departureFlightCount = Number(dateFlightData?.flights_out ?? 0)
        this.baggageCountItems[0].num = Number(dateBaggageData?.bags ?? 0)
        this.baggageCountItems[1].num = Number(dateBaggageData?.bags_in ?? 0)
        this.baggageCountItems[2].num = Number(dateBaggageData?.bags_out ?? 0)
        this.baggageCountItems[3].num = Number(
          dateBaggageData?.transfer_bags ?? 0
        )
        const sortedInHoutData = this._.sortBy(inHourData, 'dat')
        const sortedOutHoutData = this._.sortBy(outHourData, 'dat')
        const sortedTransHoutData = this._.sortBy(transHourData, 'dat')
        this.inHourDataOption.xAxis.data = sortedInHoutData.reduce(
          (prev, curr) => {
            if ((curr.dat ?? '') !== '') {
              prev.push(`${curr.dat}${curr.dat <= 12 ? 'am' : 'pm'}`)
            }
            return prev
          },
          []
        )
        this.inHourDataOption.series[0].data = sortedInHoutData.reduce(
          (prev, curr) => {
            if ((curr.dat ?? '') !== '') {
              prev.push(Number(curr.bags))
            }
            return prev
          },
          []
        )
        this.outHourDataOption.xAxis.data = sortedOutHoutData.reduce(
          (prev, curr) => {
            if ((curr.dat ?? '') !== '') {
              prev.push(`${curr.dat}${curr.dat <= 12 ? 'am' : 'pm'}`)
            }
            return prev
          },
          []
        )
        this.outHourDataOption.series[0].data = sortedOutHoutData.reduce(
          (prev, curr) => {
            if ((curr.dat ?? '') !== '') {
              prev.push(Number(curr.bags))
            }
            return prev
          },
          []
        )
        this.transHourDataOption.xAxis.data = sortedTransHoutData.reduce(
          (prev, curr) => {
            if ((curr.dat ?? '') !== '') {
              prev.push(`${curr.dat}${curr.dat <= 12 ? 'am' : 'pm'}`)
            }
            return prev
          },
          []
        )
        this.transHourDataOption.series[0].data = sortedTransHoutData.reduce(
          (prev, curr) => {
            if ((curr.dat ?? '') !== '') {
              prev.push(Number(curr.bags))
            }
            return prev
          },
          []
        )
      } catch (error) {
        console.error(error)
      }
      this.loading = false
    },
  },
}
</script>

<style lang="scss" scoped>
.dashboard {
  width: 100%;
  height: calc(100vh - 48px - 32px);
  padding: 16px 20px;
  background-color: #081821;
  color: #fff;
  &-scrollbar {
    margin-right: -20px;
    width: calc(100% + 20px);
    height: 100%;
    overflow-x: hidden;
    overflow-y: auto;
  }
  &-wrapper {
    width: 100%;
    height: 968px;
    display: flex;
    flex-direction: column;
    flex-wrap: wrap;
    justify-content: space-between;
  }
  &-card {
    width: calc((100% - 16px * 2) / 3);
    height: calc((100% - 16px * 2) / 3);
    padding: 25px;
    display: flex;
    flex-direction: column;
    border: 1px solid #3a4456;
    background: linear-gradient(270deg, rgba(118, 142, 184, 0.25), transparent);
    position: relative;
    &::before {
      content: '';
      display: block;
      width: 0;
      height: 0;
      position: absolute;
      top: 0;
      left: 0;
      border: 12px solid #6d7d98;
      border-right-color: transparent;
      border-bottom-color: transparent;
    }
    &-wrapper {
      height: 0;
      flex: 1;
      &:not(:first-child) {
        margin-top: 25px;
      }
    }
    &-title {
      height: 40px;
      line-height: 16px;
      font-size: 16px;
      font-family: Helvetica, Microsoft YaHei;
      font-weight: bold;
    }
    &-content {
      height: calc(100% - 40px);
    }
    &:nth-child(1) {
      .dashboard-card-content {
        max-height: 64px;
      }
    }
    &:nth-child(3) {
      height: 40px;
      padding: 0 25px;
      &::before {
        display: none;
      }
      .dashboard-card-title {
        height: 38px;
        display: flex;
        justify-content: space-between;
        line-height: 38px;
        .el-select {
          width: 120px;
          ::v-deep .el-input__inner {
            border: none;
            background-color: transparent;
            font-size: 16px;
            font-family: Helvetica, Microsoft YaHei;
            font-weight: bold;
            color: #ffffff;
          }
        }
      }
    }
    &:nth-child(4) {
      height: calc((100% - 16px * 2) / 3 - 40px - 16px);
    }
    &:nth-child(2),
    &:nth-child(5) {
      height: calc((100% - 16px * 2) / 3 * 2 + 16px);
    }
    &:nth-child(4) {
      .dashboard-card-content {
        display: flex;
        flex-wrap: wrap;
        justify-content: space-between;
        .baggage-count-item {
          height: 50%;
          padding-left: 96px;
          display: flex;
          flex-direction: column;
          justify-content: center;
          position: relative;
          font-family: Helvetica, Microsoft YaHei;
          font-weight: bold;
          .baggage-count-num {
            width: 120px;
            font-size: 36px;
            color: #f7c15a;
          }
          .baggage-count-title {
            font-size: 14px;
          }
          &::before {
            content: url('../../assets/analysis/ic.png');
            display: block;
            width: 72px;
            height: 72px;
            position: absolute;
            top: 50%;
            left: 0;
            transform: translate(0, -50%);
          }
        }
      }
    }
    &:nth-child(5) {
      background: transparent;
      border: none;
      &::before {
        display: none;
      }
    }
  }
  .scroll-table {
    height: 100%;
    overflow: hidden;
    .company-baggage-item {
      margin-top: 36px;
      display: flex;
      align-items: center;
      font-size: 14px;
      font-family: Helvetica;
      font-weight: bold;
      color: #ffffff;
      .company-progress {
        flex: 1;
        margin: 0 23px;
      }
      ::v-deep .progress {
        flex: 1;
        margin: 0 36px;
        .el-progress-bar {
          padding-right: 0;
          .el-progress-bar__outer {
            background-color: #534e75;
          }
        }
        .el-progress__text {
          display: none;
        }
      }
    }
  }
}
</style>
