TabCharge.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  1. /**
  2. * 新版充电页面
  3. * @邠心vbe on 2023/02/06
  4. */
  5. import React, { Component } from 'react';
  6. import { StyleSheet, ScrollView, RefreshControl } from 'react-native';
  7. import apiCharge from '../../api/apiCharge';
  8. import Dialog from '../../components/Dialog';
  9. import { PageList } from '../Router';
  10. import { EnterStationDialog } from './Charging';
  11. import { QRResult } from '../charge/QRScan';
  12. import { ErrorDialog } from './InfoDialog';
  13. import PagerUtil from './PagerUtil';
  14. import StepStartView from '../charging/StepStartView';
  15. import StepChargeView from '../charging/StepChargeView';
  16. import utils from '../../utils/utils';
  17. import app from '../../../app.json';
  18. import { PaymentDefault } from '../payment/PaymentConfig';
  19. import { MyRefreshProps } from '../../components/ThemesConfig';
  20. import ChargingStartView from '../chargeV3/ChargingStartView';
  21. export default class TabCharge extends Component {
  22. constructor(props) {
  23. super(props);
  24. this.state = {
  25. available: false,
  26. isPrivate: false,
  27. refreshing: false,
  28. isStart: false,
  29. isPending: false,
  30. isCharging: false,
  31. isAuthentic: false,
  32. selectRate: '',
  33. connectorInfo: {},
  34. stationInfo: {},
  35. lastUpdated: '',
  36. errorCode: 'A9',
  37. errorMessage: '',
  38. showErrorDialog: false,
  39. showStationDialog: false,
  40. currentPerUser: undefined,
  41. canIntoCharging: false,
  42. //currentPayment: PAYTYPE.CREDIT_WALLET,
  43. //currentPaytype: "Credit Wallet",
  44. currentPayment: PaymentDefault.DEFAULT.payType,
  45. currentPaytype: PaymentDefault.DEFAULT.payName,
  46. selectedVoucher: {}
  47. };
  48. this.changeMethod = false;
  49. this.canAutoRefresh = false;
  50. this.inputStationId = '';
  51. this.autoIntoCharging = true;
  52. this.intoChargingStatus = ["Preparing", "Charging", "Initiating", "SuspendedEVSE", "SuspendedEV"]
  53. }
  54. componentDidMount() {
  55. this.canAutoRefresh = true;
  56. PagerUtil.addOnRefresh(this);
  57. //this.onRefresh();
  58. }
  59. onRefresh() {
  60. console.log("Charge刷新", this.props.route.name);
  61. const info = PagerUtil.getStationInfo();
  62. this.setState({
  63. refreshing: false,
  64. stationInfo: info
  65. }, () => {
  66. this.init();
  67. console.log("站点信息", this.state.stationInfo);
  68. //this.checkIsCharge();
  69. });
  70. }
  71. onPullRefresh() {
  72. this.setState({
  73. refreshing: true
  74. })
  75. PagerUtil.setBackRefreshing();
  76. }
  77. init() {
  78. console.log("Charge刷新", "init");
  79. if (PagerUtil.isSelectVoucher) {
  80. this.setState({
  81. selectedVoucher: PagerUtil.getSelectedVoucher()
  82. })
  83. }
  84. this.onMethodChanged();
  85. this.refreshAvailable();
  86. if (QRResult.haveResult()) {
  87. console.log("Charge刷新", "haveResult");
  88. const info = QRResult.getResult()
  89. console.log('QRResult', info);
  90. if (PagerUtil.ENABLE_NEW_UI) {
  91. //新充电流程
  92. this.setState({
  93. connectorInfo: info
  94. }, () => {
  95. this.checkChargeStatus(true);
  96. })
  97. } else {
  98. this.setState({
  99. isAuthentic: true,
  100. connectorInfo: info
  101. //soc: info.chargeType == 'AC' ? 0 : 'In Charging'
  102. }, () => {
  103. PagerUtil.onCharge(this.props);
  104. this.checkChargeStatus(true);
  105. });
  106. }
  107. //QRResult.clearResult();
  108. } else if (this.state.isStart) {
  109. console.log("Charge刷新", "isStart");
  110. this.checkIsCharge();
  111. } else {
  112. console.log("Charge刷新", "noStart");
  113. this.getConnectorInfo();
  114. //this.checkChargeStatus();
  115. }
  116. }
  117. componentWillUnmount() {
  118. this.canAutoRefresh = false;
  119. }
  120. //刷新可用充电接口
  121. refreshAvailable() {
  122. const info = this.state.stationInfo
  123. const all = info?.allConnector;
  124. if (info.siteType == 'Private') {
  125. this.setState({
  126. isPrivate: true
  127. })
  128. }
  129. if (all) {
  130. this.setState({
  131. available: !all.available > 0
  132. });
  133. }
  134. }
  135. /**
  136. * 激活自动进入新充电页面的开关
  137. */
  138. activeNewUIPage() {
  139. this.autoIntoCharging = true;
  140. }
  141. toChargingPage() {
  142. this.autoIntoCharging = false;
  143. utils.toChargingPage({
  144. id: this.state.stationInfo.id,
  145. name: this.state.stationInfo.name,
  146. address: this.state.stationInfo.address,
  147. chargeBoxId: this.state.connectorInfo.chargeBoxId,
  148. connectorId: this.state.connectorInfo.connectorId
  149. });
  150. }
  151. enterStatioinId() {
  152. if (QRResult.haveResult()) {
  153. if (PagerUtil.ENABLE_NEW_UI) {
  154. this.onRefresh();
  155. } else {
  156. const info = QRResult.getResult()
  157. console.log('EnterResult', info);
  158. this.setState({
  159. isAuthentic: true,
  160. connectorInfo: info
  161. //soc: info.chargeType == 'AC' ? 0 : 'In Charging'
  162. });
  163. this.checkChargeStatus();
  164. }
  165. }
  166. }
  167. onPaymentMethodChanged(payment) {
  168. this.setState({
  169. currentPayment: payment
  170. })
  171. }
  172. onMethodChange() {
  173. this.changeMethod = true;
  174. startPage(PageList.paymentMethod, {info: this.state.connectorInfo, type: this.state.currentPayment});
  175. }
  176. onMethodChanged() {
  177. if (this.changeMethod) {
  178. this.changeMethod = false;
  179. if (global.paymentOption?.title) {
  180. this.setState({
  181. //currentPerUser: global.paymentOption.amount,
  182. currentPayment: global.paymentOption.value,
  183. currentPaytype: global.paymentOption.title
  184. }, () => {
  185. global.paymentOption= {}
  186. })
  187. }
  188. }
  189. }
  190. //打开输入弹窗
  191. onEnterStation() {
  192. this.setState({
  193. showStationDialog: true
  194. })
  195. }
  196. //自动刷新
  197. autoCheckIsCharge() {
  198. if (this.canAutoRefresh) {
  199. this.checkIsCharge();
  200. }
  201. }
  202. //自动刷新状态
  203. autoCheckChargeStatus() {
  204. setTimeout(() => {
  205. if (this.canAutoRefresh) {
  206. this.checkChargeStatus();
  207. }
  208. }, 10000);
  209. }
  210. //扫码后获取连接器数据
  211. getConnectorInfo() {
  212. console.log("[TabCharge] getConnectorInfo", this.state.stationInfo.id);
  213. apiCharge.checkIsCharging({sitePk: this.state.stationInfo.id}).then(res => {
  214. this.setState({
  215. connectorInfo: res.data
  216. }, () => {
  217. this.checkChargeStatus();
  218. });
  219. }).catch((err) => {
  220. });
  221. }
  222. //获取充电进度数据(百分比)
  223. checkIsCharge(showError) {
  224. const params = {
  225. sitePk: this.state.stationInfo.id
  226. }
  227. apiCharge.checkIsCharging(params).then(res => {
  228. this.setState({
  229. isStart: true,
  230. isCharging: true,
  231. isAuthentic: true,
  232. connectorInfo: res.data,
  233. lastUpdated: utils.getNowHHmm()
  234. });
  235. if (this.canAutoRefresh) {
  236. setTimeout(() => {
  237. this.autoCheckIsCharge();
  238. }, 30000);
  239. }
  240. PagerUtil.onCharge(this.props);
  241. }).catch(({err, code}) => {
  242. //TODO 模拟测试
  243. //TODO 模拟测试-End
  244. this.setState({
  245. isStart: false,
  246. isCharging: false
  247. });
  248. setTimeout(() => {
  249. this.autoCheckIsCharge();
  250. this.canAutoRefresh = false;
  251. }, 30000);
  252. if (showError) {
  253. this.setState({
  254. errorCode: 'A4',
  255. showErrorDialog: true,
  256. errorMessage: 'Your vehicle doesn’t seem to be charging. Please check your vehicle.'
  257. });
  258. }
  259. });
  260. }
  261. //获取充电进度数据-end
  262. //获取充电桩对应接口的状态
  263. checkChargeStatus(haveResult=false) {
  264. //TODO 模拟测试
  265. /*this.setState({
  266. isStart: true,
  267. isCharging: true,
  268. isAuthentic: true
  269. });
  270. return;*/
  271. //TODO 模拟测试-End
  272. const params = {
  273. connectorId: this.state.connectorInfo.connectorId,
  274. chargeBoxId: this.state.connectorInfo.chargeBoxId,
  275. }
  276. if (!PagerUtil.ENABLE_NEW_UI) {
  277. if (!params.chargeBoxId || !params.connectorId) {
  278. this.checkIsCharge();
  279. return;
  280. }
  281. }
  282. apiCharge.getCurrentStatus(params).then(res => {
  283. if (res.data.status) {
  284. if (PagerUtil.ENABLE_NEW_UI && (this.intoChargingStatus.indexOf(res.data.status) >= 0 || haveResult)) {
  285. //进入新流程
  286. this.setState({
  287. canIntoCharging: true
  288. }, () => {
  289. if (this.autoIntoCharging) {
  290. this.toChargingPage();
  291. } else {
  292. PagerUtil.onCharge(this.props);
  293. }
  294. })
  295. } else {
  296. if (haveResult) {
  297. PagerUtil.onCharge(this.props);
  298. }
  299. switch (res.data.status) {
  300. case 'Available': //可用的
  301. this.state.connectorInfo.isCheckThrough = false;
  302. this.setState({
  303. isStart: false,
  304. isPending: false,
  305. isCharging: false,
  306. connectorInfo: this.state.connectorInfo
  307. });
  308. break;
  309. case 'Preparing': //已插入
  310. this.state.connectorInfo.isCheckThrough = true;
  311. this.setState({
  312. isStart: false,
  313. isPending: false,
  314. isCharging: false,
  315. available: true,
  316. connectorInfo: this.state.connectorInfo
  317. });
  318. //this.checkIsCharge();
  319. break;
  320. case 'Charging': //正在充电
  321. this.canAutoRefresh = true;
  322. this.state.connectorInfo.isCheckThrough = true;
  323. this.setState({
  324. isPending: false,
  325. connectorInfo: this.state.connectorInfo
  326. });
  327. this.checkIsCharge();
  328. break;
  329. case 'Initiating': //充电确认中
  330. this.canAutoRefresh = true;
  331. this.state.connectorInfo.isCheckThrough = true;
  332. this.setState({
  333. isStart: true,
  334. isPending: true,
  335. isCharging: true,
  336. isAuthentic: true,
  337. connectorInfo: this.state.connectorInfo
  338. });
  339. this.autoCheckChargeStatus();
  340. break;
  341. case 'SuspendedEVSE':
  342. this.setState({
  343. errorCode: 'A5',
  344. showErrorDialog: true,
  345. errorMessage: $t('charging.errUnable2Charge')
  346. });
  347. break;
  348. case 'SuspendedEV': //已连接上但未充电
  349. this.checkIsCharge(true);
  350. break;
  351. case 'Reserved': //预定中
  352. this.setState({
  353. errorCode: 'A5',
  354. showErrorDialog: true,
  355. errorMessage: $t('charging.errUnable2Reserved')
  356. });
  357. break;
  358. case 'Finishing': //已完成
  359. if (res.data.chargingPk) {
  360. Dialog.showProgressDialog();
  361. setTimeout(() => {
  362. Dialog.dismissLoading();
  363. this.setState({
  364. isStart: false,
  365. isPending: false,
  366. isCharging: false
  367. });
  368. startPage(PageList.summary, {
  369. chargingPk: res.data.chargingPk,
  370. id: this.state.stationInfo.id,
  371. name: this.state.stationInfo.name,
  372. address: this.state.stationInfo.address
  373. });
  374. }, 2000);
  375. } else {
  376. this.setState({
  377. isStart: true,
  378. isPending: false,
  379. isCharging: false
  380. });
  381. }
  382. break;
  383. default:
  384. this.setState({
  385. isStart: false,
  386. isPending: false,
  387. isCharging: false
  388. });
  389. this.setState({
  390. errorCode: 'A4',
  391. showErrorDialog: true,
  392. errorMessage: $t('charging.errNotChargeE0')
  393. });
  394. break;
  395. }
  396. }
  397. } else {
  398. this.setState({
  399. errorCode: 'A4',
  400. showErrorDialog: true,
  401. errorMessage: $t('charging.errNotChargeE0')
  402. });
  403. }
  404. }).catch((err) => {
  405. toastShort(err)
  406. this.setState({
  407. errorCode: 'A9',
  408. showErrorDialog: true,
  409. errorMessage: $t('charging.errAuthenticationError')
  410. });
  411. })
  412. }
  413. //获取充电桩对应接口的状态-end
  414. //开始充电-start
  415. startCharge() {
  416. if (this.state.connectorInfo.isCheckThrough) {
  417. Dialog.showProgressDialog();
  418. const params = {
  419. sitePk: this.state.stationInfo.id,
  420. chargeBoxId: this.state.connectorInfo.chargeBoxId,
  421. connectorId: this.state.connectorInfo.connectorId
  422. }
  423. if (app.charge.paymentMethod) { //V3版本开始充电
  424. this.onStartChargeV3(params);
  425. return;
  426. }
  427. apiCharge.startCharge(params).then(res => {
  428. console.log("开始充电返回", res);
  429. setTimeout(() => {
  430. this.setState({
  431. isStart: true,
  432. isPending: true,
  433. isCharging: true
  434. });
  435. this.canAutoRefresh = true;
  436. this.autoCheckChargeStatus();
  437. Dialog.dismissLoading();
  438. if (res.msg) {
  439. Dialog.showResultDialog(res.msg)
  440. }
  441. //this.autoCheckIsCharge();
  442. }, 3000);
  443. }).catch(({err, code, data}) => {
  444. //toastShort(err);
  445. console.log("开始充电错误", err, code);
  446. Dialog.dismissLoading();
  447. if (code == 5200) {
  448. this.setState({
  449. errorCode: 'none',
  450. showErrorDialog: true,
  451. errorMessage: "(" + data.transactionPk + ') ' + err
  452. });
  453. } else {
  454. this.setState({
  455. errorCode: 'A4',
  456. showErrorDialog: true,
  457. errorMessage: ''+err
  458. });
  459. }
  460. });
  461. } else {
  462. this.setState({
  463. errorCode: 'A1',
  464. showErrorDialog: true,
  465. errorMessage: $t('charging.errNotConnected')
  466. });
  467. }
  468. }
  469. onStartChargeV3(params) {
  470. if (this.state.currentPayment?.code) {
  471. params.paymentMethod = this.state.currentPayment?.code
  472. }
  473. if (app.v3.vouchers && this.state.selectedVoucher?.userVoucherId) {
  474. params.userVoucherIds = [this.state.selectedVoucher.userVoucherId]
  475. }
  476. console.log("[开始充电V3-params]", params);
  477. apiCharge.startChargeV3(params).then(res => {
  478. console.log("[开始充电V3-response]", res);
  479. if (res.data.webPaymentUrl) {
  480. this.setState({
  481. currentPerUse: "Pending"
  482. })
  483. startPage(PageList.paymentWeb, { amount: params.sitePk, url: res.data.webPaymentUrl, type: 'PayPerUse' });
  484. } else {
  485. setTimeout(() => {
  486. this.setState({
  487. isStart: true,
  488. isPending: true,
  489. isCharging: true
  490. });
  491. this.canAutoRefresh = true;
  492. this.autoCheckChargeStatus();
  493. Dialog.dismissLoading();
  494. if (res.msg) {
  495. Dialog.showResultDialog(res.msg)
  496. }
  497. //this.autoCheckIsCharge();
  498. }, 3000);
  499. }
  500. }).catch(({err, code, data}) => {
  501. //toastShort(err);
  502. console.log("[开始充电V3-错误]", err, code);
  503. Dialog.dismissLoading();
  504. if (code == 5200) {
  505. this.setState({
  506. errorCode: 'none',
  507. showErrorDialog: true,
  508. errorMessage: "(" + data.transactionPk + ') ' + err
  509. });
  510. } else {
  511. this.setState({
  512. errorCode: 'A4',
  513. showErrorDialog: true,
  514. errorMessage: ''+err
  515. });
  516. }
  517. });
  518. }
  519. //开始充电-end
  520. //停止充电-start
  521. onStopCharge() {
  522. if (this.state.isCharging) {
  523. Dialog.showDialog({
  524. title: $t('charging.titleStopCharging'),
  525. message: $t('charging.confirmStopCharging'),
  526. callback: ok => {
  527. if (ok == Dialog.BUTTON_OK) {
  528. this.stopCharge();
  529. }
  530. }
  531. });
  532. } else {
  533. this.stopCharge();
  534. }
  535. }
  536. stopCharge() {
  537. this.canAutoRefresh = false;
  538. Dialog.showProgressDialog();
  539. apiCharge.stopCharge().then(res => {
  540. if (res.msg) {
  541. toastShort(res.msg)
  542. }
  543. if (res.data.chargingPk) {
  544. setTimeout(() => {
  545. Dialog.dismissLoading();
  546. this.setState({
  547. isStart: false,
  548. isPending: false,
  549. isCharging: false,
  550. selectedVoucher: {}
  551. });
  552. PagerUtil.setSelectedVoucher({});
  553. startPage(PageList.summary, {
  554. chargingPk: res.data.chargingPk,
  555. id: this.state.stationInfo.id,
  556. name: this.state.stationInfo.name,
  557. address: this.state.stationInfo.address
  558. });
  559. }, 3000);
  560. } else {
  561. Dialog.dismissLoading();
  562. toastShort($t('charging.errDetected'));
  563. }
  564. }).catch((err) => {
  565. Dialog.dismissLoading();
  566. toastShort(err);
  567. this.setState({
  568. isStart: false,
  569. isPending: false,
  570. isCharging: false
  571. });
  572. //模拟进入结算页
  573. /*startPage(PageList.summary, {
  574. chargingPk: 1,
  575. id: this.state.stationInfo.id,
  576. name: this.state.stationInfo.name,
  577. address: this.state.stationInfo.address
  578. });*/
  579. });
  580. }
  581. //停止充电-end
  582. closeError() {
  583. this.setState({
  584. showErrorDialog: false,
  585. showStationDialog: false
  586. });
  587. }
  588. render() {
  589. return (
  590. <ScrollView
  591. style={styles.container}
  592. keyboardShouldPersistTaps={isIOS ? 'never' : 'handled'}
  593. contentContainerStyle={$padding(0, 16)}
  594. refreshControl={
  595. <RefreshControl
  596. {...MyRefreshProps()}
  597. refreshing={this.state.refreshing}
  598. onRefresh={() => this.onPullRefresh()}
  599. />
  600. }>
  601. { this.state.isAuthentic //是否扫码认证
  602. ? <StepChargeView
  603. isStart={this.state.isStart} //是否开始充电
  604. isPending={this.state.isPending}
  605. isCharging={this.state.isCharging}
  606. lastUpdated={this.state.lastUpdated}
  607. connectorInfo={this.state.connectorInfo}
  608. currentPayment={this.state.currentPayment}
  609. selectedVoucher={this.state.selectedVoucher}
  610. onStartCharge={() => this.startCharge()}
  611. onStopCharge={() => this.onStopCharge()}
  612. onPaymentMethodChanged={(type) => this.onPaymentMethodChanged(type)}/>
  613. : ( app.isLumiWhitelabel
  614. ? <ChargingStartView
  615. isPrivate={this.state.isPrivate}
  616. canIntoCharging={this.state.canIntoCharging}
  617. stationInfo={this.state.stationInfo}
  618. onEnterStation={() => this.onEnterStation()}
  619. onIntoCharging={() => this.toChargingPage()}/>
  620. : <StepStartView
  621. isPrivate={this.state.isPrivate}
  622. canIntoCharging={this.state.canIntoCharging}
  623. stationInfo={this.state.stationInfo}
  624. onEnterStation={() => this.onEnterStation()}
  625. onIntoCharging={() => this.toChargingPage()}/>
  626. )
  627. }
  628. <ErrorDialog
  629. visible={this.state.showErrorDialog}
  630. code={this.state.errorCode}
  631. message={this.state.errorMessage}
  632. onClose={() => {
  633. this.closeError();
  634. }}
  635. />
  636. <EnterStationDialog
  637. visible={this.state.showStationDialog}
  638. stationId={this.state.stationInfo.id}
  639. onConfirm={() => this.enterStatioinId()}
  640. onClose={() => this.closeError()}
  641. />
  642. </ScrollView>
  643. );
  644. }
  645. }
  646. const styles = StyleSheet.create({
  647. container: {
  648. flex: 1
  649. },
  650. title: {
  651. color: '#000',
  652. fontSize: 14,
  653. fontWeight: 'bold',
  654. paddingTop: 16,
  655. paddingBottom: 16
  656. }
  657. })