Home.js 10 KB

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