zhaoke 2 жил өмнө
parent
commit
325bd1dbb5

+ 44 - 36
src/router/index.js

@@ -6,18 +6,19 @@
  * @Description: In User Settings Edit
  * @FilePath: \Foshan4A\src\router\index.js
  */
-import Vue from 'vue'
-import Router from 'vue-router'
-import store from '@/store'
+import Vue from "vue";
+import Router from "vue-router";
+import store from "@/store";
 
-Vue.use(Router)
+Vue.use(Router);
 
 /* Layout */
 // import Layout from '@/layout'
-import routesOne from './routes/routes-file-one'
-import routesTwo from './routes/routes-file-two'
-import routesThree from './routes/routes-file-three'
-import routesFileFour from './routes/routes-file-four'
+import routesOne from "./routes/routes-file-one";
+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";
 /**
  * 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
@@ -38,11 +39,11 @@ import routesFileFour from './routes/routes-file-four'
  */
 
 const routesPush = (arr, routes) => {
-  if (!Array.isArray(arr)) return '请传入数组格式路由表'
+  if (!Array.isArray(arr)) return "请传入数组格式路由表";
   for (let i = 0; i < arr.length; i++) {
-    routes.unshift(arr[i])
+    routes.unshift(arr[i]);
   }
-}
+};
 
 /**
  * constantRoutes
@@ -51,71 +52,78 @@ const routesPush = (arr, routes) => {
  */
 export const constantRoutes = [
   {
-    path: '/login',
-    component: () => import('@/views/login/index'),
-    hidden: true
+    path: "/login",
+    component: () => import("@/views/login/index"),
+    hidden: true,
   },
   {
-    path: '/404',
-    component: () => import('@/views/404'),
-    hidden: true
-  }
+    path: "/404",
+    component: () => import("@/views/404"),
+    hidden: true,
+  },
   // { path: '/', redirect: '/nopower', component: () => import('@/views/noPower'), hidden: true }
   // 404 page must be placed at the end !!!
-]
+];
 
 // 动态路由
-export const asyncRoutes = []
+export const asyncRoutes = [];
 // 插入路由
 routesPush(
   [
     ...routesOne,
     ...routesTwo,
     ...routesThree,
-    ...routesFileFour
+    ...routesFileFour,
+    ...routesFive,
   ],
   asyncRoutes
-)
+);
 // asyncRoutes.push({ path: '/', component: () => import('@/views/noPower'), hidden: true })
-asyncRoutes.push({ path: '*', component: () => import('@/views/404'), hidden: true })
+asyncRoutes.push({
+  path: "*",
+  component: () => import("@/views/404"),
+  hidden: true,
+});
 
 const createRouter = () =>
   new Router({
     // mode: 'history', // require service support
     scrollBehavior: () => ({ y: 0 }),
-    routes: constantRoutes
-  })
+    routes: constantRoutes,
+  });
 
-const router = createRouter()
+const router = createRouter();
 
 router.beforeEach((to, from, next) => {
   // 如果 要 from(离开) 的页面是 keepAlive缓存的,
   // 再根据 deepth 来判断是前进还是后退
   if (from.meta.keepAlive) {
     if (to.meta.deepth && to.meta.deepth > from.meta.deepth) {
-      store.dispatch('keepAlive/editPage', from)
+      store.dispatch("keepAlive/editPage", from);
     } else {
-      store.dispatch('keepAlive/deletePage', to)
+      store.dispatch("keepAlive/deletePage", to);
     }
   }
   // 如果要to(进入)的页面是需要keepAlive缓存的,把name push进keepAlive数组中
   if (to.meta.keepAlive) {
-    const currentPage = store.state.keepAlive.keepAlivePages.find(page => page.name === to.name)
+    const currentPage = store.state.keepAlive.keepAlivePages.find(
+      (page) => page.name === to.name
+    );
     if (currentPage) {
       if (currentPage.fullPath !== to.fullPath) {
-        next(currentPage.fullPath)
+        next(currentPage.fullPath);
       }
     } else {
-      store.dispatch('keepAlive/addPage', to)
+      store.dispatch("keepAlive/addPage", to);
     }
   }
-  next()
-})
+  next();
+});
 
 // Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
 export function resetRouter() {
-  const newRouter = createRouter()
-  router.matcher = newRouter.matcher // reset router
+  const newRouter = createRouter();
+  router.matcher = newRouter.matcher; // reset router
 }
 
-export default router
+export default router;

+ 83 - 0
src/router/routes/routes-file-five.js

@@ -0,0 +1,83 @@
+/*
+ * @Author: zk
+ * @Date: 2022-01-17 10:40:48
+ * @LastEditTime: 2022-03-09 17:28:35
+ * @LastEditors: your name
+ * @Description: 离港路由
+ */
+import Layout from "@/layout";
+
+const auditRoutes = {
+  path: "/departure",
+  component: Layout,
+  meta: { roles: ["departure_menu"] },
+  children: [
+    {
+      path: "/departure",
+      component: () => import("@/views/baggageManagement"),
+      meta: {
+        title: "离港管理",
+        imgstyle: "ic_list_nav_leave_default.png",
+        imgstyleup: "ic_list_nav_leave_check.png",
+      },
+      children: [
+        {
+          path: "/departure",
+          name: "DepartureOne",
+          component: () => import("@/views/baggageManagement"),
+          meta: {
+            // title: "离港视图",
+            title: "行李视图",
+            roles: ["departure_page"],
+            keepAlive: true,
+            deepth: 1,
+          },
+          // redirect: "/departure/terminalView",
+          redirect: "/departure/baggageView",
+          children: [
+            {
+              path: "/departure/baggageView",
+              name: "DepartureBaggageView",
+              component: () =>
+                import(
+                  "@/views/baggageManagement/components/departure/baggage"
+                ),
+              meta: { keepAlive: true, deepth: 2 },
+            },
+            // {
+            //   path: '/departure/terminalView',
+            //   name: 'DepartureTerminalView',
+            //   component: () => import('@/views/baggageManagement/components/departure'),
+            //   meta: { keepAlive: true, deepth: 2 }
+            // },
+            {
+              path: "/departure/flightView",
+              name: "DepartureTwo",
+              component: () => import("@/views/baggageManagement"),
+              meta: { title: "航班视图", keepAlive: true, deepth: 2 },
+              children: [
+                {
+                  path: "/departure/flightView",
+                  name: "DepartureFlightView",
+                  component: () =>
+                    import(
+                      "@/views/baggageManagement/components/departure/flight"
+                    ),
+                  meta: { keepAlive: true, deepth: 3 },
+                },
+                // {
+                //   path: '/departure/baggageView',
+                //   name: 'DepartureBaggageView',
+                //   component: () => import('@/views/baggageManagement/components/departure/baggage'),
+                //   meta: { title: '行李视图', keepAlive: true, deepth: 4 }
+                // }
+              ],
+            },
+          ],
+        },
+      ],
+    },
+  ],
+};
+
+export default [auditRoutes];

+ 27 - 0
src/views/baggageManagement/components/arrival/baggage.vue

@@ -0,0 +1,27 @@
+<!--
+ * @Author: Badguy
+ * @Date: 2022-03-09 11:51:26
+ * @LastEditTime: 2022-03-09 11:51:26
+ * @LastEditors: your name
+ * @Description: 进港行李视图
+ * have a nice day!
+-->
+
+<template>
+  <BaggageView />
+</template>
+
+<script>
+import BaggageView from '../baggage'
+
+export default {
+  name: 'ArrivalBaggageView',
+  components: {
+    BaggageView
+  }
+}
+</script>
+
+<style>
+
+</style>

+ 27 - 0
src/views/baggageManagement/components/arrival/flight.vue

@@ -0,0 +1,27 @@
+<!--
+ * @Author: Badguy
+ * @Date: 2022-03-09 11:49:13
+ * @LastEditTime: 2022-03-09 11:50:43
+ * @LastEditors: your name
+ * @Description: 进港行李视图
+ * have a nice day!
+-->
+
+<template>
+  <FlightView />
+</template>
+
+<script>
+import FlightView from '../flight'
+
+export default {
+  name: 'ArrivalFlightView',
+  components: {
+    FlightView
+  }
+}
+</script>
+
+<style>
+
+</style>

+ 524 - 0
src/views/baggageManagement/components/arrival/index.vue

