TabCharge.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  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/QRResult';
  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. payPerUseAmount: this.state.stationInfo.payPerUseAmount
  150. });
  151. }
  152. enterStatioinId() {
  153. if (QRResult.haveResult()) {
  154. if (PagerUtil.ENABLE_NEW_UI) {
  155. this.onRefresh();
  156. } else {
  157. const info = QRResult.getResult()
  158. console.log('EnterResult', info);
  159. this.setState({
  160. isAuthentic: true,
  161. connectorInfo: info
  162. //soc: info.chargeType == 'AC' ? 0 : 'In Charging'
  163. });
  164. this.checkChargeStatus();
  165. }
  166. }
  167. }
  168. onPaymentMethodChanged(payment) {
  169. this.setState({
  170. currentPayment: payment
  171. })
  172. }
  173. onMethodChange() {
  174. this.changeMethod = true;
  175. startPage(PageList.paymentMethod, {info: this.state.connectorInfo, type: this.state.currentPayment});
  176. }
  177. onMethodChanged() {
  178. if (this.changeMethod) {
  179. this.changeMethod = false;
  180. if (global.paymentOption?.title) {
  181. this.setState({
  182. //currentPerUser: global.paymentOption.amount,
  183. currentPayment: global.paymentOption.value,
  184. currentPaytype: global.paymentOption.title
  185. }, () => {
  186. global.paymentOption= {}
  187. })
  188. }
  189. }
  190. }
  191. //打开输入弹窗
  192. onEnterStation() {
  193. this.setState({
  194. showStationDialog: true
  195. })
  196. }
  197. //自动刷新
  198. autoCheckIsCharge() {
  199. if (this.canAutoRefresh) {
  200. this.checkIsCharge();
  201. }
  202. }
  203. //自动刷新状态
  204. autoCheckChargeStatus() {
  205. setTimeout(() => {
  206. if (this.canAutoRefresh) {
  207. this.checkChargeStatus();
  208. }
  209. }, 10000);
  210. }
  211. //扫码后获取连接器数据
  212. getConnectorInfo() {
  213. console.log("[TabCharge] getConnectorInfo", this.state.stationInfo.id);
  214. apiCharge.checkIsCharging({sitePk: this.state.stationInfo.id}).then(res => {
  215. this.setState({
  216. connectorInfo: res.data
  217. }, () => {
  218. this.checkChargeStatus();
  219. });
  220. }).catch((err) => {
  221. });
  222. }
  223. //获取充电进度数据(百分比)
  224. checkIsCharge(showError) {
  225. const params = {
  226. sitePk: this.state.stationInfo.id
  227. }
  228. apiCharge.checkIsCharging(params).then(res => {
  229. this.setState({
  230. isStart: true,
  231. isCharging: true,
  232. isAuthentic: true,
  233. connectorInfo: res.data,
  234. lastUpdated: utils.getNowHHmm()
  235. });
  236. if (this.canAutoRefresh) {
  237. setTimeout(() => {
  238. this.autoCheckIsCharge();
  239. }, 30000);
  240. }
  241. PagerUtil.onCharge(this.props);
  242. }).catch(({err, code}) => {
  243. //TODO 模拟测试
  244. //TODO 模拟测试-End
  245. this.setState({
  246. isStart: false,
  247. isCharging: false
  248. });
  249. setTimeout(() => {
  250. this.autoCheckIsCharge();
  251. this.canAutoRefresh = false;
  252. }, 30000);
  253. if (showError) {
  254. this.setState({
  255. errorCode: 'A4',
  256. showErrorDialog: true,
  257. errorMessage: 'Your vehicle doesn’t seem to be charging. Please check your vehicle.'
  258. });
  259. }
  260. });
  261. }
  262. //获取充电进度数据-end
  263. //获取充电桩对应接口的状态
  264. checkChargeStatus(haveResult=false) {
  265. //TODO 模拟测试
  266. /*this.setState({
  267. isStart: true,
  268. isCharging: true,
  269. isAuthentic: true
  270. });
  271. return;*/
  272. //TODO 模拟测试-End
  273. const params = {
  274. connectorId: this.state.connectorInfo.connectorId,
  275. chargeBoxId: this.state.connectorInfo.chargeBoxId,
  276. }
  277. if (!PagerUtil.ENABLE_NEW_UI) {
  278. if (!params.chargeBoxId || !params.connectorId) {
  279. this.checkIsCharge();
  280. return;
  281. }
  282. }
  283. apiCharge.getCurrentStatus(params).then(res => {
  284. if (res.data.status) {
  285. if (PagerUtil.ENABLE_NEW_UI && (this.intoChargingStatus.indexOf(res.data.status) >= 0 || haveResult)) {
  286. //进入新流程
  287. this.setState({
  288. canIntoCharging: true
  289. }, () => {
  290. if (this.autoIntoCharging) {
  291. this.toChargingPage();
  292. } else {
  293. PagerUtil.onCharge(this.props);
  294. }
  295. })
  296. } else {
  297. if (haveResult) {
  298. PagerUtil.onCharge(this.props);
  299. }
  300. switch (res.data.status) {
  301. case 'Available': //可用的
  302. this.state.connectorInfo.isCheckThrough = false;
  303. this.setState({
  304. isStart: false,
  305. isPending: false,
  306. isCharging: false,
  307. connectorInfo: this.state.connectorInfo
  308. });
  309. break;
  310. case 'Preparing': //已插入
  311. this.state.connectorInfo.isCheckThrough = true;
  312. this.setState({
  313. isStart: false,
  314. isPending: false,
  315. isCharging: false,
  316. available: true,
  317. connectorInfo: this.state.connectorInfo
  318. });
  319. //this.checkIsCharge();
  320. break;
  321. case 'Charging': //正在充电
  322. this.canAutoRefresh = true;
  323. this.state.connectorInfo.isCheckThrough = true;
  324. this.setState({
  325. isPending: false,
  326. connectorInfo: this.state.connectorInfo
  327. });
  328. this.checkIsCharge();
  329. break;
  330. case 'Initiating': //充电确认中
  331. this.canAutoRefresh = true;
  332. this.state.connectorInfo.isCheckThrough = true;
  333. this.setState({
  334. isStart: true,
  335. isPending: true,
  336. isCharging: true,
  337. isAuthentic: true,
  338. connectorInfo: this.state.connectorInfo
  339. });
  340. this.autoCheckChargeStatus();
  341. break;
  342. case 'SuspendedEVSE':
  343. this.setState({
  344. errorCode: 'A5',
  345. showErrorDialog: true,
  346. errorMessage: $t('charging.errUnable2Charge')
  347. });
  348. break;
  349. case 'SuspendedEV': //已连接上但未充电
  350. this.checkIsCharge(true);
  351. break;
  352. case 'Reserved': //预定中
  353. this.setState({
  354. errorCode: 'A5',
  355. showErrorDialog: true,
  356. errorMessage: $t('charging.errUnable2Reserved')
  357. });
  358. break;
  359. case 'Finishing': //已完成
  360. if (res.data.chargingPk) {
  361. Dialog.showProgressDialog();
  362. setTimeout(() => {
  363. Dialog.dismissLoading();
  364. this.setState({
  365. isStart: false,
  366. isPending: false,
  367. isCharging: false
  368. });
  369. startPage(PageList.summary, {
  370. chargingPk: res.data.chargingPk,
  371. id: this.state.stationInfo.id,
  372. name: this.state.stationInfo.name,
  373. address: this.state.stationInfo.address
  374. });
  375. }, 2000);
  376. } else {
  377. this.setState({
  378. isStart: true,
  379. isPending: false,
  380. isCharging: false
  381. });
  382. }
  383. break;
  384. default:
  385. this.setState({
  386. isStart: false,
  387. isPending: false,
  388. isCharging: false
  389. });
  390. this.setState({
  391. errorCode: 'A4',
  392. showErrorDialog: true,
  393. errorMessage: $t('charging.errNotChargeE0')
  394. });
  395. break;
  396. }
  397. }
  398. } else {
  399. this.setState({
  400. errorCode: 'A4',
  401. showErrorDialog: true,
  402. errorMessage: $t('charging.errNotChargeE0')
  403. });
  404. }
  405. }).catch((err) => {
  406. toastShort(err)
  407. this.setState({
  408. errorCode: 'A9',
  409. showErrorDialog: true,
  410. errorMessage: $t('charging.errAuthenticationError')
  411. });
  412. })
  413. }
  414. //获取充电桩对应接口的状态-end
  415. //开始充电-start
  416. startCharge() {
  417. if (this.state.connectorInfo.isCheckThrough) {
  418. Dialog.showProgressDialog();
  419. const params = {
  420. sitePk: this.state.stationInfo.id,
  421. chargeBoxId: this.state.connectorInfo.chargeBoxId,
  422. connectorId: this.state.connectorInfo.connectorId
  423. }
  424. if (app.charge.paymentMethod) { //V3版本开始充电
  425. this.onStartChargeV3(params);
  426. return;
  427. }
  428. apiCharge.startCharge(params).then(res => {
  429. console.log("开始充电返回", res);
  430. setTimeout(() => {
  431. this.setState({
  432. isStart: true,
  433. isPending: true,
  434. isCharging: true
  435. });
  436. this.canAutoRefresh = true;
  437. this.autoCheckChargeStatus();
  438. Dialog.dismissLoading();
  439. if (res.msg) {
  440. Dialog.showResultDialog(res.msg)
  441. }
  442. //this.autoCheckIsCharge();
  443. }, 3000);
  444. }).catch(({err, code, data}) => {
  445. //toastShort(err);
  446. console.log("开始充电错误", err, code);
  447. Dialog.dismissLoading();
  448. if (code == 5200) {
  449. this.setState({
  450. errorCode: 'none',
  451. showErrorDialog: true,
  452. errorMessage: "(" + data.transactionPk + ') ' + err
  453. });
  454. } else {
  455. this.setState({
  456. errorCode: 'A4',
  457. showErrorDialog: true,
  458. errorMessage: ''+err
  459. });
  460. }
  461. });
  462. } else {
  463. this.setState({
  464. errorCode: 'A1',
  465. showErrorDialog: true,
  466. errorMessage: $t('charging.errNotConnected')
  467. });
  468. }
  469. }
  470. onStartChargeV3(params) {
  471. if (this.state.currentPayment?.code) {
  472. params.paymentMethod = this.state.currentPayment?.code
  473. }
  474. if (app.v3.vouchers && this.state.selectedVoucher?.userVoucherId) {
  475. params.userVoucherIds = [this.state.selectedVoucher.userVoucherId]
  476. }
  477. console.log("[开始充电V3-params]", params);
  478. apiCharge.startChargeV3(params).then(res => {
  479. console.log("[开始充电V3-response]", res);
  480. if (res.data.webPaymentUrl) {
  481. this.setState({
  482. currentPerUse: "Pending"
  483. })
  484. startPage(PageList.paymentWeb, { amount: params.sitePk, url: res.data.webPaymentUrl, type: 'PayPerUse' });
  485. } else {
  486. setTimeout(() => {
  487. this.setState({
  488. isStart: true,
  489. isPending: true,
  490. isCharging: true
  491. });
  492. this.canAutoRefresh = true;
  493. this.autoCheckChargeStatus();
  494. Dialog.dismissLoading();
  495. if (res.msg) {
  496. Dialog.showResultDialog(res.msg)
  497. }
  498. //this.autoCheckIsCharge();
  499. }, 3000);
  500. }
  501. }).catch(({err, code, data}) => {
  502. //toastShort(err);
  503. console.log("[开始充电V3-错误]", err, code);
  504. Dialog.dismissLoading();
  505. if (code == 5200) {
  506. this.setState({
  507. errorCode: 'none',
  508. showErrorDialog: true,
  509. errorMessage: "(" + data.transactionPk + ') ' + err
  510. });
  511. } else {
  512. this.setState({
  513. errorCode: 'A4',
  514. showErrorDialog: true,
  515. errorMessage: ''+err
  516. });
  517. }
  518. });
  519. }
  520. //开始充电-end
  521. //停止充电-start
  522. onStopCharge() {
  523. if (this.state.isCharging) {
  524. Dialog.showDialog({
  525. title: $t('charging.titleStopCharging'),
  526. message: $t('charging.confirmStopCharging'),
  527. callback: ok => {
  528. if (ok == Dialog.BUTTON_OK) {
  529. this.stopCharge();
  530. }
  531. }
  532. });
  533. } else {
  534. this.stopCharge();
  535. }
  536. }
  537. stopCharge() {
  538. this.canAutoRefresh = false;
  539. Dialog.showProgressDialog();
  540. apiCharge.stopCharge().then(res => {
  541. if (res.msg) {
  542. toastShort(res.msg)
  543. }
  544. if (res.data.chargingPk) {
  545. setTimeout(() => {
  546. Dialog.dismissLoading();
  547. this.setState({
  548. isStart: false,
  549. isPending: false,
  550. isCharging: false,
  551. selectedVoucher: {}
  552. });
  553. PagerUtil.setSelectedVoucher({});
  554. startPage(PageList.summary, {
  555. chargingPk: res.data.chargingPk,
  556. id: this.state.stationInfo.id,
  557. name: this.state.stationInfo.name,
  558. address: this.state.stationInfo.address
  559. });
  560. }, 3000);
  561. } else {
  562. Dialog.dismissLoading();
  563. toastShort($t('charging.errDetected'));
  564. }
  565. }).catch((err) => {
  566. Dialog.dismissLoading();
  567. toastShort(err);
  568. this.setState({
  569. isStart: false,
  570. isPending: false,
  571. isCharging: false
  572. });
  573. //模拟进入结算页
  574. /*startPage(PageList.summary, {
  575. chargingPk: 1,
  576. id: this.state.stationInfo.id,
  577. name: this.state.stationInfo.name,
  578. address: this.state.stationInfo.address
  579. });*/
  580. });
  581. }
  582. //停止充电-end
  583. closeError() {
  584. this.setState({
  585. showErrorDialog: false,
  586. showStationDialog: false
  587. });
  588. }
  589. render() {
  590. return (
  591. <ScrollView
  592. style={styles.container}
  593. keyboardShouldPersistTaps={isIOS ? 'never' : 'handled'}
  594. contentContainerStyle={$padding(0, 16)}
  595. refreshControl={
  596. <RefreshControl
  597. {...MyRefreshProps()}
  598. refreshing={this.state.refreshing}
  599. onRefresh={() => this.onPullRefresh()}
  600. />
  601. }>
  602. { this.state.isAuthentic //是否扫码认证
  603. ? <StepChargeView
  604. isStart={this.state.isStart} //是否开始充电
  605. isPending={this.state.isPending}
  606. isCharging={this.state.isCharging}
  607. lastUpdated={this.state.lastUpdated}
  608. connectorInfo={this.state.connectorInfo}
  609. currentPayment={this.state.currentPayment}
  610. selectedVoucher={this.state.selectedVoucher}
  611. onStartCharge={() => this.startCharge()}
  612. onStopCharge={() => this.onStopCharge()}
  613. onPaymentMethodChanged={(type) => this.onPaymentMethodChanged(type)}/>
  614. : ( app.isLumiWhitelabel
  615. ? <ChargingStartView
  616. isPrivate={this.state.isPrivate}
  617. canIntoCharging={this.state.canIntoCharging}
  618. stationInfo={this.state.stationInfo}
  619. onEnterStation={() => this.onEnterStation()}
  620. onIntoCharging={() => this.toChargingPage()}/>
  621. : <StepStartView
  622. isPrivate={this.state.isPrivate}
  623. canIntoCharging={this.state.canIntoCharging}
  624. stationInfo={this.state.stationInfo}
  625. onEnterStation={() => this.onEnterStation()}
  626. onIntoCharging={() => this.toChargingPage()}/>
  627. )
  628. }
  629. <ErrorDialog
  630. visible={this.state.showErrorDialog}
  631. code={this.state.errorCode}
  632. message={this.state.errorMessage}
  633. onClose={() => {
  634. this.closeError();
  635. }}
  636. />
  637. <EnterStationDialog
  638. visible={this.state.showStationDialog}
  639. stationId={this.state.stationInfo.id}
  640. onConfirm={() => this.enterStatioinId()}
  641. onClose={() => this.closeError()}
  642. />
  643. </ScrollView>
  644. );
  645. }
  646. }
  647. const styles = StyleSheet.create({
  648. container: {
  649. flex: 1
  650. },
  651. title: {
  652. color: '#000',
  653. fontSize: 14,
  654. fontWeight: 'bold',
  655. paddingTop: 16,
  656. paddingBottom: 16
  657. }
  658. })