Explorar o código

Add analytics

wudebin hai 1 mes
pai
achega
fc4574bfb8

+ 2 - 2
Strides-SPAPP/android/app/version.properties

@@ -1,2 +1,2 @@
-#Fri Apr 10 15:01:26 CST 2026
-VERSION_CODE=870
+#Mon Apr 20 16:07:55 CST 2026
+VERSION_CODE=874

+ 6 - 6
Strides-SPAPP/app/api/http.js

@@ -23,7 +23,7 @@ Axios.interceptors.response.use((response) => {
     console.log('-------', response.status, JSON.stringify(response.data));
   }
   if (response.status != 200) {
-    utils.logEventTracking("api_error: " + response.config.url + ", " + response.status)
+    utils.logEventTracking("api_error", response.config.url + ", " + response.status)
   }
   if (response.data.code == '401' || response.data.code == '402') {
     setAccessToken('');
@@ -37,12 +37,12 @@ Axios.interceptors.response.use((response) => {
   return response.data;
 }, (error) => {
   console.info('-------error', error);
-  utils.logEventTracking("api_failure: " + error)
+  utils.logEventTracking("api_failure", error)
   return Promise.reject(error);
 });
 
 export const get = (path, params) => {
-  utils.logEventTracking("api_get: " + path)
+  utils.logEventTracking("api_get", path)
   return new Promise((resolve, reject) => {
     Axios.get(host + service + path, {
       params: params,
@@ -68,7 +68,7 @@ export const get = (path, params) => {
 }
 
 export const post = (path, params) => {
-  utils.logEventTracking("api_post: " + path)
+  utils.logEventTracking("api_post", path)
   return new Promise((resolve, reject) => {
     Axios.post(host + service + path, params, {
       method: 'POST',
@@ -93,7 +93,7 @@ export const post = (path, params) => {
 }
 
 export const upload = (path, params, header={}) => {
-  utils.logEventTracking("api_upload: " + path)
+  utils.logEventTracking("api_upload", path)
   return new Promise((resolve, reject) => {
     Axios.post(host + service + path, params, {
       method: 'POST',
@@ -120,7 +120,7 @@ export const upload = (path, params, header={}) => {
 }
 
 export const del = (path) => {
-  utils.logEventTracking("api_delete: " + path)
+  utils.logEventTracking("api_delete", path)
   return new Promise((resolve, reject) => {
     Axios.delete(host + service + path, {
       method: 'DELETE',

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

@@ -7,6 +7,7 @@ import { Animated, Easing, Image, StyleSheet, View } from 'react-native'
 import {InitSomething} from '../components/Dialog';
 import MyStatusBar from '../components/MyStatusBar';
 import { PageList } from './Router';
+import analytics from '@react-native-firebase/analytics';
 
 class Launch extends React.Component {
   
@@ -30,6 +31,7 @@ class Launch extends React.Component {
   }
 
   init() {
+    analytics().logAppOpen();
     Animated.timing(this.state.opacity, {
       toValue: 1,
       duration: 1500,

+ 1 - 1
Strides-SPAPP/app/pages/Router.js

@@ -521,7 +521,7 @@ const Router = () => {
     global.startPage = (name, params = {}) => {
       if (utils.isNotEmpty(name)) {
         let _current = navigation.current?.getCurrentRoute()
-        utils.logEventTracking("page_navigation: " + _current.name + " → " + name);
+        utils.logEventTracking("page_navigation", _current.name + " → " + name);
         navigation.current?.navigate(name, params);
       }
     }

+ 22 - 9
Strides-SPAPP/app/pages/charge/QRScan.js

@@ -23,10 +23,16 @@ const QRScanner = ({ onCodeScanned, isActive }) => {
   const [hasPermission, setHasPermission] = useState(false);
   const device = useCameraDevice('back');
   useEffect(() => {
-    (async () => {
-      const status = await Camera.requestCameraPermission();
-      setHasPermission(status == 'granted');
-    })();
+    console.log("相机设备", device);
+    utils.logEventTracking("scan_camera_devices", (utils.isNotEmpty(device) ? "OK" : "NULL"))
+    Camera.requestCameraPermission().then(res => {
+      console.log("相机权限请求", res);
+      utils.logEventTracking("scan_camera_permission", res)
+      setHasPermission(res == 'granted');
+    }).catch(err => {
+      console.warn("相机权限请求错误", err);
+      utils.logEventTracking("scan_camera_permission_error", err)
+    });
   }, []);
   const codeScanner = useCodeScanner({
     codeTypes: ['qr'],
@@ -112,7 +118,7 @@ export default class QRScan extends Component {
       isResult: true
     });
     Vibration.vibrate(100);
-    utils.logEventTracking("scan_qr_result: " + msg)
+    utils.logEventTracking("scan_qr_result", msg)
     if (msg.indexOf('::') > 0) {
       const arr = msg.split('::');
       if (arr.length == 2) {
@@ -141,10 +147,11 @@ export default class QRScan extends Component {
       message: 'It\'s not a legal QR code',
       showCancel: false,
       callback: (e) => {
-      this.setState({
-        isResult: false
-      });
-    }});
+        this.setState({
+          isResult: false
+        });
+      }
+    });
   }
 
   getChargeDetail(qr) {
@@ -175,6 +182,12 @@ export default class QRScan extends Component {
           if (code == 5194 && btn == Dialog.BUTTON_OK && app.vehicle.enable) {
             startPage(app.vehicle.newVersionPage ? PageList.vehiclesListV2 : PageList.myVehicles)
           }
+        },
+        onBackPress: btn => {
+          Dialog.dismissDialog();
+          this.setState({
+            isResult: false
+          });
         }
       });
     })

+ 9 - 1
Strides-SPAPP/app/pages/home/Index.js

@@ -17,6 +17,7 @@ import DrawerView from './Drawer.js';
 import DrawerViewV2 from './DrawerV2.js';
 import DrawerViewV3 from './DrawerV3.js';
 import DrawerViewV4 from './DrawerV4.js';
+import analytics from '@react-native-firebase/analytics';
 import crashlytics from '@react-native-firebase/crashlytics';
 
 const Drawer = createDrawerNavigator();
@@ -44,7 +45,13 @@ export default class Home extends Component {
         this.setState({
           userInfo: info
         });
-        crashlytics().setUserId("" + info.userPk)
+        if (!global.hasAnalytics) {
+          global.hasAnalytics = true;
+          crashlytics().setUserId("" + info.userPk)
+          analytics().logLogin({
+            method: "userId: " + info.userPk
+          })
+        }
       }, true);
       if (app.notifications.enable && this.state.isLogin) {
         this.getNotificationTotal();
@@ -95,6 +102,7 @@ export default class Home extends Component {
       isLogin: false,
       userInfo: {}
     });
+    global.hasAnalytics = false;
     setAccessToken('');
     Dialog.dismissLoading();
   }

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

@@ -114,10 +114,10 @@ const getPermission = (back) => {
     : PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION)
   .then(res => {
     console.log('[LocationPermission] requestPermission', res);
-    utils.logEventTracking("permission_resut: " + res)
+    utils.logEventTracking("permission_resut", res)
     back(res == RESULTS.GRANTED);
   }).catch(erros => {
-    utils.logEventTracking("permission_resut: " + erros)
+    utils.logEventTracking("permission_result_err", erros)
     console.info('[LocationPermission] requestPermission-catch', erros)
     back(false);
   });

+ 1 - 1
Strides-SPAPP/app/pages/member/ApplyMember.js

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

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

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

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

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

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

@@ -42,7 +42,7 @@ export default class ProfileV2 extends Component {
   }
 
   deleteAccount() {
-    utils.logEventTracking("user_action: delete_account")
+    utils.logEventTracking("user_action", "delete_account")
     Dialog.showDialog({
       title: $t('profile.deleteAccount'),
       message: $t('profile.confirmDeleteAccount'),
@@ -91,7 +91,7 @@ export default class ProfileV2 extends Component {
   }
 
   logout() {
-    utils.logEventTracking("user_action: logout")
+    utils.logEventTracking("user_action", "logout")
     Dialog.showDialog({
       title: $t('profile.signOut'),
       message: $t('profile.tipSignOut'),
@@ -113,6 +113,7 @@ export default class ProfileV2 extends Component {
       setStorageJson('loginData', data);
       setStorage('RegisterTokenDate', "");
     }
+    global.hasAnalytics = false;
     global.userInfo = {}
     /*this.setState({
       isLogin: false,

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

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

+ 1 - 1
Strides-SPAPP/app/pages/wallet/Overview.js

@@ -5,7 +5,7 @@
 import React, { Component } from 'react';
 import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
 import { ElevationObject } from '../../components/Button';
-import {VictoryAxis, VictoryBar, VictoryArea, VictoryChart, VictoryTheme, VictoryLabel} from 'victory-native';
+import {VictoryAxis, VictoryBar, VictoryArea, VictoryChart, VictoryTheme, VictoryLabel} from 'react-native';
 import apiWallet from '../../api/apiWallet';
 import Svg, { Defs, LinearGradient, Stop } from 'react-native-svg';
 import utils from '../../utils/utils';

+ 1 - 0
Strides-SPAPP/app/utils/constant.js

@@ -51,6 +51,7 @@ global.accessToken = '';
 global.startPage = {};
 global.storageSite = [];
 global.chargeInfoState = {};
+global.hasAnalytics = false;
 
 global.userInfo = {
   userPk: -1,

+ 13 - 3
Strides-SPAPP/app/utils/utils.js

@@ -6,6 +6,7 @@ import { getStorageSync, setStorage } from "./storage";
 import { PERMISSIONS } from "react-native-permissions";
 import app from '../../app.json';
 import { PageList } from "../pages/Router";
+import analytics from '@react-native-firebase/analytics';
 import crashlytics from '@react-native-firebase/crashlytics';
 
 /**
@@ -345,10 +346,19 @@ export default {
     const pattern = /^[a-zA-Z0-9]+[\S]*@[a-zA-Z0-9_-]+[\.][\Sa-zA-Z]+$/
     return pattern.test(email)
   },
-  logEventTracking(message) {
-    if (app.debug && message) {
+  logEventTracking(event, message="") {
+    if (app.debug && event && message) {
       console.log("已记录事件跟踪", message);
-      crashlytics().log(message);
+      if (!app.product) {
+        analytics().logEvent("event_" + event, {
+          message: message
+        });
+      }
+      if (message) {
+        crashlytics().log(event + ": " + message);
+      } else {
+        crashlytics().log(event);
+      }
     }
   }
 }

+ 1 - 0
Strides-SPAPP/package.json

@@ -27,6 +27,7 @@
     "@react-native-community/datetimepicker": "8.5.1",
     "@react-native-community/geolocation": "3.4.0",
     "@react-native-community/push-notification-ios": "1.11.0",
+    "@react-native-firebase/analytics": "23.8.6",
     "@react-native-firebase/app": "23.8.6",
     "@react-native-firebase/crashlytics": "23.8.6",
     "@react-native-masked-view/masked-view": "0.3.0",