LineAnalysis.vue 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042
  1. <template>
  2. <Layout>
  3. <template #left>
  4. <div class="left">
  5. <div class="left-top">
  6. <Box
  7. v-for="(item, index) in leftContent.tCharts"
  8. :key="index"
  9. :width="680"
  10. :height="406"
  11. :name="item.name"
  12. >
  13. <Echart :option="item.option" />
  14. </Box>
  15. </div>
  16. <Box
  17. class="left-bottom"
  18. :width="1370"
  19. :height="818"
  20. :name="'近期调整线路'"
  21. >
  22. <div class="content">
  23. <div class="control">
  24. <SelectDate
  25. @date-change="selectDatechange"
  26. />
  27. <n-date-picker
  28. v-model:value="lineAdjustData.range"
  29. :bordered="false"
  30. type="daterange"
  31. style="width: 260px;"
  32. />
  33. </div>
  34. <div class="content-top">
  35. <div class="title">
  36. <icon
  37. :name="'1-6'"
  38. :size="30"
  39. />
  40. <div>线路调整总览</div>
  41. </div>
  42. <div class="overview">
  43. <div
  44. v-for="item,key in lineAdjustData.overview"
  45. :key="key"
  46. class="item"
  47. >
  48. <icon
  49. :name="'1-6'"
  50. :size="40"
  51. />
  52. <div class="name">
  53. {{ lineAdjustData.map[key] }}
  54. </div>
  55. <div class="num">
  56. {{ item }}
  57. </div>
  58. </div>
  59. </div>
  60. </div>
  61. <div class="content-bottom">
  62. <div class="title">
  63. <icon
  64. :name="'1-6'"
  65. :size="30"
  66. />
  67. <div>线路调整详情</div>
  68. </div>
  69. <n-data-table
  70. :columns="lineAdjustData.columns"
  71. :data="lineAdjustData.tableData"
  72. max-height="470"
  73. striped
  74. class="table"
  75. />
  76. </div>
  77. </div>
  78. </Box>
  79. </div>
  80. </template>
  81. <template #right>
  82. <div class="right">
  83. <div class="right-top">
  84. <Box
  85. v-for="(item, index) in rightContent.tCharts"
  86. :key="index"
  87. :width="680"
  88. :height="406"
  89. :name="item.name"
  90. >
  91. <Echart :option="item.option" />
  92. </Box>
  93. </div>
  94. <Box
  95. class="right-center"
  96. :width="1370"
  97. :height="406"
  98. :name="'线路运行速度'"
  99. >
  100. <Echart :option="rightContent.center" />
  101. <div class="control">
  102. <SelectDate
  103. @date-change="rankDatechange"
  104. />
  105. <n-date-picker
  106. v-model:value="rankRange"
  107. :bordered="false"
  108. type="daterange"
  109. style="width: 260px;"
  110. />
  111. </div>
  112. </Box>
  113. <Box
  114. class="right-bottom"
  115. :width="1370"
  116. :height="406"
  117. :name="'站点客流排名'"
  118. >
  119. <Echart :option="rightContent.bottom" />
  120. <div class="control">
  121. <SelectDate
  122. @date-change="stationRankchange"
  123. />
  124. <n-date-picker
  125. v-model:value="stationRankRange"
  126. :bordered="false"
  127. type="daterange"
  128. style="width: 260px;"
  129. />
  130. </div>
  131. </Box>
  132. </div>
  133. </template>
  134. </Layout>
  135. </template>
  136. <script setup lang='ts'>
  137. import Layout from '@/components/layout.vue'
  138. import Box from '@/components/box.vue'
  139. import Echart from '@/components/chart.vue'
  140. import SelectDate from '@/components/selectDate.vue'
  141. import {
  142. Ref, h, ref, watch
  143. } from 'vue'
  144. import { graphic } from 'echarts'
  145. import LineAnalysisService from '../services/lineAnalysis.service'
  146. import { format, subDays } from 'date-fns'
  147. const leftContent:Ref<any> = ref({
  148. tCharts: [
  149. {
  150. name: '线路类型',
  151. option: {
  152. grid: {
  153. containLabel: true
  154. },
  155. // 图表图例
  156. legend: {
  157. show: true,
  158. type: 'scroll',
  159. orient: 'horizontal', // 图例排列方向
  160. icon: 'circle', // 图例样式为圆形
  161. itemWidth: 10, // 图例图形的宽度
  162. itemHeight: 16, // 图例图形的高度
  163. itemGap: 10, // 图例项之间的间隔
  164. left: 'center', // 图例距离容器右侧的距离
  165. bottom: 0, // 图例垂直居中
  166. textStyle: {
  167. color: 'white', // 图例文字颜色
  168. fontSize: 20
  169. }
  170. },
  171. // color: [ '#6386e0', '#fb9a55', '#6bd98d', '#8dfd15', '#6bd98d', '#fff' ],
  172. series: [
  173. {
  174. type: 'pie', // 图表类型为饼图
  175. radius: '60%', // 控制内外圆环的半径,30%代表内圆,60%代表外圆
  176. avoidLabelOverlap: true, // 是否启用防止标签重叠策略
  177. showEmptyCircle: true, // 是否在无数据的时候显示一个占位圆
  178. label: {
  179. show: true,
  180. formatter: '{b}: {c}条',
  181. color: 'white'
  182. },
  183. data: [
  184. { key: 2, name: '常规', value: 130 },
  185. { key: 2, name: '快线', value: 50 },
  186. { key: 2, name: '特色线路', value: 50 }
  187. ]
  188. }
  189. ]
  190. }
  191. },
  192. {
  193. name: '区域里程',
  194. option: {
  195. tooltip: {
  196. trigger: 'axis',
  197. axisPointer: {
  198. type: 'shadow'
  199. }
  200. },
  201. grid: {
  202. top: 20,
  203. left: 20,
  204. bottom: 20,
  205. right: 20,
  206. containLabel: true
  207. },
  208. xAxis: {
  209. type: 'value',
  210. splitLine: {
  211. lineStyle: {
  212. color: '#fff'
  213. }
  214. },
  215. axisLabel: {
  216. color: '#fff',
  217. fontSize: 18
  218. }
  219. },
  220. yAxis: {
  221. type: 'category',
  222. inverse: true,
  223. axisTick: {
  224. alignWithLabel: true,
  225. lineStyle: {
  226. color: '#fff'
  227. }
  228. },
  229. axisLine: {
  230. lineStyle: {
  231. color: '#fff'
  232. }
  233. },
  234. data: [ '雨城区', '雨城区', '雨城区', '雨城区', '雨城区', '雨城区', '雨城区', '雨城区' ],
  235. axisLabel: {
  236. fontSize: 18,
  237. color: '#fff',
  238. margin: 10,
  239. rich: {
  240. a1: {
  241. backgroundColor: '#FFFF0050',
  242. width: 30,
  243. height: 28,
  244. align: 'center',
  245. borderRadius: 15,
  246. fontSize: 18,
  247. borderColor: '#FFFF00',
  248. borderType: 'solid',
  249. borderWidth: 1,
  250. padding: [ 2, 0, 0, 0 ]
  251. },
  252. a2: {
  253. backgroundColor: '#F2F2F250',
  254. width: 30,
  255. height: 28,
  256. align: 'center',
  257. borderRadius: 15,
  258. fontSize: 18,
  259. borderColor: '#F2F2F2',
  260. borderType: 'solid',
  261. borderWidth: 1,
  262. padding: [ 2, 0, 0, 0 ]
  263. },
  264. a3: {
  265. backgroundColor: '#FAAD0E50',
  266. width: 30,
  267. height: 28,
  268. align: 'center',
  269. borderRadius: 15,
  270. fontSize: 18,
  271. borderColor: '#FAAD0E',
  272. borderType: 'solid',
  273. borderWidth: 1,
  274. padding: [ 2, 0, 0, 0 ]
  275. },
  276. b: {
  277. backgroundColor: '#00FFFF50',
  278. width: 30,
  279. height: 28,
  280. align: 'center',
  281. borderRadius: 15,
  282. fontSize: 18,
  283. borderColor: '#00FFFF',
  284. borderType: 'solid',
  285. borderWidth: 1,
  286. padding: [ 2, 0, 0, 0 ]
  287. }
  288. },
  289. formatter: (params: string, _id: number) => {
  290. const id = _id + 1
  291. if (_id < 3) {
  292. return `{a${id}|${id}} ${params}`
  293. }
  294. return `{b|${id}} ${params}`
  295. }
  296. }
  297. },
  298. series: [
  299. {
  300. z: 2,
  301. name: 'value',
  302. type: 'bar',
  303. barWidth: 25,
  304. zlevel: 1,
  305. data: [ '80', '70', '60', '50', '40', '30', '20', '10' ],
  306. itemStyle: {
  307. borderRadius: [ 0, 16, 16, 0 ],
  308. color: new graphic.LinearGradient(0, 0, 1, 0, [
  309. {
  310. offset: 0,
  311. color: 'rgba(20,167,250,0.3)'
  312. },
  313. {
  314. offset: 1,
  315. color: 'rgba(0,255,209,1)'
  316. }
  317. ])
  318. },
  319. label: {
  320. position: 'inside',
  321. color: '#fff',
  322. fontSize: 16
  323. }
  324. }
  325. ]
  326. }
  327. }
  328. ]
  329. })
  330. const rightContent:Ref<any> = ref({
  331. tCharts: [
  332. {
  333. name: '线路长度分布',
  334. option: {
  335. title: {
  336. text: '总', // 图标内容文本
  337. subtext: '200',
  338. left: 'center', // 图标内容水平居中
  339. top: 'center', // 图标内容垂直居中
  340. // 文本样式
  341. textStyle: {
  342. color: '#fff', // 图标内容文字颜色
  343. fontSize: '18px', // 图标内容文字大小
  344. fontWeight: 'normal'
  345. },
  346. subtextStyle: {
  347. color: '#fff', // 图标内容文字颜色
  348. fontSize: '18px', // 图标内容文字大小
  349. fontWeight: 'normal'
  350. }
  351. },
  352. grid: {
  353. containLabel: true
  354. },
  355. // 图表图例
  356. legend: {
  357. show: true,
  358. type: 'scroll',
  359. orient: 'horizontal', // 图例排列方向
  360. icon: 'circle', // 图例样式为圆形
  361. itemWidth: 10, // 图例图形的宽度
  362. itemHeight: 16, // 图例图形的高度
  363. itemGap: 10, // 图例项之间的间隔
  364. left: 'center', // 图例距离容器右侧的距离
  365. bottom: 0, // 图例垂直居中
  366. textStyle: {
  367. color: 'white', // 图例文字颜色
  368. fontSize: 20
  369. }
  370. },
  371. // color: [ '#6386e0', '#fb9a55', '#6bd98d', '#8dfd15', '#6bd98d', '#fff' ],
  372. series: [
  373. {
  374. type: 'pie', // 图表类型为饼图
  375. radius: [ '45%', '65%' ], // 控制内外圆环的半径,30%代表内圆,60%代表外圆
  376. avoidLabelOverlap: true, // 是否启用防止标签重叠策略
  377. showEmptyCircle: true, // 是否在无数据的时候显示一个占位圆
  378. label: {
  379. show: true,
  380. formatter: '{b} : {d}%',
  381. color: 'white'
  382. },
  383. data: [
  384. { key: 2, name: '5km', value: 180 },
  385. { key: 2, name: '5-10km', value: 50 },
  386. { key: 2, name: '10-15km', value: 30 },
  387. { key: 2, name: '15-20km', value: 20 },
  388. { key: 2, name: '20km', value: 10 }
  389. ]
  390. }
  391. ]
  392. }
  393. },
  394. {
  395. name: '线路占据分布',
  396. option: {
  397. title: {
  398. text: '总', // 图标内容文本
  399. subtext: '190',
  400. left: 'center', // 图标内容水平居中
  401. top: 'center', // 图标内容垂直居中
  402. // 文本样式
  403. textStyle: {
  404. color: '#fff', // 图标内容文字颜色
  405. fontSize: '18px', // 图标内容文字大小
  406. fontWeight: 'normal'
  407. },
  408. subtextStyle: {
  409. color: '#fff', // 图标内容文字颜色
  410. fontSize: '18px', // 图标内容文字大小
  411. fontWeight: 'normal'
  412. }
  413. },
  414. grid: {
  415. containLabel: true
  416. },
  417. // 图表图例
  418. legend: {
  419. show: true,
  420. type: 'scroll',
  421. orient: 'horizontal', // 图例排列方向
  422. icon: 'circle', // 图例样式为圆形
  423. itemWidth: 10, // 图例图形的宽度
  424. itemHeight: 16, // 图例图形的高度
  425. itemGap: 10, // 图例项之间的间隔
  426. left: 'center', // 图例距离容器右侧的距离
  427. bottom: 0, // 图例垂直居中
  428. textStyle: {
  429. color: 'white', // 图例文字颜色
  430. fontSize: 20
  431. }
  432. },
  433. // color: [ '#6386e0', '#fb9a55', '#6bd98d', '#8dfd15', '#6bd98d', '#fff' ],
  434. series: [
  435. {
  436. type: 'pie', // 图表类型为饼图
  437. radius: [ '45%', '65%' ], // 控制内外圆环的半径,30%代表内圆,60%代表外圆
  438. avoidLabelOverlap: true, // 是否启用防止标签重叠策略
  439. showEmptyCircle: true, // 是否在无数据的时候显示一个占位圆
  440. label: {
  441. show: true,
  442. formatter: '{b} : {d}%',
  443. color: 'white'
  444. },
  445. data: [
  446. { key: 2, name: '<300m', value: 180 },
  447. { key: 2, name: '300-500m', value: 50 },
  448. { key: 2, name: '300-1000m', value: 30 },
  449. { key: 2, name: '>1000m', value: 20 }
  450. ]
  451. }
  452. ]
  453. }
  454. }
  455. ],
  456. center: {
  457. grid: {
  458. containLabel: true,
  459. right: 30,
  460. left: 50,
  461. bottom: '25%',
  462. top: '20%'
  463. },
  464. legend: {
  465. show: true,
  466. left: 'center',
  467. bottom: '15%',
  468. itemWidth: 15,
  469. itemHeight: 10,
  470. textStyle: {
  471. color: '#646464',
  472. fontSize: 18
  473. }
  474. },
  475. xAxis: [ {
  476. type: 'category',
  477. axisLine: {
  478. show: false
  479. },
  480. axisLabel: {
  481. color: '#fff',
  482. fontSize: 18
  483. // formatter: (value: number) => format( 1'时')
  484. },
  485. splitLine: {
  486. show: false
  487. },
  488. axisTick: {
  489. show: false
  490. },
  491. data: [ '1时', '2时', '3时', '4时', '5时', '6时', '7时', '8时', '9时', '10时', '11时', '12时' ]
  492. } ],
  493. yAxis: [ {
  494. name: 'km/h',
  495. nameLocation: 'center',
  496. nameGap: 50,
  497. nameTextStyle: {
  498. color: '#fff',
  499. fontSize: 18
  500. },
  501. padding: 5,
  502. // max: 1000,
  503. splitLine: {
  504. show: true,
  505. lineStyle: {
  506. color: '#A1A7B3'
  507. // type: 'dashed'
  508. }
  509. },
  510. axisLine: {
  511. show: false
  512. },
  513. axisLabel: {
  514. show: true,
  515. margin: 10,
  516. textStyle: {
  517. color: '#fff'
  518. }
  519. },
  520. axisTick: {
  521. show: false
  522. }
  523. }
  524. ],
  525. series: [ {
  526. name: '常规',
  527. type: 'line',
  528. smooth: true,
  529. symbolSize: 0,
  530. itemStyle: {
  531. normal: {
  532. // color: '#4293FD',
  533. lineStyle: {
  534. // color: '#4293FD',
  535. width: 2
  536. }
  537. }
  538. },
  539. data: [ 120, 132, 101, 134, 90, 230, 210, 182, 191, 234, 290, 330 ]
  540. },
  541. {
  542. name: '快线',
  543. type: 'line',
  544. smooth: true,
  545. symbolSize: 0,
  546. itemStyle: {
  547. normal: {
  548. // color: '#23D0C4',
  549. lineStyle: {
  550. // color: '#23D0C4',
  551. width: 2
  552. }
  553. }
  554. },
  555. data: [ 220, 182, 191, 234, 290, 330, 310, 201, 154, 190, 330, 410 ]
  556. },
  557. {
  558. name: '特色线路',
  559. type: 'line',
  560. smooth: true,
  561. symbolSize: 0,
  562. itemStyle: {
  563. normal: {
  564. // color: '#23D0C4',
  565. lineStyle: {
  566. // color: '#23D0C4',
  567. width: 2
  568. }
  569. }
  570. },
  571. data: [ 220, 182, 191, 234, 290, 330, 310, 201, 154, 190, 330, 410 ]
  572. }
  573. ],
  574. dataZoom: {}
  575. },
  576. bottom: {
  577. grid: {
  578. containLabel: true,
  579. top: '35%',
  580. right: 30,
  581. left: 50,
  582. bottom: 0
  583. },
  584. tooltip: {
  585. trigger: 'axis',
  586. axisPointer: {
  587. type: 'shadow'
  588. }
  589. },
  590. legend: {
  591. top: 70,
  592. left: '50%',
  593. itemWidth: 18,
  594. itemHeight: 18,
  595. itemGap: 30,
  596. textStyle: {
  597. fontSize: 18,
  598. color: '#C9D2FA'
  599. }
  600. },
  601. xAxis: {
  602. // name: "班级",
  603. triggerEvent: true,
  604. data: [
  605. '雨城区',
  606. '芦山县',
  607. '名山县',
  608. '天全县',
  609. '宝兴县',
  610. '汉源县',
  611. '雨城区',
  612. '芦山县',
  613. '名山县',
  614. '天全县',
  615. '宝兴县',
  616. '汉源县'
  617. ],
  618. axisLabel: {
  619. interval: 0,
  620. show: true,
  621. fontSize: 18,
  622. color: '#C9D2FA'
  623. },
  624. axisLine: {
  625. show: false,
  626. lineStyle: {
  627. show: false,
  628. color: '#F3F3F3',
  629. width: 2
  630. }
  631. },
  632. axisTick: {
  633. show: false
  634. }
  635. },
  636. yAxis: [
  637. {
  638. name: '人数',
  639. nameLocation: 'center',
  640. nameGap: 50,
  641. nameTextStyle: {
  642. color: '#fff',
  643. fontSize: 18
  644. },
  645. splitNumber: 2,
  646. axisLabel: {
  647. show: true,
  648. fontSize: 18,
  649. color: '#C9D2FA'
  650. },
  651. axisLine: {
  652. show: false
  653. },
  654. axisTick: {
  655. show: false
  656. },
  657. splitLine: {
  658. lineStyle: {
  659. type: 'dashed',
  660. color: '#3E4A82'
  661. }
  662. }
  663. }
  664. ],
  665. series: [
  666. {
  667. name: '客流量',
  668. type: 'bar',
  669. silent: true,
  670. itemStyle: {
  671. normal: {
  672. color: new graphic.LinearGradient(
  673. 0,
  674. 0,
  675. 0,
  676. 1,
  677. [
  678. {
  679. offset: 0,
  680. color: '#FFD35D'// 0% 处的颜色
  681. },
  682. {
  683. offset: 0.5,
  684. color: '#7ec2f382'// 0% 处的颜色
  685. },
  686. {
  687. offset: 1,
  688. color: '#1890ff21' // 100% 处的颜色
  689. }
  690. ],
  691. false
  692. )
  693. }
  694. },
  695. barWidth: 30,
  696. data: [ 200, 108, 200, 40, 210, 100, 200, 108, 200, 40, 210, 100 ]
  697. }
  698. ]
  699. }
  700. })
  701. const lineAnalysisService = new LineAnalysisService()
  702. async function getAnalysisLineType() {
  703. const res = await lineAnalysisService.getAnalysisLineType()
  704. leftContent.value.tCharts[0].option.series[0].data = res.map((item:any) => ({
  705. name: item.type,
  706. value: item.number
  707. }))
  708. }
  709. getAnalysisLineType()
  710. async function getAnalysisRegionFlow() {
  711. const res = await lineAnalysisService.getAnalysisRegionFlow()
  712. const yData = []
  713. const seriesData = []
  714. for (let i = 0; i < res.length; i++) {
  715. const item = res[i]
  716. yData.push(item.region)
  717. seriesData.push(item.flow)
  718. }
  719. leftContent.value.tCharts[1].option.yAxis.data = yData
  720. leftContent.value.tCharts[1].option.series[0].data = seriesData
  721. }
  722. getAnalysisRegionFlow()
  723. const lineAdjustData = ref({
  724. range: [ subDays(Date.now(), 7), Date.now() ],
  725. type: 4,
  726. tableData: [] as any[],
  727. columns: [
  728. {
  729. title: '序号',
  730. render: (_: any, rowIndex: number) => h('span', rowIndex + 1)
  731. },
  732. {
  733. title: '措施',
  734. key: 'measure',
  735. render: (_: any) => h('span', lineAdjustData.value.map[_.measure])
  736. },
  737. {
  738. title: '区域',
  739. key: 'region'
  740. },
  741. {
  742. title: '线路',
  743. key: 'lineName'
  744. },
  745. {
  746. title: '线路类型',
  747. key: 'lineType'
  748. },
  749. {
  750. title: '时间',
  751. key: 'time'
  752. }
  753. ],
  754. overview: {
  755. // 新辟
  756. 1: 0,
  757. // 撤销
  758. 2: 0,
  759. // 调整
  760. 3: 0
  761. },
  762. map: {
  763. 1: '新辟',
  764. 2: '撤销',
  765. 3: '调整'
  766. }as any
  767. })
  768. async function getAnalysisLineAdjust(params:any) {
  769. const res = await lineAnalysisService.getAnalysisLineAdjust(params)
  770. let total1 = 0
  771. let total2 = 0
  772. let total3 = 0
  773. for (let i = 0; i < res.length; i++) {
  774. const item = res[i]
  775. if (item.measure === 1) {
  776. total1++
  777. }
  778. if (item.measure === 2) {
  779. total2++
  780. }
  781. if (item.measure === 3) {
  782. total3++
  783. }
  784. }
  785. lineAdjustData.value.overview[1] = total1
  786. lineAdjustData.value.overview[2] = total2
  787. lineAdjustData.value.overview[3] = total3
  788. lineAdjustData.value.tableData = res
  789. }
  790. function selectDatechange(type: number) {
  791. lineAdjustData.value.type = type
  792. const params = {
  793. type: lineAdjustData.value.type
  794. }
  795. getAnalysisLineAdjust(params)
  796. }
  797. watch(() => lineAdjustData.value.range, () => {
  798. const params = {
  799. startTime: format(lineAdjustData.value.range[0], 'yyyy-MM-dd'),
  800. endTime: format(lineAdjustData.value.range[1], 'yyyy-MM-dd')
  801. }
  802. getAnalysisLineAdjust(params)
  803. }, { immediate: true })
  804. async function getAnalysisLineLength() {
  805. const res = await lineAnalysisService.getAnalysisLineLength()
  806. const seriesData = []
  807. let total = 0
  808. for (let i = 0; i < res.length; i++) {
  809. const item = res[i]
  810. seriesData.push({
  811. name: item.lengthType,
  812. value: item.proportion
  813. })
  814. total += +item.proportion
  815. }
  816. rightContent.value.tCharts[0].option.series[0].data = seriesData
  817. rightContent.value.tCharts[0].option.title.subtext = total
  818. }
  819. getAnalysisLineLength()
  820. async function getAnalysisLineDistance() {
  821. const res = await lineAnalysisService.getAnalysisLineDistance()
  822. const seriesData = []
  823. let total = 0
  824. for (let i = 0; i < res.length; i++) {
  825. const item = res[i]
  826. seriesData.push({
  827. name: item.distanceType,
  828. value: item.proportion
  829. })
  830. total += +item.proportion
  831. }
  832. rightContent.value.tCharts[1].option.series[0].data = seriesData
  833. rightContent.value.tCharts[1].option.title.subtext = total
  834. }
  835. getAnalysisLineDistance()
  836. const rankRange = ref([ subDays(Date.now(), 7), Date.now() ])
  837. async function getAnalysisLineOperate(params:any) {
  838. const res = await lineAnalysisService.getAnalysisLineOperate(params)
  839. const xAxisData = []
  840. const seriesData1 = []
  841. const seriesData2 = []
  842. const seriesData3 = []
  843. for (let i = 0; i < res.length; i++) {
  844. const item = res[i]
  845. xAxisData.push(item.time)
  846. seriesData1.push(item.conventionLine)
  847. seriesData2.push(item.expressLine)
  848. seriesData3.push(item.characteristicLine)
  849. }
  850. rightContent.value.center.xAxis[0].data = xAxisData
  851. rightContent.value.center.series[0].data = seriesData1
  852. rightContent.value.center.series[1].data = seriesData2
  853. rightContent.value.center.series[2].data = seriesData3
  854. }
  855. function rankDatechange(type: number) {
  856. const params = {
  857. type
  858. }
  859. getAnalysisLineOperate(params)
  860. }
  861. watch(() => rankRange.value, () => {
  862. const params = {
  863. startTime: format(rankRange.value[0], 'yyyy-MM-dd'),
  864. endTime: format(rankRange.value[1], 'yyyy-MM-dd')
  865. }
  866. getAnalysisLineOperate(params)
  867. }, { immediate: true })
  868. const stationRankRange = ref([ subDays(Date.now(), 7), Date.now() ])
  869. async function getAnalysisStationRank(params:any) {
  870. const res = await lineAnalysisService.getAnalysisStationRank(params)
  871. const groupData = groupBy(res, 'stationName')
  872. console.log(groupData, 'groupData')
  873. const xAxisData = []
  874. const seriesData1 = []
  875. for (const key in groupData) {
  876. const item = groupData[key]
  877. xAxisData.push(key)
  878. const total = item.reduce((prev: any, item: { flow: number }) => {
  879. prev += item.flow
  880. return prev
  881. }, 0)
  882. seriesData1.push(total)
  883. }
  884. rightContent.value.bottom.xAxis.data = xAxisData
  885. rightContent.value.bottom.series[0].data = seriesData1
  886. }
  887. function stationRankchange(type: number) {
  888. const params = {
  889. type
  890. }
  891. getAnalysisStationRank(params)
  892. }
  893. watch(() => stationRankRange.value, () => {
  894. const params = {
  895. startTime: format(stationRankRange.value[0], 'yyyy-MM-dd HH:mm:ss'),
  896. endTime: format(stationRankRange.value[1], 'yyyy-MM-dd HH:mm:ss')
  897. }
  898. getAnalysisStationRank(params)
  899. }, { immediate: true })
  900. function groupBy(array: any[], id: string) {
  901. const groups:any = {}
  902. array.forEach((o) => {
  903. let group = JSON.stringify(o[id])
  904. if (typeof o[id] === 'string') {
  905. group = o[id]
  906. }
  907. groups[group] = groups[group] || []
  908. groups[group].push(o)
  909. })
  910. // return Object.values(groups);
  911. return groups
  912. }
  913. </script>
  914. <style lang="scss" scoped>
  915. .left {
  916. &-top {
  917. display: flex;
  918. justify-content: space-between;
  919. }
  920. &-bottom {
  921. .content {
  922. width: 100%;
  923. padding: 35px;
  924. position: relative;
  925. .title {
  926. display: flex;
  927. gap: 10px;
  928. color: #FFFFFF;
  929. text-shadow: 1px 1px 10px rgba(0, 255, 255, 0.7);
  930. font-size: 20px;
  931. .icon {
  932. width: 30px;
  933. height: 30px;
  934. background: #000;
  935. }
  936. }
  937. .overview {
  938. display: flex;
  939. padding: 34px;
  940. justify-content: space-between;
  941. .item {
  942. width: 375px;
  943. height: 65px;
  944. background: rgba(27, 175, 255, 0.298);
  945. border: 1px solid #00FFFF;
  946. display: flex;
  947. align-items: center;
  948. justify-content: center;
  949. color: #FFFFFF;
  950. font-size: 20px;
  951. gap: 10px;
  952. .icon {
  953. width: 30px;
  954. height: 30px;
  955. background: #000;
  956. }
  957. .num {
  958. color: #00FFFF;
  959. font-size: 30px;
  960. font-family: Impact Normal;
  961. }
  962. }
  963. }
  964. .table{
  965. margin-top: 30px;
  966. text-align: center;
  967. font-size: 16px;
  968. th{
  969. border: 0;
  970. }
  971. }
  972. .control{
  973. position: absolute;
  974. top: 30px;
  975. right: 125px;
  976. .selectDate{
  977. top: 0px;
  978. left: -300px;
  979. }
  980. }
  981. }
  982. }
  983. }
  984. .right{
  985. &-top {
  986. display: flex;
  987. justify-content: space-between;
  988. }
  989. &-center,&-bottom {
  990. position: relative;
  991. .control{
  992. position: absolute;
  993. top: 60px;
  994. right: 110px;
  995. .selectDate{
  996. top: 0px;
  997. left: -300px;
  998. }
  999. }
  1000. }
  1001. }
  1002. </style>