Home.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. /**
  2. * 首页通用页
  3. * @邠心vbe on 2021/08/13
  4. */
  5. import React, { Component } from 'react';
  6. import { View, StyleSheet, BackHandler, Linking, AppState } from 'react-native';
  7. import app from '../../../app.json'
  8. import { i18nUtil } from '../../i18n';
  9. import apiBase from '../../api/apiBase';
  10. import apiStation from '../../api/apiStation';
  11. import Dialog from '../../components/Dialog';
  12. import utils from '../../utils/utils';
  13. import { SettingUtil } from '../Settings';
  14. import MyStatusBar from '../../components/MyStatusBar';
  15. import LocationPermission from './maps/LocationPermission';
  16. import MapUI from './MapUI';
  17. import MapUILumi from './MapUILumi';
  18. import storage from '../../utils/storage';
  19. const KEY_STORE_LIST = "map_stop_list"
  20. export default class HomePage extends Component {
  21. constructor(props) {
  22. super(props);
  23. this.state = {
  24. region: {
  25. latitude: 1.3532623163977149,
  26. longitude: 103.87092316860532,
  27. latitudeDelta: 0.0922,
  28. longitudeDelta: 0.0421
  29. },
  30. mapReady: false,
  31. showStation: false,
  32. stationId: "",
  33. stationInfo: {},
  34. stopList: [],
  35. hasPermission: isIOS,
  36. permissionDenied: false
  37. };
  38. this.isHide = true;
  39. this.denied = true;
  40. this.backSeconds = 0;
  41. this.refreshTime = 0;
  42. this.settingInfo = {}
  43. this.viewIndex = -1;
  44. this.filter = {
  45. parkingFee: 'ALL',
  46. connectorType: ''
  47. };
  48. this.refresh = false;
  49. this.stateListener;
  50. this.forceUpdateDialog = undefined;
  51. this.locationListener = undefined;
  52. }
  53. componentDidMount() {
  54. const navigation = this.props.navigation;
  55. if (this.locationListener) {
  56. this.locationListener.removeListener();
  57. this.locationListener = undefined;
  58. }
  59. if (!isIOS) {
  60. this.locationListener = new LocationPermission.LocationListener();
  61. if (this.locationListener) {
  62. this.locationListener.addListener();
  63. }
  64. }
  65. navigation.addListener('focus', () => {
  66. //console.log('------Home------', "Focus")
  67. this.onCloseInfo();
  68. SettingUtil.getSettings(set => {
  69. //console.log("获取设置信息", set);
  70. this.settingInfo = set;
  71. this.init();
  72. })
  73. this.isHide = false;
  74. /*if (!app.isWhitelabel) {
  75. MyStatusBar.setStatusBarThemes(MyStatusBar.DARK_STYLE, colorLight);
  76. }*/
  77. MyStatusBar.setTranslucentStatusBar();
  78. });
  79. navigation.addListener('blur', () => {
  80. //toastShort('onStop')
  81. this.isHide = true;
  82. /*if (app.isLumiWhitelabel) {
  83. MyStatusBar.setStatusBarThemes(MyStatusBar.DARK_STYLE, colorLight);
  84. } else {
  85. MyStatusBar.setStatusBarThemes(themeStatusBar, colorPrimaryDark);
  86. }*/
  87. setTimeout(() => {
  88. MyStatusBar.setStatusBarTheme(MyStatusBar.DEFAULT_STYLE);
  89. }, 50);
  90. setTimeout(() => {
  91. navigation.closeDrawer();
  92. }, 500);
  93. });
  94. this.stateListener = AppState.addEventListener("change", state => {
  95. if (state == 'active' && this.forceUpdateDialog) {
  96. this.showUpdateDialog(this.forceUpdateDialog);
  97. }
  98. });
  99. BackHandler.addEventListener('hardwareBackPress', this.toExit)
  100. this.isHide = false;
  101. this.checkUpdateVersion();
  102. }
  103. componentWillUnmount() {
  104. /*console.log("componentWillUnmount")
  105. if (this.unsubscribe) {
  106. this.unsubscribe();
  107. }*/
  108. this.backSeconds = 0;
  109. if (this.stateListener) {
  110. this.stateListener.remove();
  111. }
  112. BackHandler.removeEventListener("hardwareBackPress", this.toExit);
  113. }
  114. init() {
  115. if (this.state.stopList.length == 0 && !this.refresh) {
  116. storage.getStorage(KEY_STORE_LIST).then(data => {
  117. console.log("获取站点缓存", "成功");
  118. if (data) {
  119. const list = JSON.parse(data);
  120. this.setState({
  121. stopList: list
  122. }, () => {
  123. this.checkPermission2Geo(true);
  124. })
  125. } else {
  126. this.checkPermission2Geo(true);
  127. }
  128. }).catch(err => {
  129. console.log("获取站点缓存-err", err);
  130. this.checkPermission2Geo(true);
  131. })
  132. }
  133. }
  134. toExit = () => {
  135. //console.log("beforeRemove", this.isHide);
  136. if (this.state.stationInfo?.id) {
  137. this.setState({
  138. stationInfo: {}
  139. });
  140. return true;
  141. }
  142. if (!this.isHide) {
  143. if (isIOS) {
  144. //e.preventDefault();
  145. } else {
  146. let time = new Date().getTime();
  147. //console.log("beforeRemove2", time, this.backSeconds);
  148. if (time - this.backSeconds < 2000) {
  149. BackHandler.exitApp();
  150. } else {
  151. toastShort($t("home.backAgainTips"));
  152. this.backSeconds = time;
  153. //e.preventDefault();
  154. }
  155. }
  156. return true;
  157. }
  158. }
  159. checkGPS() {
  160. if (this.locationListener) {
  161. this.locationListener.check();
  162. }
  163. }
  164. onMapReady() {
  165. this.setState({
  166. mapReady: true
  167. }, () => {
  168. this.init();
  169. });
  170. }
  171. checkUpdateVersion() {
  172. apiBase.checkUpdate().then(res => {
  173. if (res.data.versionCode > app.versionCode) {
  174. var desc = JSON.parse(res.data?.versionDesc ?? "{}");
  175. if (desc) {
  176. const upLog = i18nUtil.analyzeLocaleData(desc);
  177. if (typeof upLog == "string") {
  178. const prps = {
  179. title: $t("home.versionUpdate"),
  180. message: $t("home.newVersionName") + res.data.versionName + "\n\n" + upLog,
  181. showCancel: !(res.data.force),
  182. ok: $t("home.updateNow"),
  183. cancel: $t("home.later"),
  184. callback: btn => {
  185. if (btn == Dialog.BUTTON_OK) {
  186. //TODO 跳转到应用商店
  187. const uri = isIOS
  188. ? app.storeUrl.ios
  189. : app.storeUrl.android
  190. Linking.openURL(uri);
  191. }
  192. }
  193. }
  194. if (res.data.force) {
  195. prps.onBackPress = () => {
  196. }
  197. this.forceUpdateDialog = prps;
  198. }
  199. this.showUpdateDialog(prps);
  200. }
  201. }
  202. }
  203. }).catch(err => {
  204. })
  205. }
  206. showUpdateDialog(options) {
  207. if (Dialog.isShowing()) {
  208. setTimeout(() => {
  209. this.showUpdateDialog(options)
  210. }, 500);
  211. return;
  212. }
  213. Dialog.showDialog(options)
  214. }
  215. getPermission() {
  216. LocationPermission.requestPermission(hasPermission => {
  217. if (hasPermission) {
  218. this.setState({
  219. hasPermission: true
  220. });
  221. this.checkPermission2Geo();
  222. } else {
  223. this.noPermissionSite();
  224. }
  225. })
  226. }
  227. checkPermission2Geo(refresh) {
  228. if (this.refresh == refresh) {
  229. return;
  230. }
  231. if (refresh) {
  232. //避免关闭自动移动地图后无法点击按钮移动地图
  233. this.refresh = true
  234. }
  235. console.log("checkPermission2Geo", refresh);
  236. this.checkGPS();
  237. if (this.state.hasPermission) {
  238. this.infoGeoLocation();
  239. } else {
  240. LocationPermission.checkPermission((hasPermission, canRequestPermission) => {
  241. if (hasPermission) {
  242. this.setState({
  243. hasPermission: true
  244. });
  245. this.infoGeoLocation();
  246. } else {
  247. if (canRequestPermission) {
  248. if (this.denied) {
  249. this.denied = false;
  250. this.getPermission();
  251. } else {
  252. //避免多次请求
  253. this.denied = true;
  254. this.noPermissionSite();
  255. }
  256. } else {
  257. this.noPermissionSite();
  258. }
  259. }
  260. })
  261. }
  262. }
  263. noPermissionSite() {
  264. console.log("未获取权限也获取站点列表");
  265. this.setState({
  266. hasPermission: false,
  267. permissionDenied: true
  268. });
  269. let first = this.state.stopList.length == 0;//是否第一次加载
  270. this.getStationList(this.state.region, first);
  271. }
  272. /**
  273. * 获取定位数据
  274. * @param {*} again
  275. */
  276. infoGeoLocation(again) {
  277. if (this.state.mapReady) {
  278. navigator.geolocation.getCurrentPosition(location => {
  279. let region = {
  280. latitude: location.coords.latitude,
  281. longitude: location.coords.longitude,
  282. latitudeDelta: 0.0922,
  283. longitudeDelta: 0.0421
  284. }
  285. //console.log("getGeoLocation", region);
  286. //if (this.state.stopList.length == 0) { //只加载一次
  287. let time = new Date().getTime();
  288. let interval = this.settingInfo.refreshInterval * 1000;//重复加载时间
  289. let first = this.state.stopList.length == 0;//是否第一次加载
  290. if (first || this.refresh || time - this.refreshTime > interval) { //一分钟(10秒)加载一次
  291. this.getStationList(region, first || this.refresh);
  292. this.refreshTime = time;
  293. } else if (this.settingInfo.moveMyLocation) {
  294. this.setState({
  295. region: region
  296. });
  297. }
  298. }, error => {
  299. console.info("getGeoLocation", error);
  300. if (!again) {
  301. setTimeout(() => {
  302. this.infoGeoLocation(true);
  303. }, 2000);
  304. }
  305. });
  306. }
  307. }
  308. findFilter(data) {
  309. this.filter = data;
  310. console.log("筛选站点", data);
  311. this.getStationList();
  312. }
  313. /**
  314. * 获取所有充电桩
  315. * @param {Location} region 当前位置
  316. * @param {boolean} first 是否初始化
  317. */
  318. getStationList(region, first) {
  319. //Dialog.showProgressDialog();
  320. if (getUserId()) {
  321. this.filter.operaUserId = getUserId()
  322. }
  323. if (region && (this.settingInfo.moveMyLocation || first)) {
  324. this.setState({
  325. region: region
  326. });
  327. }
  328. apiStation.getAllStation(this.filter).then(res => {
  329. Dialog.dismissLoading();
  330. if (res.data.sites) {
  331. const list = [];
  332. res.data.sites.forEach(item => {
  333. let available = false
  334. if (item.allConnector && item.allConnector.available) {
  335. available = true
  336. }
  337. list.push({
  338. id: item.sitePk,
  339. name: item.siteName,
  340. //address: item.siteAddress,
  341. available: available,
  342. siteType: item.siteType,
  343. latitude: item.locationLatitude,
  344. longitude: item.locationLongitude,
  345. favorite: item?.favorite ? true : false,
  346. hasLabel: item?.hasLabel,
  347. upcoming: item?.upcoming
  348. /*acConnector: item.acConnector,
  349. allConnector: item.allConnector,
  350. dcConnector: item.dcConnector,
  351. distance: utils.getDistance(item.distance)*/
  352. });
  353. });
  354. this.setState({
  355. stopList: list
  356. });
  357. if (this.filter.connectorType == "" && this.filter.parkingFee == "ALL") {
  358. storage.setStorageJson(KEY_STORE_LIST, list);
  359. }
  360. }
  361. this.refresh = false;
  362. }).catch(err => {
  363. Dialog.dismissLoading();
  364. toastShort(err);
  365. /*this.setState({
  366. stopList: []
  367. });*/
  368. this.refresh = false;
  369. })
  370. }
  371. //点击Marker获取StaionInfo
  372. viewChargeStation(id) {
  373. //console.log('info', this.state.stopList[index]);
  374. //const stationInfo = this.state.stopList[index];
  375. if (this.state.stationId == id) {
  376. return;
  377. }
  378. this.setState({
  379. stationId: id,
  380. stationInfo: {},
  381. showStation: true
  382. });
  383. if (app.modules.bookmarks) {
  384. for (let i = 0; i < this.state.stopList.length; i++) {
  385. let info = this.state.stopList[i];
  386. if (info.id == id) {
  387. this.viewIndex = i;
  388. break;
  389. }
  390. }
  391. }
  392. if (this.state.hasPermission) {
  393. navigator.geolocation.getCurrentPosition(location => {
  394. let region = {
  395. latitude: location.coords.latitude,
  396. longitude: location.coords.longitude,
  397. latitudeDelta: 0.0922,
  398. longitudeDelta: 0.0421
  399. }
  400. setTimeout(() => {
  401. this.getStationInfo(id, region);
  402. }, 500);
  403. /*if (this.settingInfo.alwaysLocation) {
  404. this.setState({
  405. region: region
  406. });
  407. }*/
  408. });
  409. } else {
  410. //无定位权限仍然显示
  411. setTimeout(() => {
  412. this.getStationInfo(id, this.state.region);
  413. }, 500);
  414. }
  415. //startPage(PageList.chargeDetail, {...this.state.stopList[index]});
  416. }
  417. getStationInfo(id, location) {
  418. apiStation.getStationRate({
  419. sitePk: id,
  420. lat: location?.latitude,
  421. lng: location?.longitude
  422. }).then(res => {
  423. if (res.data.sitePk) {
  424. var info = utils.getSiteInfo(res.data);
  425. this.setState({
  426. stationInfo: info
  427. });
  428. } else {
  429. this.setState({
  430. stationInfo: {}
  431. });
  432. }
  433. }).catch(err => {
  434. this.setState({
  435. stationInfo: {}
  436. });
  437. toastShort(err);
  438. });
  439. }
  440. onCloseInfo() {
  441. this.viewIndex = -1;
  442. this.setState({
  443. stationId: "",
  444. stationInfo: {},
  445. showStation: false
  446. });
  447. }
  448. favoriteSite() {
  449. if (this.state.stationInfo?.id) {
  450. Dialog.showProgressDialog();
  451. apiStation.bookmarkSite(this.state.stationInfo.id).then(res => {
  452. const info = {...this.state.stationInfo, favorite: !this.state.stationInfo.favorite}
  453. if (this.viewIndex >= 0) {
  454. const list = [...this.state.stopList]
  455. const inf = {...list[this.viewIndex], favorite: info.favorite};
  456. list[this.viewIndex] = inf;
  457. this.setState({
  458. stopList: list,
  459. stationInfo: info
  460. });
  461. } else {
  462. this.setState({
  463. stationInfo: info
  464. });
  465. }
  466. }).catch(err => {
  467. toastShort(err);
  468. console.log(err)
  469. }).finally(() => {
  470. Dialog.dismissLoading();
  471. })
  472. }
  473. }
  474. hidePermissionPanel() {
  475. this.setState({
  476. permissionDenied: false
  477. })
  478. }
  479. render() {
  480. return (
  481. <View style={ui.flex1}>
  482. { app.isLumiWhitelabel
  483. ? <MapUILumi
  484. state={this.state}
  485. navigation={this.props.navigation}
  486. onFilter={data => this.findFilter(data)}
  487. onMapReady={() => this.onMapReady()}
  488. onFavorite={() => this.favoriteSite()}
  489. onCloseInfo={() => this.onCloseInfo()}
  490. onLocation={() => this.checkPermission2Geo(true)}
  491. useApplesMap={this.settingInfo.useApplesMap}
  492. showUserLocation={this.state.hasPermission && this.settingInfo.alwaysLocation}
  493. viewChargeStation={id => this.viewChargeStation(id)}/>
  494. : <MapUI
  495. state={this.state}
  496. navigation={this.props.navigation}
  497. onFilter={data => this.findFilter(data)}
  498. onMapReady={() => this.onMapReady()}
  499. onFavorite={() => this.favoriteSite()}
  500. onCloseInfo={() => this.onCloseInfo()}
  501. onLocation={() => this.checkPermission2Geo(true)}
  502. useApplesMap={this.settingInfo.useApplesMap}
  503. showUserLocation={this.state.hasPermission && this.settingInfo.alwaysLocation}
  504. viewChargeStation={id => this.viewChargeStation(id)}
  505. />
  506. }
  507. <LocationPermission.VIEW
  508. visible={this.state.permissionDenied}
  509. onView={() => this.hidePermissionPanel()}/>
  510. <View style={styles.drawerLeftTouchView}></View>
  511. </View>
  512. );
  513. }
  514. }
  515. const styles = StyleSheet.create({
  516. drawerLeftTouchView: {
  517. top: 0,
  518. left: 0,
  519. bottom: 0,
  520. width: 4,
  521. zIndex: 5,
  522. position: 'absolute',
  523. backgroundColor: 'rgba(0,0,0,0)'
  524. }
  525. })