index.vue 28 KB

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