123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537 |
- <template>
- <div class="dashboard">
- <ComHead :tabs-index="0" />
- <div class="dashboard-content">
- <div class="dashboard-content-top flex">
- <div class="dashboard-content-top-left">
- <div class="dashboard-content-top-left-item">
- <div class="dashboard-content-top-left-item-top">
- <div class="dashboard-content-top-left-item-top-title">
- 小时峰值分析
- </div>
- <div class="dashboard-content-top-left-item-top-time" @click="showDatePicker(showTimeMsg.HourlyPeak)">
- <el-icon color="#ffffff" size="18">
- <Calendar />
- </el-icon>
- <el-icon color="#ffffff">
- <CaretBottom />
- </el-icon>
- </div>
- </div>
- <div v-loading="loading1" element-loading-text="数据加载中..." element-loading-svg-view-box="-10, -10, 50, 50" element-loading-background="rgba(0,0,0, 0.3)" class="dashboard-content-top-left-item-bottom">
- <Echarts id="ww1" :option="hourlyPeakObj" />
- </div>
- </div>
- <div class="dashboard-content-top-left-item">
- <div class="dashboard-content-top-left-item-top">
- <div class="dashboard-content-top-left-item-top-title">
- 日趋势分析
- </div>
- <div class="dashboard-content-top-left-item-top-time" @click="showDatePicker(showTimeMsg.WaybillTrend)">
- <el-icon color="#ffffff" size="18">
- <Calendar />
- </el-icon>
- <el-icon color="#ffffff">
- <CaretBottom />
- </el-icon>
- </div>
- </div>
- <div v-loading="loading2" element-loading-text="数据加载中..." element-loading-svg-view-box="-10, -10, 50, 50" element-loading-background="rgba(0,0,0, 0.3)" class="dashboard-content-top-left-item-bottom">
- <Echarts id="ww12" :option="waybillTrendObj" />
- </div>
- </div>
- <div class="dashboard-content-top-left-item">
- <div class="dashboard-content-top-left-item-top">
- <div class="dashboard-content-top-left-item-top-title">
- 目的站统计分析
- </div>
- <div class="dashboard-content-bottom-left-top-time" @click="showDatePicker(showTimeMsg.NodePeak)">
- <el-icon color="#ffffff" size="18">
- <Calendar />
- </el-icon>
- <el-icon color="#ffffff">
- <CaretBottom />
- </el-icon>
- </div>
- </div>
- <div v-loading="loading3" element-loading-text="数据加载中..." element-loading-svg-view-box="-10, -10, 50, 50" element-loading-background="rgba(0,0,0, 0.3)" class="dashboard-content-top-left-item-bottom">
- <Echarts id="ww4" :option="nodePeakObj" />
- </div>
- </div>
- </div>
- <!-- 地图 -->
- <div class="dashboard-content-top-center">
- <div v-loading="loading4" element-loading-text="数据加载中..." element-loading-svg-view-box="-10, -10, 50, 50" element-loading-background="rgba(0,0,0, 0.3)" class="dashboard-content-top-center-top">
- <div class="dashboard-content-top-center-top-list">
- <div class="dashboard-content-top-center-top-list-txt">今日计划航班数</div>
- <div class="dashboard-content-top-center-top-list-num">{{ flightNums }}</div>
- </div>
- <div class="dashboard-content-top-center-top-list">
- <div class="dashboard-content-top-center-top-list-txt">已完成航班数</div>
- <div class="dashboard-content-top-center-top-list-num">{{ stockNums }}</div>
- </div>
- <div class="dashboard-content-top-center-top-list">
- <div class="dashboard-content-top-center-top-list-txt">已装载总量(吨)</div>
- <div class="dashboard-content-top-center-top-list-num">{{ formatWeight(weightNums) }}</div>
- </div>
- </div>
- <div v-loading="loading5" element-loading-text="数据加载中..." element-loading-svg-view-box="-10, -10, 50, 50" element-loading-background="rgba(0,0,0, 0.3)" class="dashboard-content-top-center-bottom">
- <div class="dashboard-content-top-center-bottom-title">航班动态跟踪</div>
- <div class="dashboard-content-top-center-bottom-content">
- <div class="dashboard-content-top-center-bottom-content-head">
- <div class="dashboard-content-top-center-bottom-content-head-list">公司/航班号</div>
- <div class="dashboard-content-top-center-bottom-content-head-list">航班状态</div>
- <div class="dashboard-content-top-center-bottom-content-head-list">经停/到达站</div>
- <div class="dashboard-content-top-center-bottom-content-head-list">计划起飞</div>
- <div class="dashboard-content-top-center-bottom-content-head-list">预飞时间</div>
- <div class="dashboard-content-top-center-bottom-content-head-list">机型</div>
- <div class="dashboard-content-top-center-bottom-content-head-list">类型</div>
- </div>
- <div ref="scrollContent" class="dashboard-content-top-center-bottom-content-bottom">
- <vue3-seamless-scroll :list="listData" :limitScrollNum="limitScrollNum" :hover-stop="true" :hover="true" :step="0.3">
- <div v-for="(item,index) in listData" :key="index" class="dashboard-content-top-center-bottom-content-bottom-list">
- <div class="dashboard-content-top-center-bottom-content-bottom-list-txt">{{ item.flightNo }}</div>
- <div class="dashboard-content-top-center-bottom-content-bottom-list-txt">{{ item.flightState }}</div>
- <div class="dashboard-content-top-center-bottom-content-bottom-list-txt">{{ item.airport }}</div>
- <div class="dashboard-content-top-center-bottom-content-bottom-list-txt">{{ item.planTime }}</div>
- <div class="dashboard-content-top-center-bottom-content-bottom-list-txt">--</div>
- <div class="dashboard-content-top-center-bottom-content-bottom-list-txt">{{ item.planeType }}</div>
- <div class="dashboard-content-top-center-bottom-content-bottom-list-txt">{{ item.KHT }}</div>
- </div>
- </vue3-seamless-scroll>
- </div>
- </div>
- </div>
- </div>
- <div class="dashboard-content-top-right">
- <div class="dashboard-content-top-right-item">
- <div class="dashboard-content-top-right-item-top">
- <div class="dashboard-content-top-right-item-top-title">
- 航司统计分析
- </div>
- <div class="dashboard-content-top-right-item-top-time" @click="showDatePicker(showTimeMsg.AirlineTraffic)">
- <el-icon color="#ffffff" size="18">
- <Calendar />
- </el-icon>
- <el-icon color="#ffffff">
- <CaretBottom />
- </el-icon>
- </div>
- </div>
- <div v-loading="loading6" element-loading-text="数据加载中..." element-loading-svg-view-box="-10, -10, 50, 50" element-loading-background="rgba(0,0,0, 0.3)" class="dashboard-content-top-right-item-bottom">
- <Echarts id="a1" :option="airlineTrafficObj" />
- </div>
- </div>
- <div class="dashboard-content-top-right-item">
- <div class="dashboard-content-top-right-item-top">
- <div class="dashboard-content-top-right-item-top-title">
- 特货分类统计
- </div>
- <div class="dashboard-content-top-right-item-top-time">
- <el-dropdown trigger="click" @command="handleCommand">
- <span class="icons">
- <span class="icons-txt">{{ specialGoods }}</span>
- <el-icon color="#ffffff">
- <CaretBottom />
- </el-icon>
- </span>
- <template #dropdown>
- <el-dropdown-menu>
- <el-dropdown-item v-for="(item,index) in specialGoodsDatas" :key="index" :command="item.specialTypeName">{{ item.specialTypeName }}</el-dropdown-item>
- </el-dropdown-menu>
- </template>
- </el-dropdown>
- </div>
- </div>
- <div v-loading="loading7" element-loading-text="数据加载中..." element-loading-svg-view-box="-10, -10, 50, 50" element-loading-background="rgba(0,0,0, 0.3)" class="dashboard-content-top-left-item-bottom">
- <Echarts id="ww44" :option="airlineObj" />
- </div>
- </div>
- <div class="dashboard-content-top-right-item">
- <div class="dashboard-content-top-right-item-top">
- <div class="dashboard-content-top-right-item-top-title">
- 拉货统计分析
- </div>
- <div class="dashboard-content-top-right-item-top-time" @click="showDatePicker(showTimeMsg.PickingStatistics)">
- <el-icon color="#ffffff" size="18">
- <Calendar />
- </el-icon>
- <el-icon color="#ffffff">
- <CaretBottom />
- </el-icon>
- </div>
- </div>
- <div v-loading="loading8" element-loading-text="数据加载中..." element-loading-svg-view-box="-10, -10, 50, 50" element-loading-background="rgba(0,0,0, 0.3)" class="dashboard-content-top-left-item-bottom">
- <Echarts id="ww45" :option="pickingObj" />
- </div>
- </div>
- </div>
- </div>
- </div>
- <Dialog :flag="flag" msg-title="日期选择" @resetForm="resetForm" @submitForm="submitForm">
- <el-form :model="form" label-width="120px">
- <el-form-item label="开始日期">
- <el-date-picker :disabled-date="disabledStartDate" v-model="form.startDate" type="date" placeholder="请选择开始日期" size="default" format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
- </el-form-item>
- <el-form-item label="结束日期">
- <el-date-picker :disabled-date="disabledEndDate" v-model="form.endDate" type="date" placeholder="请选择结束日期" size="default" format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
- </el-form-item>
- </el-form>
- </Dialog>
- </div>
- </template>
- <script setup lang="ts">
- import { ref, onMounted } from "vue";
- import { Vue3SeamlessScroll } from "vue3-seamless-scroll";
- import Echarts from "@/components/Echarts/commonChartsBar.vue";
- import ComHead from "./components/comHead.vue";
- import { Calendar, CaretBottom } from "@element-plus/icons-vue";
- import Dialog from "@/components/dialog/index.vue";
- import { usePublic, showTimeMsg } from "./hooks/usePublic";
- import nodeCode from "./hooks/nodeCode";
- import { parseTime, isValue } from "@/utils/validate";
- import * as _ from "lodash";
- const {
- optionLeft,
- airCompaneBaggage,
- airlineAbnormalBaggage,
- getPublicData,
- formatGoods,
- formatWeight,
- } = usePublic();
- const timePickerName = ref<number>(0);
- const limitScrollNum = ref<number>(13);
- const scrollContent = ref<HTMLElement>();
- const flag = ref<boolean>(false);
- const loading1 = ref<boolean>(false);
- const loading2 = ref<boolean>(false);
- const loading3 = ref<boolean>(false);
- const loading4 = ref<boolean>(false);
- const loading5 = ref<boolean>(false);
- const loading6 = ref<boolean>(false);
- const loading7 = ref<boolean>(false);
- const loading8 = ref<boolean>(false);
- const hourlyPeakObj = ref<any>({});
- const waybillTrendObj = ref<any>({});
- const nodePeakObj = ref<any>({});
- const airlineTrafficObj = ref<any>({});
- const airlineObj = ref<any>({});
- const pickingObj = ref<any>({});
- const flightNums = ref<number>(0);
- const stockNums = ref<number>(0);
- const specialGoods = ref<string>("");
- const specialGoodsDatas = ref<any>([]);
- const specialGoodsAll = ref<any>([]);
- const weightNums = ref<number | string>(0);
- const form = ref({
- startDate: parseTime(Date.now() - 24 * 60 * 60 * 1000 * 7, "{y}-{m}-{d}"),
- endDate: parseTime(Date.now(), "{y}-{m}-{d}"),
- });
- const dateNow = ref({
- time: parseTime(Date.now(), "{y}-{m}-{d}"),
- });
- const listData = ref<any>([]);
- const disabledStartDate = (time: Date) => {
- const timer: any = form.value.endDate;
- const data = new Date(timer);
- return time.getTime() > data.getTime();
- };
- const disabledEndDate = (time: Date) => {
- const timer: any = form.value.startDate;
- let data = new Date(timer);
- return data.getTime() > time.getTime();
- };
- const resetForm = () => {
- flag.value = false;
- };
- const submitForm = () => {
- flag.value = false;
- switch (timePickerName.value) {
- case showTimeMsg.HourlyPeak:
- dateNow.value.time = form.value.startDate;
- hourlyPeakFunc();
- break;
- case showTimeMsg.WaybillTrend:
- waybillTrendFunc();
- break;
- case showTimeMsg.NodePeak:
- nodePeakFunc();
- break;
- case showTimeMsg.AirlineTraffic:
- airlineTrafficFunc();
- break;
- case showTimeMsg.AirlineAbnormal:
- airlineFunc();
- break;
- case showTimeMsg.PickingStatistics:
- pickingFuncs();
- break;
- default:
- break;
- }
- };
- const showDatePicker = (id?) => {
- flag.value = true;
- timePickerName.value = id;
- };
- const sortClass = (sortData) => {
- const groupBy = (array, f) => {
- let groups = {};
- array.forEach((o) => {
- let group = JSON.stringify(f(o));
- groups[group] = groups[group] || [];
- groups[group].push(o);
- });
- return Object.keys(groups).map((group) => {
- return groups[group];
- });
- };
- const sorted = groupBy(sortData, (item) => {
- return item.jobName;
- });
- return sorted;
- };
- const pubFunc = (listValues, target, type?) => {
- const newObj = _.cloneDeep(target);
- const [jobTimes, stockNums, weights] = [<any>[], <any>[], <any>[]];
- listValues.forEach((item) => {
- jobTimes.push(item.jobTime);
- stockNums.push(item.stockNum);
- weights.push(item.weight);
- });
- newObj.xAxis.data = jobTimes;
- if (type) {
- newObj.series[1].data = stockNums;
- newObj.series[0].data = weights;
- } else {
- newObj.series[0].data = stockNums;
- newObj.series[1].data = weights;
- }
- return newObj;
- };
- const parseDate = (date: string) => {
- const dates = date.split("-");
- const newDate = dates.shift();
- return dates.join("-");
- };
- // 特货分类统计-选取下拉数据
- const handleCommand = (command: string) => {
- specialGoods.value = command;
- const newObj: any = _.cloneDeep(airlineAbnormalBaggage.option.baseOption);
- const result = formatGoods(command, specialGoodsAll.value);
- airlineObj.value = pubFunc(result, newObj);
- };
- //获取小时峰值分布
- const hourlyPeakFunc = async () => {
- loading1.value = true;
- const listValues = (await getPublicData(DATACONTENT_ID.jscHourlyPeakId, [
- { flightDate1: dateNow.value.time, flightDate2: form.value.endDate },
- ])) as any;
- if (listValues && isValue(listValues)) {
- hourlyPeakObj.value = pubFunc(listValues, optionLeft, true);
- }
- loading1.value = false;
- };
- //运单趋势分析
- const waybillTrendFunc = async () => {
- loading2.value = true;
- const listValues = (await getPublicData(DATACONTENT_ID.jscWaybillTrendId, [
- { flightDate1: form.value.startDate, flightDate2: form.value.endDate },
- ])) as any;
- if (listValues && isValue(listValues)) {
- listValues.forEach((item) => {
- item.jobTime = parseDate(item["jobTime"]);
- });
- waybillTrendObj.value = pubFunc(listValues, optionLeft, true);
- }
- loading2.value = false;
- };
- //始发站/目的站统计分析
- const nodePeakFunc = async () => {
- loading3.value = true;
- const listValues = (await getPublicData(DATACONTENT_ID.jscAirlineAbnormalId, [
- { fd1: form.value.startDate, fd2: form.value.endDate, fttp: "国内离港" },
- ])) as any;
- if (listValues && isValue(listValues)) {
- const newObj = _.cloneDeep(airCompaneBaggage.option.baseOption);
- listValues.forEach((item) => {
- item.jobTime = item["airport"];
- });
- nodePeakObj.value = pubFunc(listValues, newObj, true);
- }
- loading3.value = false;
- };
- //航班数&运单数
- const numbersFunc = async () => {
- loading4.value = true;
- const listValues = (await getPublicData(DATACONTENT_ID.jscNumbersId, [
- {
- fd1: parseTime(Date.now(), "{y}-{m}-{d}"),
- fd2: parseTime(Date.now(), "{y}-{m}-{d}"),
- },
- ])) as any;
- if (listValues && isValue(listValues)) {
- const { flightNum, finishFlightNum, weight } = listValues[0];
- flightNums.value = flightNum ?? 0;
- stockNums.value = finishFlightNum ?? 0;
- weightNums.value = weight ?? 0;
- }
- loading4.value = false;
- };
- //航司运量
- const airlineTrafficFunc = async () => {
- loading6.value = true;
- const listValues = (await getPublicData(DATACONTENT_ID.jscAirlineTrafficId, [
- { flightDate1: form.value.startDate, flightDate2: form.value.endDate },
- ])) as any;
- if (listValues && isValue(listValues)) {
- const newObj: any = _.cloneDeep(airCompaneBaggage.option.baseOption);
- (newObj.dataZoom = [
- {
- id: "dataZoomX",
- type: "slider",
- xAxisIndex: [0],
- filterMode: "filter",
- start: 0,
- end: 20,
- },
- ]),
- listValues.forEach((item) => {
- item.jobTime = item["IACACode"];
- });
- airlineTrafficObj.value = pubFunc(listValues, newObj, true);
- }
- loading6.value = false;
- };
- //航班表格
- const airlineAbnormalFunc = async () => {
- loading5.value = true;
- const listValues = (await getPublicData(DATACONTENT_ID.jscFlightDynamicsId, [
- {
- fd1: parseTime(Date.now(), "{y}-{m}-{d}"),
- fd2: parseTime(Date.now(), "{y}-{m}-{d}"),
- fttp: "国内离港",
- },
- ])) as any;
- const domHeight = scrollContent.value?.clientHeight;
- if (domHeight && typeof domHeight == "number") {
- const cell = Math.ceil(domHeight / 40);
- limitScrollNum.value = cell;
- }
- if (listValues && isValue(listValues)) {
- listData.value = listValues;
- }
- loading5.value = false;
- };
- //航班动态统计
- // const airlineFunc = async () => {
- // loading7.value = true;
- // const listValues = (await getPublicData(DATACONTENT_ID.jscAirlineId, [
- // {
- // fd1: form.value.startDate,
- // fd2: form.value.endDate,
- // },
- // ])) as any;
- // if (listValues && isValue(listValues)) {
- // const res = findData(
- // nodeCode.departure,
- // listValues,
- // "nodeCode",
- // "flightNum"
- // );
- // const newObj: any = _.cloneDeep(airlineAbnormalBaggage.option.baseOption);
- // (newObj.dataZoom = [
- // {
- // id: "dataZoomX",
- // type: "slider",
- // xAxisIndex: [0],
- // filterMode: "filter",
- // start: 0,
- // end: 40,
- // },
- // ]),
- // res.forEach((item) => {
- // item.jobTime = item["name"] ?? item["nodeCode"];
- // item.weight = item["flightNum"];
- // });
- // airlineObj.value = pubFunc(res, newObj);
- // }
- // loading7.value = false;
- // };
- //特货分类统计
- const airlineFunc = async () => {
- loading7.value = true;
- const listValues = (await getPublicData(DATACONTENT_ID.jscGoodsId, [
- {
- fd1: form.value.startDate,
- fd2: form.value.endDate,
- fttp: "国内离港",
- },
- ])) as any;
- if (listValues && isValue(listValues)) {
- const newObj: any = _.cloneDeep(airlineAbnormalBaggage.option.baseOption);
- const newDatas = _.cloneDeep(listValues);
- const nameDatas = _.unionBy(newDatas, "specialTypeName");
- const names: any = [...nameDatas];
- specialGoods.value = names[0]["specialTypeName"];
- specialGoodsDatas.value = names;
- specialGoodsAll.value = listValues;
- const result = formatGoods(
- names[0]["specialTypeName"],
- specialGoodsAll.value
- );
- airlineObj.value = pubFunc(result, newObj);
- }
- loading7.value = false;
- };
- //拉货统计
- const pickingFuncs = async () => {
- loading8.value = true;
- const listValues = (await getPublicData(DATACONTENT_ID.jscGgPullId, [
- {
- fd1: form.value.startDate,
- fd2: form.value.endDate,
- },
- ])) as any;
- if (listValues && isValue(listValues)) {
- const newObj: any = _.cloneDeep(airlineAbnormalBaggage.option.baseOption);
- listValues.forEach((item) => {
- item.jobTime = parseDate(item["flightDate"]);
- item.weight = item["flightNum"];
- });
- pickingObj.value = pubFunc(listValues, newObj);
- }
- loading8.value = false;
- };
- onMounted(() => {
- hourlyPeakFunc();
- waybillTrendFunc();
- nodePeakFunc();
- numbersFunc();
- airlineTrafficFunc();
- airlineAbnormalFunc();
- airlineFunc();
- pickingFuncs();
- });
- </script>
- <style lang="scss" scoped>
- @import "./css/index.scss";
- </style>
|