index.vue 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141
  1. <!--
  2. * @Author: zk
  3. * @Date: 2022-01-17 10:39:22
  4. * @LastEditTime: 2022-06-28 10:04:17
  5. * @LastEditors: your name
  6. * @Description: 中转进港
  7. -->
  8. <template>
  9. <div class="transfer-in">
  10. <!--功能区-表单-->
  11. <div
  12. ref="formWrap"
  13. class="terminal-form-wrap"
  14. >
  15. <el-form
  16. ref="form"
  17. :inline="true"
  18. :model="formData"
  19. :rules="rules"
  20. class="form"
  21. >
  22. <div class="form-left">
  23. <el-form-item prop="currentAirport">
  24. <!-- <el-cascader
  25. v-model="formData.currentAirport"
  26. style="width:144px;margin-left:10px"
  27. placeholder="全部机场"
  28. size="small"
  29. :options="currentAirportList"
  30. :props="currentAirportProps"
  31. collapse-tags
  32. clearable
  33. filterable
  34. @change="setCurrentAirport"
  35. /> -->
  36. <el-select
  37. v-model="formData.currentAirport"
  38. class="input-shadow"
  39. size="small"
  40. style="width: 100px"
  41. filterable
  42. default-first-option
  43. placeholder="请选择机场"
  44. @change="airPortChange"
  45. >
  46. <el-option
  47. v-for="(item, index) in AirportList"
  48. :key="index"
  49. :label="item.planDepartureApt"
  50. :value="item.planDepartureApt"
  51. />
  52. </el-select>
  53. </el-form-item>
  54. <el-form-item prop="inboundCarrier">
  55. <el-cascader
  56. v-model="formData.inboundCarrier"
  57. class="input-shadow"
  58. style="width: 140px"
  59. size="small"
  60. :options="carrierProps"
  61. :props="optionProps"
  62. placeholder="进港承运航司"
  63. collapse-tags
  64. clearable
  65. filterable
  66. default-first-option
  67. @change="resetLoopEvent"
  68. />
  69. </el-form-item>
  70. <el-form-item prop="outgoingAirline">
  71. <el-cascader
  72. v-model="formData.outgoingAirline"
  73. class="input-shadow"
  74. style="width: 140px"
  75. size="small"
  76. :options="carrierPropsop"
  77. :props="optionPropser"
  78. placeholder="离港承运航司"
  79. collapse-tags
  80. clearable
  81. filterable
  82. default-first-option
  83. @change="resetLoopEvent"
  84. />
  85. </el-form-item>
  86. <!-- <el-form-item prop="startDate">
  87. <el-date-picker
  88. v-model="formData.startDate"
  89. class="input-shadow"
  90. style="width: 216px"
  91. size="small"
  92. type="date"
  93. value-format="yyyy-MM-dd"
  94. placeholder="开始时间"
  95. @change="startDateChangeHandler"
  96. />
  97. </el-form-item>
  98. <el-form-item prop="endDate">
  99. <el-date-picker
  100. v-model="formData.endDate"
  101. class="input-shadow"
  102. style="width: 216px"
  103. size="small"
  104. type="date"
  105. value-format="yyyy-MM-dd"
  106. placeholder="结束时间"
  107. @change="endDateChangeHandler"
  108. />
  109. </el-form-item> -->
  110. <el-form-item
  111. prop="flightDate"
  112. label="航班日期"
  113. >
  114. <el-date-picker
  115. v-model="formData.flightDate"
  116. :clearable="false"
  117. size="small"
  118. style="width: 280px"
  119. type="daterange"
  120. value-format="yyyy-MM-dd"
  121. start-placeholder="开始日期"
  122. end-placeholder="结束日期"
  123. :picker-options="dateRangePickerOptions"
  124. @change="dateChangeHandler"
  125. />
  126. </el-form-item>
  127. <el-form-item>
  128. <div class="box-item">
  129. <p>预计中转数:</p>
  130. <li
  131. v-for="(item, index) in orderNum"
  132. :key="index"
  133. :class="{ 'number-item': !isNaN(item), 'mark-item': isNaN(item) }"
  134. >
  135. <span v-if="!isNaN(item)">
  136. <i ref="numberItem">0123456789</i>
  137. </span>
  138. <span
  139. v-else
  140. class="comma"
  141. >{{ item }}</span
  142. >
  143. </li>
  144. </div>
  145. </el-form-item>
  146. </div>
  147. <div
  148. class="form-right"
  149. @keyup.enter="onSubmit(1)"
  150. >
  151. <el-form-item prop="search">
  152. <el-popover
  153. :value="popoverVisible"
  154. placement="bottom"
  155. trigger="manual"
  156. >
  157. <span>请输入航班号(示例:CA1234)或行李牌号(示例:1234567890)</span>
  158. <el-input
  159. slot="reference"
  160. v-model="formData.search"
  161. class="input-shadow"
  162. style="width: 240px"
  163. size="small"
  164. placeholder="请输入内容"
  165. prefix-icon="el-icon-search"
  166. clearable
  167. @focus="popoverVisible = true"
  168. @blur="popoverVisible = false"
  169. />
  170. </el-popover>
  171. </el-form-item>
  172. <el-form-item>
  173. <el-button
  174. class="btn-shadow"
  175. size="mini"
  176. type="primary"
  177. @click="onSubmit(1)"
  178. >搜索</el-button
  179. >
  180. </el-form-item>
  181. <el-form-item>
  182. <el-button
  183. class="btn-shadow"
  184. size="mini"
  185. type="primary"
  186. @click="changeView"
  187. >切换视角</el-button
  188. >
  189. </el-form-item>
  190. <!-- <el-form-item v-is="['ti_timeIcon']">
  191. <TimeZoneSelector />
  192. </el-form-item> -->
  193. <el-form-item>
  194. <TimeZoneSelector />
  195. </el-form-item>
  196. <!-- <el-form-item v-is="['ti_columnSettings']">
  197. <img class="btn-img btn-shadow" src="@/assets/baggage/ic_setting.png" title="列设置" @click="show" />
  198. </el-form-item> -->
  199. <el-form-item>
  200. <img
  201. class="btn-img btn-shadow"
  202. src="@/assets/baggage/ic_setting.png"
  203. title="列设置"
  204. @click="show"
  205. />
  206. </el-form-item>
  207. <!-- <el-form-item v-is="['dm_dt_columnSettings']">
  208. <img class="btn-img btn-shadow" src="@/assets/baggage/ic_export.png" title="导出" @click="exportHandler('table', '航站中转进港列表')" />
  209. </el-form-item> -->
  210. <el-form-item>
  211. <img
  212. class="btn-img btn-shadow"
  213. src="@/assets/baggage/ic_export.png"
  214. title="导出"
  215. @click="exportHandler('table', '航站中转进港列表')"
  216. />
  217. </el-form-item>
  218. </div>
  219. </el-form>
  220. </div>
  221. <!--表格-->
  222. <div
  223. v-loading="loading"
  224. class="terminal-table"
  225. element-loading-text="拼命加载中"
  226. element-loading-spinner="el-icon-loading"
  227. element-loading-background="rgba(0, 0, 0, 0.8)"
  228. >
  229. <el-table
  230. ref="table"
  231. class="table"
  232. :data="dealedTableData"
  233. :height="computedTableHeight"
  234. show-summary
  235. :summary-method="summaryMethod"
  236. :span-method="arraySpanMethod"
  237. :header-cell-class-name="headerCellClass"
  238. :row-class-name="tableRowClassName"
  239. :cell-class-name="cellClass"
  240. border
  241. stripe
  242. fit
  243. @cell-click="cellClickHandler"
  244. >
  245. <el-table-column
  246. v-for="col in tableColsCopy"
  247. :key="col.prop"
  248. :prop="col.prop"
  249. :label="col.label"
  250. :width="col.width"
  251. :fixed="col.fixed"
  252. >
  253. <el-table-column
  254. v-for="childCol in col.children"
  255. :key="childCol.prop"
  256. :prop="childCol.prop"
  257. :label="childCol.label"
  258. :width="childCol.width"
  259. :formatter="tableFormat"
  260. >
  261. <template #header>
  262. <el-tooltip
  263. :content="childCol.desc || childCol.label"
  264. placement="top"
  265. >
  266. <TableHeaderCell
  267. :label="childCol.label"
  268. :filter-options="tableDataFilters[childCol.prop]"
  269. :filter-values.sync="filterValues[childCol.prop]"
  270. :sortable="childCol.sortable"
  271. :sort-rule.sync="tableDataSortRules[childCol.prop]"
  272. />
  273. </el-tooltip>
  274. </template>
  275. </el-table-column>
  276. </el-table-column>
  277. </el-table>
  278. </div>
  279. <!--列设置-->
  280. <Dialog
  281. :flag="dialogFlag"
  282. class="dialog-check-group"
  283. >
  284. <div class="dialog-wrapper">
  285. <div class="title">列设置</div>
  286. <div class="content">
  287. <el-tree
  288. ref="columnSetTree"
  289. :data="tableCols"
  290. :class="colsCheckClass"
  291. show-checkbox
  292. node-key="index"
  293. :default-expand-all="true"
  294. :props="{
  295. label: 'label',
  296. children: 'children'
  297. }"
  298. :default-checked-keys="checkedKeysTemp"
  299. @check="handleCheck"
  300. />
  301. </div>
  302. <div class="foot right t30">
  303. <el-button
  304. size="medium"
  305. class="r24"
  306. type="primary"
  307. @click="onCheck"
  308. >确定</el-button
  309. >
  310. <el-button
  311. size="medium"
  312. @click="hide"
  313. >取消</el-button
  314. >
  315. </div>
  316. </div>
  317. </Dialog>
  318. </div>
  319. </template>
  320. <script>
  321. import Dialog from '@/layout/components/Dialog'
  322. import TimeZoneSelector from '@/components/TimeZoneSelector'
  323. import terminalMixin from '../../mixins/terminal'
  324. import formMixin from '../../mixins/form'
  325. import tableColsMixin from '../../mixins/tableCols'
  326. import timeZoneMixin from '../../mixins/timeZone'
  327. import pf from '@/layout/mixin/publicFunc'
  328. import { TempQuery } from '@/api/temp'
  329. import { GeneralDataReception } from '@/api/temp'
  330. import TableHeaderCell from '@/components/TableHeaderCell'
  331. import { setTableFilters, throttledExportToExcel, timeInZone } from '@/utils/table'
  332. import { parseTime } from '@/utils/index'
  333. import { mapGetters } from 'vuex'
  334. export default {
  335. name: 'DepartureTerminalView',
  336. components: { Dialog, TimeZoneSelector, TableHeaderCell },
  337. mixins: [terminalMixin, formMixin, tableColsMixin, timeZoneMixin, pf],
  338. data() {
  339. return {
  340. optionProps: {
  341. value: 'inAicompanyCode2',
  342. label: 'inAicompanyCode2'
  343. },
  344. optionPropser: {
  345. value: 'outAicompanyCode2',
  346. label: 'outAicompanyCode2'
  347. },
  348. popoverVisible: false,
  349. orderNum: ['0', '0', '0', '0', '0', '0'], // 默认总数
  350. // 初始表头
  351. tableCols: [
  352. {
  353. prop: 'arrivalInfo',
  354. label: '进港航班',
  355. width: 180,
  356. fixed: 'left',
  357. children: [
  358. {
  359. prop: 'preFlightNO',
  360. label: '航班号',
  361. desc: '进港航班编号',
  362. width: 80,
  363. filterable: true,
  364. sortable: true
  365. },
  366. {
  367. prop: 'preFlightDate',
  368. label: '航班日期',
  369. desc: '指航班计划起飞日期(不变的,机票上),不是预计起飞日期(预计起飞时间可能多个),也不是实际起飞日期(实际起飞等于最后预计)',
  370. width: 100
  371. },
  372. {
  373. prop: 'preAirport',
  374. label: '起飞航站',
  375. desc: '指进港航班的起飞机场三字码',
  376. width: 100,
  377. filterable: true,
  378. sortable: true
  379. },
  380. {
  381. prop: 'actualLandingTime',
  382. label: '降落时间',
  383. desc: '根据优先级别显示时间。优先级别:1.实际降落时间,2.预计降落时间,3.计划降落时间',
  384. width: 100
  385. },
  386. {
  387. prop: 'landingBuild',
  388. label: '降落航站楼',
  389. desc: '指航班降落后位于机场的哪个航站楼',
  390. width: 98,
  391. filterable: true,
  392. sortable: true
  393. },
  394. {
  395. prop: 'carousel',
  396. label: '行李转盘',
  397. desc: '指航班到达后行李提取的地方,仅显示最新信息',
  398. width: 100,
  399. filterable: true,
  400. sortable: true
  401. },
  402. {
  403. prop: 'standForLanding',
  404. label: '降落停机位',
  405. desc: '指航班的停机位代码,数据是变化的,仅显示最新信息',
  406. width: 98,
  407. filterable: true,
  408. sortable: true
  409. },
  410. {
  411. prop: 'inTransferBaggageCount',
  412. label: '中转行李数',
  413. desc: '指航班在本航站预计需要中转至对应航班的行李数量'
  414. }
  415. ]
  416. },
  417. {
  418. prop: 'departureInfo',
  419. label: '离港航班',
  420. children: [
  421. {
  422. prop: 'inTransferredBaggageCount',
  423. label: '已中转行李数',
  424. desc: '指航班在本航站实际已经中转至对应航班的行李数量',
  425. width: 100
  426. },
  427. {
  428. prop: 'flightNO',
  429. label: '航班号',
  430. desc: '指航班编号',
  431. width: 80,
  432. filterable: true,
  433. sortable: true
  434. },
  435. {
  436. prop: 'flightDate',
  437. label: '航班日期',
  438. desc: '指航班计划起飞日期(不变的,机票上),不是预计起飞日期(预计起飞时间可能多个),也不是实际起飞日期(实际起飞等于最后预计)',
  439. width: 100
  440. },
  441. {
  442. prop: 'actualDepartureTime',
  443. label: '起飞时间',
  444. desc: '指航班预计起飞时间,数据是变化的,仅显示最新结果',
  445. width: 100
  446. },
  447. {
  448. prop: 'targetAirport',
  449. label: '目的站',
  450. desc: '指航班执飞航段的目的航站,以航站三字码+航站简称显示',
  451. filterable: true,
  452. sortable: true
  453. },
  454. {
  455. prop: 'departureBuild',
  456. label: '起飞航站楼',
  457. desc: '指航班执飞航段的起飞航站的航站楼',
  458. width: 98,
  459. filterable: true,
  460. sortable: true
  461. },
  462. {
  463. prop: 'bordingGate',
  464. label: '起飞登机口',
  465. desc: '指航班的登机口代码,数据是变化的,仅显示最新信息',
  466. width: 98,
  467. filterable: true,
  468. sortable: true
  469. },
  470. {
  471. prop: 'standForDepartrue',
  472. label: '起飞停机位',
  473. desc: '指航班的停机位代码,数据是变化的,仅显示最新信息',
  474. width: 98,
  475. filterable: true,
  476. sortable: true
  477. },
  478. // {
  479. // prop: 'outTransferBaggageCount',
  480. // label: '中转进行李数',
  481. // desc: '指其它航班预计中转至本航班的行李数量',
  482. // width: 100
  483. // },
  484. // {
  485. // prop: 'outTransferredBaggageCount',
  486. // label: '已中转进行李数',
  487. // desc: '指其它航班实际已中转至本航班的行李数量',
  488. // width: 120
  489. // },
  490. {
  491. prop: 'timeDifference',
  492. label: '转运时间',
  493. desc: '指中转动作完成时间'
  494. }
  495. ]
  496. }
  497. ],
  498. loading: false,
  499. AirportList: [],
  500. carrierProps: [],
  501. carrierPropsop: [],
  502. loopEvent: null,
  503. arrivalCount: 0,
  504. baggageCount: 0,
  505. hasSetTableScroll: false,
  506. spanArr: [],
  507. contactDot: 0,
  508. flag: 0,
  509. table: null,
  510. WarningData: []
  511. }
  512. },
  513. computed: {
  514. singleDay() {
  515. return this.startDate === this.endDate
  516. },
  517. ...mapGetters(['timeZone'])
  518. },
  519. watch: {
  520. dealedTableData: {
  521. handler(val) {
  522. this.spanArr = []
  523. let contactDot = this.contactDot
  524. val.forEach((item, index, arr) => {
  525. if (index === 0) {
  526. this.spanArr.push(1)
  527. } else {
  528. if (
  529. item['preFlightNO'] === arr[index - 1]['preFlightNO'] &&
  530. item['preFlightDate'] === arr[index - 1]['preFlightDate']
  531. ) {
  532. this.spanArr[contactDot] += 1
  533. this.spanArr.push(0)
  534. } else {
  535. this.spanArr.push(1)
  536. contactDot = index
  537. }
  538. }
  539. })
  540. },
  541. deep: true
  542. }
  543. },
  544. created() {
  545. // this.getAirPortData()
  546. },
  547. mounted() {
  548. this.$refs['form'].validateField('flightDate')
  549. this.getAirPortData()
  550. this.table = this.$refs.table.bodyWrapper
  551. const that = this
  552. this.table.addEventListener('scroll', () => {
  553. that.scrollTop = this.table.scrollTop
  554. })
  555. },
  556. activated() {
  557. this.table.scrollTop = this.scrollTop
  558. this.getTableData()
  559. this.getWarningData()
  560. this.loopEvent = setInterval(this.getTableData, LOOP_INTERVAL.transferArrivalTable)
  561. // const { startDate, endDate } = this.$route.query
  562. // Object.entries(this.$route.query).forEach(([key, value]) => {
  563. // if ((value ?? '') !== '' && JSON.stringify(value) !== '[]') {
  564. // this.formData[key] = value
  565. // }
  566. // })
  567. // if (startDate !== null && startDate !== undefined) {
  568. // this.formData.flightDate[0] = startDate
  569. // }
  570. // if (endDate !== null && endDate !== undefined) {
  571. // this.formData.flightDate[1] = endDate
  572. // }
  573. },
  574. deactivated() {
  575. if (this.loopEvent) {
  576. clearInterval(this.loopEvent)
  577. this.loopEvent = null
  578. }
  579. },
  580. beforeDestroy() {
  581. if (this.loopEvent) {
  582. clearInterval(this.loopEvent)
  583. this.loopEvent = null
  584. }
  585. },
  586. methods: {
  587. async getWarningData() {
  588. try {
  589. // const res = await TempQuery({
  590. // id: SERVICE_ID.departureWarningId,
  591. // dataContent: []
  592. // })
  593. const res = await this.getQueryList(SERVICE_ID.departureWarningId, {}, 1, 999)
  594. if (Number(res.code) === 0) {
  595. const { listValues } = res.returnData
  596. this.WarningData = listValues
  597. } else {
  598. this.$message.error(res.message)
  599. }
  600. } catch (error) {
  601. this.$message.error('失败')
  602. }
  603. },
  604. resetLoopEvent() {
  605. this.loading = true
  606. this.hasSetTableScroll = false
  607. this.loopEvent && clearInterval(this.loopEvent)
  608. this.getTableData()
  609. this.loopEvent = setInterval(this.getTableData, LOOP_INTERVAL.transferArrivalTable)
  610. },
  611. headerCellClass({ row, column }) {
  612. const classes = []
  613. const rule = this.tableDataSortRules[column.property]
  614. if (rule) {
  615. classes.push(rule)
  616. }
  617. return classes.join(' ')
  618. },
  619. tableRowClassName({ row, rowIndex }) {
  620. const classes = []
  621. if (row.hasArrived) {
  622. classes.push('bgl-hui')
  623. if (rowIndex === this.arrivalCount - 1) {
  624. classes.push('redBorder')
  625. }
  626. }
  627. return classes.join(' ')
  628. },
  629. changeView() {
  630. // const query = {
  631. // ...this.formData,
  632. // startDate: this.startDate,
  633. // endDate: this.endDate
  634. // }
  635. // delete query.flightDate
  636. // this.$router.replace({
  637. // path: '/transfer/departure',
  638. // query
  639. // })
  640. this.$router.push('/transfer/departure')
  641. },
  642. airPortChange() {
  643. this.getAviationData()
  644. this.upAviationData()
  645. this.resetLoopEvent()
  646. },
  647. dateChangeHandler() {
  648. this.getAviationData()
  649. this.upAviationData()
  650. this.resetLoopEvent()
  651. },
  652. // 选择机场
  653. async getAirPortData() {
  654. try {
  655. // const res = await TempQuery({
  656. // id: SERVICE_ID.departureAirId,
  657. // dataContent: []
  658. // })
  659. const res = await this.getQueryListAuth(SERVICE_ID.departureAirId, {}, 1, 9999, 280)
  660. if (Number(res.code) === 0) {
  661. if (res.returnData?.listValues?.length) {
  662. this.AirportList = this._.orderBy(res.returnData.listValues, o => o.planDepartureApt)
  663. this.formData.currentAirport = res.returnData.listValues[0].planDepartureApt
  664. this.getAviationData()
  665. this.upAviationData()
  666. this.resetLoopEvent()
  667. } else {
  668. this.$message.warning('无航站数据权限')
  669. }
  670. } else {
  671. this.$message.error(res.message)
  672. }
  673. } catch (error) {
  674. this.$message.error('失败')
  675. }
  676. },
  677. // 选择航司
  678. async getAviationData() {
  679. try {
  680. // const res = await TempQuery({
  681. // id: SERVICE_ID.departureAviJoinId,
  682. // dataContent: [this.formData.currentAirport]
  683. // })
  684. const res = await this.getQueryListAuth(SERVICE_ID.departureAviJoinId, {}, 1, 9999, 281)
  685. if (Number(res.code) === 0) {
  686. this.carrierProps = res.returnData.listValues
  687. } else {
  688. this.$message.error(res.message)
  689. }
  690. } catch (error) {
  691. this.$message.error('失败')
  692. }
  693. },
  694. // 选择航司
  695. async upAviationData() {
  696. try {
  697. // const res = await TempQuery({
  698. // id: SERVICE_ID.departureAviLeaveId,
  699. // dataContent: [this.formData.currentAirport]
  700. // })
  701. const res = await this.getQueryListAuth(SERVICE_ID.departureAviLeaveId, {}, 1, 9999, 281)
  702. if (Number(res.code) === 0) {
  703. this.carrierPropsop = res.returnData.listValues
  704. } else {
  705. this.$message.error(res.message)
  706. }
  707. } catch (error) {
  708. this.$message.error('失败')
  709. }
  710. },
  711. // 获取表单下拉框数据
  712. // getFormData(params) {
  713. // this.relatedAirportQuery({
  714. // ...params,
  715. // type: 'OUT'
  716. // })
  717. // this.outgoingAirlineQuery(params)
  718. // this.craftTypeQuery(params)
  719. // this.flightAttrQuery(params)
  720. // },
  721. // 获取表格数据
  722. async getTableData() {
  723. if (!this.formData.currentAirport || !this.startDate || !this.endDate) {
  724. return
  725. }
  726. // const arrs1 = [this.formData.inboundCarrier.length === 0 ? '' : this.formData.inboundCarrier[0]]
  727. // const arrs2 = [this.formData.outgoingAirline.length === 0 ? '' : this.formData.outgoingAirline[0]]
  728. // const arr = [
  729. // this.formData.currentAirport,
  730. // this.startDate,
  731. // this.endDate,
  732. // ...arrs1,
  733. // ...arrs1,
  734. // ...arrs1,
  735. // ...arrs2,
  736. // ...arrs2,
  737. // ...arrs2
  738. // // this.formData.inboundCarrier,
  739. // // this.formData.outgoingAirline,
  740. // // JSON.stringify(this.formData.inboundCarrier),
  741. // // JSON.stringify(this.formData.outgoingAirline),
  742. // ]
  743. try {
  744. // const res = await TempQuery({
  745. // id: SERVICE_ID.departureTableId,
  746. // dataContent: [...arr]
  747. // })
  748. const res = await this.getQueryList(SERVICE_ID.departureTableId, { departureAirport: this.formData.currentAirport, flightDateStart: this.startDate, flightDateEnd: this.endDate, inFlightNO: null, flightNO: null }, 1, 9999)
  749. if (Number(res.code) === 0) {
  750. this.initTableData(res.returnData.listValues)
  751. } else {
  752. }
  753. this.loading = false
  754. } catch (error) {
  755. if (this.loopEvent) {
  756. clearInterval(this.loopEvent)
  757. this.loopEvent = null
  758. }
  759. this.loading = false
  760. }
  761. },
  762. initTableData(tableData) {
  763. const currentTime = new Date()
  764. const curTime = this.formatTime(currentTime)
  765. this.baggageCount = 0
  766. tableData.forEach(item => {
  767. if (item['actualLandingTime'] && !item['flightCanceled']) {
  768. const now = new Date()
  769. const actualLandingTime = new Date(item['actualLandingTime'].replace('T', ' '))
  770. if (now > actualLandingTime) {
  771. item['hasArrived'] = true
  772. } else {
  773. item['hasArrived'] = false
  774. }
  775. } else {
  776. item['hasArrived'] = false
  777. }
  778. const o1 = item['inTransferBaggageCount']
  779. const o2 = item['inTransferredBaggageCount']
  780. const out1 = o1 != undefined || o1 != null ? o1 : 0
  781. const out2 = o2 != undefined || o2 != null ? o2 : 0
  782. if (item['hasArrived'] && out1 - out2 > 0) {
  783. this.WarningData.forEach(p => {
  784. const startTime = this.formatTime(timeInZone((p.startDate ?? '').replace('T', ' '), this.timeZone), 2)
  785. const endTime = this.formatTime(timeInZone((p.endDate ?? '').replace('T', ' '), this.timeZone), 2)
  786. const planTime = this.formatTime(
  787. timeInZone((item.actualDepartureTime ?? '').replace('T', ' '), this.timeZone),
  788. 2
  789. )
  790. const capTime = Math.ceil((planTime - curTime) / (1000 * 60))
  791. if (Number(startTime) - Number(curTime) < 0 && Number(endTime) - Number(curTime) > 0) {
  792. const newItem = _.cloneDeep(item)
  793. if (p.flightNO != '' && p.flightNO == item.flightNO) {
  794. if (p.warningDuration && capTime - p.warningDuration < 0 && capTime - p.alarmDuration > 0) {
  795. item['warningState'] = 1
  796. const returnedTarget = Object.assign(newItem, p)
  797. this.sendLog(returnedTarget)
  798. }
  799. if (p.alarmDuration && capTime - p.alarmDuration < 0) {
  800. item['warningState'] = 2
  801. const returnedTarget = Object.assign(newItem, p)
  802. this.sendLog(returnedTarget)
  803. }
  804. } else if (p.flightNO == '' && p.IATACode != '') {
  805. if (item.flightNO.substring(0, 2) == p.IATACode) {
  806. if (p.warningDuration && capTime - p.warningDuration < 0 && capTime - p.alarmDuration > 0) {
  807. item['warningState'] = 1
  808. const returnedTarget = Object.assign(newItem, p)
  809. this.sendLog(returnedTarget)
  810. }
  811. if (p.alarmDuration && capTime - p.alarmDuration < 0) {
  812. item['warningState'] = 2
  813. const returnedTarget = Object.assign(newItem, p)
  814. this.sendLog(returnedTarget)
  815. }
  816. }
  817. }
  818. }
  819. })
  820. }
  821. this.baggageCount = this.baggageCount + Number(item.inTransferBaggageCount)
  822. })
  823. this.tableData = this._.sortBy(tableData, ['actualLandingTime', 'preFlightNO', 'actualDepartureTime', 'flightNO'])
  824. setTableFilters(this.tableData, this.tableDataFilters)
  825. this.toOrderNum(this.baggageCount)
  826. this.$nextTick(() => {
  827. this.setTableScroll()
  828. })
  829. },
  830. formatTime(date, type = 1) {
  831. let time = null
  832. if (type == 1) {
  833. time = parseTime(date, '{y}-{m}-{d} {h}:{i}:{s}')
  834. } else {
  835. time = date
  836. }
  837. const newTimt = new Date(time)
  838. return newTimt.getTime()
  839. },
  840. async sendLog(obj) {
  841. try {
  842. const newObj = {
  843. logTime: parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}'),
  844. logInfo: JSON.stringify(obj),
  845. flightNO: obj.flightNO,
  846. flightDate: obj.flightDate,
  847. luggageSN: '',
  848. strategyUseID: obj.alarmStrategyID,
  849. event: 1
  850. }
  851. await GeneralDataReception({
  852. serviceId: SERVICE_ID.departureScId,
  853. dataContent: JSON.stringify(newObj)
  854. })
  855. } catch (error) {
  856. this.$message.error('失败')
  857. }
  858. },
  859. setTableScroll() {
  860. this.arrivalCount = 0
  861. this.dealedTableData.forEach(row => {
  862. if (row['hasArrived']) {
  863. this.arrivalCount++
  864. }
  865. })
  866. if (!this.singleDay || this.hasSetTableScroll || this.arrivalCount === 0) {
  867. return
  868. }
  869. const table = this.$refs['table'].$el
  870. const scrollParent = table.querySelector('.el-table__body-wrapper')
  871. if (scrollParent.scrollHeight <= scrollParent.offsetHeight) {
  872. return
  873. }
  874. const lastRow = table.querySelectorAll('.el-table__body tr')[this.arrivalCount - 1]
  875. setTimeout(() => {
  876. const scrollMid = lastRow.offsetTop + lastRow.offsetHeight - scrollParent.offsetHeight / 2
  877. const scrollMax = scrollParent.scrollHeight - scrollParent.offsetHeight
  878. if (scrollMid > 0) {
  879. const scrollHeight = Math.min(scrollMid, scrollMax)
  880. scrollParent.scrollTo(0, scrollHeight)
  881. }
  882. }, 0)
  883. this.hasSetTableScroll = true
  884. },
  885. setNumberTransform() {
  886. const numberItems = this.$refs.numberItem // 拿到数字的ref,计算元素数量
  887. const numberArr = this.orderNum.filter(item => !isNaN(item))
  888. // 结合CSS 对数字字符进行滚动,显示订单数量
  889. for (let index = 0; index < numberItems.length; index++) {
  890. const elem = numberItems[index]
  891. elem.style.transform = `translate(-50%, -${numberArr[index] * 10}%)`
  892. }
  893. },
  894. toOrderNum(num) {
  895. num = num.toString()
  896. if (num.length < 6) {
  897. num = '0' + num // 如未满八位数,添加"0"补位
  898. this.toOrderNum(num) // 递归添加"0"补位
  899. } else if (num.length >= 6) {
  900. this.orderNum = num.split('') // 将其便变成数据,渲染至滚动数组
  901. } else {
  902. // 订单总量数字超过八位显示异常
  903. this.$message.warning('总量数字过大')
  904. }
  905. this.setNumberTransform()
  906. },
  907. arraySpanMethod({ row, column, rowIndex, columnIndex }) {
  908. for (let i = 0; i < 7; i++) {
  909. if (columnIndex === i) {
  910. const _row = this.spanArr[rowIndex]
  911. const _col = _row > 0 ? 1 : 0
  912. return {
  913. rowspan: _row,
  914. colspan: _col
  915. }
  916. }
  917. }
  918. },
  919. exportHandler(refName, tableName) {
  920. if (this.loading) {
  921. return
  922. }
  923. const table = this.$refs[refName].$el.cloneNode(true)
  924. const fileName = `${tableName}-${this.currentAirport}-${this.startDate}-${this.endDate}.xlsx`
  925. throttledExportToExcel(table, tableName, fileName, 2)
  926. }
  927. }
  928. }
  929. </script>
  930. <style
  931. lang="scss"
  932. scoped
  933. >
  934. .terminal-form-wrap {
  935. padding-top: 11px;
  936. padding-left: 5px;
  937. ::v-deep .form {
  938. display: flex;
  939. justify-content: space-between;
  940. .form-left {
  941. flex: 1;
  942. }
  943. .form-right {
  944. flex: 0 1 auto;
  945. }
  946. .el-form-item {
  947. margin-bottom: 0px;
  948. margin-right: 8px;
  949. button,
  950. input,
  951. optgroup,
  952. select,
  953. textarea {
  954. font-family: Helvetica, 'Microsoft YaHei';
  955. font-size: 14px;
  956. }
  957. .el-switch__label {
  958. color: #303133;
  959. }
  960. .el-form-item__error {
  961. z-index: 10;
  962. }
  963. }
  964. .btn-img {
  965. position: relative;
  966. top: 6px;
  967. }
  968. }
  969. .box-item {
  970. position: relative;
  971. height: 50px;
  972. font-size: 18px;
  973. line-height: 32px;
  974. text-align: center;
  975. list-style: none;
  976. color: #2d7cff;
  977. writing-mode: vertical-lr;
  978. text-orientation: upright;
  979. /*文字禁止编辑*/
  980. -moz-user-select: none; /*火狐*/
  981. -webkit-user-select: none; /*webkit浏览器*/
  982. -ms-user-select: none; /*IE10*/
  983. -khtml-user-select: none; /*早期浏览器*/
  984. user-select: none;
  985. /* overflow: hidden; */
  986. p {
  987. line-height: 32px;
  988. writing-mode: horizontal-tb !important;
  989. text-orientation: none !important;
  990. /*文字禁止编辑*/
  991. -moz-user-select: none; /*火狐*/
  992. -webkit-user-select: none; /*webkit浏览器*/
  993. -ms-user-select: none; /*IE10*/
  994. -khtml-user-select: none; /*早期浏览器*/
  995. user-select: none;
  996. margin-top: 5px;
  997. }
  998. }
  999. /* 默认逗号设置 */
  1000. .mark-item {
  1001. width: 10px;
  1002. height: 32px;
  1003. margin-right: 5px;
  1004. line-height: 10px;
  1005. font-size: 18px;
  1006. position: relative;
  1007. & > span {
  1008. position: absolute;
  1009. width: 100%;
  1010. bottom: 0;
  1011. writing-mode: vertical-rl;
  1012. text-orientation: upright;
  1013. }
  1014. }
  1015. /*滚动数字设置*/
  1016. .number-item {
  1017. width: 41px;
  1018. height: 42px;
  1019. /* 背景图片 */
  1020. // background: url(/images/text-bg-blue.png) no-repeat center center;
  1021. // background-size: 100% 100%;
  1022. // background: #ccc;
  1023. list-style: none;
  1024. margin-right: 5px;
  1025. // background:rgba(250,250,250,1);
  1026. border-radius: 4px;
  1027. border: 3px solid rgb(221, 221, 221);
  1028. & > span {
  1029. position: relative;
  1030. display: inline-block;
  1031. margin-right: 10px;
  1032. width: 100%;
  1033. height: 100%;
  1034. writing-mode: vertical-rl;
  1035. text-orientation: upright;
  1036. overflow: hidden;
  1037. & > i {
  1038. font-style: normal;
  1039. position: absolute;
  1040. top: 11px;
  1041. left: 50%;
  1042. transform: translate(-50%, -1%);
  1043. transition: transform 1s ease-in-out;
  1044. letter-spacing: 10px;
  1045. }
  1046. }
  1047. }
  1048. .number-item:last-child {
  1049. margin-right: 0;
  1050. }
  1051. }
  1052. .terminal-table {
  1053. width: 100%;
  1054. ::v-deep .table {
  1055. width: 100%;
  1056. .cell {
  1057. padding: 0;
  1058. text-align: center;
  1059. font-size: 14px;
  1060. font-family: Helvetica, 'Microsoft YaHei';
  1061. letter-spacing: 0;
  1062. }
  1063. .cell-click {
  1064. cursor: pointer;
  1065. color: #2d7cff;
  1066. &.cell-clicked {
  1067. color: purple;
  1068. }
  1069. }
  1070. .el-table__header-wrapper,
  1071. .el-table__fixed-header-wrapper {
  1072. .cell {
  1073. font-weight: bold;
  1074. color: #101116;
  1075. }
  1076. .has-gutter {
  1077. tr {
  1078. .bgl-huang {
  1079. background: #fcf0b1;
  1080. }
  1081. }
  1082. }
  1083. }
  1084. .el-table__body-wrapper,
  1085. .el-table__fixed-body-wrapper {
  1086. tr.bgl-hui {
  1087. background: #d2d6df;
  1088. td {
  1089. background: #d2d6df;
  1090. }
  1091. &.redBorder {
  1092. position: relative;
  1093. &::after {
  1094. content: '';
  1095. position: absolute;
  1096. left: 0;
  1097. bottom: 0;
  1098. width: 100%;
  1099. height: 2px;
  1100. background: #e83f82;
  1101. }
  1102. }
  1103. }
  1104. }
  1105. td.cell-toUnload {
  1106. background: lightcoral !important;
  1107. position: relative;
  1108. &::after {
  1109. content: '';
  1110. display: block;
  1111. width: 100%;
  1112. height: 100%;
  1113. position: absolute;
  1114. top: 0;
  1115. left: 0;
  1116. border: 2px dashed red;
  1117. }
  1118. }
  1119. td.cell-toUnloadNew {
  1120. background: #fcf0b1 !important;
  1121. position: relative;
  1122. &::after {
  1123. content: '';
  1124. display: block;
  1125. width: 100%;
  1126. height: 100%;
  1127. position: absolute;
  1128. top: 0;
  1129. left: 0;
  1130. border: 2px dashed #e28913;
  1131. }
  1132. }
  1133. .el-table__cell.is-hidden > * {
  1134. visibility: visible;
  1135. }
  1136. }
  1137. }
  1138. </style>