Home.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. /**
  2. * 首页地图页
  3. * @邠心vbe on 2021/08/13
  4. */
  5. import React, { Component } from 'react';
  6. import { View, Text, Pressable, Image, StyleSheet, BackHandler } from 'react-native';
  7. import {check, request, openSettings, PERMISSIONS, RESULTS} from 'react-native-permissions';
  8. import apiStation from '../../api/apiStation';
  9. import Dialog from '../../components/Dialog';
  10. import { Styles } from '../../components/Toolbar';
  11. import utils from '../../utils/utils';
  12. import { PageList } from '../Router';
  13. import { SettingUtil } from '../Settings';
  14. import BottomSiteInfo from './maps/BottomSiteInfo';
  15. import Maps from './maps/Maps';
  16. import SearchTool from './maps/SearchTool';
  17. export default class HomePage extends Component {
  18. constructor(props) {
  19. super(props);
  20. this.state = {
  21. region: {
  22. latitude: 1.3532623163977149,
  23. longitude: 103.87092316860532,
  24. latitudeDelta: 0.0922,
  25. longitudeDelta: 0.0421
  26. },
  27. mapReady: false,
  28. stationInfo: {},
  29. stopList: [],
  30. hasPermission: isIOS
  31. };
  32. this.isHide = true;
  33. this.denied = true;
  34. this.backSeconds = 0;
  35. this.refreshTime = 0;
  36. this.settingInfo = {}
  37. //this.unsubscribe = null;
  38. this.filter = {
  39. parkingFee: 'ALL',
  40. connectorType: ''
  41. };
  42. }
  43. componentDidMount() {
  44. console.log("componentDidMount")
  45. const navigation = this.props.navigation;
  46. navigation.addListener('focus', () => {
  47. //toastShort('onResume')
  48. this.setState({
  49. stationInfo: {}
  50. });
  51. SettingUtil.getSettings(set => {
  52. console.log("获取设置信息", set);
  53. this.settingInfo = set;
  54. this.checkPermission2Geo();
  55. })
  56. console.log("focus");
  57. this.isHide = false;
  58. });
  59. navigation.addListener('blur', () => {
  60. //toastShort('onStop')
  61. this.isHide = true;
  62. setTimeout(() => {
  63. navigation.closeDrawer();
  64. }, 200);
  65. });
  66. /*this.unsubscribe = navigation.addListener('beforeRemove', (e) => {
  67. this.toExit(e);
  68. });*/
  69. BackHandler.addEventListener('hardwareBackPress', this.toExit)
  70. this.isHide = false;
  71. }
  72. /*componentDidUpdate() {
  73. console.log("componentDidUpdate", this.unsubscribe);
  74. if (!this.unsubscribe) {
  75. this.unsubscribe = this.props.navigation.addListener('beforeRemove', (e) => {
  76. this.toExit(e);
  77. });
  78. }
  79. }*/
  80. componentWillUnmount() {
  81. /*console.log("componentWillUnmount")
  82. if (this.unsubscribe) {
  83. this.unsubscribe();
  84. }*/
  85. this.backSeconds = 0;
  86. BackHandler.removeEventListener("hardwareBackPress", this.toExit)
  87. }
  88. toExit = () => {
  89. console.log("beforeRemove", this.isHide);
  90. if (!this.isHide) {
  91. if (isIOS) {
  92. //e.preventDefault();
  93. } else {
  94. let time = new Date().getTime();
  95. //console.log("beforeRemove2", time, this.backSeconds);
  96. if (time - this.backSeconds < 2000) {
  97. BackHandler.exitApp();
  98. } else {
  99. toastShort("Press the back button again to exit the program");
  100. this.backSeconds = time;
  101. //e.preventDefault();
  102. }
  103. }
  104. return true;
  105. }
  106. }
  107. getPermission() {
  108. request(
  109. isIOS
  110. ? PERMISSIONS.IOS.LOCATION_WHEN_IN_USE
  111. : PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION)
  112. .then(res => {
  113. console.log('getPermission', res)
  114. this.setState({
  115. hasPermission: true
  116. });
  117. this.checkPermission2Geo();
  118. }).catch(err => {
  119. console.info('getPermission', err)
  120. });
  121. }
  122. checkPermission2Geo(refresh) {
  123. if (this.state.hasPermission) {
  124. if (refresh) {
  125. //避免关闭自动移动地图后无法点击按钮移动地图
  126. this.state.stopList = []
  127. }
  128. this.infoGeoLocation();
  129. return;
  130. }
  131. check(
  132. isIOS
  133. ? PERMISSIONS.IOS.LOCATION_WHEN_IN_USE
  134. : PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION)
  135. .then(res => {
  136. //console.log('checkPermission2Geo', res);
  137. switch (res) {
  138. case RESULTS.UNAVAILABLE:
  139. console.log('此功能不可用(在此设备上/在此上下文中)');
  140. if (isIOS) {
  141. this.setState({
  142. hasPermission: true
  143. });
  144. this.infoGeoLocation();
  145. }
  146. break;
  147. case RESULTS.DENIED:
  148. console.log('权限未被请求/被拒绝,但可以请求');
  149. if (this.denied) {
  150. this.denied = false;
  151. this.getPermission();
  152. } else {
  153. this.denied = true;
  154. }
  155. break;
  156. case RESULTS.LIMITED:
  157. console.log('权限是有限的:有些操作是可能的');
  158. this.setState({
  159. hasPermission: true
  160. });
  161. this.infoGeoLocation();
  162. break;
  163. case RESULTS.GRANTED:
  164. console.log('许可被授予');
  165. this.setState({
  166. hasPermission: true
  167. });
  168. this.infoGeoLocation();
  169. break;
  170. case RESULTS.BLOCKED:
  171. console.log('权限被拒绝,不再可请求');
  172. Dialog.showDialog({
  173. title: 'Error',
  174. message: 'Can not get charge station, Please grant location permissions.',
  175. ok: 'SETTING',
  176. callback: btn => {
  177. if (btn == Dialog.BUTTON_OK) {
  178. console.log('ok');
  179. openSettings().catch(() => console.warn('cannot open settings'));
  180. }
  181. }
  182. });
  183. //toastShort('Save to gallery failed');
  184. break;
  185. }
  186. }).catch(err => {
  187. console.log('checkPermission2Geo-error', err);
  188. });
  189. }
  190. infoGeoLocation(again) {
  191. if (this.state.mapReady) {
  192. navigator.geolocation.getCurrentPosition(location => {
  193. let region = {
  194. latitude: location.coords.latitude,
  195. longitude: location.coords.longitude,
  196. latitudeDelta: 0.0922,
  197. longitudeDelta: 0.0421
  198. }
  199. //console.log("getGeoLocation", region);
  200. //if (this.state.stopList.length == 0) { //只加载一次
  201. let time = new Date().getTime();
  202. let interval = this.settingInfo.refreshInterval * 1000;
  203. let first = this.state.stopList.length == 0;
  204. if (first || time - this.refreshTime > interval) { //一分钟(10秒)加载一次
  205. this.getStationList(region, first);
  206. this.refreshTime = time;
  207. } else if (this.settingInfo.alwaysLocation) {
  208. this.setState({
  209. region: region
  210. });
  211. }
  212. }, error => {
  213. console.info("getGeoLocation", error);
  214. if (!again) {
  215. setTimeout(() => {
  216. this.infoGeoLocation(true);
  217. }, 2000);
  218. }
  219. });
  220. }
  221. }
  222. findFilter(data) {
  223. this.filter = data;
  224. this.getStationList();
  225. }
  226. /**
  227. * 获取所有充电桩
  228. * @param {Location} region 当前位置
  229. * @param {boolean} first 是否初始化
  230. */
  231. getStationList(region, first) {
  232. Dialog.showProgressDialog('Loading...');
  233. apiStation.getAllStation(this.filter).then(res => {
  234. Dialog.dismissLoading();
  235. if (res.data.sites) {
  236. const list = [];
  237. res.data.sites.forEach(item => {
  238. let available = false
  239. if (item.allConnector && item.allConnector.available) {
  240. available = true
  241. }
  242. list.push({
  243. id: item.sitePk,
  244. name: item.siteName,
  245. //address: item.siteAddress,
  246. available: available,
  247. siteType: item.siteType,
  248. latitude: item.locationLatitude,
  249. longitude: item.locationLongitude,
  250. /*acConnector: item.acConnector,
  251. allConnector: item.allConnector,
  252. dcConnector: item.dcConnector,
  253. distance: utils.getDistance(item.distance)*/
  254. });
  255. });
  256. this.setState({
  257. stopList: list
  258. });
  259. if (region && (this.settingInfo.alwaysLocation || first)) {
  260. setTimeout(() => {
  261. this.setState({
  262. region: region
  263. });
  264. }, 500);
  265. }
  266. }
  267. }).catch(err => {
  268. Dialog.dismissLoading();
  269. toastShort(err);
  270. this.setState({
  271. stopList: []
  272. });
  273. })
  274. }
  275. //点击Marker获取StaionInfo
  276. viewChargeStation(id, index) {
  277. //console.log('info', this.state.stopList[index]);
  278. //const stationInfo = this.state.stopList[index];
  279. navigator.geolocation.getCurrentPosition(location => {
  280. let params = {
  281. lat: location.coords.latitude,
  282. lng: location.coords.longitude,
  283. sitePk: id//stationInfo.id
  284. }
  285. apiStation.getStationRate(params).then(res => {
  286. if (res.data.sitePk) {
  287. var info = utils.getSiteInfo(res.data);
  288. this.setState({
  289. stationInfo: info
  290. });
  291. } else {
  292. this.setState({
  293. stationInfo: stationInfo
  294. });
  295. }
  296. }).catch(err => {
  297. this.setState({
  298. stationInfo: stationInfo
  299. });
  300. });
  301. });
  302. //startPage(PageList.chargeDetail, {...this.state.stopList[index]});
  303. }
  304. render() {
  305. return (
  306. <View style={ui.flex1}>
  307. <View style={Styles.toolbar}>
  308. <Pressable
  309. style={Styles.backIcon}
  310. android_ripple = {rippleLess}
  311. onPress={() => {
  312. this.props.navigation.toggleDrawer();
  313. }}>
  314. <EvilIcons name={'navicon'} size={28} color={colorPrimary} />
  315. </Pressable>
  316. <View style={styles.logoView}>
  317. <Image
  318. source={require('../../images/tool-logo.png')}
  319. style={Styles.logo}
  320. />
  321. </View>
  322. {/* <Text style={ui.flex1}></Text> */}
  323. <Pressable
  324. style={Styles.backIcon}
  325. android_ripple = {rippleLess}
  326. onPress={() => startPage(PageList.scanqr, {actionDetail: true})}>
  327. <MaterialCommunityIcons
  328. name='line-scan'
  329. size={20}
  330. color={colorPrimary}
  331. />
  332. </Pressable>
  333. </View>
  334. <SearchTool
  335. count={this.state.stopList.length}
  336. mapReady={this.state.mapReady}
  337. onFilter={data => this.findFilter(data)}
  338. onLocation={() => this.checkPermission2Geo(true)}
  339. />
  340. <View style={styles.mapContent}>
  341. { this.state.hasPermission &&
  342. <Maps.Maps3
  343. region={this.state.region}
  344. stopList={this.state.stopList}
  345. onMapReady={() => {
  346. this.setState({
  347. mapReady: true
  348. }, () => {
  349. this.checkPermission2Geo();
  350. });
  351. }}
  352. onMarkerPress={id => this.viewChargeStation(id)}
  353. />
  354. }
  355. <BottomSiteInfo stationInfo={this.state.stationInfo}/>
  356. </View>
  357. <View style={styles.drawerLeftTouchView}></View>
  358. </View>
  359. );
  360. }
  361. }
  362. const styles = StyleSheet.create({
  363. logoView: {
  364. /*left: 0,
  365. right: 0,
  366. bottom: 0,
  367. zIndex: 1,
  368. alignItems: 'center',
  369. position: 'absolute',*/
  370. flex: 1,
  371. alignItems: 'center',
  372. justifyContent: 'center'
  373. },
  374. searchView: {
  375. ...$padding(8, 16, 16),
  376. backgroundColor: colorThemes
  377. },
  378. searchInput: {
  379. alignItems: 'center',
  380. borderWidth: 1,
  381. borderStyle: 'solid',
  382. borderRadius: 60,
  383. borderColor: colorAccent,
  384. flexDirection: 'row',
  385. paddingLeft: 16,
  386. paddingRight: 16,
  387. backgroundColor: 'rgba(255, 255, 255, 0.5)'
  388. },
  389. searchText: {
  390. flex: 1,
  391. color: '#444',
  392. padding: 8,
  393. fontSize: 15
  394. },
  395. drawerLeftTouchView: {
  396. top: 0,
  397. left: 0,
  398. bottom: 0,
  399. width: 4,
  400. zIndex: 5,
  401. position: 'absolute',
  402. backgroundColor: 'rgba(0,0,0,0)'
  403. },
  404. mapContent: {
  405. flex: 1,
  406. zIndex: 4,
  407. position: 'relative',
  408. }
  409. })