index.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. <template>
  2. <view class="container">
  3. <view class="dboxs dport">
  4. <view class="dboxtitle"><image class="portimg" src="/static/images/new/start/port.png"/>
  5. <view class="dboxtitle-text"> {{ i18('设备端口') }}</view>
  6. </view>
  7. <view class="dportitems">
  8. <view class="dportitem " v-for="item in curPort" @click="selectPort(item.id);">
  9. <p class="dpropitem-title "> {{ item.text }}</p>
  10. <view style="position: absolute;right: 0px;z-index: 9999" v-if="item.id == choosePort">
  11. <image class="dportitem-img" style="width: 15px;height: 15px" src="/static/images/new/start/choose.png"/>
  12. </view>
  13. <view class="dpropitem-block dportitem-block-2" v-if="item.status == 2">
  14. <image class="dportitem-img" src="/static/images/new/start/using.png"/>
  15. <view class="dpropitem-status">{{ i18('充电中') }}</view>
  16. </view>
  17. <view class="dpropitem-block dportitem-block-1" v-if="item.status == 1 || item.status == 7">
  18. <image class="dportitem-img" src="/static/images/new/start/free.png"/>
  19. <view class="dpropitem-status">{{ i18('空闲中') }}</view>
  20. </view>
  21. <view class="dpropitem-block dportitem-block-3" style="background: rgb(247,238,240);color:#FF6868" v-if="item.status == 3">
  22. <image class="dportitem-img" src="/static/images/new/start/ban.png"/>
  23. <view class="dpropitem-status">{{ i18('禁用中') }}</view>
  24. </view>
  25. <view class="dpropitem-block dportitem-block-3" style="background: rgb(248,244,230);color:#FFAA00" v-if="item.status == 4">
  26. <image class="dportitem-img" src="/static/images/new/start/bad.png"/>
  27. <view class="dpropitem-status">{{ i18('故障中') }}</view>
  28. </view>
  29. <view class="dpropitem-block dportitem-block-3" style=";" v-if="item.status == 5">
  30. <image class="dportitem-img" src="/static/images/new/start/lianjie.png"/>
  31. <view class="dpropitem-status">{{ i18('已连接') }}</view>
  32. </view>
  33. <view class="dpropitem-block dportitem-block-3" style="background: rgb(239,235,254);color:#A552FF" v-if="item.status == 6">
  34. <image class="dportitem-img" src="/static/images/new/start/yuyue.png"/>
  35. <view class="dpropitem-status">{{ i18('已预约') }}</view>
  36. </view>
  37. </view>
  38. </view>
  39. </view>
  40. <view class="dboxs dport" style="height: 100px" @click="planCharge">
  41. <view class="dboxtitle"><image class="portimg" src="/static/images/new/start/clock.png"/>
  42. <view class="dboxtitle-text">{{ i18('预约充电') }}</view>
  43. </view>
  44. <view class="port-text" v-if="planInfo != null" style="left:40px;top:48px;font-size: 14px">
  45. {{ i18('已预约') }} {{planInfo.runTime}}
  46. </view>
  47. <view class="port-text" style="left:40px;top:55px;font-size: 14px" v-else>
  48. {{ i18('点击预约充电') }}
  49. </view>
  50. <view class="port-num" style="left:40px;top:70px;font-size: 12px" v-if="planInfo != null">
  51. {{ i18('可点击取消预约') }}
  52. </view>
  53. <view class="port-icon" v-if="planInfo == null" style="width: 50px;height: 50px;right:10px;top:28%">
  54. <image class="btn-image" src="/static/images/new/start/clock.png" >
  55. </image>
  56. </view>
  57. <view class="port-icon" v-if="planInfo != null" style="width: 50px;height: 50px;right:10px;top:28%">
  58. <image class="btn-image" src="/static/images/new/start/del.png" >
  59. </image>
  60. </view>
  61. </view>
  62. <view class="dboxs dport" style="height: 200px">
  63. <view class="dboxtitle"><image class="portimg" src="/static/images/new/start/oper.png"/>
  64. <view class="dboxtitle-text"> {{ i18('设备操作') }}</view>
  65. </view>
  66. <view class="control-btn" @click="trigger()" v-if="portDetail.portStatus == 2">
  67. <image class="btn-image" src="/static/images/new/start/stop.png" >
  68. </image>
  69. <view>{{ i18('停止充电') }}</view>
  70. </view>
  71. <view class="control-btn" @click="trigger()" v-if="portDetail.portStatus != 2">
  72. <image class="btn-image" src="/static/images/new/start/using.png" >
  73. </image>
  74. <view>{{ i18('立即充电') }}</view>
  75. </view>
  76. <view class="control-btn" @click="getInfo">
  77. <image class="btn-image" src="/static/images/new/start/get.png" >
  78. </image>
  79. <view>{{ i18('获取状态') }}</view>
  80. </view>
  81. <view class="control-btn" @click="toSet">
  82. <image class="btn-image" src="/static/images/new/start/oper.png" >
  83. </image>
  84. <view>{{ i18('设备控制') }}</view>
  85. </view>
  86. <view class="control-btn" @click="goBack">
  87. <image class="btn-image" src="/static/images/new/start/back.png" >
  88. </image>
  89. <view>{{ i18('查看状态') }}</view>
  90. </view>
  91. <view class="control-btn" @click="restart">
  92. <image class="btn-image" src="/static/images/new/start/reset.png" >
  93. </image>
  94. <view>{{ i18('重置设备') }}</view>
  95. </view>
  96. </view>
  97. <u-picker @cancel="showPort=false" @confirm="confirmPort" :show="showPort" :columns="portList" keyName="text"></u-picker>
  98. </view>
  99. </template>
  100. <script>
  101. import {getDeviceInfo,getPortDetail,startCharge,stopCharge,sendPortDetailCmd,checkStatusChange,getPlanInfo,cancelPlan} from "@/api/device/device";
  102. import {restart} from '@/api/device/current.js'
  103. import websocket from '@/utils/websocket'
  104. import i18 from '@/utils/i18.js'
  105. export default {
  106. data() {
  107. return {
  108. deviceInfo:{},
  109. visitTime:"",
  110. timer:null,
  111. showPort:false,
  112. portDetail:{portStatus:0,POWER:0,voltage:0},
  113. statusTimer:"",
  114. connected:false,
  115. scriptTask:null,
  116. choosePort:1,
  117. portList:[[{port:1,text:"端口一"}]],
  118. planInfo:null,
  119. days:["","周一","周二","周三","周四","周五","周六","周日"],
  120. curPort:[]
  121. }
  122. },
  123. computed: {
  124. imgUrl() {
  125. return getApp().globalData.config.imgUrl;
  126. }
  127. },
  128. onLoad(opt) {
  129. this.deviceInfo.deviceId = opt.id;
  130. this.deviceInfo.ccid = opt.ccid;
  131. this.deviceInfo.qrcode = opt.qrcode;
  132. },
  133. onShow(){
  134. this.getInfo();
  135. this.getPlanInfo();
  136. },
  137. onUnload (){
  138. this.closeSocket();
  139. },
  140. methods: {
  141. i18(text){
  142. return i18(text)
  143. },
  144. restart(){
  145. let deviceId = this.deviceInfo.deviceId;
  146. this.$modal.loading("正在重置中,请稍等...");
  147. // 重启充电桩
  148. let self = this;
  149. restart({deviceId:deviceId,ccid:this.deviceInfo.ccid}).then(res => {
  150. this.$modal.loading("正在重置中,请稍等...");
  151. setTimeout(function(){
  152. self.getInfo()
  153. },5000)
  154. })
  155. },
  156. goBack(){
  157. uni.navigateBack({
  158. });
  159. },
  160. planCharge(){
  161. if(this.planInfo != null){
  162. this.$modal.confirm("确认取消预约?").then(res=>{
  163. this.cancelPlan();
  164. })
  165. }else{
  166. this.toPlan()
  167. }
  168. },
  169. cancelPlan(){
  170. cancelPlan(this.planInfo.id).then(res=>{
  171. this.$modal.msg("取消成功");
  172. this.planInfo = null;
  173. this.getPlanInfo();
  174. })
  175. },
  176. getPlanInfo(){
  177. getPlanInfo(this.deviceInfo.deviceId,this.choosePort).then(res=>{
  178. let data = res.data;
  179. if(data != null){
  180. let planType = data.planType;
  181. if(planType == 1){//单次预约
  182. let planInfo = {};
  183. planInfo.runTime = data.runTime;
  184. this.planInfo = planInfo;
  185. this.planInfo.id = data.id;
  186. }else{
  187. let planInfo = {};
  188. planInfo.runTime = data.runTime;
  189. let repeatDays = data.repeatDays;
  190. let days = repeatDays.split(",")
  191. let strs = "";
  192. for (let i = 0; i < days.length; i++) {
  193. if(strs.length>0){
  194. strs+=",";
  195. }
  196. strs +=i18(this.days[days[i]]);
  197. }
  198. this.planInfo = planInfo;
  199. this.planInfo.runTime = strs+" "+data.repeatTime;
  200. this.planInfo.id = data.id;
  201. }
  202. }
  203. })
  204. },
  205. confirmPort(e){
  206. let value = e.value[0]
  207. this.choosePort = value.port;
  208. this.showPort = false;
  209. this.getInfo()
  210. },
  211. parsePortCmd(real_data) {
  212. let self = this;
  213. self.portDetail = real_data
  214. self.curPort = [];
  215. let port_first_status = self.portDetail["port_first_status"];
  216. let port_second_status = self.portDetail["port_second_status"]
  217. if (port_first_status) {
  218. self.portList[0].push({port: 1, text: i18("端口一")});
  219. self.curPort.push({
  220. text: i18("端口一"),
  221. status: port_first_status,
  222. id: 1,
  223. })
  224. }
  225. if (port_second_status) {
  226. self.portList[0].push({port: 2, text: i18("端口二")});
  227. self.curPort.push({
  228. text: i18("端口二"),
  229. status: port_second_status,
  230. id: 2
  231. })
  232. }
  233. let choosePort = self.choosePort
  234. if (choosePort == 1) {
  235. self.portDetail.portStatus = port_first_status;
  236. } else if (choosePort == 2) {
  237. self.portDetail.portStatus = port_second_status;
  238. }
  239. self.$modal.closeLoading();
  240. },
  241. initSocket(key){
  242. let self = this;
  243. let socketUrl = getApp().globalData.config.socketUrl
  244. this.scriptTask = websocket({
  245. url:"/"+key+"/",
  246. });
  247. let scriptTask = this.scriptTask;
  248. scriptTask.onOpen(function (res) {
  249. console.log('WebSocket连接已打开!');
  250. self.connected = true;
  251. });
  252. scriptTask.onError(function (res) {
  253. self.connected = false;
  254. console.log(res);
  255. });
  256. scriptTask.onMessage(function (res) {
  257. let data = JSON.parse(res.data);
  258. let type = data.type;
  259. let real_data = data.real_data;
  260. if(type == 103){
  261. self.parsePortCmd(real_data);
  262. }
  263. if(type == 116){
  264. self.$modal.closeLoading();
  265. self.getInfo();
  266. }
  267. if(type == 113){
  268. self.$modal.closeLoading();
  269. self.getInfo();
  270. }
  271. if(type == 96){
  272. self.mainBoardInfo = real_data;
  273. self.formatMainboardData();
  274. self.$modal.closeLoading();
  275. }
  276. self.$forceUpdate();
  277. console.log('收到服务器内容:' + JSON.stringify(data));
  278. });
  279. scriptTask.onClose(function (res) {
  280. console.log('WebSocket 已关闭!');
  281. });
  282. },
  283. toSet(){
  284. this.closeSocket();
  285. uni.navigateTo({
  286. url: '/pages/weitiandi/device/setting?id='+this.deviceInfo.deviceId+"&ccid="+this.deviceInfo.ccid
  287. });
  288. },
  289. toPlan(){
  290. uni.navigateTo({
  291. url: '/pages/weitiandi/device/plan?port='+this.choosePort+'&id='+this.deviceInfo.deviceId+"&ccid="+this.deviceInfo.ccid
  292. });
  293. },
  294. trigger(){
  295. let portStatus = this.portDetail.portStatus;
  296. if(portStatus == 2){//需要停止充电
  297. this.$modal.confirm("需要停止充电么?").then(res=>{
  298. this.stopCharge();
  299. })
  300. }else{
  301. if(portStatus == 1){
  302. this.$modal.msg("请先将充电枪插入后再点击充电");
  303. }
  304. if(portStatus == 5){
  305. this.$modal.confirm("确认开始充电么?").then(res=>{
  306. this.startCharge();
  307. })
  308. }
  309. }
  310. },
  311. getInfo() {
  312. let self = this;
  313. this.$modal.loading("正在获取状态,请稍等...");
  314. sendPortDetailCmd(this.deviceInfo).then(res => {
  315. this.$modal.loading("正在获取状态,请稍等...");
  316. this.visitTime = res.msg;
  317. if(!this.visitTime){
  318. this.$modal.msg("请重新进入页面");
  319. return;
  320. }
  321. if(!this.scriptTask){
  322. this.initSocket(this.deviceInfo.deviceId);
  323. }
  324. setTimeout(function (){
  325. getPortDetail(self.deviceInfo,self.visitTime).then(res=>{
  326. let data = res.data;
  327. if(data != null){
  328. self.parsePortCmd(data);
  329. }else{
  330. }
  331. });
  332. },500)
  333. })
  334. },
  335. stopCharge(){
  336. let self = this;
  337. this.deviceInfo.port = this.choosePort;
  338. stopCharge(this.deviceInfo).then(()=>{
  339. self.$modal.loading("停止成功");
  340. setTimeout((()=>{
  341. self.getInfo();
  342. }),1000);
  343. })
  344. },
  345. startCharge(){
  346. let self = this;
  347. this.deviceInfo.port = this.choosePort;
  348. startCharge(this.deviceInfo).then(res=>{
  349. self.$modal.loading("启动成功");
  350. setTimeout((()=>{
  351. self.getInfo();
  352. }),1000);
  353. })
  354. },
  355. getPortInfo(){
  356. this.startPortDetailTimer();
  357. },
  358. startPortDetailTimer(){
  359. let self = this;
  360. this.timer = setTimeout(function (){
  361. getPortDetail(self.deviceInfo,self.visitTime).then(res=>{
  362. let data = res.data;
  363. if(data != null){
  364. self.portDetail = data;
  365. self.checkStatusCheck();
  366. self.$modal.closeLoading();
  367. }else{
  368. self.startPortDetailTimer();
  369. }
  370. });
  371. },1000);
  372. },
  373. checkStatusCheck(){
  374. this.statusChangeTimer();
  375. },
  376. checkOnPage(){
  377. var pages = getCurrentPages() // 获取栈实例
  378. let currentRoute = pages[pages.length - 1].route; // 获取当前页面路由
  379. if("pages/weitiandi/device/index" != currentRoute){
  380. return false;
  381. }
  382. return true;
  383. },
  384. closeSocket(){
  385. this.scriptTask.close();
  386. this.scriptTask = null;
  387. },
  388. statusChangeTimer(){
  389. let self = this;
  390. this.statusTimer = setTimeout(function(){
  391. if(!this.checkOnPage()){
  392. return;
  393. }
  394. checkStatusChange(self.deviceInfo,self.visitTime).then(res=>{
  395. let data = res.data;
  396. if(data != null){
  397. self.getInfo();
  398. }else{
  399. self.statusChangeTimer();
  400. }
  401. });
  402. },3000);
  403. }
  404. }
  405. }
  406. </script>
  407. <style>
  408. .container {
  409. background: rgb(249, 252, 255);
  410. inset: 0;
  411. position: absolute;
  412. }
  413. .header {
  414. position: relative;
  415. margin-top:4vw;
  416. }
  417. .header-status-desc {
  418. position: absolute;
  419. text-align: center;
  420. width: 100%;
  421. bottom:1vh;
  422. font-size: 5vw;
  423. font-weight: bold;
  424. color: #0E9F9B;
  425. margin-bottom: 5vw;
  426. }
  427. .header-status {
  428. font-weight: bold;
  429. text-align: center;
  430. }
  431. .chong-active {
  432. color: #0E9F9B
  433. }
  434. .header-img {
  435. width: 100%;
  436. padding: 5% 10%;
  437. text-align: center;
  438. }
  439. .header-img image {
  440. width: 100%;
  441. height: 23vh;
  442. }
  443. .info-body{
  444. background: #0E9F9B;
  445. height: 20vh;
  446. margin: 0 2%;
  447. border-radius: 1vw;
  448. margin-top:2vh;
  449. color: #F8FCFF;
  450. line-height: 3vh;
  451. }
  452. .info-content{
  453. display: inline-block;
  454. width: 23%;
  455. text-align: center;
  456. margin: 1%;
  457. margin-top:2.5vh;
  458. }
  459. .info-content-value{
  460. font-weight: bold;
  461. }
  462. .info-content-text{
  463. }
  464. .info-summary{
  465. display: flex;
  466. flex-direction: row;
  467. text-align: center;
  468. margin:3vh 0;
  469. }
  470. .summary{
  471. width: 33%;
  472. line-height: 2.5vh;
  473. }
  474. .charge-num{
  475. color: #0E9F9B;
  476. font-weight: bold;
  477. font-size: 4.5vw;
  478. }
  479. .charge-title{
  480. color: #B2B2B2;
  481. font-weight: 400;
  482. }
  483. .btn-image{
  484. width: 90%;
  485. height: 100%;
  486. }
  487. .info-bottom-btn{
  488. display: flex;
  489. flex-direction: row;
  490. text-align: center;
  491. position: relative;
  492. margin-top: 10vh
  493. ;
  494. }
  495. .btn-area{
  496. width: 50%;
  497. height: 50px;
  498. }
  499. .left{
  500. position: relative;
  501. left: 10px;
  502. text-align: right;
  503. }
  504. .right{
  505. text-align: left;
  506. position: relative;
  507. right: 10px;
  508. }
  509. .info-plan{
  510. text-align: center;
  511. color: #0E9F9B;
  512. margin-top:1vh;
  513. font-weight: 400;
  514. }
  515. .setting{
  516. position: fixed;
  517. right: -1px;
  518. top: 10vh;
  519. z-index: 999;
  520. background: rgb(227,243,245);
  521. color: #0E9F9B;
  522. font-size: 10px;
  523. border-radius: 5px;
  524. padding: 3px;
  525. }
  526. .port{
  527. height: 70px;
  528. background: #F8FCFF;
  529. border: 0px solid #F8FCFF;
  530. box-shadow: 0px 0px 6px 1px rgba(101,101,101,0.29);
  531. border-radius: 4px;
  532. margin:0 10px;
  533. position: relative;
  534. margin-top:10px;
  535. }
  536. .plan{
  537. height: 70px;
  538. background: #F8FCFF;
  539. border: 0px solid #F8FCFF;
  540. box-shadow: 0px 0px 6px 1px rgba(101,101,101,0.29);
  541. border-radius: 4px;
  542. margin:0 10px;
  543. position: relative;
  544. margin-top:15px;
  545. }
  546. .port-image{
  547. height: 40px;
  548. width: 40px;
  549. position: absolute;
  550. top:15px;
  551. left:20px;
  552. }
  553. .port-text{
  554. position: absolute;
  555. top:13px;
  556. left:75px;
  557. font-weight: bold;
  558. }
  559. .port-num{
  560. position: absolute;
  561. top:38px;
  562. left:75px;
  563. color: #B2B2B2;
  564. }
  565. .port-icon{
  566. position: absolute;
  567. top:30px;
  568. right:5px;
  569. width: 10px;
  570. height: 16px;
  571. }
  572. .port-icon image{
  573. width: 90%;
  574. }
  575. .body-bottom{
  576. padding:0 22px;
  577. }
  578. .body-bottom .info-content{
  579. width: 30%;
  580. }
  581. .bottom-control{
  582. height: 22vh;
  583. margin: 0 2%;
  584. margin-top:2vh;
  585. line-height: 3vh;
  586. background: #F8FCFF;
  587. border: 0px solid #F8FCFF;
  588. box-shadow: 0px 0px 6px 1px rgba(101,101,101,0.29);
  589. border-radius: 4px;
  590. padding:3%;
  591. }
  592. .control-btn{
  593. display: inline-block;;
  594. height: 60px;
  595. width: 25%;
  596. padding:10px 20px;
  597. text-align: center;
  598. font-size: 12px;
  599. color: black;
  600. }
  601. .control-btn .btn-image{
  602. }
  603. .dportitem{
  604. color: #60af7b
  605. }
  606. .dboxs{
  607. background: #F8FCFF;
  608. border: 0px solid #F8FCFF;
  609. box-shadow: 0px 0px 6px 1px rgba(101,101,101,0.29);
  610. border-radius: 4px;
  611. padding: 20px;
  612. font-size: 0.24rem;
  613. color: #1A87FF;
  614. margin:20px;
  615. position: relative;
  616. }
  617. .portimg{
  618. width: 20px;
  619. height: 20px;
  620. }
  621. .dportitem-img{
  622. width: 30px;
  623. height: 30px;
  624. }
  625. .dpropitem-block{
  626. padding: 0.12rem 0.37rem;
  627. background: #e6f6f1;
  628. display: flex;
  629. width: 70px;
  630. height: 70px;
  631. flex-direction: column;
  632. justify-content: center;
  633. align-items: center;
  634. position: relative;
  635. }
  636. .dportitem{
  637. margin:10px;
  638. width: 70px;
  639. position: relative;
  640. display: inline-block;
  641. }
  642. .dportitem-block-2{
  643. background: #f9f4e5;
  644. color: #FFAA00;
  645. }
  646. .dpropitem-title{
  647. text-align: center;
  648. margin-bottom: 5px;
  649. font-size: 16px;
  650. }
  651. .dpropitem-status{
  652. font-size: 14px;
  653. }
  654. .dboxtitle{
  655. font-size: 18px;
  656. position: relative;
  657. }
  658. .dboxtitle-text{
  659. display: inline-block;
  660. position: absolute;
  661. top: -2px;
  662. left: 25px;
  663. }
  664. .btn-image{
  665. width: 30px;
  666. height: 30px;
  667. }
  668. .control-btn{
  669. font-size: 14px;
  670. }
  671. </style>