PointsHistory.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /**
  2. * 积分历史列表页面
  3. * @邠心vbe on 2024/05/07
  4. */
  5. import React, { Component } from 'react';
  6. import { View, Text, RefreshControl, FlatList, StyleSheet } from 'react-native';
  7. import { MyRefreshProps } from '../../components/ThemesConfig';
  8. import TextView from '../../components/TextView';
  9. import Dialog from '../../components/Dialog';
  10. import apiVoucher from '../../api/apiVoucher';
  11. import VbeSkeleton from '../../components/VbeSkeleton';
  12. export default class PointsHistory extends Component {
  13. constructor(props) {
  14. super(props);
  15. this.state = {
  16. dataList: [],
  17. hasMore: true,
  18. loading: true,
  19. refreshing: false,
  20. loadingList: ["","","",""]
  21. };
  22. }
  23. componentDidMount() {
  24. this.getHistoryList();
  25. }
  26. onRefresh() {
  27. this.setState({
  28. refreshing: true
  29. })
  30. this.getHistoryList();
  31. }
  32. getNextPage() {
  33. if (this.state.dataList.length > 0 && this.state.hasMore) {
  34. console.log("[Points History]", "getNextPage");
  35. const last = this.state.dataList[this.state.dataList.length-1]
  36. this.getHistoryList(last.pointsHistoryId);
  37. }
  38. }
  39. getHistoryList(lastPk="") {
  40. apiVoucher.getPointsHistory(lastPk).then(res => {
  41. if (res.data) {
  42. if (lastPk) {
  43. if (res.data.length > 0) {
  44. const list = this.state.dataList;
  45. this.setState({
  46. dataList: list.concat(res.data)
  47. });
  48. } else {
  49. this.setState({
  50. hasMore: false
  51. })
  52. }
  53. } else {
  54. this.setState({
  55. dataList: res.data,
  56. hasMore: true
  57. });
  58. }
  59. } else {
  60. this.setState({
  61. dataList: []
  62. });
  63. }
  64. }).catch(err => {
  65. toastShort(err)
  66. }).finally(() => {
  67. this.setState({
  68. loading: false,
  69. refreshing: false
  70. });
  71. });
  72. }
  73. listItem = ({item, index, separators}) => {
  74. return (
  75. <View style={styles.itemView}>
  76. <MaterialCommunityIcons
  77. style={styles.iconType}
  78. name={item.action == "Increase" ? "ev-station" : "ticket-percent-outline"}
  79. size={20}
  80. color={textPrimary}/>
  81. <View style={styles.itemContent}>
  82. <View style={ui.flex1}>
  83. <TextView style={styles.issueName}>{item.remarks}</TextView>
  84. <TextView style={styles.issueDesc}>{(item.siteName ?? item.voucherName) + ", " + (item.chargeBoxId ? item.chargeBoxId + ", " : "") + item.refId}</TextView>
  85. </View>
  86. { item.action == "Increase"
  87. ? <TextView style={styles.amountText}>+ {item.points}</TextView>
  88. : <TextView style={styles.amountDuct}>- {item.points}</TextView>
  89. }
  90. </View>
  91. </View>
  92. )
  93. }
  94. divideView = (props) => {
  95. return (<View style={styles.divide}></View>)
  96. }
  97. bottomView = () => {
  98. if (!this.state.hasMore) {
  99. return (<Text style={styles.noMore}>{$t('wallet.noMore')}</Text>)
  100. } else {
  101. return null
  102. }
  103. }
  104. render() {
  105. if (this.state.loading) {
  106. return (
  107. <View style={styles.listView}>
  108. { this.state.loadingList.map((item, index) =>
  109. <View style={styles.loadingView} key={index}>
  110. <VbeSkeleton
  111. style={styles.iconDefault}
  112. layout={[
  113. {width: 30, height: 30, borderRadius: 30}
  114. ]}
  115. animationDirection={"horizontalRight"}
  116. />
  117. <VbeSkeleton
  118. style={ui.flex1}
  119. layout={[
  120. {width: '60%', height: 18},
  121. {width: '80%', height: 12, marginTop: 8}
  122. ]}
  123. animationDirection={"horizontalRight"}
  124. />
  125. </View>
  126. )}
  127. </View>
  128. )
  129. } else {
  130. return (
  131. <FlatList
  132. style={styles.listView}
  133. data={this.state.dataList}
  134. renderItem={this.listItem}
  135. ItemSeparatorComponent={this.divideView}
  136. ListFooterComponent={this.bottomView}
  137. keyExtractor={item => item.pointsHistoryId}
  138. onEndReached={() => this.getNextPage()}
  139. onEndReachedThreshold={0.3}
  140. refreshControl={
  141. <RefreshControl
  142. {...MyRefreshProps()}
  143. refreshing={this.state.refreshing}
  144. onRefresh={() => this.onRefresh()}
  145. />
  146. }
  147. ListEmptyComponent={<Text style={styles.noData}>{$t('points.noData')}</Text>}
  148. />
  149. );
  150. }
  151. }
  152. }
  153. const styles = StyleSheet.create({
  154. listView: {
  155. flex: 1
  156. },
  157. itemView: {
  158. paddingLeft: 16,
  159. paddingRight: 16,
  160. alignItems: 'center',
  161. flexDirection: 'row'
  162. },
  163. loadingView: {
  164. padding: 16,
  165. alignItems: 'center',
  166. flexDirection: 'row'
  167. },
  168. itemContent: {
  169. flex: 1,
  170. marginLeft: 8,
  171. ...$padding(16, 4),
  172. alignItems: 'center',
  173. flexDirection: 'row'
  174. },
  175. divide: {
  176. marginLeft: 52,
  177. marginRight: 16,
  178. borderTopWidth: 1,
  179. borderTopColor: '#eee',
  180. },
  181. iconType: {
  182. width: 28,
  183. height: 28,
  184. textAlign: 'center',
  185. lineHeight: 27,
  186. borderWidth: 1,
  187. borderRadius: 30,
  188. borderColor: textPrimary
  189. },
  190. iconDefault: {
  191. width: 28,
  192. height: 28,
  193. marginRight: 16
  194. },
  195. issueName: {
  196. color: textPrimary,
  197. fontSize: 12,
  198. paddingBottom: 2
  199. },
  200. issueDesc: {
  201. color: '#999',
  202. fontSize: 8
  203. },
  204. amountDuct: {
  205. color: '#FF2E00',
  206. fontSize: 12,
  207. paddingLeft: 8
  208. },
  209. amountText: {
  210. color: colorAccent,
  211. fontSize: 12,
  212. paddingLeft: 8
  213. },
  214. noData: {
  215. color: textPlacehoder,
  216. fontSize: 8,
  217. padding: 20,
  218. textAlign: 'center'
  219. },
  220. noMore: {
  221. color: textPlacehoder,
  222. fontSize: 10,
  223. padding: 16,
  224. textAlign: 'center'
  225. }
  226. })