index.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. <template>
  2. <view class="container fixed">
  3. <view class="toolbar" v-if="chargeInfo">
  4. <view class="tool-title">Charge</view>
  5. <view class="tool-desc" v-if="chargeInfo.chargeBoxId">{{chargeInfo.chargeBoxId + "-" + chargeInfo.connectorId}}</view>
  6. <view class="tool-desc" v-else>-</view>
  7. </view>
  8. <header-view
  9. title="Insert Charging Cable"
  10. :status="connectorInfo.status"
  11. :isLoading="isLoading"
  12. :password="password"/>
  13. <info-view
  14. :info="connectorInfo"
  15. :isLoading="isLoading"/>
  16. <payment-view
  17. v-if="connectorInfo.status == 'Preparing'"
  18. :info="connectorInfo"/>
  19. <divide size="36"/>
  20. <view class="bottom-button">
  21. <button
  22. v-if="connectorInfo.status == 'Initiating'"
  23. class="ui-button margin0"
  24. type="primary"
  25. @click="onStart"
  26. :disabled="!connectorInfo.shouldClickStart">START CHARGING</button>
  27. <button
  28. v-else-if="connectorInfo.status == 'Charging'"
  29. class="ui-button margin0"
  30. type="primary"
  31. @click="stopCharge">INPUT PIN TO STOP CHARGING</button>
  32. <view class="flexc" v-else-if="connectorInfo.status == 'Finishing'">
  33. <button
  34. class="ui-button margin0 flex3"
  35. type="primary"
  36. :disabled="!chargingPk"
  37. @click="toReceipt">VIEW RECEIPT</button>
  38. <divide :size="24"/>
  39. <button
  40. class="ui-button margin0 flex1"
  41. type="accent"
  42. @click="goBack">EXIT</button>
  43. </view>
  44. <template v-else-if="connectorInfo.status == 'Preparing'">
  45. <template v-if="password">
  46. <button
  47. class="ui-button margin0"
  48. type="primary"
  49. @click="onStart"
  50. v-if="connectorInfo.paymentStatus == 'PAID'">START CHARGING</button>
  51. <button
  52. class="ui-button margin0"
  53. type="primary"
  54. @click="onPayment"
  55. v-else>
  56. <view class="flexcc">
  57. <text>MAKE PAYMENT</text>
  58. <view class="icon-key" v-if="false">
  59. <i-icon name="key-fill" size="32rpx" color="#333"/>
  60. </view>
  61. </view>
  62. </button>
  63. </template>
  64. <button
  65. v-else
  66. class="ui-button margin0"
  67. type="accent"
  68. @click="showPinPage">INPUT PIN</button>
  69. </template>
  70. <button
  71. v-else-if="connectorInfo.status == 'Available' && isLoading"
  72. class="ui-button margin0"
  73. type="cancel"
  74. @click="cancelAuth">CANCEL</button>
  75. <button
  76. v-else
  77. class="ui-button margin0"
  78. type="primary"
  79. @click="onAuthentic"
  80. :disabled="connectorInfo.status != 'Available' || isLoading">
  81. <view class="flexcc">
  82. <text>AUTHENTICATE</text>
  83. <view class="icon-key" v-if="false">
  84. <i-icon name="key-fill" size="32rpx" color="#333"/>
  85. </view>
  86. </view>
  87. </button>
  88. </view>
  89. <PasswordView
  90. :visible="showPin || stopPin"
  91. :verify="stopPin"
  92. @change="changePassword"/>
  93. </view>
  94. </template>
  95. <script>
  96. import HeaderView from './views/HeaderView.vue';
  97. import InfoView from './views/InfoView.vue';
  98. import PaymentView from './views/PaymentView.vue';
  99. import PasswordView from '@/components/PasswordView.vue';
  100. import apiCharge from '@/api/apiCharge';
  101. import {openUrl} from '@/utils/utils.js';
  102. import settings from '../../settings';
  103. import auth from '../../utils/auth';
  104. export default {
  105. data() {
  106. return {
  107. refreshId: 0,
  108. isLoading: false,
  109. waitPayment: false,
  110. isPaymentFailed: false,
  111. chargeInfo: {
  112. chargeBoxId: "",
  113. connectorId: ""
  114. },
  115. connectorInfo: {},
  116. stoped: false,
  117. creditHistoryPk: "",
  118. chargingPk: "",
  119. paymentId:"",
  120. showPin: false,
  121. stopPin: false,
  122. password: ""
  123. }
  124. },
  125. components: {
  126. HeaderView,
  127. InfoView,
  128. PaymentView,
  129. PasswordView
  130. },
  131. onLoad(query) {
  132. if (query.pk) {
  133. this.paymentId = query.pk;
  134. }
  135. if (query.info) {
  136. this.chargeInfo = JSON.parse(decodeURIComponent(query.info));
  137. } /*else {
  138. this.waitPayment = getApp().globalData.waitPayment;
  139. let id = auth.getPaymentId();
  140. if (id) {
  141. this.paymentId = id;
  142. }
  143. }*/
  144. if (!query.pk && !query.info) {
  145. uni.reLaunch({
  146. url: "/pages/index/index"
  147. });
  148. return;
  149. }
  150. this.refreshStatus(500);
  151. },
  152. methods: {
  153. goBack() {
  154. uni.redirectTo({
  155. url: "/pages/index/index"
  156. })
  157. },
  158. refreshStatus(time=2000) {
  159. this.refreshId += 1;
  160. setTimeout(() => {
  161. if (this.stoped) {
  162. return;
  163. }
  164. if (this.paymentId) {
  165. this.getChargingStatus(this.refreshId);
  166. } else if (this.chargeInfo.connectorId) {
  167. this.getChargerInfo(this.refreshId)
  168. }
  169. }, time);
  170. },
  171. getChargerInfo(id) {
  172. if (id !== this.refreshId) {
  173. return;
  174. }
  175. apiCharge.getChargerDetails(this.chargeInfo).then(res => {
  176. if (res.data) {
  177. this.connectorInfo = res.data;
  178. this.showPageWithStatus()
  179. }
  180. }).catch(err => {
  181. uni.showModal({
  182. title: "Error",
  183. content: err,
  184. confirmText: "OK",
  185. showCancel: false,
  186. success: res => {
  187. if (res.confirm) {
  188. this.goBack();
  189. }
  190. }
  191. })
  192. }).finally(() => {
  193. uni.stopPullDownRefresh();
  194. })
  195. },
  196. getChargingStatus(id) {
  197. if (id !== this.refreshId) {
  198. return;
  199. }
  200. apiCharge.getChargingDetails({
  201. creditHistoryPk: this.paymentId
  202. }).then(res => {
  203. if (res.data) {
  204. this.connectorInfo = res.data;
  205. if (res.data.creditHistoryPk) {
  206. this.createPayment(res.data.creditHistoryPk);
  207. }
  208. if (!this.chargeInfo.chargeBoxId && res.data.chargeBoxId) {
  209. this.chargeInfo.chargeBoxId = res.data.chargeBoxId;
  210. this.chargeInfo.connectorId = res.data.connectorId;
  211. }
  212. this.showPageWithStatus()
  213. }
  214. }).catch(err => {
  215. /*uni.showToast({
  216. icon: "none",
  217. title: err
  218. })*/
  219. uni.showModal({
  220. title: "Error",
  221. content: err,
  222. confirmText: "OK",
  223. showCancel: false,
  224. success: res => {
  225. if (res.confirm) {
  226. this.goBack();
  227. }
  228. }
  229. })
  230. }).finally(() => {
  231. uni.stopPullDownRefresh();
  232. })
  233. },
  234. showPageWithStatus() {
  235. //this.connectorInfo.status = "Charging"
  236. switch (this.connectorInfo.status) {
  237. case "Available":
  238. if (this.isLoading) {
  239. this.refreshStatus(3000);
  240. }
  241. break;
  242. case "Preparing":
  243. this.isLoading = false;
  244. if (this.connectorInfo.paymentStatus == "FAILED") {
  245. this.isPaymentFailed = true;
  246. }
  247. break;
  248. case "Initiating":
  249. if (this.isLoading || this.waitPayment) {
  250. this.refreshStatus(3000);
  251. } else {
  252. this.isLoading = true;
  253. this.refreshStatus(3000);
  254. }
  255. break;
  256. case "Charging":
  257. if (this.waitPayment) {
  258. this.isLoading = true;
  259. this.waitPayment = false;
  260. getApp().globalData.waitPayment = false;
  261. this.refreshStatus(3000);
  262. } else {
  263. this.isLoading = false;
  264. this.refreshStatus(10000);
  265. }
  266. break;
  267. case "Finishing":
  268. if (this.connectorInfo.chargingPk) {
  269. this.chargingPk = this.connectorInfo.chargingPk;
  270. //this.toReceipt();
  271. } else {
  272. this.refreshStatus(5000);
  273. }
  274. break;
  275. default:
  276. this.refreshId = 0;
  277. this.isLoading = false;
  278. break;
  279. }
  280. uni.hideLoading();
  281. },
  282. changePassword(psd) {
  283. this.password = psd;
  284. if (this.stopPin) {
  285. this.stopPin = false;
  286. this.onStop();
  287. } else {
  288. this.showPin = false;
  289. //this.onAuthentic();
  290. }
  291. },
  292. refreshPayment() {
  293. uni.showLoading({
  294. title: "Waiting..."
  295. });
  296. this.getChargingStatus();
  297. },
  298. onAuthentic() {
  299. this.isLoading = true;
  300. this.refreshStatus();
  301. },
  302. showPinPage() {
  303. this.showPin = true;
  304. },
  305. cancelAuth() {
  306. this.isLoading = false;
  307. },
  308. onPayment() {
  309. if (!this.password) {
  310. this.showPin = true;
  311. return;
  312. }
  313. uni.showLoading({
  314. title: "Waiting..."
  315. })
  316. apiCharge.makePayment({
  317. ...this.chargeInfo,
  318. pin: this.password
  319. }).then(res => {
  320. if (res.data.creditHistoryPk) {
  321. this.createPayment(res.data.creditHistoryPk);
  322. }
  323. if (res.data.webPaymentUrl) {
  324. openUrl(res.data.webPaymentUrl);
  325. }
  326. }).catch(err => {
  327. uni.showModal({
  328. title: "Error",
  329. content: err,
  330. confirmText: "OK",
  331. showCancel: false,
  332. })
  333. /*uni.showToast({
  334. icon: "none",
  335. title: err
  336. })*/
  337. }).finally(() => {
  338. uni.hideLoading();
  339. });
  340. },
  341. onStart() {
  342. this.isLoading = true;
  343. uni.showLoading({
  344. title: "Loading..."
  345. })
  346. apiCharge.startCharge({
  347. //connectorPk: this.connectorPk,
  348. creditHistoryPk: this.paymentId
  349. }).then(res => {
  350. this.refreshStatus();
  351. if (res.msg) {
  352. uni.showToast({
  353. icon: "none",
  354. title: res.msg
  355. })
  356. } else {
  357. uni.hideLoading();
  358. }
  359. }).catch(err => {
  360. this.isLoading = false;
  361. //this.paymentId = "";
  362. //auth.setPaymentId("");
  363. this.connectorInfo.paymentStatus = "";
  364. uni.showToast({
  365. icon: "none",
  366. title: err
  367. })
  368. })
  369. },
  370. stopCharge() {
  371. uni.showModal({
  372. title: "Confirm Stop Charging?",
  373. content: "Your charging session will stop",
  374. confirmText: "CONFIRM",
  375. cancelText: "CANCEL",
  376. success: res => {
  377. if (res.confirm) {
  378. this.stopPin = true;
  379. }
  380. }
  381. })
  382. },
  383. onStop() {
  384. uni.showLoading({
  385. title: "Stopping..."
  386. })
  387. apiCharge.stopCharge({
  388. creditHistoryPk: this.paymentId,
  389. pin: this.password
  390. }).then(res => {
  391. this.stoped = true;
  392. this.paymentId = "";
  393. auth.setPaymentId("");
  394. if (res.data.chargingPk) {
  395. uni.hideLoading();
  396. this.connectorInfo.status = "Finishing";
  397. this.chargingPk = res.data.chargingPk;
  398. //this.toReceipt();
  399. } else {
  400. uni.showToast({
  401. icon: "none",
  402. title: "Stop failed"
  403. });
  404. this.refreshStatus();
  405. }
  406. }).catch(err => {
  407. uni.showModal({
  408. title: "Error",
  409. content: err,
  410. confirmText: "OK",
  411. showCancel: false
  412. })
  413. uni.hideLoading();
  414. this.refreshStatus();
  415. })
  416. },
  417. confirmStop() {
  418. uni.showModal({
  419. title: "Confirm Stop Charging?",
  420. content: "Your charging session will stop",
  421. confirmText: "CONFIRM",
  422. cancelText: "BACK",
  423. //confirmColor: "var(--primary-color)",
  424. success: (res) => {
  425. if (res.confirm) {
  426. this.onStop();
  427. }
  428. }
  429. })
  430. },
  431. createPayment(id) {
  432. if (id) {
  433. this.paymentId = id;
  434. //auth.setPaymentId("" + id);
  435. }
  436. },
  437. resetPayment() {
  438. this.isLoading = false;
  439. this.waitPayment = false;
  440. this.isPaymentFailed = false;
  441. getApp().globalData.waitPayment = false;
  442. },
  443. toReceipt() {
  444. uni.navigateTo({
  445. url: "/pages/receipt/index?id=" + this.chargingPk
  446. })
  447. }
  448. },
  449. onPullDownRefresh() {
  450. this.refreshStatus(500);
  451. }
  452. }
  453. </script>
  454. <style scoped>
  455. .container {
  456. display: flex;
  457. flex-direction: column;
  458. }
  459. .toolbar {
  460. display: flex;
  461. padding: 16rpx;
  462. position: relative;
  463. align-items: center;
  464. flex-direction: column;
  465. justify-content: center;
  466. background-color: white;
  467. }
  468. .tool-title {
  469. color: #111;
  470. font-size: 32rpx;
  471. font-weight: bold;
  472. padding-bottom: 4rpx;
  473. }
  474. .tool-desc {
  475. color: #666;
  476. font-size: 24rpx;
  477. }
  478. .bottom-button {
  479. padding: 32rpx;
  480. background-color: white;
  481. box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.1);
  482. }
  483. .icon-key {
  484. padding: 0 8rpx;
  485. transform: rotate(-90deg);
  486. }
  487. .ui-button[disabled] >>> .icon-key span {
  488. color: #888;
  489. }
  490. </style>