eleDetail.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. <template>
  2. <view class="ele-details-page">
  3. <cu-custom :isBack="true">
  4. <template slot="content">
  5. <view class="nav-title">小气候监测站II监测要素</view>
  6. </template>
  7. </cu-custom>
  8. <view class="date-picker" @click="openDatePicker">
  9. <text>{{ startDate }}</text>
  10. <text class="separator">-</text>
  11. <text>{{ endDate }}</text>
  12. <image class="date-icon" src="/static/images/device/date-active.svg" />
  13. </view>
  14. <u-calendar
  15. v-model="show"
  16. :mode="mode"
  17. @change="onDateChange"
  18. ref="calendar"
  19. range-color="#999"
  20. btn-type="success"
  21. active-bg-color="#0BBC58"
  22. range-bg-color="rgba(11,188,88,0.13)"
  23. ></u-calendar>
  24. <view class="echarts-board">
  25. <view class="period-tabs">
  26. <view
  27. class="tab-item"
  28. :class="{ active: activePeriod === '24h' }"
  29. @click="changePeriod('24h')"
  30. >24小时</view
  31. >
  32. <view
  33. class="tab-item"
  34. :class="{ active: activePeriod === '7d' }"
  35. @click="changePeriod('7d')"
  36. >一周</view
  37. >
  38. <view
  39. class="tab-item"
  40. :class="{ active: activePeriod === '30d' }"
  41. @click="changePeriod('30d')"
  42. >一月</view
  43. >
  44. </view>
  45. <view class="element-tabs" v-if="hasData">
  46. <view class="ele-board">
  47. <view
  48. v-for="(item, index) in eleTabs"
  49. :key="index"
  50. class="ele-item"
  51. :class="{ 'ele-active': eleActive === index }"
  52. @click="changeElement(index)"
  53. >{{ item.name }}</view
  54. >
  55. </view>
  56. <view class="fold-icon" @click="toggleFold">
  57. <u-icon :name="isFolded ? 'arrow-down' : 'arrow-up'"></u-icon>
  58. </view>
  59. </view>
  60. <!-- 展开后的所有要素 -->
  61. <view v-if="!isFolded && hasData" class="expanded-elements">
  62. <view
  63. class="expanded-item"
  64. v-for="(item, index) in eleTabs"
  65. :key="index"
  66. :class="{ 'ele-active': eleActive === index }"
  67. @click="changeElement(index)"
  68. >
  69. {{ item.name }}
  70. </view>
  71. </view>
  72. <view class="chart-container" v-if="hasData">
  73. <canvas
  74. v-show="!show"
  75. canvas-id="temperatureChart"
  76. id="temperatureChart"
  77. class="chart"
  78. @touchstart="touchLineA($event)"
  79. @touchmove="moveLineA($event)"
  80. @touchend="touchEndLineA($event)"
  81. disable-scroll="true"
  82. ></canvas>
  83. </view>
  84. <view class="no-data" v-else>
  85. <text>暂无数据</text>
  86. </view>
  87. <!-- <view class="stats-panel">
  88. <view class="stat-item">
  89. <text class="value">27<text class="unit">°C</text></text>
  90. <text class="label">最低值</text>
  91. </view>
  92. <view class="stat-item">
  93. <text class="value">32<text class="unit">°C</text></text>
  94. <text class="label">平均值</text>
  95. </view>
  96. <view class="stat-item">
  97. <text class="value red">42<text class="unit red">°C</text></text>
  98. <text class="label">最高值</text>
  99. </view>
  100. </view> -->
  101. </view>
  102. <view class="history-section">
  103. <view class="section-title">历史数据</view>
  104. <view class="table-wrap">
  105. <view class="fixed-column">
  106. <view class="table-cell header">上报时间</view>
  107. <view class="table-cell" v-for="(item, idx) in tableList" :key="idx">
  108. {{ item.time }}
  109. </view>
  110. </view>
  111. <view class="table-bg"></view>
  112. <scroll-view class="scroll-column" scroll-x="true">
  113. <view class="scroll-content">
  114. <view class="table-row">
  115. <view class="table-cell header">{{
  116. activeChartInfo.name + "(" + activeChartInfo.unit + ")"
  117. }}</view>
  118. </view>
  119. <view class="table-row" v-for="(item, idx) in tableList" :key="idx">
  120. <view class="table-cell">{{ item[activeChartInfo.key] }}</view>
  121. </view>
  122. </view>
  123. </scroll-view>
  124. </view>
  125. <view class="pagination">
  126. <view
  127. class="page-item prev"
  128. @click="prevPage"
  129. :class="{ disabled: currentPage === 1 }"
  130. >上一页</view
  131. >
  132. <view class="page-info">
  133. <text class="curret-page">{{ currentPage }}</text>
  134. <text>/</text>
  135. <text>{{ totalPages }}</text>
  136. </view>
  137. <view
  138. class="page-item next"
  139. @click="nextPage"
  140. :class="{ disabled: currentPage >= totalPages }"
  141. >下一页</view
  142. >
  143. </view>
  144. </view>
  145. </view>
  146. </template>
  147. <script>
  148. import uCharts from "../../../components/js_sdk/u-charts/u-charts/u-charts.js";
  149. import baseCharts from "./charts.vue";
  150. export default {
  151. components: { baseCharts },
  152. onLoad(options) {
  153. const deviceInfo = JSON.parse(decodeURIComponent(options.deviceInfo));
  154. this.eleKey = options.eleKey || "";
  155. this.initDateRange(deviceInfo.uptime);
  156. this.deviceInfo = deviceInfo;
  157. this.getChartData();
  158. this.getObData();
  159. },
  160. data() {
  161. return {
  162. temperatureChart: null,
  163. activePeriod: "",
  164. activeElement: "temperature",
  165. show: false,
  166. mode: "range",
  167. startDate: "",
  168. endDate: "",
  169. isFolded: true, // 控制要素是否收起
  170. eleTabs: [],
  171. eleActive: 0,
  172. hasData: true,
  173. tableList: [],
  174. titles: [],
  175. currentPage: 1,
  176. pageSize: 9,
  177. total: 0,
  178. chartData: {
  179. categories: [],
  180. series: [],
  181. },
  182. activeChartInfo: {},
  183. eleKey: "",
  184. };
  185. },
  186. computed: {
  187. totalPages() {
  188. return Math.ceil(this.total / this.pageSize);
  189. },
  190. },
  191. methods: {
  192. initDateRange(timestamp) {
  193. if (!timestamp) {
  194. const today = new Date();
  195. this.endDate = this.formatDate(today);
  196. const startDate = new Date(today);
  197. startDate.setDate(startDate.getDate() - 7);
  198. this.startDate = this.formatDate(startDate);
  199. return;
  200. }
  201. const date = new Date(Number(timestamp) * 1000);
  202. this.endDate = this.formatDate(date);
  203. const startDate = new Date(date);
  204. startDate.setDate(startDate.getDate() - 7);
  205. this.startDate = this.formatDate(startDate);
  206. },
  207. formatDate(date) {
  208. const year = date.getFullYear();
  209. const month = String(date.getMonth() + 1).padStart(2, "0");
  210. const day = String(date.getDate()).padStart(2, "0");
  211. return `${year}-${month}-${day}`;
  212. },
  213. initChart() {
  214. const ctx = uni.createCanvasContext("temperatureChart", this);
  215. const currentEle = this.eleTabs[this.eleActive];
  216. console.log(currentEle, "currentEle");
  217. // u-charts 的 series.data 必须是数字数组;原数据 value 为字符串(含 "/"、"NA"),
  218. // 直接传对象数组会导致 Y 轴 min/max 计算异常,刻度全部相同
  219. const seriesData = currentEle.data.map((item) => {
  220. const val = item.value;
  221. if (val === "/" || val === "NA" || val === null || val === undefined || val === "") {
  222. return 0;
  223. }
  224. const num = Number(val);
  225. return isNaN(num) ? 0 : num;
  226. });
  227. const series = [
  228. {
  229. name: currentEle.name,
  230. data: seriesData,
  231. lineWidth: 3,
  232. pointShape: "circle",
  233. pointSize: 12,
  234. pointColor: currentEle.color,
  235. pointBorderColor: "#fff",
  236. pointBorderWidth: 2,
  237. symbol: "emptyCircle",
  238. symbolSize: 6,
  239. legendShape: "circle",
  240. },
  241. ];
  242. const xData = currentEle.data.map((item) => item.time);
  243. this.temperatureChart = new uCharts({
  244. $this: this,
  245. canvasId: "temperatureChart",
  246. type: "line",
  247. context: ctx,
  248. width: 340,
  249. height: 180,
  250. categories: xData,
  251. series: series,
  252. legend: {
  253. position: "top",
  254. show: true,
  255. padding: 5,
  256. fontColor: "#303133",
  257. fontSize: 12,
  258. itemType: "circle",
  259. itemShape: "emptyCircle",
  260. itemWidth: 12,
  261. itemHeight: 12,
  262. lineWidth: 2,
  263. },
  264. xAxis: {
  265. axisLineColor: "#E4E7ED",
  266. disableGrid: true,
  267. fontColor: "#656565",
  268. fontSize: 10,
  269. itemCount: 5,
  270. scrollShow: true,
  271. },
  272. yAxis: {
  273. tofix: 2,
  274. axisLineColor: "#E4E7ED",
  275. fontColor: "#656565",
  276. gridColor: "#E4E7ED",
  277. dashLength: 4,
  278. disableGrid: false,
  279. fontSize: 10,
  280. },
  281. dataLabel: false,
  282. enableScroll: true,
  283. background: "#FFFFFF",
  284. extra: {
  285. line: {
  286. type: "curve",
  287. width: 2,
  288. activeType: "hollow",
  289. },
  290. },
  291. });
  292. },
  293. touchLineA(e) {
  294. this.temperatureChart.scrollStart(e);
  295. },
  296. moveLineA(e) {
  297. this.temperatureChart.scroll(e);
  298. },
  299. touchEndLineA(e) {
  300. this.temperatureChart.scrollEnd(e);
  301. //下面是toolTip事件,如果滚动后不需要显示,可不填写
  302. // this.temperatureChart.showToolTip(e, {
  303. // format: function(item, category) {
  304. // console.log(item, 'iyee', e)
  305. // return category + ' ' + item.name + ':' + item.data
  306. // }
  307. // });
  308. },
  309. // 打开日期选择器
  310. openDatePicker() {
  311. this.show = true;
  312. // 延迟设置日期,确保组件已经初始化
  313. this.$nextTick(() => {
  314. if (this.$refs.calendar) {
  315. // 直接设置组件内部的日期状态
  316. const calendar = this.$refs.calendar;
  317. calendar.startDate = this.startDate;
  318. calendar.endDate = this.endDate;
  319. // 如果有选中的日期范围,设置对应的年、月、日
  320. if (this.startDate) {
  321. const startParts = this.startDate.split("-");
  322. calendar.startYear = parseInt(startParts[0]);
  323. calendar.startMonth = parseInt(startParts[1]);
  324. calendar.startDay = parseInt(startParts[2]);
  325. }
  326. if (this.endDate) {
  327. const endParts = this.endDate.split("-");
  328. calendar.endYear = parseInt(endParts[0]);
  329. calendar.endMonth = parseInt(endParts[1]);
  330. calendar.endDay = parseInt(endParts[2]);
  331. }
  332. // 如果有开始日期,设置日历当前显示的年月为开始日期的年月
  333. if (this.startDate) {
  334. const startParts = this.startDate.split("-");
  335. calendar.year = parseInt(startParts[0]);
  336. calendar.month = parseInt(startParts[1]);
  337. calendar.changeData();
  338. }
  339. }
  340. });
  341. },
  342. // 日期选择变化事件
  343. onDateChange(e) {
  344. this.startDate = e.startDate;
  345. this.endDate = e.endDate;
  346. this.activePeriod = "custom"; // 设置为自定义周期
  347. this.show = false;
  348. this.getChartData();
  349. },
  350. // 切换时间周期
  351. changePeriod(period) {
  352. this.activePeriod = period;
  353. // 根据选择的周期自动计算日期范围
  354. const now = new Date();
  355. const endDate = now.toISOString().split("T")[0];
  356. const startDate = new Date();
  357. if (period === "24h") {
  358. startDate.setDate(now.getDate());
  359. } else if (period === "7d") {
  360. startDate.setDate(now.getDate() - 7);
  361. } else if (period === "30d") {
  362. startDate.setMonth(now.getMonth() - 1);
  363. }
  364. this.startDate = startDate.toISOString().split("T")[0];
  365. this.endDate = endDate;
  366. this.getChartData();
  367. },
  368. // 切换要素标签
  369. changeElement(index) {
  370. if (this.eleTabs.length === 0) return;
  371. this.eleActive = index;
  372. this.activeChartInfo = this.eleTabs[index];
  373. const key = this.activeChartInfo.unit ? this.activeChartInfo.name + '(' + this.activeChartInfo.unit + ')' : this.activeChartInfo.name
  374. const keyValue = this.getKeyByName(key)
  375. this.activeChartInfo.key = keyValue
  376. this.isFolded = true; // 关闭展开面板
  377. this.$nextTick(() => {
  378. this.initChart();
  379. });
  380. },
  381. getKeyByName(key){
  382. const titles = [...this.titles]
  383. let k
  384. titles.forEach(title => {
  385. if(title.name === key){
  386. k = title.key
  387. }
  388. })
  389. return k
  390. },
  391. // 切换要素展开/收起状态
  392. toggleFold() {
  393. this.isFolded = !this.isFolded;
  394. },
  395. // 上一页
  396. prevPage() {
  397. if (this.currentPage > 1) {
  398. this.currentPage--;
  399. this.getObData();
  400. }
  401. },
  402. // 下一页
  403. nextPage() {
  404. if (this.currentPage < this.totalPages) {
  405. this.currentPage++;
  406. this.getObData();
  407. }
  408. },
  409. // 折线图数据
  410. getChartData() {
  411. this.$myRequest({
  412. url: "/api/api_gateway?method=greenhouse.env_first.monitor_data",
  413. data: {
  414. device_id: this.deviceInfo.devBid,
  415. start: String(
  416. Math.floor(new Date(this.startDate + " 00:00:00").getTime() / 1000),
  417. ),
  418. end: String(
  419. Math.floor(new Date(this.endDate + " 23:59:59").getTime() / 1000),
  420. ),
  421. page: 1,
  422. size: 999,
  423. },
  424. }).then((res) => {
  425. console.log("getChartData:", res);
  426. if (res && Array.isArray(res) && res.length > 0) {
  427. this.eleTabs = res;
  428. this.hasData = true;
  429. this.activeChartInfo =
  430. this.eleTabs.find((item) => item.name === this.eleKey) ||
  431. this.eleTabs[0];
  432. this.eleActive = this.eleTabs.indexOf(this.activeChartInfo);
  433. const key = this.activeChartInfo.unit ? this.activeChartInfo.name + '(' + this.activeChartInfo.unit + ')' : this.activeChartInfo.name
  434. const keyValue = this.getKeyByName(key)
  435. this.activeChartInfo.key = keyValue
  436. this.$nextTick(() => {
  437. this.initChart();
  438. });
  439. } else {
  440. this.eleTabs = [];
  441. this.hasData = false;
  442. }
  443. });
  444. },
  445. // 历史数据
  446. getObData() {
  447. this.$myRequest({
  448. url: "/api/api_gateway?method=greenhouse.env_first.history_data",
  449. data: {
  450. device_id: this.deviceInfo.devBid,
  451. start: String(
  452. Math.floor(new Date(this.startDate + " 00:00:00").getTime() / 1000),
  453. ),
  454. end: String(
  455. Math.floor(new Date(this.endDate + " 23:59:59").getTime() / 1000),
  456. ),
  457. page: this.currentPage,
  458. page_size: this.pageSize,
  459. },
  460. }).then((res) => {
  461. console.log("getObData:", res);
  462. const columns = res.title;
  463. const data = res.table;
  464. const newData = data.map((item) => {
  465. return this.processData(item);
  466. });
  467. const resCol = this.convertDynamic(columns, (prop, val) =>
  468. Array.isArray(val) ? `${val[1]}${val[3] || ""}` : val,
  469. );
  470. this.columns = resCol;
  471. this.titles = res?.title || [];
  472. this.tableList = newData;
  473. this.total = res.total;
  474. console.log("tableList:", this.columns);
  475. console.log("tableList", this.tableList);
  476. });
  477. },
  478. convertDynamic(data, getLabelValue) {
  479. if (!data || typeof data !== "object") return [];
  480. const result = [];
  481. const keys = Object.keys(data);
  482. for (const prop of keys) {
  483. const arr = data[prop];
  484. const value = getLabelValue(prop, arr, data);
  485. if (value !== undefined && value !== null) {
  486. result.push({
  487. label: String(value),
  488. prop,
  489. align: "center",
  490. });
  491. }
  492. }
  493. return result;
  494. },
  495. processData(data) {
  496. return Object.entries(data).reduce((acc, [key, value]) => {
  497. acc[key] = Array.isArray(value) ? value[0] : value;
  498. return acc;
  499. }, {});
  500. },
  501. },
  502. };
  503. </script>
  504. <style lang="scss">
  505. .ele-details-page {
  506. background:
  507. linear-gradient(180deg, #ffffff00 0%, #f5f6fa 23.64%, #f5f6fa 100%),
  508. linear-gradient(102deg, #bfeadd 6.77%, #b8f1e7 40.15%, #b9eef5 84.02%);
  509. min-height: 100vh;
  510. padding: 0 32rpx;
  511. padding-top: 98rpx;
  512. }
  513. .nav-title{
  514. text-align: center;
  515. }
  516. .date-picker {
  517. display: flex;
  518. align-items: center;
  519. justify-content: space-between;
  520. background-color: #fff;
  521. border-radius: 40rpx;
  522. padding: 16rpx 24rpx;
  523. margin-bottom: 36rpx;
  524. font-size: 28rpx;
  525. color: #999;
  526. margin-top: 46rpx;
  527. .date-icon {
  528. width: 32rpx;
  529. height: 32rpx;
  530. }
  531. }
  532. .separator {
  533. margin: 0 16rpx;
  534. }
  535. .echarts-board {
  536. padding: 32rpx;
  537. border-radius: 16rpx;
  538. background: #fff;
  539. margin-bottom: 24rpx;
  540. position: relative;
  541. .period-tabs {
  542. width: 350rpx;
  543. height: 64rpx;
  544. display: flex;
  545. justify-content: space-between;
  546. align-items: center;
  547. margin: auto;
  548. margin-bottom: 12rpx;
  549. border-radius: 32rpx;
  550. background: #f1f4f8;
  551. padding: 8rpx 10rpx;
  552. color: #303133;
  553. font-family: "Source Han Sans CN VF";
  554. font-size: 26rpx;
  555. font-style: normal;
  556. font-weight: 400;
  557. line-height: normal;
  558. .tab-item {
  559. padding: 5rpx 24rpx;
  560. height: 48rpx;
  561. line-height: 48rpx;
  562. border-radius: 32rpx;
  563. }
  564. .active {
  565. background: #fff;
  566. }
  567. }
  568. .element-tabs {
  569. display: flex;
  570. justify-content: space-between;
  571. align-items: center;
  572. overflow-x: auto;
  573. white-space: nowrap;
  574. .ele-board {
  575. flex: 1;
  576. display: flex;
  577. align-items: center;
  578. overflow-x: auto;
  579. overflow-y: hidden;
  580. white-space: nowrap;
  581. }
  582. .ele-item {
  583. position: relative;
  584. color: #999999;
  585. font-size: 28rpx;
  586. font-weight: 400;
  587. white-space: nowrap;
  588. margin-right: 16rpx;
  589. padding: 14rpx 16rpx;
  590. cursor: pointer;
  591. }
  592. .ele-active {
  593. color: #303133;
  594. font-weight: 500;
  595. &::after {
  596. content: "";
  597. position: absolute;
  598. left: 50%;
  599. transform: translateX(-50%);
  600. bottom: 4rpx;
  601. display: block;
  602. width: 30rpx;
  603. height: 8rpx;
  604. border-radius: 4rpx;
  605. background: #1fc676;
  606. }
  607. }
  608. .fold-icon {
  609. width: 48rpx;
  610. border-left: 2px solid #999;
  611. padding-left: 16rpx;
  612. margin-left: 16rpx;
  613. cursor: pointer;
  614. display: none;
  615. }
  616. }
  617. /* 展开后的要素容器样式 */
  618. .expanded-elements {
  619. position: absolute;
  620. top: 126rpx;
  621. left: 0;
  622. right: 0;
  623. background: #f5f7fa;
  624. border-radius: 12rpx;
  625. padding: 16rpx;
  626. display: flex;
  627. flex-wrap: wrap;
  628. gap: 16rpx;
  629. z-index: 10;
  630. box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
  631. }
  632. .expanded-item {
  633. flex: 0 0 calc(33.33% - 16rpx);
  634. text-align: center;
  635. padding: 16rpx 0;
  636. border-radius: 8rpx;
  637. color: #999999;
  638. font-size: 26rpx;
  639. background: #ffffff;
  640. cursor: pointer;
  641. transition: all 0.3s ease;
  642. }
  643. .expanded-item.ele-active {
  644. color: #1fc676;
  645. background: #e6f7ef;
  646. font-weight: 500;
  647. }
  648. .chart-container {
  649. border-radius: 16rpx;
  650. margin-bottom: 24rpx;
  651. position: relative;
  652. padding: 10rpx;
  653. overflow: hidden;
  654. height: 336rpx;
  655. z-index:0;
  656. .chart {
  657. width: 100%;
  658. height: 336rpx;
  659. }
  660. }
  661. .no-data {
  662. border-radius: 16rpx;
  663. margin-bottom: 24rpx;
  664. padding: 10rpx;
  665. height: 336rpx;
  666. display: flex;
  667. align-items: center;
  668. justify-content: center;
  669. background-color: #f9f9f9;
  670. text {
  671. color: #999;
  672. font-size: 32rpx;
  673. }
  674. }
  675. .stats-panel {
  676. display: flex;
  677. justify-content: space-between;
  678. background-color: #f1f4f8;
  679. border-radius: 16rpx;
  680. padding: 24rpx 64rpx;
  681. .stat-item {
  682. display: flex;
  683. flex-direction: column;
  684. align-items: center;
  685. .label {
  686. color: #656565;
  687. font-size: 24rpx;
  688. font-weight: 400;
  689. }
  690. .value {
  691. font-size: 40rpx;
  692. font-weight: bold;
  693. }
  694. .unit {
  695. color: #999999;
  696. font-size: 20rpx;
  697. }
  698. .red {
  699. color: #fb4e52;
  700. }
  701. }
  702. }
  703. }
  704. .history-section {
  705. background-color: #fff;
  706. border-radius: 16rpx;
  707. padding: 24rpx 32rpx;
  708. .section-title {
  709. font-size: 28rpx;
  710. font-weight: bold;
  711. margin-bottom: 16rpx;
  712. color: #303133;
  713. }
  714. .table-wrap {
  715. display: flex;
  716. width: 100%;
  717. box-sizing: border-box;
  718. margin: 20rpx 0;
  719. color: #042118;
  720. font-family: "Source Han Sans CN VF";
  721. font-size: 24rpx;
  722. font-style: normal;
  723. font-weight: 400;
  724. line-height: normal;
  725. .fixed-column {
  726. width: 250rpx;
  727. .table-cell {
  728. width: 100%;
  729. white-space: nowrap;
  730. }
  731. }
  732. .table-bg {
  733. width: 16rpx;
  734. background: linear-gradient(270deg, #ffffff33 0%, #9598a433 100%);
  735. }
  736. .scroll-column {
  737. flex: 1;
  738. height: auto;
  739. overflow: hidden;
  740. margin-left: -10rpx;
  741. }
  742. .scroll-content {
  743. min-width: 100%;
  744. width: fit-content;
  745. display: flex;
  746. flex-direction: column;
  747. .table-row {
  748. display: flex;
  749. .table-cell {
  750. flex: 1;
  751. }
  752. }
  753. }
  754. .table-cell {
  755. width: 160rpx;
  756. height: 64rpx;
  757. line-height: 64rpx;
  758. text-align: center;
  759. border-bottom: 2px solid #e4e7ed;
  760. box-sizing: border-box;
  761. }
  762. .table-cell.header {
  763. background: #f6f8fc;
  764. }
  765. }
  766. .pagination {
  767. display: flex;
  768. align-items: center;
  769. justify-content: space-between;
  770. margin-top: 24rpx;
  771. .page-item {
  772. width: 104rpx;
  773. height: 48rpx;
  774. color: #656565;
  775. font-size: 24rpx;
  776. line-height: 48rpx;
  777. text-align: center;
  778. border: 2rpx solid #e4e7ed;
  779. border-radius: 8rpx;
  780. }
  781. .page-item.disabled {
  782. color: #999;
  783. border-color: #e4e7ed;
  784. background-color: #f5f7fa;
  785. }
  786. .next {
  787. color: #0bbc58;
  788. border: 2rpx solid #0bbc58;
  789. }
  790. .next.disabled {
  791. color: #999;
  792. border-color: #e4e7ed;
  793. background-color: #f5f7fa;
  794. }
  795. .page-info {
  796. color: #999999;
  797. font-family: "Source Han Sans CN VF";
  798. font-size: 24rpx;
  799. font-style: normal;
  800. font-weight: 400;
  801. line-height: normal;
  802. .curret-page {
  803. color: #303133;
  804. }
  805. }
  806. }
  807. }
  808. ::v-deep .u-calendar__action {
  809. display: flex;
  810. justify-content: center;
  811. }
  812. </style>