index.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916
  1. <template>
  2. <view class="warning-center">
  3. <!-- 顶部导航栏 -->
  4. <custom-card>
  5. <block slot="backText">预警中心</block>
  6. </custom-card>
  7. <!-- 主要内容 -->
  8. <view class="content">
  9. <!-- 宣传语区域 -->
  10. <view class="banner">
  11. <view class="banner-text">
  12. <text class="banner-title">天灾虫害,预警在先</text>
  13. <text class="banner-subtitle">全天候监测,风险早知晓</text>
  14. </view>
  15. <view class="warning-icon">
  16. <view class="icon-triangle">
  17. <image :src="exclamation" class="icon-image" />
  18. </view>
  19. </view>
  20. </view>
  21. <!-- 日期选择器 -->
  22. <view class="date-picker">
  23. <view class="date-inputs" @click="showDatePickerHandle()">
  24. <text class="date-label">{{ startTime }}</text>
  25. <text class="date-separator">-</text>
  26. <text class="date-label">{{ endTime }}</text>
  27. <u-icon name="calendar" size="28rpx" color="#999" />
  28. </view>
  29. <view class="date-icons">
  30. <image :src="warning" class="icon-image" />
  31. </view>
  32. </view>
  33. <!-- 标签导航 -->
  34. <view class="tab-nav">
  35. <view
  36. v-for="(tab, index) in tabs"
  37. :key="index"
  38. class="tab-item"
  39. :class="{ active: activeTab === index }"
  40. @click="activeTabHandler(index)"
  41. >
  42. {{ tab }}
  43. </view>
  44. </view>
  45. <!-- 预警列表 -->
  46. <scroll-view
  47. v-if="activeTab == 0"
  48. class="warning-list"
  49. scroll-y
  50. :scroll-top="listScrollTop"
  51. scroll-with-animation
  52. @scrolltolower="loadMore"
  53. @scrolltoupper="refresh"
  54. >
  55. <view
  56. v-for="(warning, index) in warningList"
  57. :key="index"
  58. class="warning-item"
  59. @click="popupShowHandler(warning)"
  60. >
  61. <view class="warning-header">
  62. <view class="warning-type">
  63. <view
  64. class="type-icon"
  65. :class="warning.status == '0' ? 'type-blue' : 'type-gray'"
  66. >
  67. <image :src="weather" class="icon-image" />
  68. </view>
  69. <text class="type-text">{{ warning.warning_title }}</text>
  70. <text class="device-type">{{ warning.device_type }}</text>
  71. </view>
  72. <view
  73. class="warning-level"
  74. :class="
  75. warning.level == '0'
  76. ? warning.status != '0'
  77. ? 'level-normal-gray'
  78. : 'level-normal'
  79. : warning.level == '1'
  80. ? warning.status != '0'
  81. ? 'level-important-gray'
  82. : 'level-important'
  83. : warning.status != '0'
  84. ? 'level-urgent-gray'
  85. : 'level-urgent'
  86. "
  87. >
  88. </view>
  89. </view>
  90. <view class="warning-content">
  91. {{ warning.warning_content }}
  92. </view>
  93. <view class="warning-footer">
  94. <text class="warning-time">{{ formatTime(warning.upl_time) }}</text>
  95. <view class="warning-location">
  96. <u-icon name="location" size="20rpx" color="#999" />
  97. </view>
  98. </view>
  99. <view class="location-text">
  100. <u-icon name="map" size="28"></u-icon>
  101. <text style="margin-left: 10rpx">{{ warning.address || '-' }}</text>
  102. </view>
  103. </view>
  104. <!-- 加载更多提示 -->
  105. <view class="loading-more">
  106. <text v-if="loading">加载中...</text>
  107. <text v-else-if="finished">没有更多数据了</text>
  108. <text v-else>上拉加载更多</text>
  109. </view>
  110. </scroll-view>
  111. <scroll-view
  112. v-if="activeTab == 1"
  113. class="warning-list"
  114. scroll-y
  115. :scroll-top="listScrollTop"
  116. scroll-with-animation
  117. @scrolltolower="loadMore"
  118. @scrolltoupper="refresh"
  119. >
  120. <view
  121. v-for="(warning, index) in manualWarningList"
  122. :key="index"
  123. class="warning-item"
  124. @click="popupManualShowHandler(warning)"
  125. >
  126. <view class="warning-content">
  127. {{ warning.conf }}
  128. </view>
  129. <view class="warning-footer">
  130. <text class="warning-time">{{
  131. formatTime(warning.create_time)
  132. }}</text>
  133. <view class="warning-location">
  134. <u-icon name="location" size="20rpx" color="#999" />
  135. </view>
  136. </view>
  137. </view>
  138. <!-- 加载更多提示 -->
  139. <view class="loading-more">
  140. <text v-if="loading">加载中...</text>
  141. <text v-else-if="finished">没有更多数据了</text>
  142. <text v-else>上拉加载更多</text>
  143. </view>
  144. </scroll-view>
  145. <!-- 回到顶部 -->
  146. <view class="back-to-top" @click="scrollToTop">
  147. <u-icon name="arrow-up" size="28rpx" color="#999" />
  148. </view>
  149. </view>
  150. <u-calendar
  151. v-model="showDatePicker"
  152. :mode="mode"
  153. @change="changeCalendar"
  154. ></u-calendar>
  155. <u-popup v-model="popupShow" mode="bottom" height="50%" border-radius="20">
  156. <view class="popup-container">
  157. <view
  158. class="popup-icon"
  159. :class="
  160. current.level == '0'
  161. ? current.status != '0'
  162. ? 'popup-level-normal-gray'
  163. : 'popup-level-normal'
  164. : current.level == '1'
  165. ? current.status != '0'
  166. ? 'popup-level-important-gray'
  167. : 'popup-level-important'
  168. : current.status != '0'
  169. ? 'popup-level-urgent-gray'
  170. : 'popup-level-urgent'
  171. "
  172. >
  173. </view>
  174. <view class="popup-header">{{ current.warning_title }}</view>
  175. <view class="popup-type">
  176. <text class="type-text">{{ current.device_type }}</text>
  177. </view>
  178. <view class="popup-content">{{ current.warning_content }}</view>
  179. <view class="popup-time">{{ formatTime(current.upl_time) }}</view>
  180. <view class="popup-text">
  181. <u-icon name="map" size="28"></u-icon>
  182. <text style="margin-left: 10rpx">{{ warning.address || '-' }}</text>
  183. </view>
  184. </view>
  185. </u-popup>
  186. <u-popup
  187. v-model="popupManualShow"
  188. mode="bottom"
  189. height="50%"
  190. border-radius="20"
  191. >
  192. <view class="popup-container" style="margin-top: 40rpx">
  193. <view class="popup-content">{{ currentManual.conf }}</view>
  194. <view class="popup-time">{{
  195. formatTime(currentManual.create_time)
  196. }}</view>
  197. </view>
  198. </u-popup>
  199. </view>
  200. </template>
  201. <script>
  202. import exclamation from './assets/exclamation.png';
  203. import warning from './assets/warning.png';
  204. import pest from './assets/pest.png';
  205. import weather from './assets/weather.png';
  206. import offline from './assets/offline.png';
  207. export default {
  208. data() {
  209. return {
  210. current: {},
  211. currentManual: {},
  212. popupShow: false,
  213. popupManualShow: false,
  214. exclamation,
  215. warning,
  216. pest,
  217. weather,
  218. offline,
  219. showDatePicker: false,
  220. mode: 'range',
  221. activeTab: 0,
  222. listScrollTop: 0,
  223. tabs: ['环境监测', '手动预警'],
  224. warningList: [],
  225. manualWarningList: [],
  226. page_size: 10,
  227. page: 1,
  228. // 获取7天前的日期
  229. startTime: this.getSevenDaysAgo() || '开始日期',
  230. endTime: this.getCurrentDate() || '结束日期',
  231. deviceId: '',
  232. device_type_id: '',
  233. total: 0,
  234. loading: false,
  235. finished: false,
  236. refreshing: false,
  237. };
  238. },
  239. onLoad() {
  240. this.getWarningList();
  241. },
  242. methods: {
  243. activeTabHandler(index) {
  244. this.activeTab = index;
  245. this.page = 1;
  246. if (index == 0) {
  247. this.getWarningList();
  248. } else if (index == 1) {
  249. this.getWarningManualList();
  250. }
  251. },
  252. popupManualShowHandler(warning) {
  253. this.currentManual = warning;
  254. this.popupManualShow = true;
  255. },
  256. popupShowHandler(warning) {
  257. this.current = warning;
  258. const params = {
  259. record_ids: warning.id,
  260. };
  261. this.readHandler(params);
  262. this.popupShow = true;
  263. },
  264. changeCalendar(e) {
  265. this.startTime = e.startDate;
  266. this.endTime = e.endDate;
  267. // 重置分页参数
  268. this.page = 1;
  269. this.loading = false;
  270. this.finished = false;
  271. if (this.activeTab == 0) {
  272. this.getWarningList();
  273. } else if (this.activeTab == 1) {
  274. this.getWarningManualList();
  275. }
  276. },
  277. // 加载更多
  278. loadMore() {
  279. if (this.finished) return;
  280. if (this.activeTab == 0) {
  281. this.getWarningList();
  282. } else if (this.activeTab == 1) {
  283. this.getWarningManualList();
  284. }
  285. },
  286. // 下拉刷新
  287. refresh() {
  288. if (this.loading) return;
  289. // 重置分页参数
  290. this.page = 1;
  291. this.loading = false;
  292. this.finished = false;
  293. this.refreshing = true;
  294. if (this.activeTab == 0) {
  295. this.getWarningList();
  296. } else if (this.activeTab == 1) {
  297. this.getWarningManualList();
  298. }
  299. },
  300. // 已读
  301. async readHandler(params) {
  302. await this.$myRequest({
  303. url: '/api/api_gateway?method=device.env_sec_alert.update_env_sec_alert_record',
  304. method: 'POST',
  305. data: params,
  306. });
  307. this.page = 1;
  308. if (this.activeTab == 0) {
  309. this.getWarningList();
  310. }
  311. },
  312. formatTime(time) {
  313. if (!time) {
  314. return '';
  315. }
  316. const date = new Date(time * 1000);
  317. const year = date.getFullYear();
  318. const month = String(date.getMonth() + 1).padStart(2, '0');
  319. const day = String(date.getDate()).padStart(2, '0');
  320. const hour = String(date.getHours()).padStart(2, '0');
  321. const minute = String(date.getMinutes()).padStart(2, '0');
  322. const second = String(date.getSeconds()).padStart(2, '0');
  323. return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
  324. },
  325. // 获取7天前的日期
  326. getSevenDaysAgo() {
  327. const today = new Date();
  328. const sevenDaysAgo = new Date(today);
  329. sevenDaysAgo.setDate(today.getDate() - 7);
  330. const year = sevenDaysAgo.getFullYear();
  331. const month = String(sevenDaysAgo.getMonth() + 1).padStart(2, '0');
  332. const day = String(sevenDaysAgo.getDate()).padStart(2, '0');
  333. return `${year}-${month}-${day}`;
  334. },
  335. // 获取当前日期
  336. getCurrentDate() {
  337. const today = new Date();
  338. const year = today.getFullYear();
  339. const month = String(today.getMonth() + 1).padStart(2, '0');
  340. const day = String(today.getDate()).padStart(2, '0');
  341. return `${year}-${month}-${day}`;
  342. },
  343. showDatePickerHandle() {
  344. this.showDatePicker = true;
  345. },
  346. // 把日期转成秒数
  347. dateToTimestamp(date) {
  348. return Math.floor(new Date(date).getTime() / 1000);
  349. },
  350. async getWarningManualList() {
  351. if (this.loading) return;
  352. this.loading = true;
  353. const start = this.dateToTimestamp(this.startTime + ' 00:00:00');
  354. const end = this.dateToTimestamp(this.endTime + ' 23:59:59');
  355. const params = {
  356. start,
  357. end,
  358. page: this.page,
  359. page_size: this.page_size,
  360. device_id: this.deviceId,
  361. device_type_id: this.device_type_id,
  362. };
  363. try {
  364. const res = await this.$myRequest({
  365. url: '/api/api_gateway?method=device.env_sec_alert.get_manual_env_sec_alert_record',
  366. method: 'POST',
  367. data: params,
  368. });
  369. const resData = res?.data || [];
  370. const list = resData || [];
  371. if (this.page === 1) {
  372. this.manualWarningList = list;
  373. } else {
  374. this.manualWarningList = [...this.manualWarningList, ...list];
  375. }
  376. this.total = res?.total || 0;
  377. this.loading = false;
  378. // 计算是否还有更多数据
  379. if (this.manualWarningList.length >= this.total) {
  380. this.finished = true;
  381. } else {
  382. this.page++;
  383. }
  384. // 结束刷新状态
  385. if (this.refreshing) {
  386. this.refreshing = false;
  387. }
  388. } catch (error) {
  389. console.error('获取预警列表失败:', error);
  390. this.loading = false;
  391. if (this.refreshing) {
  392. this.refreshing = false;
  393. }
  394. }
  395. },
  396. async getWarningList() {
  397. if (this.loading) return;
  398. this.loading = true;
  399. const start = this.dateToTimestamp(this.startTime + ' 00:00:00');
  400. const end = this.dateToTimestamp(this.endTime + ' 23:59:59');
  401. const params = {
  402. start,
  403. end,
  404. page: this.page,
  405. page_size: this.page_size,
  406. device_id: this.deviceId,
  407. device_type_id: this.device_type_id,
  408. };
  409. try {
  410. const res = await this.$myRequest({
  411. url: '/api/api_gateway?method=device.env_sec_alert.get_env_sec_alert',
  412. method: 'POST',
  413. data: params,
  414. });
  415. const resData = res?.data || [];
  416. const list = resData || [];
  417. if (this.page === 1) {
  418. this.warningList = list;
  419. } else {
  420. this.warningList = [...this.warningList, ...list];
  421. }
  422. this.total = res?.total_num || 0;
  423. this.loading = false;
  424. // 计算是否还有更多数据
  425. if (this.warningList.length >= this.total) {
  426. this.finished = true;
  427. } else {
  428. this.page++;
  429. }
  430. // 结束刷新状态
  431. if (this.refreshing) {
  432. this.refreshing = false;
  433. }
  434. } catch (error) {
  435. console.error('获取预警列表失败:', error);
  436. this.loading = false;
  437. if (this.refreshing) {
  438. this.refreshing = false;
  439. }
  440. }
  441. },
  442. // 回到顶部
  443. scrollToTop() {
  444. this.listScrollTop = 0;
  445. },
  446. },
  447. };
  448. </script>
  449. <style scoped lang="scss">
  450. .warning-center {
  451. min-height: 100vh;
  452. font-family: 'Source Han Sans CN';
  453. background: linear-gradient(0deg, #f5f6fa 79.64%, #ffeeec 99.35%);
  454. }
  455. ::v-deep .u-calendar__action {
  456. display: flex;
  457. }
  458. ::v-deep .u-calendar__action__icon {
  459. width: 40rpx;
  460. }
  461. ::v-deep .u-calendar__action__text {
  462. width: calc(100% - 160rpx);
  463. text-align: center;
  464. }
  465. .content {
  466. padding: 0 32rpx;
  467. }
  468. /* 宣传语区域 */
  469. .banner {
  470. display: flex;
  471. align-items: center;
  472. justify-content: space-between;
  473. margin: 32rpx 0;
  474. margin-bottom: 0rpx;
  475. padding: 24rpx;
  476. .banner-text {
  477. flex: 1;
  478. .banner-title {
  479. font-style: italic;
  480. display: block;
  481. color: #303133;
  482. font-family: 'Source Han Sans CN VF';
  483. font-size: 40rpx;
  484. font-weight: 700;
  485. margin-bottom: 8rpx;
  486. }
  487. .banner-subtitle {
  488. display: block;
  489. font-size: 24rpx;
  490. color: #666666;
  491. }
  492. }
  493. .warning-icon {
  494. .icon-triangle {
  495. width: 130rpx;
  496. height: 130rpx;
  497. position: relative;
  498. .icon-image {
  499. width: 100%;
  500. height: 100%;
  501. }
  502. }
  503. }
  504. }
  505. .popup-container {
  506. position: relative;
  507. .popup-icon {
  508. position: absolute;
  509. top: 0;
  510. right: 0;
  511. margin-left: 12rpx;
  512. width: 112rpx;
  513. height: 48rpx;
  514. background: url('./assets/normal-gray.png');
  515. background-repeat: no-repeat;
  516. background-size: 100%;
  517. &.popup-level-normal {
  518. background: url('./assets/normal.png');
  519. background-repeat: no-repeat;
  520. background-size: 100%;
  521. }
  522. &.popup-level-normal-gray {
  523. background: url('./assets/normal-gray.png');
  524. background-repeat: no-repeat;
  525. background-size: 100%;
  526. }
  527. &.popup-level-important-gray {
  528. background: url('./assets/important-gray.png');
  529. background-repeat: no-repeat;
  530. background-size: 100%;
  531. }
  532. &.popup-level-important {
  533. background: url('./assets/important.png');
  534. background-repeat: no-repeat;
  535. background-size: 100%;
  536. }
  537. &.popup-level-urgent-gray {
  538. background: url('./assets/urgent-gray.png');
  539. background-repeat: no-repeat;
  540. background-size: 100%;
  541. }
  542. &.popup-level-urgent {
  543. background: url('./assets/urgent.png');
  544. background-repeat: no-repeat;
  545. background-size: 100%;
  546. }
  547. }
  548. }
  549. .popup-header {
  550. padding: 20rpx 32rpx;
  551. width: 100%;
  552. text-align: left;
  553. color: #303133;
  554. font-family: 'Source Han Sans CN VF';
  555. font-size: 32rx;
  556. font-weight: 700;
  557. }
  558. .popup-type {
  559. border-radius: 32rpx;
  560. margin-left: 32rpx;
  561. display: inline-block;
  562. border: 2rpx solid #e4e7ed;
  563. padding: 2rpx 12rpx;
  564. color: #666666;
  565. font-family: 'Source Han Sans CN VF';
  566. font-size: 24rpx;
  567. font-weight: 400;
  568. margin-bottom: 24rpx;
  569. }
  570. .popup-content {
  571. padding: 0 32rpx;
  572. line-height: 50rpx;
  573. }
  574. .popup-time {
  575. padding: 0 32rpx;
  576. margin-top: 36rpx;
  577. color: #999999;
  578. font-size: 24rpx;
  579. text-align: left;
  580. color: #bdbdbd;
  581. font-family: 'Source Han Sans CN VF';
  582. font-style: normal;
  583. font-weight: 400;
  584. }
  585. .popup-location {
  586. font-size: 24rpx;
  587. margin-top: 16rpx;
  588. padding-top: 16rpx;
  589. font-family: 'Source Han Sans CN VF';
  590. color: #999999;
  591. display: flex;
  592. align-items: center;
  593. }
  594. .popup-text {
  595. padding: 0 32rpx;
  596. font-size: 24rpx;
  597. margin-top: 16rpx;
  598. padding-top: 16rpx;
  599. font-family: 'Source Han Sans CN VF';
  600. color: #999999;
  601. display: flex;
  602. align-items: center;
  603. }
  604. /* 日期选择器 */
  605. .date-picker {
  606. display: flex;
  607. align-items: center;
  608. justify-content: space-between;
  609. margin-bottom: 32rpx;
  610. .date-inputs {
  611. display: flex;
  612. align-items: center;
  613. background: #ffffff;
  614. border-radius: 48rpx;
  615. padding: 14rpx;
  616. box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
  617. .date-label {
  618. width: 250rpx;
  619. font-size: 26rpx;
  620. color: #999999;
  621. text-align: center;
  622. }
  623. .date-separator {
  624. margin: 0 24rpx;
  625. font-size: 26rpx;
  626. color: #999999;
  627. }
  628. }
  629. .date-icons {
  630. display: flex;
  631. align-items: center;
  632. justify-content: center;
  633. width: 60rpx;
  634. height: 60rpx;
  635. border-radius: 50%;
  636. background: #ffffff;
  637. .icon-image {
  638. width: 32rpx;
  639. height: 32rpx;
  640. }
  641. }
  642. }
  643. /* 标签导航 */
  644. .tab-nav {
  645. display: flex;
  646. margin-bottom: 24rpx;
  647. border-bottom: 1rpx solid #e5e5e5;
  648. .tab-item {
  649. padding: 20rpx 0;
  650. font-size: 28rpx;
  651. color: #666666;
  652. position: relative;
  653. margin-right: 30rpx;
  654. &.active {
  655. color: #333333;
  656. font-weight: 500;
  657. &::after {
  658. content: '';
  659. position: absolute;
  660. bottom: 0;
  661. left: 50%;
  662. transform: translateX(-50%);
  663. width: 100%;
  664. height: 4rpx;
  665. background: #515153;
  666. border-radius: 2rpx;
  667. }
  668. }
  669. }
  670. }
  671. /* 预警列表 */
  672. .warning-list {
  673. margin-bottom: 100rpx;
  674. height: calc(100vh - 600rpx);
  675. overflow-y: auto;
  676. .warning-item {
  677. position: relative;
  678. padding: 28rpx 24rpx;
  679. margin-bottom: 24rpx;
  680. background: #ffffff;
  681. border-radius: 16rpx;
  682. box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
  683. .warning-header {
  684. display: flex;
  685. align-items: center;
  686. justify-content: space-between;
  687. margin-bottom: 16rpx;
  688. .warning-type {
  689. display: flex;
  690. align-items: center;
  691. flex: 1;
  692. min-width: 0;
  693. .type-icon {
  694. width: 48rpx;
  695. height: 48rpx;
  696. border-radius: 50%;
  697. margin-right: 12rpx;
  698. flex-shrink: 0;
  699. display: flex;
  700. align-items: center;
  701. justify-content: center;
  702. &.type-red {
  703. background: linear-gradient(180deg, #ffa9a5 0%, #ff716a 100%);
  704. }
  705. &.type-blue {
  706. background: linear-gradient(180deg, #83d2ff 0%, #09a5fc 100%);
  707. }
  708. &.type-yellow {
  709. background: linear-gradient(180deg, #fed057 0%, #ffaf40 100%);
  710. }
  711. &.type-gray {
  712. background: #dddfe6;
  713. }
  714. .icon-image {
  715. width: 28rpx;
  716. height: 28rpx;
  717. }
  718. }
  719. .type-text {
  720. font-size: 26rpx;
  721. font-weight: 500;
  722. color: #333333;
  723. margin-right: 12rpx;
  724. flex-shrink: 0;
  725. }
  726. .device-type {
  727. font-size: 22rpx;
  728. color: #515153;
  729. font-family: 'Source Han Sans CN VF';
  730. font-style: normal;
  731. font-weight: 400;
  732. border: 2rpx solid #e4e7ed;
  733. padding: 2rpx 12rpx;
  734. border-radius: 32rpx;
  735. margin-left: 8rpx;
  736. flex-shrink: 0;
  737. }
  738. }
  739. .warning-level {
  740. position: absolute;
  741. top: 0;
  742. right: 0;
  743. margin-left: 12rpx;
  744. width: 112rpx;
  745. height: 48rpx;
  746. background: url('./assets/normal-gray.png');
  747. background-repeat: no-repeat;
  748. background-size: 100%;
  749. &.level-normal {
  750. background: url('./assets/normal.png');
  751. background-repeat: no-repeat;
  752. background-size: 100%;
  753. }
  754. &.level-normal-gray {
  755. background: url('./assets/normal-gray.png');
  756. background-repeat: no-repeat;
  757. background-size: 100%;
  758. }
  759. &.level-important {
  760. background: url('./assets/important.png');
  761. background-repeat: no-repeat;
  762. background-size: 100%;
  763. }
  764. &.level-important-gray {
  765. background: url('./assets/important-gray.png');
  766. background-repeat: no-repeat;
  767. background-size: 100%;
  768. }
  769. &.level-urgent-gray {
  770. background: url('./assets/urgent-gray.png');
  771. background-repeat: no-repeat;
  772. background-size: 100%;
  773. }
  774. &.level-urgent {
  775. background: url('./assets/urgent.png');
  776. background-repeat: no-repeat;
  777. background-size: 100%;
  778. }
  779. }
  780. }
  781. .warning-content {
  782. font-size: 28rpx;
  783. color: #333333;
  784. line-height: 40rpx;
  785. margin-bottom: 20rpx;
  786. //最多显示2行
  787. overflow: hidden;
  788. text-overflow: ellipsis;
  789. display: -webkit-box;
  790. -webkit-line-clamp: 2;
  791. -webkit-box-orient: vertical;
  792. }
  793. .warning-footer {
  794. display: flex;
  795. align-items: center;
  796. justify-content: space-between;
  797. .warning-time {
  798. font-size: 24rpx;
  799. color: #999999;
  800. }
  801. .warning-location {
  802. display: flex;
  803. align-items: center;
  804. }
  805. }
  806. .location-text {
  807. font-size: 24rpx;
  808. margin-top: 16rpx;
  809. padding-top: 16rpx;
  810. border-top: 1rpx solid #f0f0f0;
  811. font-family: 'Source Han Sans CN VF';
  812. color: #999999;
  813. display: flex;
  814. align-items: center;
  815. }
  816. }
  817. }
  818. /* 加载更多提示 */
  819. .loading-more {
  820. text-align: center;
  821. padding: 32rpx 0;
  822. font-size: 24rpx;
  823. color: #999999;
  824. }
  825. /* 回到顶部 */
  826. .back-to-top {
  827. position: fixed;
  828. bottom: 80rpx;
  829. right: 32rpx;
  830. width: 64rpx;
  831. height: 64rpx;
  832. background: #ffffff;
  833. border-radius: 50%;
  834. display: flex;
  835. align-items: center;
  836. justify-content: center;
  837. box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
  838. z-index: 99;
  839. }
  840. /* 顶部导航栏右侧图标 */
  841. .header-right {
  842. display: flex;
  843. align-items: center;
  844. .notification-icon {
  845. position: relative;
  846. margin-right: 32rpx;
  847. .badge {
  848. position: absolute;
  849. top: -4rpx;
  850. right: -4rpx;
  851. width: 12rpx;
  852. height: 12rpx;
  853. background: #ff6b6b;
  854. border-radius: 50%;
  855. }
  856. }
  857. }
  858. </style>