SearchV2.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  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 Search 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. distance: utils.getDistance(item.distance),
  63. serviceProvider: item.serviceProvider
  64. });
  65. });
  66. setTimeout(() => {
  67. this.setState({
  68. isSearch: false,
  69. searchResult: list
  70. });
  71. }, time);
  72. }
  73. }).catch(err => {
  74. console.log('searchStation-err', err);
  75. this.setState({
  76. isSearch: false,
  77. searchResult: []
  78. });
  79. });
  80. }
  81. favoriteSite(index, info) {
  82. if (info?.id) {
  83. Dialog.showProgressDialog();
  84. apiStation.bookmarkSite(info.id).then(res => {
  85. if (index >= 0) {
  86. const list = [...this.state.searchResult];
  87. list[index].favorite = !info.favorite;
  88. this.setState({
  89. searchResult: list
  90. });
  91. }
  92. }).catch(err => {
  93. toastShort(err);
  94. }).finally(() => {
  95. Dialog.dismissLoading();
  96. })
  97. }
  98. }
  99. intoStation(info) {
  100. startPage(PageList.chargeDetailPage, {stationInfo: info, action: 'search', from: PageList.search});
  101. }
  102. listItem = (props) => {
  103. return (
  104. <ListViewV2
  105. {...props}
  106. onPress={() => this.intoStation(props.item)}
  107. onFavorite={() => this.favoriteSite(props.index, props.item)}/>
  108. )
  109. }
  110. render() {
  111. return (
  112. <View style={styles.container}>
  113. <View style={styles.searchView}>
  114. <Feather
  115. name={'search'}
  116. size={20}
  117. color={'#999'}/>
  118. <TextInput
  119. style={styles.searchInput}
  120. autoFocus={true}
  121. maxLength={50}
  122. numberOfLines={1}
  123. returnKeyType={'search'}
  124. clearButtonMode={'while-editing'}
  125. placeholder={$t('home.searchHint')}
  126. placeholderTextColor={textPlacehoder}
  127. onChangeText={text => {
  128. this.searchWorld = text;
  129. }}
  130. onSubmitEditing={() => {
  131. //this.getGeoLocation();
  132. this.searchStation(this.state.latlng, 500);
  133. }}/>
  134. </View>
  135. { this.state.isSearch
  136. ? <View style={styles.searchingView}>
  137. <Image
  138. style={styles.seachingIcon}
  139. source={require('../../images/icon/search-loading.gif')}/>
  140. </View>
  141. : <FlatList
  142. style={styles.listView}
  143. data={this.state.searchResult}
  144. renderItem={this.listItem}
  145. keyExtractor={item => item.id}
  146. keyboardShouldPersistTaps="always"
  147. ListEmptyComponent={<Text style={styles.noResult}>{$t('home.noSearch')}</Text>}
  148. />
  149. }
  150. </View>
  151. );
  152. }
  153. }
  154. const styles = StyleSheet.create({
  155. container: {
  156. flex: 1,
  157. backgroundColor: colorLight //pageBackground
  158. },
  159. searchView: {
  160. marginTop: 16,
  161. marginLeft: 16,
  162. marginRight: 16,
  163. marginBottom: 8,
  164. paddingLeft: 16,
  165. paddingRight: 16,
  166. borderRadius: 60,
  167. borderWidth: 1,
  168. borderColor: '#E5E5E5',
  169. alignItems: 'center',
  170. flexDirection: 'row',
  171. backgroundColor: '#F5F5F5'
  172. },
  173. searchInput: {
  174. flex: 1,
  175. color: textPrimary,
  176. ...$padding(6, 8),
  177. fontSize: 15,
  178. marginLeft: 4,
  179. lineHeight: 20
  180. },
  181. searchingView: {
  182. padding: 0,
  183. alignItems: 'center'
  184. },
  185. seachingIcon: {
  186. width: 120,
  187. height: 120
  188. },
  189. noResult: {
  190. color: '#999',
  191. fontSize: 14,
  192. padding: 20,
  193. textAlign: 'center',
  194. },
  195. listView: {
  196. flex: 1
  197. },
  198. itemView: {
  199. alignItems: 'center',
  200. flexDirection: 'row',
  201. borderBottomWidth: 1,
  202. borderBottomColor: '#eee'
  203. },
  204. stationInfo: {
  205. flex: 1,
  206. padding: 16
  207. },
  208. nameView: {
  209. paddingTop: 3,
  210. alignItems: 'center',
  211. flexDirection: 'row'
  212. },
  213. stationName: {
  214. color: textPrimary,
  215. fontSize: 18,
  216. fontWeight: 'bold'
  217. },
  218. stationAddress: {
  219. color: '#666',
  220. fontSize: 14,
  221. paddingBottom: 8
  222. },
  223. infoStatus: {
  224. fontSize: 10,
  225. paddingTop: 3,
  226. paddingLeft: 8,
  227. paddingRight: 8,
  228. paddingBottom: 3,
  229. borderRadius: 5,
  230. marginLeft: 12,
  231. },
  232. selected: {
  233. color: textPrimary,
  234. backgroundColor: colorAccent
  235. },
  236. available: {
  237. color: textLight,
  238. backgroundColor: '#90DB0A'
  239. },
  240. unavailable: {
  241. color: '#999',
  242. fontSize: 10.5,
  243. paddingTop: 7,
  244. paddingLeft: 9,
  245. paddingRight: 9,
  246. paddingBottom: 7,
  247. backgroundColor: '#CCC'
  248. },
  249. connectView: {
  250. paddingTop: 4,
  251. paddingBottom: 4,
  252. alignItems: 'center',
  253. flexDirection: 'row'
  254. },
  255. directView: {
  256. zIndex: 1,
  257. paddingTop: 4,
  258. paddingRight: 16,
  259. alignItems: 'center'
  260. },
  261. distanceText: {
  262. color: textPrimary,
  263. fontSize: 12,
  264. paddingTop: 2
  265. },
  266. });