Charge.js 22 KB

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