index.vue 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. <!--
  2. * @Author: your name
  3. * @Date: 2022-01-17 10:39:22
  4. * @LastEditTime: 2022-05-20 16:48:33
  5. * @LastEditors: your name
  6. * @Description: 行李视图
  7. -->
  8. <template>
  9. <div class="baggage-view">
  10. <div class="part1">
  11. <div class="title">
  12. <span>行李基本信息</span>
  13. <el-radio-group
  14. v-model="infoBtn"
  15. class="radioBtn"
  16. size="mini"
  17. fill="#FFFFFF"
  18. text-color="#28344D"
  19. >
  20. <el-radio-button
  21. v-for="item in infoRadios"
  22. :key="item"
  23. :label="item"
  24. />
  25. </el-radio-group>
  26. </div>
  27. <div class="part1_info">
  28. <el-row :gutter="12">
  29. <el-col
  30. v-for="(item, index) in baggageBasicInfoCols"
  31. :key="index"
  32. :span="[1, 4, 5].includes(index % 7) ? 4 : 3"
  33. >
  34. <span class="label">{{ item.label }}:</span><span
  35. class="content"
  36. :title="formattedBaggageInfo(item.prop)"
  37. >{{ formattedBaggageInfo(item.prop) }}</span>
  38. </el-col>
  39. </el-row>
  40. </div>
  41. </div>
  42. <div
  43. v-show="infoBtn === infoRadios[0]"
  44. class="part2"
  45. >
  46. <div class="part2_info">
  47. <div
  48. style="width: 120px"
  49. class="title"
  50. >行李跟踪信息</div>
  51. <div class="type normal">
  52. {{ baggageBasicInfo.BagStatus }}
  53. </div>
  54. <div class="step">
  55. <div class="baggage-track-chart">
  56. <div class="stepLine">
  57. <div
  58. :style="{ width: lineWidth }"
  59. class="stepLineBlue"
  60. />
  61. </div>
  62. <el-popover
  63. v-for="(item, index) in stepData"
  64. :key="index"
  65. :ref="'popover' + index"
  66. :value="popoverVisible(item)"
  67. :open-delay="500"
  68. placement="left-end"
  69. popper-class="popover-dark"
  70. trigger="manual"
  71. >
  72. <div class="pre-line">{{ messageTooltip(item.resourceFile) }}</div>
  73. <div
  74. slot="reference"
  75. :class="{ 'stepItem': true, activeItem: item.DealTime }"
  76. @mouseenter="itemMouseEnterHandler(item)"
  77. @mouseleave="itemMouseLeaveHandler(item)"
  78. >
  79. <span class="head">
  80. <!-- {{ item.airPort }} -->
  81. <!-- <span v-if="item.airPort && item.nodeName !== ''">-</span> -->
  82. <span>{{ item.NodeNameEN }}</span>
  83. </span>
  84. <span>{{ item.DealTime }}</span>
  85. <!-- <span>{{ item.time }}</span> -->
  86. </div>
  87. </el-popover>
  88. </div>
  89. </div>
  90. </div>
  91. <div class="btns">
  92. <img
  93. class="btn-square"
  94. src="../../../../assets/baggage/ic_export.png"
  95. >
  96. <img
  97. class="btn-square"
  98. src="../../../../assets/baggage/ic_setting.png"
  99. @click="show"
  100. >
  101. </div>
  102. </div>
  103. <div
  104. v-show="infoBtn == infoRadios[0]"
  105. class="part3"
  106. >
  107. <!-- <el-popover
  108. trigger="hover"
  109. placement="top-start"
  110. popper-class="popover-dark"
  111. :visible-arrow="false"
  112. :disabled="!messageTooltipVisible"
  113. >
  114. <div class="pre-line">{{ messageTooltip }}</div> -->
  115. <el-table
  116. ref="table"
  117. :data="baggageTableData"
  118. height="calc(100vh - 80px - 232px - 128px - 3 * 8px - 44px)"
  119. size="mini"
  120. border
  121. fit
  122. :header-cell-class-name="cellClass"
  123. :header-cell-style="{ color: '#101116' }"
  124. :cell-class-name="cellClass"
  125. :span-method="tableSpanMethod"
  126. @cell-mouse-enter="cellMouseEnterHandler"
  127. @cell-mouse-leave="cellMouseLeaveHandler"
  128. >
  129. <el-table-column
  130. v-for="item in tableColsCopy"
  131. :key="item.index"
  132. :prop="item.prop"
  133. :label="item.name"
  134. :align="item.align || 'center'"
  135. :width="item.width"
  136. show-overflow-tooltip
  137. >
  138. <template slot="header">
  139. <div class="cell-content">{{ item.name }}</div>
  140. </template>
  141. <template slot-scope="scope">
  142. <div class="cell-content">{{ scope.row[item.prop] }}</div>
  143. </template>
  144. </el-table-column>
  145. </el-table>
  146. <!-- </el-popover> -->
  147. </div>
  148. <div
  149. v-show="infoBtn === infoRadios[1]"
  150. class="part4"
  151. >
  152. <header class="head">
  153. <div class="title">行李跟踪信息</div>
  154. <div class="btns">
  155. <img
  156. class="btn-square"
  157. src="../../../../assets/baggage/ic_export.png"
  158. >
  159. <img
  160. class="btn-square"
  161. src="../../../../assets/baggage/ic_setting.png"
  162. @click="show"
  163. >
  164. </div>
  165. </header>
  166. <main class="main">
  167. <template v-if="messageList.length">
  168. <el-row
  169. :gutter="24"
  170. type="flex"
  171. >
  172. <el-col
  173. v-for="(message, index) in messageList"
  174. :key="index"
  175. :span="6"
  176. >
  177. <div class="card">
  178. <div class="message-date">{{ message.date }}</div>
  179. <div class="message-content">
  180. {{ message.dataContent.replaceAll(/[\r\n]{2,}/g, '\n') }}
  181. <!-- BSM <br>
  182. .V/1LHRB <br>
  183. .F/XX1640/08APR/PEK/Y <br>
  184. .O/ZZ941/08APR/DXB/E <br>
  185. .N/0666826758001 <br>
  186. .D/SELF//08APR/110023L//PEK30113 <br>
  187. .S/N/32L/C/030//Y/I <br>
  188. .W/K/l/0 <br>
  189. .P/1CUI/DI ENDBSM<br> -->
  190. </div>
  191. </div>
  192. </el-col>
  193. </el-row>
  194. </template>
  195. <template v-else>
  196. <el-empty
  197. :image-size="1"
  198. description="暂无数据"
  199. />
  200. </template>
  201. </main>
  202. </div>
  203. <!--列设置-->
  204. <Dialog
  205. :flag="dialogFlag"
  206. class="dialog-check-cols"
  207. >
  208. <div class="col-dialog">
  209. <div class="title">列设置</div>
  210. <div class="content">
  211. <el-tree
  212. :data="tableCols"
  213. :class="colsCheckClass"
  214. show-checkbox
  215. node-key="index"
  216. :default-expand-all="true"
  217. :props="{
  218. label: 'name',
  219. children: 'children',
  220. }"
  221. :default-checked-keys="checkedKeysTemp"
  222. @check="handleCheck"
  223. />
  224. </div>
  225. <div class="foot right t30">
  226. <el-button
  227. size="medium"
  228. class="r24"
  229. type="primary"
  230. @click="onCheck"
  231. >确定</el-button>
  232. <el-button
  233. size="medium"
  234. @click="hide"
  235. >取消</el-button>
  236. </div>
  237. </div>
  238. </Dialog>
  239. </div>
  240. </template>
  241. <script>
  242. import Dialog from '@/layout/components/Dialog/index.vue'
  243. import { queryMap, myQuery } from '@/api/dataIntegration'
  244. import tableColsMixin from '../../mixins/tableCols'
  245. export default {
  246. name: 'BaggageView',
  247. components: {
  248. Dialog
  249. },
  250. mixins: [tableColsMixin],
  251. data() {
  252. return {
  253. departureAirport: '',
  254. landingAirport: '',
  255. queryData: {},
  256. baggageBasicInfoCols: [
  257. {
  258. label: '行李牌号',
  259. prop: 'bagNo'
  260. },
  261. {
  262. label: '航班号',
  263. prop: 'FlightNO'
  264. },
  265. {
  266. label: '企业或团队名称',
  267. prop: 'teamOrGroup'
  268. },
  269. {
  270. label: '值机位置',
  271. prop: 'checkInLocation'
  272. },
  273. {
  274. label: '特殊行李类型',
  275. prop: 'specialType'
  276. },
  277. {
  278. label: 'PNR编号',
  279. prop: 'PNR'
  280. },
  281. {
  282. label: '旅客姓名大写拼音',
  283. prop: 'name'
  284. },
  285. {
  286. label: '装载序列号',
  287. prop: 'loadSequenceIndex'
  288. },
  289. {
  290. label: '总件数',
  291. prop: 'totalNumber'
  292. },
  293. {
  294. label: '总重量',
  295. prop: 'totalWeight'
  296. },
  297. {
  298. label: '尺寸',
  299. prop: 'size'
  300. },
  301. {
  302. label: '外部特征描述',
  303. prop: 'externalCharacterization'
  304. },
  305. {
  306. label: '常旅客号',
  307. prop: 'frequentFlyerNumber'
  308. },
  309. {
  310. label: '常旅客级别',
  311. prop: 'frequentFlyerClass'
  312. },
  313. {
  314. label: '是否取消值机',
  315. prop: 'whetherToCancelTheCheckIn'
  316. },
  317. {
  318. label: '是否可装载',
  319. prop: 'isItLoadable'
  320. },
  321. {
  322. label: '是否可运输',
  323. prop: 'isItTransportable'
  324. },
  325. {
  326. label: '行李激活状态',
  327. prop: 'activeState'
  328. },
  329. {
  330. label: '无BSM状态',
  331. prop: 'noBSM'
  332. },
  333. {
  334. label: '中转标记',
  335. prop: 'transitSign'
  336. },
  337. {
  338. label: '速运标记',
  339. prop: 'expressSign'
  340. },
  341. {
  342. label: '破损标记',
  343. prop: 'brokenSign'
  344. },
  345. {
  346. label: '投诉标记',
  347. prop: 'complaintSign'
  348. },
  349. {
  350. label: '赔偿标记',
  351. prop: 'compensationSign'
  352. },
  353. {
  354. label: '异常状态',
  355. prop: 'bagExcType'
  356. }
  357. ],
  358. baggageBasicInfo: {},
  359. dialogVisibledele: false,
  360. active: 2,
  361. infoBtn: '跟踪信息',
  362. infoRadios: ['跟踪信息', '跟踪报文'],
  363. messageList: [
  364. // {
  365. // content: `BSM
  366. // .V/1LHRB
  367. // .F/XX1640/08APR/PEK/Y
  368. // .O/ZZ941/08APR/DXB/E
  369. // .N/0666826758001
  370. // .D/SELF//08APR/110023L//PEK30113
  371. // .S/N/32L/C/030//Y/I
  372. // .W/K/l/0
  373. // .P/1CUI/DI ENDBSM`,
  374. // date: '2022-04-25 12:42:38:00'
  375. // }
  376. ],
  377. messageTooltipList: [],
  378. checkList: [],
  379. stepData: new Array(9).fill({}),
  380. tableCols: [
  381. {
  382. name: '航班号',
  383. prop: 'flightNo'
  384. },
  385. { name: '航班日期', prop: 'flightDate', width: 100 },
  386. {
  387. name: '起飞航站\n预计起飞时间',
  388. prop: 'departureAirport',
  389. width: 111
  390. },
  391. {
  392. name: '目的航站\n预计降落时间',
  393. prop: 'landingAirport',
  394. sortable: 'custom',
  395. width: 111
  396. },
  397. { name: '旅客仓位', prop: 'passengerCompartment', width: 70 },
  398. { name: '旅客座位号', prop: 'passengerSeatNumber' },
  399. { name: '值机序号', prop: 'passengerCheckInNumber', width: 70 },
  400. { name: '节点标识', prop: 'nodeCode', width: 100 },
  401. { name: '节点名称', prop: 'nodeName' },
  402. { name: '位置标识', prop: 'locationCode' },
  403. // { name: '位置码', prop: '', },
  404. { name: '位置描述', prop: 'locationRemark' },
  405. { name: '读取时间', prop: 'dealTime', width: 158 },
  406. { name: '结果', prop: 'status' },
  407. { name: '次级代码', prop: 'secondaryCode', width: 70 },
  408. { name: '操作人', prop: 'AgentCode', width: 100 },
  409. { name: '设备ID', prop: 'DeviceCode' },
  410. { name: '发往位置', prop: 'toLocation' },
  411. { name: '发往位置描述', prop: 'toLocationMark', width: 110 },
  412. { name: '装载序号', prop: 'LoadSN' },
  413. { name: '容器编号', prop: 'U_Device_ID', width: 100 }
  414. ],
  415. baggageTableData: [],
  416. spanArr: [],
  417. pos: 0,
  418. hoveredRow: null,
  419. loopEvent: null,
  420. queryMessageLoop: null
  421. }
  422. },
  423. computed: {
  424. lineWidth() {
  425. for (let i = this.stepData.length - 1; i > -1; i--) {
  426. if (this.stepData[i].DealTime) {
  427. return (i * 100) / (this.stepData.length - 1) + '%'
  428. }
  429. }
  430. return 0
  431. },
  432. messageTooltip() {
  433. return function (resourceFile) {
  434. const message = this.messageTooltipList.find(message => message.resourceFile === resourceFile)
  435. return message ? `${message.date}\n${message.dataContent.replaceAll(/[\r\n]{2,}/g, '\n')}` : ''
  436. }
  437. },
  438. popoverVisible() {
  439. return function (item) {
  440. return (
  441. (item.hover || item.tableHover) &&
  442. this.messageTooltipList.some(message => message.resourceFile === item.resourceFile)
  443. )
  444. }
  445. },
  446. formattedBaggageInfo() {
  447. return function (prop) {
  448. const value = this.baggageBasicInfo[prop]
  449. if ((value ?? '') === '') {
  450. return ''
  451. } else if (prop === 'transitSign') {
  452. return Number(value) === 1 ? '中转' : '非中转'
  453. } else if (
  454. [
  455. 'whetherToCancelTheCheckIn',
  456. 'isItLoadable',
  457. 'isItTransportable',
  458. 'activeState',
  459. 'noBSM',
  460. 'expressSign',
  461. 'brokenSign',
  462. 'complaintSign',
  463. 'compensationSign',
  464. 'bagExcType'
  465. ].includes(prop)
  466. ) {
  467. return Number(value) === 1 || String(value) === 'Y' ? '是' : '否'
  468. } else {
  469. return value
  470. }
  471. }
  472. }
  473. },
  474. watch: {
  475. infoBtn(val) {
  476. const that = this
  477. if (val === '跟踪报文') {
  478. clearInterval(this.loopEvent)
  479. this.loopEvent = null
  480. this.baggageMessageQuery()
  481. this.queryMessageLoop = setInterval(function () {
  482. that.baggageMessageQuery()
  483. }, 5000)
  484. } else {
  485. clearInterval(this.queryMessageLoop)
  486. this.queryMessageLoop = null
  487. this.queryBaggageAll()
  488. this.loopEvent = setInterval(function () {
  489. that.queryBaggageAll()
  490. }, 3000)
  491. }
  492. },
  493. hoveredRow: {
  494. handler(row) {
  495. this.stepData.forEach(item => {
  496. item.tableHover = row && item.resourceFile === row.resourceFile
  497. })
  498. },
  499. deep: true
  500. }
  501. },
  502. mounted() {
  503. this.queryData = this._.cloneDeep(this.$route.query)
  504. // console.log(this.queryData)
  505. const that = this
  506. this.queryBaggageAll()
  507. this.loopEvent = setInterval(function () {
  508. that.queryBaggageAll()
  509. }, 3000)
  510. },
  511. updated() {
  512. this.$refs['table']?.doLayout()
  513. },
  514. beforeDestroy() {
  515. clearInterval(this.loopEvent)
  516. this.loopEvent = null
  517. clearInterval(this.queryMessageLoop)
  518. this.queryMessageLoop = null
  519. },
  520. methods: {
  521. // objectSpanMethod({ row, column, rowIndex, columnIndex }) {
  522. // if (columnIndex < 4) {
  523. // const _row = this.spanArr[rowIndex]
  524. // const _col = _row > 0 ? 1 : 0
  525. // return {
  526. // rowspan: _row,
  527. // colspan: _col
  528. // }
  529. // }
  530. // },
  531. initTableData(tableData) {
  532. const spanArr = []
  533. let pos = 0
  534. for (let i = 0; i < tableData.length; i++) {
  535. if (i === 0) {
  536. spanArr.push(1)
  537. } else {
  538. if (
  539. tableData[i]['flightNo'] === tableData[i - 1]['flightNo'] &&
  540. tableData[i]['flightDate'] === tableData[i - 1]['flightDate'] &&
  541. tableData[i]['departureAirport'] === tableData[i - 1]['departureAirport'] &&
  542. tableData[i]['landingAirport'] === tableData[i - 1]['landingAirport']
  543. ) {
  544. spanArr[pos] += 1
  545. spanArr.push(0)
  546. } else {
  547. spanArr.push(1)
  548. pos = i
  549. }
  550. }
  551. }
  552. this.spanArr = spanArr
  553. this.pos = pos
  554. },
  555. cellClass({ row, column, rowIndex, columnIndex }) {
  556. if (['departureAirport', 'landingAirport'].includes(column.property)) {
  557. return 'pre-line'
  558. }
  559. },
  560. tableSpanMethod({ row, column, rowIndex, columnIndex }) {
  561. if (['flightNo', 'flightDate', 'departureAirport', 'landingAirport'].includes(column['property'])) {
  562. const _row = this.spanArr[rowIndex]
  563. const _col = _row > 0 ? 1 : 0
  564. return {
  565. rowspan: _row,
  566. colspan: _col
  567. }
  568. }
  569. },
  570. itemMouseEnterHandler(item) {
  571. if (item.resourceFile) {
  572. this.checkBaggageMessage(item.resourceFile)
  573. item.hover = true
  574. }
  575. },
  576. itemMouseLeaveHandler(item) {
  577. item.hover = false
  578. },
  579. cellMouseEnterHandler(row, column, cell, event) {
  580. if (row?.resourceFile) {
  581. this.checkBaggageMessage(row.resourceFile)
  582. }
  583. this.hoveredRow = row
  584. },
  585. cellMouseLeaveHandler() {
  586. this.hoveredRow = null
  587. },
  588. async checkBaggageMessage(resourceFile) {
  589. if (!this.messageTooltipList.some(message => message.resourceFile === resourceFile)) {
  590. const result = await this.queryMessage([resourceFile])
  591. this.messageTooltipList.push({
  592. ...result[0],
  593. resourceFile
  594. })
  595. }
  596. },
  597. // 行李详情基础信息
  598. queryBaggageBasicInfo(dataContent) {
  599. return myQuery(queryMap.baggageBasicInfoByID, ...dataContent)
  600. },
  601. // 行李详情追踪链
  602. queryBaggageTrack(dataContent) {
  603. return myQuery(queryMap.baggageTrackByID, ...dataContent)
  604. },
  605. // 行李详情表格
  606. queryBaggageDetails(dataContent) {
  607. return myQuery(queryMap.baggageDetailsByID, ...dataContent)
  608. },
  609. // 原始报文
  610. queryMessage(dataContent) {
  611. return myQuery(queryMap.message, ...dataContent)
  612. },
  613. async queryBaggageAll(queryData = this.queryData) {
  614. const { FlightNO, FlightDate, BagSN } = queryData
  615. const dataContent = [FlightNO, FlightDate, BagSN]
  616. try {
  617. const [
  618. baggageBasicInfo,
  619. // baggageTrack,
  620. baggageDetails
  621. ] = await Promise.all([
  622. this.queryBaggageBasicInfo(dataContent),
  623. // this.queryBaggageTrack(new Array(2).fill(dataContent).flat()),
  624. this.queryBaggageDetails(new Array(6).fill(dataContent).flat())
  625. ])
  626. if (baggageBasicInfo.length) {
  627. baggageBasicInfo[0].FlightNO = FlightNO
  628. this.baggageBasicInfo = baggageBasicInfo[0]
  629. }
  630. // this._.sortBy(baggageTrack, item => item.DealTime).forEach((item, index) => {
  631. // item['DealTime'] = item['DealTime'].replace('T', '\n')
  632. // item.NodeNameEN && this.stepData.splice(index, 1, item)
  633. // })
  634. // const baggageDetailsData = this._.sortBy(baggageDetails, ['flightDate', 'dealTime'])
  635. this.baggageTableData = baggageDetails.map((item, index) => {
  636. const { hover, tableHover } = this.stepData[index] ?? {}
  637. this.stepData.splice(index, 1, {
  638. NodeNameEN: item.nodeCode,
  639. DealTime: item.dealTime.replace('T', '\n'),
  640. resourceFile: item.resourceFile,
  641. hover: !!hover,
  642. tableHover: !!tableHover
  643. })
  644. if (item['dealTime'].split('T').length > 1) {
  645. item['dealTime'] = item['dealTime'].replace('T', ' ')
  646. }
  647. item['departureAirport'] = `${item['departureAirport']}\n${item['departureTime'].replace('T', '\n')}`
  648. item['landingAirport'] = `${item['landingAirport']}\n${item['landingTime'].replace('T', '\n')}`
  649. return item
  650. })
  651. this.initTableData(this.baggageTableData)
  652. } catch (error) {
  653. console.log('错误', error)
  654. }
  655. },
  656. async baggageMessageQuery() {
  657. const { FlightNO, FlightDate, BagSN } = this.queryData
  658. const dataContent = [FlightNO, FlightDate, BagSN]
  659. try {
  660. const result = await this.queryMessage(dataContent)
  661. this.messageList = result
  662. } catch (error) {
  663. console.log('出错了', error)
  664. }
  665. }
  666. }
  667. }
  668. </script>
  669. <style lang="scss">
  670. .radioBtn {
  671. padding: 5px;
  672. background: #000d2a;
  673. .el-radio-button__inner {
  674. background: #000d2a;
  675. color: #fff;
  676. border: none;
  677. font-weight: bold;
  678. }
  679. .el-radio-button:first-child .el-radio-button__inner {
  680. border: none;
  681. }
  682. }
  683. </style>
  684. <style lang="scss" scoped>
  685. .baggage-view {
  686. width: 100%;
  687. height: calc(100vh - 81px);
  688. overflow: hidden;
  689. background: #dfe3ea;
  690. padding: 8px 8px 0;
  691. .part1 {
  692. width: 100%;
  693. height: 232px;
  694. background: #041741;
  695. padding: 16px 30px;
  696. .title {
  697. font-size: 18px;
  698. font-weight: bold;
  699. color: #ffffff;
  700. width: 320px;
  701. display: flex;
  702. flex-direction: row;
  703. justify-content: space-between;
  704. align-items: center;
  705. }
  706. .part1_info {
  707. width: 100%;
  708. color: #fff;
  709. font-size: 14px;
  710. font-weight: 400;
  711. color: #ffffff;
  712. > .el-row > .el-col {
  713. height: 38px;
  714. line-height: 38px;
  715. display: flex;
  716. .label {
  717. flex-basis: 126px;
  718. text-align: right;
  719. }
  720. .content {
  721. flex: 1;
  722. margin: 0;
  723. white-space: nowrap;
  724. overflow: hidden;
  725. text-overflow: ellipsis;
  726. }
  727. }
  728. }
  729. }
  730. .part2 {
  731. margin: 8px 0;
  732. width: 100%;
  733. padding: 24px 30px;
  734. background: #ffffff;
  735. display: flex;
  736. flex-direction: row;
  737. justify-content: space-between;
  738. align-items: center;
  739. .part2_info {
  740. display: flex;
  741. flex-direction: row;
  742. justify-content: flex-start;
  743. align-items: center;
  744. .title {
  745. font-size: 18px;
  746. font-weight: bold;
  747. color: #303133;
  748. margin-right: 42px;
  749. }
  750. .type {
  751. font-size: 18px;
  752. font-weight: bold;
  753. margin-right: 80px;
  754. }
  755. .warn {
  756. color: #df3559;
  757. }
  758. .normal {
  759. color: #519f6b;
  760. }
  761. .step {
  762. height: 80px;
  763. width: 1430px;
  764. position: relative;
  765. .baggage-track-chart {
  766. display: flex;
  767. flex-direction: row;
  768. justify-content: space-between;
  769. align-items: center;
  770. width: 100%;
  771. overflow-x: scroll;
  772. overflow-y: hidden;
  773. > span {
  774. z-index: 1;
  775. }
  776. }
  777. .stepLine {
  778. width: 100%;
  779. height: 20px;
  780. background: #afb4bf;
  781. position: absolute;
  782. top: 50%;
  783. margin-top: -10px;
  784. border-radius: 10px;
  785. .stepLineBlue {
  786. position: absolute;
  787. height: 100%;
  788. background: #041741;
  789. border-radius: 10px;
  790. }
  791. }
  792. .stepItem {
  793. width: 80px;
  794. height: 80px;
  795. background: #afb4bf;
  796. border-radius: 50%;
  797. text-align: center;
  798. font-weight: bold;
  799. color: #ffffff;
  800. font-size: 12px;
  801. display: flex;
  802. flex-direction: column;
  803. align-content: space-around;
  804. align-items: center;
  805. // padding-top: 19px;
  806. justify-content: center;
  807. .head {
  808. font-size: 14px;
  809. }
  810. }
  811. .activeItem {
  812. background: #041741;
  813. }
  814. }
  815. }
  816. }
  817. .part3 {
  818. width: 100%;
  819. // header-80px、part1-232px、part2-128px、间隙3*8px、底部44px
  820. height: calc(100vh - 80px - 232px - 128px - 3 * 8px - 44px);
  821. background: #ffffff;
  822. ::v-deep .el-table {
  823. width: 100%;
  824. // &.el-table--striped {
  825. // .el-table__body tr.el-table__row--striped td.el-table__cell,
  826. // .el-table__header .el-table__cell {
  827. // background: #ffffff;
  828. // }
  829. // }
  830. .el-table__cell {
  831. // background: #f0f3f7;
  832. padding: 0;
  833. .cell {
  834. padding: 0;
  835. word-spacing: 0;
  836. font-size: 14px;
  837. font-family: Helvetica, 'Microsoft YaHei';
  838. font-weight: 400;
  839. color: #303133;
  840. .cell-content {
  841. padding: 6px 0;
  842. }
  843. }
  844. }
  845. .el-table__body .el-table__cell .cell {
  846. padding: 6px 10px;
  847. .cell-content {
  848. display: inline;
  849. padding: 0;
  850. }
  851. }
  852. }
  853. }
  854. .part4 {
  855. width: 100%;
  856. height: calc(100vh - 80px - 232px - 2 * 8px - 44px);
  857. .head {
  858. padding: 16px 24px 11px 30px;
  859. background: transparent;
  860. display: flex;
  861. justify-content: space-between;
  862. .title {
  863. line-height: 30px;
  864. font-size: 18px;
  865. font-weight: bold;
  866. color: #303133;
  867. }
  868. }
  869. .main {
  870. height: calc(100% - 57px);
  871. overflow-y: auto;
  872. overflow-x: hidden;
  873. ::v-deep .el-row {
  874. flex-wrap: wrap;
  875. .card {
  876. width: 100%;
  877. min-height: 440px;
  878. padding: 24px 0 24px 32px;
  879. background: #ffffff;
  880. box-shadow: 0px 3px 2px 0px rgba(0, 0, 0, 0.29);
  881. margin-bottom: 24px;
  882. > .message-date {
  883. width: 160px;
  884. height: 26px;
  885. line-height: 14px;
  886. font-size: 14px;
  887. font-family: Helvetica;
  888. color: #afb4bf;
  889. border-bottom: 1px solid #afb4bf;
  890. margin-bottom: 18px;
  891. }
  892. > .message-content {
  893. white-space: pre-line;
  894. line-height: 24px;
  895. font-size: 14px;
  896. color: #303133;
  897. }
  898. }
  899. }
  900. }
  901. }
  902. .btns {
  903. height: 30px;
  904. display: flex;
  905. .btn-square {
  906. margin-left: 10px;
  907. width: 30px;
  908. cursor: pointer;
  909. }
  910. }
  911. }
  912. </style>
  913. <style lang="scss">
  914. .el-popover {
  915. &.popover-dark {
  916. background: #303133;
  917. color: #ffffff;
  918. border: none;
  919. }
  920. .pre-line {
  921. white-space: pre-line;
  922. }
  923. }
  924. .el-popper[x-placement^='top'].popover-dark .popper__arrow::after {
  925. border-top-color: #303133;
  926. }
  927. .el-popper[x-placement^='right'].popover-dark .popper__arrow::after {
  928. border-right-color: #303133;
  929. }
  930. .el-popper[x-placement^='bottom'].popover-dark .popper__arrow::after {
  931. border-bottom-color: #303133;
  932. }
  933. .el-popper[x-placement^='left'].popover-dark .popper__arrow::after {
  934. border-left-color: #303133;
  935. }
  936. </style>