index.vue 23 KB

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