index.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  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. initSocket(key){
  212. let self = this;
  213. let socketUrl = getApp().globalData.config.socketUrl
  214. this.scriptTask = websocket({
  215. url:"/"+key+"/",
  216. });
  217. let scriptTask = this.scriptTask;
  218. scriptTask.onOpen(function (res) {
  219. console.log('WebSocket连接已打开!');
  220. self.connected = true;
  221. });
  222. scriptTask.onError(function (res) {
  223. self.connected = false;
  224. console.log(res);
  225. });
  226. scriptTask.onMessage(function (res) {
  227. let data = JSON.parse(res.data);
  228. let type = data.type;
  229. let real_data = data.real_data;
  230. if(type == 103){
  231. self.portDetail = real_data
  232. self.curPort = [];
  233. let port_first_status = self.portDetail["port_first_status"];
  234. let port_second_status = self.portDetail["port_second_status"]
  235. if(port_first_status){
  236. self.portList[0].push({port:1,text:i18("端口一")});
  237. self.curPort.push({
  238. text:i18("端口一"),
  239. status:port_first_status,
  240. id:1,
  241. })
  242. }
  243. if(port_second_status){
  244. self.portList[0].push({port:2,text:i18("端口二")});
  245. self.curPort.push({
  246. text:i18("端口二"),
  247. status:port_second_status,
  248. id:2
  249. })
  250. }
  251. let choosePort = self.choosePort
  252. if(choosePort == 1){
  253. self.portDetail.portStatus = port_first_status;
  254. }else if(choosePort == 2){
  255. self.portDetail.portStatus = port_second_status;
  256. }
  257. self.$modal.closeLoading();
  258. }
  259. if(type == 116){
  260. self.$modal.closeLoading();
  261. self.getInfo();
  262. }
  263. if(type == 113){
  264. self.$modal.closeLoading();
  265. self.getInfo();
  266. }
  267. if(type == 96){
  268. self.mainBoardInfo = real_data;
  269. self.formatMainboardData();
  270. self.$modal.closeLoading();
  271. }
  272. self.$forceUpdate();
  273. console.log('收到服务器内容:' + JSON.stringify(data));
  274. });
  275. scriptTask.onClose(function (res) {
  276. console.log('WebSocket 已关闭!');
  277. });
  278. },
  279. toSet(){
  280. this.closeSocket();
  281. uni.navigateTo({
  282. url: '/pages/weitiandi/device/setting?id='+this.deviceInfo.deviceId+"&ccid="+this.deviceInfo.ccid
  283. });
  284. },
  285. toPlan(){
  286. uni.navigateTo({
  287. url: '/pages/weitiandi/device/plan?port='+this.choosePort+'&id='+this.deviceInfo.deviceId+"&ccid="+this.deviceInfo.ccid
  288. });
  289. },
  290. trigger(){
  291. let portStatus = this.portDetail.portStatus;
  292. if(portStatus == 2){//需要停止充电
  293. this.$modal.confirm("需要停止充电么?").then(res=>{
  294. this.stopCharge();
  295. })
  296. }else{
  297. if(portStatus == 1){
  298. this.$modal.msg("请先将充电枪插入后再点击充电");
  299. }
  300. if(portStatus == 5){
  301. this.$modal.confirm("确认开始充电么?").then(res=>{
  302. this.startCharge();
  303. })
  304. }
  305. }
  306. },
  307. getInfo() {
  308. this.$modal.loading("正在获取状态,请稍等...");
  309. sendPortDetailCmd(this.deviceInfo).then(res => {
  310. this.$modal.loading("正在获取状态,请稍等...");
  311. this.visitTime = res.msg;
  312. if(!this.visitTime){
  313. this.$modal.msg("请重新进入页面");
  314. return;
  315. }
  316. if(!this.scriptTask){
  317. this.initSocket(this.deviceInfo.deviceId);
  318. }
  319. // this.getPortInfo()
  320. })
  321. },
  322. stopCharge(){
  323. let self = this;
  324. this.deviceInfo.port = this.choosePort;
  325. stopCharge(this.deviceInfo).then(()=>{
  326. self.$modal.loading("停止成功");
  327. setTimeout((()=>{
  328. self.getInfo();
  329. }),1000);
  330. })
  331. },
  332. startCharge(){
  333. let self = this;
  334. this.deviceInfo.port = this.choosePort;
  335. startCharge(this.deviceInfo).then(res=>{
  336. self.$modal.loading("启动成功");
  337. setTimeout((()=>{
  338. self.getInfo();
  339. }),1000);
  340. })
  341. },
  342. getPortInfo(){
  343. this.startPortDetailTimer();
  344. },
  345. startPortDetailTimer(){
  346. let self = this;
  347. this.timer = setTimeout(function (){
  348. getPortDetail(self.deviceInfo,self.visitTime).then(res=>{
  349. let data = res.data;
  350. if(data != null){
  351. self.portDetail = data;
  352. self.checkStatusCheck();
  353. self.$modal.closeLoading();
  354. }else{
  355. self.startPortDetailTimer();
  356. }
  357. });
  358. },1000);
  359. },
  360. checkStatusCheck(){
  361. this.statusChangeTimer();
  362. },
  363. checkOnPage(){
  364. var pages = getCurrentPages() // 获取栈实例
  365. let currentRoute = pages[pages.length - 1].route; // 获取当前页面路由
  366. if("pages/weitiandi/device/index" != currentRoute){
  367. return false;
  368. }
  369. return true;
  370. },
  371. closeSocket(){
  372. this.scriptTask.close();
  373. this.scriptTask = null;
  374. },
  375. statusChangeTimer(){
  376. let self = this;
  377. this.statusTimer = setTimeout(function(){
  378. if(!this.checkOnPage()){
  379. return;
  380. }
  381. checkStatusChange(self.deviceInfo,self.visitTime).then(res=>{
  382. let data = res.data;
  383. if(data != null){
  384. self.getInfo();
  385. }else{
  386. self.statusChangeTimer();
  387. }
  388. });
  389. },3000);
  390. }
  391. }
  392. }
  393. </script>
  394. <style>
  395. .container {
  396. background: rgb(249, 252, 255);
  397. inset: 0;
  398. position: absolute;
  399. }
  400. .header {
  401. position: relative;
  402. margin-top:4vw;
  403. }
  404. .header-status-desc {
  405. position: absolute;
  406. text-align: center;
  407. width: 100%;
  408. bottom:1vh;
  409. font-size: 5vw;
  410. font-weight: bold;
  411. color: #0E9F9B;
  412. margin-bottom: 5vw;
  413. }
  414. .header-status {
  415. font-weight: bold;
  416. text-align: center;
  417. }
  418. .chong-active {
  419. color: #0E9F9B
  420. }
  421. .header-img {
  422. width: 100%;
  423. padding: 5% 10%;
  424. text-align: center;
  425. }
  426. .header-img image {
  427. width: 100%;
  428. height: 23vh;
  429. }
  430. .info-body{
  431. background: #0E9F9B;
  432. height: 20vh;
  433. margin: 0 2%;
  434. border-radius: 1vw;
  435. margin-top:2vh;
  436. color: #F8FCFF;
  437. line-height: 3vh;
  438. }
  439. .info-content{
  440. display: inline-block;
  441. width: 23%;
  442. text-align: center;
  443. margin: 1%;
  444. margin-top:2.5vh;
  445. }
  446. .info-content-value{
  447. font-weight: bold;
  448. }
  449. .info-content-text{
  450. }
  451. .info-summary{
  452. display: flex;
  453. flex-direction: row;
  454. text-align: center;
  455. margin:3vh 0;
  456. }
  457. .summary{
  458. width: 33%;
  459. line-height: 2.5vh;
  460. }
  461. .charge-num{
  462. color: #0E9F9B;
  463. font-weight: bold;
  464. font-size: 4.5vw;
  465. }
  466. .charge-title{
  467. color: #B2B2B2;
  468. font-weight: 400;
  469. }
  470. .btn-image{
  471. width: 90%;
  472. height: 100%;
  473. }
  474. .info-bottom-btn{
  475. display: flex;
  476. flex-direction: row;
  477. text-align: center;
  478. position: relative;
  479. margin-top: 10vh
  480. ;
  481. }
  482. .btn-area{
  483. width: 50%;
  484. height: 50px;
  485. }
  486. .left{
  487. position: relative;
  488. left: 10px;
  489. text-align: right;
  490. }
  491. .right{
  492. text-align: left;
  493. position: relative;
  494. right: 10px;
  495. }
  496. .info-plan{
  497. text-align: center;
  498. color: #0E9F9B;
  499. margin-top:1vh;
  500. font-weight: 400;
  501. }
  502. .setting{
  503. position: fixed;
  504. right: -1px;
  505. top: 10vh;
  506. z-index: 999;
  507. background: rgb(227,243,245);
  508. color: #0E9F9B;
  509. font-size: 10px;
  510. border-radius: 5px;
  511. padding: 3px;
  512. }
  513. .port{
  514. height: 70px;
  515. background: #F8FCFF;
  516. border: 0px solid #F8FCFF;
  517. box-shadow: 0px 0px 6px 1px rgba(101,101,101,0.29);
  518. border-radius: 4px;
  519. margin:0 10px;
  520. position: relative;
  521. margin-top:10px;
  522. }
  523. .plan{
  524. height: 70px;
  525. background: #F8FCFF;
  526. border: 0px solid #F8FCFF;
  527. box-shadow: 0px 0px 6px 1px rgba(101,101,101,0.29);
  528. border-radius: 4px;
  529. margin:0 10px;
  530. position: relative;
  531. margin-top:15px;
  532. }
  533. .port-image{
  534. height: 40px;
  535. width: 40px;
  536. position: absolute;
  537. top:15px;
  538. left:20px;
  539. }
  540. .port-text{
  541. position: absolute;
  542. top:13px;
  543. left:75px;
  544. font-weight: bold;
  545. }
  546. .port-num{
  547. position: absolute;
  548. top:38px;
  549. left:75px;
  550. color: #B2B2B2;
  551. }
  552. .port-icon{
  553. position: absolute;
  554. top:30px;
  555. right:5px;
  556. width: 10px;
  557. height: 16px;
  558. }
  559. .port-icon image{
  560. width: 90%;
  561. }
  562. .body-bottom{
  563. padding:0 22px;
  564. }
  565. .body-bottom .info-content{
  566. width: 30%;
  567. }
  568. .bottom-control{
  569. height: 22vh;
  570. margin: 0 2%;
  571. margin-top:2vh;
  572. line-height: 3vh;
  573. background: #F8FCFF;
  574. border: 0px solid #F8FCFF;
  575. box-shadow: 0px 0px 6px 1px rgba(101,101,101,0.29);
  576. border-radius: 4px;
  577. padding:3%;
  578. }
  579. .control-btn{
  580. display: inline-block;;
  581. height: 60px;
  582. width: 25%;
  583. padding:10px 20px;
  584. text-align: center;
  585. font-size: 12px;
  586. color: black;
  587. }
  588. .control-btn .btn-image{
  589. }
  590. .dportitem{
  591. color: #60af7b
  592. }
  593. .dboxs{
  594. background: #F8FCFF;
  595. border: 0px solid #F8FCFF;
  596. box-shadow: 0px 0px 6px 1px rgba(101,101,101,0.29);
  597. border-radius: 4px;
  598. padding: 20px;
  599. font-size: 0.24rem;
  600. color: #1A87FF;
  601. margin:20px;
  602. position: relative;
  603. }
  604. .portimg{
  605. width: 20px;
  606. height: 20px;
  607. }
  608. .dportitem-img{
  609. width: 30px;
  610. height: 30px;
  611. }
  612. .dpropitem-block{
  613. padding: 0.12rem 0.37rem;
  614. background: #e6f6f1;
  615. display: flex;
  616. width: 70px;
  617. height: 70px;
  618. flex-direction: column;
  619. justify-content: center;
  620. align-items: center;
  621. position: relative;
  622. }
  623. .dportitem{
  624. margin:10px;
  625. width: 70px;
  626. position: relative;
  627. display: inline-block;
  628. }
  629. .dportitem-block-2{
  630. background: #f9f4e5;
  631. color: #FFAA00;
  632. }
  633. .dpropitem-title{
  634. text-align: center;
  635. margin-bottom: 5px;
  636. font-size: 16px;
  637. }
  638. .dpropitem-status{
  639. font-size: 14px;
  640. }
  641. .dboxtitle{
  642. font-size: 18px;
  643. position: relative;
  644. }
  645. .dboxtitle-text{
  646. display: inline-block;
  647. position: absolute;
  648. top: -2px;
  649. left: 25px;
  650. }
  651. .btn-image{
  652. width: 30px;
  653. height: 30px;
  654. }
  655. .control-btn{
  656. font-size: 14px;
  657. }
  658. </style>