index.vue 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993
  1. <template>
  2. <view class="device-details-page">
  3. <cu-custom :isBack="true">
  4. <template slot="content">
  5. <view class="nav-title">{{ deviceInfo.devName }}</view>
  6. </template>
  7. </cu-custom>
  8. <!-- 设备基本信息 -->
  9. <view class="device-info">
  10. <view class="operation" @click.stop="isShowOperation = !isShowOperation">操作</view>
  11. <view class="operation-container" v-if="isShowOperation" @click="closeOperationHandler">
  12. <view class="operation-background"></view>
  13. <view class="operation-content">
  14. <view class="operation-item" @click="goPage('devRepair')">
  15. <image :src="serviceIcon" class="operation-icon"></image>
  16. 维修
  17. </view>
  18. <view class="operation-item" @click="goPage('devControl')">
  19. <image :src="settingIcon" class="operation-icon"></image>
  20. 设置
  21. </view>
  22. <view class="operation-item" @click="goPage('simDetail')">
  23. <image :src="simIcon" class="operation-icon"></image>
  24. SIM卡
  25. </view>
  26. <!-- <view class="operation-item" @click="modification">
  27. <image :src="editIcon" class="operation-icon"></image>
  28. 修改
  29. </view> -->
  30. </view>
  31. </view>
  32. <view @click="copy(deviceInfo.devBid)" class="info-item">
  33. <text class="info-label">设备ID</text>
  34. <text class="info-value">{{ deviceInfo.devBid }}</text>
  35. <image
  36. src="/static/images/device/copy.svg"
  37. mode=""
  38. class="info-img"
  39. ></image>
  40. </view>
  41. <view class="info-item">
  42. <text class="info-label">上报时间</text>
  43. <text class="info-value">{{ formatTimestamp(deviceInfo.uptime) }}</text>
  44. </view>
  45. <view class="info-item">
  46. <text class="info-label">设备位置</text>
  47. <text class="info-value">{{ deviceInfo.address }}</text>
  48. </view>
  49. <view class="dev-status">{{
  50. deviceInfo.devStatus == "1" ? "在线" : "离线"
  51. }}</view>
  52. </view>
  53. <!-- 标签页切换 -->
  54. <view class="tab-container">
  55. <view class="tab-top">
  56. <view
  57. class="tab-item"
  58. :class="{ active: activeTab === 'monitoring' }"
  59. @click="switchTab('monitoring')"
  60. >
  61. <text class="tab-text">监测要素</text>
  62. <image
  63. v-if="activeTab === 'monitoring'"
  64. src="/static/images/device/smile.svg"
  65. mode=""
  66. class="smile"
  67. ></image>
  68. </view>
  69. <view
  70. class="tab-item"
  71. :class="{ active: activeTab === 'details' }"
  72. @click="switchTab('details')"
  73. >
  74. <text class="tab-text">设备详情</text>
  75. <image
  76. v-if="activeTab === 'details'"
  77. src="/static/images/device/smile.svg"
  78. mode=""
  79. class="smile"
  80. ></image>
  81. </view>
  82. </view>
  83. </view>
  84. <!-- 标签页内容 -->
  85. <view class="tab-content">
  86. <!-- 监测要素页面 -->
  87. <view v-if="activeTab === 'monitoring'" class="monitoring-page">
  88. <view
  89. class="data-card"
  90. v-for="(item, index) in monitorList"
  91. :key="index"
  92. @click="goPage('eleDetail', item)"
  93. >
  94. <view class="card-title">{{ item.factorName }}</view>
  95. <view class="data-value-row">
  96. <view>
  97. <text v-if="item.yData && item.yData.length" class="data-value">{{ item.yData[0] }}</text>
  98. <text class="data-unit">{{ item.factorUnit }}</text>
  99. </view>
  100. <image
  101. class="device-img"
  102. :src="`/static/images/device/${item.key}-default.svg`"
  103. mode="aspectFit"
  104. ></image>
  105. </view>
  106. <view class="card-thrid">
  107. <text>{{ item.alias || '' }}</text>
  108. </view>
  109. </view>
  110. </view>
  111. <!-- 设备详情页面 -->
  112. <view v-if="activeTab === 'details'" class="details-page">
  113. <!-- 设备参数 -->
  114. <view class="device-params">
  115. <view class="device-control">
  116. <!-- <view class="control-left">
  117. <view>2025-12-28 08:00:00</view>
  118. <u-icon name="reload" class="reload-img"></u-icon>
  119. </view> -->
  120. <view class="control-left">
  121. <view>{{formatTimestamp(deviceInfo.uptime)}}</view>
  122. <u-icon name="reload" color="#0BBC58" style="margin-left: 12rpx" @click="refreshData"></u-icon>
  123. </view>
  124. <!-- <view class="control-right">
  125. <image
  126. class="control-img"
  127. src="/static/images/cb/control.svg"
  128. mode="aspectFit"
  129. @click="goPage('devControl')"
  130. ></image>
  131. <image
  132. class="control-img"
  133. src="/static/images/cb/setting.svg"
  134. mode="aspectFit"
  135. @click="goPage('devRepair')"
  136. ></image>
  137. <image
  138. class="control-img"
  139. src="/static/images/cb/sim.svg"
  140. mode="aspectFit"
  141. @click="goPage('simDetail')"
  142. ></image>
  143. </view> -->
  144. </view>
  145. <view class="params-board">
  146. <view class="params-left">
  147. <view
  148. v-for="(item, index) in statusList"
  149. :key="index"
  150. class="params-item"
  151. >
  152. <view class="params-val">{{ item.val }}</view>
  153. <view class="params-label">{{ item.label }}</view>
  154. </view>
  155. </view>
  156. <view class="params-right">
  157. <image
  158. class="device-img"
  159. src="/static/images/device/dev-station.svg"
  160. mode="aspectFit"
  161. ></image>
  162. </view>
  163. </view>
  164. </view>
  165. <!-- 设备数据表格 -->
  166. <view class="table-container">
  167. <view class="table-control">
  168. <view class="title">设备数据</view>
  169. <view class="date-board" @click="openDatePicker">
  170. <text>{{ startDate }}</text>
  171. <text class="line">至</text>
  172. <text>{{ endDate }}</text>
  173. <image class="date-icon" src="/static/images/device/date.svg" />
  174. </view>
  175. </view>
  176. <u-calendar
  177. v-model="show"
  178. :mode="mode"
  179. @change="onDateChange"
  180. ref="calendar"
  181. ></u-calendar>
  182. <view class="table-wrap" v-if="tableData && tableData.length > 0">
  183. <view class="fixed-column">
  184. <view class="table-cell header">上报时间</view>
  185. <view
  186. class="table-cell"
  187. v-for="(item, idx) in tableData"
  188. :key="idx"
  189. >
  190. {{ item.uptime }}
  191. </view>
  192. </view>
  193. <view class="table-bg"></view>
  194. <scroll-view class="scroll-column" scroll-x="true">
  195. <view class="scroll-content">
  196. <view class="table-row">
  197. <view
  198. class="table-cell header"
  199. v-for="(item, index) in tableColumn"
  200. :key="index"
  201. >{{ item.label }}</view
  202. >
  203. </view>
  204. <view
  205. class="table-row"
  206. v-for="(item, idx) in tableData"
  207. :key="idx"
  208. >
  209. <view
  210. class="table-cell"
  211. v-for="(item1, index1) in tableColumn"
  212. :key="index1"
  213. >{{ item[item1.prop] }}</view
  214. >
  215. </view>
  216. </view>
  217. </scroll-view>
  218. </view>
  219. <view class="empty-state" v-else>
  220. <u-empty text="暂无数据" mode="list"></u-empty>
  221. </view>
  222. <view class="pagination" v-if="tableData && tableData.length > 0">
  223. <view
  224. class="page-item prev"
  225. :class="{ disabled: page <= 1 }"
  226. @click="prevPage"
  227. >上一页</view>
  228. <view class="page-info">
  229. <text class="curret-page">{{ page }}</text>
  230. <text>/</text>
  231. <text>{{ totalPages }}</text>
  232. </view>
  233. <view
  234. class="page-item next"
  235. :class="{ disabled: page >= totalPages }"
  236. @click="nextPage"
  237. >下一页</view>
  238. </view>
  239. </view>
  240. </view>
  241. </view>
  242. </view>
  243. </template>
  244. <script>
  245. export default {
  246. onLoad(options) {
  247. console.log(options, "optionsss");
  248. this.deviceInfo = options;
  249. this.initDateRange(options.uptime);
  250. this.getQxzObData();
  251. this.getDeviceStatus();
  252. this.getDeviceData();
  253. },
  254. data() {
  255. return {
  256. deviceInfo: {},
  257. isShowOperation: false,
  258. activeTab: "monitoring",
  259. monitorList: [],
  260. statusList: [],
  261. show: false,
  262. mode: "range",
  263. startDate: "",
  264. endDate: "",
  265. page: 1,
  266. photoIcon:'https://s3.hnyfwlw.com/webstaticimg/bigdata_app/newImg/home/photoIcon.png',
  267. editIcon:'https://s3.hnyfwlw.com/webstaticimg/bigdata_app/newImg/home/editIcon.png',
  268. serviceIcon:'https://s3.hnyfwlw.com/webstaticimg/bigdata_app/newImg/home/serviceIcon.png',
  269. simIcon:'https://s3.hnyfwlw.com/webstaticimg/bigdata_app/newImg/home/simIcon.png',
  270. settingIcon:'https://s3.hnyfwlw.com/webstaticimg/bigdata_app/newImg/home/settingIcon.png',
  271. isShowPhoto:false,
  272. pageSize: 9,
  273. total: 0,
  274. tableData: [],
  275. tableColumn: [],
  276. };
  277. },
  278. computed: {
  279. totalPages() {
  280. return Math.ceil(this.total / this.pageSize) || 1;
  281. },
  282. },
  283. methods: {
  284. closeOperationHandler(){
  285. this.isShowOperation = false;
  286. },
  287. async refreshData(){
  288. await this.$myRequest({
  289. url: '/api/api_gateway?method=qxz.device.control',
  290. data: {
  291. device_id: this.deviceInfo.devBid,
  292. cmd: 'READ',
  293. },
  294. });
  295. //弹框提示
  296. uni.showToast({
  297. title: '刷新成功',
  298. icon: 'success',
  299. });
  300. this.getDeviceData();
  301. },
  302. formatTimestamp(timestamp) {
  303. if (!timestamp) return "";
  304. const date = new Date(Number(timestamp) * 1000);
  305. const year = date.getFullYear();
  306. const month = String(date.getMonth() + 1).padStart(2, "0");
  307. const day = String(date.getDate()).padStart(2, "0");
  308. const hours = String(date.getHours()).padStart(2, "0");
  309. const minutes = String(date.getMinutes()).padStart(2, "0");
  310. const seconds = String(date.getSeconds()).padStart(2, "0");
  311. return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  312. },
  313. formatDate(date) {
  314. const year = date.getFullYear();
  315. const month = String(date.getMonth() + 1).padStart(2, "0");
  316. const day = String(date.getDate()).padStart(2, "0");
  317. return `${year}-${month}-${day}`;
  318. },
  319. initDateRange(timestamp) {
  320. if (!timestamp) {
  321. const today = new Date();
  322. this.endDate = this.formatDate(today);
  323. const startDate = new Date(today);
  324. startDate.setDate(startDate.getDate() - 7);
  325. this.startDate = this.formatDate(startDate);
  326. return;
  327. }
  328. const date = new Date(Number(timestamp) * 1000);
  329. this.endDate = this.formatDate(date);
  330. const startDate = new Date(date);
  331. startDate.setDate(startDate.getDate() - 7);
  332. this.startDate = this.formatDate(startDate);
  333. },
  334. switchTab(tab) {
  335. this.activeTab = tab;
  336. },
  337. copy(item) {
  338. console.log(item);
  339. uni.setClipboardData({
  340. data: item,
  341. success: function () {
  342. console.log("success");
  343. },
  344. });
  345. },
  346. goPage(type, eleItem) {
  347. let url = ''
  348. if (eleItem && eleItem.key) {
  349. url = `/pages/deviceDetails/weatherStation/${type}?deviceInfo=${encodeURIComponent(JSON.stringify(this.deviceInfo))}&eleKey=${eleItem.key}`
  350. } else {
  351. url = `/pages/deviceDetails/weatherStation/${type}?deviceInfo=${encodeURIComponent(JSON.stringify(this.deviceInfo))}`
  352. }
  353. if(type==='devRepair'){
  354. url = `/pages/afterSale/addafter?d_id=${this.deviceInfo.d_id}&device_id=${this.deviceInfo.devBid}&device_type=${this.deviceInfo.deviceType}`
  355. }
  356. uni.navigateTo({
  357. url
  358. });
  359. },
  360. openDatePicker() {
  361. this.show = true;
  362. },
  363. onDateChange(event) {
  364. if (event && event.startDate && event.endDate) {
  365. this.startDate = event.startDate;
  366. this.endDate = event.endDate;
  367. this.show = false;
  368. this.page = 1;
  369. this.getDeviceData();
  370. }
  371. },
  372. prevPage() {
  373. if (this.page <= 1) return;
  374. this.page--;
  375. this.getDeviceData();
  376. },
  377. nextPage() {
  378. if (this.page >= this.totalPages) return;
  379. this.page++;
  380. this.getDeviceData();
  381. },
  382. // 获取设备最新监测数据
  383. async getQxzObData() {
  384. const res = await this.$myRequest({
  385. url: "/api/api_gateway?method=qxz.data.qxz_ob_last_data",
  386. data: {
  387. device_id: this.deviceInfo.devBid,
  388. },
  389. });
  390. console.log("设备最新监测数据:", res);
  391. const title = res.title
  392. const data = res.data
  393. const alias = res.alias
  394. this.monitorList = this.formatChartData(title, data, alias)
  395. },
  396. formatChartData(obj, data, alias) {
  397. const keys = Object.keys(obj);
  398. const result = [];
  399. console.log(data, 'datadata');
  400. for (const prop of keys) {
  401. const objArr = obj[prop];
  402. if (objArr[4] == 1) {
  403. result.push({
  404. factorName: objArr[1],
  405. key: prop,
  406. yData: data[prop],
  407. factorUnit: objArr[3],
  408. newData: objArr[5],
  409. alias: alias[prop]
  410. });
  411. }
  412. }
  413. console.log(result, 'real-time data');
  414. return result;
  415. },
  416. convertDynamic(data, getLabelValue) {
  417. if (!data || typeof data !== 'object') return [];
  418. const result = [];
  419. const keys = Object.keys(data);
  420. for (const prop of keys) {
  421. const arr = data[prop];
  422. const value = getLabelValue(prop, arr, data);
  423. if (value !== undefined && value !== null) {
  424. result.push({
  425. label: String(value),
  426. prop,
  427. align: 'center'
  428. });
  429. }
  430. }
  431. return result;
  432. },
  433. // 获取设备状态数据
  434. async getDeviceStatus() {
  435. const res = await this.$myRequest({
  436. url: "/api/api_gateway?method=qxz.data.qxz_status",
  437. data: {
  438. device_id: this.deviceInfo.devBid,
  439. },
  440. });
  441. console.log("getDeviceStatus:", res);
  442. const newArr = this.transformObjectToArray(res);
  443. this.statusList = newArr;
  444. console.log(this.statusList, "getDevStatus");
  445. },
  446. transformObjectToArray(originalData) {
  447. if (
  448. typeof originalData !== "object" ||
  449. originalData === null ||
  450. Array.isArray(originalData)
  451. ) {
  452. return [];
  453. }
  454. return Object.keys(originalData).map((key) => {
  455. const [val = "", label = ""] = originalData[key] || [];
  456. return {
  457. label,
  458. val,
  459. key,
  460. };
  461. });
  462. },
  463. // 设备数据列表
  464. async getDeviceData() {
  465. const data = await this.$myRequest({
  466. url: "/api/api_gateway?method=qxz.data.qxz_device_data",
  467. data: {
  468. device_id: this.deviceInfo.devBid,
  469. page: String(this.page),
  470. page_size: String(this.pageSize),
  471. start: String(Math.floor(new Date(this.startDate + " 00:00:00").getTime() / 1000)),
  472. end: String(Math.floor(new Date(this.endDate + " 23:59:59").getTime() / 1000)),
  473. },
  474. });
  475. console.log(data, "resss");
  476. if (Array.isArray(data) && data.length > 0) {
  477. this.total = data[0]?.count || 0;
  478. this.tableData = data[0].data || [];
  479. const title = data[0].title;
  480. this.tableColumn = title
  481. .map((item) => {
  482. return {
  483. label: item[1],
  484. prop: item[0],
  485. };
  486. })
  487. .filter((item) => item.prop !== "uptime");
  488. } else {
  489. // 没数据时,设置为空
  490. this.total = 0;
  491. this.tableData = [];
  492. this.tableColumn = [];
  493. }
  494. console.log(this.tableColumn, "tableCol");
  495. console.log(this.tableData, "tableData");
  496. },
  497. },
  498. };
  499. </script>
  500. <style lang="scss">
  501. .device-details-page {
  502. background:
  503. linear-gradient(180deg, #ffffff00 0%, #f5f6fa 23.64%, #f5f6fa 100%),
  504. linear-gradient(102deg, #bfeadd 6.77%, #b8f1e7 40.15%, #b9eef5 84.02%);
  505. min-height: 100vh;
  506. padding: 0 32rpx;
  507. padding-top: 98rpx;
  508. }
  509. /* 设备基本信息 */
  510. .device-info {
  511. background-color: #ffffff;
  512. margin: 46rpx 0 24rpx 0;
  513. padding: 32rpx 24rpx;
  514. border-radius: 16rpx;
  515. background: linear-gradient(180deg, #eff 0%, #fff 23.56%);
  516. position: relative;
  517. .info-item {
  518. display: flex;
  519. align-items: center;
  520. margin-bottom: 16rpx;
  521. }
  522. .info-item:last-child {
  523. margin-bottom: 0;
  524. }
  525. .operation-container{
  526. position: fixed;
  527. right: 0;
  528. top: 0;
  529. width: 100%;
  530. height: 100%;
  531. z-index: 99;
  532. }
  533. .operation{
  534. position: fixed;
  535. top: 260rpx;
  536. right: 0;
  537. z-index: 999;
  538. width:48rpx;
  539. height: 100rpx;
  540. line-height: 50rpx;
  541. border-radius: 8px 0 0 8px;
  542. border-top: 4rpx solid #FFF;
  543. border-bottom: 4rpx solid #FFF;
  544. border-left: 4rpx solid #FFF;
  545. background: #dddfe6a3;
  546. color: #515153;
  547. text-align: center;
  548. font-family: "Source Han Sans CN VF";
  549. font-size: 24rpx;
  550. font-weight: 500;
  551. writing-mode: vertical-rl;
  552. }
  553. .operation-background{
  554. position: fixed;
  555. right: 0;
  556. top: 0;
  557. width: 100%;
  558. height: 100%;
  559. z-index: 998;
  560. background: #00000040;
  561. }
  562. .operation-content{
  563. position: fixed;
  564. top: 240rpx;
  565. right: 80rpx;
  566. height: 126rpx;
  567. display: flex;
  568. padding: 16rpx 32rpx;
  569. align-items: center;
  570. gap: 64rpx;
  571. z-index: 999;
  572. border-radius: 32rpx;
  573. border: 2rpx solid #FFF;
  574. background: #FFF;
  575. backdrop-filter: blur(8rpx);
  576. .operation-item{
  577. display: flex;
  578. flex-direction: column;
  579. align-items: center;
  580. justify-content: center;
  581. color: #333333;
  582. text-align: center;
  583. font-family: "Source Han Sans CN VF";
  584. font-size: 24rpx;
  585. font-weight: 400;
  586. }
  587. .operation-icon{
  588. width: 58rpx;
  589. height: 58rpx;
  590. }
  591. }
  592. .info-label {
  593. width: 116rpx;
  594. color: #999999;
  595. text-align: right;
  596. font-family: "Source Han Sans CN VF";
  597. font-size: 28rpx;
  598. font-style: normal;
  599. font-weight: 400;
  600. line-height: normal;
  601. margin-right: 32rpx;
  602. white-space: nowrap;
  603. }
  604. .info-value {
  605. color: #333333;
  606. font-family: "Source Han Sans CN VF";
  607. font-size: 28rpx;
  608. font-style: normal;
  609. font-weight: 400;
  610. line-height: normal;
  611. text-overflow: ellipsis;
  612. overflow: hidden;
  613. white-space: nowrap;
  614. }
  615. .info-img {
  616. width: 32rpx;
  617. height: 32rpx;
  618. margin-left: 16rpx;
  619. background: #0bbc581a;
  620. display: flex;
  621. align-items: center;
  622. justify-content: center;
  623. }
  624. .tishi {
  625. width: 24rpx;
  626. height: 24rpx;
  627. }
  628. .dev-status {
  629. position: absolute;
  630. right: 0;
  631. top: 0;
  632. border: 2rpx solid #ffffff;
  633. background: #0bbc581a;
  634. width: 152rpx;
  635. height: 56rpx;
  636. color: #0bbc58;
  637. text-align: center;
  638. font-size: 28rpx;
  639. font-weight: 400;
  640. line-height: 52rpx;
  641. border-radius: 0 16rpx 0 64rpx;
  642. }
  643. }
  644. /* 标签页切换 */
  645. .tab-container {
  646. background-color: #ffffff;
  647. border-radius: 16rpx;
  648. overflow: hidden;
  649. padding: 0 32rpx;
  650. margin-bottom: 24rpx;
  651. .tab-top {
  652. display: flex;
  653. }
  654. .tab-item {
  655. flex: 1;
  656. height: 80rpx;
  657. display: flex;
  658. flex-direction: column;
  659. align-items: center;
  660. position: relative;
  661. color: #666666;
  662. text-align: center;
  663. font-family: "Source Han Sans CN VF";
  664. font-size: 28rpx;
  665. font-style: normal;
  666. font-weight: 400;
  667. line-height: normal;
  668. .tab-text {
  669. margin-top: 16rpx;
  670. }
  671. .smile {
  672. width: 24rpx;
  673. height: 18rpx;
  674. }
  675. }
  676. .tab-item.active {
  677. color: #333333;
  678. font-weight: 700;
  679. }
  680. .time-board {
  681. display: flex;
  682. align-items: center;
  683. justify-content: space-between;
  684. margin-bottom: 16rpx;
  685. }
  686. .time-filter {
  687. display: flex;
  688. align-items: center;
  689. justify-content: space-between;
  690. width: 256rpx;
  691. height: 48rpx;
  692. padding: 6rpx 8rpx;
  693. border-radius: 32rpx;
  694. background: #f1f4f8;
  695. color: #303133;
  696. font-size: 20rpx;
  697. font-weight: 400;
  698. .filter-item {
  699. padding: 4rpx 16rpx;
  700. height: 36rpx;
  701. line-height: 36rpx;
  702. }
  703. .active {
  704. border-radius: 32rpx;
  705. background: #fff;
  706. }
  707. }
  708. }
  709. /* 监测要素页面 */
  710. .monitoring-page {
  711. padding-bottom: 20px;
  712. display: flex;
  713. flex-wrap: wrap;
  714. justify-content: space-between;
  715. .data-card {
  716. width: calc(50% - 8rpx);
  717. margin-bottom: 16rpx;
  718. background-color: #ffffff;
  719. border-radius: 16rpx;
  720. padding: 16rpx 24rpx;
  721. height: 186rpx;
  722. font-family: "Source Han Sans CN VF";
  723. font-size: 28rpx;
  724. font-weight: 400;
  725. box-sizing: border-box;
  726. .card-title {
  727. color: #042118;
  728. margin-bottom: 6rpx;
  729. }
  730. .data-value-row {
  731. display: flex;
  732. justify-content: space-between;
  733. align-items: center;
  734. color: #042118;
  735. font-family: "Source Han Sans CN VF";
  736. font-weight: 400;
  737. .data-value {
  738. font-size: 40rpx;
  739. font-weight: 700;
  740. margin-right: 8rpx;
  741. }
  742. .data-unit {
  743. font-size: 24rpx;
  744. }
  745. .device-img {
  746. width: 52rpx;
  747. height: 52rpx;
  748. }
  749. }
  750. .card-thrid {
  751. color: #687a74;
  752. margin-top: 6rpx;
  753. }
  754. }
  755. }
  756. /* 设备详情页面 */
  757. .details-page {
  758. .device-params {
  759. background-color: #ffffff;
  760. border-radius: 16rpx;
  761. padding: 32rpx;
  762. margin-bottom: 24rpx;
  763. .device-control {
  764. position: relative;
  765. z-index: 3;
  766. display: flex;
  767. align-items: center;
  768. justify-content: space-between;
  769. margin-bottom: 24rpx;
  770. .control-left {
  771. color: #999999;
  772. font-family: "Source Han Sans CN VF";
  773. font-size: 28rpx;
  774. display: flex;
  775. align-items: center;
  776. .reload-img {
  777. font-size: 32rpx;
  778. color: #0bbc58;
  779. margin-left: 14rpx;
  780. }
  781. }
  782. .control-right {
  783. display: flex;
  784. align-items: center;
  785. .control-img {
  786. width: 48rpx;
  787. height: 48rpx;
  788. margin-left: 24rpx;
  789. }
  790. }
  791. }
  792. .params-board {
  793. display: flex;
  794. justify-content: space-between;
  795. align-items: center;
  796. position: relative;
  797. .params-left {
  798. display: flex;
  799. flex-wrap: wrap;
  800. .params-item {
  801. display: flex;
  802. flex-direction: column;
  803. width: 100%;
  804. // width: calc(50% - 20rpx);
  805. margin-bottom: 24rpx;
  806. .params-val {
  807. color: #303133;
  808. font-size: 28rpx;
  809. font-weight: 700;
  810. }
  811. .params-label {
  812. color: #999999;
  813. font-size: 24rpx;
  814. font-weight: 400;
  815. }
  816. }
  817. }
  818. .params-right {
  819. position: absolute;
  820. right: 0;
  821. top: 0rpx;
  822. .device-img {
  823. width: 150rpx;
  824. }
  825. }
  826. }
  827. }
  828. .table-container {
  829. padding: 16rpx 32rpx 32rpx 32rpx;
  830. border-radius: 16rpx;
  831. background: #fff;
  832. .table-control {
  833. display: flex;
  834. align-items: center;
  835. justify-content: space-between;
  836. margin-bottom: 16rpx;
  837. .title {
  838. color: #042118;
  839. font-family: "Source Han Sans CN VF";
  840. font-size: 28rpx;
  841. font-style: normal;
  842. font-weight: 700;
  843. line-height: normal;
  844. }
  845. .date-board {
  846. display: flex;
  847. align-items: center;
  848. color: #020305;
  849. font-family: "Source Han Sans CN VF";
  850. font-size: 24rpx;
  851. font-weight: 400;
  852. border-radius: 32rpx;
  853. background: #f1f4f8;
  854. padding: 7rpx 24rpx;
  855. .line {
  856. color: #656565;
  857. margin: 0 10rpx;
  858. }
  859. .date-icon {
  860. width: 32rpx;
  861. height: 32rpx;
  862. margin-left: 16rpx;
  863. }
  864. }
  865. }
  866. .table-wrap {
  867. display: flex;
  868. width: 100%;
  869. height: 788rpx;
  870. box-sizing: border-box;
  871. margin: 20rpx 0;
  872. color: #042118;
  873. font-family: "Source Han Sans CN VF";
  874. font-size: 24rpx;
  875. font-style: normal;
  876. font-weight: 400;
  877. line-height: normal;
  878. .fixed-column {
  879. width: 250rpx;
  880. .table-cell {
  881. width: 100%;
  882. white-space: nowrap;
  883. }
  884. }
  885. .table-bg {
  886. width: 16rpx;
  887. background: linear-gradient(270deg, #ffffff33 0%, #9598a433 100%);
  888. }
  889. .scroll-column {
  890. flex: 1;
  891. height: auto;
  892. overflow: hidden;
  893. margin-left: -10rpx;
  894. }
  895. .scroll-content {
  896. min-width: 100%;
  897. width: fit-content;
  898. display: flex;
  899. flex-direction: column;
  900. .table-row {
  901. display: flex;
  902. .table-cell {
  903. flex: 1;
  904. }
  905. }
  906. }
  907. .table-cell {
  908. width: 160rpx;
  909. height: 80rpx;
  910. line-height: 80rpx;
  911. text-align: center;
  912. border-bottom: 2px solid #e4e7ed;
  913. box-sizing: border-box;
  914. overflow: hidden;
  915. padding: 0 4rpx;
  916. text-overflow: ellipsis;
  917. }
  918. .table-cell.header {
  919. background: #f6f8fc;
  920. }
  921. }
  922. .pagination {
  923. display: flex;
  924. align-items: center;
  925. justify-content: space-between;
  926. margin-top: 24rpx;
  927. .page-item {
  928. width: 104rpx;
  929. height: 48rpx;
  930. color: #656565;
  931. font-size: 24rpx;
  932. line-height: 48rpx;
  933. text-align: center;
  934. border: 2rpx solid #e4e7ed;
  935. border-radius: 8rpx;
  936. }
  937. .prev.disabled {
  938. color: #c0c4cc;
  939. border-color: #e4e7ed;
  940. }
  941. .next {
  942. color: #0bbc58;
  943. border: 2px solid #0bbc58;
  944. }
  945. .next.disabled {
  946. color: #c0c4cc;
  947. border-color: #e4e7ed;
  948. }
  949. .page-info {
  950. color: #999999;
  951. font-family: "Source Han Sans CN VF";
  952. font-size: 24rpx;
  953. font-style: normal;
  954. font-weight: 400;
  955. line-height: normal;
  956. .curret-page {
  957. color: #303133;
  958. }
  959. }
  960. }
  961. .empty-state {
  962. padding: 80rpx 0;
  963. }
  964. }
  965. }
  966. ::v-deep .u-calendar__action {
  967. display: flex;
  968. justify-content: center;
  969. }
  970. </style>