Charge.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  1. /**
  2. * 充电页面
  3. * @邠心vbe on 2021/04/12
  4. */
  5. import React, { Component } from 'react';
  6. import { View, Text, StyleSheet, ImageBackground, Image, TextInput } from 'react-native';
  7. import apiCharge from '../../api/apiCharge';
  8. import Button from '../../components/Button';
  9. import Dialog from '../../components/Dialog';
  10. import { PageList } from '../Router';
  11. import { BatteryView, ChargeStyle, circleSize, EnterStationDialog, TypeImage } from './Charging';
  12. import Payment from '../wallet/Payment';
  13. import { QRResult } from './QRScan';
  14. import { ErrorDialog } from './InfoDialog';
  15. import utils from '../../utils/utils';
  16. import TextView from '../../components/TextView';
  17. import { PaymentDefault, PAYTYPE } from '../payment/PaymentConfig';
  18. export default class Charge extends Component {
  19. constructor(props) {
  20. super(props);
  21. this.state = {
  22. available: false,
  23. isPrivate: false,
  24. refreshId: 0,
  25. isStart: false,
  26. isPending: false,
  27. isCharging: false,
  28. isAuthentic: false,
  29. rateList: [],
  30. selectRate: '',
  31. connectorInfo: {},
  32. stationInfo: {},
  33. lastUpdated: '',
  34. errorCode: 'A9',
  35. errorMessage: '',
  36. showErrorDialog: false,
  37. showStationDialog: false,
  38. curerntPerUser: undefined,
  39. //currentPayment: PAYTYPE.CREDIT_WALLET,
  40. //currentPaytype: "Credit Wallet",
  41. currentPayment: PaymentDefault.DEFAULT.payType,
  42. currentPaytype: PaymentDefault.DEFAULT.payName
  43. };
  44. this.changeMethod = false;
  45. this.canAutoRefresh = false;
  46. this.inputStationId = '';
  47. }
  48. componentDidMount() {
  49. this.canAutoRefresh = true;
  50. if (this.props.stationInfo) {
  51. this.setState({
  52. rateList: this.props.stationInfo.rateList ?? [],
  53. stationInfo: this.props.stationInfo
  54. }, () => {
  55. this.refreshAvailable();
  56. this.checkIsCharge();
  57. });
  58. }
  59. }
  60. componentDidUpdate() {
  61. if (this.props.visible && this.props.refreshId != this.state.refreshId) {
  62. this.onMethodChanged();
  63. this.setState({
  64. refreshId: this.props.refreshId,
  65. rateList: this.props.stationInfo.rateList ?? [],
  66. stationInfo: this.props.stationInfo
  67. }, () => this.refreshAvailable());
  68. if (QRResult.haveResult()) {
  69. const info = QRResult.getResult()
  70. console.log('QRResult', info);
  71. this.setState({
  72. isAuthentic: true,
  73. connectorInfo: info
  74. //soc: info.chargeType == 'AC' ? 0 : 'In Charging'
  75. });
  76. this.checkChargeStatus();
  77. } else if (this.state.isStart) {
  78. this.checkIsCharge();
  79. } else {
  80. this.checkChargeStatus();
  81. }
  82. }
  83. }
  84. componentWillUnmount() {
  85. this.canAutoRefresh = false;
  86. }
  87. //刷新可用充电接口
  88. refreshAvailable() {
  89. const info = this.state.stationInfo
  90. const all = info?.allConnector;
  91. if (info.siteType == 'Private') {
  92. this.setState({
  93. isPrivate: true
  94. })
  95. }
  96. if (all) {
  97. this.setState({
  98. available: !all.available > 0
  99. });
  100. }
  101. }
  102. enterStatioinId() {
  103. if (QRResult.haveResult()) {
  104. const info = QRResult.getResult()
  105. console.log('EnterResult', info);
  106. this.setState({
  107. isAuthentic: true,
  108. connectorInfo: info
  109. //soc: info.chargeType == 'AC' ? 0 : 'In Charging'
  110. });
  111. this.checkChargeStatus();
  112. }
  113. }
  114. onMethodChange() {
  115. this.changeMethod = true;
  116. startPage(PageList.paymentMethod, {info: this.state.connectorInfo, type: this.state.currentPayment});
  117. }
  118. onMethodChanged() {
  119. if (this.changeMethod) {
  120. this.changeMethod = false;
  121. if (global.paymentOption?.title) {
  122. this.setState({
  123. curerntPerUser: global.paymentOption.amount,
  124. currentPayment: global.paymentOption.value,
  125. currentPaytype: global.paymentOption.title
  126. }, () => {
  127. global.paymentOption= {}
  128. })
  129. }
  130. }
  131. }
  132. //扫码之前-站点信息Section
  133. StationInfo() {
  134. return (
  135. <View style={styles.listView}>
  136. <View style={ChargeStyle.stationInfoView}>
  137. <ImageBackground
  138. style={{
  139. width: 42,
  140. height: 42
  141. }}
  142. source={require('../../images/charge/icon-station-no.png')}>
  143. <TextView style={{
  144. left: 0,
  145. right: 0,
  146. bottom: 1,
  147. fontSize: 8,
  148. textAlign: 'center',
  149. position: 'absolute'
  150. }}>{this.state.connectorInfo.connectorId}</TextView>
  151. </ImageBackground>
  152. <View style={ChargeStyle.infoGroup}>
  153. <TextView style={ChargeStyle.infoTitle}>Type</TextView>
  154. <TextView style={ChargeStyle.infoText}>{this.state.connectorInfo.chargeType}{this.state.connectorInfo.wattage}</TextView>
  155. </View>
  156. <View style={ChargeStyle.infoGroup}>
  157. <TextView style={ChargeStyle.infoTitle}>Power</TextView>
  158. <TextView style={ChargeStyle.infoText}>{this.state.connectorInfo.wattage}kW{/*this.state.connectorInfo.rateType*/}</TextView>
  159. </View>
  160. <View style={ChargeStyle.infoGroup}>
  161. <TextView style={ChargeStyle.infoTitle}>Rate</TextView>
  162. <TextView style={ChargeStyle.infoText}>{currency}{this.state.connectorInfo.rate}/{this.state.connectorInfo.rateType}</TextView>
  163. </View>
  164. { this.state.connectorInfo.isCheckThrough
  165. ? <View style={ChargeStyle.infoGroup}>
  166. <MaterialIcons name='check-circle' size={18} color='#90DB0A'/>
  167. <TextView style={ChargeStyle.authText}>Authenticated</TextView>
  168. </View>
  169. : <View style={ChargeStyle.infoGroup}>
  170. <MaterialCommunityIcons name='close-circle' size={18} color='#FF6666'/>
  171. <TextView style={ChargeStyle.authText}>Not Connected</TextView>
  172. </View>
  173. }
  174. </View>
  175. </View>
  176. );
  177. }
  178. //扫码之前-站点信息Section-end
  179. //扫码之后-选择的站点信息Section
  180. UseStationInfo() {
  181. return (
  182. <View style={[styles.listView, { marginTop: 16}]}>
  183. <View style={ChargeStyle.stationInfoView}>
  184. <ImageBackground
  185. style={{
  186. width: 42,
  187. height: 42
  188. }}
  189. source={require('../../images/charge/icon-station-no.png')}>
  190. <TextView style={{
  191. left: 0,
  192. right: 0,
  193. bottom: 1,
  194. fontSize: 8,
  195. color: textPrimary,
  196. textAlign: 'center',
  197. position: 'absolute'
  198. }}>{this.state.connectorInfo.connectorId}</TextView>
  199. </ImageBackground>
  200. <View style={ChargeStyle.infoGroup}>
  201. <TextView style={ChargeStyle.infoTitle}>Type</TextView>
  202. <TextView style={ChargeStyle.infoText}>{this.state.connectorInfo.chargeType}{this.state.connectorInfo.wattage}</TextView>
  203. </View>
  204. <View style={ChargeStyle.infoGroup}>
  205. <TextView style={ChargeStyle.infoTitle}>Power</TextView>
  206. <TextView style={ChargeStyle.infoText}>{this.state.connectorInfo.wattage}kW</TextView>
  207. </View>
  208. <View style={ChargeStyle.infoGroup}>
  209. <TextView style={ChargeStyle.infoTitle}>Rate</TextView>
  210. <TextView style={ChargeStyle.infoText}>{currency}{this.state.connectorInfo.rate}/{this.state.connectorInfo.rateType}</TextView>
  211. </View>
  212. <View style={ChargeStyle.infoGroup}>
  213. <TextView style={styles.inUse}>In Use</TextView>
  214. </View>
  215. </View>
  216. <View style={[ChargeStyle.stationInfoView, ChargeStyle.itemDivide]}>
  217. <View style={ChargeStyle.infoGroup}>
  218. <TextView style={ChargeStyle.infoTitle}>Time Elapsed</TextView>
  219. <TextView style={ChargeStyle.infoText}>{this.state.connectorInfo.timeElapsed?.toFixed(0) ?? 0} Minutes</TextView>
  220. </View>
  221. <View style={ChargeStyle.infoGroup}>
  222. <TextView style={ChargeStyle.infoTitle}>Total kWh Delivered</TextView>
  223. <TextView style={ChargeStyle.infoText}>{this.state.connectorInfo.totalKWhDelivered ?? 0} kWh</TextView>
  224. </View>
  225. <View style={ChargeStyle.infoGroup}>
  226. <TextView style={ChargeStyle.infoTitle}>Total Charges</TextView>
  227. <TextView style={ChargeStyle.infoText}>{currency} {this.state.connectorInfo.totalCharges?.toFixed(2) ?? '0.0'}</TextView>
  228. </View>
  229. </View>
  230. </View>
  231. );
  232. }
  233. //扫码之后-选择的站点信息Section-end
  234. //初始页面-扫码认证之前
  235. StepRateView() {
  236. return (
  237. <>
  238. <TextView style={styles.title}>Rates</TextView>
  239. <View style={styles.listView}>
  240. { this.state.rateList.length > 0
  241. ? this.state.rateList.map((item, index) => {
  242. return (
  243. <View key={index} style={[ChargeStyle.stationInfoView, index > 0 ? ChargeStyle.itemDivide : {}]}>
  244. <Image
  245. style={ChargeStyle.infoIcon}
  246. source={item.type?.indexOf('AC') >= 0 ? TypeImage.AC : TypeImage.DC}/>
  247. <View style={ChargeStyle.infoGroup}>
  248. <TextView style={ChargeStyle.infoTitle}>Type</TextView>
  249. <TextView style={ChargeStyle.infoText}>{item.type}</TextView>
  250. </View>
  251. <View style={ChargeStyle.infoGroup}>
  252. <TextView style={ChargeStyle.infoTitle}>Power</TextView>
  253. <TextView style={ChargeStyle.infoText}>{item.power}</TextView>
  254. </View>
  255. <View style={ChargeStyle.infoGroup}>
  256. <TextView style={ChargeStyle.infoTitle}>Rate</TextView>
  257. <TextView style={ChargeStyle.infoText}>{item.rates}</TextView>
  258. </View>
  259. { item?.connectorCount?.available > 0
  260. ? <TextView style={[ChargeStyle.infoStatus, ChargeStyle.statusAvailable]}>Available</TextView>
  261. : <TextView style={[ChargeStyle.infoStatus, ChargeStyle.statusUnavailable]}>Unavailable</TextView>
  262. }
  263. </View>
  264. );
  265. })
  266. : <Text style={ui.noData}>No Rates</Text>
  267. }
  268. </View>
  269. <View style={styles.privateView}>
  270. { this.state.isPrivate &&
  271. <Text style={styles.privateText}>NOTE: The charging stations are for private usage.</Text>
  272. }
  273. </View>
  274. <Payment refreshId={this.state.refreshId}/>
  275. <View style={styles.buttonGroup}>
  276. <Button
  277. style={styles.buttonLeft}
  278. text='Scan QR'
  279. //disabled={this.state.available}
  280. onClick={() => {
  281. startPage(PageList.scanqr, {actionDetail: false, id: this.state.stationInfo.id});
  282. }}/>
  283. <Button
  284. style={styles.buttonRight}
  285. text='Enter Station ID'
  286. //disabled={this.state.available}
  287. onClick={() => {
  288. this.setState({
  289. showStationDialog: true
  290. })
  291. }}/>
  292. </View>
  293. </>
  294. );
  295. }
  296. //初始页面-扫码认证之前-end
  297. //扫码认证之后-充电开始之前
  298. StepStartView() {
  299. return (
  300. <>
  301. <TextView style={styles.title}>Your Selection</TextView>
  302. {this.StationInfo()}
  303. <View style={ui.center}>
  304. <ImageBackground
  305. style={styles.batteryBorder}
  306. source={require('../../images/charge/ic-charge-circle.png')}>
  307. <Text style={{
  308. color: textPrimary,
  309. fontSize: 16,
  310. lineHeight: 22,
  311. textAlign: 'center'
  312. }}>
  313. Press<Text style={{padding: 10, fontWeight: 'bold'}}> Start </Text>to begin Charging
  314. </Text>
  315. </ImageBackground>
  316. </View>
  317. <Payment
  318. refreshId={this.state.refreshId}
  319. payType={this.state.currentPaytype}
  320. balance={this.state.curerntPerUser}
  321. isPayPerUse={this.state.currentPayment == PAYTYPE.PAY_PER_USE}
  322. onMethodChange={() => this.onMethodChange()}
  323. />
  324. <Button
  325. style={styles.buttonView}
  326. text='Start'
  327. elevation={1.5}
  328. onClick={() => this.startCharge()}/>
  329. </>
  330. );
  331. }
  332. //扫码认证之后-充电开始之前-end
  333. //正在充电页面
  334. StepChargeView() {
  335. return (
  336. <>
  337. {this.UseStationInfo()}
  338. <BatteryView
  339. soc={this.state.connectorInfo.batteryPercent}
  340. isCharging={this.state.isCharging}
  341. isPending={this.state.isPending}
  342. />
  343. { this.state.lastUpdated
  344. ? <Text style={styles.updateTip}>{'Last updated at ' + this.state.lastUpdated + '\nPull down to refresh'}</Text>
  345. : null
  346. }
  347. <Payment
  348. refreshId={this.state.refreshId}
  349. payType={this.state.currentPaytype}
  350. balance={this.state.curerntPerUser}
  351. />
  352. <Button
  353. style={styles.buttonView}
  354. disabled={this.state.isPending}
  355. text={this.state.isCharging ? 'Stop Charging' : 'Complete'}
  356. elevation={1.5}
  357. onClick={() => {
  358. if (this.state.isCharging) {
  359. Dialog.showDialog({
  360. title: 'Stop Charging',
  361. message: 'Are you sure stop charging?',
  362. callback: ok => {
  363. if (ok == Dialog.BUTTON_OK) {
  364. this.stopCharge();
  365. }
  366. }
  367. });
  368. } else {
  369. this.stopCharge();
  370. }
  371. }}/>
  372. </>
  373. );
  374. }
  375. //正在充电页面-end
  376. //自动刷新
  377. autoCheckIsCharge() {
  378. if (this.canAutoRefresh) {
  379. this.checkIsCharge();
  380. }
  381. }
  382. //自动刷新状态
  383. autoCheckChargeStatus() {
  384. setTimeout(() => {
  385. if (this.canAutoRefresh) {
  386. this.checkChargeStatus();
  387. }
  388. }, 10000);
  389. }
  390. //获取充电数据(百分比)
  391. checkIsCharge(showError) {
  392. const params = {
  393. sitePk: this.props.stationInfo.id
  394. }
  395. apiCharge.checkIsCharging(params).then(res => {
  396. this.setState({
  397. isStart: true,
  398. isCharging: true,
  399. isAuthentic: true,
  400. connectorInfo: res.data,
  401. lastUpdated: utils.getNowHHmm()
  402. });
  403. if (this.canAutoRefresh) {
  404. setTimeout(() => {
  405. this.autoCheckIsCharge();
  406. }, 30000);
  407. }
  408. if (!this.props.visible && this.props.onCharge)
  409. this.props.onCharge()
  410. }).catch((err) => {
  411. //TODO 模拟测试
  412. this.setState({
  413. isStart: false,
  414. isCharging: false
  415. });
  416. setTimeout(() => {
  417. this.autoCheckIsCharge();
  418. }, 30000);
  419. if (showError) {
  420. this.setState({
  421. errorCode: 'A4',
  422. showErrorDialog: true,
  423. errorMessage: 'Your vehicle doesn’t seem to be charging. Please check your vehicle.'
  424. });
  425. }
  426. });
  427. }
  428. //获取充电桩对应接口的状态
  429. checkChargeStatus() {
  430. //TODO 模拟测试
  431. /*this.setState({
  432. isStart: true,
  433. isCharging: true,
  434. isAuthentic: true
  435. });
  436. return;*/
  437. const params = {
  438. connectorId: this.state.connectorInfo.connectorId,
  439. chargeBoxId: this.state.connectorInfo.chargeBoxId,
  440. }
  441. if (!params.chargeBoxId || !params.connectorId) {
  442. return;
  443. }
  444. apiCharge.getCurrentStatus(params).then(res => {
  445. if (res.data.status) {
  446. switch (res.data.status) {
  447. case 'Available': //可用的
  448. this.state.connectorInfo.isCheckThrough = false;
  449. this.setState({
  450. isStart: false,
  451. isPending: false,
  452. isCharging: false,
  453. connectorInfo: this.state.connectorInfo
  454. });
  455. break;
  456. case 'Preparing': //已插入
  457. this.state.connectorInfo.isCheckThrough = true;
  458. this.setState({
  459. isStart: false,
  460. isPending: false,
  461. isCharging: false,
  462. available: true,
  463. connectorInfo: this.state.connectorInfo
  464. });
  465. //this.checkIsCharge();
  466. break;
  467. case 'Charging': //正在充电
  468. this.canAutoRefresh = true;
  469. this.state.connectorInfo.isCheckThrough = true;
  470. this.setState({
  471. isPending: false,
  472. connectorInfo: this.state.connectorInfo
  473. });
  474. this.checkIsCharge();
  475. break;
  476. case 'Initiating': //充电确认中
  477. this.canAutoRefresh = true;
  478. this.state.connectorInfo.isCheckThrough = true;
  479. this.setState({
  480. isStart: true,
  481. isPending: true,
  482. isCharging: true,
  483. isAuthentic: true,
  484. connectorInfo: this.state.connectorInfo
  485. });
  486. this.autoCheckChargeStatus();
  487. break;
  488. case 'SuspendedEVSE':
  489. this.setState({
  490. errorCode: 'A5',
  491. showErrorDialog: true,
  492. errorMessage: 'The charging station is unable to charge your vehicle.Please reauthenticate.'
  493. });
  494. break;
  495. case 'SuspendedEV': //已连接上但未充电
  496. this.checkIsCharge(true);
  497. break;
  498. case 'Reserved': //预定中
  499. this.setState({
  500. errorCode: 'A5',
  501. showErrorDialog: true,
  502. errorMessage: 'The charging station is reserved and unable to charge your vehicle.'
  503. });
  504. break;
  505. case 'Finishing': //已完成
  506. this.setState({
  507. isStart: true,
  508. isPending: false,
  509. isCharging: false
  510. });
  511. break;
  512. default:
  513. this.setState({
  514. isStart: false,
  515. isPending: false,
  516. isCharging: false
  517. });
  518. this.setState({
  519. errorCode: 'A4',
  520. showErrorDialog: true,
  521. errorMessage: 'Your vehicle doesn’t seem to be charging. Please check your vehicle. (E0)'
  522. });
  523. break;
  524. }
  525. }
  526. }).catch((err) => {
  527. toastShort(err)
  528. this.setState({
  529. errorCode: 'A9',
  530. showErrorDialog: true,
  531. errorMessage: 'There seems to be an authentication error! Please try again'
  532. });
  533. })
  534. }
  535. //开始充电api
  536. startCharge() {
  537. if (this.state.connectorInfo.isCheckThrough) {
  538. Dialog.showProgressDialog();
  539. const params = {
  540. chargeBoxId: this.state.connectorInfo.chargeBoxId,
  541. connectorId: this.state.connectorInfo.connectorId
  542. }
  543. apiCharge.startCharge(params).then(res => {
  544. this.setState({
  545. isStart: true,
  546. isPending: true,
  547. isCharging: true
  548. });
  549. this.canAutoRefresh = true;
  550. this.autoCheckChargeStatus();
  551. /*setTimeout(() => {
  552. this.autoCheckIsCharge();
  553. }, 30000);*/
  554. Dialog.dismissLoading();
  555. }).catch((err) => {
  556. //toastShort(err);
  557. Dialog.dismissLoading();
  558. this.setState({
  559. errorCode: 'A4',
  560. showErrorDialog: true,
  561. errorMessage: ''+err
  562. });
  563. });
  564. } else {
  565. this.setState({
  566. errorCode: 'A1',
  567. showErrorDialog: true,
  568. errorMessage: 'Your vehicle is not connected to the charging station. Please check the connector.'
  569. });
  570. }
  571. }
  572. //停止充电api
  573. stopCharge() {
  574. this.canAutoRefresh = false;
  575. Dialog.showProgressDialog();
  576. apiCharge.stopCharge().then(res => {
  577. if (res.data.chargingPk) {
  578. setTimeout(() => {
  579. Dialog.dismissLoading();
  580. this.setState({
  581. isStart: false,
  582. isPending: false,
  583. isCharging: false
  584. });
  585. startPage(PageList.summary, {
  586. chargingPk: res.data.chargingPk,
  587. id: this.state.stationInfo.id,
  588. name: this.state.stationInfo.name,
  589. address: this.state.stationInfo.address
  590. });
  591. }, 3000);
  592. } else {
  593. Dialog.dismissLoading();
  594. toastShort('An error detected, please retry.')
  595. }
  596. }).catch((err) => {
  597. Dialog.dismissLoading();
  598. toastShort(err);
  599. this.setState({
  600. isStart: false,
  601. isPending: false,
  602. isCharging: false
  603. });
  604. //模拟进入结算页
  605. /*startPage(PageList.summary, {
  606. chargingPk: 1,
  607. id: this.state.stationInfo.id,
  608. name: this.state.stationInfo.name,
  609. address: this.state.stationInfo.address
  610. });*/
  611. });
  612. }
  613. closeError() {
  614. this.setState({
  615. showErrorDialog: false,
  616. showStationDialog: false
  617. });
  618. }
  619. render() {
  620. return (
  621. <View style={{
  622. paddingLeft: 16,
  623. paddingRight: 16,
  624. ...this.props.style
  625. }}>
  626. { this.state.isAuthentic //是否扫码认证
  627. ? this.state.isStart //是否开始充电
  628. ? this.StepChargeView()
  629. : this.StepStartView()
  630. : this.StepRateView()
  631. }
  632. <ErrorDialog
  633. visible={this.state.showErrorDialog}
  634. code={this.state.errorCode}
  635. message={this.state.errorMessage}
  636. onClose={() => {
  637. this.closeError();
  638. }}
  639. />
  640. <EnterStationDialog
  641. visible={this.state.showStationDialog}
  642. stationId={this.state.stationInfo.id}
  643. onConfirm={() => this.enterStatioinId()}
  644. onClose={() => this.closeError()}
  645. />
  646. </View>
  647. );
  648. }
  649. }
  650. const styles = StyleSheet.create({
  651. title: {
  652. color: '#000',
  653. fontSize: 14,
  654. fontWeight: 'bold',
  655. paddingTop: 16,
  656. paddingBottom: 16
  657. },
  658. listView: {
  659. padding: 8,
  660. borderRadius: 8,
  661. backgroundColor: '#F5F5F5'
  662. },
  663. batteryBorder: {
  664. margin: 30,
  665. padding: 32,
  666. width: circleSize,
  667. height: circleSize,
  668. alignItems: 'center',
  669. justifyContent: 'center'
  670. },
  671. buttonView: {
  672. marginTop: 16,
  673. marginBottom: 32
  674. },
  675. buttonGroup: {
  676. marginTop: 16,
  677. marginBottom: 16,
  678. alignItems: 'center',
  679. flexDirection: 'row'
  680. },
  681. buttonLeft: {
  682. flex: 1,
  683. elevation: 1.5,
  684. },
  685. buttonRight: {
  686. flex: 1,
  687. marginLeft: 16,
  688. elevation: 1.5
  689. },
  690. inUse: {
  691. color: '#fff',
  692. fontSize: 12,
  693. paddingTop: 4,
  694. paddingLeft: 8,
  695. paddingRight: 8,
  696. paddingBottom: 4,
  697. borderRadius: 4,
  698. backgroundColor: '#FF7A00'
  699. },
  700. updateTip: {
  701. color: '#aaa',
  702. fontSize: 10,
  703. textAlign: 'center',
  704. paddingBottom: 16
  705. },
  706. privateView: {
  707. height: $vht(25),
  708. alignItems: 'center',
  709. justifyContent: 'center'
  710. },
  711. privateText: {
  712. color: '#FA5759'
  713. }
  714. })