detail.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  1. <template>
  2. <view class="device-detail">
  3. <view class="device-detail__header">
  4. <u-icon
  5. size="36"
  6. class="arrow-left"
  7. name="arrow-left"
  8. @click="handleBack"
  9. ></u-icon>
  10. {{ deviceInfo.name }}
  11. </view>
  12. <view class="operation" @click.stop="isShowOperation = !isShowOperation">操作</view>
  13. <view class="operation-container" v-if="isShowOperation" @click="closeOperationHandler">
  14. <view class="operation-background"></view>
  15. <view class="operation-content">
  16. <view class="operation-item" v-if="isShowPhoto" @click="handlePhotoClick">
  17. <image :src="photoIcon" class="operation-icon"></image>
  18. 拍照
  19. </view>
  20. <view class="operation-item" @click="handleServiceClick">
  21. <image :src="serviceIcon" class="operation-icon"></image>
  22. 维修
  23. </view>
  24. <view class="operation-item" @click="handleSettingClick">
  25. <image :src="settingIcon" class="operation-icon"></image>
  26. 设置
  27. </view>
  28. <view class="operation-item" @click="handleSimClick">
  29. <image :src="simIcon" class="operation-icon"></image>
  30. SIM卡
  31. </view>
  32. <view class="operation-item" @click="modification">
  33. <image :src="editIcon" class="operation-icon"></image>
  34. 修改
  35. </view>
  36. </view>
  37. </view>
  38. <view class="device-detail__body">
  39. <DeviceCard
  40. :dataSource="deviceInfo"
  41. :collectTime="time"
  42. :title="deviceInfo.name"
  43. :deviceType="deviceType"
  44. />
  45. <view class="tabs">
  46. <view class="tab-container" v-if="isShowTab">
  47. <view class="tab-item" :class="activeTab === 'viewImage'?'active':''" @click="handleTabClick('viewImage')">
  48. 图像数据
  49. </view>
  50. <view class="tab-item" :class="activeTab === 'pestAnalysis'?'active':''" @click="handleTabClick('pestAnalysis')">
  51. 鼠情分析
  52. </view>
  53. <view class="tab-item" :class="activeTab === 'aiAnalysis'?'active':''" @click="handleTabClick('aiAnalysis')">
  54. 设备预警
  55. </view>
  56. <view class="tab-item" :class="activeTab === 'deviceData'?'active':''" @click="handleTabClick('deviceData')">
  57. 设备数据
  58. </view>
  59. </view>
  60. <view class="select-timer-container">
  61. <view class="select-year">
  62. <view class="select-year-item" @click="showPicker = true">
  63. {{ currentYear }}
  64. <u-icon name="arrow-down" size="18" class="arrow-down"></u-icon>
  65. </view>
  66. </view>
  67. <view class="tabs-timer-container" @click="showCalendar">
  68. <view class="tabs-timer-item">
  69. {{startDate}}
  70. </view>
  71. <view class="tabs-timer-item">
  72. {{endDate}}
  73. </view>
  74. <u-icon name="calendar" size="36" class="calendar-icon"></u-icon>
  75. </view>
  76. </view>
  77. </view>
  78. <view v-show="activeTab === 'pestAnalysis'" class="tab-content">
  79. <PestDiscern
  80. :total="total"
  81. :pest_order="pest_order"
  82. />
  83. <PestEchart
  84. :pest_order="pest_order"
  85. @getInfo="getInfo"
  86. :endDate="endDate"
  87. :d_id="deviceInfo.d_id"
  88. :day="day"
  89. :pest="pest"
  90. />
  91. <RodentAnalysis :active="activeTab === 'pestAnalysis'" />
  92. <PestArchive
  93. :pest_info="pestInfo"
  94. />
  95. <!-- <view v-if="!pests.length">
  96. <u-empty text="暂无数据"></u-empty>
  97. </view> -->
  98. </view>
  99. <view v-if="activeTab === 'viewImage'">
  100. <!-- 实现下拉加载 -->
  101. <scroll-view class="scroll-view" scroll-y style="height: 60vh;" @scrolltolower="handleReachBottom">
  102. <photoImage
  103. :images="imageList"
  104. :pestList="pestList"
  105. :disableShow="disableShow"
  106. @changeTab="changeTab"
  107. :currentYear="currentYear"
  108. :deviceInfo="deviceInfo"
  109. />
  110. </scroll-view>
  111. </view>
  112. <view v-if="activeTab === 'aiAnalysis'">
  113. <AiChat
  114. :pestMessage="pestMessage"
  115. />
  116. </view>
  117. <view v-if="activeTab === 'deviceData'">
  118. <DeviceData
  119. :deviceStatic="deviceStatic"
  120. :deviceInfo="deviceInfo"
  121. :polylineList="polylineList"
  122. :deviceHistoryList="deviceHistoryList"
  123. :totalPage="totalPage"
  124. :currentPage="page"
  125. :page_size="page_size"
  126. @prevPage="prevPage"
  127. @nextPage="nextPage"
  128. />
  129. </view>
  130. </view>
  131. <u-calendar v-model="show" :mode="mode" range-color="#999" btn-type="success" active-bg-color="#0BBC58" range-bg-color="rgba(11,188,88,0.13)" @change="handleChange" :max-date="maxDate" :min-date="minDate"></u-calendar>
  132. <u-picker v-model="showPicker" mode="selector" :range="selectorRange" range-key="id" :default-selector="[0]" @confirm="confirmHandler"></u-picker>
  133. </view>
  134. </template>
  135. <script>
  136. import DeviceCard from './components/DeviceCard.vue';
  137. import PestDiscern from './components/pestDiscern.vue';
  138. import PestEchart from './components/pestEchart.vue';
  139. import PestArchive from './components/pestArchive.vue';
  140. import photoImage from './components/photoImage.vue';
  141. import DeviceData from './components/deviceData.vue';
  142. import AiChat from './components/aiChat.vue';
  143. import RodentAnalysis from './components/rodentAnalysis.vue';
  144. export default {
  145. components: {
  146. DeviceCard,
  147. PestDiscern,
  148. AiChat,
  149. PestEchart,
  150. PestArchive,
  151. photoImage,
  152. DeviceData,
  153. RodentAnalysis,
  154. },
  155. data(){
  156. return {
  157. isShowTab:false,
  158. showPicker: false,
  159. disableShow: false,
  160. isShowOperation: false,
  161. photoIcon:'https://s3.hnyfwlw.com/webstaticimg/bigdata_app/newImg/home/photoIcon.png',
  162. editIcon:'https://s3.hnyfwlw.com/webstaticimg/bigdata_app/newImg/home/editIcon.png',
  163. serviceIcon:'https://s3.hnyfwlw.com/webstaticimg/bigdata_app/newImg/home/serviceIcon.png',
  164. simIcon:'https://s3.hnyfwlw.com/webstaticimg/bigdata_app/newImg/home/simIcon.png',
  165. settingIcon:'https://s3.hnyfwlw.com/webstaticimg/bigdata_app/newImg/home/settingIcon.png',
  166. totalPage:0,
  167. currentYear: new Date().getFullYear(),
  168. selectorRange: [],
  169. maxDate: this.formatDate(new Date()),
  170. minDate: this.formatDate(new Date(new Date().getFullYear(), 0, 1)),
  171. show: false,
  172. showSim: false,
  173. // 当前日期向前推30天 格式2026-01-01 月份和日期小于10的时候前面加个0
  174. startDate: this.formatDate(new Date(new Date().getTime() - 30 * 24 * 60 * 60 * 1000)),
  175. endDate: this.formatDate(new Date()),
  176. mode: 'range',
  177. imageList: [],
  178. pest_order:{},
  179. pestMessage:'',
  180. deviceInfo: {},
  181. pestInfo: {},
  182. time: '',
  183. activeTab: 'pestAnalysis',
  184. deviceType: '',
  185. location: '',
  186. total: 0,
  187. imgTotal: 0,
  188. day: [],
  189. pest: [],
  190. page:1,
  191. is_pest:'',
  192. page_size:24,
  193. pestList:[],
  194. pest_names:'',
  195. pests:[],
  196. polylineList:[],
  197. isShowPhoto:false,
  198. deviceHistoryList:[],
  199. deviceStatic:{}
  200. }
  201. },
  202. onLoad(options){
  203. this.deviceInfo = JSON.parse(options.info);
  204. this.getPestAnalysis();
  205. this.isShow();
  206. const currentYear = new Date().getFullYear();
  207. this.selectorRange = [];
  208. for(let i = 0;i<50;i++){
  209. const item = {
  210. label: currentYear - i,
  211. id: currentYear - i
  212. }
  213. this.selectorRange.push(item);
  214. }
  215. },
  216. methods: {
  217. formatePestMessage(data) {
  218. if (data.length === 0) {
  219. this.pestMessage = '';
  220. return;
  221. }
  222. this.pestMessage = `当前设备位置为${this.deviceInfo.address},在${this.startDate}至${this.endDate} 监测到的害虫如下:`;
  223. data.map((item, index) => {
  224. if(index === data.length - 1){
  225. this.pestMessage += `${item.name}:${item.value}头.`;
  226. } else {
  227. this.pestMessage += `${item.name}:${item.value}头,`;
  228. }
  229. });
  230. },
  231. handleReachBottom(){
  232. if (this.activeTab === 'viewImage') {
  233. if(this.imageList.length >= this.imgTotal){
  234. return
  235. }
  236. this.initImageList(true);
  237. }
  238. },
  239. handleSimClick(){
  240. // this.showSim = true;
  241. //`/pages/deviceDetails/weatherStation/${type}?deviceInfo=${encodeURIComponent(JSON.stringify(this.deviceInfo))}`
  242. uni.navigateTo({
  243. url:
  244. '/pages/deviceDetails/weatherStation/simDetail?deviceInfo=' +
  245. encodeURIComponent(JSON.stringify(this.deviceInfo))
  246. });
  247. },
  248. modification() {
  249. uni.navigateTo({
  250. url:
  251. '/pages/equipList2/seabox/modification?data=' +
  252. JSON.stringify(this.deviceInfo) +
  253. '&id=' +
  254. this.deviceInfo.type,
  255. });
  256. },
  257. async handlePhotoClick(){
  258. const res = await this.$myRequest({
  259. url: '/api/api_gateway?method=forecast.send_control.admin_device_control',
  260. method: 'POST',
  261. data: {
  262. device_type_id: this.deviceInfo.type,
  263. d_id: this.deviceInfo.d_id,
  264. cmd: 'takephoto',
  265. },
  266. });
  267. if(res){
  268. this.$u.toast('拍照成功')
  269. }
  270. },
  271. handleServiceClick(){
  272. uni.navigateTo({
  273. url: '/pages/afterSale/addafter?d_id=' + this.deviceInfo.d_id +'&device_id='+this.deviceInfo.id + '&device_type=' + this.deviceInfo.type,
  274. })
  275. },
  276. handleSettingClick(){
  277. uni.navigateTo({
  278. url: '/pages/cbd/deviceControl?deviceId=' + this.deviceInfo.id + '&d_id=' + this.deviceInfo.d_id,
  279. });
  280. },
  281. closeOperationHandler(){
  282. this.isShowOperation = false;
  283. },
  284. isShow(){
  285. // disable == 0 或者 device_model == 15 表示不可以查看
  286. if(!this.deviceInfo.d_id){
  287. return false;
  288. }
  289. let showStatus = true;
  290. if(this.deviceInfo.device_model == 15 || this.deviceInfo.device_model == 12){
  291. showStatus = false;
  292. }
  293. if(showStatus){
  294. this.activeTab = 'pestAnalysis';
  295. }else{
  296. this.activeTab = 'deviceData';
  297. }
  298. this.initAction();
  299. this.isShowTab = showStatus;
  300. if(this.deviceInfo.disable == 0){
  301. this.disableShow = false;
  302. if(showStatus){
  303. this.activeTab = 'viewImage';
  304. this.handleTabClick('viewImage');
  305. }
  306. }else{
  307. this.disableShow = true;
  308. }
  309. },
  310. prevPage(e){
  311. if(e == 1){
  312. return
  313. }
  314. this.page = e-=1;
  315. this.getDeviceHistoryData();
  316. },
  317. nextPage(e){
  318. if(e * this.page_size >= this.totalPage){
  319. return
  320. }
  321. this.page = e+=1;
  322. this.getDeviceHistoryData();
  323. },
  324. changeTab(pestList){
  325. let pest_names = pestList.map(item => item.pest_name);
  326. this.pest_names = pest_names.join(',');
  327. this.initImageList();
  328. },
  329. confirmHandler(e){
  330. this.currentYear = this.selectorRange[e].id;
  331. if(this.currentYear == new Date().getFullYear()){
  332. // 结束日期为this.endDate的月份和日期加上选择的年份
  333. const timeDate = this.currentYear + '-' + this.endDate.split('-')[1] + '-' + this.endDate.split('-')[2];
  334. this.endDate = this.formatDate(new Date(timeDate));
  335. // 开始日期为结束日期前30天
  336. this.startDate = this.formatDate(new Date(new Date(this.endDate).getTime() - 30 * 24 * 60 * 60 * 1000));
  337. this.maxDate = this.formatDate(new Date());
  338. this.minDate = this.formatDate(new Date(new Date().getFullYear(), 0, 1));
  339. }else{
  340. // 结束日期为this.endDate的月份和日期加上选择的年份
  341. const timeDate = this.currentYear + '-' + this.endDate.split('-')[1] + '-' + this.endDate.split('-')[2];
  342. this.endDate = this.formatDate(new Date(timeDate));
  343. // 开始日期为结束日期前30天
  344. this.startDate = this.formatDate(new Date(new Date(this.endDate).getTime() - 30 * 24 * 60 * 60 * 1000));
  345. this.maxDate = this.formatDate(new Date(this.currentYear, 11, 31));
  346. this.minDate = this.formatDate(new Date(this.currentYear, 0, 1));
  347. }
  348. this.initAction();
  349. this.showPicker = false;
  350. },
  351. getInfo(info){
  352. this.pestInfo = info;
  353. },
  354. // 格式化日期为YYYY-MM-DD格式,月份和日期小于10时前面加0
  355. formatDate(date) {
  356. const year = date.getFullYear();
  357. const month = String(date.getMonth() + 1).padStart(2, '0');
  358. const day = String(date.getDate()).padStart(2, '0');
  359. return `${year}-${month}-${day}`;
  360. },
  361. handleChange(e){
  362. this.startDate = e.startDate;
  363. this.endDate = e.endDate;
  364. this.page = 1;
  365. this.initAction();
  366. },
  367. showCalendar(){
  368. this.show = true;
  369. },
  370. handleBack() {
  371. uni.navigateBack({
  372. delta: 1
  373. });
  374. },
  375. initAction(){
  376. // this.pest_order =
  377. if(this.activeTab === 'pestAnalysis'){
  378. this.getPestAnalysis();
  379. }else if(this.activeTab === 'aiAnalysis'){
  380. this.getAiAnalysis();
  381. }else if(this.activeTab === 'viewImage'){
  382. this.initPest();
  383. this.initImageList();
  384. }else if(this.activeTab === 'deviceData'){
  385. this.getDeviceData();
  386. this.getPolylineData();
  387. this.getDeviceHistoryData();
  388. }
  389. },
  390. getAiAnalysis(){
  391. },
  392. handleTabClick(tab) {
  393. this.activeTab = tab;
  394. this.initAction();
  395. },
  396. async getDeviceData(){
  397. const res = await this.$myRequest({
  398. url: '/api/api_gateway?method=forecast.worm_lamp.device_status_data',
  399. method: 'POST',
  400. data: {
  401. device_id: this.deviceInfo.id,
  402. },
  403. });
  404. this.deviceStatic = res;
  405. },
  406. async initImageList(isLoadMore){
  407. if(isLoadMore){
  408. this.page++;
  409. }
  410. uni.showLoading({
  411. title: '加载中',
  412. })
  413. const res = await this.$myRequest({
  414. url: '/api/api_gateway?method=forecast.new_cbd.photo_list',
  415. method: 'POST',
  416. data: {
  417. page:this.page,
  418. page_size:this.page_size,
  419. device_id: this.deviceInfo.id,
  420. is_pest: this.is_pest,
  421. identify_model: 'B',
  422. pest_names: this.pest_names,
  423. time_begin: this.formatDate(new Date(this.startDate)) + ' 00:00:00',// 格式化开始时间YYYY-MM-DD HH:MM:SS
  424. time_end: this.formatDate(new Date(this.endDate)) + ' 23:59:59',// 格式化结束时间YYYY-MM-DD HH:MM:SS
  425. },
  426. });
  427. const data = res?.data || [];
  428. uni.hideLoading();
  429. this.imgTotal = res?.num || 0;
  430. if (isLoadMore) {
  431. this.imageList = [...this.imageList, ...data];
  432. } else {
  433. this.imageList = data;
  434. }
  435. },
  436. async initPest(){
  437. const res = await this.$myRequest({
  438. url: '/api/api_gateway?method=forecast.new_cbd.pest_type_list',
  439. method: 'POST',
  440. data:{
  441. page:1,
  442. page_size:999999,
  443. device_id: this.deviceInfo.id,
  444. identify_model: 'B',
  445. time_begin: this.formatDate(new Date(this.startDate)) + ' 00:00:00',// 格式化开始时间YYYY-MM-DD HH:MM:SS
  446. time_end: this.formatDate(new Date(this.endDate)) + ' 23:59:59',// 格式化结束时间YYYY-MM-DD HH:MM:SS
  447. },
  448. });
  449. const data = res?.data || [];
  450. this.pestList = data
  451. },
  452. async getPolylineData(){
  453. const res = await this.$myRequest({
  454. url: '/api/api_gateway?method=forecast.worm_lamp.device_polyline_data',
  455. method: 'POST',
  456. data: {
  457. device_type_id: this.deviceInfo.type_id,
  458. d_id: this.deviceInfo.d_id,
  459. start_time: new Date(this.startDate + ' 00:00:00').getTime()/1000,// 转成毫秒
  460. end_time: new Date(this.endDate + ' 23:59:59').getTime()/1000,
  461. },
  462. });
  463. const data = res || [];
  464. this.polylineList = data
  465. },
  466. async getDeviceHistoryData(){
  467. const res = await this.$myRequest({
  468. url: '/api/api_gateway?method=forecast.worm_lamp.device_history_data',
  469. method: 'POST',
  470. data: {
  471. device_type_id: this.deviceInfo.type_id,
  472. device_id: this.deviceInfo.id,
  473. start_time: new Date(this.startDate + ' 00:00:00').getTime()/1000,
  474. end_time: new Date(this.endDate + ' 23:59:59').getTime()/1000,
  475. page: this.page,
  476. page_size: this.page_size,
  477. },
  478. });
  479. const data = res?.data || [];
  480. this.totalPage = res.counts;
  481. this.deviceHistoryList = data
  482. },
  483. async getPestAnalysis(){
  484. const res = await this.$myRequest({
  485. url: '/api/api_gateway?method=forecast.cbd_analysis.analysis_pest_result',
  486. method: 'POST',
  487. data: {
  488. d_id: this.deviceInfo.d_id,
  489. start: this.startDate,
  490. end: this.endDate,
  491. model: 'B'
  492. },
  493. });
  494. console.log(res,'resresres')
  495. const pest_order = res?.pest_order;
  496. this.getInfo({});
  497. let total = 0;
  498. this.pests = [];
  499. const data = [];
  500. for(let key in pest_order){
  501. total += pest_order[key] || 0;
  502. this.pests.push({
  503. name: key,
  504. percent: (pest_order[key] / total) * 100
  505. })
  506. data.push({
  507. name: key,
  508. value: pest_order[key] || 0
  509. })
  510. }
  511. this.pest_order = pest_order;
  512. this.formatePestMessage([...data.reverse()]);
  513. this.day = res?.day || [];
  514. const pest = res?.pest || [];
  515. this.pest = pest;
  516. // pest.forEach(p =>{
  517. // for(let i = 0;i< p.length;i++){
  518. // this.pest.push(p[i]);
  519. // }
  520. // })
  521. this.total = total;
  522. }
  523. }
  524. }
  525. </script>
  526. <style scoped lang="scss">
  527. ::v-deep .u-calendar__action{
  528. display:flex;
  529. justify-content: space-between;
  530. }
  531. ::v-deep .u-hover-class{
  532. .u-calendar__content__item__inner{
  533. color:#aaa !important;
  534. }
  535. }
  536. .operation-container{
  537. position: fixed;
  538. right: 0;
  539. top: 0;
  540. width: 100%;
  541. height: 100%;
  542. z-index: 99;
  543. }
  544. .operation{
  545. position: fixed;
  546. top: 260rpx;
  547. right: 0;
  548. z-index: 999;
  549. width:48rpx;
  550. height: 100rpx;
  551. line-height: 50rpx;
  552. border-radius: 8px 0 0 8px;
  553. border-top: 4rpx solid #FFF;
  554. border-bottom: 4rpx solid #FFF;
  555. border-left: 4rpx solid #FFF;
  556. background: #dddfe6a3;
  557. color: #515153;
  558. text-align: center;
  559. font-family: "Source Han Sans CN VF";
  560. font-size: 24rpx;
  561. font-weight: 500;
  562. writing-mode: vertical-rl;
  563. }
  564. .operation-background{
  565. position: fixed;
  566. right: 0;
  567. top: 0;
  568. width: 100%;
  569. height: 100%;
  570. z-index: 998;
  571. background: #00000040;
  572. }
  573. .operation-content{
  574. position: fixed;
  575. top: 240rpx;
  576. right: 80rpx;
  577. height: 126rpx;
  578. display: flex;
  579. padding: 16rpx 32rpx;
  580. align-items: center;
  581. gap: 64rpx;
  582. z-index: 999;
  583. border-radius: 32rpx;
  584. border: 2rpx solid #FFF;
  585. background: #FFF;
  586. backdrop-filter: blur(8rpx);
  587. .operation-item{
  588. display: flex;
  589. flex-direction: column;
  590. align-items: center;
  591. justify-content: center;
  592. color: #333333;
  593. text-align: center;
  594. font-family: "Source Han Sans CN VF";
  595. font-size: 24rpx;
  596. font-weight: 400;
  597. }
  598. .operation-icon{
  599. width: 58rpx;
  600. height: 58rpx;
  601. }
  602. }
  603. .device-detail {
  604. display: flex;
  605. width: 100%;
  606. min-height: calc(100vh - 112rpx);
  607. padding-top: 112rpx;
  608. flex-direction: column;
  609. align-items: center;
  610. background: linear-gradient(180deg, #ffffff00 0%, #F5F6FA 23.64%, #F5F6FA 100%), linear-gradient(102deg, #BFEADD 6.77%, #B8F1E7 40.15%, #B9EEF5 84.02%);
  611. .device-detail__header {
  612. width: 100%;
  613. font-size: 28rpx;
  614. color: #999;
  615. color: #042118;
  616. font-family: 'Source Han Sans CN VF';
  617. font-weight: 700;
  618. position: relative;
  619. text-align: center;
  620. .arrow-left {
  621. position: absolute;
  622. left: 32rpx;
  623. margin-right: 12rpx;
  624. }
  625. }
  626. .device-detail__body {
  627. width: calc(100% - 64rpx);
  628. margin: 0 auto;
  629. border-radius: 16rpx;
  630. overflow-x: hidden;
  631. overflow-y: auto;
  632. // 隐藏滚动条
  633. -ms-overflow-style: none;
  634. scrollbar-width: none;
  635. }
  636. .tab-content{
  637. width: 100%;
  638. padding-bottom: 32rpx;
  639. }
  640. .tabs {
  641. background: #ffffff;
  642. margin: 24rpx 0;
  643. border-radius: 16rpx;
  644. padding: 16rpx 0;
  645. padding-top: 0;
  646. .tab-container{
  647. display: flex;
  648. width: 100%;
  649. height: 88rpx;
  650. line-height: 88rpx;
  651. text-align: center;
  652. font-size: 28rpx;
  653. font-weight: 700;
  654. color: #042118;
  655. font-family: 'Source Han Sans CN VF';
  656. }
  657. .select-timer-container{
  658. display:flex;
  659. align-items: center;
  660. padding-left: 32rpx;
  661. .select-year{
  662. width: 110rpx;
  663. text-align: center;
  664. height: 64rpx;
  665. border-radius: 32rpx;
  666. font-family: 'Source Han Sans CN VF';
  667. line-height: 64rpx;
  668. background: #F1F4F8;
  669. padding: 0 32rpx;
  670. .select-year-item{
  671. color: #656565;
  672. font-size: 24rpx;
  673. display: flex;
  674. align-items: center;
  675. justify-content: space-around;
  676. }
  677. }
  678. }
  679. .tabs-timer-container{
  680. display: flex;
  681. align-items: center;
  682. width: calc(100% - 256rpx);
  683. height: 64rpx;
  684. line-height: 64rpx;
  685. text-align: center;
  686. font-size: 24rpx;
  687. font-weight: 500;
  688. font-family: 'Source Han Sans CN VF';
  689. border-radius: 32rpx;
  690. background: #F1F4F8;
  691. padding: 0 32rpx;
  692. color: #656565;
  693. margin: 16rpx;
  694. position: relative;
  695. .tabs-timer-item{
  696. width: 42%;
  697. color: #656565;
  698. text-align: center;
  699. font-family: "Source Han Sans CN VF";
  700. font-size: 24rpx;
  701. font-weight: 400;
  702. }
  703. .calendar-icon{
  704. margin-left: 24rpx;
  705. }
  706. }
  707. .tab-item {
  708. flex: 1;
  709. color: #999999;
  710. text-align: center;
  711. font-family: "Source Han Sans CN VF";
  712. font-size: 28rpx;
  713. font-weight: 400;
  714. }
  715. .active{
  716. position: relative;
  717. color: #303133;
  718. text-align: center;
  719. font-family: "Source Han Sans CN VF";
  720. font-size: 28rpx;
  721. font-weight: 700;
  722. &::after {
  723. content: '';
  724. position: absolute;
  725. bottom: 0;
  726. left: 50%;
  727. -webkit-transform: translateX(-50%);
  728. transform: translateX(-50%);
  729. width: 36rpx;
  730. height: 36rpx;
  731. border: 6rpx solid #0BBC58;
  732. border-radius: 50%;
  733. border-color: transparent;
  734. border-bottom-color: #0BBC58;
  735. }
  736. }
  737. }
  738. }
  739. </style>