|
|
@@ -0,0 +1,390 @@
|
|
|
+/**
|
|
|
+ * 钱包概述页面优化版
|
|
|
+ * @邠心vbe on 2024/03/27
|
|
|
+ */
|
|
|
+import React, { Component } from 'react';
|
|
|
+import { View, StyleSheet, Text, Pressable } from 'react-native';
|
|
|
+import { ElevationObject } from '../../components/Button';
|
|
|
+import apiWallet from '../../api/apiWallet';
|
|
|
+import utils from '../../utils/utils';
|
|
|
+import TextView from '../../components/TextView';
|
|
|
+import Dialog from '../../components/Dialog';
|
|
|
+
|
|
|
+const chartThemes = "#A6EB7C"; //配置柱状图颜色
|
|
|
+
|
|
|
+export default class OverviewV2 extends Component {
|
|
|
+ constructor(props) {
|
|
|
+ super(props);
|
|
|
+ this.state = {
|
|
|
+ skeleton: true,
|
|
|
+ glanceData: {},
|
|
|
+ monthData: [],
|
|
|
+ weekdayData: [],
|
|
|
+ weekIndex: 0,
|
|
|
+ monthIndex: 0,
|
|
|
+ maxWeek: 0,
|
|
|
+ maxMonth: 0
|
|
|
+ };
|
|
|
+ this.nowDataString = new Date().toDateString()
|
|
|
+ this.refreshing = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ componentDidMount() {
|
|
|
+ console.log("概述", this.props);
|
|
|
+ if (!this.props.skeleton) {
|
|
|
+ this.refreshing = true;
|
|
|
+ //Dialog.showProgressDialog();
|
|
|
+ this.getOverview();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ componentDidUpdate() {
|
|
|
+ if (this.props.shown && !this.props.skeleton) {
|
|
|
+ if (this.props.refresh && !this.refreshing) {
|
|
|
+ this.refreshing = true;
|
|
|
+ this.getOverview();
|
|
|
+ } else if (this.state.skeleton && !this.refreshing) {
|
|
|
+ this.refreshing = true;
|
|
|
+ this.getOverview();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ getOverview() {
|
|
|
+ apiWallet.getOverviewData().then(res => {
|
|
|
+ var glanceData = {}
|
|
|
+ var weekdayData = []
|
|
|
+ var monthData = []
|
|
|
+ var weekIndex = 0
|
|
|
+ var monthIndex = 0
|
|
|
+ let maxWeek = 0;
|
|
|
+ let maxMonth = 0;
|
|
|
+ if (res.data) {
|
|
|
+ if (res.data.atAGlance) {
|
|
|
+ glanceData = res.data.atAGlance
|
|
|
+ }
|
|
|
+ if (res.data.statisticsForThisWeek) {
|
|
|
+ res.data.statisticsForThisWeek.forEach((item, index) => {
|
|
|
+ if (this.nowDataString.indexOf(item.x) >= 0) {
|
|
|
+ weekIndex = index;
|
|
|
+ }
|
|
|
+ if (item.y > maxWeek) {
|
|
|
+ maxWeek = item.y;
|
|
|
+ }
|
|
|
+ //item.y += index + 2;
|
|
|
+ item.label = currency + item.y;
|
|
|
+ item.title = item.dateTimeStr + ' | ' + item.label + ' | ' + item.power + 'kW';
|
|
|
+ weekdayData.push(item);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (res.data.pastSixMonths) {
|
|
|
+ res.data.pastSixMonths.forEach((item, index) => {
|
|
|
+ if (this.nowDataString.indexOf(item.x) >= 0) {
|
|
|
+ monthIndex = index;
|
|
|
+ }
|
|
|
+ //item.y += index + 3;
|
|
|
+ if (item.y > maxMonth) {
|
|
|
+ maxMonth = item.y;
|
|
|
+ }
|
|
|
+ item.label = currency + item.y;
|
|
|
+ item.title = item.x + ' | ' + item.label + ' | ' + item.power + 'kW';
|
|
|
+ monthData.push(item);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.setState({
|
|
|
+ glanceData: glanceData,
|
|
|
+ weekIndex: weekIndex,
|
|
|
+ monthIndex: monthIndex,
|
|
|
+ weekdayData: weekdayData,
|
|
|
+ monthData: monthData,
|
|
|
+ maxWeek: maxWeek,
|
|
|
+ maxMonth: maxMonth
|
|
|
+ }, () => {
|
|
|
+ this.setState({
|
|
|
+ skeleton: false
|
|
|
+ }, () => {
|
|
|
+ this.stopRefresh();
|
|
|
+ })
|
|
|
+ });
|
|
|
+
|
|
|
+ }).catch(err => {
|
|
|
+ toastShort(err);
|
|
|
+ this.stopRefresh();
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ stopRefresh() {
|
|
|
+ if (this.props.refreshed) {
|
|
|
+ this.props.refreshed();
|
|
|
+ }
|
|
|
+ this.refreshing = false;
|
|
|
+ Dialog.dismissLoading();
|
|
|
+ }
|
|
|
+
|
|
|
+ changeWeek(index) {
|
|
|
+ this.setState({
|
|
|
+ weekIndex: index
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ changeMonth(index) {
|
|
|
+ this.setState({
|
|
|
+ monthIndex: index
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ getWeekHeight(y) {
|
|
|
+ if (y) {
|
|
|
+ let r = y / this.state.maxWeek * 100;
|
|
|
+ return Math.ceil(r);
|
|
|
+ } else {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ getMonthHeight(y) {
|
|
|
+ if (y) {
|
|
|
+ let r = y / this.state.maxMonth * 100;
|
|
|
+ return Math.ceil(r);
|
|
|
+ } else {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ render() {
|
|
|
+ return (
|
|
|
+ <View style={this.props.shown ? ui.flex1 : styles.hide}>
|
|
|
+ { this.props.atAglance &&
|
|
|
+ <View style={styles.glanceView}>
|
|
|
+ <TextView style={styles.glanceTitle}>{$t('wallet.atAglance')}</TextView>
|
|
|
+ <View style={styles.overviewRow}>
|
|
|
+ <View style={ui.flex1}>
|
|
|
+ <TextView style={styles.valueText}>{this.state.glanceData.averageCharge ?? 0}</TextView>
|
|
|
+ <TextView style={styles.titleText}>kWh/{$t('wallet.perWeek')}</TextView>
|
|
|
+ <TextView style={styles.subTitleText}>{$t('wallet.averageCharge')}</TextView>
|
|
|
+ </View>
|
|
|
+ <View style={ui.flex1}>
|
|
|
+ <TextView style={styles.valueText}>{this.state.glanceData.averageSpend ?? 0}</TextView>
|
|
|
+ <TextView style={styles.titleText}>{currency}/{$t('wallet.perWeek')}</TextView>
|
|
|
+ <TextView style={styles.subTitleText}>{$t('wallet.averageSpend')}</TextView>
|
|
|
+ </View>
|
|
|
+ <View style={ui.flex1}>
|
|
|
+ <TextView style={styles.valueText}>{utils.hour2HHmm(this.state.glanceData.averageTime)}</TextView>
|
|
|
+ <TextView style={styles.titleText}>{$t('wallet.perHrWeek')}</TextView>
|
|
|
+ <TextView style={styles.subTitleText}>{$t('wallet.averageTime')}</TextView>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ }
|
|
|
+ <View style={styles.statisticView}>
|
|
|
+ <View style={ui.flexcw}>
|
|
|
+ <TextView style={this.props.isTabPage ? styles.sectionTitleV2 : styles.sectionTitle}>{$t('wallet.forWeekOf')}</TextView>
|
|
|
+ {/* <Text style={styles.linkText}>1st Jan to 8th Jan </Text> */}
|
|
|
+ </View>
|
|
|
+ <View style={styles.overviewRow}>
|
|
|
+ <View style={ui.flex1}>
|
|
|
+ {/* <Text style={styles.valueText}>{this.state.glanceData.averageCharge ?? 0}</Text> */}
|
|
|
+ <TextView style={styles.titleText}>{this.state.glanceData.averageCharge ?? 0} kWh{/*$t('wallet.perWeek')*/}</TextView>
|
|
|
+ <TextView style={styles.subTitleText}>{$t('wallet.averageCharge')}</TextView>
|
|
|
+ </View>
|
|
|
+ <View style={styles.overviewDivide}></View>
|
|
|
+ <View style={ui.flex1}>
|
|
|
+ {/* <Text style={styles.valueText}>{this.state.glanceData.averageSpend ?? 0}</Text> */}
|
|
|
+ <TextView style={styles.titleText}>{this.state.glanceData.currencySymbol} {this.state.glanceData.averageSpend ?? 0}{/*$t('wallet.perWeek')*/}</TextView>
|
|
|
+ <TextView style={styles.subTitleText}>{$t('wallet.averageSpend')}</TextView>
|
|
|
+ </View>
|
|
|
+ <View style={styles.overviewDivide}></View>
|
|
|
+ <View style={ui.flex1}>
|
|
|
+ {/* <Text style={styles.valueText}>{utils.hour2HHmm(this.state.glanceData.averageTime)}</Text> */}
|
|
|
+ <TextView style={styles.titleText}>{utils.hour2HHmm(this.state.glanceData.averageTime)}{/*$t('wallet.perWeek')*/}</TextView>
|
|
|
+ <TextView style={styles.subTitleText}>{$t('wallet.averageTime')}</TextView>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ <View style={ui.flex1}>
|
|
|
+ <View style={styles.statisticView}>
|
|
|
+ <TextView style={this.props.isTabPage ? styles.sectionTitleV2 : styles.sectionTitle}>{$t('wallet.statistics4week')}</TextView>
|
|
|
+ <TextView style={styles.statisticTitle}>{this.state.weekdayData[this.state.weekIndex]?.title}</TextView>
|
|
|
+ <View style={styles.barChartView}>
|
|
|
+ { this.state.weekdayData.map((item, index) => (
|
|
|
+ <View
|
|
|
+ style={styles.barChartItem}
|
|
|
+ key={index}>
|
|
|
+ <Text
|
|
|
+ style={styles.barLabelText}
|
|
|
+ onPress={() => this.changeWeek(index)}>
|
|
|
+ {item.label}
|
|
|
+ </Text>
|
|
|
+ <Pressable
|
|
|
+ style={[
|
|
|
+ styles.barChartValue,
|
|
|
+ {
|
|
|
+ height: this.getWeekHeight(item.y),
|
|
|
+ opacity: index == this.state.weekIndex ? 1 : 0.6
|
|
|
+ }
|
|
|
+ ]}
|
|
|
+ onPress={() => this.changeWeek(index)}
|
|
|
+ />
|
|
|
+ <Text style={styles.barLabelText}>{item.x}</Text>
|
|
|
+ </View>
|
|
|
+ ))}
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ <View style={styles.statisticView}>
|
|
|
+ <TextView style={this.props.isTabPage ? styles.sectionTitleV2 : styles.sectionTitle}>{$t('wallet.statistics4HalfYear')}</TextView>
|
|
|
+ <TextView style={styles.statisticTitle}>{this.state.monthData[this.state.monthIndex]?.title}</TextView>
|
|
|
+ <View style={styles.barChartView}>
|
|
|
+ { this.state.monthData.map((item, index) => (
|
|
|
+ <View
|
|
|
+ style={styles.barChartItem}
|
|
|
+ key={index}>
|
|
|
+ <Text
|
|
|
+ style={styles.barLabelText}
|
|
|
+ onPress={() => this.changeMonth(index)}>
|
|
|
+ {item.label}
|
|
|
+ </Text>
|
|
|
+ <Pressable
|
|
|
+ style={[
|
|
|
+ styles.barChartValue,
|
|
|
+ {
|
|
|
+ height: this.getMonthHeight(item.y),
|
|
|
+ opacity: index == this.state.monthIndex ? 1 : 0.6
|
|
|
+ }
|
|
|
+ ]}
|
|
|
+ onPress={() => this.changeMonth(index)}
|
|
|
+ />
|
|
|
+ <Text style={styles.barLabelText}>{item.x}</Text>
|
|
|
+ </View>
|
|
|
+ ))}
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const animate = {
|
|
|
+ duration: 500,
|
|
|
+ onLoad: {
|
|
|
+ duration: 200
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const axisTheme = {
|
|
|
+ axis: {stroke: "#fff"},
|
|
|
+ grid: {strokeWidth: 0},
|
|
|
+ ticks: {size: 0},
|
|
|
+ tickLabels: {color: '#666', fontSize: 12, padding: 8},
|
|
|
+}
|
|
|
+
|
|
|
+const styles = StyleSheet.create({
|
|
|
+ hide: {
|
|
|
+ display: 'none'
|
|
|
+ },
|
|
|
+ glanceView: {
|
|
|
+ marginTop: 16,
|
|
|
+ marginLeft: 16,
|
|
|
+ marginRight: 16,
|
|
|
+ marginBottom: 4,
|
|
|
+ ...ElevationObject(2),
|
|
|
+ overflow: 'hidden',
|
|
|
+ borderTopLeftRadius: 6,
|
|
|
+ borderTopRightRadius: 6,
|
|
|
+ backgroundColor: colorLight
|
|
|
+ },
|
|
|
+ glanceTitle: {
|
|
|
+ color: textPrimary,
|
|
|
+ fontSize: 16,
|
|
|
+ paddingTop: 4,
|
|
|
+ paddingLeft: 16,
|
|
|
+ paddingBottom: 4,
|
|
|
+ backgroundColor: '#C4C8DF'
|
|
|
+ },
|
|
|
+ overviewRow: {
|
|
|
+ paddingTop: 16,
|
|
|
+ paddingBottom: 10,
|
|
|
+ alignItems: 'center',
|
|
|
+ flexDirection: 'row'
|
|
|
+ },
|
|
|
+ overviewDivide: {
|
|
|
+ width: 1,
|
|
|
+ height: 12,
|
|
|
+ backgroundColor: '#D9D9D9'
|
|
|
+ },
|
|
|
+ valueText: {
|
|
|
+ color: '#000',
|
|
|
+ fontSize: 22,
|
|
|
+ paddingBottom: 8,
|
|
|
+ textAlign: 'center'
|
|
|
+ },
|
|
|
+ titleText: {
|
|
|
+ color: textPrimary,
|
|
|
+ fontSize: 14,
|
|
|
+ textAlign: 'center'
|
|
|
+ },
|
|
|
+ subTitleText: {
|
|
|
+ color: textCancel,
|
|
|
+ fontSize: 12,
|
|
|
+ textAlign: 'center'
|
|
|
+ },
|
|
|
+ statisticView: {
|
|
|
+ marginTop: 0,
|
|
|
+ paddingBottom: 16,
|
|
|
+ backgroundColor: colorLight
|
|
|
+ },
|
|
|
+ sectionTitle: {
|
|
|
+ color: textPrimary,
|
|
|
+ fontSize: 14,
|
|
|
+ paddingLeft: 16,
|
|
|
+ fontWeight: 'bold'
|
|
|
+ },
|
|
|
+ sectionTitleV2: {
|
|
|
+ flex: 1,
|
|
|
+ color: textPrimary,
|
|
|
+ fontSize: 14,
|
|
|
+ marginLeft: 16,
|
|
|
+ marginRight: 16,
|
|
|
+ paddingBottom: 4,
|
|
|
+ fontWeight: 'bold',
|
|
|
+ textTransform: 'uppercase',
|
|
|
+ borderBottomWidth: 1,
|
|
|
+ borderBottomColor: colorPrimary
|
|
|
+ },
|
|
|
+ statisticTitle: {
|
|
|
+ color: textPrimary,
|
|
|
+ fontSize: 14,
|
|
|
+ paddingTop: 24,
|
|
|
+ paddingBottom: 8,
|
|
|
+ textAlign: 'center'
|
|
|
+ },
|
|
|
+ statisticChart: {
|
|
|
+ height: 120
|
|
|
+ },
|
|
|
+ linkText: {
|
|
|
+ ...ui.link,
|
|
|
+ fontSize: 14,
|
|
|
+ paddingRight: 16
|
|
|
+ },
|
|
|
+ barChartView: {
|
|
|
+ height: 200,
|
|
|
+ padding: 16,
|
|
|
+ alignItems: 'flex-end',
|
|
|
+ flexDirection: 'row',
|
|
|
+ justifyContent: 'space-between'
|
|
|
+ },
|
|
|
+ barChartItem: {
|
|
|
+ alignItems: 'center'
|
|
|
+ },
|
|
|
+ barLabelText: {
|
|
|
+ padding: 4,
|
|
|
+ fontSize: 12,
|
|
|
+ textAlign: 'center'
|
|
|
+ },
|
|
|
+ barChartValue: {
|
|
|
+ width: 24,
|
|
|
+ minHeight: 1,
|
|
|
+ backgroundColor: colorAccent
|
|
|
+ }
|
|
|
+})
|