index.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. <template>
  2. <div class="dashboard">
  3. <div class="dashboard-scrollbar">
  4. <div class="dashboard-wrapper">
  5. <div class="dashboard-card">
  6. <div class="dashboard-card-wrapper">
  7. <div class="dashboard-card-title">当日进港航班数</div>
  8. <div class="dashboard-card-content">
  9. <CountBox
  10. :count-number="arrivalFlightCount"
  11. :count-length="9"
  12. />
  13. </div>
  14. </div>
  15. <div class="dashboard-card-wrapper">
  16. <div class="dashboard-card-title">当日出港航班数</div>
  17. <div class="dashboard-card-content">
  18. <CountBox
  19. :count-number="departureFlightCount"
  20. :count-length="9"
  21. />
  22. </div>
  23. </div>
  24. </div>
  25. <div class="dashboard-card">
  26. <div class="dashboard-card-wrapper">
  27. <div class="dashboard-card-title">航司行李量排行</div>
  28. </div>
  29. </div>
  30. <div class="dashboard-card">
  31. <div class="dashboard-card-wrapper">
  32. <div class="dashboard-card-title">
  33. <span class="title-text">航站选择</span>
  34. <el-select
  35. v-model="currentAirport"
  36. placeholder="请选择航站"
  37. filterable
  38. >
  39. <el-option
  40. v-for="option in aiportOptions"
  41. :key="option.value"
  42. :label="option.label"
  43. :value="option.value"
  44. />
  45. </el-select>
  46. </div>
  47. </div>
  48. </div>
  49. <div class="dashboard-card">
  50. <div class="dashboard-card-wrapper">
  51. <div class="dashboard-card-title">当日行李量统计</div>
  52. <div class="dashboard-card-content">
  53. <div
  54. v-for="item in baggageCountItems"
  55. :key="item.title"
  56. class="baggage-count-item"
  57. >
  58. <div class="baggage-count-num">{{ item.num }}</div>
  59. <div class="baggage-count-title">{{ item.title }}</div>
  60. </div>
  61. </div>
  62. </div>
  63. </div>
  64. <div class="dashboard-card">
  65. <div class="dashboard-card-wrapper">
  66. <div class="dashboard-card-title">当日行李目的地分布图</div>
  67. </div>
  68. <div class="dashboard-card-content">
  69. <MapCharts
  70. id="box-map"
  71. :option="boxMap"
  72. />
  73. </div>
  74. </div>
  75. <div class="dashboard-card">
  76. <div class="dashboard-card-wrapper">
  77. <div class="dashboard-card-title">每日小时行李处理量 - 进港</div>
  78. </div>
  79. </div>
  80. <div class="dashboard-card">
  81. <div class="dashboard-card-wrapper">
  82. <div class="dashboard-card-title">每日小时行李处理量 - 出港</div>
  83. </div>
  84. </div>
  85. <div class="dashboard-card">
  86. <div class="dashboard-card-wrapper">
  87. <div class="dashboard-card-title">每日小时行李处理量 - 中转</div>
  88. </div>
  89. </div>
  90. </div>
  91. </div>
  92. </div>
  93. </template>
  94. <script>
  95. import CountBox from '@/components/CountBox/index.vue'
  96. import BarCharts from '@/layout/components/Echarts/commonChartsBar.vue'
  97. import MapCharts from '@/layout/components/Echarts/commonChartsChinaMap.vue'
  98. import vueSeamlessScroll from 'vue-seamless-scroll'
  99. import { Query } from '@/api/webApi'
  100. const defaultDate = '2023-05-09'
  101. export default {
  102. name: 'Dashboard',
  103. components: {
  104. CountBox,
  105. BarCharts,
  106. MapCharts,
  107. vueSeamlessScroll,
  108. },
  109. data() {
  110. return {
  111. arrivalFlightCount: 0,
  112. departureFlightCount: 0,
  113. currentAirport: 'CTU',
  114. aiportOptions: [
  115. {
  116. label: '成都双流机场',
  117. value: 'CTU',
  118. },
  119. ],
  120. baggageCountItems: [
  121. {
  122. title: '行李总数',
  123. num: 223124,
  124. },
  125. {
  126. title: '进港行李数',
  127. num: 223124,
  128. },
  129. {
  130. title: '出港行李数',
  131. num: 223124,
  132. },
  133. {
  134. title: '中转行李数',
  135. num: 223124,
  136. },
  137. ],
  138. boxMap: {
  139. tooltip: {
  140. trigger: 'item',
  141. formatter: function (item) {
  142. if (item.data && item.data.index) {
  143. const html = `<div>
  144. <div>TOP ${item.data.index}</div>
  145. <div>${item.data.name} ${item.data.value}</div>
  146. </div>`
  147. return html
  148. } else {
  149. return '<div>暂无数据</div>'
  150. }
  151. },
  152. },
  153. legend: {
  154. show: false,
  155. },
  156. grid: {
  157. left: 0,
  158. right: 0,
  159. top: 0,
  160. bottom: 0,
  161. },
  162. visualMap: {
  163. type: 'continuous',
  164. text: ['高', '低'],
  165. min: 0,
  166. max: 20000,
  167. seriesIndex: [0, 2],
  168. dimension: 0,
  169. realtime: false,
  170. left: 0,
  171. bottom: '30%',
  172. itemWidth: 8,
  173. itemHeight: 93,
  174. calculable: true,
  175. inRange: {
  176. color: ['#869CBC', 'yellow'],
  177. symbolSize: [100, 100],
  178. },
  179. textStyle: {
  180. color: '#fff',
  181. },
  182. outOfRange: {
  183. color: ['orange'],
  184. symbolSize: [100, 100],
  185. },
  186. },
  187. toolbox: {
  188. show: false,
  189. },
  190. xAxis: {
  191. show: false,
  192. },
  193. yAxis: {
  194. show: false,
  195. },
  196. series: [
  197. {
  198. name: '行李数',
  199. type: 'map',
  200. mapType: 'china',
  201. // left: '100',
  202. // width: '40%',
  203. roam: 'move',
  204. mapValueCalculation: 'sum',
  205. zoom: 1,
  206. selectedMode: false,
  207. showLegendSymbol: false,
  208. left: '10%',
  209. top: '10%',
  210. width: '80%',
  211. label: {
  212. normal: {
  213. textStyle: {
  214. color: '#666666',
  215. },
  216. },
  217. emphasis: {
  218. textStyle: {
  219. color: '#234EA5',
  220. },
  221. },
  222. },
  223. itemStyle: {
  224. normal: {
  225. areaColor: '#fff',
  226. borderColor: '#666666',
  227. },
  228. emphasis: {
  229. areaColor: '#E5F39B',
  230. },
  231. },
  232. data: [],
  233. },
  234. ],
  235. },
  236. }
  237. },
  238. mounted() {
  239. this.getMap()
  240. },
  241. methods: {
  242. // 当日行李分布
  243. async getMap() {
  244. const { code, returnData: listValues } = await Query({
  245. serviceId: SERVICE_ID.dashboardMap,
  246. dataContent: [
  247. {
  248. airport: this.currentAirport,
  249. fd1: defaultDate,
  250. fd2: defaultDate,
  251. },
  252. ],
  253. })
  254. if (code == 0) {
  255. listValues.sort((a, b) => b.bags - a.bags)
  256. listValues.map((item, index) => {
  257. item.name = item.in_province
  258. item.value = item.bags
  259. item.index = index + 1
  260. })
  261. this.boxMap.series[0].data = listValues
  262. }
  263. },
  264. },
  265. }
  266. </script>
  267. <style lang="scss" scoped>
  268. .dashboard {
  269. width: 100%;
  270. height: calc(100vh - 48px - 32px);
  271. padding: 16px 20px;
  272. background-color: #081821;
  273. color: #fff;
  274. &-scrollbar {
  275. margin-right: -20px;
  276. width: calc(100% + 20px);
  277. height: 100%;
  278. overflow-x: hidden;
  279. overflow-y: auto;
  280. }
  281. &-wrapper {
  282. width: 100%;
  283. height: 968px;
  284. display: flex;
  285. flex-direction: column;
  286. flex-wrap: wrap;
  287. justify-content: space-between;
  288. }
  289. &-card {
  290. width: calc((100% - 16px * 2) / 3);
  291. height: calc((100% - 16px * 2) / 3);
  292. padding: 25px;
  293. display: flex;
  294. flex-direction: column;
  295. border: 1px solid #3a4456;
  296. background: linear-gradient(270deg, rgba(118, 142, 184, 0.25), transparent);
  297. position: relative;
  298. &::before {
  299. content: '';
  300. display: block;
  301. width: 0;
  302. height: 0;
  303. position: absolute;
  304. top: 0;
  305. left: 0;
  306. border: 12px solid #6d7d98;
  307. border-right-color: transparent;
  308. border-bottom-color: transparent;
  309. }
  310. &-wrapper {
  311. height: 0;
  312. flex: 1;
  313. &:not(:first-child) {
  314. margin-top: 25px;
  315. }
  316. }
  317. &-title {
  318. height: 40px;
  319. line-height: 16px;
  320. font-size: 16px;
  321. font-family: Helvetica, Microsoft YaHei;
  322. font-weight: bold;
  323. }
  324. &-content {
  325. height: calc(100% - 40px);
  326. }
  327. &:nth-child(1) {
  328. .dashboard-card-content {
  329. max-height: 64px;
  330. }
  331. }
  332. &:nth-child(3) {
  333. height: 40px;
  334. padding: 0 25px;
  335. &::before {
  336. display: none;
  337. }
  338. .dashboard-card-title {
  339. height: 38px;
  340. display: flex;
  341. justify-content: space-between;
  342. line-height: 38px;
  343. .el-select {
  344. width: 160px;
  345. ::v-deep .el-input__inner {
  346. border: none;
  347. background-color: transparent;
  348. font-size: 16px;
  349. font-family: Helvetica, Microsoft YaHei;
  350. font-weight: bold;
  351. color: #ffffff;
  352. }
  353. }
  354. }
  355. }
  356. &:nth-child(4) {
  357. height: calc((100% - 16px * 2) / 3 - 40px - 16px);
  358. }
  359. &:nth-child(2),
  360. &:nth-child(5) {
  361. height: calc((100% - 16px * 2) / 3 * 2 + 16px);
  362. }
  363. &:nth-child(4) {
  364. .dashboard-card-content {
  365. display: flex;
  366. flex-wrap: wrap;
  367. justify-content: space-between;
  368. .baggage-count-item {
  369. height: 50%;
  370. padding-left: 96px;
  371. display: flex;
  372. flex-direction: column;
  373. justify-content: center;
  374. position: relative;
  375. font-family: Helvetica, Microsoft YaHei;
  376. font-weight: bold;
  377. .baggage-count-num {
  378. font-size: 36px;
  379. color: #f7c15a;
  380. }
  381. .baggage-count-title {
  382. font-size: 14px;
  383. }
  384. &::before {
  385. content: url('../../assets/analysis/ic.png');
  386. display: block;
  387. width: 72px;
  388. height: 72px;
  389. position: absolute;
  390. top: 50%;
  391. left: 0;
  392. transform: translate(0, -50%);
  393. }
  394. }
  395. }
  396. }
  397. &:nth-child(5) {
  398. background: transparent;
  399. border: none;
  400. &::before {
  401. display: none;
  402. }
  403. }
  404. }
  405. }
  406. </style>