index.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  1. <script setup lang="ts">
  2. import { computed, markRaw, ref } from 'vue'
  3. import homePage from './components/HomePage.vue'
  4. import cehicleOperation from './components/CehicleOperation.vue'
  5. import lineAnalysis from './components/LineAnalysis.vue'
  6. import maintenanceDynamics from './components/MaintenanceDynamics.vue'
  7. import facilityManagement from './components/FacilityManagement.vue'
  8. import stationManagement from './components/StationManagement.vue'
  9. import passengerFlow from './components/PassengerFlow.vue'
  10. import ChangeLine from '@/components/changeLine.vue'
  11. import Map from '@/components/map/map.vue'
  12. import useStore from '@/pages/store'
  13. import HomeService from './services/homepage.service'
  14. import CehicleOperationService from './services/cehicleOperation.service'
  15. import MaintenanceDynamicsService from './services/maintenanceDynamics.Service'
  16. import PassengerFlowService from './services/passengerFlow.service'
  17. import FacilityManagementService from './services/facilityManagement.service'
  18. import StationManagementService from './services/stationManagement.service'
  19. import LineAnalysisService from './services/lineAnalysis.service'
  20. const homeService = new HomeService()
  21. const cehicleOperationService = new CehicleOperationService()
  22. const passengerFlowService = new PassengerFlowService()
  23. const maintenanceDynamicsService = new MaintenanceDynamicsService()
  24. const facilityManagementService = new FacilityManagementService()
  25. const stationManagementService = new StationManagementService()
  26. const lineAnalysisService = new LineAnalysisService()
  27. const store = useStore()
  28. const menus = [
  29. {
  30. name: '主页',
  31. key: 'homePage',
  32. component: markRaw(homePage),
  33. count: [
  34. { label: '设备车辆', value: 166, util: '辆' },
  35. { label: '线路', value: 60, util: '条' },
  36. { label: '场站', value: 100, util: '个' },
  37. { label: '中途站 ', value: 50, util: '个' },
  38. { label: '班次数量', value: 300, util: '趟' },
  39. {
  40. label: '总里程', value: 100, util: '万公里', style: { right: '-40px' }
  41. },
  42. { label: '入场率', value: 100, util: '%' }
  43. ],
  44. contrlSelect: {
  45. title: '显示点位',
  46. icon: '51',
  47. option: [
  48. {
  49. label: '车辆',
  50. value: 'bus',
  51. icon: '39'
  52. },
  53. {
  54. label: '场站',
  55. value: 'busStation',
  56. icon: '40'
  57. },
  58. {
  59. label: '线路',
  60. value: 'line',
  61. icon: '41'
  62. },
  63. {
  64. label: '充电桩',
  65. value: 'powerCharge',
  66. icon: '42'
  67. },
  68. {
  69. label: '维修站',
  70. value: 'maintenanceStation',
  71. icon: '43'
  72. },
  73. {
  74. label: '中途站点',
  75. value: 'station',
  76. icon: '44'
  77. }
  78. ],
  79. checked: [ 'bus', 'busStation', 'line', 'powerCharge', 'maintenanceStation', 'station' ]
  80. }
  81. },
  82. {
  83. name: '线路运营',
  84. key: 'cehicleOperation',
  85. component: markRaw(cehicleOperation),
  86. count: [
  87. { label: '今日客流', value: 2000, util: '人' },
  88. { label: '计划班次', value: 14, util: '次' },
  89. { label: '已发班次', value: 8, util: '次' },
  90. { label: '塌班 ', value: 0, util: '次' },
  91. {
  92. label: '计划里程', value: 1400, util: '公里', style: { right: '-18px' }
  93. },
  94. {
  95. label: '当前里程', value: 100, util: '公里', style: { right: '-18px' }
  96. },
  97. { label: '空驶率', value: 1, util: '%' }
  98. ],
  99. contrlSelect: {
  100. title: '公交状态',
  101. icon: '51',
  102. option: [
  103. {
  104. label: '拥挤',
  105. value: 1,
  106. icon: '45'
  107. },
  108. {
  109. label: '中等',
  110. value: 2,
  111. icon: '46'
  112. },
  113. {
  114. label: '舒适',
  115. value: 3,
  116. icon: '47'
  117. },
  118. {
  119. label: '维保',
  120. value: 4,
  121. icon: '48'
  122. },
  123. {
  124. label: '充电',
  125. value: 5,
  126. icon: '49'
  127. },
  128. {
  129. label: '停驶',
  130. value: 6,
  131. icon: '50'
  132. }
  133. ],
  134. checked: [ 1, 2, 3, 4, 5, 6 ]
  135. }
  136. },
  137. {
  138. name: '客流分析',
  139. key: 'passengerFlow',
  140. component: markRaw(passengerFlow),
  141. count: [
  142. {
  143. label: '客运量', value: 10, util: '万人次', style: { right: '-40px' }
  144. },
  145. { label: '满载率', value: 14, util: '%' },
  146. {
  147. label: '免费换乘', value: 8, util: '万人次', style: { right: '-40px' }
  148. },
  149. { label: '分担率 ', value: 0, util: '%' },
  150. { label: '平均乘距', value: 1400, util: 'km' }
  151. ],
  152. contrlSelect: {
  153. title: '场站分布',
  154. icon: '51',
  155. option: [
  156. {
  157. label: '线路客流量',
  158. value: 1,
  159. icon: ''
  160. },
  161. {
  162. label: '客流热力图',
  163. value: 2,
  164. icon: ''
  165. }
  166. ],
  167. checked: [ 1, 2, 3 ]
  168. }
  169. },
  170. {
  171. name: '维保动态',
  172. key: 'maintenanceDynamics',
  173. component: markRaw(maintenanceDynamics),
  174. count: [
  175. { label: '维保场', value: 10, util: '个' },
  176. { label: '运维驿站', value: 14, util: '个' },
  177. { label: '已保养', value: 8, util: '辆' },
  178. { label: '已维修 ', value: 0, util: '辆' }
  179. ],
  180. contrlSelect: {
  181. title: '线路类型',
  182. icon: '51',
  183. option: [
  184. {
  185. label: '维保场',
  186. value: 'maintenanceStation',
  187. icon: '43'
  188. },
  189. {
  190. label: '运维驿站',
  191. value: 'operationStation',
  192. icon: '43'
  193. }
  194. ],
  195. checked: [ 'maintenanceStation', 'operationStation' ]
  196. }
  197. },
  198. {
  199. name: '设施管理',
  200. key: 'facilityManagement',
  201. component: markRaw(facilityManagement),
  202. count: [
  203. { label: '车辆', value: 2000, util: '辆' },
  204. { label: '电子站牌', value: 14, util: '座' },
  205. { label: '洗车机', value: 8, util: '座' },
  206. { label: '充电桩 ', value: 0, util: '台' },
  207. { label: '车载部件', value: 1400, util: '个' }
  208. ],
  209. contrlSelect: {
  210. title: '维修点分布',
  211. icon: '51',
  212. option: [
  213. {
  214. label: '车辆',
  215. value: 'carInfo',
  216. icon: '39'
  217. },
  218. {
  219. label: '电子站牌',
  220. value: 'electronicStationSign',
  221. icon: '43'
  222. },
  223. {
  224. label: '洗衣机',
  225. value: 'carWasher',
  226. icon: '43'
  227. },
  228. {
  229. label: '充电桩',
  230. value: 'powerCharge',
  231. icon: '42'
  232. },
  233. {
  234. label: '车载部件',
  235. value: 'vehicleMountedComponents',
  236. icon: '43'
  237. }
  238. ],
  239. checked: [ 'carInfo', 'electronicStationSign', 'carWasher', 'powerCharge', 'vehicleMountedComponents' ]
  240. }
  241. },
  242. {
  243. name: '场站管理',
  244. key: 'stationManagement',
  245. component: markRaw(stationManagement),
  246. count: [
  247. { label: '场站', value: 2000, util: '个' },
  248. {
  249. label: '总面积', value: 14, util: '万平方米', style: { right: '-50px' }
  250. },
  251. { label: '发车线路', value: 8, util: '条' },
  252. { label: '入场车辆 ', value: 0, util: '辆' },
  253. { label: '静态停车', value: 1400, util: '辆' },
  254. { label: '充电桩', value: 8, util: '辆' },
  255. { label: '充电 ', value: 0, util: '辆' },
  256. { label: '维保', value: 1400, util: '辆' }
  257. ],
  258. contrlSelect: {
  259. title: '场站分布',
  260. icon: '51',
  261. option: [
  262. {
  263. label: '枢纽站',
  264. value: 'hubStation',
  265. icon: '43'
  266. },
  267. {
  268. label: '首末站',
  269. value: 'startEndStation',
  270. icon: '43'
  271. },
  272. {
  273. label: '停保场',
  274. value: 'parkingLot',
  275. icon: '43'
  276. },
  277. {
  278. label: '维保站',
  279. value: 'maintenanceStation',
  280. icon: '43'
  281. }
  282. ],
  283. checked: [ 'hubStation', 'startEndStation', 'parkingLot', 'maintenanceStation' ]
  284. }
  285. },
  286. {
  287. name: '线路分析',
  288. key: 'lineAnalysis',
  289. component: markRaw(lineAnalysis),
  290. count: [
  291. { label: '线路', value: 2000, util: '条' },
  292. { label: '站点', value: 14, util: '个' },
  293. {
  294. label: '线路长度', value: 8, util: '公里', style: { right: '-18px' }
  295. },
  296. {
  297. label: '线路密度 ', value: 0, util: 'km/km³', style: { right: '-35px' }
  298. },
  299. { label: '线路重复率', value: 1400, util: '%' },
  300. { label: '线路覆盖率', value: 8, util: '%' }
  301. ],
  302. contrlSelect: {
  303. title: '线路类型',
  304. icon: '51',
  305. option: [
  306. {
  307. label: '常规',
  308. value: 1,
  309. icon: ''
  310. },
  311. {
  312. label: '快线',
  313. value: 2,
  314. icon: ''
  315. },
  316. {
  317. label: '特色',
  318. value: 3,
  319. icon: ''
  320. }
  321. ],
  322. checked: [ 1, 2, 3 ]
  323. }
  324. }
  325. ]
  326. const active = ref(0)
  327. const currentComponent = ref(menus[active.value].component)
  328. const weather = computed(() => store.weather)
  329. const warningMsg = ref({
  330. value: '这里是预警提示信息这里是预警提示信息这里是预警提示信息这里是预警提示信息这里是预是预警提示信息这里',
  331. time: ' 2023-01-01 12:00:00',
  332. btns: [
  333. {
  334. name: '忽略',
  335. event: '',
  336. type: 'default'
  337. },
  338. {
  339. name: '立即处理',
  340. event: '',
  341. type: 'error'
  342. }
  343. ]
  344. })
  345. function changMenu(_id: number) {
  346. active.value = _id
  347. currentComponent.value = menus[_id].component
  348. }
  349. async function getBusTotal() {
  350. const res = await homeService.getBusTotal()
  351. menus[0].count[0].value = res.busNum
  352. menus[0].count[1].value = res.lineNum
  353. menus[0].count[2].value = res.stationNum
  354. menus[0].count[3].value = res.midwayStationNum
  355. menus[0].count[4].value = res.classesNum
  356. menus[0].count[5].value = res.totalMileage
  357. menus[0].count[6].value = res.admissionRate
  358. }
  359. getBusTotal()
  360. async function getBusLineStatistics() {
  361. const res = await cehicleOperationService.getBusLineStatistics()
  362. menus[1].count[0].value = res.passengerFlow
  363. menus[1].count[1].value = res.planClasses
  364. menus[1].count[2].value = res.setOutClasses
  365. menus[1].count[3].value = res.collapseClasses
  366. menus[1].count[4].value = res.planMileage
  367. menus[1].count[5].value = res.currentMileage
  368. menus[1].count[6].value = res.unloadedRatio
  369. }
  370. getBusLineStatistics()
  371. async function getTrafficAnalysis() {
  372. const res = await passengerFlowService.getTrafficAnalysis()
  373. menus[2].count[0].value = res.trafficVolume
  374. menus[2].count[1].value = res.fullLoad
  375. menus[2].count[2].value = res.freeTransfer
  376. menus[2].count[3].value = res.shareRate
  377. menus[2].count[4].value = res.avgRidingDistance
  378. console.log('getTrafficAnalysis')
  379. }
  380. getTrafficAnalysis()
  381. async function getMaintenanceInfo() {
  382. const res = await maintenanceDynamicsService.getMaintenanceInfo()
  383. menus[3].count[0].value = res.maintenanceSite
  384. menus[3].count[1].value = res.maintenanceStation
  385. menus[3].count[2].value = res.maintained
  386. menus[3].count[3].value = res.repaired
  387. }
  388. getMaintenanceInfo()
  389. async function getFacilityStatistics() {
  390. const res = await facilityManagementService.getFacilityStatistics()
  391. let vehicleNumTotal = 0
  392. let stationNumTotal = 0
  393. let carWasherNumTotal = 0
  394. let chargingStationNumTotal = 0
  395. let vehicleComponentsNumTotal = 0
  396. for (let i = 0; i < res.length; i++) {
  397. const item = res[i]
  398. vehicleNumTotal += +item.vehicleNum
  399. stationNumTotal += +item.stationNum
  400. carWasherNumTotal += +item.carWasherNum
  401. chargingStationNumTotal += +item.chargingStationNum
  402. vehicleComponentsNumTotal += +item.vehicleComponentsNum
  403. }
  404. menus[4].count[0].value = vehicleNumTotal
  405. menus[4].count[1].value = stationNumTotal
  406. menus[4].count[2].value = carWasherNumTotal
  407. menus[4].count[3].value = chargingStationNumTotal
  408. menus[4].count[4].value = vehicleComponentsNumTotal
  409. }
  410. getFacilityStatistics()
  411. async function getStationStatistics() {
  412. const res = await stationManagementService.getStationStatistics()
  413. menus[5].count[0].value = res.stationNum
  414. menus[5].count[1].value = res.totalArea
  415. menus[5].count[2].value = res.lineNum
  416. menus[5].count[3].value = res.vehicleNum
  417. menus[5].count[4].value = res.parkNum
  418. menus[5].count[5].value = res.chargingNum
  419. menus[5].count[6].value = res.chargeVehicle
  420. menus[5].count[7].value = res.maintenanceNum
  421. }
  422. getStationStatistics()
  423. async function getAnalysisLineStatistics() {
  424. const res = await lineAnalysisService.getAnalysisLineStatistics()
  425. menus[6].count[0].value = res.lineNum
  426. menus[6].count[1].value = res.stationNum
  427. menus[6].count[2].value = res.lineLength
  428. menus[6].count[3].value = res.lineDensity
  429. menus[6].count[4].value = res.lineRepetition
  430. menus[6].count[5].value = res.lineCoverageRate
  431. }
  432. getAnalysisLineStatistics()
  433. </script>
  434. <template>
  435. <div class="home">
  436. <div class="home-top">
  437. <img src="../../../assets/img/6.svg">
  438. <div class="home-top-user">
  439. <div>安全运营<span>100</span>天</div>
  440. <div v-if="weather">
  441. <img :src="weather.icon">
  442. {{ weather.weather }}
  443. <span>{{ weather.temperature }}℃</span>
  444. </div>
  445. <div>
  446. <img src="../../../assets/img/10.svg">
  447. 你的名称
  448. </div>
  449. </div>
  450. </div>
  451. <div class="home-content">
  452. <div class="home-content-top">
  453. <div class="home-content-top-menus">
  454. <template
  455. v-for="(item, index) in menus"
  456. :key="index"
  457. >
  458. <div
  459. :class="{ active: index === active }"
  460. @click="changMenu(index)"
  461. >
  462. {{ item.name }}
  463. </div>
  464. </template>
  465. </div>
  466. </div>
  467. <div class="home-content-left" />
  468. <div class="home-content-right" />
  469. <div class="home-content-center">
  470. <Map :Item="(menus[active] as any)" />
  471. </div>
  472. <div class="home-content-left-img" />
  473. <div class="home-content-right-img" />
  474. <div class="home-content-center-tooltip">
  475. <Icon
  476. name="37"
  477. :size="37"
  478. />
  479. <div>{{ warningMsg.value }}</div>
  480. <div>{{ warningMsg.time }}</div>
  481. <div>
  482. <template
  483. v-for="(item, index) in warningMsg.btns"
  484. :key="index"
  485. >
  486. <n-button
  487. round
  488. :type="item.type"
  489. >
  490. {{ item.name }}
  491. </n-button>
  492. </template>
  493. </div>
  494. </div>
  495. <div class="home-content-bottom-bottom">
  496. <template
  497. v-for="(item, index) in menus[active].count"
  498. :key="index"
  499. >
  500. <div>
  501. <div>{{ item.label }}</div>
  502. <div>
  503. <span>{{ item.value }}</span>
  504. <span :style="item.style">{{ item.util }}</span>
  505. </div>
  506. </div>
  507. </template>
  508. </div>
  509. <component :is="currentComponent" />
  510. <ChangeLine v-show="active===1" />
  511. </div>
  512. <div class="home-bottom">
  513. 雅安市公共交通集团有限公司
  514. </div>
  515. </div>
  516. </template>
  517. <style lang="scss" scoped>
  518. .home {
  519. height: 1456px;
  520. width: 4784px;
  521. background: #030E25;
  522. &-top {
  523. height: 160px;
  524. background: url(../../../assets//img/2.svg) no-repeat top center;
  525. background-size: cover;
  526. text-align: center;
  527. position: relative;
  528. &>img {
  529. width: 900px;
  530. height: 130px;
  531. }
  532. &-user {
  533. position: absolute;
  534. display: flex;
  535. align-items: center;
  536. right: 30px;
  537. top: 30px;
  538. &>div {
  539. margin: 0 25px;
  540. font-size: 24px;
  541. &:first-child {
  542. font-weight: 400;
  543. color: #80FFFF;
  544. span {
  545. color: white;
  546. font-weight: 700;
  547. font-size: 50px;
  548. margin: 0 5px;
  549. }
  550. }
  551. &:last-child {
  552. color: white;
  553. display: flex;
  554. align-items: center;
  555. margin-right: 0;
  556. img {
  557. border-radius: 50%;
  558. width: 80px;
  559. height: 80px;
  560. overflow: hidden;
  561. margin-right: 15px;
  562. }
  563. }
  564. &:nth-child(2) {
  565. display: flex;
  566. align-items: flex-end;
  567. color: white;
  568. img {
  569. width: 56px;
  570. height: 56px;
  571. margin-right: 10px;
  572. }
  573. span {
  574. color: #80FFFF;
  575. margin-left: 10px;
  576. }
  577. }
  578. }
  579. }
  580. }
  581. &-content {
  582. height: calc(1456px - 160px - 72px);
  583. position: relative;
  584. &-top {
  585. position: absolute;
  586. left: 50%;
  587. top: -30px;
  588. transform: translate(-50%, 0);
  589. height: 185px;
  590. width: calc(100% - 1370px - 1370px);
  591. background: url(../../../assets//img/5.svg) no-repeat center;
  592. background-size: cover;
  593. z-index: 2;
  594. &-menus {
  595. display: flex;
  596. align-items: center;
  597. justify-content: space-evenly;
  598. padding: 0 410px;
  599. &>div {
  600. text-shadow: 1px 1px 10px rgba(0, 0, 0, 0.698);
  601. font-family: Arial Normal;
  602. font-size: 24px;
  603. text-align: center;
  604. letter-spacing: 0px;
  605. color: #D7D7D7;
  606. cursor: pointer;
  607. height: 111px;
  608. width: 175px;
  609. line-height: 111px;
  610. }
  611. .active {
  612. color: white;
  613. background: url(../../../assets/img/7.svg) no-repeat center;
  614. background-size: cover;
  615. }
  616. }
  617. }
  618. &-left,
  619. &-right {
  620. position: absolute;
  621. height: 110%;
  622. width: 40px;
  623. top: -117px;
  624. }
  625. &-left {
  626. left: 7px;
  627. background: url(../../../assets/img/8.svg) no-repeat left top;
  628. background-size: cover;
  629. &-img {
  630. background: url(../../../assets/img/35.png) no-repeat left top;
  631. background-size: cover;
  632. width: 175px;
  633. position: absolute;
  634. left: 1396px;
  635. top: 0;
  636. height: 103%;
  637. z-index: 2;
  638. background-position: -113px 0;
  639. }
  640. }
  641. &-right {
  642. right: 7px;
  643. background: url(../../../assets/img/9.svg) no-repeat left top;
  644. background-size: cover;
  645. &-img {
  646. background: url(../../../assets/img/34.png) no-repeat right top;
  647. background-size: cover;
  648. width: 175px;
  649. position: absolute;
  650. right: 1394px;
  651. top: 0;
  652. height: 103%;
  653. z-index: 2;
  654. background-position: -203px 0;
  655. }
  656. }
  657. &-center {
  658. position: absolute;
  659. left: 50%;
  660. top: 0;
  661. width: 1990px;
  662. height: 100%;
  663. z-index: 1;
  664. margin: 0 auto;
  665. transform: translate(-50%, 0);
  666. &-tooltip {
  667. position: absolute;
  668. top: 90px;
  669. border: solid 1px red;
  670. border-radius: 30px;
  671. z-index: 3;
  672. left: 50%;
  673. transform: translate(-50%, 0);
  674. display: flex;
  675. align-items: center;
  676. padding: 8px 10px;
  677. color: #E73D41;
  678. font-size: 23px;
  679. animation: flicker 0.5s infinite alternate;
  680. background: #e73d4048;
  681. &>svg {
  682. margin-right: 10px;
  683. margin-left: 10px;
  684. }
  685. &>div:nth-child(2) {
  686. max-width: 938px;
  687. min-width: 100px;
  688. overflow: hidden;
  689. text-overflow: ellipsis;
  690. white-space: nowrap;
  691. }
  692. &>div:nth-child(3) {
  693. margin: 0 60px;
  694. }
  695. & button:last-child {
  696. margin-left: 10px;
  697. }
  698. }
  699. }
  700. &-bottom-bottom {
  701. position: absolute;
  702. display: flex;
  703. align-items: center;
  704. left: 50%;
  705. z-index: 3;
  706. bottom: 45px;
  707. transform: translate(-50%, 0);
  708. &>div {
  709. width: 158px;
  710. height: 138px;
  711. background: url(../../../assets/img/38.svg) no-repeat;
  712. margin: 0 10px;
  713. text-align: center;
  714. text-shadow: rgba(0, 255, 255, 0.698) 1px 1px 10px;
  715. overflow-wrap: break-word;
  716. background-size: cover;
  717. padding-top: 10px ;
  718. &>div:first-child {
  719. font-size: 20px;
  720. color: rgb(128, 255, 255);
  721. }
  722. &>div:last-child {
  723. position: relative;
  724. &>span{
  725. color: rgb(255, 255, 255);
  726. font-family: "Impact Normal", Impact, sans-serif;
  727. }
  728. &>span:first-child {
  729. padding-top: 10px;
  730. font-size: 40px;
  731. }
  732. &>span:last-child{
  733. font-size: 20px;
  734. position: absolute;
  735. top: 16px;
  736. right: 0;
  737. }
  738. }
  739. }
  740. }
  741. .drag-container{
  742. left: 1581px;
  743. top: 318px;
  744. }
  745. }
  746. &-bottom {
  747. height: 72px;
  748. background: url(../../../assets/img/3.svg) no-repeat center;
  749. background-size: cover;
  750. text-align: center;
  751. line-height: 72px;
  752. color: white;
  753. font-size: 20px;
  754. letter-spacing: 20px;
  755. text-shadow: 1px 1px 5px rgba(0, 255, 255, 0.6);
  756. }
  757. }
  758. @keyframes flicker {
  759. 0% {
  760. opacity: 0.8;
  761. }
  762. 100% {
  763. opacity: 0.3;
  764. }
  765. }
  766. </style>