@@ -0,0 +1,524 @@
+<!--
+ * @Author: zk
+ * @Date: 2022-01-17 10:39:22
+ * @LastEditTime: 2022-03-15 16:26:13
+ * @LastEditors: your name
+ * @Description: 进港01
+-->
+<template>
+  <div class="arrival-one">
+    <!--功能区-表单-->
+    <div class="arrival-form">
+      <el-form
+        ref="form"
+        :inline="true"
+        :model="formData"
+        :rules="rules"
+        class="form"
+      >
+        <el-form-item prop="currentAirport">
+          <el-cascader
+            v-model="formData.currentAirport"
+            style="width:144px;"
+            placeholder="全部机场"
+            size="small"
+            :options="currentAirportOptions"
+            :props="currentAirportProps"
+            collapse-tags
+            clearable
+            filterable
+            @change="setCurrentAirport"
+          />
+        </el-form-item>
+        <el-form-item prop="relatedAirport">
+          <el-cascader
+            v-model="formData.relatedAirport"
+            style="width:136px;"
+            size="small"
+            :options="relatedAirportOptions"
+            :props="relatedAirportProps"
+            placeholder="全部起飞站"
+            collapse-tags
+            clearable
+            filterable
+            @change="onSubmit"
+          />
+        </el-form-item>
+        <el-form-item prop="inboundCarrier">
+          <el-cascader
+            v-model="formData.inboundCarrier"
+            style="width:164px;"
+            size="small"
+            :options="inboundCarrierOptions"
+            :props="inboundCarrierProps"
+            placeholder="全部航司"
+            collapse-tags
+            clearable
+            filterable
+            @change="onSubmit"
+          />
+        </el-form-item>
+        <el-form-item prop="craftType">
+          <el-cascader
+            v-model="formData.craftType"
+            style="width:120px;"
+            size="small"
+            :options="craftTypeOptions"
+            :props="craftTypeProps"
+            placeholder="全部机型"
+            collapse-tags
+            clearable
+            filterable
+            @change="onSubmit"
+          />
+        </el-form-item>
+        <el-form-item prop="flightAttr">
+          <el-cascader
+            v-model="formData.flightAttr"
+            style="width:120px;"
+            size="small"
+            :options="flightAttrOptions"
+            :props="flightAttrProps"
+            placeholder="国际/国内"
+            collapse-tags
+            clearable
+            filterable
+            @change="onSubmit"
+          />
+        </el-form-item>
+        <el-form-item prop="startDate">
+          <el-date-picker
+            v-model="formData.startDate"
+            style="width:216px;"
+            size="small"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="开始时间"
+            @change="setStartDate"
+          />
+        </el-form-item>
+        <el-form-item prop="endDate">
+          <el-date-picker
+            v-model="formData.endDate"
+            style="width:216px;"
+            size="small"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="结束时间"
+            @change="setEndDate"
+          />
+        </el-form-item>
+        <el-form-item prop="search">
+          <el-input
+            v-model="formData.search"
+            style="width:240px;margin-left:105px;"
+            size="small"
+            placeholder="请输入内容"
+            prefix-icon="el-icon-search"
+            clearable
+            @clear="inputClear"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button
+            size="small"
+            type="primary"
+            @click="onSubmit"
+          >搜索</el-button>
+        </el-form-item>
+        <el-form-item v-is="['i_showTransit']">
+          <el-switch
+            v-model="formData.switch"
+            style="margin-left:40px;"
+            active-text="显示中转"
+          />
+        </el-form-item>
+        <el-form-item v-is="['i_timeIcon']">
+          <el-dropdown>
+            <img
+              class="checkTime msgImg"
+              src="../../../../assets/departure/ic_time.png"
+            >
+            <el-dropdown-menu
+              slot="dropdown"
+              class="time-zone"
+            >
+              <el-dropdown-item>国内Local/国际UTC</el-dropdown-item>
+              <el-dropdown-item>Local</el-dropdown-item>
+              <el-dropdown-item>UTC</el-dropdown-item>
+            </el-dropdown-menu>
+          </el-dropdown>
+        </el-form-item>
+        <el-form-item v-is="['i_columnSettings']">
+          <img
+            class="msgImg"
+            src="../../../../assets/departure/ic_setting.png"
+            @click="show"
+          >
+        </el-form-item>
+      </el-form>
+    </div>
+    <!--表格-->
+    <div
+      v-loading="loading"
+      class="arrival-table"
+      element-loading-text="拼命加载中"
+      element-loading-spinner="el-icon-loading"
+      element-loading-background="rgba(0, 0, 0, 0.8)"
+    >
+      <el-table
+        ref="table"
+        :row-class-name="tableRowClassName"
+        :data="tableData"
+        class="table"
+        :height="computedTableHeight"
+        show-summary
+        :summary-method="summaryMethod"
+        border
+        stripe
+        @row-click="rowClick"
+      >
+        <el-table-column
+          v-for="(item,index) in tableColsCopy"
+          :key="index"
+          :prop="item.statCode"
+          :label="item.statName"
+        >
+          <el-table-column
+            v-for="(p,i) in item.children"
+            :key="i"
+            :prop="p.statCode"
+            :label="p.statName"
+            :width="item.width"
+            :formatter="tableFormat"
+          />
+        </el-table-column>
+      </el-table>
+    </div>
+    <!--列设置-->
+    <Dialog
+      :flag="dialogFlag"
+      class="dialog-check-cols"
+    >
+      <div class="col-dialog">
+        <div class="title">列设置</div>
+        <div class="content">
+          <el-tree
+            :data="tableCols"
+            :class="colsCheckClass"
+            show-checkbox
+            node-key="index"
+            :default-expand-all="true"
+            :props="{
+              label: 'statName',
+              children: 'children'
+            }"
+            :default-checked-keys="checkedKeysTemp"
+            @check="handleCheck"
+          />
+        </div>
+        <div class="foot right t30">
+          <el-button
+            size="medium"
+            class="r24"
+            type="primary"
+            @click="onCheck"
+          >确定</el-button>
+          <el-button
+            size="medium"
+            @click="hide"
+          >取消</el-button>
+        </div>
+      </div>
+    </Dialog>
+  </div>
+</template>
+
+<script>
+import Dialog from '@/layout/components/Dialog'
+import terminalMixin from '../../mixins/terminal'
+import formMixin from '../../mixins/form'
+import tableColsMixin from '../../mixins/tableCols'
+
+export default {
+  name: 'ArrivalTerminalView',
+  components: { Dialog },
+  mixins: [terminalMixin, formMixin, tableColsMixin],
+  data() {
+    return {
+      // 初始表头
+      tableCols: [
+        {
+          statCode: 'flightInfo',
+          statName: '航班信息',
+          children: [
+            {
+              statCode: 'FlightNO',
+              statName: '航班号',
+              width: 91
+            },
+            {
+              statCode: 'FlightDate',
+              statName: '执飞日期',
+              width: 105
+            },
+            {
+              statCode: 'PlanLandingTime',
+              statName: '到港时间',
+              width: 115
+            },
+            {
+              statCode: 'PlanDepartureApt',
+              statName: '起飞航站',
+              width: 71
+            },
+            {
+              statCode: 'LandingBuild',
+              statName: '到达航站楼',
+              width: 65
+            },
+            {
+              statCode: 'Carousel',
+              statName: '行李转盘',
+              width: 68
+            },
+            {
+              statCode: 'StandForLanding',
+              statName: '停机位',
+              width: 68
+            }
+          ]
+        },
+        {
+          statCode: 'depatureInfo',
+          statName: '始飞站行李信息',
+          children: [
+            {
+              statCode: 'checkin',
+              statName: '值机',
+              width: 72
+            },
+            {
+              statCode: 'expect_load',
+              statName: '预计装载',
+              width: 101
+            },
+            {
+              statCode: 'loadflight',
+              statName: '已装载',
+              width: 65
+            }
+          ]
+        },
+        {
+          statCode: 'arriveInfo',
+          statName: '到达行李信息',
+          children: [
+            {
+              statCode: 'reach',
+              statName: '到达',
+              width: 88
+            },
+            {
+              statCode: 'did_not_arrive',
+              statName: '未到达',
+              width: 76
+            },
+            {
+              statCode: 'special',
+              statName: '特殊',
+              width: 88
+            },
+            {
+              statCode: 'claim',
+              statName: '理赔',
+              width: 83
+            }
+          ]
+        },
+        {
+          statCode: 'uninstallInfo',
+          statName: '卸载状态',
+          children: [
+            {
+              statCode: 'uninstalled',
+              statName: '已卸载',
+              width: 83
+            },
+            {
+              statCode: 'to_be_uninstalled',
+              statName: '待卸载',
+              width: 80
+            }
+          ]
+        },
+        {
+          statCode: 'stopBaggage',
+          statName: '终止行李',
+          children: [
+            {
+              statCode: 'terminateArrive',
+              statName: '到达',
+              width: 79
+            },
+            {
+              statCode: 'terminatedNotArrived',
+              statName: '未到达',
+              width: 82
+            }
+          ]
+        },
+        {
+          statCode: 'TransferBaggage',
+          statName: '转运行李',
+          children: [
+            {
+              statCode: 'delivered',
+              statName: '已交运',
+              width: 89
+            },
+            {
+              statCode: 'not_shipped',
+              statName: '未交运',
+              width: 89
+            }
+          ]
+        },
+        {
+          statCode: 'disBaggage',
+          statName: '行李分布',
+          children: [
+            {
+              statCode: 'container',
+              statName: '容器',
+              width: 97
+            },
+            {
+              statCode: 'bulk',
+              statName: '散装',
+              width: 101
+            }
+          ]
+        }
+      ]
+    }
+  },
+  methods: {
+    tableRowClassName({ row, rowIndex }) {
+      if (rowIndex < 2) {
+        return 'bgl-hui'
+      }
+    },
+    // 获取表单下拉框数据
+    getFormData(params) {
+      this.relatedAirportQuery({
+        ...params,
+        type: 'IN'
+      })
+      this.inboundCarrierQuery(params)
+      this.craftTypeQuery(params)
+      this.flightAttrQuery(params)
+    },
+    // 获取表格数据
+    getTableData(params) {
+      this.integratedQuery({
+        ...params,
+        type: 'IN'
+      })
+    },
+    initTableData(tableData) {
+      this.tableData = this._.sortBy(tableData, ['FlightDate', 'PlanLandingTime'])
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.arrival-form {
+  padding-top: 11px;
+  ::v-deep .form {
+    .el-form-item {
+      margin-bottom: 0px;
+      margin-right: 8px;
+      button,
+      input,
+      optgroup,
+      select,
+      textarea {
+        font-family: Helvetica, 'Microsoft YaHei';
+        font-size: 14px;
+      }
+      .el-switch__label {
+        color: #303133;
+      }
+      .el-form-item__error {
+        z-index: 10;
+      }
+    }
+    .checkTime {
+      margin: 0 16px;
+    }
+    .msgImg {
+      cursor: pointer;
+      position: relative;
+      top: 6px;
+    }
+  }
+}
+.arrival-table {
+  width: calc(100vw - 60px);
+  ::v-deep .table {
+    width: 100%;
+    .cell {
+      padding: 0;
+      text-align: center;
+      font-family: Helvetica, 'Microsoft YaHei';
+      font-size: 14px;
+      letter-spacing: 0;
+    }
+    .el-table__header-wrapper {
+      .cell {
+        font-weight: bold;
+        color: #101116;
+      }
+      .has-gutter {
+        tr {
+          .bgl-huang {
+            background: #fcf0b1;
+          }
+        }
+      }
+    }
+    .el-table__body-wrapper {
+      tr.bgl-hui {
+        background: #d2d6df;
+        td {
+          background: #d2d6df;
+        }
+        &:nth-child(5) {
+          position: relative;
+          &::after {
+            content: '';
+            position: absolute;
+            left: 0;
+            bottom: 0;
+            width: 100%;
+            height: 2px;
+            background: #e83f82;
+          }
+        }
+      }
+    }
+  }
+}
+::v-deep .dialog-check-cols .el-tree {
+  &.has-children .el-tree-node > .el-tree-node__children {
+    display: flex;
+    flex-wrap: wrap;
+  }
+  &.no-children {
+    display: flex;
+    flex-wrap: wrap;
+  }
+}
+</style>

+ 618 - 0
src/views/baggageManagement/components/baggage/index.vue

@@ -0,0 +1,618 @@
+<!--
+ * @Author: your name
+ * @Date: 2022-01-17 10:39:22
+ * @LastEditTime: 2022-03-14 12:04:16
+ * @LastEditors: your name
+ * @Description: 行李视图
+-->
+<template>
+  <div class="departureTwo">
+    <div class="part1">
+      <div class="title">
+        <span>行李基本信息</span>
+        <el-radio-group
+          v-model="infoBtn"
+          class="radioBtn"
+          size="mini"
+          fill="#FFFFFF"
+          text-color="#28344D"
+        >
+          <el-radio-button label="跟踪信息" />
+          <el-radio-button label="跟踪报文" />
+        </el-radio-group>
+      </div>
+      <div class="part1_info">
+        <el-row :gutter="50">
+          <el-col :span="3">行李牌号:{{ infoData.bagNo }}</el-col>
+          <el-col :span="3">特殊行李类型:{{ infoData.specialType }}</el-col>
+          <el-col :span="3">旅客姓名:{{ infoData.name }}</el-col>
+          <el-col :span="3">行李异常分类: QOD20481</el-col>
+          <el-col :span="4">企业或团队名称:{{ infoData.teamOrGroup }}</el-col>
+          <el-col :span="4">PNR: {{ infoData.pnr }}</el-col>
+        </el-row>
+      </div>
+    </div>
+    <div class="part2">
+      <div class="part2_info">
+        <div class="title">行李跟踪信息</div>
+        <div
+          v-if="infoBtn == '跟踪信息'"
+          class="type normal"
+        >
+          {{ infoData.status }}
+        </div>
+        <div
+          v-if="infoBtn == '跟踪信息'"
+          class="step"
+        >
+          <div class="stepLine">
+            <div
+              :style="{ width: lineWidth }"
+              class="stepLineBlue"
+            />
+          </div>
+          <div
+            v-for="(item, index) in stepData"
+            :key="index"
+            class="stepItem"
+            :class="{ activeItem: item.date.length > 0 }"
+          >
+            <span class="head">{{ item.airPort }}
+              <span v-if="item.airPort && item.nodeName !== ''">-</span>
+              <span>{{ item.nodeName.split('/')[1] || item.nodeName }}</span>
+            </span>
+            <span>{{ item.date }}</span>
+            <span>{{ item.time }}</span>
+          </div>
+        </div>
+      </div>
+      <div class="Btn">
+        <el-button
+          type="primary"
+          icon="el-icon-download"
+          size="mini"
+        />
+        <el-button
+          class="setBtn"
+          type="primary"
+          icon="el-icon-s-tools"
+          size="mini"
+          @click="show"
+        />
+      </div>
+    </div>
+    <div
+      v-if="infoBtn == '跟踪信息'"
+      class="part3"
+    >
+      <el-table
+        ref="table"
+        :data="baggageTableData"
+        border
+        style="width: 100%"
+        height="calc(100vh - 81px - 144px - 156px)"
+        stripe
+        size="mini"
+        :span-method="objectSpanMethod"
+        :header-cell-style="{ color: '#101116' }"
+      >
+        <el-table-column
+          v-for="item in tableColsCopy"
+          :key="item.index"
+          :prop="item.prop"
+          :label="item.name"
+          :align="item.align"
+          :show-overflow-tooltip="true"
+          :render-header="renderHeader"
+        />
+      </el-table>
+    </div>
+
+    <div
+      v-if="infoBtn == '跟踪报文'"
+      class="part4"
+    >
+      <template v-if="messageList.length">
+        <el-row
+          :gutter="24"
+          type="flex"
+        >
+          <el-col
+            v-for="(message, index) in messageList"
+            :key="index"
+            :span="6"
+          >
+            <div class="card">
+              <div class="message">
+                {{ message.replace(/\s+/g, '').split('.').join('\n.') }}
+                <!-- BSM <br>
+              .V/1LHRB <br>
+              .F/XX1640/08APR/PEK/Y <br>
+              .O/ZZ941/08APR/DXB/E <br>
+              .N/0666826758001 <br>
+              .D/SELF//08APR/110023L//PEK30113 <br>
+              .S/N/32L/C/030//Y/I <br>
+              .W/K/l/0 <br>
+              .P/1CUI/DI ENDBSM<br> -->
+              </div>
+            </div>
+          </el-col>
+        </el-row>
+      </template>
+      <template v-else>
+        <el-empty
+          :image-size="1"
+          description="暂无数据"
+        />
+      </template>
+    </div>
+    <!--列设置-->
+    <Dialog
+      :flag="dialogFlag"
+      class="dialog-check-cols"
+    >
+      <div class="col-dialog">
+        <div class="title">列设置</div>
+        <div class="content">
+          <el-tree
+            :data="tableCols"
+            :class="colsCheckClass"
+            show-checkbox
+            node-key="index"
+            :default-expand-all="true"
+            :props="{
+              label: 'name',
+              children: 'children'
+            }"
+            :default-checked-keys="checkedKeysTemp"
+            @check="handleCheck"
+          />
+        </div>
+        <div class="foot right t30">
+          <el-button
+            size="medium"
+            class="r24"
+            type="primary"
+            @click="onCheck"
+          >确定</el-button>
+          <el-button
+            size="medium"
+            @click="hide"
+          >取消</el-button>
+        </div>
+      </div>
+    </Dialog>
+  </div>
+</template>
+<script>
+import Dialog from '@/layout/components/Dialog/index.vue'
+import { nodeinfoes, fulltrackinfoAndNodeInfoList, BaggageMessageQuery } from '@/api/flight'
+import tableColsMixin from '../../mixins/tableCols'
+
+export default {
+  name: 'BaggageView',
+  components: {
+    Dialog
+  },
+  mixins: [tableColsMixin],
+  data() {
+    return {
+      departureAirport: '',
+      landingAirport: '',
+      infoData: null,
+      dialogVisibledele: false,
+      active: 2,
+      infoBtn: '跟踪信息',
+      hasMessageGotten: false,
+      messageList: [
+        // `BSM
+        // .V/1LHRB
+        // .F/XX1640/08APR/PEK/Y
+        // .O/ZZ941/08APR/DXB/E
+        // .N/0666826758001
+        // .D/SELF//08APR/110023L//PEK30113
+        // .S/N/32L/C/030//Y/I
+        // .W/K/l/0
+        // .P/1CUI/DI ENDBSM`
+      ],
+      lineWidth: '',
+      checkList: [],
+      stepData: [
+        {
+          airPort: this.departureAirport,
+          nodeCode: 'CHECKIN',
+          nodeName: '值机',
+          date: '',
+          time: ''
+        },
+        {
+          airPort: this.departureAirport,
+          nodeCode: 'SECURITY',
+          nodeName: '安检',
+          date: '',
+          time: ''
+        },
+        {
+          airPort: this.departureAirport,
+          nodeCode: 'SORT',
+          nodeName: '分拣',
+          date: '',
+          time: ''
+        },
+        {
+          airPort: this.departureAirport,
+          nodeCode: 'LOAD',
+          nodeName: '装载/装车',
+          date: '',
+          time: ''
+        },
+        {
+          airPort: this.departureAirport,
+          nodeCode: 'INF',
+          nodeName: '装机',
+          date: '',
+          time: ''
+        },
+        // {
+        //   airPort: this.landingAirport,
+        //   nodeCode: '',
+        //   nodeName: '卸机',
+        //   date: '',
+        //   time: ''
+        // },
+        {
+          airPort: this.landingAirport,
+          nodeCode: 'UNLOAD',
+          nodeName: '卸车',
+          date: '',
+          time: ''
+        },
+        {
+          airPort: this.landingAirport,
+          nodeCode: 'TiQu',
+          nodeName: '提取',
+          date: '',
+          time: ''
+        }
+      ],
+      tableCols: [
+        {
+          name: '航班号',
+          prop: 'flightNo',
+          align: 'center'
+        },
+        { name: '航班日期', prop: 'flightDate', align: 'center' },
+        {
+          name: '起飞航站/预计起飞时间',
+          prop: 'start',
+          align: 'center'
+        },
+        {
+          name: '目的航站/预计降落时间',
+          prop: 'end',
+          align: 'center',
+          sortable: 'custom'
+        },
+        { name: '旅客仓位', prop: 'passengerCompartment', align: 'center' },
+        { name: '旅客座位号', prop: 'passengerSeatNumber', align: 'center' },
+        { name: '值机序号', prop: 'passengerCheckInNumber', align: 'center' },
+        { name: '节点标识', prop: 'nodeCode', align: 'center' },
+        { name: '节点名称', prop: 'nodeName', align: 'center' },
+        { name: '位置码', prop: 'locationCode', align: 'center' },
+        { name: '位置描述', prop: 'locationRemark', align: 'center' },
+        { name: '读取时间', prop: 'dealTime', align: 'center' },
+        { name: '结果', prop: 'status', align: 'center' },
+        { name: '次级代码', prop: 'secondaryCode', align: 'center' },
+        { name: '操作人', prop: 'creator', align: 'center' },
+        { name: '设备ID', prop: 'deviceId', align: 'center' },
+        { name: '发往位置', prop: 'toLocation', align: 'center' },
+        { name: '位置描述', prop: 'toLocationRemark', align: 'center' },
+        { name: '装载序号', prop: 'loadSequenceNumber', align: 'center' },
+        { name: '容器编号', prop: 'containerNumber', align: 'center' },
+        { name: '报文', prop: 'messageType', align: 'center' }
+      ],
+      baggageTableData: [],
+      spanArr: [],
+      pos: 0
+    }
+  },
+  watch: {
+    infoBtn(val) {
+      if (val === '跟踪报文' && !this.hasMessageGotten) {
+        const { flightNo, flightDate, bagNo } = this.infoData
+        const params = { flightNo, flightDate, bagNo }
+        this.baggageMessageQuery(params)
+      }
+    }
+  },
+  created() {
+    this.infoData = this._.cloneDeep(this.$route.query)
+    // console.log(this.infoData)
+    // this.baggageTableColumnCheckList = this._.cloneDeep(this.baggageTableColumn)
+    const nodeData = {
+      flightNo: this.infoData.flightNo,
+      flightDate: this.infoData.flightDate,
+      bagNo: this.infoData.bagNo
+    }
+    this.getNodeinfoes(nodeData)
+    this.getFulltrackinfoAndNodeInfoList(nodeData)
+  },
+  methods: {
+    async getFulltrackinfoAndNodeInfoList(data) {
+      try {
+        const result = await fulltrackinfoAndNodeInfoList(data)
+        if (result.returnData.length > 0) {
+          this.departureAirport = result.returnData[0].departureAirport
+          this.landingAirport = result.returnData[0].landingAirport
+        }
+        result.returnData.forEach(item => {
+          item['start'] = item.departureAirport + '\n' + item.departureTime
+          item['end'] = item.landingAirport + '\n' + item.landingTime
+          item['dealTime'] = item.dealTime.split('T')[1]
+        })
+        this.baggageTableData = this._.cloneDeep(result.returnData)
+        for (var i = 0; i < this.baggageTableData.length; i++) {
+          if (i === 0) {
+            this.spanArr.push(1)
+            this.pos = 0
+          } else {
+            // 判断当前元素与上一个元素是否相同
+            if (this.baggageTableData[i].flightNo === this.baggageTableData[i - 1].flightNo) {
+              this.spanArr[this.pos] += 1
+              this.spanArr.push(0)
+            } else {
+              this.spanArr.push(1)
+              this.pos = i
+            }
+          }
+          // console.log(this.spanArr)
+        }
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    async getNodeinfoes(data) {
+      try {
+        const result = await nodeinfoes(data)
+        const nodes = this._.cloneDeep(result.returnData)
+        let finalStep = 0
+        this.stepData.forEach((item, index) => {
+          nodes.forEach(node => {
+            if (item.nodeCode === node.nodeCode) {
+              item.date = node.realTime.split(' ')[0]
+              item.time = node.realTime.split(' ')[1]
+              finalStep < index + 1 && (finalStep = index + 1)
+            }
+          })
+        })
+        this.lineWidth = (finalStep / 8) * 100 + '%'
+        // console.log(this.stepData)
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    async baggageMessageQuery(params) {
+      try {
+        const result = await BaggageMessageQuery(params)
+        this.hasMessageGotten = true
+        // console.log(result.returnData)
+        this.messageList = result.returnData
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
+      if (columnIndex < 4) {
+        const _row = this.spanArr[rowIndex]
+        const _col = _row > 0 ? 1 : 0
+        // console.log(`rowspan:${_row} colspan:${_col}`)
+        return {
+          rowspan: _row,
+          colspan: _col
+        }
+      }
+    },
+    renderHeader(h, { column, $index }) {
+      const arr = column.label.split('/')
+      if (arr.length > 1) {
+        return h('span', {
+          attrs: {},
+          domProps: {
+            innerHTML: '<span>' + arr[0] + '</span><br>' + arr[1]
+          }
+        })
+      } else {
+        return h('span', {
+          attrs: {},
+          domProps: {
+            innerHTML: '<span>' + arr[0] + '</span>'
+          }
+        })
+      }
+    }
+  }
+}
+</script>
+<style lang="scss">
+.radioBtn {
+  padding: 5px;
+  background: #000d2a;
+  .el-radio-button__inner {
+    background: #000d2a;
+    color: #fff;
+    border: none;
+    font-weight: bold;
+  }
+  .el-radio-button:first-child .el-radio-button__inner {
+    border: none;
+  }
+}
+</style>
+<style lang="scss" scoped>
+.departureTwo {
+  width: 100%;
+  height: calc(100vh - 81px);
+  overflow: hidden;
+  background: #dfe3ea;
+  padding: 10px 5px 0 5px;
+  .part1 {
+    width: 100%;
+    height: 144px;
+    background: #041741;
+    padding: 31px 18px;
+    .title {
+      font-size: 18px;
+      font-weight: bold;
+      color: #ffffff;
+      width: 320px;
+      display: flex;
+      flex-direction: row;
+      justify-content: space-between;
+      align-items: center;
+    }
+    .part1_info {
+      width: 100%;
+      padding-top: 25px;
+      color: #fff;
+      font-size: 14px;
+      font-weight: 400;
+      color: #ffffff;
+    }
+  }
+  .part2 {
+    width: 100%;
+    padding: 24px 0;
+    padding-left: 32px;
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+    .part2_info {
+      display: flex;
+      flex-direction: row;
+      justify-content: flex-start;
+      align-items: center;
+      .title {
+        font-size: 18px;
+        font-weight: bold;
+        color: #303133;
+        margin-right: 42px;
+      }
+      .type {
+        font-size: 18px;
+        font-weight: bold;
+        margin-right: 80px;
+      }
+      .warn {
+        color: #df3559;
+      }
+      .normal {
+        color: #519f6b;
+      }
+      .step {
+        height: 80px;
+        width: 980px;
+        display: flex;
+        flex-direction: row;
+        justify-content: space-between;
+        align-items: center;
+        position: relative;
+        .stepLine {
+          width: 100%;
+          height: 20px;
+          background: #afb4bf;
+          position: absolute;
+          top: 50%;
+          margin-top: -10px;
+          border-radius: 10px;
+          .stepLineBlue {
+            position: absolute;
+            height: 100%;
+            z-index: 1;
+            background: #041741;
+            border-radius: 10px;
+          }
+        }
+        .stepItem {
+          width: 80px;
+          height: 80px;
+          background: #afb4bf;
+          border-radius: 50%;
+          z-index: 1;
+          text-align: center;
+          font-weight: bold;
+          color: #ffffff;
+          font-size: 12px;
+          display: flex;
+          flex-direction: column;
+          align-content: space-around;
+          align-items: center;
+          // padding-top: 19px;
+          justify-content: center;
+          .head {
+            font-size: 14px;
+          }
+        }
+        .activeItem {
+          background: #041741;
+        }
+      }
+    }
+    .Btn {
+      height: 30px;
+      display: flex;
+      .el-button {
+        margin-left: 10px;
+        width: 30px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+      }
+      .setBtn {
+        margin-right: 30px;
+      }
+    }
+  }
+  .part3 {
+    width: 100%;
+    height: calc(100vh - 81px - 144px - 145px);
+    padding: 10px 5px 15px 5px;
+    ::v-deep .el-table .cell {
+      white-space: pre-line;
+    }
+  }
+  .part4 {
+    width: 100%;
+    height: calc(100vh - 81px - 144px - 100px);
+    overflow-y: auto;
+    overflow-x: hidden;
+    ::v-deep .el-row {
+      flex-wrap: wrap;
+      .card {
+        width: 100%;
+        min-height: 280px;
+        padding: 36px 0 15px 31px;
+        background: #ffffff;
+        box-shadow: 0px 3px 2px 0px rgba(0, 0, 0, 0.29);
+        margin-bottom: 24px;
+        > .message {
+          white-space: pre-line;
+          line-height: 24px;
+          font-size: 14px;
+          color: #303133;
+        }
+      }
+    }
+  }
+}
+::v-deep .dialog-check-cols .el-tree {
+  &.has-children .el-tree-node > .el-tree-node__children {
+    display: flex;
+    flex-wrap: wrap;
+  }
+  &.no-children {
+    display: flex;
+    flex-wrap: wrap;
+  }
+}
+</style>

+ 27 - 0
src/views/baggageManagement/components/departure/baggage.vue

@@ -0,0 +1,27 @@
+<!--
+ * @Author: Badguy
+ * @Date: 2022-03-09 11:51:26
+ * @LastEditTime: 2022-03-09 11:53:12
+ * @LastEditors: your name
+ * @Description: 离港行李视图
+ * have a nice day!
+-->
+
+<template>
+  <BaggageView />
+</template>
+
+<script>
+import BaggageView from '../baggage'
+
+export default {
+  name: 'DepartureBaggageView',
+  components: {
+    BaggageView
+  }
+}
+</script>
+
+<style>
+
+</style>

+ 27 - 0
src/views/baggageManagement/components/departure/flight.vue

@@ -0,0 +1,27 @@
+<!--
+ * @Author: Badguy
+ * @Date: 2022-03-09 11:49:13
+ * @LastEditTime: 2022-03-09 11:53:27
+ * @LastEditors: your name
+ * @Description: 离港行李视图
+ * have a nice day!
+-->
+
+<template>
+  <FlightView />
+</template>
+
+<script>
+import FlightView from '../flight'
+
+export default {
+  name: 'DepartureFlightView',
+  components: {
+    FlightView
+  }
+}
+</script>
+
+<style>
+
+</style>

+ 493 - 0
src/views/baggageManagement/components/departure/index.vue

@@ -0,0 +1,493 @@
+<!--
+ * @Author: zk
+ * @Date: 2022-01-17 10:39:22
+ * @LastEditTime: 2022-03-15 16:21:43
+ * @LastEditors: your name
+ * @Description: 离港01
+-->
+<template>
+  <div class="departure-one">
+    <!--功能区-表单-->
+    <div class="departure-form">
+      <el-form
+        ref="form"
+        :inline="true"
+        :model="formData"
+        :rules="rules"
+        class="form"
+      >
+        <el-form-item prop="currentAirport">
+          <el-cascader
+            v-model="formData.currentAirport"
+            style="width:144px;"
+            placeholder="全部机场"
+            size="small"
+            :options="currentAirportOptions"
+            :props="currentAirportProps"
+            collapse-tags
+            clearable
+            filterable
+            @change="setCurrentAirport"
+          />
+        </el-form-item>
+        <el-form-item prop="relatedAirport">
+          <el-cascader
+            v-model="formData.relatedAirport"
+            style="width:136px;"
+            size="small"
+            :options="relatedAirportOptions"
+            :props="relatedAirportProps"
+            placeholder="全部目的地"
+            collapse-tags
+            clearable
+            filterable
+            @change="onSubmit"
+          />
+        </el-form-item>
+        <el-form-item prop="outgoingAirline">
+          <el-cascader
+            v-model="formData.outgoingAirline"
+            style="width:164px;"
+            size="small"
+            :options="outgoingAirlineOptions"
+            :props="outgoingAirlineProps"
+            placeholder="全部航司"
+            collapse-tags
+            clearable
+            filterable
+            @change="onSubmit"
+          />
+        </el-form-item>
+        <el-form-item prop="craftType">
+          <el-cascader
+            v-model="formData.craftType"
+            style="width:120px;"
+            size="small"
+            :options="craftTypeOptions"
+            :props="craftTypeProps"
+            placeholder="全部机型"
+            collapse-tags
+            clearable
+            filterable
+            @change="onSubmit"
+          />
+        </el-form-item>
+        <el-form-item prop="flightAttr">
+          <el-cascader
+            v-model="formData.flightAttr"
+            style="width:120px;"
+            size="small"
+            :options="flightAttrOptions"
+            :props="flightAttrProps"
+            placeholder="国际/国内"
+            collapse-tags
+            clearable
+            filterable
+            @change="onSubmit"
+          />
+        </el-form-item>
+        <el-form-item prop="startDate">
+          <el-date-picker
+            v-model="formData.startDate"
+            style="width:216px;"
+            size="small"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="开始时间"
+            @change="setStartDate"
+          />
+        </el-form-item>
+        <el-form-item prop="endDate">
+          <el-date-picker
+            v-model="formData.endDate"
+            style="width:216px;"
+            size="small"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="结束时间"
+            @change="setEndDate"
+          />
+        </el-form-item>
+        <el-form-item prop="search">
+          <el-input
+            v-model="formData.search"
+            style="width:240px;margin-left:105px;"
+            size="small"
+            placeholder="请输入内容"
+            prefix-icon="el-icon-search"
+            clearable
+            @clear="inputClear"
+            @keyup.enter="onSubmit"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button
+            size="small"
+            type="primary"
+            @click="onSubmit"
+          >搜索</el-button>
+        </el-form-item>
+        <el-form-item v-is="['i_showTransit']">
+          <el-switch
+            v-model="formData.switch"
+            style="margin-left:40px;"
+            active-text="显示中转"
+          />
+        </el-form-item>
+        <el-form-item v-is="['i_timeIcon']">
+          <el-dropdown>
+            <img
+              class="checkTime msgImg"
+              src="../../../../assets/departure/ic_time.png"
+            >
+            <el-dropdown-menu
+              slot="dropdown"
+              class="time-zone"
+            >
+              <el-dropdown-item>国内Local/国际UTC</el-dropdown-item>
+              <el-dropdown-item>Local</el-dropdown-item>
+              <el-dropdown-item>UTC</el-dropdown-item>
+            </el-dropdown-menu>
+          </el-dropdown>
+        </el-form-item>
+        <el-form-item v-is="['i_columnSettings']">
+          <img
+            class="msgImg"
+            src="../../../../assets/departure/ic_setting.png"
+            @click="show"
+          >
+        </el-form-item>
+      </el-form>
+    </div>
+    <!--表格-->
+    <div
+      v-loading="loading"
+      class="departure-table"
+      element-loading-text="拼命加载中"
+      element-loading-spinner="el-icon-loading"
+      element-loading-background="rgba(0, 0, 0, 0.8)"
+    >
+      <el-table
+        ref="table"
+        :data="tableData"
+        class="table"
+        :height="computedTableHeight"
+        :header-cell-class-name="tableCellClassName"
+        :row-class-name="tableRowClassName"
+        show-summary
+        :summary-method="summaryMethod"
+        border
+        stripe
+        @row-click="rowClick"
+      >
+        <el-table-column
+          v-for="(item,index) in tableColsCopy"
+          :key="index"
+          :prop="item.statCode"
+          :label="item.statName"
+          :width="item.width"
+          :formatter="tableFormat"
+        />
+      </el-table>
+    </div>
+    <!--列设置-->
+    <Dialog
+      :flag="dialogFlag"
+      class="dialog-check-cols"
+    >
+      <div class="col-dialog">
+        <div class="title">列设置</div>
+        <div class="content">
+          <el-tree
+            :data="tableCols"
+            :class="colsCheckClass"
+            show-checkbox
+            node-key="index"
+            :default-expand-all="true"
+            :props="{
+              label: 'statName',
+              children: 'children'
+            }"
+            :default-checked-keys="checkedKeysTemp"
+            @check="handleCheck"
+          />
+        </div>
+        <div class="foot right t30">
+          <el-button
+            size="medium"
+            class="r24"
+            type="primary"
+            @click="onCheck"
+          >确定</el-button>
+          <el-button
+            size="medium"
+            @click="hide"
+          >取消</el-button>
+        </div>
+      </div>
+    </Dialog>
+  </div>
+</template>
+
+<script>
+import Dialog from '@/layout/components/Dialog'
+import terminalMixin from '../../mixins/terminal'
+import formMixin from '../../mixins/form'
+import tableColsMixin from '../../mixins/tableCols'
+
+export default {
+  name: 'DepartureTerminalView',
+  components: { Dialog },
+  mixins: [terminalMixin, formMixin, tableColsMixin],
+  data() {
+    return {
+      // 初始表头
+      tableCols: [
+        {
+          statCode: 'FlightNO',
+          statName: '航班号',
+          width: 132
+        },
+        {
+          statCode: 'FlightDate',
+          statName: '执飞日期',
+          width: 105
+        },
+        {
+          statCode: 'PlanDepartureTime',
+          statName: '预计起飞时间',
+          width: 115
+        },
+        {
+          statCode: 'PlanLandingApt',
+          statName: '目的站',
+          width: 71
+        },
+        {
+          statCode: 'DepartureBuild',
+          statName: '航站楼',
+          width: 65
+        },
+        {
+          statCode: 'BordingGate',
+          statName: '登机口',
+          width: 68
+        },
+        {
+          statCode: 'StandForDepartrue',
+          statName: '停机位',
+          width: 54
+        },
+        {
+          statCode: 'passagernum',
+          statName: '托运旅客',
+          width: 88
+        },
+        {
+          statCode: 'checkin',
+          statName: '值机',
+          width: 72
+        },
+        {
+          statCode: 'not_actived',
+          statName: '未激活',
+          width: 76
+        },
+        {
+          statCode: 'expect_load',
+          statName: '预计装载',
+          width: 101
+        },
+        {
+          statCode: 'security_all',
+          statName: '安检',
+          width: 88
+        },
+        {
+          statCode: 'fenj',
+          statName: '分拣',
+          width: 83
+        },
+        {
+          statCode: 'loadcar',
+          statName: '装车',
+          width: 83
+        },
+        {
+          statCode: 'loadflight',
+          statName: '装机',
+          width: 80
+        },
+        {
+          statCode: 'waitfanj',
+          statName: '待翻减',
+          width: 79
+        },
+        {
+          statCode: 'hasfanj',
+          statName: '已翻减',
+          width: 82
+        },
+        {
+          statCode: 'delbag',
+          statName: '取消托运',
+          width: 89
+        },
+        {
+          statCode: 'no_bsm',
+          statName: '无BSM',
+          width: 68
+        },
+        {
+          statCode: 'riskWarning',
+          statName: '风险预警',
+          width: 75
+        },
+        {
+          statCode: 'departureAnomaly',
+          statName: '离港异常',
+          width: 72
+        },
+        {
+          statCode: 'transfer_all',
+          statName: '中转进行李'
+        }
+      ]
+    }
+  },
+  methods: {
+    tableRowClassName({ row, rowIndex }) {
+      if (rowIndex < 5) {
+        return 'bgl-hui'
+      }
+    },
+    tableCellClassName({ row, column }) {
+      if (
+        column.property === 'transfer_all' ||
+        column.property === 'departureAnomaly' ||
+        column.property === 'riskWarning'
+      ) {
+        return 'bgl-huang'
+      }
+    },
+    // 获取表单下拉框数据
+    getFormData(params) {
+      this.relatedAirportQuery({
+        ...params,
+        type: 'OUT'
+      })
+      this.outgoingAirlineQuery(params)
+      this.craftTypeQuery(params)
+      this.flightAttrQuery(params)
+    },
+    // 获取表格数据
+    getTableData(params) {
+      this.integratedQuery({
+        ...params,
+        type: 'OUT'
+      })
+    },
+    initTableData(tableData) {
+      tableData.forEach(item => {
+        item['wantfanj'] = item['delbag'] - item['hasfanj']
+      })
+      this.tableData = this._.sortBy(tableData, ['FlightDate', 'PlanDepartureTime'])
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.departure-form {
+  padding-top: 11px;
+  ::v-deep .form {
+    .el-form-item {
+      margin-bottom: 0px;
+      margin-right: 8px;
+      button,
+      input,
+      optgroup,
+      select,
+      textarea {
+        font-family: Helvetica, 'Microsoft YaHei';
+        font-size: 14px;
+      }
+      .el-switch__label {
+        color: #303133;
+      }
+      .el-form-item__error {
+        z-index: 10;
+      }
+    }
+    .checkTime {
+      margin: 0 16px;
+    }
+    .msgImg {
+      cursor: pointer;
+      position: relative;
+      top: 6px;
+    }
+  }
+}
+.departure-table {
+  width: calc(100vw - 60px);
+  ::v-deep .table {
+    width: 100%;
+    .cell {
+      padding: 0;
+      text-align: center;
+      font-size: 14px;
+      font-family: Helvetica, 'Microsoft YaHei';
+      letter-spacing: 0;
+    }
+    .el-table__header-wrapper {
+      .cell {
+        font-weight: bold;
+        color: #101116;
+      }
+      .has-gutter {
+        tr {
+          .bgl-huang {
+            background: #fcf0b1;
+          }
+        }
+      }
+    }
+    .el-table__body-wrapper {
+      tr.bgl-hui {
+        background: #d2d6df;
+        td {
+          background: #d2d6df;
+        }
+        &:nth-child(5) {
+          position: relative;
+          &::after {
+            content: '';
+            position: absolute;
+            left: 0;
+            bottom: 0;
+            width: 100%;
+            height: 2px;
+            background: #e83f82;
+          }
+        }
+      }
+    }
+  }
+}
+::v-deep .dialog-check-cols .el-tree {
+  &.has-children .el-tree-node > .el-tree-node__children {
+    display: flex;
+    flex-wrap: wrap;
+  }
+  &.no-children {
+    display: flex;
+    flex-wrap: wrap;
+  }
+}
+::v-deep .time-zone .el-dropdown-menu__item {
+  font-family: Helvetica, 'Microsoft YaHei';
+  font-size: 12px;
+  color: #101116;
+}
+</style>

+ 687 - 0
src/views/baggageManagement/components/flight/index.vue

@@ -0,0 +1,687 @@
+<!--
+ * @Author: your name
+ * @Date: 2022-01-17 10:39:22
+ * @LastEditTime: 2022-03-10 15:30:37
+ * @LastEditors: your name
+ * @Description: 航班视图
+-->
+<template>
+  <div class="flight-view">
+    <div class="flight-wrap">
+      <div class="part1">
+        <div class="title">
+          {{ infoData.PlanDepartureApt }} - {{ infoData.FlightNO }} -
+          {{ infoData.PlanLandingApt }}
+        </div>
+        <div class="part1_info">
+          <div class="part1_info_box">
+            <el-row>
+              <el-col :span="12">
+                <span>起飞机场简称:</span>
+              </el-col>
+              <el-col :span="12">
+                <span>{{ infoData.planDepartureaptName }}</span>
+              </el-col>
+            </el-row>
+
+            <el-row>
+              <el-col :span="12">
+                <span>起飞机场三字码:</span>
+              </el-col>
+              <el-col :span="12">
+                <span>{{ infoData.PlanDepartureApt }}</span>
+              </el-col>
+            </el-row>
+
+            <el-row>
+              <el-col :span="12">
+                <span>起飞机场航站楼:</span>
+              </el-col>
+              <el-col :span="12">
+                <span>{{ infoData.DepartureBuild }}</span>
+              </el-col>
+            </el-row>
+
+            <el-row>
+              <el-col :span="12">
+                <span>日期:{{ infoData.PlanDepartureTime.split("T")[0] }}</span>
+              </el-col>
+              <el-col :span="12">
+                <span>时间:{{ infoData.PlanDepartureTime.split("T")[1] }}</span>
+              </el-col>
+            </el-row>
+
+            <el-row>
+              <el-col :span="12">
+                <span>登机口:{{ infoData.BordingGate }}</span>
+              </el-col>
+              <el-col :span="12">
+                <span>停机位:{{ infoData.StandForDeparture }}</span>
+              </el-col>
+            </el-row>
+          </div>
+          <div class="part1_info_box">
+            <el-row>
+              <el-col :span="12">
+                <span>航班号:</span>
+              </el-col>
+              <el-col :span="12">
+                <span>{{ infoData.FlightNO }}</span>
+              </el-col>
+            </el-row>
+
+            <el-row>
+              <el-col :span="12">
+                <span>航班状态:</span>
+              </el-col>
+              <el-col :span="12">
+                <span>{{ infoData.FlightStatus }}</span>
+              </el-col>
+            </el-row>
+
+            <el-row>
+              <el-col :span="12">
+                <span>托运旅客数:</span>
+              </el-col>
+              <el-col :span="12">
+                <span>{{ infoData.passagernum }}</span>
+              </el-col>
+            </el-row>
+
+            <el-row>
+              <el-col :span="12">
+                <span>终点行李数:</span>
+              </el-col>
+              <el-col :span="12">
+                <span>{{ infoData.terminus }}</span>
+              </el-col>
+            </el-row>
+
+            <el-row>
+              <el-col :span="12">
+                <span>中转行李数:</span>
+              </el-col>
+              <el-col :span="12">
+                <span>{{ infoData.transfer_all }}</span>
+              </el-col>
+            </el-row>
+          </div>
+          <div class="part1_info_box">
+            <el-row>
+              <el-col :span="12">
+                <span>降落机场简称:</span>
+              </el-col>
+              <el-col :span="12">
+                <span>{{ infoData.PlanLandingaptName }}</span>
+              </el-col>
+            </el-row>
+
+            <el-row>
+              <el-col :span="12">
+                <span>降落机场三字码:</span>
+              </el-col>
+              <el-col :span="12">
+                <span>{{ infoData.PlanLandingApt }}</span>
+              </el-col>
+            </el-row>
+
+            <el-row>
+              <el-col :span="12">
+                <span>降落机场航站楼:</span>
+              </el-col>
+              <el-col :span="12">
+                <span>{{ infoData.LandingBuild }}</span>
+              </el-col>
+            </el-row>
+
+            <el-row>
+              <el-col :span="12">
+                <span>日期:{{ infoData.PlanLandingTime.split("T")[0] }}</span>
+              </el-col>
+              <el-col :span="12">
+                <span>时间:{{ infoData.PlanLandingTime.split("T")[1] }}</span>
+              </el-col>
+            </el-row>
+
+            <el-row>
+              <el-col :span="12">
+                <span>提取转盘:{{ infoData.Carousel }}</span>
+              </el-col>
+              <el-col :span="12">
+                <span>停机位:{{ infoData.StandForLanding }}</span>
+              </el-col>
+            </el-row>
+          </div>
+        </div>
+      </div>
+      <div class="part2">
+        <el-table
+          :data="containerTableData"
+          border
+          style="width: 100%"
+          height="344"
+          stripe
+          size="mini"
+          show-summary
+          :header-cell-style="{ color: '#101116' }"
+        >
+          <el-table-column
+            v-for="item in containerTableColumn"
+            :key="item.id"
+            :prop="item.prop"
+            :label="item.name"
+            :align="item.align"
+            :show-overflow-tooltip="true"
+          />
+        </el-table>
+      </div>
+      <div
+        class="part3"
+        style="padding-right: 4px;"
+      >
+        <div class="title">中转进</div>
+        <el-table
+          :data="transferInTableData"
+          border
+          style="width: 100%"
+          height="162"
+          stripe
+          size="mini"
+          show-summary
+          :header-cell-style="{ color: '#101116' }"
+        >
+          <el-table-column
+            v-for="item in transferInTableColumn"
+            :key="item.id"
+            :prop="item.prop"
+            :label="item.name"
+            :align="item.align"
+            :show-overflow-tooltip="true"
+          />
+        </el-table>
+      </div>
+      <div
+        class="part3"
+        style="padding-left: 4px;"
+      >
+        <div class="title">中转出</div>
+        <el-table
+          :data="transferOutTableData"
+          border
+          style="width: 100%"
+          height="162"
+          stripe
+          size="mini"
+          show-summary
+          :header-cell-style="{ color: '#101116' }"
+        >
+          <el-table-column
+            v-for="item in transferOutTableColumn"
+            :key="item.id"
+            :prop="item.prop"
+            :label="item.name"
+            :align="item.align"
+            :show-overflow-tooltip="true"
+          />
+        </el-table>
+      </div>
+      <div class="part4">
+        <div class="title">
+          <el-cascader
+            placeholder="全部行李"
+            :options="options"
+            :props="props"
+            collapse-tags
+            size="mini"
+            clearable
+          />
+          <div class="search">
+            <el-input
+              v-model="keyWords"
+              placeholder="请输入需要搜索姓名或行李编号"
+              size="mini"
+              style="width: 280px"
+            />
+            <el-button
+              class="searchBtn"
+              type="primary"
+              size="mini"
+            >搜索</el-button>
+          </div>
+          <el-switch
+            v-model="openUTC"
+            active-text="开启UTC"
+          />
+          <el-button
+            class="btn-square"
+            type="primary"
+            icon="el-icon-download"
+            size="mini"
+          />
+          <el-button
+            class="btn-square setBtn"
+            type="primary"
+            icon="el-icon-s-tools"
+            size="mini"
+            @click="show"
+          />
+        </div>
+        <el-table
+          ref="table"
+          :data="baggageTableData"
+          border
+          style="width: 100%"
+          height="320"
+          stripe
+          size="mini"
+          :header-cell-style="{ color: '#101116' }"
+          @row-click="rowClick"
+        >
+          <el-table-column
+            v-for="item in tableColsCopy"
+            :key="item.index"
+            :prop="item.prop"
+            :label="item.name"
+            :align="item.align"
+            :sortable="item.sortable"
+          />
+        </el-table>
+      </div>
+    </div>
+    <!--列设置-->
+    <Dialog
+      :flag="dialogFlag"
+      class="dialog-check-cols"
+    >
+      <div class="col-dialog">
+        <div class="title">列设置</div>
+        <div class="content">
+          <el-tree
+            :data="tableCols"
+            :class="colsCheckClass"
+            show-checkbox
+            node-key="index"
+            :default-expand-all="true"
+            :props="{
+              label: 'name',
+              children: 'children'
+            }"
+            :default-checked-keys="checkedKeysTemp"
+            @check="handleCheck"
+          />
+        </div>
+        <div class="foot right t30">
+          <el-button
+            size="medium"
+            class="r24"
+            type="primary"
+            @click="onCheck"
+          >确定</el-button>
+          <el-button
+            size="medium"
+            @click="hide"
+          >取消</el-button>
+        </div>
+      </div>
+    </Dialog>
+  </div>
+</template>
+<script>
+import Dialog from '@/layout/components/Dialog/index.vue'
+import { baggageSearchIO, baggageSearchIOContainer, baggageSearchIOAll } from '@/api/flight'
+import tableColsMixin from '../../mixins/tableCols'
+
+const arrivalBaggageTableColumn = [
+  { name: '旅客姓名', prop: 'name', align: 'center', sortable: 'custom' },
+  { name: '行李牌号', prop: 'bagNo', align: 'center' },
+  {
+    name: '特殊行李类型',
+    prop: 'specialType',
+    align: 'center',
+    sortable: 'custom'
+  },
+  {
+    name: '容器编号',
+    prop: 'containerNo',
+    align: 'center',
+    sortable: 'custom'
+  },
+  { name: '装载序号', prop: 'loadSequenceIndex', align: 'center' },
+  { name: '卸载', prop: 'uninstall', align: 'center' },
+  { name: '到达', prop: 'arrival', align: 'center' },
+  { name: '提取', prop: 'extract', align: 'center' },
+  { name: '旅客仓位', prop: 'positionNo', align: 'center' },
+  { name: '中转标志', prop: 'transitStatus', align: 'center' },
+  { name: '卷宗号', prop: 'fileNumber', align: 'center' }
+]
+const departureBaggageTableColumn = [
+  { name: '旅客姓名', prop: 'name', align: 'center', sortable: 'custom' },
+  { name: '行李牌号', prop: 'bagNo', align: 'center' },
+  {
+    name: '特殊行李类型',
+    prop: 'specialType',
+    align: 'center',
+    sortable: 'custom'
+  },
+  {
+    name: '容器编号',
+    prop: 'containerNo',
+    align: 'center',
+    sortable: 'custom'
+  },
+  { name: '装载序号', prop: 'loadSequenceIndex', align: 'center' },
+  { name: '值机', prop: 'checkIn', align: 'center' },
+  { name: '安检', prop: 'security', align: 'center' },
+  { name: '分拣', prop: 'sorting', align: 'center' },
+  { name: '装车', prop: 'loading', align: 'center' },
+  { name: '装机', prop: 'installed', align: 'center' },
+  { name: '中转标志', prop: 'transitStatus', align: 'center' },
+  { name: '卷宗号', prop: 'fileNumber', align: 'center' }
+]
+export default {
+  name: 'FlightView',
+  components: {
+    Dialog
+  },
+  mixins: [tableColsMixin],
+  data() {
+    return {
+      infoData: null,
+      keyWords: '',
+      openUTC: true,
+      props: { multiple: true },
+      options: [
+        { value: 0, label: 'VIP行李' },
+        { value: 0, label: 'VIP行李' }
+      ],
+      containerTableColumn: [
+        { name: '容器编号', prop: 'containerNo', align: 'center' },
+        { name: '类型', prop: 'type', align: 'center' },
+        { name: '行李数', prop: 'total', align: 'center' }
+      ],
+      transferInTableColumn: [
+        { name: '航班号', prop: 'preFlightNo', align: 'center' },
+        { name: '日期', prop: 'preFlightDate', align: 'center' },
+        { name: '时间', prop: 'preFlightLandingDateTime', align: 'center' },
+        { name: '始发站', prop: 'preAirportName', align: 'center' },
+        { name: '航班状态', prop: 'flightStatus', align: 'center' },
+        { name: '中转数', prop: 'total', align: 'center' }
+      ],
+      transferOutTableColumn: [
+        { name: '航班号', prop: 'transferFlightNo', align: 'center' },
+        { name: '日期', prop: 'transferFlightDate', align: 'center' },
+        { name: '时间', prop: 'transferFlightTime', align: 'center' },
+        { name: '目的站', prop: 'destinationAirportName', align: 'center' },
+        { name: '中转数', prop: 'total', align: 'center' }
+      ],
+      tableCols:
+        this.$route.matched[0].path === '/arrival' || this.$route.matched[1].path === '/transfer/arrival'
+          ? arrivalBaggageTableColumn
+          : departureBaggageTableColumn,
+      containerTableData: [], // 容器统计
+      transferInTableData: [], // 中转进
+      transferOutTableData: [], // 中转出
+      baggageTableData: [] // 行列表
+    }
+  },
+  created() {
+    this.infoData = this._.cloneDeep(this.$route.query)
+    this.infoData['terminus'] = this['transfer_out_all']
+      ? this.infoData['checkin'] - this['transfer_out_all']
+      : this.infoData['checkin']
+    // console.log(this.infoData)
+    const dataIn = {
+      flightNO: this.infoData.FlightNO,
+      flightDate: this.infoData.FlightDate,
+      preFlightNO: true,
+      transferFlightNO: false
+    }
+    const dataOut = {
+      flightNO: this.infoData.FlightNO,
+      flightDate: this.infoData.FlightDate,
+      preFlightNO: false,
+      transferFlightNO: true
+    }
+    const containerData = {
+      flightNO: this.infoData.FlightNO,
+      flightDate: this.infoData.FlightDate,
+      preFlightNO: true,
+      transferFlightNO: true
+    }
+
+    const searchAllData = {
+      flightNO: this.infoData.FlightNO,
+      flightDate: this.infoData.FlightDate,
+      preFlightNO: true,
+      transferFlightNO: true
+    }
+    this.getbaggageSearchIn(dataIn)
+    this.getbaggageSearchOut(dataOut)
+    this.getBaggageSearchIOContainer(containerData)
+    this.getBaggageSearchIOAll(searchAllData)
+  },
+  methods: {
+    async getBaggageSearchIOAll(data) {
+      const getNodeInfo = node => `${node.locationPointDescribe ? node.locationPointDescribe : node.locationPoint}\n
+            ${node.realTime}`
+      try {
+        const result = await baggageSearchIOAll(data)
+        this.baggageTableData = result.returnData.map(element => {
+          element['nodeInfos'].forEach(node => {
+            switch (node.nodeCode) {
+              case 'CHECKIN':
+                element['checkIn'] = getNodeInfo(node)
+                break
+              case 'SECURITY':
+                element['security'] = getNodeInfo(node)
+                break
+              case 'SORT':
+                element['sorting'] = getNodeInfo(node)
+                break
+              case 'LOAD':
+                element['loading'] = getNodeInfo(node)
+                break
+              case 'INF':
+                element['installed'] = getNodeInfo(node)
+                break
+              case 'UNLOAD':
+                element['security'] = getNodeInfo(node)
+                element['arrival'] = getNodeInfo(node)
+                break
+              case 'TiQu':
+                element['extract'] = getNodeInfo(node)
+                break
+              default:
+                break
+            }
+          })
+          return element
+        })
+        // result.returnData.forEach(element => {
+        //   element['checkIn'] = element.checkInLocation + '\n' + element.checkInTime
+        //   element['security'] = element.securityStatus + '\n' + element.securityTime
+        //   element['sorting'] = element.sortingNo + '\n' + element.sortingTime
+        //   element['loading'] = element.loadingNumber + '\n' + element.loadingTime
+        //   element['installed'] = element.installedNumber + '\n' + element.installedTime
+        //   element['uninstall'] = element.uninstall + '\n' + element.uninstallTime
+        //   element['arrival'] = element.reach + '\n' + element.timeOfArrival
+        //   element['extract'] = element.extract + '\n' + element.extractionTime
+        // })
+        // this.baggageTableData = this._.cloneDeep(result.returnData)
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    async getBaggageSearchIOContainer(data) {
+      try {
+        const result = await baggageSearchIOContainer(data)
+        this.containerTableData = this._.cloneDeep(result.returnData)
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    async getbaggageSearchIn(data) {
+      try {
+        const result = await baggageSearchIO(data)
+        this.transferInTableData = this._.cloneDeep(result.returnData)
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    async getbaggageSearchOut(data) {
+      try {
+        const result = await baggageSearchIO(data)
+        this.transferOutTableData = this._.cloneDeep(result.returnData)
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    rowClick(row, column, event) {
+      row['flightNo'] = this.infoData.FlightNO
+      row['flightDate'] = this.infoData.FlightDate
+      this.$router.push({
+        path: `/${this.$route.path.split('/').slice(1, -1).join('/')}/baggageView`,
+        query: row
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.flight-view {
+  padding: 16px 8px 44px;
+  overflow: hidden;
+  background: #dfe3ea;
+  .flight-wrap {
+    width: 100%;
+    height: calc(100vh - 140px);
+    display: flex;
+    flex-direction: row;
+    justify-content: flex-start;
+    flex-wrap: wrap;
+    overflow: auto;
+    .part1 {
+      width: 71.15%;
+      height: 344px;
+      background: #041741;
+      padding: 24px;
+      .title {
+        font-size: 18px;
+        font-weight: bold;
+        color: #ffffff;
+      }
+      .part1_info {
+        width: 100%;
+        display: flex;
+        flex-direction: row;
+        justify-content: space-between;
+        padding-top: 32px;
+
+        .part1_info_box {
+          width: calc(33.333% - 48px);
+          height: 244px;
+          background: #2c416d;
+          position: relative;
+          padding: 24px;
+          display: flex;
+          flex-direction: column;
+          align-content: space-around;
+          .el-row {
+            margin-bottom: 27px;
+          }
+          span {
+            display: block;
+            font-size: 16px;
+            font-weight: 400;
+            color: #ffffff;
+          }
+        }
+        .part1_info_box::after {
+          content: '';
+          border-top: 15px solid transparent;
+          border-left: 10px solid transparent;
+          border-bottom: 10px solid #fff;
+          position: absolute;
+          right: -34px;
+          transform: rotate(-45deg);
+          top: 50%;
+          margin-top: -15px;
+        }
+        .part1_info_box:last-child::after {
+          content: '';
+          border-top: 0;
+          border-left: 0;
+          border-bottom: 0;
+        }
+      }
+    }
+    .part2 {
+      width: calc(100% - 71.15%);
+      height: 344px;
+      padding-left: 16px;
+    }
+    .part3 {
+      width: 50%;
+      height: 204px;
+      margin-top: 8px;
+      .title {
+        background: #fafcff;
+        font-size: 14px;
+        font-weight: bold;
+        color: #101116;
+        padding: 12px 0;
+        text-align: center;
+      }
+    }
+    .part4 {
+      width: 100%;
+      height: 384px;
+      .title {
+        padding: 16px 0;
+        display: flex;
+        flex-direction: row;
+        justify-content: flex-end;
+        align-items: center;
+        .search {
+          display: flex;
+          flex-direction: row;
+          margin-left: 20px;
+          margin-right: 10px;
+        }
+        .el-button {
+          margin-left: 10px;
+          &.btn-square {
+            width: 30px;
+            height: 30px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+          }
+        }
+        .setBtn {
+          margin-right: 30px;
+        }
+      }
+      ::v-deep .el-table .cell {
+        white-space: pre-line;
+      }
+      .el-table {
+        .el-table__body-wrapper {
+          min-height: 178px;
+        }
+      }
+    }
+  }
+}
+::v-deep .dialog-check-cols .el-tree {
+  &.has-children .el-tree-node > .el-tree-node__children {
+    display: flex;
+    flex-wrap: wrap;
+  }
+  &.no-children {
+    display: flex;
+    flex-wrap: wrap;
+  }
+}
+</style>

+ 27 - 0
src/views/baggageManagement/components/transferArrival/baggage.vue

@@ -0,0 +1,27 @@
+<!--
+ * @Author: Badguy
+ * @Date: 2022-03-09 11:51:26
+ * @LastEditTime: 2022-03-09 11:54:07
+ * @LastEditors: your name
+ * @Description: 中转进港行李视图
+ * have a nice day!
+-->
+
+<template>
+  <BaggageView />
+</template>
+
+<script>
+import BaggageView from '../baggage'
+
+export default {
+  name: 'TransferArrivalBaggageView',
+  components: {
+    BaggageView
+  }
+}
+</script>
+
+<style>
+
+</style>

+ 27 - 0
src/views/baggageManagement/components/transferArrival/flight.vue

@@ -0,0 +1,27 @@
+<!--
+ * @Author: Badguy
+ * @Date: 2022-03-09 11:49:13
+ * @LastEditTime: 2022-03-09 11:54:06
+ * @LastEditors: your name
+ * @Description: 中转进港行李视图
+ * have a nice day!
+-->
+
+<template>
+  <FlightView />
+</template>
+
+<script>
+import FlightView from '../flight'
+
+export default {
+  name: 'TransferArrivalFlightView',
+  components: {
+    FlightView
+  }
+}
+</script>
+
+<style>
+
+</style>

+ 488 - 0
src/views/baggageManagement/components/transferArrival/index.vue

@@ -0,0 +1,488 @@
+<!--
+ * @Author: Badguy
+ * @Date: 2022-02-09 16:35:57
+ * @LastEditTime: 2022-03-15 18:01:35
+ * @LastEditors: your name
+ * @Description: 中转01-进港
+ * have a nice day!
+-->
+
+<template>
+  <div class="terminal-arrival">
+    <div class="terminal-header">
+      <!--功能区-表单-->
+      <div class="terminal-form">
+        <el-form
+          ref="form"
+          :inline="true"
+          :model="formData"
+          :rules="rules"
+          class="form"
+        >
+          <el-form-item prop="currentAirport">
+            <el-cascader
+              v-model="formData.currentAirport"
+              style="width: 144px;"
+              placeholder="航站"
+              size="small"
+              :options="currentAirportOptions"
+              :props="currentAirportProps"
+              collapse-tags
+              clearable
+              filterable
+              @change="setCurrentAirport"
+            />
+          </el-form-item>
+          <el-form-item prop="inboundCarrier">
+            <el-cascader
+              v-model="formData.inboundCarrier"
+              style="width: 164px;"
+              size="small"
+              :options="inboundCarrierOptions"
+              :props="inboundCarrierProps"
+              placeholder="进港承运航司"
+              collapse-tags
+              clearable
+              filterable
+              @change="onSubmit"
+            />
+          </el-form-item>
+          <el-form-item prop="outgoingAirline">
+            <el-cascader
+              v-model="formData.outgoingAirline"
+              style="width: 164px;"
+              size="small"
+              :options="outgoingAirlineOptions"
+              :props="outgoingAirlineProps"
+              placeholder="离港承运航司"
+              collapse-tags
+              clearable
+              filterable
+              @change="onSubmit"
+            />
+          </el-form-item>
+          <el-form-item prop="craftType">
+            <el-cascader
+              v-model="formData.craftType"
+              style="width: 120px;"
+              size="small"
+              :options="craftTypeOptions"
+              :props="craftTypeProps"
+              placeholder="选择机型"
+              collapse-tags
+              clearable
+              filterable
+              @change="onSubmit"
+            />
+          </el-form-item>
+          <el-form-item prop="flightAttr">
+            <el-cascader
+              v-model="formData.flightAttr"
+              style="width: 120px;"
+              size="small"
+              :options="flightAttrOptions"
+              :props="flightAttrProps"
+              placeholder="航班类型"
+              collapse-tags
+              clearable
+              filterable
+              @change="onSubmit"
+            />
+          </el-form-item>
+          <el-form-item prop="startDate">
+            <el-date-picker
+              v-model="formData.startDate"
+              style="width: 216px;"
+              size="small"
+              type="date"
+              value-format="yyyy-MM-dd"
+              placeholder="开始时间"
+              @change="setStartDate"
+            />
+          </el-form-item>
+          <el-form-item prop="endDate">
+            <el-date-picker
+              v-model="formData.endDate"
+              style="width: 216px; margin-right: 104px"
+              size="small"
+              type="date"
+              value-format="yyyy-MM-dd"
+              placeholder="结束时间"
+              @change="setEndDate"
+            />
+          </el-form-item>
+          <el-form-item prop="search">
+            <el-input
+              v-model="formData.search"
+              style="width: 240px; margin-right: 4px"
+              size="small"
+              placeholder="请输入内容"
+              prefix-icon="el-icon-search"
+              @keyup.enter="onSubmit"
+            />
+          </el-form-item>
+          <el-form-item>
+            <el-button
+              size="small"
+              type="primary"
+              class="btn-search"
+              @click="onSubmit"
+            >搜索</el-button>
+          </el-form-item>
+          <el-form-item v-is="['ti_showTransit']">
+            <el-button
+              size="small"
+              type="primary"
+              @click="changeView"
+            >切换视角</el-button>
+          </el-form-item>
+          <el-form-item v-is="['ti_timeIcon']">
+            <el-dropdown>
+              <img
+                class="checkTime msgImg"
+                src="@/assets/departure/ic_time.png"
+              >
+              <el-dropdown-menu
+                slot="dropdown"
+                class="time-zone"
+              >
+                <el-dropdown-item>国内Local/国际UTC</el-dropdown-item>
+                <el-dropdown-item>Local</el-dropdown-item>
+                <el-dropdown-item>UTC</el-dropdown-item>
+              </el-dropdown-menu>
+            </el-dropdown>
+          </el-form-item>
+          <el-form-item v-is="['ti_columnSettings']">
+            <img
+              class="msgImg"
+              src="@/assets/departure/ic_setting.png"
+              @click="show"
+            >
+          </el-form-item>
+        </el-form>
+      </div>
+    </div>
+    <!--表格-->
+    <div
+      v-loading="loading"
+      element-loading-text="拼命加载中"
+      element-loading-spinner="el-icon-loading"
+      element-loading-background="rgba(0, 0, 0, 0.8)"
+      class="terminal-table"
+    >
+      <el-table
+        ref="table"
+        :data="tableData"
+        class="table"
+        max-height="100%"
+        :height="computedTableHeight"
+        :span-method="tableSpanMethod"
+        show-summary
+        :summary-method="summaryMethod"
+        border
+        stripe
+        @row-click="rowClick"
+      >
+        <el-table-column
+          v-for="(item,index) in tableColsCopy"
+          :key="index"
+          :prop="item.statCode"
+          :label="item.statName"
+        >
+          <el-table-column
+            v-for="(p,i) in item.children"
+            :key="i"
+            :prop="p.statCode"
+            :label="p.statName"
+            :formatter="tableFormat"
+          />
+        </el-table-column>
+      </el-table>
+    </div>
+    <!--列设置-->
+    <Dialog
+      :flag="dialogFlag"
+      class="dialog-check-cols"
+    >
+      <div class="colDialog">
+        <div class="title">列设置</div>
+        <div class="content">
+          <el-tree
+            :data="tableCols"
+            :class="colsCheckClass"
+            show-checkbox
+            node-key="index"
+            :default-expand-all="true"
+            :props="{
+              label: 'statName',
+              children: 'children'
+            }"
+            :default-checked-keys="checkedKeysTemp"
+            @check="handleCheck"
+          />
+        </div>
+        <div class="foot right t30">
+          <el-button
+            size="medium"
+            class="r24"
+            type="primary"
+            @click="onCheck"
+          >确定</el-button>
+          <el-button
+            size="medium"
+            @click="hide"
+          >取消</el-button>
+        </div>
+      </div>
+    </Dialog>
+  </div>
+</template>
+
+<script>
+import Dialog from '@/layout/components/Dialog'
+import terminalMixin from '../../mixins/terminal'
+import formMixin from '../../mixins/form'
+import tableColsMixin from '../../mixins/tableCols'
+
+export default {
+  name: 'TransferArrivalTerminalView',
+  components: {
+    Dialog
+  },
+  mixins: [terminalMixin, formMixin, tableColsMixin],
+  data() {
+    return {
+      // 初始表头
+      tableCols: [
+        {
+          statCode: 'arrivalInfo',
+          statName: '进港航班',
+          children: [
+            {
+              statCode: 'FlightNO',
+              statName: '航班号',
+              width: 122
+            },
+            {
+              statCode: 'FlightDate',
+              statName: '航班日期',
+              width: 83
+            },
+            {
+              statCode: 'PlanLandingTime',
+              statName: '进港时间',
+              width: 79
+            },
+            {
+              statCode: 'PlanDepartureApt',
+              statName: '始飞站',
+              width: 58
+            },
+            {
+              statCode: 'LandingBuild',
+              statName: '航站楼',
+              width: 63
+            },
+            {
+              statCode: 'Carousel',
+              statName: '行李转盘',
+              width: 84
+            },
+            {
+              statCode: 'StandForLanding',
+              statName: '停机位',
+              width: 63
+            },
+            {
+              statCode: 'positionDistribution',
+              statName: '仓位分布',
+              width: 98
+            },
+            {
+              statCode: 'expect_load',
+              statName: '转运数',
+              width: 103
+            },
+            {
+              statCode: 'loadflight',
+              statName: '已装载',
+              width: 81
+            }
+          ]
+        },
+        {
+          statCode: 'transferInfo',
+          statName: '转运信息',
+          children: [
+            {
+              statCode: 'transfer_time',
+              statName: '转运时间',
+              width: 92
+            },
+            {
+              statCode: 'transfer_status',
+              statName: '状态',
+              width: 108
+            }
+          ]
+        },
+        {
+          statCode: 'departureInfo',
+          statName: '离港航班',
+          children: [
+            {
+              statCode: 'transfer_number',
+              statName: '转运数',
+              width: 81
+            },
+            {
+              statCode: 'transfer_loaded',
+              statName: '已装载',
+              width: 100
+            },
+            {
+              statCode: 'TransferFlightPlanDepartureTime',
+              statName: '离港时间',
+              width: 93
+            },
+            {
+              statCode: 'TransferFlightNO',
+              statName: '航班号',
+              width: 106
+            },
+            {
+              statCode: 'TransferFlightDate',
+              statName: '航班日期',
+              width: 107
+            },
+            {
+              statCode: 'TransferFlightPlanLandingApt',
+              statName: '目的站',
+              width: 85
+            },
+            {
+              statCode: 'TransferDepartureBuild',
+              statName: '航站楼',
+              width: 78
+            },
+            {
+              statCode: 'TransferBordingGate',
+              statName: '登机口',
+              width: 73
+            },
+            {
+              statCode: 'TransferStandForDepartrue',
+              statName: '停机位',
+              width: 83
+            }
+          ]
+        }
+      ]
+    }
+  },
+  methods: {
+    // 获取表单下拉框数据
+    getFormData(params) {
+      this.inboundCarrierQuery(params)
+      this.outgoingAirlineQuery(params)
+      this.craftTypeQuery(params)
+      this.flightAttrQuery(params)
+    },
+    // 获取表格数据
+    getTableData(params) {
+      this.integratedQueryTransfer({
+        ...params,
+        type: 'IN'
+      })
+    },
+    changeView() {
+      this.$router.replace({
+        path: '/transfer/departure'
+      })
+    },
+    // 行合并
+    // initTableData(tableData) {
+    //   this.tableData = mergeTableRow({
+    //     data: this._.sortBy(tableData, ['FlightDate', 'PlanLandingTime']),
+    //     mergeColNames: [
+    //       'FlightNO',
+    //       'FlightDate',
+    //       'PlanLandingTime',
+    //       'PlanDepartureApt',
+    //       'LandingBuild',
+    //       'Carousel',
+    //       'StandForLanding',
+    //       'positionDistribution',
+    //       'expect_load',
+    //       'loadflight'
+    //     ],
+    //     firstMergeColNames: [
+    //       'FlightDate',
+    //       'PlanLandingTime',
+    //       'PlanDepartureApt',
+    //       'LandingBuild',
+    //       'Carousel',
+    //       'StandForLanding',
+    //       'positionDistribution',
+    //       'expect_load',
+    //       'loadflight'
+    //     ],
+    //     firstMerge: 'FlightNO'
+    //   })
+    // },
+    initTableData(tableData) {
+      const spanArr = []
+      let pos = 0
+      tableData = this._.sortBy(tableData, [
+        'FlightDate',
+        'PlanLandingTime',
+        'TransferFlightDate',
+        'TransferFlightPlanDepartureTime'
+      ])
+      for (let i = 0; i < tableData.length; i++) {
+        if (i === 0) {
+          spanArr.push(1)
+        } else {
+          if (tableData[i]['FlightNO'] === tableData[i - 1]['FlightNO']) {
+            spanArr[pos] += 1
+            spanArr.push(0)
+          } else {
+            spanArr.push(1)
+            pos = i
+          }
+        }
+      }
+      this.spanArr = spanArr
+      this.pos = pos
+      this.tableData = tableData
+    },
+    tableSpanMethod({ row, column, rowIndex, columnIndex }) {
+      if (
+        [
+          'FlightNO',
+          'FlightDate',
+          'PlanLandingTime',
+          'PlanDepartureApt',
+          'LandingBuild',
+          'Carousel',
+          'StandForLanding',
+          'positionDistribution',
+          'expect_load',
+          'loadflight'
+        ].includes(column['property'])
+      ) {
+        const _row = this.spanArr[rowIndex]
+        const _col = _row > 0 ? 1 : 0
+        return {
+          rowspan: _row,
+          colspan: _col
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import '../../style/transfer.scss';
+</style>

+ 27 - 0
src/views/baggageManagement/components/transferDeparture/baggage.vue

@@ -0,0 +1,27 @@
+<!--
+ * @Author: Badguy
+ * @Date: 2022-03-09 11:51:26
+ * @LastEditTime: 2022-03-09 11:54:15
+ * @LastEditors: your name
+ * @Description: 中转离港行李视图
+ * have a nice day!
+-->
+
+<template>
+  <BaggageView />
+</template>
+
+<script>
+import BaggageView from '../baggage'
+
+export default {
+  name: 'TransferDepartureBaggageView',
+  components: {
+    BaggageView
+  }
+}
+</script>
+
+<style>
+
+</style>

+ 27 - 0
src/views/baggageManagement/components/transferDeparture/flight.vue

@@ -0,0 +1,27 @@
+<!--
+ * @Author: Badguy
+ * @Date: 2022-03-09 11:49:13
+ * @LastEditTime: 2022-03-09 11:54:48
+ * @LastEditors: your name
+ * @Description: 中转离港行李视图
+ * have a nice day!
+-->
+
+<template>
+  <FlightView />
+</template>
+
+<script>
+import FlightView from '../flight'
+
+export default {
+  name: 'TransferDepartureFlightView',
+  components: {
+    FlightView
+  }
+}
+</script>
+
+<style>
+
+</style>

+ 483 - 0
src/views/baggageManagement/components/transferDeparture/index.vue

@@ -0,0 +1,483 @@
+<!--
+ * @Author: Badguy
+ * @Date: 2022-02-09 16:36:40
+ * @LastEditTime: 2022-03-15 18:02:46
+ * @LastEditors: your name
+ * @Description: 中转01-出港
+ * have a nice day!
+-->
+
+<template>
+  <div class="terminal-departure">
+    <div class="terminal-header">
+      <!--功能区-表单-->
+      <div class="terminal-form">
+        <el-form
+          ref="form"
+          :inline="true"
+          :model="formData"
+          :rules="rules"
+          class="form"
+        >
+          <el-form-item prop="currentAirport">
+            <el-cascader
+              v-model="formData.currentAirport"
+              style="width: 144px;"
+              placeholder="航站"
+              size="small"
+              :options="currentAirportOptions"
+              :props="currentAirportProps"
+              collapse-tags
+              clearable
+              filterable
+              @change="setCurrentAirport"
+            />
+          </el-form-item>
+          <el-form-item prop="outgoingAirline">
+            <el-cascader
+              v-model="formData.outgoingAirline"
+              style="width: 164px;"
+              size="small"
+              :options="outgoingAirlineOptions"
+              :props="outgoingAirlineProps"
+              placeholder="离港承运航司"
+              collapse-tags
+              clearable
+              filterable
+              @change="onSubmit"
+            />
+          </el-form-item>
+          <el-form-item prop="inboundCarrier">
+            <el-cascader
+              v-model="formData.inboundCarrier"
+              style="width: 164px;"
+              size="small"
+              :options="inboundCarrierOptions"
+              :props="inboundCarrierProps"
+              placeholder="进港承运航司"
+              collapse-tags
+              clearable
+              filterable
+              @change="onSubmit"
+            />
+          </el-form-item>
+          <el-form-item prop="craftType">
+            <el-cascader
+              v-model="formData.craftType"
+              style="width: 120px;"
+              size="small"
+              :options="craftTypeOptions"
+              :props="craftTypeProps"
+              placeholder="选择机型"
+              collapse-tags
+              clearable
+              filterable
+              @change="onSubmit"
+            />
+          </el-form-item>
+          <el-form-item prop="flightAttr">
+            <el-cascader
+              v-model="formData.flightAttr"
+              style="width: 120px;"
+              size="small"
+              :options="flightAttrOptions"
+              :props="flightAttrProps"
+              placeholder="航班类型"
+              collapse-tags
+              clearable
+              filterable
+              @change="onSubmit"
+            />
+          </el-form-item>
+          <el-form-item prop="startDate">
+            <el-date-picker
+              v-model="formData.startDate"
+              style="width: 216px;"
+              size="small"
+              type="date"
+              value-format="yyyy-MM-dd"
+              placeholder="开始时间"
+              @change="setStartDate"
+            />
+          </el-form-item>
+          <el-form-item prop="endDate">
+            <el-date-picker
+              v-model="formData.endDate"
+              style="width: 216px;  margin-right: 104px"
+              size="small"
+              type="date"
+              value-format="yyyy-MM-dd"
+              placeholder="结束时间"
+              @change="setEndDate"
+            />
+          </el-form-item>
+          <el-form-item prop="search">
+            <el-input
+              v-model="formData.search"
+              style="width: 240px; margin-right: 4px"
+              size="small"
+              placeholder="请输入内容"
+              prefix-icon="el-icon-search"
+              @keyup.enter="onSubmit"
+            />
+          </el-form-item>
+          <el-form-item>
+            <el-button
+              size="small"
+              type="primary"
+              class="btn-search"
+              @click="onSubmit"
+            >搜索</el-button>
+          </el-form-item>
+          <el-form-item v-is="['td_showTransit']">
+            <el-button
+              size="small"
+              type="primary"
+              @click="changeView"
+            >切换视角</el-button>
+          </el-form-item>
+          <el-form-item v-is="['td_timeIcon']">
+            <el-dropdown>
+              <img
+                class="checkTime msgImg"
+                src="@/assets/departure/ic_time.png"
+              >
+              <el-dropdown-menu
+                slot="dropdown"
+                class="time-zone"
+              >
+                <el-dropdown-item>国内Local/国际UTC</el-dropdown-item>
+                <el-dropdown-item>Local</el-dropdown-item>
+                <el-dropdown-item>UTC</el-dropdown-item>
+              </el-dropdown-menu>
+            </el-dropdown>
+          </el-form-item>
+          <el-form-item v-is="['td_columnSettings']">
+            <img
+              class="msgImg"
+              src="@/assets/departure/ic_setting.png"
+              @click="show"
+            >
+          </el-form-item>
+        </el-form>
+      </div>
+    </div>
+    <!--表格-->
+    <div
+      v-loading="loading"
+      element-loading-text="拼命加载中"
+      element-loading-spinner="el-icon-loading"
+      element-loading-background="rgba(0, 0, 0, 0.8)"
+      class="terminal-table"
+    >
+      <el-table
+        ref="table"
+        :data="tableData"
+        class="table"
+        :height="computedTableHeight"
+        max-height="100%"
+        :span-method="tableSpanMethod"
+        show-summary
+        :summary-method="summaryMethod"
+        border
+        stripe
+        @row-click="rowClick"
+      >
+        <el-table-column
+          v-for="(item,index) in tableColsCopy"
+          :key="index"
+          :prop="item.statCode"
+          :label="item.statName"
+        >
+          <el-table-column
+            v-for="(p,i) in item.children"
+            :key="i"
+            :prop="p.statCode"
+            :label="p.statName"
+            :formatter="tableFormat"
+          />
+        </el-table-column>
+      </el-table>
+    </div>
+    <!--列设置-->
+    <Dialog
+      :flag="dialogFlag"
+      class="dialog-check-cols"
+    >
+      <div class="colDialog">
+        <div class="title">列设置</div>
+        <div class="content">
+          <el-tree
+            :data="tableCols"
+            :class="colsCheckClass"
+            show-checkbox
+            node-key="index"
+            :default-expand-all="true"
+            :props="{
+              label: 'statName',
+              children: 'children'
+            }"
+            :default-checked-keys="checkedKeysTemp"
+            @check="handleCheck"
+          />
+        </div>
+        <div class="foot right t30">
+          <el-button
+            size="medium"
+            class="r24"
+            type="primary"
+            @click="onCheck"
+          >确定</el-button>
+          <el-button
+            size="medium"
+            @click="hide"
+          >取消</el-button>
+        </div>
+      </div>
+    </Dialog>
+  </div>
+</template>
+
+<script>
+import Dialog from '@/layout/components/Dialog'
+// import { mergeTableRow } from '@/utils/table'
+import terminalMixin from '../../mixins/terminal'
+import formMixin from '../../mixins/form'
+import tableColsMixin from '../../mixins/tableCols'
+
+export default {
+  name: 'TransferDepartureTerminalView',
+  components: {
+    Dialog
+  },
+  mixins: [terminalMixin, formMixin, tableColsMixin],
+  data() {
+    return {
+      // 初始表头
+      tableCols: [
+        {
+          statCode: 'departureInfo',
+          statName: '离港航班',
+          children: [
+            {
+              statCode: 'FlightNO',
+              statName: '航班号',
+              width: 105
+            },
+            {
+              statCode: 'FlightDate',
+              statName: '航班日期',
+              width: 88
+            },
+            {
+              statCode: 'PlanDepartureTime',
+              statName: '离港时间',
+              width: 83
+            },
+            {
+              statCode: 'PlanLandingApt',
+              statName: '目的站',
+              width: 57
+            },
+            {
+              statCode: 'DepartureBuild',
+              statName: '航站楼',
+              width: 68
+            },
+            {
+              statCode: 'Carousel',
+              statName: '行李转盘',
+              width: 84
+            },
+            {
+              statCode: 'StandForDepartrue',
+              statName: '停机位',
+              width: 67
+            },
+            {
+              statCode: 'positionDistribution',
+              statName: '仓位分布',
+              width: 98
+            },
+            {
+              statCode: 'expect_load',
+              statName: '转运数',
+              width: 103
+            },
+            {
+              statCode: 'loadflight',
+              statName: '已装载',
+              width: 81
+            }
+          ]
+        },
+        {
+          statCode: 'transferInfo',
+          statName: '转运信息',
+          children: [
+            {
+              statCode: 'transfer_time',
+              statName: '转运时间',
+              width: 92
+            },
+            {
+              statCode: 'transfer_status',
+              statName: '状态',
+              width: 108
+            }
+          ]
+        },
+        {
+          statCode: 'arrivalInfo',
+          statName: '进港航班',
+          children: [
+            {
+              statCode: 'transfer_number',
+              statName: '转运数',
+              width: 81
+            },
+            {
+              statCode: 'transfer_loaded',
+              statName: '已装载',
+              width: 100
+            },
+            {
+              statCode: 'PrePlanLandingTime',
+              statName: '进港时间',
+              width: 93
+            },
+            {
+              statCode: 'PreFlightNO',
+              statName: '航班号',
+              width: 106
+            },
+            {
+              statCode: 'PreFlightDate',
+              statName: '航班日期',
+              width: 107
+            },
+            {
+              statCode: 'PrePlanDepartureApt',
+              statName: '始飞站',
+              width: 70
+            },
+            {
+              statCode: 'PrePlanLandingBuild',
+              statName: '航站楼',
+              width: 70
+            },
+            {
+              statCode: 'PreBoardingGate',
+              statName: '登机口',
+              width: 71
+            },
+            {
+              statCode: 'PreStandForLanding',
+              statName: '停机位'
+            }
+          ]
+        }
+      ]
+    }
+  },
+  methods: {
+    // 获取表单下拉框数据
+    getFormData(params) {
+      this.inboundCarrierQuery(params)
+      this.outgoingAirlineQuery(params)
+      this.craftTypeQuery(params)
+      this.flightAttrQuery(params)
+    },
+    // 获取表格数据
+    getTableData(params) {
+      this.integratedQueryTransfer({
+        ...params,
+        type: 'OUT'
+      })
+    },
+    changeView() {
+      this.$router.replace({
+        path: '/transfer/arrival'
+      })
+    },
+    // 行合并
+    // initTableData() {
+    //   this.tableData = mergeTableRow({
+    //     data: this.tableData,
+    //     mergeColNames: [
+    //       'departureFlight',
+    //       'departureDate',
+    //       'departureTime',
+    //       'destinationStation',
+    //       'departureTerminal',
+    //       'baggageTurntable',
+    //       'departurePosition',
+    //       'cabin',
+    //       'departureExpectedLoad',
+    //       'departureAlreadyLoad'
+    //     ],
+    //     firstMergeColNames: [
+    //       'departureDate',
+    //       'departureTime',
+    //       'destinationStation',
+    //       'departureTerminal',
+    //       'baggageTurntable',
+    //       'departurePosition',
+    //       'cabin',
+    //       'departureExpectedLoad',
+    //       'departureAlreadyLoad'
+    //     ],
+    //     firstMerge: 'departureFlight'
+    //   })
+    // },
+    initTableData(tableData) {
+      const spanArr = []
+      let pos = 0
+      tableData = this._.sortBy(tableData, ['FlightDate', 'PlanDepartureTime', 'PreFlightDate', 'PrePlanLandingTime'])
+      for (let i = 0; i < tableData.length; i++) {
+        if (i === 0) {
+          spanArr.push(1)
+        } else {
+          if (tableData[i]['FlightNO'] === tableData[i - 1]['FlightNO']) {
+            spanArr[pos] += 1
+            spanArr.push(0)
+          } else {
+            spanArr.push(1)
+            pos = i
+          }
+        }
+      }
+      this.spanArr = spanArr
+      this.pos = pos
+      this.tableData = tableData
+    },
+    tableSpanMethod({ row, column, rowIndex, columnIndex }) {
+      if (
+        [
+          'FlightNO',
+          'FlightDate',
+          'PlanDepartureTime',
+          'PlanLandingApt',
+          'DepartureBuild',
+          'Carousel',
+          'StandForDepartrue',
+          'positionDistribution',
+          'expect_load',
+          'loadflight'
+        ].includes(column['property'])
+      ) {
+        const _row = this.spanArr[rowIndex]
+        const _col = _row > 0 ? 1 : 0
+        return {
+          rowspan: _row,
+          colspan: _col
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import '../../style/transfer.scss';
+</style>

+ 25 - 0
src/views/baggageManagement/index.vue

@@ -0,0 +1,25 @@
+<!--
+ * @Author: Badguy
+ * @Date: 2022-02-23 11:22:45
+ * @LastEditTime: 2022-03-09 16:17:28
+ * @LastEditors: your name
+ * @Description: 行李管理
+ * have a nice day!
+-->
+
+<template>
+  <keep-alive :include="keepAlivePages">
+    <router-view />
+  </keep-alive>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+
+export default {
+  name: 'BaggageManagement',
+  computed: {
+    ...mapGetters(['keepAlivePages'])
+  }
+}
+</script>

+ 233 - 0
src/views/baggageManagement/mixins/form.js

@@ -0,0 +1,233 @@
+/*
+ * @Author: Badguy
+ * @Date: 2022-03-04 14:45:03
+ * @LastEditTime: 2022-03-15 15:53:28
+ * @LastEditors: your name
+ * @Description: 航站视图通用表单部分
+ * have a nice day!
+ */
+
+import { parseTime } from '@/utils'
+// const defaultStartTime = new Date(new Date(new Date().toLocaleDateString()).getTime())
+// const defaultEndTime = new Date(new Date(new Date().toLocaleDateString()).getTime() + 24 * 60 * 60 * 1000 - 1)
+const defaultDate = parseTime(new Date(), '{y}-{m}-{d}')
+export default {
+  data() {
+    return {
+      formData: {
+        // 搜索表单数据
+        currentAirport: [],
+        relatedAirport: [],
+        inboundCarrier: [],
+        outgoingAirline: [],
+        craftType: [],
+        flightAttr: [],
+        startDate: defaultDate,
+        endDate: defaultDate,
+        search: '',
+        switch: true
+      },
+      currentAirportOptions: [],
+      relatedAirportOptions: [],
+      inboundCarrierOptions: [],
+      outgoingAirlineOptions: [],
+      craftTypeOptions: [],
+      flightAttrOptions: [],
+      currentAirportProps: {
+        // multiple: true,
+        checkStrictly: true,
+        expandTrigger: 'hover',
+        value: 'code3',
+        label: 'name',
+        children: 'builds'
+      },
+      relatedAirportProps: {
+        multiple: true,
+        value: 'code3',
+        label: 'name'
+      },
+      inboundCarrierProps: {
+        multiple: true,
+        value: 'code2',
+        label: 'name'
+      },
+      outgoingAirlineProps: {
+        multiple: true,
+        value: 'code2',
+        label: 'name'
+      },
+      craftTypeProps: {
+        multiple: true,
+        value: 'code3',
+        label: 'name'
+      },
+      flightAttrProps: {
+        multiple: true,
+        value: 'code',
+        label: 'name'
+      },
+      // 表单规则
+      rules: {
+        currentAirport: [{ required: true, message: '请选择当前机场', trigger: 'change' }],
+        startDate: [{ required: true, message: '请选择开始时间', trigger: 'change' }],
+        endDate: [{ required: true, message: '请选择结束时间', trigger: 'change' }]
+      }
+    }
+  },
+  computed: {
+    currentAirport() {
+      return this.getSingleData(this.formData.currentAirport)
+    },
+    relatedAirport() {
+      return this.formData.relatedAirport.map(item => item[0])
+    },
+    inboundCarrier() {
+      return this.formData.inboundCarrier.map(item => item[0])
+    },
+    outgoingAirline() {
+      return this.formData.outgoingAirline.map(item => item[0])
+    },
+    craftType() {
+      return this.formData.craftType.map(item => item[0])
+    },
+    flightAttr() {
+      return this.formData.flightAttr.map(item => item[0])
+    },
+    startDate() {
+      // return parseTime(this.formData.startDate).split(' ')[0]
+      return this.formData.startDate
+    },
+    endDate() {
+      // return parseTime(this.formData.endDate).split(' ')[0]
+      return this.formData.endDate
+    },
+    computedTableHeight() {
+      const { relatedAirport, inboundCarrier, outgoingAirline, craftType, flightAttr } = this.formData
+      return relatedAirport.length ||
+        inboundCarrier.length ||
+        outgoingAirline.length ||
+        craftType.length ||
+        flightAttr.length
+        ? 'calc(100vh - 191px)'
+        : 'calc(100vh - 177px)'
+    }
+  },
+  methods: {
+    // 机场数据处理(多选)
+    getMultipleData(arr) {
+      const newArr = []
+      arr.length &&
+        arr.forEach(airport => {
+          const temp = this._.cloneDeep(this.currentAirportOptions.find(airport1 => airport1.code3 === airport[0]))
+          if (temp) {
+            temp.builds = airport[1] ? [{ name: airport[1] }] : []
+            const item = newArr.find(item => item.code3 === temp.code3)
+            if (item) {
+              item.builds.push(...temp.builds)
+            } else {
+              newArr.push(temp)
+            }
+          }
+        })
+      return newArr
+    },
+    // 机场数据处理(单选)
+    getSingleData(arr) {
+      const newArr = []
+      if (arr.length > 0) {
+        const temp = this._.cloneDeep(this.currentAirportOptions.find(airport1 => airport1.code3 === arr[0]))
+        if (temp) {
+          temp.builds = arr[1] ? [{ name: arr[1] }] : []
+          newArr.push(temp)
+        }
+      }
+      return newArr
+    },
+    // 清除表单数据
+    formClear(range) {
+      if (range === 'all') {
+        this.formData.currentAirport = []
+        this.currentAirportOptions = []
+      }
+      this.formData.relatedAirport = []
+      this.relatedAirportOptions = []
+      this.formData.inboundCarrier = []
+      this.inboundCarrierOptions = []
+      this.formData.outgoingAirline = []
+      this.outgoingAirlineOptions = []
+      this.formData.craftType = []
+      this.craftTypeOptions = []
+      this.formData.flightAttr = []
+      this.flightAttrOptions = []
+    },
+    // 文本框清除
+    inputClear() {
+      this.onSubmit()
+    },
+    // 当前机场变更
+    setCurrentAirport(data) {
+      this.formClear()
+      if (data.length === 0) {
+        return
+      }
+      const params = {
+        currentAirport: this.currentAirport,
+        startDate: this.startDate,
+        endDate: this.endDate
+      }
+      this.getFormData(params)
+    },
+    // 日期限制
+    setStartDate(val) {
+      this.formClear('all')
+      if (!val) {
+        return
+      }
+      if (this.formData.endDate && this.formData.endDate < val) {
+        this.formData.endDate = ''
+        this.$message.error('结束时间不能小于开始时间,请重新选择')
+        return false
+      } else {
+        // this.getFormData(params)
+        this.currentAirportQuery()
+        return true
+      }
+    },
+    setEndDate(val) {
+      this.formClear('all')
+      if (!val) {
+        return
+      }
+      if (this.formData.startDate && this.formData.startDate > val) {
+        this.formData.endDate = ''
+        this.$message.error('结束时间不能小于开始时间,请重新选择')
+        return false
+      } else {
+        // this.getFormData(params)
+        this.currentAirportQuery()
+        return true
+      }
+    },
+    // 搜索
+    onSubmit() {
+      this.$refs['form'].validate(valid => {
+        if (valid) {
+          const { search } = this.formData
+          const params = {
+            currentAirport: this.currentAirport,
+            relatedAirport: this.relatedAirport,
+            inboundCarrier: this.inboundCarrier,
+            craftType: this.craftType,
+            flightAttr: this.flightAttr,
+            startDate: this.startDate,
+            endDate: this.endDate,
+            world: search
+          }
+          this.getTableData(params)
+        } else {
+          return false
+        }
+      })
+    }
+  }
+}

+ 95 - 0
src/views/baggageManagement/mixins/tableCols.js

@@ -0,0 +1,95 @@
+/*
+ * @Author: Badguy
+ * @Date: 2022-03-04 11:50:22
+ * @LastEditTime: 2022-03-15 17:56:34
+ * @LastEditors: your name
+ * @Description: 航站视图表格通用部分
+ * have a nice day!
+ */
+
+export default {
+  data() {
+    return {
+      // 筛选后表头
+      tableColsCopy: [],
+      // 列设置弹框选中
+      checkedKeys: [],
+      checkedKeysTemp: [],
+      halfCheckedKeys: [],
+      // 列设置弹框开关
+      dialogFlag: false
+    }
+  },
+  created() {
+    this.initTableCols()
+  },
+  updated() {
+    // table数据更新
+    this.$nextTick(() => {
+      this.$refs.table?.doLayout()
+    })
+  },
+  computed: {
+    colsCheckClass() {
+      return this.tableCols.some(col => col.children?.length) ? 'has-children' : 'no-children'
+    }
+  },
+  methods: {
+    // 列设置-初始化
+    initTableCols() {
+      this.setTableCols(this.tableCols)
+      this.tableColsCopy = this._.cloneDeep(this.tableCols)
+      this.checkedKeysTemp = [...this.checkedKeys]
+    },
+    setTableCols(cols) {
+      for (const col of cols) {
+        col.index = this.checkedKeys.length
+        this.checkedKeys.push(this.checkedKeys.length)
+        if (col.children?.length) {
+          this.setTableCols(col.children)
+        }
+      }
+    },
+    // 列设置-确定
+    handleCheck(data, checked) {
+      this.checkedKeysTemp = [...checked.checkedKeys]
+      this.halfCheckedKeys = [...checked.halfCheckedKeys]
+    },
+    onCheck() {
+      if (this.dialogFlag === false) {
+        return
+      }
+      this.loading = true
+      const tableDataTemp = this._.cloneDeep(this.tableData)
+      this.tableData = []
+      this.dialogFlag = false
+      this.checkedKeys = [...this.checkedKeysTemp]
+      this.tableColsCopy = this.colsFilter(this._.cloneDeep(this.tableCols))
+      setTimeout(() => {
+        this.tableData = tableDataTemp
+        this.loading = false
+      }, 1000)
+    },
+    colsFilter(cols) {
+      const temp = cols.filter(col => {
+        if (this.halfCheckedKeys.includes(col.index)) {
+          col.children = this.colsFilter(col.children)
+          return true
+        } else if (this.checkedKeys.includes(col.index)) {
+          return true
+        }
+        return false
+      })
+      return temp
+    },
+    // 弹框展开
+    show() {
+      this.dialogFlag = true
+    },
+    // 弹框关闭
+    hide() {
+      this.dialogFlag = false
+      this.checkedKeysTemp = [...this.checkedKeys]
+    }
+  }
+}

+ 272 - 0
src/views/baggageManagement/mixins/terminal.js

@@ -0,0 +1,272 @@
+/*
+ * @Author: Badguy
+ * @Date: 2022-03-04 11:41:55
+ * @LastEditTime: 2022-03-15 16:20:08
+ * @LastEditors: your name
+ * @Description: 航站视图通用部分
+ * have a nice day!
+ */
+
+import {
+  CurrentAirportQuery,
+  RelatedAirportQuery,
+  AirCompanyQuery,
+  CraftTypeQuery,
+  FlightAttrQuery,
+  IntegratedQuery,
+  IntegratedQueryTransfer
+} from '@/api/flight'
+
+export default {
+  data() {
+    return {
+      // 表格数据
+      tableData: [],
+      spanArr: [],
+      pos: 0,
+      loading: false
+    }
+  },
+  created() {
+    this.currentAirportQuery()
+  },
+  methods: {
+    // 数据处理
+    formatData(arr) {
+      arr.forEach(item => {
+        item['name'] = item['name'] + item['code3']
+        item.builds &&
+          item.builds.forEach(p => {
+            p['code3'] = p.name
+          })
+      })
+      return arr
+    },
+    // 表格数据格式化
+    tableFormat(row, column, cellValue) {
+      if (cellValue || cellValue === 0) {
+        switch (column.property) {
+          case 'FlightDate':
+            return cellValue.split('-').slice(1).join('-')
+          case 'PlanLandingTime':
+          case 'PlanDepartureTime':
+          case 'PrePlanLandingTime':
+          case 'TransferFlightPlanDepartureTime':
+            return cellValue.split('T')[1].split(':').slice(0, 2).join(':')
+          default:
+            return cellValue
+        }
+      } else {
+        return ''
+      }
+    },
+    // 合计行
+    summaryMethod({ columns, data }) {
+      const sums = []
+      if (columns.length > 0) {
+        columns.forEach((column, index) => {
+          if (index === 0) {
+            sums[index] = '合计'
+          } else if (
+            // 需要计算的列
+            [
+              'passagernum',
+              'checkin',
+              'not_actived',
+              'expect_load',
+              'security_all',
+              'fenj',
+              'loadcar',
+              'loadflight',
+              'waitfanj',
+              'hasfanj',
+              'delbag',
+              'no_bsm',
+              'transfer_all',
+              'reach',
+              'did_not_arrive',
+              'special',
+              'claim',
+              'uninstalled',
+              'to_be_uninstalled',
+              'terminateArrive',
+              'terminatedNotArrived',
+              'delivered',
+              'not_shipped',
+              'container',
+              'bulk'
+            ].includes(column.property)
+          ) {
+            let values = data.map(item => Number(item[column.property]))
+            if (values.some(value => !isNaN(value))) {
+              sums[index] = values.reduce((prev, curr) => {
+                const value = Number(curr)
+                if (!isNaN(value)) {
+                  let num = Number(prev) + Number(curr)
+                  return num
+                } else {
+                  return Number(prev)
+                }
+              }, 0)
+            } else {
+              sums[index] = 0
+            }
+          } else {
+            //过滤某些字段不参与计算
+            sums[index] = '-'
+          }
+        })
+      }
+      return sums
+    },
+    // 表格行点击跳转
+    rowClick(row, column, event) {
+      this.$router.push({
+        path: `/${this.$route.path.split('/').slice(1, -1).join('/')}/flightView`,
+        query: row
+      })
+    },
+    // 全部机场查询
+    async currentAirportQuery() {
+      const params = {
+        startDate: this.startDate,
+        endDate: this.endDate
+      }
+      try {
+        const res = await CurrentAirportQuery(params)
+        if (res.code === 0) {
+          if (res.returnData.length) {
+            const datas = this.formatData(res.returnData)
+            const datasCopy = this._.cloneDeep(datas)
+            this.currentAirportOptions = datas
+            const defaultData = datasCopy[0]
+            // this.formData.currentAirport = [[defaultData.code3, defaultData.builds[0].code3]]
+            // this.formData.currentAirport = [[defaultData.code3]]
+            this.formData.currentAirport = [defaultData.code3]
+            params.currentAirport = this.currentAirport
+            this.getFormData(params)
+            this.getTableData({
+              ...params,
+              world: this.formData.search
+            })
+          }
+        } else {
+          this.$message.error(res.message)
+        }
+      } catch (error) {
+        console.log('出错了', error)
+      }
+    },
+    // 目的站/始飞站查询
+    async relatedAirportQuery(params = {}) {
+      try {
+        const res = await RelatedAirportQuery(params)
+        if (res.code === 0) {
+          const datas = this.formatData(res.returnData)
+          this.relatedAirportOptions = datas
+        } else {
+          this.$message.error(res.message)
+        }
+      } catch (error) {
+        console.log('出错了', error)
+      }
+    },
+    // 航司查询
+    async inboundCarrierQuery(params = {}) {
+      try {
+        const res = await AirCompanyQuery({
+          ...params,
+          type: 'IN'
+        })
+        if (res.code === 0) {
+          this.inboundCarrierOptions = res.returnData
+        } else {
+          this.$message.error(res.message)
+        }
+      } catch (error) {
+        console.log('出错了', error)
+      }
+    },
+    // 航司查询
+    async outgoingAirlineQuery(params = {}) {
+      try {
+        const res = await AirCompanyQuery({
+          ...params,
+          type: 'OUT'
+        })
+        if (res.code === 0) {
+          this.outgoingAirlineOptions = res.returnData
+        } else {
+          this.$message.error(res.message)
+        }
+      } catch (error) {
+        console.log('出错了', error)
+      }
+    },
+    // 机型查询
+    async craftTypeQuery(params = {}) {
+      try {
+        const res = await CraftTypeQuery(params)
+        if (res.code === 0) {
+          this.craftTypeOptions = res.returnData.map(item => ({
+            code3: item,
+            name: item
+          }))
+        } else {
+          this.$message.error(res.message)
+        }
+      } catch (error) {
+        console.log('出错了', error)
+      }
+    },
+    // 航线查询
+    async flightAttrQuery(params = {}) {
+      try {
+        const res = await FlightAttrQuery(params)
+        if (res.code === 0) {
+          this.flightAttrOptions = res.returnData
+        } else {
+          this.$message.error(res.message)
+        }
+      } catch (error) {
+        console.log('出错了', error)
+      }
+    },
+    // 综合查询
+    async integratedQuery(params = {}) {
+      try {
+        this.loading = true
+        const res = await IntegratedQuery(params)
+        if (res.code === 0) {
+          const tableData = res.returnData
+          this.initTableData(tableData)
+          this.loading = false
+        } else {
+          this.$message.error(res.message)
+          this.loading = false
+        }
+      } catch (error) {
+        console.log('出错了', error)
+        this.loading = false
+      }
+    },
+    // 中转综合查询
+    async integratedQueryTransfer(params = {}) {
+      try {
+        this.loading = true
+        const res = await IntegratedQueryTransfer(params)
+        if (res.code === 0) {
+          const tableData = res.returnData
+          this.initTableData(tableData)
+          this.loading = false
+        } else {
+          this.$message.error(res.message)
+          this.loading = false
+        }
+      } catch (error) {
+        console.log('出错了', error)
+        this.loading = false
+      }
+    }
+  }
+}

+ 88 - 0
src/views/baggageManagement/style/transfer.scss

@@ -0,0 +1,88 @@
+/*
+ * @Author: Badguy
+ * @Date: 2022-02-11 16:50:42
+ * @LastEditTime: 2022-03-15 16:25:03
+ * @LastEditors: your name
+ * @Description: 中转进港离港通用样式
+ * have a nice day!
+ */
+
+.terminal-form {
+  padding-top: 11px;
+  ::v-deep .form {
+    .el-form-item {
+      margin-bottom: 0px;
+      margin-right: 8px;
+      button,
+      input,
+      optgroup,
+      select,
+      textarea {
+        font-family: Helvetica, 'Microsoft YaHei';
+        font-size: 14px;
+      }
+      .el-form-item__error {
+        z-index: 10;
+      }
+      .checkTime {
+        margin-left: 24px;
+        margin-right: 16px;
+      }
+      .msgImg {
+        cursor: pointer;
+        position: relative;
+        top: 6px;
+      }
+    }
+  }
+}
+.terminal-table {
+  width: calc(100vw - 60px);
+  ::v-deep .table {
+    width: 100%;
+    .cell {
+      padding: 0;
+      text-align: center;
+      font-size: 14px;
+      color: #303133;
+      letter-spacing: 0;
+    }
+    .el-table__header-wrapper {
+      th {
+        background-color: #fafcff;
+      }
+      .cell {
+        font-weight: bold;
+        color: #101116;
+      }
+    }
+    .el-table__body-wrapper {
+      .el-table__cell {
+        padding: 0;
+        height: 38px;
+        line-height: 38px;
+      }
+      tr.bgl-hui {
+        background-color: #f0f3f7;
+        td {
+          background-color: #f0f3f7;
+        }
+      }
+    }
+  }
+}
+::v-deep .dialog-check-cols .el-tree {
+  &.has-children .el-tree-node > .el-tree-node__children {
+    display: flex;
+    flex-wrap: wrap;
+  }
+  &.no-children {
+    display: flex;
+    flex-wrap: wrap;
+  }
+}
+::v-deep .time-zone .el-dropdown-menu__item {
+  font-family: Helvetica, 'Microsoft YaHei';
+  font-size: 12px;
+  color: #101116;
+}