SearchV2.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /**
  2. * 新版搜索页
  3. * @邠心vbe on 2023/02/03
  4. */
  5. import React, { Component } from 'react';
  6. import { View, Text, StyleSheet, TextInput, FlatList, Image } from 'react-native';
  7. import apiStation from '../../api/apiStation';
  8. import Dialog from '../../components/Dialog';
  9. import utils from '../../utils/utils';
  10. import { PageList } from '../Router';
  11. import ListViewV2 from './ListViewV2';
  12. export default class SearchV2 extends Component {
  13. constructor(props) {
  14. super(props);
  15. this.state = {
  16. isSearch: false,
  17. searchResult: [{id:0}],
  18. latlng: {
  19. lat: 0.00001,
  20. lng: 0.00001
  21. }
  22. };
  23. }
  24. componentDidMount() {
  25. this.getGeoLocation();
  26. }
  27. getGeoLocation() {
  28. navigator.geolocation.getCurrentPosition(location => {
  29. let latlng = {
  30. lat: location.coords.latitude,
  31. lng: location.coords.longitude
  32. }
  33. this.setState({
  34. latlng: latlng
  35. })
  36. this.searchStation(latlng);
  37. }, error => {
  38. console.info("[Search] getGeoLocation", error);
  39. this.searchStation(this.state.latlng);
  40. });
  41. }
  42. searchStation(latlng, time=1000) {
  43. this.setState({
  44. isSearch: true
  45. });
  46. latlng.siteName = this.searchWorld
  47. apiStation.searchStation(latlng).then(res => {
  48. if (res.data.sites) {
  49. const list = [];
  50. res.data.sites.forEach(item => {
  51. list.push({
  52. id: item.sitePk,
  53. name: item.siteName,
  54. address: item.siteAddress,
  55. latitude: item.locationLatitude,
  56. longitude: item.locationLongitude,
  57. acConnector: item.acConnector,
  58. allConnector: item.allConnector,
  59. dcConnector: item.dcConnector,
  60. siteType: item.siteType,
  61. favorite: item.favorite,
  62. upcoming: item.upcoming,
  63. labels: item.siteLabels,
  64. distance: utils.getDistance(item.distance),
  65. serviceProvider: item.serviceProvider
  66. });
  67. });
  68. setTimeout(() => {
  69. this.setState({
  70. isSearch: false,
  71. searchResult: list
  72. });
  73. }, time);
  74. }
  75. }).catch(err => {
  76. console.log('searchStation-err', err);
  77. this.setState({
  78. isSearch: false,
  79. searchResult: []
  80. });
  81. });
  82. }
  83. favoriteSite(index, info) {
  84. if (info?.id) {
  85. Dialog.showProgressDialog();
  86. apiStation.bookmarkSite(info.id).then(res => {
  87. if (index >= 0) {
  88. const list = [...this.state.searchResult];
  89. list[index].favorite = !info.favorite;
  90. this.setState({
  91. searchResult: list
  92. });
  93. }
  94. }).catch(err => {
  95. toastShort(err);
  96. }).finally(() => {
  97. Dialog.dismissLoading();
  98. })
  99. }
  100. }
  101. intoStation(info) {
  102. if (info.upcoming) {
  103. toastShort($t("home.upcoming"))
  104. } else {
  105. utils.toChargeDetailPage(info.id, 'search', PageList.search);
  106. //startPage(PageList.chargeDetailPage, {stationInfo: info, action: 'search', from: PageList.search});
  107. }
  108. }
  109. listItem = (props) => {
  110. return (
  111. <ListViewV2
  112. {...props}
  113. onPress={() => this.intoStation(props.item)}
  114. onFavorite={() => this.favoriteSite(props.index, props.item)}/>
  115. )
  116. }
  117. render() {
  118. return (
  119. <View style={styles.container}>
  120. <View style={styles.searchView}>
  121. <Feather
  122. name={'search'}
  123. size={20}
  124. color={'#999'}/>
  125. <TextInput
  126. style={styles.searchInput}
  127. autoFocus={true}
  128. maxLength={50}
  129. numberOfLines={1}
  130. returnKeyType={'search'}
  131. clearButtonMode={'while-editing'}
  132. placeholder={$t('home.searchHint')}
  133. placeholderTextColor={textPlacehoder}
  134. onChangeText={text => {
  135. this.searchWorld = text;
  136. }}
  137. onSubmitEditing={() => {
  138. //this.getGeoLocation();
  139. this.searchStation(this.state.latlng, 500);
  140. }}/>
  141. </View>
  142. { this.state.isSearch
  143. ? <View style={styles.searchingView}>
  144. <Image
  145. style={styles.seachingIcon}
  146. source={require('../../images/icon/search-loading.gif')}/>
  147. </View>
  148. : <FlatList
  149. style={styles.listView}
  150. data={this.state.searchResult}
  151. renderItem={this.listItem}
  152. keyExtractor={item => item.id}
  153. keyboardShouldPersistTaps="always"
  154. ListEmptyComponent={<Text style={styles.noResult}>{$t('home.noSearch')}</Text>}
  155. />
  156. }
  157. </View>
  158. );
  159. }
  160. }
  161. const styles = StyleSheet.create({
  162. container: {
  163. flex: 1,
  164. backgroundColor: pageBackground
  165. },
  166. searchView: {
  167. marginTop: 16,
  168. marginLeft: 16,
  169. marginRight: 16,
  170. marginBottom: 8,
  171. paddingLeft: 16,
  172. paddingRight: 16,
  173. borderRadius: 60,
  174. borderWidth: 1,
  175. borderColor: '#E5E5E5',
  176. alignItems: 'center',
  177. flexDirection: 'row',
  178. backgroundColor: '#F5F5F5'
  179. },
  180. searchInput: {
  181. flex: 1,
  182. color: textPrimary,
  183. ...$padding(6, 8),
  184. fontSize: 15,
  185. marginLeft: 4,
  186. lineHeight: 20
  187. },
  188. searchingView: {
  189. padding: 16,
  190. alignItems: 'center'
  191. },
  192. seachingIcon: {
  193. width: 60,
  194. height: 60
  195. },
  196. noResult: {
  197. color: '#999',
  198. fontSize: 14,
  199. padding: 20,
  200. textAlign: 'center',
  201. },
  202. listView: {
  203. flex: 1
  204. },
  205. itemView: {
  206. alignItems: 'center',
  207. flexDirection: 'row',
  208. borderBottomWidth: 1,
  209. borderBottomColor: '#eee'
  210. },
  211. stationInfo: {
  212. flex: 1,
  213. padding: 16
  214. },
  215. nameView: {
  216. paddingTop: 3,
  217. alignItems: 'center',
  218. flexDirection: 'row'
  219. },
  220. stationName: {
  221. color: textPrimary,
  222. fontSize: 18,
  223. fontWeight: 'bold'
  224. },
  225. stationAddress: {
  226. color: '#666',
  227. fontSize: 14,
  228. paddingBottom: 8
  229. },
  230. infoStatus: {
  231. fontSize: 10,
  232. paddingTop: 3,
  233. paddingLeft: 8,
  234. paddingRight: 8,
  235. paddingBottom: 3,
  236. borderRadius: 5,
  237. marginLeft: 12,
  238. },
  239. selected: {
  240. color: textPrimary,
  241. backgroundColor: colorAccent
  242. },
  243. available: {
  244. color: textLight,
  245. backgroundColor: '#90DB0A'
  246. },
  247. unavailable: {
  248. color: '#999',
  249. fontSize: 10.5,
  250. paddingTop: 7,
  251. paddingLeft: 9,
  252. paddingRight: 9,
  253. paddingBottom: 7,
  254. backgroundColor: '#CCC'
  255. },
  256. connectView: {
  257. paddingTop: 4,
  258. paddingBottom: 4,
  259. alignItems: 'center',
  260. flexDirection: 'row'
  261. },
  262. directView: {
  263. zIndex: 1,
  264. paddingRight: 16,
  265. alignItems: 'center'
  266. },
  267. distanceText: {
  268. color: textPrimary,
  269. fontSize: 12,
  270. paddingTop: 2
  271. }
  272. });