status.vue 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138
  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. uni.reLaunch({
  325. url: '/pages/bluetooth/index/index'
  326. });
  327. // self.recon()
  328. } else if (res.cancel) {
  329. console.log('用户点击取消');
  330. }
  331. }
  332. });
  333. })
  334. //receive data
  335. ecBLE.onBLECharacteristicValueChange((str, strHex) => {
  336. isCheckRevHex = true;
  337. let data =
  338. (isCheckRevHex ? strHex.replace(/[0-9a-fA-F]{2}/g, ' $&') : str)
  339. // console.log(data)
  340. self.$modal.closeLoading();
  341. console.log("收到消息:"+data);
  342. //AA 67 0D 05 00 00 00 00 00 00 00 00 00 25 E2 00 80
  343. data = parseDataObj(data);
  344. self.messageCallback(data);
  345. })
  346. self.getInfo();
  347. },
  348. messageCallback(data){
  349. let self = this;
  350. console.log(data);
  351. let type = data.type;
  352. let real_data = data.real_data;
  353. if(type == 103){
  354. self.portDetail = real_data
  355. self.portList = [[]];
  356. let port_first_status = self.portDetail["port_first_status"];
  357. let port_second_status = self.portDetail["port_second_status"]
  358. if(port_first_status){
  359. self.portList[0].push({port:1,text:"端口一"});
  360. }
  361. if(port_second_status){
  362. self.portList[0].push({port:2,text:"端口二"});
  363. }
  364. let choosePort = self.choosePort
  365. if(choosePort == 1){
  366. self.portDetail.portStatus = port_first_status;
  367. }else if(choosePort == 2){
  368. self.portDetail.portStatus = port_second_status;
  369. }
  370. self.$modal.closeLoading();
  371. }
  372. if(type == 116){
  373. self.$modal.closeLoading();
  374. self.getInfo();
  375. }
  376. if(type == 113){
  377. self.$modal.closeLoading();
  378. self.getInfo();
  379. }
  380. if(type == 96){
  381. }
  382. self.$forceUpdate();
  383. console.log('收到服务器内容:' + JSON.stringify(data));
  384. if(!this.firstInit){
  385. this.firstInit = true;
  386. let autoCharge = self.getAutoChargeValue()
  387. if(self.portDetail.portStatus == 5 && autoCharge == 1){
  388. self.startCharge();
  389. }
  390. }
  391. },
  392. getAutoChargeValue(){
  393. let autoCharge = uni.getStorageSync("autoCharge");
  394. if(!autoCharge ){
  395. autoCharge = 1;
  396. }
  397. return autoCharge;
  398. },
  399. planCharge(){
  400. if(this.portDetail.portStatus == 6){
  401. this.$modal.confirm("确认取消预约?").then(res=>{
  402. this.cancelPlan();
  403. })
  404. }else{
  405. this.toPlan()
  406. }
  407. },
  408. sendBlueData(){
  409. ecBLE.writeBLECharacteristicValue(tempSendData, false)
  410. },
  411. cancelPlan(){
  412. cancelPlan(this.choosePort).then(res=>{
  413. this.$modal.msg("取消成功");
  414. this.getInfo(true);
  415. })
  416. },
  417. getPlanInfo(){
  418. getPlanInfo(this.deviceInfo.deviceId,this.choosePort).then(res=>{
  419. let data = res.data;
  420. if(data != null){
  421. let planType = data.planType;
  422. if(planType == 1){//单次预约
  423. let planInfo = {};
  424. planInfo.runTime = data.runTime;
  425. this.planInfo = planInfo;
  426. this.planInfo.id = data.id;
  427. }else{
  428. let planInfo = {};
  429. planInfo.runTime = data.runTime;
  430. let repeatDays = data.repeatDays;
  431. let days = repeatDays.split(",")
  432. let strs = "";
  433. for (let i = 0; i < days.length; i++) {
  434. if(strs.length>0){
  435. strs+=",";
  436. }
  437. strs +=this.days[days[i]];
  438. }
  439. this.planInfo = planInfo;
  440. this.planInfo.runTime = strs+" "+data.repeatTime;
  441. this.planInfo.id = data.id;
  442. }
  443. }
  444. })
  445. },
  446. confirmPort(e){
  447. let value = e.value[0]
  448. this.choosePort = value.port;
  449. this.showPort = false;
  450. this.getInfo()
  451. },
  452. initSocket(key){
  453. let self = this;
  454. },
  455. toSet(){
  456. // this.closeSocket();
  457. uni.navigateTo({
  458. url: '/pages/weitiandi/bluetooth/setting'
  459. });
  460. },
  461. toPlan(){
  462. let arr = [];
  463. let date = new Date();
  464. let min = date.getMinutes();
  465. let hour = date.getHours();
  466. let arr1 = ["今日", "明日"];
  467. let arr2 = []
  468. let arr3 = [];
  469. let arr4 = [];
  470. for (let i = 0; i < hour; i++) {
  471. arr2.push(i+"时")
  472. }
  473. this.columnData[0] = arr2;
  474. for (let i = hour+1; i < 24; i++) {
  475. arr3.push(i+"时")
  476. }
  477. this.columnData[1] = arr3;
  478. for (let i = 0; i <= 59; i++) {
  479. arr4.push(i+"分")
  480. }
  481. this.planCols = [arr1, arr3, arr4]
  482. this.showPlan = true;
  483. },
  484. trigger(){
  485. let portStatus = this.portDetail.portStatus;
  486. if(portStatus == 2){//需要停止充电
  487. this.$modal.confirm("需要停止充电么?").then(res=>{
  488. this.stopCharge();
  489. })
  490. }else{
  491. if(portStatus == 1){
  492. this.$modal.msg("请先将充电枪插入后再点击充电");
  493. }
  494. if(portStatus == 5){
  495. this.$modal.confirm("确认开始充电么?").then(res=>{
  496. this.startCharge();
  497. })
  498. }else {
  499. this.$modal.msg("端口无法开始充电");
  500. }
  501. }
  502. },
  503. getInfo(flag) {
  504. // let str = "AA 67 0D 01 00 00 00 00 00 00 00 00 00 25 E2 00 80";
  505. // let data = parseDataObj(str);
  506. // this.messageCallback(data);
  507. //
  508. //
  509. this.$modal.loading("正在获取状态,请稍等...");
  510. if(flag){
  511. setTimeout(function (){
  512. sendPortDetailCmd().then(res => {
  513. })
  514. },500)
  515. }else{
  516. sendPortDetailCmd().then(res => {
  517. })
  518. }
  519. },
  520. stopCharge(){
  521. let self = this;
  522. this.deviceInfo.port = this.choosePort;
  523. stopCharge(this.deviceInfo).then(()=>{
  524. self.$modal.loading("停止成功");
  525. setTimeout((()=>{
  526. self.getInfo();
  527. }),1000);
  528. })
  529. },
  530. startCharge(){
  531. let self = this;
  532. this.deviceInfo.port = this.choosePort;
  533. startCharge(this.deviceInfo).then(res=>{
  534. self.$modal.loading("启动成功");
  535. setTimeout((()=>{
  536. self.getInfo();
  537. }),1000);
  538. })
  539. },
  540. getPortInfo(){
  541. this.startPortDetailTimer();
  542. },
  543. startPortDetailTimer(){
  544. let self = this;
  545. this.timer = setTimeout(function (){
  546. getPortDetail(self.deviceInfo,self.visitTime).then(res=>{
  547. let data = res.data;
  548. if(data != null){
  549. self.portDetail = data;
  550. self.checkStatusCheck();
  551. self.$modal.closeLoading();
  552. }else{
  553. self.startPortDetailTimer();
  554. }
  555. });
  556. },1000);
  557. },
  558. checkStatusCheck(){
  559. this.statusChangeTimer();
  560. },
  561. checkOnPage(){
  562. var pages = getCurrentPages() // 获取栈实例
  563. let currentRoute = pages[pages.length - 1].route; // 获取当前页面路由
  564. if("pages/weitiandi/device/index" != currentRoute){
  565. return false;
  566. }
  567. return true;
  568. },
  569. goBack(){
  570. this.closeSocket();
  571. uni.navigateBack({
  572. });
  573. },
  574. closeSocket(){
  575. ecBLE.onBLEConnectionStateChange(() => {})
  576. ecBLE.onBLECharacteristicValueChange(() => {})
  577. ecBLE.closeBLEConnection()
  578. uni.removeStorageSync('blueid');
  579. },
  580. statusChangeTimer(){
  581. let self = this;
  582. this.statusTimer = setTimeout(function(){
  583. if(!this.checkOnPage()){
  584. return;
  585. }
  586. checkStatusChange(self.deviceInfo,self.visitTime).then(res=>{
  587. let data = res.data;
  588. if(data != null){
  589. self.getInfo();
  590. }else{
  591. self.statusChangeTimer();
  592. }
  593. });
  594. },3000);
  595. }
  596. }
  597. }
  598. </script>
  599. <style>
  600. .container {
  601. background: rgb(249, 252, 255);
  602. inset: 0;
  603. position: absolute;
  604. }
  605. .header {
  606. position: relative;
  607. margin-top:4vw;
  608. }
  609. .header-status-desc {
  610. position: absolute;
  611. text-align: center;
  612. width: 100%;
  613. bottom:1vh;
  614. font-size: 5vw;
  615. font-weight: bold;
  616. color: #0E9F9B;
  617. margin-bottom: 5vw;
  618. }
  619. .header-status {
  620. font-weight: bold;
  621. text-align: center;
  622. }
  623. .chong-active {
  624. color: #0E9F9B
  625. }
  626. .header-img {
  627. width: 100%;
  628. padding: 5% 10%;
  629. text-align: center;
  630. }
  631. .header-img image {
  632. width: 100%;
  633. height: 23vh;
  634. }
  635. .info-body{
  636. background: #0E9F9B;
  637. height: 20vh;
  638. margin: 0 2%;
  639. border-radius: 1vw;
  640. margin-top:2vh;
  641. color: #F8FCFF;
  642. line-height: 3vh;
  643. }
  644. .info-content{
  645. display: inline-block;
  646. width: 23%;
  647. text-align: center;
  648. margin: 1%;
  649. margin-top:2.5vh;
  650. }
  651. .info-content-value{
  652. font-weight: bold;
  653. }
  654. .info-content-text{
  655. }
  656. .info-summary{
  657. display: flex;
  658. flex-direction: row;
  659. text-align: center;
  660. margin:3vh 0;
  661. }
  662. .summary{
  663. width: 33%;
  664. line-height: 2.5vh;
  665. }
  666. .charge-num{
  667. color: #0E9F9B;
  668. font-weight: bold;
  669. font-size: 4.5vw;
  670. }
  671. .charge-title{
  672. color: #B2B2B2;
  673. font-weight: 400;
  674. }
  675. .btn-image{
  676. width: 90%;
  677. height: 100%;
  678. }
  679. .info-bottom-btn{
  680. display: flex;
  681. flex-direction: row;
  682. text-align: center;
  683. position: relative;
  684. margin-top: 10vh
  685. ;
  686. }
  687. .btn-area{
  688. width: 50%;
  689. height: 50px;
  690. }
  691. .left{
  692. position: relative;
  693. left: 10px;
  694. text-align: right;
  695. }
  696. .right{
  697. text-align: left;
  698. position: relative;
  699. right: 10px;
  700. }
  701. .info-plan{
  702. text-align: center;
  703. color: #0E9F9B;
  704. margin-top:1vh;
  705. font-weight: 400;
  706. }
  707. .setting{
  708. position: fixed;
  709. right: -1px;
  710. top: 10vh;
  711. z-index: 999;
  712. background: rgb(227,243,245);
  713. color: #0E9F9B;
  714. font-size: 10px;
  715. border-radius: 5px;
  716. padding: 3px;
  717. }
  718. .port{
  719. height: 70px;
  720. background: #F8FCFF;
  721. border: 0px solid #F8FCFF;
  722. box-shadow: 0px 0px 6px 1px rgba(101,101,101,0.29);
  723. border-radius: 4px;
  724. margin:0 10px;
  725. position: relative;
  726. margin-top:10px;
  727. }
  728. .plan{
  729. height: 70px;
  730. background: #F8FCFF;
  731. border: 0px solid #F8FCFF;
  732. box-shadow: 0px 0px 6px 1px rgba(101,101,101,0.29);
  733. border-radius: 4px;
  734. margin:0 10px;
  735. position: relative;
  736. margin-top:15px;
  737. }
  738. .port-image{
  739. height: 40px;
  740. width: 40px;
  741. position: absolute;
  742. top:15px;
  743. left:20px;
  744. }
  745. .port-text{
  746. position: absolute;
  747. top:13px;
  748. left:75px;
  749. font-weight: bold;
  750. }
  751. .port-num{
  752. position: absolute;
  753. top:38px;
  754. left:75px;
  755. color: #B2B2B2;
  756. }
  757. .port-icon{
  758. position: absolute;
  759. top:30px;
  760. right:5px;
  761. width: 10px;
  762. height: 16px;
  763. }
  764. .port-icon image{
  765. width: 90%;
  766. }
  767. .body-bottom{
  768. padding:0 22px;
  769. }
  770. .body-bottom .info-content{
  771. width: 30%;
  772. }
  773. .bottom-control{
  774. height: 22vh;
  775. margin: 0 2%;
  776. margin-top:2vh;
  777. line-height: 3vh;
  778. background: #F8FCFF;
  779. border: 0px solid #F8FCFF;
  780. box-shadow: 0px 0px 6px 1px rgba(101,101,101,0.29);
  781. border-radius: 4px;
  782. padding:3%;
  783. }
  784. .control-btn{
  785. display: inline-block;;
  786. height: 60px;
  787. width: 25%;
  788. padding:10px 20px;
  789. text-align: center;
  790. font-size: 12px;
  791. color: black;
  792. }
  793. .control-btn .btn-image{
  794. }
  795. #box {
  796. /* width: 300px; */
  797. height: 280px;
  798. position: relative;
  799. /* 背景色 */
  800. /* background: #f7f6f6; */
  801. overflow: hidden;
  802. /* padding: 50px 0; */
  803. box-sizing: border-box;
  804. ;
  805. }
  806. .box {
  807. width: 100%;
  808. height: 100%;
  809. position: absolute;
  810. display: flex;
  811. justify-content: center;
  812. /* 此处尽量不要设置背景色,可以选择在父标签上设置背景色,否则没有黏黏的效果 */
  813. filter: url("#goo");
  814. }
  815. /* 电量文字 */
  816. .text {
  817. font-weight: 200;
  818. font-size: 20px;
  819. margin-top: 5px;
  820. text-align: center;
  821. color: #ff6600;
  822. }
  823. /* 电量文字 */
  824. .text span {
  825. font-size: 15px;
  826. }
  827. .three {
  828. width: 170px;
  829. height: 170px;
  830. border-radius: 300px;
  831. opacity: 1;
  832. position: absolute;
  833. top: 20px;
  834. z-index: 10;
  835. /* 从中心向外剪切圆,相当于掏空 */
  836. /* -webkit-mask: radial-gradient(transparent 95px, white 0px); */
  837. background: #ffffff;
  838. /* animation: ballZhuan 9s linear infinite; */
  839. overflow: hidden;
  840. box-shadow: 0px 0px 19px 1px #2196f3;
  841. }
  842. .four {
  843. width: 200px;
  844. height: 200px;
  845. border-radius: 80px;
  846. opacity: 0.3;
  847. position: absolute;
  848. top: 10px;
  849. z-index: 10;
  850. /* 从中心向外剪切圆,相当于掏空 */
  851. /* -webkit-mask: radial-gradient(transparent 95px, white 0px); */
  852. background: #2196f3;
  853. animation: ballZhuan1 linear infinite;
  854. animation-duration: 11s;
  855. }
  856. .five {
  857. width: 270px;
  858. height: 270px;
  859. border-radius: 99px;
  860. opacity: 0.6;
  861. position: absolute;
  862. top: 30px;
  863. z-index: 10;
  864. /* 从中心向外剪切圆,相当于掏空 */
  865. /* -webkit-mask: radial-gradient(transparent 95px, white 0px); */
  866. background: #2196f3;
  867. animation: ballZhuan1 linear infinite;
  868. /* transform: rotate(120deg); */
  869. animation-duration: 9s;
  870. left: -67px;
  871. }
  872. .six {
  873. width: 270px;
  874. height: 270px;
  875. border-radius: 99px;
  876. opacity: 0.6;
  877. position: absolute;
  878. top:30px;
  879. z-index: 10;
  880. /* 从中心向外剪切圆,相当于掏空 */
  881. /* -webkit-mask: radial-gradient(transparent 95px, white 0px); */
  882. background: #2196f3;
  883. animation: ballZhuan1 7s linear infinite;
  884. /* transform: rotate(120deg); */
  885. right: -67px;
  886. }
  887. @keyframes ballZhuan {
  888. 100% {
  889. transform: rotate(360deg);
  890. }
  891. }
  892. @keyframes ballZhuan1 {
  893. 100% {
  894. transform: rotate(360deg);
  895. }
  896. }
  897. /* 底部的小球 */
  898. .dot {
  899. display: block;
  900. width: 20px;
  901. height: 20px;
  902. border-radius: 50%;
  903. background: rgba(101,192,255,0.28);
  904. position: absolute;
  905. z-index: 1000;
  906. bottom: -50px;
  907. }
  908. .dot:nth-of-type(1) {
  909. width: 40px;
  910. height: 40px;
  911. right: 116px;
  912. animation: dotMove 5s linear infinite;
  913. }
  914. .dot:nth-of-type(2) {
  915. width: 50px;
  916. height: 50px;
  917. left: 120px;
  918. animation: dotMove 4s linear infinite;
  919. }
  920. .dot:nth-of-type(3) {
  921. animation: dotMove 2s linear infinite;
  922. }
  923. .dot:nth-of-type(4) {
  924. width: 15px;
  925. height: 15px;
  926. left: 130px;
  927. animation: dotMove 2s linear infinite;
  928. }
  929. .dot:nth-of-type(5) {
  930. width: 30px;
  931. height: 30px;
  932. animation: dotMove 3s linear infinite;
  933. }
  934. @keyframes dotMove {
  935. 0% {
  936. transform: translateY(0px);
  937. opacity: 1;
  938. }
  939. 98% {
  940. opacity: 1;
  941. }
  942. 100% {
  943. transform: translateY(-260px);
  944. opacity: 0;
  945. }
  946. }
  947. .w-flex {
  948. display: -webkit-box;
  949. display: -webkit-flex;
  950. display: flex;
  951. padding: 0px 25px;
  952. }
  953. .w-flex__item {
  954. -webkit-box-flex: 1;
  955. -webkit-flex: 1;
  956. flex: 1;
  957. }
  958. .w-item{
  959. text-align: center;
  960. padding: 5px;
  961. }
  962. .w-item-tit{
  963. font-size: 14px;
  964. color: #888;
  965. }
  966. .w-item-num{
  967. font-size: 18px;
  968. color: #111;
  969. }
  970. .can{
  971. position: relative;
  972. z-index: 0;
  973. width: 211px;
  974. height: 211px;
  975. background-image: url(/static/images/new/quan.png);
  976. background-size: cover;
  977. display: flex;
  978. justify-content: center;
  979. align-items: center;
  980. }
  981. .dtop{
  982. background: url(/static/images/new/box1.png);
  983. background-size: cover;
  984. width: 260px;
  985. height: 236px;
  986. display: flex;
  987. justify-content: center;
  988. align-items: center;
  989. left: 15%;
  990. position: relative;
  991. }
  992. .dstatus{
  993. margin-top: 0.1rem;
  994. display: flex;
  995. flex-wrap: wrap;
  996. justify-content: space-evenly;
  997. align-content: center;
  998. }
  999. .ditem{
  1000. width: 30%;
  1001. display: flex;
  1002. flex-direction: column;
  1003. align-items: center;
  1004. margin-bottom: 0.3rem;
  1005. margin-top: 10px;
  1006. }
  1007. .itemimg{
  1008. width: 50px;
  1009. height: 50px;
  1010. }
  1011. .item-value{
  1012. font-weight: bold;
  1013. font-size: 19px;
  1014. margin:4px 0;
  1015. }
  1016. .item-text{
  1017. font-size: 13px;
  1018. margin:1px 0;
  1019. color: #999999;
  1020. }
  1021. .start{
  1022. background: #1A87FF;
  1023. color: #fff;
  1024. width: 45%;
  1025. height: 50px;
  1026. min-height: 40px;
  1027. border-radius: 50px;
  1028. display: flex;
  1029. justify-content: center;
  1030. align-items: center;
  1031. font-size: 20px;
  1032. font-weight: bold;
  1033. }
  1034. .dbtns{
  1035. display: flex;
  1036. margin-top:10px;
  1037. justify-content: space-between;
  1038. padding: 0 30px;
  1039. }
  1040. .get{
  1041. background: #fff;
  1042. border: 1px solid #1A87FF;
  1043. color: #1A87FF;
  1044. width: 45%;
  1045. height: 50px;
  1046. min-height: 40px;
  1047. border-radius: 50px;
  1048. display: flex;
  1049. justify-content: center;
  1050. align-items: center;
  1051. font-size: 20px;
  1052. font-weight: bold;
  1053. }
  1054. .dtip{
  1055. margin: 20px 20px;
  1056. padding: 10px;
  1057. background: rgba(127,200,251,0.1);
  1058. border: 1px solid #7FC8FB;
  1059. box-shadow: 0 2px 8px 0 rgba(0,0,0,0.19);
  1060. border-radius: 5px;
  1061. font-size: 17px;
  1062. font-weight: 400;
  1063. color: #B8B9BA;
  1064. margin-bottom: 10px;
  1065. }
  1066. .p1{
  1067. font-size: 20px;
  1068. color: white;
  1069. font-weight: bold;
  1070. margin-top:10px;
  1071. }
  1072. .stip{
  1073. text-align: center;
  1074. z-index: 9999;
  1075. }
  1076. </style>