status.vue 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135
  1. <template>
  2. <view class="container">
  3. <view style="height: 20px;line-height:15px;padding: 2px;text-align: center;position: fixed;right: -5px;top:30px;z-index: 9999;background: rgb(243,157,116);color: white;border-radius: 5px;font-size: 10px;width: 120rpx;" @click="goBack">
  4. {{$t('charge.break')}}
  5. </view>
  6. <view v-if="locale == 'en'" style="height: 40px;line-height:15px;padding: 2px;text-align: center;position: fixed;right: -5px;top:120px;z-index: 9999;background: #1A87FF;color: white;border-radius: 5px;font-size: 10px;width: 120rpx;" @click="modifyPwd">
  7. {{$t('charge.modifypwd')}}
  8. </view>
  9. <view v-else style="height: 20px;line-height:15px;padding: 2px;text-align: center;position: fixed;right: -5px;top:120px;z-index: 9999;background: #1A87FF;color: white;border-radius: 5px;font-size: 10px;width: 120rpx;" @click="modifyPwd">
  10. {{$t('charge.modifypwd')}}
  11. </view>
  12. <view style=";position: relative;height: 250px;margin-top:2vh;">
  13. <view class="dtop">
  14. <view class="can">
  15. <view class="box">
  16. <view class="three">
  17. <view class="four"></view>
  18. <view class="five"></view>
  19. <view class="six"></view>
  20. </view>
  21. <view class="dot"></view>
  22. <view class="dot"></view>
  23. <view class="dot"></view>
  24. <view class="dot"></view>
  25. <view class="dot"></view>
  26. </view>
  27. <!-- <canvas id="c">-->
  28. <!-- </canvas>-->
  29. <view class="stip">
  30. <view class="p0" st=""></view>
  31. <view class="p1">
  32. <view v-if="portDetail.portStatus == 2">
  33. {{$t('charge.charging')}}
  34. </view>
  35. <view v-else-if="portDetail.portStatus == 6">
  36. {{$t('charge.planed')}}
  37. </view>
  38. <view v-else-if="portDetail.portStatus == 5">
  39. {{$t('charge.connected')}}
  40. </view>
  41. <view v-else>
  42. {{$t('charge.nocharge')}}
  43. </view>
  44. </view>
  45. </view>
  46. </view>
  47. </view>
  48. </view>
  49. <view class="dstatus">
  50. <view class="ditem">
  51. <image class="itemimg" src="/static/images/new/tmp.png"/>
  52. <view class="item-value">{{portDetail.dev_temper}}℃</view>
  53. <span class="item-text">{{$t('charge.devtemper')}}</span>
  54. </view>
  55. <view class="ditem">
  56. <image class="itemimg" src="/static/images/new/dianya.png"/>
  57. <view class="item-value">{{ portDetail.voltage }}V</view>
  58. <span class="item-text">{{$t('charge.voltage')}}</span>
  59. </view>
  60. <view class="ditem">
  61. <image class="itemimg" src="/static/images/new/dianliu.png"/>
  62. <view class="item-value" v-if="portDetail.voltage == 0">0A</view>
  63. <view class="item-value" v-else>{{portDetail.POWER/portDetail.voltage}}A</view>
  64. <span class="item-text">{{$t('charge.current')}}</span>
  65. </view>
  66. <view class="ditem">
  67. <image class="itemimg" src="/static/images/new/shjian.png"/>
  68. <view class="item-value">{{ portDetail.time }}{{ i18('分钟') }}</view>
  69. <span class="item-text">{{$t('charge.chargetime')}}</span>
  70. </view>
  71. <view class="ditem">
  72. <image class="itemimg" src="/static/images/new/gonglv.png"/>
  73. <view class="item-value">{{ portDetail.power }}W</view>
  74. <span class="item-text">{{$t('charge.power')}}</span>
  75. </view>
  76. <view class="ditem">
  77. <image class="itemimg" src="/static/images/new/dianliang.png"/>
  78. <view class="item-value">{{ portDetail.elec }} {{ i18('度') }}</view>
  79. <span class="item-text">{{$t('charge.elec')}}</span>
  80. </view>
  81. </view>
  82. <view class="dbtns">
  83. <view class="start" @click="toPage">
  84. <image style="width:25px;height: 25px;margin-right: 5px;" src="/static/images/new/start.png"/>
  85. <span>{{$t('charge.startcharge')}}</span>
  86. </view>
  87. <view class="get" @click="getInfo">
  88. <image style="width:25px;height: 25px;margin-right: 5px;" src="/static/images/new/get.png"/>
  89. <span>{{$t('charge.getinfo')}}</span>
  90. </view>
  91. </view>
  92. <view class="dtip">
  93. <view style="margin:10px 0px;color: #1A87FF;"><img style="width: 13px;height: 13px" src="/static/images/new/tip.png">{{i18('温馨提示')}}</view>
  94. <view>1,{{i18('桩控制最大输出电流,当功率没有达到请检查车的状态或者车的设置')}};</view>
  95. <view>2,{{i18('启动充电-&gt;设备管理->可设置设备最大输出电流')}}</view>
  96. <view>3,{{i18('为保障您远程启动正常充电,请确保枪头完全连接充电口,同时确认您的爱车处于立即充电状态下')}};</view>
  97. <view>4,{{i18('注意规范安全充电,停好车,锁好车。')}}</view>
  98. </view>
  99. <u-picker @cancel="showPort=false" @confirm="confirmPort" :show="showPort" :columns="portList" keyName="text"></u-picker>
  100. <u-picker @cancel="cancelPicker" @confirm="confirm" :show="showPlan" :columns="planCols" @change="changeHandler"></u-picker>
  101. <u-modal :show="showPwd" :confirmText="i18('确认')" :cancelText="i18('取消')" @confirm="inputPwd" @cancel="cancel" :showCancelButton="true" :title="$t('charge.modifypwd')" >
  102. <view class="slot-content">
  103. <view>
  104. <u--input
  105. type="number"
  106. :placeholder="$t('charge.oldpwd')"
  107. border="surround"
  108. v-model="oldPwd"
  109. ></u--input>
  110. </view>
  111. <view style="margin-top:5px">
  112. <u--input
  113. type="number"
  114. :placeholder="$t('charge.newpwd')"
  115. border="surround"
  116. v-model="pwd"
  117. ></u--input>
  118. </view>
  119. </view>
  120. </u-modal>
  121. </view>
  122. </template>
  123. <script>
  124. import {getDeviceInfo,getPortDetail,startCharge,stopCharge,sendPortDetailCmd,checkStatusChange,getPlanInfo,cancelPlan,parseDataObj,planCharge,getPwd,setPwd} from "@/utils/weitiandi/device/device.js";
  125. // #ifdef APP
  126. import ecUI from '@/utils/ecUI.js'
  127. import ecBLE from '@/utils/ecBLE/ecBLE.js'
  128. // #endif
  129. // #ifdef MP
  130. const ecUI = require('@/utils/ecUI.js')
  131. const ecBLE = require('@/utils/ecBLE/ecBLE.js')
  132. // #endif
  133. import i18 from '@/utils/i18.js'
  134. let ctx
  135. let isCheckScroll = true
  136. let isCheckRevHex = false
  137. let isCheckSendHex = false
  138. let sendData = ''
  139. export default {
  140. data() {
  141. return {
  142. locale:"",
  143. oldPwd:"",
  144. pwd:"",
  145. showPwd:false,
  146. planCols:[ ],
  147. columnData:[],
  148. showPlan:false,
  149. deviceInfo:{},
  150. visitTime:"",
  151. timer:null,
  152. showPort:false,
  153. portDetail:{portStatus:0,POWER:0,voltage:0},
  154. statusTimer:"",
  155. connected:false,
  156. scriptTask:null,
  157. choosePort:1,
  158. portList:[[{port:1,text:"端口一"}]],
  159. planInfo:null,
  160. days:["","周一","周二","周三","周四","周五","周六","周日"],
  161. textRevData: '',
  162. picker:null,
  163. firstInit:false,
  164. hasRight:false,
  165. startAutoCharge:true,
  166. }
  167. },
  168. computed: {
  169. imgUrl() {
  170. return getApp().globalData.config.imgUrl;
  171. }
  172. },
  173. onLoad() {
  174. this.locale = uni.getLocale();
  175. console.log("status comeing")
  176. this.checkPassword();
  177. },
  178. onShow(){
  179. uni.setNavigationBarTitle({
  180. title: this.$t('page.detail')
  181. })
  182. this.buletooth();
  183. },
  184. onUnload (){
  185. this.closeSocket();
  186. },
  187. methods: {
  188. i18(text){
  189. return i18(text)
  190. },
  191. toPage(){
  192. uni.navigateTo({
  193. url: '/pages/weitiandi/bluetooth/index'
  194. });
  195. },
  196. cancel(){
  197. this.showPwd = false;
  198. },
  199. modifyPwd(){
  200. this.showPwd = true;
  201. },
  202. inputPwd(){
  203. let rightPwd = uni.getStorageSync("pwd");
  204. if(!this.oldPwd){
  205. this.$modal.showToast("原密码不能为空");
  206. return;
  207. }
  208. if(rightPwd != this.oldPwd){
  209. this.$modal.showToast("原密码不对");
  210. return;
  211. }
  212. if(!this.pwd){
  213. this.$modal.showToast("密码不能为空");
  214. }else {
  215. setPwd(this.pwd);
  216. this.$modal.showToast("密码修改成功");
  217. this.goBack();
  218. }
  219. },
  220. confirm(e) {
  221. let value = e.value;
  222. console.log('confirm', value)
  223. let day = value[0];
  224. let date = new Date();
  225. let nowDay = date.getDate();
  226. let hour = value[1]+"";
  227. hour = parseInt(hour.substr(0,hour.length-1),10);
  228. let min = value[2]+"";
  229. min = parseInt(min.substr(0,min.length-1),10);
  230. let todayTotalMin = 0;
  231. let planDate = {min:min,hour:hour};
  232. let nowHour = date.getHours();
  233. let nowMin = date.getMinutes();
  234. let nowDate ={min:nowMin,hour:nowHour};
  235. if("今日" == day){
  236. todayTotalMin = this.getGapMin(planDate,nowDate)
  237. }else {
  238. let nowHour = date.getHours();
  239. let min = date.getMinutes();
  240. let maxDate ={min:59,hour:23};
  241. todayTotalMin = this.getGapMin(maxDate,nowDate);
  242. let minDate = {min:0,hour:0};
  243. todayTotalMin +=this.getGapMin(planDate,minDate);
  244. }
  245. console.log(todayTotalMin);
  246. this.cancelPicker();
  247. if(todayTotalMin<=0 || todayTotalMin>1440){
  248. this.$modal.showToast("最大预约时间为24小时");
  249. }else{
  250. planCharge(this.choosePort,todayTotalMin).then(res=>{
  251. this.getInfo(true);
  252. });
  253. }
  254. },
  255. getGapMin(date1,date2){
  256. let min1 = date1.min;
  257. let hour1 = date1.hour;
  258. let min2 = date2.min;
  259. let hour2 = date2.hour;
  260. let total1 = min1+hour1*60;
  261. let total2 = min2+hour2*60;
  262. return total1-total2;
  263. },
  264. cancelPicker(e) {
  265. this.showPlan = false
  266. },
  267. changeHandler(e){
  268. const {
  269. columnIndex,
  270. value,
  271. values, // values为当前变化列的数组内容
  272. index,
  273. // 微信小程序无法将picker实例传出来,只能通过ref操作
  274. picker = this.$refs.uPicker
  275. } = e
  276. let day = e.value[0];
  277. // 当第一列值发生变化时,变化第二列(后一列)对应的选项
  278. this.picker = picker;
  279. if (columnIndex === 0) {
  280. // picker为选择器this实例,变化第二列对应的选项
  281. if(day == "今日"){
  282. picker.setColumnValues(1, this.columnData[1])
  283. }else{
  284. picker.setColumnValues(1, this.columnData[0])
  285. }
  286. }
  287. },
  288. checkPassword(){
  289. },
  290. recon(){
  291. let self = this;
  292. ecUI.showLoading('设备连接中')
  293. let blueid = uni.getStorageSync('blueid');
  294. ecBLE.onBLEConnectionStateChange(res => {
  295. ecUI.hideLoading()
  296. if (res.ok) {
  297. self.buletooth();
  298. } else {
  299. uni.removeStorageSync('blueid');
  300. ecUI.showModal(
  301. '提示',
  302. '连接失败,errCode=' + res.errCode + ',errMsg=' + res.errMsg
  303. )
  304. }
  305. })
  306. ecBLE.createBLEConnection(blueid);
  307. },
  308. buletooth(){
  309. let self = this;
  310. ctx = this
  311. isCheckScroll = true
  312. isCheckRevHex = false
  313. isCheckSendHex = false
  314. sendData = ''
  315. //on disconnect
  316. ecBLE.onBLEConnectionStateChange(() => {
  317. uni.showModal({
  318. title: '提示',
  319. content: '蓝牙断开连接',
  320. confirmText:"点击重连",
  321. showCancel:false,
  322. success: function (res) {
  323. if (res.confirm) {
  324. self.recon()
  325. } else if (res.cancel) {
  326. console.log('用户点击取消');
  327. }
  328. }
  329. });
  330. })
  331. //receive data
  332. ecBLE.onBLECharacteristicValueChange((str, strHex) => {
  333. isCheckRevHex = true;
  334. let data =
  335. (isCheckRevHex ? strHex.replace(/[0-9a-fA-F]{2}/g, ' $&') : str)
  336. // console.log(data)
  337. self.$modal.closeLoading();
  338. console.log("收到消息:"+data);
  339. //AA 67 0D 05 00 00 00 00 00 00 00 00 00 25 E2 00 80
  340. data = parseDataObj(data);
  341. self.messageCallback(data);
  342. })
  343. self.getInfo();
  344. },
  345. messageCallback(data){
  346. let self = this;
  347. console.log(data);
  348. let type = data.type;
  349. let real_data = data.real_data;
  350. if(type == 103){
  351. self.portDetail = real_data
  352. self.portList = [[]];
  353. let port_first_status = self.portDetail["port_first_status"];
  354. let port_second_status = self.portDetail["port_second_status"]
  355. if(port_first_status){
  356. self.portList[0].push({port:1,text:"端口一"});
  357. }
  358. if(port_second_status){
  359. self.portList[0].push({port:2,text:"端口二"});
  360. }
  361. let choosePort = self.choosePort
  362. if(choosePort == 1){
  363. self.portDetail.portStatus = port_first_status;
  364. }else if(choosePort == 2){
  365. self.portDetail.portStatus = port_second_status;
  366. }
  367. self.$modal.closeLoading();
  368. }
  369. if(type == 116){
  370. self.$modal.closeLoading();
  371. self.getInfo();
  372. }
  373. if(type == 113){
  374. self.$modal.closeLoading();
  375. self.getInfo();
  376. }
  377. if(type == 96){
  378. }
  379. self.$forceUpdate();
  380. console.log('收到服务器内容:' + JSON.stringify(data));
  381. if(!this.firstInit){
  382. this.firstInit = true;
  383. let autoCharge = self.getAutoChargeValue()
  384. if(self.portDetail.portStatus == 5 && autoCharge == 1){
  385. self.startCharge();
  386. }
  387. }
  388. },
  389. getAutoChargeValue(){
  390. let autoCharge = uni.getStorageSync("autoCharge");
  391. if(!autoCharge ){
  392. autoCharge = 1;
  393. }
  394. return autoCharge;
  395. },
  396. planCharge(){
  397. if(this.portDetail.portStatus == 6){
  398. this.$modal.confirm("确认取消预约?").then(res=>{
  399. this.cancelPlan();
  400. })
  401. }else{
  402. this.toPlan()
  403. }
  404. },
  405. sendBlueData(){
  406. ecBLE.writeBLECharacteristicValue(tempSendData, false)
  407. },
  408. cancelPlan(){
  409. cancelPlan(this.choosePort).then(res=>{
  410. this.$modal.msg("取消成功");
  411. this.getInfo(true);
  412. })
  413. },
  414. getPlanInfo(){
  415. getPlanInfo(this.deviceInfo.deviceId,this.choosePort).then(res=>{
  416. let data = res.data;
  417. if(data != null){
  418. let planType = data.planType;
  419. if(planType == 1){//单次预约
  420. let planInfo = {};
  421. planInfo.runTime = data.runTime;
  422. this.planInfo = planInfo;
  423. this.planInfo.id = data.id;
  424. }else{
  425. let planInfo = {};
  426. planInfo.runTime = data.runTime;
  427. let repeatDays = data.repeatDays;
  428. let days = repeatDays.split(",")
  429. let strs = "";
  430. for (let i = 0; i < days.length; i++) {
  431. if(strs.length>0){
  432. strs+=",";
  433. }
  434. strs +=this.days[days[i]];
  435. }
  436. this.planInfo = planInfo;
  437. this.planInfo.runTime = strs+" "+data.repeatTime;
  438. this.planInfo.id = data.id;
  439. }
  440. }
  441. })
  442. },
  443. confirmPort(e){
  444. let value = e.value[0]
  445. this.choosePort = value.port;
  446. this.showPort = false;
  447. this.getInfo()
  448. },
  449. initSocket(key){
  450. let self = this;
  451. },
  452. toSet(){
  453. // this.closeSocket();
  454. uni.navigateTo({
  455. url: '/pages/weitiandi/bluetooth/setting'
  456. });
  457. },
  458. toPlan(){
  459. let arr = [];
  460. let date = new Date();
  461. let min = date.getMinutes();
  462. let hour = date.getHours();
  463. let arr1 = ["今日", "明日"];
  464. let arr2 = []
  465. let arr3 = [];
  466. let arr4 = [];
  467. for (let i = 0; i < hour; i++) {
  468. arr2.push(i+"时")
  469. }
  470. this.columnData[0] = arr2;
  471. for (let i = hour+1; i < 24; i++) {
  472. arr3.push(i+"时")
  473. }
  474. this.columnData[1] = arr3;
  475. for (let i = 0; i <= 59; i++) {
  476. arr4.push(i+"分")
  477. }
  478. this.planCols = [arr1, arr3, arr4]
  479. this.showPlan = true;
  480. },
  481. trigger(){
  482. let portStatus = this.portDetail.portStatus;
  483. if(portStatus == 2){//需要停止充电
  484. this.$modal.confirm("需要停止充电么?").then(res=>{
  485. this.stopCharge();
  486. })
  487. }else{
  488. if(portStatus == 1){
  489. this.$modal.msg("请先将充电枪插入后再点击充电");
  490. }
  491. if(portStatus == 5){
  492. this.$modal.confirm("确认开始充电么?").then(res=>{
  493. this.startCharge();
  494. })
  495. }else {
  496. this.$modal.msg("端口无法开始充电");
  497. }
  498. }
  499. },
  500. getInfo(flag) {
  501. // let str = "AA 67 0D 01 00 00 00 00 00 00 00 00 00 25 E2 00 80";
  502. // let data = parseDataObj(str);
  503. // this.messageCallback(data);
  504. //
  505. //
  506. this.$modal.loading("正在获取状态,请稍等...");
  507. if(flag){
  508. setTimeout(function (){
  509. sendPortDetailCmd().then(res => {
  510. })
  511. },500)
  512. }else{
  513. sendPortDetailCmd().then(res => {
  514. })
  515. }
  516. },
  517. stopCharge(){
  518. let self = this;
  519. this.deviceInfo.port = this.choosePort;
  520. stopCharge(this.deviceInfo).then(()=>{
  521. self.$modal.loading("停止成功");
  522. setTimeout((()=>{
  523. self.getInfo();
  524. }),1000);
  525. })
  526. },
  527. startCharge(){
  528. let self = this;
  529. this.deviceInfo.port = this.choosePort;
  530. startCharge(this.deviceInfo).then(res=>{
  531. self.$modal.loading("启动成功");
  532. setTimeout((()=>{
  533. self.getInfo();
  534. }),1000);
  535. })
  536. },
  537. getPortInfo(){
  538. this.startPortDetailTimer();
  539. },
  540. startPortDetailTimer(){
  541. let self = this;
  542. this.timer = setTimeout(function (){
  543. getPortDetail(self.deviceInfo,self.visitTime).then(res=>{
  544. let data = res.data;
  545. if(data != null){
  546. self.portDetail = data;
  547. self.checkStatusCheck();
  548. self.$modal.closeLoading();
  549. }else{
  550. self.startPortDetailTimer();
  551. }
  552. });
  553. },1000);
  554. },
  555. checkStatusCheck(){
  556. this.statusChangeTimer();
  557. },
  558. checkOnPage(){
  559. var pages = getCurrentPages() // 获取栈实例
  560. let currentRoute = pages[pages.length - 1].route; // 获取当前页面路由
  561. if("pages/weitiandi/device/index" != currentRoute){
  562. return false;
  563. }
  564. return true;
  565. },
  566. goBack(){
  567. this.closeSocket();
  568. uni.navigateBack({
  569. });
  570. },
  571. closeSocket(){
  572. ecBLE.onBLEConnectionStateChange(() => {})
  573. ecBLE.onBLECharacteristicValueChange(() => {})
  574. ecBLE.closeBLEConnection()
  575. uni.removeStorageSync('blueid');
  576. },
  577. statusChangeTimer(){
  578. let self = this;
  579. this.statusTimer = setTimeout(function(){
  580. if(!this.checkOnPage()){
  581. return;
  582. }
  583. checkStatusChange(self.deviceInfo,self.visitTime).then(res=>{
  584. let data = res.data;
  585. if(data != null){
  586. self.getInfo();
  587. }else{
  588. self.statusChangeTimer();
  589. }
  590. });
  591. },3000);
  592. }
  593. }
  594. }
  595. </script>
  596. <style>
  597. .container {
  598. background: rgb(249, 252, 255);
  599. inset: 0;
  600. position: absolute;
  601. }
  602. .header {
  603. position: relative;
  604. margin-top:4vw;
  605. }
  606. .header-status-desc {
  607. position: absolute;
  608. text-align: center;
  609. width: 100%;
  610. bottom:1vh;
  611. font-size: 5vw;
  612. font-weight: bold;
  613. color: #0E9F9B;
  614. margin-bottom: 5vw;
  615. }
  616. .header-status {
  617. font-weight: bold;
  618. text-align: center;
  619. }
  620. .chong-active {
  621. color: #0E9F9B
  622. }
  623. .header-img {
  624. width: 100%;
  625. padding: 5% 10%;
  626. text-align: center;
  627. }
  628. .header-img image {
  629. width: 100%;
  630. height: 23vh;
  631. }
  632. .info-body{
  633. background: #0E9F9B;
  634. height: 20vh;
  635. margin: 0 2%;
  636. border-radius: 1vw;
  637. margin-top:2vh;
  638. color: #F8FCFF;
  639. line-height: 3vh;
  640. }
  641. .info-content{
  642. display: inline-block;
  643. width: 23%;
  644. text-align: center;
  645. margin: 1%;
  646. margin-top:2.5vh;
  647. }
  648. .info-content-value{
  649. font-weight: bold;
  650. }
  651. .info-content-text{
  652. }
  653. .info-summary{
  654. display: flex;
  655. flex-direction: row;
  656. text-align: center;
  657. margin:3vh 0;
  658. }
  659. .summary{
  660. width: 33%;
  661. line-height: 2.5vh;
  662. }
  663. .charge-num{
  664. color: #0E9F9B;
  665. font-weight: bold;
  666. font-size: 4.5vw;
  667. }
  668. .charge-title{
  669. color: #B2B2B2;
  670. font-weight: 400;
  671. }
  672. .btn-image{
  673. width: 90%;
  674. height: 100%;
  675. }
  676. .info-bottom-btn{
  677. display: flex;
  678. flex-direction: row;
  679. text-align: center;
  680. position: relative;
  681. margin-top: 10vh
  682. ;
  683. }
  684. .btn-area{
  685. width: 50%;
  686. height: 50px;
  687. }
  688. .left{
  689. position: relative;
  690. left: 10px;
  691. text-align: right;
  692. }
  693. .right{
  694. text-align: left;
  695. position: relative;
  696. right: 10px;
  697. }
  698. .info-plan{
  699. text-align: center;
  700. color: #0E9F9B;
  701. margin-top:1vh;
  702. font-weight: 400;
  703. }
  704. .setting{
  705. position: fixed;
  706. right: -1px;
  707. top: 10vh;
  708. z-index: 999;
  709. background: rgb(227,243,245);
  710. color: #0E9F9B;
  711. font-size: 10px;
  712. border-radius: 5px;
  713. padding: 3px;
  714. }
  715. .port{
  716. height: 70px;
  717. background: #F8FCFF;
  718. border: 0px solid #F8FCFF;
  719. box-shadow: 0px 0px 6px 1px rgba(101,101,101,0.29);
  720. border-radius: 4px;
  721. margin:0 10px;
  722. position: relative;
  723. margin-top:10px;
  724. }
  725. .plan{
  726. height: 70px;
  727. background: #F8FCFF;
  728. border: 0px solid #F8FCFF;
  729. box-shadow: 0px 0px 6px 1px rgba(101,101,101,0.29);
  730. border-radius: 4px;
  731. margin:0 10px;
  732. position: relative;
  733. margin-top:15px;
  734. }
  735. .port-image{
  736. height: 40px;
  737. width: 40px;
  738. position: absolute;
  739. top:15px;
  740. left:20px;
  741. }
  742. .port-text{
  743. position: absolute;
  744. top:13px;
  745. left:75px;
  746. font-weight: bold;
  747. }
  748. .port-num{
  749. position: absolute;
  750. top:38px;
  751. left:75px;
  752. color: #B2B2B2;
  753. }
  754. .port-icon{
  755. position: absolute;
  756. top:30px;
  757. right:5px;
  758. width: 10px;
  759. height: 16px;
  760. }
  761. .port-icon image{
  762. width: 90%;
  763. }
  764. .body-bottom{
  765. padding:0 22px;
  766. }
  767. .body-bottom .info-content{
  768. width: 30%;
  769. }
  770. .bottom-control{
  771. height: 22vh;
  772. margin: 0 2%;
  773. margin-top:2vh;
  774. line-height: 3vh;
  775. background: #F8FCFF;
  776. border: 0px solid #F8FCFF;
  777. box-shadow: 0px 0px 6px 1px rgba(101,101,101,0.29);
  778. border-radius: 4px;
  779. padding:3%;
  780. }
  781. .control-btn{
  782. display: inline-block;;
  783. height: 60px;
  784. width: 25%;
  785. padding:10px 20px;
  786. text-align: center;
  787. font-size: 12px;
  788. color: black;
  789. }
  790. .control-btn .btn-image{
  791. }
  792. #box {
  793. /* width: 300px; */
  794. height: 280px;
  795. position: relative;
  796. /* 背景色 */
  797. /* background: #f7f6f6; */
  798. overflow: hidden;
  799. /* padding: 50px 0; */
  800. box-sizing: border-box;
  801. ;
  802. }
  803. .box {
  804. width: 100%;
  805. height: 100%;
  806. position: absolute;
  807. display: flex;
  808. justify-content: center;
  809. /* 此处尽量不要设置背景色,可以选择在父标签上设置背景色,否则没有黏黏的效果 */
  810. filter: url("#goo");
  811. }
  812. /* 电量文字 */
  813. .text {
  814. font-weight: 200;
  815. font-size: 20px;
  816. margin-top: 5px;
  817. text-align: center;
  818. color: #ff6600;
  819. }
  820. /* 电量文字 */
  821. .text span {
  822. font-size: 15px;
  823. }
  824. .three {
  825. width: 170px;
  826. height: 170px;
  827. border-radius: 300px;
  828. opacity: 1;
  829. position: absolute;
  830. top: 20px;
  831. z-index: 10;
  832. /* 从中心向外剪切圆,相当于掏空 */
  833. /* -webkit-mask: radial-gradient(transparent 95px, white 0px); */
  834. background: #ffffff;
  835. /* animation: ballZhuan 9s linear infinite; */
  836. overflow: hidden;
  837. box-shadow: 0px 0px 19px 1px #2196f3;
  838. }
  839. .four {
  840. width: 200px;
  841. height: 200px;
  842. border-radius: 80px;
  843. opacity: 0.3;
  844. position: absolute;
  845. top: 10px;
  846. z-index: 10;
  847. /* 从中心向外剪切圆,相当于掏空 */
  848. /* -webkit-mask: radial-gradient(transparent 95px, white 0px); */
  849. background: #2196f3;
  850. animation: ballZhuan1 linear infinite;
  851. animation-duration: 11s;
  852. }
  853. .five {
  854. width: 270px;
  855. height: 270px;
  856. border-radius: 99px;
  857. opacity: 0.6;
  858. position: absolute;
  859. top: 30px;
  860. z-index: 10;
  861. /* 从中心向外剪切圆,相当于掏空 */
  862. /* -webkit-mask: radial-gradient(transparent 95px, white 0px); */
  863. background: #2196f3;
  864. animation: ballZhuan1 linear infinite;
  865. /* transform: rotate(120deg); */
  866. animation-duration: 9s;
  867. left: -67px;
  868. }
  869. .six {
  870. width: 270px;
  871. height: 270px;
  872. border-radius: 99px;
  873. opacity: 0.6;
  874. position: absolute;
  875. top:30px;
  876. z-index: 10;
  877. /* 从中心向外剪切圆,相当于掏空 */
  878. /* -webkit-mask: radial-gradient(transparent 95px, white 0px); */
  879. background: #2196f3;
  880. animation: ballZhuan1 7s linear infinite;
  881. /* transform: rotate(120deg); */
  882. right: -67px;
  883. }
  884. @keyframes ballZhuan {
  885. 100% {
  886. transform: rotate(360deg);
  887. }
  888. }
  889. @keyframes ballZhuan1 {
  890. 100% {
  891. transform: rotate(360deg);
  892. }
  893. }
  894. /* 底部的小球 */
  895. .dot {
  896. display: block;
  897. width: 20px;
  898. height: 20px;
  899. border-radius: 50%;
  900. background: rgba(101,192,255,0.28);
  901. position: absolute;
  902. z-index: 1000;
  903. bottom: -50px;
  904. }
  905. .dot:nth-of-type(1) {
  906. width: 40px;
  907. height: 40px;
  908. right: 116px;
  909. animation: dotMove 5s linear infinite;
  910. }
  911. .dot:nth-of-type(2) {
  912. width: 50px;
  913. height: 50px;
  914. left: 120px;
  915. animation: dotMove 4s linear infinite;
  916. }
  917. .dot:nth-of-type(3) {
  918. animation: dotMove 2s linear infinite;
  919. }
  920. .dot:nth-of-type(4) {
  921. width: 15px;
  922. height: 15px;
  923. left: 130px;
  924. animation: dotMove 2s linear infinite;
  925. }
  926. .dot:nth-of-type(5) {
  927. width: 30px;
  928. height: 30px;
  929. animation: dotMove 3s linear infinite;
  930. }
  931. @keyframes dotMove {
  932. 0% {
  933. transform: translateY(0px);
  934. opacity: 1;
  935. }
  936. 98% {
  937. opacity: 1;
  938. }
  939. 100% {
  940. transform: translateY(-260px);
  941. opacity: 0;
  942. }
  943. }
  944. .w-flex {
  945. display: -webkit-box;
  946. display: -webkit-flex;
  947. display: flex;
  948. padding: 0px 25px;
  949. }
  950. .w-flex__item {
  951. -webkit-box-flex: 1;
  952. -webkit-flex: 1;
  953. flex: 1;
  954. }
  955. .w-item{
  956. text-align: center;
  957. padding: 5px;
  958. }
  959. .w-item-tit{
  960. font-size: 14px;
  961. color: #888;
  962. }
  963. .w-item-num{
  964. font-size: 18px;
  965. color: #111;
  966. }
  967. .can{
  968. position: relative;
  969. z-index: 0;
  970. width: 211px;
  971. height: 211px;
  972. background-image: url(/static/images/new/quan.png);
  973. background-size: cover;
  974. display: flex;
  975. justify-content: center;
  976. align-items: center;
  977. }
  978. .dtop{
  979. background: url(/static/images/new/box1.png);
  980. background-size: cover;
  981. width: 260px;
  982. height: 236px;
  983. display: flex;
  984. justify-content: center;
  985. align-items: center;
  986. left: 15%;
  987. position: relative;
  988. }
  989. .dstatus{
  990. margin-top: 0.1rem;
  991. display: flex;
  992. flex-wrap: wrap;
  993. justify-content: space-evenly;
  994. align-content: center;
  995. }
  996. .ditem{
  997. width: 30%;
  998. display: flex;
  999. flex-direction: column;
  1000. align-items: center;
  1001. margin-bottom: 0.3rem;
  1002. margin-top: 10px;
  1003. }
  1004. .itemimg{
  1005. width: 50px;
  1006. height: 50px;
  1007. }
  1008. .item-value{
  1009. font-weight: bold;
  1010. font-size: 19px;
  1011. margin:4px 0;
  1012. }
  1013. .item-text{
  1014. font-size: 13px;
  1015. margin:1px 0;
  1016. color: #999999;
  1017. }
  1018. .start{
  1019. background: #1A87FF;
  1020. color: #fff;
  1021. width: 45%;
  1022. height: 50px;
  1023. min-height: 40px;
  1024. border-radius: 50px;
  1025. display: flex;
  1026. justify-content: center;
  1027. align-items: center;
  1028. font-size: 20px;
  1029. font-weight: bold;
  1030. }
  1031. .dbtns{
  1032. display: flex;
  1033. margin-top:10px;
  1034. justify-content: space-between;
  1035. padding: 0 30px;
  1036. }
  1037. .get{
  1038. background: #fff;
  1039. border: 1px solid #1A87FF;
  1040. color: #1A87FF;
  1041. width: 45%;
  1042. height: 50px;
  1043. min-height: 40px;
  1044. border-radius: 50px;
  1045. display: flex;
  1046. justify-content: center;
  1047. align-items: center;
  1048. font-size: 20px;
  1049. font-weight: bold;
  1050. }
  1051. .dtip{
  1052. margin: 20px 20px;
  1053. padding: 10px;
  1054. background: rgba(127,200,251,0.1);
  1055. border: 1px solid #7FC8FB;
  1056. box-shadow: 0 2px 8px 0 rgba(0,0,0,0.19);
  1057. border-radius: 5px;
  1058. font-size: 17px;
  1059. font-weight: 400;
  1060. color: #B8B9BA;
  1061. margin-bottom: 10px;
  1062. }
  1063. .p1{
  1064. font-size: 20px;
  1065. color: white;
  1066. font-weight: bold;
  1067. margin-top:10px;
  1068. }
  1069. .stip{
  1070. text-align: center;
  1071. z-index: 9999;
  1072. }
  1073. </style>