status.vue 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559
  1. <template>
  2. <view class="container">
  3. <view style="height: 0vh;place-items: center;display: grid;">
  4. <image style="height: 3vh;width: 15vh;margin-top: 5vh;top: 3vh;"
  5. src="../../../static/images/new/starts/login/backImg2.png"></image>
  6. <text @click.stop="clickRight()"
  7. style="color: #ffffff;font-size: 15px;margin: 0 0 0 31vh;font-weight: bold;">· · ·</text>
  8. <view>
  9. <uni-drawer @change="changeDrawer" style="top:20vh;height: 100vh" ref="showRight" mode="right"
  10. :mask-click="true">
  11. <scroll-view style="background: linear-gradient(#000000, #5a5a58);font-size: 20px;height: 100%;" scroll-y="true">
  12. <view class="prop-item" @click="handleLogout()">
  13. <!-- <view class="prop-item-image">
  14. <image :src="imgUrl+'/logout.png'" style="width: 30%;height:100%;" />
  15. </view> -->
  16. <view class="prop-item-right">{{i18('退出登录')}}</view>
  17. <view class="prop-item-left">
  18. <uni-icons type="forward" color="lightgray" size="16"></uni-icons>
  19. </view>
  20. </view>
  21. <u-divider />
  22. <view class="prop-item" @click="skipPage(3)">
  23. <!-- <view class="prop-item-image">
  24. <image :src="imgUrl+'/logout.png'" style="width: 30%;height:100%;" />
  25. </view> -->
  26. <view class="prop-item-right">{{i18('关于我们')}}</view>
  27. <view class="prop-item-left">
  28. <uni-icons type="forward" color="lightgray" size="16"></uni-icons>
  29. </view>
  30. </view>
  31. <u-divider />
  32. <view class="prop-item" @click="skipPage(4)">
  33. <!-- <view class="prop-item-image">
  34. <image :src="imgUrl+'/logout.png'" style="width: 30%;height:100%;" />
  35. </view> -->
  36. <view class="prop-item-right">{{i18('帮助')}}</view>
  37. <view class="prop-item-left">
  38. <uni-icons type="forward" color="lightgray" size="16"></uni-icons>
  39. </view>
  40. </view>
  41. <u-divider />
  42. </scroll-view>
  43. </uni-drawer>
  44. </view>
  45. </view>
  46. <view style=";position: relative;top: 10vh;margin-top:4vh;text-align: center;padding:0 28%;">
  47. <view class="progress_box" style="text-align: center">
  48. <canvas class="progress_bg" canvas-id="cpbg"></canvas>
  49. <canvas class="progress_bar" canvas-id="cpbar"></canvas>
  50. <canvas class="progress_line" canvas-id="cpline"></canvas>
  51. <view class="progress_txt">
  52. <view class="progress_info">
  53. <view class="p0" style="color: azure;" st="">{{ deviceInfo.qrcode}}</view>
  54. <view class="p1">
  55. <view v-if="portStatus == 2" style="position: relative;
  56. left: -17px;">
  57. {{$t('charge.charging')}}
  58. </view>
  59. <view v-else-if="portStatus == 6" style="position: relative;
  60. left: -17px;">
  61. {{$t('charge.planed')}}
  62. </view>
  63. <view v-else-if="portStatus == 5" style="position: relative;
  64. left: -17px;">
  65. {{$t('charge.connected')}}
  66. </view>
  67. <view v-else>
  68. {{$t('charge.nocharge')}}
  69. </view>
  70. </view>
  71. </view>
  72. </view>
  73. </view>
  74. <!-- <view class="dtop">
  75. <view class="can" style="background-image: url(/static/images/new/quan.png);">
  76. <view class="box">
  77. <view class="three">
  78. <view class="four"></view>
  79. <view class="five"></view>
  80. <view class="six"></view>
  81. </view>
  82. <view class="dot"></view>
  83. <view class="dot"></view>
  84. <view class="dot"></view>
  85. <view class="dot"></view>
  86. <view class="dot"></view>
  87. </view>
  88. <view class="stip">
  89. <view class="p0" st="">{{ deviceInfo.qrcode}}</view>
  90. <view class="p1">
  91. <view v-if="portStatus == 2">
  92. {{$t('charge.charging')}}
  93. </view>
  94. <view v-else-if="portStatus == 6">
  95. {{$t('charge.planed')}}
  96. </view>
  97. <view v-else-if="portStatus == 5">
  98. {{$t('charge.connected')}}
  99. </view>
  100. <view v-else>
  101. {{$t('charge.nocharge')}}
  102. </view>
  103. </view>
  104. </view>
  105. </view>
  106. </view>-->
  107. </view>
  108. <view style="display: flex;align-items: center;flex-direction: column;color: aliceblue;margin-top: 5vh;">
  109. <view
  110. style="background-color: black;justify-content: center;display: flex;justify-items: center;flex-direction: row;text-align: center;width: 36vh;;border-radius: 27px;">
  111. <view span="3" style="width: 9vh;">
  112. <view class="item-value">{{ deviceV }}V</view>
  113. <span class="item-text">{{$t('charge.voltage')}}</span>
  114. </view>
  115. <u-line direction="col" color="#6F84AC" length="50"></u-line>
  116. <view span="3" style="width: 9vh;">
  117. <view class="item-value">{{ gonglv }}W</view>
  118. <span class="item-text">{{$t('charge.power')}}</span>
  119. </view>
  120. <u-line direction="col" color="#6F84AC" length="50"></u-line>
  121. <view span="3" style="width: 9vh;">
  122. <view class="item-value">{{deviceTemp}}℃</view>
  123. <span class="item-text">{{$t('charge.devtemper')}}</span>
  124. </view>
  125. <u-line direction="col" color="#6F84AC" length="50"></u-line>
  126. <view span="3" style="width: 9vh;">
  127. <view class="item-value" v-if="portDetail.voltage == 0">0 {{ i18('度') }}</view>
  128. <view class="item-value" v-else>{{ dianliang }} {{ i18('度') }}</view>
  129. <span class="item-text">{{$t('charge.elec')}}</span>
  130. </view>
  131. </view>
  132. </view>
  133. <view style="display: flex;align-items: center;flex-direction: column;color: aliceblue;margin-top: 3vh;">
  134. <view
  135. style="position:relative;justify-content: center;display: flex;justify-items: center;flex-direction: row;text-align: center;width: 100%;height: 30px;}">
  136. <view style="width: 80px;left:10%;position: absolute;font-size: 12px;">
  137. <view style="margin-left: 1vh;width: 100px">
  138. <view><span v-if="portDetail.portStatus == 6">{{i18('剩余时间')}}</span>
  139. <span v-else>{{$t('charge.chargetime')}}</span></view>
  140. <view class="demo-layout bg-purple"
  141. style="border-radius: 8px;background-color: aliceblue;color: #000;">
  142. <view >{{ chargeTime }}{{ i18('分钟') }}</view>
  143. </view>
  144. </view>
  145. </view>
  146. <view span="2" style="width: 100px;left:36%;position: absolute">
  147. <view v-if="portDetail.portStatus == 2"
  148. style="text-align: center;position: absolute;margin:-1vh 5vw;border: 0ch;height: 20vh;">
  149. <u-button @click="toPage()" shape="circle"
  150. style="background: #ec3e41;color:white;width: 100vm;border: 0ch;height: 6vh;">Charge</u-button>
  151. </view>
  152. <view v-if="portDetail.portStatus != 2"
  153. style="text-align: center;position: absolute;margin:-1vh 5vw;border: 0ch;height: 20vh;">
  154. <u-button @click="toPage()" shape="circle"
  155. style="background: #57B03D;color:white;width: 80px;border: 0ch;height: 6vh;">Charge</u-button>
  156. </view>
  157. <!-- <view class="control-btn" @click="trigger()" v-if="portDetail.portStatus == 2">
  158. <image class="btn-image" src="/static/images/new/start/stop.png" >
  159. </image>
  160. <view>{{ i18('停止充电') }}</view>
  161. </view>
  162. <view class="control-btn" @click="trigger()" v-if="portDetail.portStatus != 2">
  163. <image class="btn-image" src="/static/images/new/start/using.png" >
  164. </image>
  165. <view>{{ i18('立即充电') }}</view>
  166. </view> -->
  167. </view>
  168. <view span="3" style="width: 80px;left:65%;position: absolute">
  169. <view style="margin-left: 1vh;font-size: 12px;">
  170. <view> Ampere</view>
  171. <view class="demo-layout bg-purple"
  172. style="border-radius: 8px;background-color: aliceblue;color: #000;">
  173. <view v-if="deviceV == 0">0A</view>
  174. <view v-else>{{currentValue}}A</view>
  175. </view>
  176. </view>
  177. </view>
  178. </view>
  179. </view>
  180. <view style="display: flex;align-items: center;justify-content: center;margin-top: 0vh;">
  181. <view @click="toSetting">
  182. <image src="../../../static/images/new/starts/status/Setting.png"
  183. style="width: 60px;height: 60px;margin: 2vh 2vh;"></image>
  184. </view>
  185. <!-- <view class="" @click="wifi">
  186. <image src="../../../static/images/new/starts/status/WiFi.png"
  187. style="width: 60px;height: 60px;margin: 2vh 0.2vh;"></image>
  188. </view> -->
  189. <!-- <view class="">
  190. <image src="../../../static/images/new/starts/status/Lock/Unlocked.png"
  191. style="width: 60px;height: 60px;margin: 2vh 2vh;"></image>
  192. </view> -->
  193. <view class="" @click="getInfo">
  194. <image src="../../../static/images/new/starts/status/Refresh.png"
  195. style="width: 60px;height: 60px;margin: 2vh 2vh;;"></image>
  196. </view>
  197. <!-- <view class="">
  198. <image src="../../../static/images/new/starts/status/Link.png"
  199. style="width: 60px;height: 60px;margin: 2vh 0.2vh;"></image>
  200. </view> -->
  201. </view>
  202. <view style="display: flex;align-items: center;justify-content: center;">
  203. <view @click="skipPage(0)">
  204. <image src="../../../static/images/new/starts/tabbar/one_off.png"
  205. style="width: 60px;height: 60px;margin: 2vh 0.2vh;"></image>
  206. </view>
  207. <view @click="skipPage(1)">
  208. <image src="../../../static/images/new/starts/tabbar/two_off.png"
  209. style="width: 60px;height: 60px;margin: 2vh 0.2vh;"></image>
  210. </view>
  211. <view @click="skipPage(2)">
  212. <image src="../../../static/images/new/starts/tabbar/three_off.png"
  213. style="width: 60px;height: 60px;margin: 2vh 0.2vh;"></image>
  214. </view>
  215. </view>
  216. <!-- <view style="display: flex;flex-direction: row;margin:0 33%;" v-if="curPort.length>1">
  217. <view class="port_item" :class="item.id==choosePort?'selected_item':''" v-for="item in curPort"
  218. @click="selectPort(item.id);">{{ i18(item.text )}}</view>
  219. </view>
  220. <view class="dstatus">
  221. <view class="ditem">
  222. <image class="itemimg" src="/static/images/new/tmp.png" />
  223. <view class="item-value">{{deviceTemp}}℃</view>
  224. <span class="item-text">{{$t('charge.devtemper')}}</span>
  225. </view>
  226. <view class="ditem">
  227. <image class="itemimg" src="/static/images/new/dianya.png" />
  228. <view class="item-value">{{ deviceV }}V</view>
  229. <span class="item-text">{{$t('charge.voltage')}}</span>
  230. </view>
  231. <view class="ditem">
  232. <image class="itemimg" src="/static/images/new/dianliu.png" />
  233. <view class="item-value" v-if="deviceV == 0">0A</view>
  234. <view class="item-value" v-else>{{currentValue}}A</view>
  235. <span class="item-text">{{$t('charge.current')}}</span>
  236. </view>
  237. <view class="ditem">
  238. <image class="itemimg" src="/static/images/new/shjian.png" />
  239. <view class="item-value">{{ chargeTime }}{{ i18('分钟') }}</view>
  240. <span class="item-text" v-if="portDetail.portStatus == 6">{{i18('剩余时间')}}</span>
  241. <span class="item-text" v-else>{{$t('charge.chargetime')}}</span>
  242. </view>
  243. <view class="ditem">
  244. <image class="itemimg" src="/static/images/new/gonglv.png" />
  245. <view class="item-value">{{ gonglv }}W</view>
  246. <span class="item-text">{{$t('charge.power')}}</span>
  247. </view>
  248. <view class="ditem">
  249. <image class="itemimg" src="/static/images/new/dianliang.png" />
  250. <view class="item-value" v-if="portDetail.voltage == 0">0 {{ i18('度') }}</view>
  251. <view class="item-value" v-else>{{ dianliang }} {{ i18('度') }}</view>
  252. <span class="item-text">{{$t('charge.elec')}}</span>
  253. </view>
  254. </view>
  255. <view class="dbtns">
  256. <view class="start" @click="toPage">
  257. <image style="width:25px;height: 25px;margin-right: 5px;" src="/static/images/new/start.png" />
  258. <span>{{$t('charge.startcharge')}}</span>
  259. </view>
  260. <view class="get" @click="getInfo">
  261. <image style="width:25px;height: 25px;margin-right: 5px;" src="/static/images/new/get.png" />
  262. <span>{{$t('charge.getinfo')}}</span>
  263. </view>
  264. </view> -->
  265. <!-- <view class="dtip">
  266. <view style="margin:10px 0px;color: #1A87FF;"><img style="width: 13px;height: 13px"
  267. src="/static/images/new/tip.png">{{i18('温馨提示')}}</view>
  268. <view>1,{{i18('桩控制最大输出电流,当功率没有达到请检查车的状态或者车的设置')}};</view>
  269. <view>2,{{i18('启动充电-&gt;设备管理->可设置设备最大输出电流')}}</view>
  270. <view>3,{{i18('为保障您远程启动正常充电,请确保枪头完全连接充电口,同时确认您的爱车处于立即充电状态下')}};</view>
  271. <view>4,{{i18('注意规范安全充电,停好车,锁好车。')}}</view>
  272. </view> -->
  273. </view>
  274. </template>
  275. <script>
  276. import {
  277. getDeviceInfo,
  278. getPortDetail,
  279. startCharge,
  280. stopCharge,
  281. sendPortDetailCmd,
  282. checkStatusChange,
  283. getPlanInfo,
  284. cancelPlan
  285. } from "@/api/device/device";
  286. import websocket from '@/utils/websocket'
  287. import i18 from '@/utils/i18.js'
  288. export default {
  289. data() {
  290. return {
  291. refreshTimer: null,
  292. curPort: [],
  293. chargeTime: 0,
  294. deviceTemp: 0,
  295. deviceV: 0,
  296. currentValue: 0,
  297. gonglv: 0,
  298. dianliang: 0,
  299. portStatus: 0,
  300. deviceInfo: {},
  301. visitTime: "",
  302. timer: null,
  303. showPort: false,
  304. portDetail: {
  305. portStatus: 0,
  306. POWER: 0,
  307. voltage: 0
  308. },
  309. statusTimer: "",
  310. connected: false,
  311. scriptTask: null,
  312. choosePort: 1,
  313. portList: [
  314. [{
  315. port: 1,
  316. text: "端口一"
  317. }]
  318. ],
  319. planInfo: null,
  320. days: ["", "周一", "周二", "周三", "周四", "周五", "周六", "周日"],
  321. clickRightTag: 0
  322. }
  323. },
  324. computed: {
  325. imgUrl() {
  326. return getApp().globalData.config.imgUrl;
  327. }
  328. },
  329. onLoad(opt) {
  330. this.deviceInfo.deviceId = opt.id;
  331. this.deviceInfo.ccid = opt.ccid;
  332. this.deviceInfo.qrcode = opt.qrcode;
  333. this.startTimer();
  334. },
  335. onShow() {
  336. this.getInfo();
  337. this.getPlanInfo();
  338. },
  339. onUnload() {
  340. this.closeSocket();
  341. if (this.refreshTimer != null) {
  342. clearTimeout(this.refreshTimer)
  343. }
  344. },
  345. mounted: function() {
  346. this.drawCircle(100);
  347. this.drawProgressbg();
  348. //参数为1-100
  349. this.drawLine();
  350. },
  351. methods: {
  352. resetMainboard() {
  353. let deviceId = this.deviceId;
  354. // 恢复默认配置
  355. let self = this;
  356. this.$modal.loading("正在重置,请稍等...");
  357. reset({deviceId:deviceId,ccid:this.ccid}).then(res => {
  358. this.$modal.loading("正在重置,请稍等...");
  359. setTimeout(function(){
  360. self.sendMainboardCmd();
  361. },5000)
  362. })
  363. },
  364. skipPage(type){
  365. if(type==0){
  366. uni.navigateTo({
  367. url:'/pages/index'
  368. })
  369. }else if(type==1){
  370. uni.navigateTo({
  371. url:'/pages/weitiandi/deviceList'
  372. })
  373. }else if(type==2){
  374. uni.navigateTo({
  375. url:'/pages/mine/index'
  376. })
  377. }else{
  378. this.$modal.showToast("功能开发中..");
  379. }
  380. },
  381. handleLogout() {
  382. this.$modal.confirm('确定注销并退出系统吗?').then(() => {
  383. this.$store.dispatch('LogOut').then(() => {
  384. uni.setStorageSync("loginInfo",'');
  385. this.$tab.reLaunch('/pages/index')
  386. })
  387. })
  388. },
  389. changeDrawer(event) {
  390. if (event) {
  391. // 抽屉打开时的逻辑
  392. this.clickRightTag = 1
  393. } else {
  394. // 抽屉关闭时的逻辑
  395. this.clickRightTag = 0
  396. }
  397. },
  398. //自定义头右操作函数
  399. clickRight() {
  400. //打开抽屉
  401. if (this.clickRightTag == 0) {
  402. this.$refs.showRight.open();
  403. this.clickRightTag = 1
  404. } else {
  405. this.$refs.showRight.close()
  406. this.clickRightTag = 0
  407. }
  408. },
  409. //开始充电按钮
  410. trigger() {
  411. let portStatus = this.portDetail.portStatus;
  412. if (portStatus == 2) { //需要停止充电
  413. this.$modal.confirm("需要停止充电么?").then(res => {
  414. this.stopCharge();
  415. })
  416. } else {
  417. if (portStatus == 1) {
  418. this.$modal.msg("请先将充电枪插入后再点击充电");
  419. }
  420. if (portStatus == 5) {
  421. this.$modal.confirm("确认开始充电么?").then(res => {
  422. this.startCharge();
  423. })
  424. }
  425. }
  426. },
  427. drawProgressbg: function() {
  428. // 自定义组件实例 this ,表示在这个自定义组件下查找拥有 canvas-id 的 <canvas/>
  429. var ctx = uni.createCanvasContext('cpbg', this);
  430. ctx.setLineWidth(19); // 设置圆环的宽度
  431. ctx.setStrokeStyle('#E9E9E9'); // 设置圆环的颜色
  432. // ctx.setLineCap('round'); // 设置圆环端点的形状
  433. ctx.setLineCap('square'); // 设置圆环端点的形状
  434. ctx.beginPath(); //开始一个新的路径
  435. ctx.arc(90, 90, 80, 0 * Math.PI, 2 * Math.PI, false);
  436. //设置一个原点(110,110),半径为100的圆的路径到当前路径
  437. ctx.stroke(); //对当前路径进行描边
  438. ctx.draw();
  439. },
  440. drawCircle: function(step) {
  441. var ctx = uni.createCanvasContext('cpbar', this);
  442. // 进度条的渐变(中心x坐标-半径-边宽,中心Y坐标,中心x坐标+半径+边宽,中心Y坐标)
  443. var gradient = ctx.createLinearGradient(0, 0, 130, 0);
  444. let increase = 0.05;
  445. let end = (step / 100) * 2 * Math.PI - Math.PI / 2; // 最后的角度
  446. let current = -Math.PI / 2; // 起始角度
  447. if(this.portDetail.portStatus != 2){
  448. let timer = setInterval(() => {
  449. gradient.addColorStop('0', '#57B03D');
  450. gradient.addColorStop('1.0', '#57B03D');
  451. ctx.setLineWidth(12);
  452. ctx.setStrokeStyle(gradient);
  453. ctx.setLineCap('square');
  454. ctx.beginPath();
  455. // 参数step 为绘制的百分比
  456. if (current < end) {
  457. current = current + increase;
  458. }
  459. if (current >= end) {
  460. current = end;
  461. if(this.portDetail.portStatus != 2){
  462. clearInterval(timer);
  463. }else{
  464. current = -Math.PI / 2; // 起始角度
  465. }
  466. }
  467. ctx.arc(90, 90, 80, -Math.PI / 2, current, false);
  468. ctx.stroke();
  469. ctx.draw();
  470. }, 20);
  471. }
  472. },
  473. // 画刻度
  474. drawLine() {
  475. var context = uni.createCanvasContext("cpline", this);
  476. var r = 80;
  477. var x0 = 90;
  478. var y0 = 90;
  479. var x;
  480. var y;
  481. var lineWidth = 15;
  482. for (let i = 0; i < 60; i++) {
  483. context.beginPath();
  484. context.setLineWidth(lineWidth);
  485. context.setStrokeStyle("#FFFFFF");
  486. x = x0 - r * Math.sin(((6 * (i + 1) - 3) * Math.PI) / 180);
  487. y = y0 - r * Math.cos(((6 * (i + 1) - 3) * Math.PI) / 180);
  488. // console.log('x0:' + x0 + ' y0:' + y0 + ' x:' + x + ' y:' + y);
  489. context.moveTo(x, y);
  490. context.arc(
  491. x0,
  492. y0,
  493. r,
  494. ((270 - 6 * (i + 1) + 3) * Math.PI) / 180,
  495. ((270 - 6 * i) * Math.PI) / 180,
  496. false
  497. );
  498. context.stroke();
  499. context.closePath();
  500. }
  501. context.stroke();
  502. context.draw();
  503. },
  504. toPage() {
  505. let imei = this.deviceInfo.deviceId;
  506. let ccid = this.deviceInfo.ccid;
  507. this.closeSocket();
  508. uni.navigateTo({
  509. url: '/pages/weitiandi/device/index?id=' + imei + '&ccid=' + ccid
  510. });
  511. },
  512. toSetting(){
  513. let imei = this.deviceInfo.deviceId;
  514. let ccid = this.deviceInfo.ccid;
  515. this.closeSocket();
  516. uni.navigateTo({
  517. url: '/pages/weitiandi/device/setting?id=' + imei + '&ccid=' + ccid
  518. });
  519. },
  520. i18(text) {
  521. return i18(text)
  522. },
  523. planCharge() {
  524. if (this.planInfo != null) {
  525. this.$modal.confirm("确认取消预约?").then(res => {
  526. this.cancelPlan();
  527. })
  528. } else {
  529. this.toPlan()
  530. }
  531. },
  532. cancelPlan() {
  533. cancelPlan(this.planInfo.id).then(res => {
  534. this.$modal.msg("取消成功");
  535. this.planInfo = null;
  536. this.getPlanInfo();
  537. })
  538. },
  539. getPlanInfo() {
  540. getPlanInfo(this.deviceInfo.deviceId, this.choosePort).then(res => {
  541. let data = res.data;
  542. if (data != null) {
  543. let planType = data.planType;
  544. if (planType == 1) { //单次预约
  545. let planInfo = {};
  546. planInfo.runTime = data.runTime;
  547. this.planInfo = planInfo;
  548. this.planInfo.id = data.id;
  549. } else {
  550. let planInfo = {};
  551. planInfo.runTime = data.runTime;
  552. let repeatDays = data.repeatDays;
  553. let days = repeatDays.split(",")
  554. let strs = "";
  555. for (let i = 0; i < days.length; i++) {
  556. if (strs.length > 0) {
  557. strs += ",";
  558. }
  559. strs += this.days[days[i]];
  560. }
  561. this.planInfo = planInfo;
  562. this.planInfo.runTime = strs + " " + data.repeatTime;
  563. this.planInfo.id = data.id;
  564. }
  565. }
  566. })
  567. },
  568. startTimer() {
  569. let self = this;
  570. if (this.refreshTimer != null) {
  571. clearTimeout(this.refreshTimer);
  572. }
  573. self.refreshTimer = setTimeout(function() {
  574. self.getInfo();
  575. self.startTimer();
  576. }, 30000);
  577. },
  578. confirmPort(e) {
  579. let value = e.value[0]
  580. this.choosePort = value.port;
  581. this.showPort = false;
  582. this.getInfo()
  583. },
  584. parsePortCmd(real_data) {
  585. let self = this;
  586. self.portDetail = real_data;
  587. self.portList = [
  588. []
  589. ];
  590. self.curPort = [];
  591. let port_first_status = self.portDetail["port_first_status"];
  592. let port_second_status = self.portDetail["port_second_status"]
  593. if (port_first_status) {
  594. self.portList[0].push({
  595. port: 1,
  596. text: "端口一"
  597. });
  598. self.curPort.push({
  599. text: "端口一",
  600. status: port_first_status,
  601. id: 1,
  602. })
  603. let power = self.portDetail.power;
  604. let voltage = parseInt(self.portDetail.voltage);
  605. if (voltage > 0) {
  606. let current = power / voltage;
  607. current = current.toFixed(1);
  608. self.portDetail.currentValue = current;
  609. }
  610. }
  611. if (port_second_status) {
  612. self.portList[0].push({
  613. port: 2,
  614. text: "端口二"
  615. });
  616. self.curPort.push({
  617. text: "端口二",
  618. status: port_second_status,
  619. id: 2
  620. })
  621. let power = self.portDetail.power_1;
  622. let voltage = parseInt(self.portDetail.voltage);
  623. if (voltage > 0) {
  624. let current = power / voltage;
  625. current = current.toFixed(1);
  626. self.portDetail.currentValue_1 = current;
  627. }
  628. }
  629. let choosePort = self.choosePort
  630. /**
  631. * chargeTime:0,
  632. * deviceTemp:0,
  633. * deviceV:0,
  634. * currentValue:0,
  635. * gonglv:0,
  636. * dianliang:0,
  637. * portStatus:0,
  638. */
  639. if (choosePort == 1) {
  640. self.portDetail.portStatus = port_first_status;
  641. self.chargeTime = self.portDetail.time;
  642. self.gonglv = self.portDetail.power;
  643. self.dianliang = self.portDetail.elec / 100;
  644. self.currentValue = self.portDetail.currentValue;
  645. if (port_first_status != 2) {
  646. self.chargeTime = 0;
  647. if (port_first_status == 6) {
  648. self.chargeTime = self.portDetail.time;
  649. }
  650. self.gonglv = 0;
  651. self.dianliang = 0;
  652. self.currentValue = 0;
  653. }
  654. } else if (choosePort == 2) {
  655. self.portDetail.portStatus = port_second_status;
  656. self.chargeTime = self.portDetail.time_1;
  657. self.gonglv = self.portDetail.power_1;
  658. self.dianliang = self.portDetail.elec_1 / 100;
  659. self.currentValue = self.portDetail.currentValue_1;
  660. if (port_second_status != 2) {
  661. self.chargeTime = 0;
  662. if (port_first_status == 6) {
  663. self.chargeTime = self.portDetail.time_1;
  664. }
  665. self.gonglv = 0;
  666. self.dianliang = 0;
  667. self.currentValue = 0;
  668. }
  669. }
  670. self.portStatus = self.portDetail.portStatus;
  671. self.deviceTemp = self.portDetail.dev_temper;
  672. self.deviceV = self.portDetail.voltage;
  673. self.$modal.closeLoading();
  674. if(self.portDetail.portStatus==2){
  675. this.drawCircle(100);
  676. }
  677. },
  678. initSocket(key) {
  679. let self = this;
  680. let socketUrl = getApp().globalData.config.socketUrl
  681. this.scriptTask = websocket({
  682. url: "/" + key + "/",
  683. });
  684. let scriptTask = this.scriptTask;
  685. scriptTask.onOpen(function(res) {
  686. console.log('WebSocket连接已打开!');
  687. self.connected = true;
  688. });
  689. scriptTask.onError(function(res) {
  690. self.connected = false;
  691. console.log(res);
  692. });
  693. scriptTask.onMessage(function(res) {
  694. let data = JSON.parse(res.data);
  695. let type = data.type;
  696. let real_data = data.real_data;
  697. if (type == 103) {
  698. self.parsePortCmd(real_data);
  699. }
  700. if (type == 116) {
  701. self.$modal.closeLoading();
  702. self.getInfo();
  703. }
  704. if (type == 113) {
  705. self.$modal.closeLoading();
  706. self.getInfo();
  707. }
  708. if (type == 96) {
  709. self.mainBoardInfo = real_data;
  710. self.formatMainboardData();
  711. self.$modal.closeLoading();
  712. }
  713. self.$forceUpdate();
  714. console.log('收到服务器内容:' + JSON.stringify(data));
  715. });
  716. scriptTask.onClose(function(res) {
  717. console.log('WebSocket 已关闭!');
  718. });
  719. },
  720. toSet() {
  721. this.closeSocket();
  722. uni.navigateTo({
  723. url: '/pages/weitiandi/device/setting?id=' + this.deviceInfo.deviceId + "&ccid=" + this
  724. .deviceInfo.ccid
  725. });
  726. },
  727. toPlan() {
  728. uni.navigateTo({
  729. url: '/pages/weitiandi/device/plan?port=' + this.choosePort + '&id=' + this.deviceInfo
  730. .deviceId + "&ccid=" + this.deviceInfo.ccid
  731. });
  732. },
  733. trigger() {
  734. let portStatus = this.portDetail.portStatus;
  735. if (portStatus == 2) { //需要停止充电
  736. this.$modal.confirm("需要停止充电么?").then(res => {
  737. this.stopCharge();
  738. this.drawCircle(0);
  739. })
  740. } else {
  741. if (portStatus == 1) {
  742. this.$modal.msg("请先将充电枪插入后再点击充电");
  743. }
  744. if (portStatus == 5) {
  745. this.$modal.confirm("确认开始充电么?").then(res => {
  746. this.startCharge();
  747. this.drawCircle(100); //参数为1-100
  748. })
  749. }
  750. }
  751. },
  752. getInfo() {
  753. let self = this;
  754. this.$modal.loading("正在获取状态,请稍等...");
  755. sendPortDetailCmd(this.deviceInfo).then(res => {
  756. this.$modal.loading("正在获取状态,请稍等...");
  757. this.visitTime = res.msg;
  758. if (!this.visitTime) {
  759. this.$modal.msg("请重新进入页面");
  760. return;
  761. }
  762. if (!this.scriptTask) {
  763. this.initSocket(this.deviceInfo.deviceId);
  764. }
  765. setTimeout(function() {
  766. getPortDetail(self.deviceInfo, self.visitTime).then(res => {
  767. let data = res.data;
  768. if (data != null) {
  769. self.parsePortCmd(data);
  770. } else {}
  771. });
  772. }, 500)
  773. })
  774. },
  775. stopCharge() {
  776. let self = this;
  777. this.deviceInfo.port = this.choosePort;
  778. stopCharge(this.deviceInfo).then(() => {
  779. self.$modal.loading("停止成功");
  780. setTimeout((() => {
  781. self.getInfo();
  782. }), 1000);
  783. })
  784. },
  785. startCharge() {
  786. let self = this;
  787. this.deviceInfo.port = this.choosePort;
  788. startCharge(this.deviceInfo).then(res => {
  789. self.$modal.loading("启动成功");
  790. setTimeout((() => {
  791. self.getInfo();
  792. }), 1000);
  793. })
  794. },
  795. getPortInfo() {
  796. this.startPortDetailTimer();
  797. },
  798. startPortDetailTimer() {
  799. let self = this;
  800. this.timer = setTimeout(function() {
  801. getPortDetail(self.deviceInfo, self.visitTime).then(res => {
  802. let data = res.data;
  803. if (data != null) {
  804. self.portDetail = data;
  805. self.checkStatusCheck();
  806. self.$modal.closeLoading();
  807. } else {
  808. self.startPortDetailTimer();
  809. }
  810. });
  811. }, 1000);
  812. },
  813. checkStatusCheck() {
  814. this.statusChangeTimer();
  815. },
  816. checkOnPage() {
  817. var pages = getCurrentPages() // 获取栈实例
  818. let currentRoute = pages[pages.length - 1].route; // 获取当前页面路由
  819. if ("pages/weitiandi/device/index" != currentRoute) {
  820. return false;
  821. }
  822. return true;
  823. },
  824. closeSocket() {
  825. this.scriptTask.close();
  826. this.scriptTask = null;
  827. },
  828. statusChangeTimer() {
  829. let self = this;
  830. this.statusTimer = setTimeout(function() {
  831. if (!this.checkOnPage()) {
  832. return;
  833. }
  834. checkStatusChange(self.deviceInfo, self.visitTime).then(res => {
  835. let data = res.data;
  836. if (data != null) {
  837. self.getInfo();
  838. } else {
  839. self.statusChangeTimer();
  840. }
  841. });
  842. }, 3000);
  843. },
  844. wifi() {
  845. uni.navigateTo({
  846. url: '/pages/bluetooth/index/wifi'
  847. });
  848. },
  849. }
  850. }
  851. </script>
  852. <style>
  853. .container {
  854. /* //background: rgb(208, 208, 208); */
  855. background-image: url('../../../static/images/new/starts/bg1.jpg');
  856. inset: 0;
  857. position: absolute;
  858. background-size: cover;
  859. background-repeat: no-repeat;
  860. }
  861. .prop-item {
  862. position: relative;
  863. display: flex;
  864. flex-direction: row;
  865. height: 40px;
  866. line-height: 40px;
  867. margin: 0 20rpx;
  868. }
  869. .prop-item-left {
  870. color: #BCBCBF;
  871. ;
  872. width: 30%;
  873. font-size: 14px;
  874. //margin-left: 36px;
  875. }
  876. .prop-item-image {
  877. width: 15px;
  878. height: 15px;
  879. position: absolute;
  880. left: 2vw;
  881. top: 0.5vh;
  882. }
  883. .prop-item-right {
  884. position: absolute;
  885. right: 10rpx;
  886. top: 5rpx;
  887. color: #BCBCBF;
  888. }
  889. .progress_box {
  890. /* position: relative; */
  891. width: 35vh;
  892. height: 35vh;
  893. /* background-color: red; */
  894. display: inline-block;
  895. align-items: center;
  896. justify-content: center;
  897. text-align: center;
  898. }
  899. .pcds {
  900. margin-top: 90rpx;
  901. color: black;
  902. }
  903. .progress_bg {
  904. position: absolute;
  905. width: 30vh;
  906. height: 30vh;
  907. }
  908. .progress_txt {
  909. position: absolute;
  910. font-size: 28upx;
  911. margin-top: 54px;
  912. margin-left: 74px;
  913. color: #999999;
  914. }
  915. .progress_bar {
  916. position: absolute;
  917. width: 30vh;
  918. height: 30vh;
  919. }
  920. .progress_line {
  921. position: absolute;
  922. width: 30vh;
  923. height: 30vh;
  924. }
  925. .progress_info {
  926. font-size: 25upx;
  927. /* padding-left: 16upx; */
  928. letter-spacing: 2upx;
  929. margin: 1vh 0vh 0vh -3vh;
  930. }
  931. .header {
  932. position: relative;
  933. margin-top: 4vw;
  934. }
  935. .header-status-desc {
  936. position: absolute;
  937. text-align: center;
  938. width: 100%;
  939. bottom: 1vh;
  940. font-size: 5vw;
  941. font-weight: bold;
  942. color: #0E9F9B;
  943. margin-bottom: 5vw;
  944. }
  945. .header-status {
  946. font-weight: bold;
  947. text-align: center;
  948. }
  949. .chong-active {
  950. color: #0E9F9B
  951. }
  952. .header-img {
  953. width: 100%;
  954. padding: 5% 10%;
  955. text-align: center;
  956. }
  957. .header-img image {
  958. width: 100%;
  959. height: 23vh;
  960. }
  961. .info-body {
  962. background: #0E9F9B;
  963. height: 20vh;
  964. margin: 0 2%;
  965. border-radius: 1vw;
  966. margin-top: 2vh;
  967. color: #F8FCFF;
  968. line-height: 3vh;
  969. }
  970. .info-content {
  971. display: inline-block;
  972. width: 23%;
  973. text-align: center;
  974. margin: 1%;
  975. margin-top: 2.5vh;
  976. }
  977. .info-content-value {
  978. font-weight: bold;
  979. }
  980. .info-content-text {}
  981. .info-summary {
  982. display: flex;
  983. flex-direction: row;
  984. text-align: center;
  985. margin: 3vh 0;
  986. }
  987. .summary {
  988. width: 33%;
  989. line-height: 2.5vh;
  990. }
  991. .charge-num {
  992. color: #0E9F9B;
  993. font-weight: bold;
  994. font-size: 4.5vw;
  995. }
  996. .charge-title {
  997. color: #B2B2B2;
  998. font-weight: 400;
  999. }
  1000. .btn-image {
  1001. width: 90%;
  1002. height: 100%;
  1003. }
  1004. .info-bottom-btn {
  1005. display: flex;
  1006. flex-direction: row;
  1007. text-align: center;
  1008. position: relative;
  1009. margin-top: 10vh;
  1010. }
  1011. .btn-area {
  1012. width: 50%;
  1013. height: 50px;
  1014. }
  1015. .left {
  1016. position: relative;
  1017. left: 10px;
  1018. text-align: right;
  1019. }
  1020. .right {
  1021. text-align: left;
  1022. position: relative;
  1023. right: 10px;
  1024. }
  1025. .info-plan {
  1026. text-align: center;
  1027. color: #0E9F9B;
  1028. margin-top: 1vh;
  1029. font-weight: 400;
  1030. }
  1031. .setting {
  1032. position: fixed;
  1033. right: -1px;
  1034. top: 10vh;
  1035. z-index: 999;
  1036. background: rgb(227, 243, 245);
  1037. color: #0E9F9B;
  1038. font-size: 10px;
  1039. border-radius: 5px;
  1040. padding: 3px;
  1041. }
  1042. .port {
  1043. height: 70px;
  1044. background: #F8FCFF;
  1045. border: 0px solid #F8FCFF;
  1046. box-shadow: 0px 0px 6px 1px rgba(101, 101, 101, 0.29);
  1047. border-radius: 4px;
  1048. margin: 0 10px;
  1049. position: relative;
  1050. margin-top: 10px;
  1051. }
  1052. .plan {
  1053. height: 70px;
  1054. background: #F8FCFF;
  1055. border: 0px solid #F8FCFF;
  1056. box-shadow: 0px 0px 6px 1px rgba(101, 101, 101, 0.29);
  1057. border-radius: 4px;
  1058. margin: 0 10px;
  1059. position: relative;
  1060. margin-top: 15px;
  1061. }
  1062. .port-image {
  1063. height: 40px;
  1064. width: 40px;
  1065. position: absolute;
  1066. top: 15px;
  1067. left: 20px;
  1068. }
  1069. .port-text {
  1070. position: absolute;
  1071. top: 13px;
  1072. left: 75px;
  1073. font-weight: bold;
  1074. }
  1075. .port-num {
  1076. position: absolute;
  1077. top: 38px;
  1078. left: 75px;
  1079. color: #B2B2B2;
  1080. }
  1081. .port-icon {
  1082. position: absolute;
  1083. top: 30px;
  1084. right: 5px;
  1085. width: 10px;
  1086. height: 16px;
  1087. }
  1088. .port-icon image {
  1089. width: 90%;
  1090. }
  1091. .body-bottom {
  1092. padding: 0 22px;
  1093. }
  1094. .body-bottom .info-content {
  1095. width: 30%;
  1096. }
  1097. .bottom-control {
  1098. height: 22vh;
  1099. margin: 0 2%;
  1100. margin-top: 2vh;
  1101. line-height: 3vh;
  1102. background: #F8FCFF;
  1103. border: 0px solid #F8FCFF;
  1104. box-shadow: 0px 0px 6px 1px rgba(101, 101, 101, 0.29);
  1105. border-radius: 4px;
  1106. padding: 3%;
  1107. }
  1108. .control-btn {
  1109. display: inline-block;
  1110. ;
  1111. height: 60px;
  1112. width: 25%;
  1113. padding: 10px 20px;
  1114. text-align: center;
  1115. font-size: 12px;
  1116. color: black;
  1117. }
  1118. .control-btn .btn-image {}
  1119. #box {
  1120. /* width: 300px; */
  1121. height: 280px;
  1122. position: relative;
  1123. /* 背景色 */
  1124. /* background: #f7f6f6; */
  1125. overflow: hidden;
  1126. /* padding: 50px 0; */
  1127. box-sizing: border-box;
  1128. ;
  1129. }
  1130. .box {
  1131. width: 100%;
  1132. height: 100%;
  1133. position: absolute;
  1134. display: flex;
  1135. justify-content: center;
  1136. /* 此处尽量不要设置背景色,可以选择在父标签上设置背景色,否则没有黏黏的效果 */
  1137. filter: url("#goo");
  1138. }
  1139. /* 电量文字 */
  1140. .text {
  1141. font-weight: 200;
  1142. font-size: 20px;
  1143. margin-top: 5px;
  1144. text-align: center;
  1145. color: #ff6600;
  1146. }
  1147. /* 电量文字 */
  1148. .text span {
  1149. font-size: 15px;
  1150. }
  1151. /* 顶部的两个旋转小球 */
  1152. .top_ball {
  1153. width: 200px;
  1154. height: 200px;
  1155. border-radius: 35%;
  1156. opacity: 0.5;
  1157. position: absolute;
  1158. top: 20px;
  1159. z-index: 10;
  1160. /* 从中心向外剪切圆,相当于掏空 */
  1161. -webkit-mask: radial-gradient(transparent 95px, white 0px);
  1162. }
  1163. /* 顶部的两个旋转小球 */
  1164. .top_ball.one {
  1165. background: var(--c);
  1166. animation: ballZhuan 5s linear infinite;
  1167. }
  1168. /* 顶部的两个旋转小球 */
  1169. .top_ball.two {
  1170. background: var(--c);
  1171. animation: ballZhuan 8s linear infinite;
  1172. }
  1173. .three {
  1174. width: 170px;
  1175. height: 170px;
  1176. border-radius: 300px;
  1177. opacity: 1;
  1178. position: absolute;
  1179. top: 20px;
  1180. z-index: 10;
  1181. /* 从中心向外剪切圆,相当于掏空 */
  1182. /* -webkit-mask: radial-gradient(transparent 95px, white 0px); */
  1183. background: #ffffff;
  1184. /* animation: ballZhuan 9s linear infinite; */
  1185. overflow: hidden;
  1186. box-shadow: 0px 0px 19px 1px #2196f3;
  1187. }
  1188. .four {
  1189. width: 200px;
  1190. height: 200px;
  1191. border-radius: 80px;
  1192. opacity: 0.3;
  1193. position: absolute;
  1194. top: 10px;
  1195. z-index: 10;
  1196. /* 从中心向外剪切圆,相当于掏空 */
  1197. /* -webkit-mask: radial-gradient(transparent 95px, white 0px); */
  1198. background: #2196f3;
  1199. animation: ballZhuan1 linear infinite;
  1200. animation-duration: 11s;
  1201. }
  1202. .five {
  1203. width: 270px;
  1204. height: 270px;
  1205. border-radius: 99px;
  1206. opacity: 0.6;
  1207. position: absolute;
  1208. top: 30px;
  1209. z-index: 10;
  1210. /* 从中心向外剪切圆,相当于掏空 */
  1211. /* -webkit-mask: radial-gradient(transparent 95px, white 0px); */
  1212. background: #2196f3;
  1213. animation: ballZhuan1 linear infinite;
  1214. /* transform: rotate(120deg); */
  1215. animation-duration: 9s;
  1216. left: -67px;
  1217. }
  1218. .six {
  1219. width: 270px;
  1220. height: 270px;
  1221. border-radius: 99px;
  1222. opacity: 0.6;
  1223. position: absolute;
  1224. top: 30px;
  1225. z-index: 10;
  1226. /* 从中心向外剪切圆,相当于掏空 */
  1227. /* -webkit-mask: radial-gradient(transparent 95px, white 0px); */
  1228. background: #2196f3;
  1229. animation: ballZhuan1 7s linear infinite;
  1230. /* transform: rotate(120deg); */
  1231. right: -67px;
  1232. }
  1233. @keyframes ballZhuan {
  1234. 100% {
  1235. transform: rotate(360deg);
  1236. }
  1237. }
  1238. @keyframes ballZhuan1 {
  1239. 100% {
  1240. transform: rotate(360deg);
  1241. }
  1242. }
  1243. /* 底部的小球 */
  1244. .dot {
  1245. display: block;
  1246. width: 20px;
  1247. height: 20px;
  1248. border-radius: 50%;
  1249. background: rgba(101, 192, 255, 0.28);
  1250. position: absolute;
  1251. z-index: 1000;
  1252. bottom: -50px;
  1253. }
  1254. .dot:nth-of-type(1) {
  1255. width: 40px;
  1256. height: 40px;
  1257. right: 116px;
  1258. animation: dotMove 5s linear infinite;
  1259. }
  1260. .dot:nth-of-type(2) {
  1261. width: 50px;
  1262. height: 50px;
  1263. left: 120px;
  1264. animation: dotMove 4s linear infinite;
  1265. }
  1266. .dot:nth-of-type(3) {
  1267. animation: dotMove 2s linear infinite;
  1268. }
  1269. .dot:nth-of-type(4) {
  1270. width: 15px;
  1271. height: 15px;
  1272. left: 130px;
  1273. animation: dotMove 2s linear infinite;
  1274. }
  1275. .dot:nth-of-type(5) {
  1276. width: 30px;
  1277. height: 30px;
  1278. animation: dotMove 3s linear infinite;
  1279. }
  1280. @keyframes dotMove {
  1281. 0% {
  1282. transform: translateY(0px);
  1283. opacity: 1;
  1284. }
  1285. 98% {
  1286. opacity: 1;
  1287. }
  1288. 100% {
  1289. transform: translateY(-260px);
  1290. opacity: 0;
  1291. }
  1292. }
  1293. .w-flex {
  1294. display: -webkit-box;
  1295. display: -webkit-flex;
  1296. display: flex;
  1297. padding: 0px 25px;
  1298. }
  1299. .w-flex__item {
  1300. -webkit-box-flex: 1;
  1301. -webkit-flex: 1;
  1302. flex: 1;
  1303. }
  1304. .w-item {
  1305. text-align: center;
  1306. padding: 5px;
  1307. }
  1308. .w-item-tit {
  1309. font-size: 14px;
  1310. color: #888;
  1311. }
  1312. .w-item-num {
  1313. font-size: 18px;
  1314. color: #111;
  1315. }
  1316. .can {
  1317. position: relative;
  1318. z-index: 0;
  1319. width: 211px;
  1320. height: 211px;
  1321. background-size: cover;
  1322. display: flex;
  1323. justify-content: center;
  1324. align-items: center;
  1325. }
  1326. .dtop {
  1327. background: url(/static/images/new/box1.png);
  1328. background-size: cover;
  1329. width: 260px;
  1330. height: 236px;
  1331. display: flex;
  1332. justify-content: center;
  1333. align-items: center;
  1334. left: 15%;
  1335. position: relative;
  1336. }
  1337. .dstatus {
  1338. margin-top: 0.1rem;
  1339. display: flex;
  1340. flex-wrap: wrap;
  1341. justify-content: space-evenly;
  1342. align-content: center;
  1343. }
  1344. .ditem {
  1345. width: 30%;
  1346. display: flex;
  1347. flex-direction: column;
  1348. align-items: center;
  1349. margin-bottom: 0.3rem;
  1350. margin-top: 10px;
  1351. }
  1352. .itemimg {
  1353. width: 50px;
  1354. height: 50px;
  1355. }
  1356. .item-value {
  1357. font-weight: bold;
  1358. font-size: 15px;
  1359. margin: 4px 0;
  1360. }
  1361. .item-text {
  1362. font-size: 11px;
  1363. margin: 1px 0;
  1364. color: #999999;
  1365. }
  1366. .start {
  1367. background: #1A87FF;
  1368. color: #fff;
  1369. width: 45%;
  1370. height: 50px;
  1371. min-height: 40px;
  1372. border-radius: 50px;
  1373. display: flex;
  1374. justify-content: center;
  1375. align-items: center;
  1376. font-size: 20px;
  1377. font-weight: bold;
  1378. }
  1379. .dbtns {
  1380. display: flex;
  1381. margin-top: 10px;
  1382. justify-content: space-between;
  1383. padding: 0 30px;
  1384. }
  1385. .get {
  1386. background: #fff;
  1387. border: 1px solid #1A87FF;
  1388. color: #1A87FF;
  1389. width: 45%;
  1390. height: 50px;
  1391. min-height: 40px;
  1392. border-radius: 50px;
  1393. display: flex;
  1394. justify-content: center;
  1395. align-items: center;
  1396. font-size: 20px;
  1397. font-weight: bold;
  1398. }
  1399. .dtip {
  1400. margin: 20px 20px;
  1401. padding: 10px;
  1402. background: rgba(127, 200, 251, 0.1);
  1403. border: 1px solid #7FC8FB;
  1404. box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.19);
  1405. border-radius: 5px;
  1406. font-size: 17px;
  1407. font-weight: 400;
  1408. color: #B8B9BA;
  1409. margin-bottom: 10px;
  1410. }
  1411. .p1 {
  1412. font-size: 20px;
  1413. color: white;
  1414. font-weight: bold;
  1415. margin-top: 10px;
  1416. /* margin-left: -1vh;; */
  1417. }
  1418. .stip {
  1419. text-align: center;
  1420. z-index: 9999;
  1421. }
  1422. </style>