index.vue 27 KB

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