wudebin пре 2 месеци
родитељ
комит
9b78910ba2

+ 9 - 0
Strides-SPAPP/app/api/http.js

@@ -1,6 +1,7 @@
 import Axios from 'axios';
 import Axios from 'axios';
 import { PageList } from '../pages/Router';
 import { PageList } from '../pages/Router';
 import app from '../../app.json';
 import app from '../../app.json';
+import utils from '../utils/utils';
 
 
 //config
 //config
 //const hostUrl = 'http://161.117.183.142/';
 //const hostUrl = 'http://161.117.183.142/';
@@ -21,6 +22,9 @@ Axios.interceptors.response.use((response) => {
     console.log('-------', response.config.method, response.config.url);
     console.log('-------', response.config.method, response.config.url);
     console.log('-------', response.status, JSON.stringify(response.data));
     console.log('-------', response.status, JSON.stringify(response.data));
   }
   }
+  if (response.status != 200) {
+    utils.logEventTracking("api_error: " + response.config.url + ", " + response.status)
+  }
   if (response.data.code == '401' || response.data.code == '402') {
   if (response.data.code == '401' || response.data.code == '402') {
     setAccessToken('');
     setAccessToken('');
     startPage(PageList.login, {action: response.data.code});
     startPage(PageList.login, {action: response.data.code});
@@ -33,10 +37,12 @@ Axios.interceptors.response.use((response) => {
   return response.data;
   return response.data;
 }, (error) => {
 }, (error) => {
   console.info('-------error', error);
   console.info('-------error', error);
+  utils.logEventTracking("api_failure: " + error)
   return Promise.reject(error);
   return Promise.reject(error);
 });
 });
 
 
 export const get = (path, params) => {
 export const get = (path, params) => {
+  utils.logEventTracking("api_get: " + path)
   return new Promise((resolve, reject) => {
   return new Promise((resolve, reject) => {
     Axios.get(host + service + path, {
     Axios.get(host + service + path, {
       params: params,
       params: params,
@@ -62,6 +68,7 @@ export const get = (path, params) => {
 }
 }
 
 
 export const post = (path, params) => {
 export const post = (path, params) => {
+  utils.logEventTracking("api_post: " + path)
   return new Promise((resolve, reject) => {
   return new Promise((resolve, reject) => {
     Axios.post(host + service + path, params, {
     Axios.post(host + service + path, params, {
       method: 'POST',
       method: 'POST',
@@ -86,6 +93,7 @@ export const post = (path, params) => {
 }
 }
 
 
 export const upload = (path, params, header={}) => {
 export const upload = (path, params, header={}) => {
+  utils.logEventTracking("api_upload: " + path)
   return new Promise((resolve, reject) => {
   return new Promise((resolve, reject) => {
     Axios.post(host + service + path, params, {
     Axios.post(host + service + path, params, {
       method: 'POST',
       method: 'POST',
@@ -112,6 +120,7 @@ export const upload = (path, params, header={}) => {
 }
 }
 
 
 export const del = (path) => {
 export const del = (path) => {
+  utils.logEventTracking("api_delete: " + path)
   return new Promise((resolve, reject) => {
   return new Promise((resolve, reject) => {
     Axios.delete(host + service + path, {
     Axios.delete(host + service + path, {
       method: 'DELETE',
       method: 'DELETE',

+ 2 - 0
Strides-SPAPP/app/pages/Router.js

@@ -520,6 +520,8 @@ const Router = () => {
     //注入全局方法
     //注入全局方法
     global.startPage = (name, params = {}) => {
     global.startPage = (name, params = {}) => {
       if (utils.isNotEmpty(name)) {
       if (utils.isNotEmpty(name)) {
+        let _current = navigation.current?.getCurrentRoute()
+        utils.logEventTracking("page_navigation: " + _current.name + " → " + name);
         navigation.current?.navigate(name, params);
         navigation.current?.navigate(name, params);
       }
       }
     }
     }

+ 3 - 1
Strides-SPAPP/app/pages/charge/QRScan.js

@@ -15,6 +15,7 @@ import Button from '../../components/Button';
 import TextView from '../../components/TextView';
 import TextView from '../../components/TextView';
 import { EnterStationDialog } from '../chargeV2/Charging';
 import { EnterStationDialog } from '../chargeV2/Charging';
 import QRResult from './QRResult';
 import QRResult from './QRResult';
+import utils from '../../utils/utils';
 
 
 // 函数组件:QR码扫描器
 // 函数组件:QR码扫描器
 const QRScanner = ({ onCodeScanned, isActive }) => {
 const QRScanner = ({ onCodeScanned, isActive }) => {
@@ -103,6 +104,7 @@ export default class QRScan extends Component {
         });
         });
       }
       }
     });
     });
+    utils.logEventTracking("scan_qr_click")
   }
   }
 
 
   scanResult = (msg) => {
   scanResult = (msg) => {
@@ -110,7 +112,7 @@ export default class QRScan extends Component {
       isResult: true
       isResult: true
     });
     });
     Vibration.vibrate(100);
     Vibration.vibrate(100);
-    console.log("result2", msg);
+    utils.logEventTracking("scan_qr_result: " + msg)
     if (msg.indexOf('::') > 0) {
     if (msg.indexOf('::') > 0) {
       const arr = msg.split('::');
       const arr = msg.split('::');
       if (arr.length == 2) {
       if (arr.length == 2) {

+ 27 - 2
Strides-SPAPP/app/pages/chargeV2/SummaryV2.js

@@ -386,7 +386,32 @@ export default class SummaryV2 extends Component {
             </View>
             </View>
           }
           }
           {this.getSectionSkeleton()}
           {this.getSectionSkeleton()}
-          { utils.isNotEmpty(this.state.summaryInfo.idleFee) &&
+          { utils.isNotEmpty(this.state.summaryInfo.idleFeeV2) &&
+            <View style={styles.sections}>
+              <TextView style={styles.formTitle}>{$t('receipt.breakdownIdlesFees')}</TextView>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>Idle Fee Rules:</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.idleFeeV2.idleRule}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>Idle Fee Start Time:</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.idleFeeV2.gracePeriodStartTime}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>Idle Fee Period:</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.idleFeeV2.idlePeriod}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>Idle Fee End Time:</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.idleFeeV2.gracePeriodEndTime}</TextView>
+              </View>
+              <View style={styles.formRow}>
+                <TextView style={styles.label}>{$t('receipt.labelIdleFeeSubtotal3')}</TextView>
+                <TextView style={styles.text}>{this.state.summaryInfo.idleFeeV2.sumFee}</TextView>
+              </View>
+            </View>
+          }
+          {/* utils.isNotEmpty(this.state.summaryInfo.idleFee) &&
             <View style={styles.sections}>
             <View style={styles.sections}>
               <TextView style={styles.formTitle}>{$t('receipt.breakdownIdlesFees')}</TextView>
               <TextView style={styles.formTitle}>{$t('receipt.breakdownIdlesFees')}</TextView>
               <View style={styles.formRow}>
               <View style={styles.formRow}>
@@ -402,7 +427,7 @@ export default class SummaryV2 extends Component {
                 <TextView style={styles.text}>{this.state.summaryInfo.idleFee.subtotal}</TextView>
                 <TextView style={styles.text}>{this.state.summaryInfo.idleFee.subtotal}</TextView>
               </View>
               </View>
             </View>
             </View>
-          }
+          */}
           {this.getSectionSkeleton()}
           {this.getSectionSkeleton()}
           { utils.isNotEmpty(this.state.summaryInfo.reservationFee) &&
           { utils.isNotEmpty(this.state.summaryInfo.reservationFee) &&
             <View style={styles.sections}>
             <View style={styles.sections}>

+ 3 - 0
Strides-SPAPP/app/pages/chargingV2/ChargingPage.js

@@ -283,6 +283,7 @@ export default class ChargingPage extends Component {
   }
   }
 
 
   onStartCharge() {
   onStartCharge() {
+    utils.logEventTracking("charging_start_click")
     if (app.charge.paymentMethod) { //V3版本开始充电
     if (app.charge.paymentMethod) { //V3版本开始充电
       if (utils.isNotEmpty(this.state.stationInfo.payPerUseAmount) && this.state.currentPayment?.code.indexOf(PAYTYPE.PAY_PER_USE_CONTAIN) >= 0) {
       if (utils.isNotEmpty(this.state.stationInfo.payPerUseAmount) && this.state.currentPayment?.code.indexOf(PAYTYPE.PAY_PER_USE_CONTAIN) >= 0) {
         this.setState({
         this.setState({
@@ -399,6 +400,7 @@ export default class ChargingPage extends Component {
         this.setState({
         this.setState({
           currentPerUse: "Pending"
           currentPerUse: "Pending"
         })
         })
+        utils.logEventTracking("payment_initiate", res.data.webPaymentUrl)
         startPage(PageList.paymentWeb, { amount: params.sitePk, url: res.data.webPaymentUrl, type: 'PayPerUse' });
         startPage(PageList.paymentWeb, { amount: params.sitePk, url: res.data.webPaymentUrl, type: 'PayPerUse' });
       } else {
       } else {
         setTimeout(() => {
         setTimeout(() => {
@@ -441,6 +443,7 @@ export default class ChargingPage extends Component {
     this.setState({
     this.setState({
       isStoping: true
       isStoping: true
     })
     })
+    utils.logEventTracking("charging_stop_click")
     //Dialog.showProgressDialog();
     //Dialog.showProgressDialog();
     apiCharge.stopCharge().then(res => {
     apiCharge.stopCharge().then(res => {
       if (res.data.chargingPk) {
       if (res.data.chargingPk) {

+ 5 - 0
Strides-SPAPP/app/pages/home/Home.js

@@ -107,6 +107,11 @@ export default class HomePage extends Component {
       }, 500);
       }, 500);
     });
     });
     this.stateListener = AppState.addEventListener("change", state => {
     this.stateListener = AppState.addEventListener("change", state => {
+      if (state == 'active') {
+        utils.logEventTracking("app_forground")
+      } else {
+        utils.logEventTracking("app_background")
+      }
       if (state == 'active' && this.forceUpdateDialog) {
       if (state == 'active' && this.forceUpdateDialog) {
         this.showUpdateDialog(this.forceUpdateDialog);
         this.showUpdateDialog(this.forceUpdateDialog);
       }
       }

+ 4 - 0
Strides-SPAPP/app/pages/home/maps/LocationPermission.js

@@ -7,6 +7,7 @@ import { StyleSheet, View } from 'react-native';
 import { check, openSettings, PERMISSIONS, request, RESULTS } from 'react-native-permissions';
 import { check, openSettings, PERMISSIONS, request, RESULTS } from 'react-native-permissions';
 import Button from '../../../components/Button';
 import Button from '../../../components/Button';
 import TextView from '../../../components/TextView';
 import TextView from '../../../components/TextView';
+import utils from '../../../utils/utils';
 //import LocationEnabler from 'react-native-location-enabler';
 //import LocationEnabler from 'react-native-location-enabler';
 
 
 //global.hasPermission = false;
 //global.hasPermission = false;
@@ -106,14 +107,17 @@ const checkPermission = (back) => {
  * @param {function} back callback(hasPermission)
  * @param {function} back callback(hasPermission)
  */
  */
 const getPermission = (back) => {
 const getPermission = (back) => {
+  utils.logEventTracking("permission_request: LOCATION")
   request(
   request(
       isIOS 
       isIOS 
     ? PERMISSIONS.IOS.LOCATION_WHEN_IN_USE
     ? PERMISSIONS.IOS.LOCATION_WHEN_IN_USE
     : PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION)
     : PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION)
   .then(res => {
   .then(res => {
     console.log('[LocationPermission] requestPermission', res);
     console.log('[LocationPermission] requestPermission', res);
+    utils.logEventTracking("permission_resut: " + res)
     back(res == RESULTS.GRANTED);
     back(res == RESULTS.GRANTED);
   }).catch(erros => {
   }).catch(erros => {
+    utils.logEventTracking("permission_resut: " + erros)
     console.info('[LocationPermission] requestPermission-catch', erros)
     console.info('[LocationPermission] requestPermission-catch', erros)
     back(false);
     back(false);
   });
   });

+ 2 - 0
Strides-SPAPP/app/pages/member/ApplyMember.js

@@ -14,6 +14,7 @@ import ImagePicker from 'react-native-image-crop-picker';
 import CheckBoxText from '../../components/CheckBoxText';
 import CheckBoxText from '../../components/CheckBoxText';
 import Button from '../../components/Button';
 import Button from '../../components/Button';
 import TextView from '../../components/TextView';
 import TextView from '../../components/TextView';
+import utils from '../../utils/utils';
 
 
 const options = {
 const options = {
   width: 300,
   width: 300,
@@ -93,6 +94,7 @@ export default class ApplyMember extends Component {
       if (image.path) {
       if (image.path) {
         apiUpload.uploadImage(image.path, image.mime, 'MEMBERSHIP').then(res => {
         apiUpload.uploadImage(image.path, image.mime, 'MEMBERSHIP').then(res => {
           if (res.success && res.data.picturePath) {
           if (res.success && res.data.picturePath) {
+            utils.logEventTracking("file_upload: " + res.data.picturePath)
             this.changeForm("cardFront", res.data.picturePath)
             this.changeForm("cardFront", res.data.picturePath)
             toastShort($t('common.uploadSuccess'));
             toastShort($t('common.uploadSuccess'));
           } else {
           } else {

+ 1 - 0
Strides-SPAPP/app/pages/my/EditProfile.js

@@ -224,6 +224,7 @@ export default class EditProfile extends Component {
         /*this.setState({
         /*this.setState({
           userInfo: userInfo
           userInfo: userInfo
         });*/
         });*/
+        utils.logEventTracking("file_upload: " + res.data.picturePath)
         this.updateProfile(this.state.userInfo);
         this.updateProfile(this.state.userInfo);
       } else {
       } else {
         toastShort($t('common.uploadFailed'));
         toastShort($t('common.uploadFailed'));

+ 1 - 0
Strides-SPAPP/app/pages/my/Feedback.js

@@ -155,6 +155,7 @@ export default class Feedback extends React.Component {
             this.setState({
             this.setState({
               imageUrl: imageUrl
               imageUrl: imageUrl
             });
             });
+            utils.logEventTracking("file_upload: " + res.data.picturePath)
             toastShort($t('common.uploadSuccess'));
             toastShort($t('common.uploadSuccess'));
           } else {
           } else {
             toastShort($t('common.uploadFailed'));
             toastShort($t('common.uploadFailed'));

+ 2 - 0
Strides-SPAPP/app/pages/my/ProfileV2.js

@@ -42,6 +42,7 @@ export default class ProfileV2 extends Component {
   }
   }
 
 
   deleteAccount() {
   deleteAccount() {
+    utils.logEventTracking("user_action: delete_account")
     Dialog.showDialog({
     Dialog.showDialog({
       title: $t('profile.deleteAccount'),
       title: $t('profile.deleteAccount'),
       message: $t('profile.confirmDeleteAccount'),
       message: $t('profile.confirmDeleteAccount'),
@@ -90,6 +91,7 @@ export default class ProfileV2 extends Component {
   }
   }
 
 
   logout() {
   logout() {
+    utils.logEventTracking("user_action: logout")
     Dialog.showDialog({
     Dialog.showDialog({
       title: $t('profile.signOut'),
       title: $t('profile.signOut'),
       message: $t('profile.tipSignOut'),
       message: $t('profile.tipSignOut'),

+ 1 - 0
Strides-SPAPP/app/pages/vehicles/VehicleDetail.js

@@ -137,6 +137,7 @@ export default class VehicleDetail extends Component {
         apiUpload.uploadImage(image.path, image.mime, 'PDVL').then(res => {
         apiUpload.uploadImage(image.path, image.mime, 'PDVL').then(res => {
           if (res.success && res.data.picturePath) {
           if (res.success && res.data.picturePath) {
             this.changeForm("vehiclePhoto", res.data.picturePath)
             this.changeForm("vehiclePhoto", res.data.picturePath)
+            utils.logEventTracking("file_upload: " + res.data.picturePath)
             toastShort($t('common.uploadSuccess'));
             toastShort($t('common.uploadSuccess'));
           } else {
           } else {
             toastShort($t('common.uploadFailed'));
             toastShort($t('common.uploadFailed'));

+ 7 - 0
Strides-SPAPP/app/utils/utils.js

@@ -6,6 +6,7 @@ import { getStorageSync, setStorage } from "./storage";
 import { PERMISSIONS } from "react-native-permissions";
 import { PERMISSIONS } from "react-native-permissions";
 import app from '../../app.json';
 import app from '../../app.json';
 import { PageList } from "../pages/Router";
 import { PageList } from "../pages/Router";
+import crashlytics from '@react-native-firebase/crashlytics';
 
 
 /**
 /**
  * 工具集
  * 工具集
@@ -343,5 +344,11 @@ export default {
   isValidEmail(email) {
   isValidEmail(email) {
     const pattern = /^[a-zA-Z0-9]+[\S]*@[a-zA-Z0-9_-]+[\.][\Sa-zA-Z]+$/
     const pattern = /^[a-zA-Z0-9]+[\S]*@[a-zA-Z0-9_-]+[\.][\Sa-zA-Z]+$/
     return pattern.test(email)
     return pattern.test(email)
+  },
+  logEventTracking(message) {
+    if (app.debug && message) {
+      console.log("已记录事件跟踪", message);
+      crashlytics().log(message);
+    }
   }
   }
 }
 }