Browse Source

添加日志上报

lex 10 months ago
parent
commit
5bb262f08c

+ 1 - 1
index.html

@@ -68,4 +68,4 @@
   <script type="module" src="/src/student/main.ts"></script>
 </body>
 
-</html>
+</html>

+ 205 - 0
src/hooks/useErrorLog/index.ts

@@ -0,0 +1,205 @@
+import { state } from '@/state';
+import dayjs from 'dayjs';
+import request from '@/helpers/request';
+import { router as routeCommon } from '../../router/routes-common'
+import schoolRouter from '../../router/routes-school'
+import teacherRouter from '../../router/routes-teacher'
+import studentRouter from '../../router/routes-student'
+
+/** 错误信息列表 */
+export const api_sysExceptionLogSave = (params: any): Promise<any> => {
+  return request.post(state.platformApi + '/sysExceptionLog/save', {
+    data: params,
+    hideLoading: true
+  });
+};
+
+type uploadType = {
+  clientType?: string;
+  phone?: string | undefined | null;
+  userAgent?: string;
+  appType?: string;
+  content?: string;
+  exceptionType?: string;
+  exceptionTime?: string;
+  deviceType?: string | null;
+  deviceVersion?: string | null
+}
+
+/**
+ * 页面有报错时上传错误日志
+ * @params
+ */
+export default function useErrorLog() {
+  let _whiteBlanks: string[] = [];
+
+  let _defaultParams = {
+    clientType: state.platformType,
+    phone: '',
+    userAgent: '',
+    appType: 'WEB',
+    content: '',
+    exceptionType: 'ERROR',
+    exceptionTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
+    deviceType: null,
+    deviceVersion: null
+  }
+
+  /** 操作记录的缓存 */
+  const operationErrorLog = (type: 'set' | 'get' | 'remove', params?: any) => {
+    if (type === "set") {
+      const tempList = operationErrorLog('get') || []
+      tempList.push(params)
+    } else if (type === 'get') {
+      const tempList = localStorage.getItem('orchestra-error-log')
+      return tempList ? JSON.parse(tempList) : []
+    } else if (type === "remove") {
+      localStorage.removeItem('orchestra-error-log')
+    }
+  }
+
+  const _uploadErrorLog = async (event: any) => {
+    try {
+      /*
+        日志上报:1.手机号、应用端 iOS|安卓 App类型(老师端|学生端|web)、App版本、系统信息(系统版本|web userAgent)、错误信息(什么位置出现,错误内容) 错误时间 上报类型(错误、埋点)
+        Phone、 type 、content
+        手机号|上报类型 (error、record)|content 内容jsonString (应用端 iOS|安卓 App类型(老师端|学生端|web)、App版本、系统信息(系统版本|web userAgent)、错误信息(什么位置出现,错误内容) 错误时间)
+        手机号 |上报类型 |业务平台|应用端(iOS|安卓)|
+     */
+      const href = window.location.href;
+      const index = _whiteBlanks.findIndex(
+        (item: string) => href.indexOf(item) !== -1
+      );
+
+      const whiteIp = ['online.lexiaoya.cn', 'test.lexiaoya.cn', 'dev.lexiaoya.cn']
+      console.log(window.location.hash, index, 'errorLog')
+      if (!whiteIp.includes(window.location.host)) {
+        return
+      }
+      if (!(window.location.hash === '#/' || index !== -1)) {
+        return
+      }
+      // 错误信息
+      // 资源加载失败,可以在这里处理错误
+      const contentError = `Error message: ${event.target.tagName || ''};${event.target.src || event.target.href || ''
+        };lineno: ${event.lineno || ''};message: ${event.message || ''
+        };filename: ${event.filename || ''};fileUrl: ${window.location.href
+        }`;
+      // }
+
+      const params = [
+        {
+          ..._defaultParams,
+          phone: state.user.data?.phone,
+          userAgent: window.navigator.userAgent,
+          content: contentError,
+          exceptionTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
+        }
+      ];
+      // console.log(params)
+      // 如果不是登录则存在缓存里面
+      if (state.user.status !== "login") {
+        operationErrorLog('set', params)
+        return
+      }
+      await api_sysExceptionLogSave(params);
+    } catch {
+      //
+    }
+  };
+
+
+  /** 初始化在缓存里面的数据 */
+  const _initUpdaloadErrorLog = async () => {
+    if (state.user.status !== 'login') return
+    try {
+      const tempList = operationErrorLog('get') || []
+      if (tempList.length > 0) {
+        await api_sysExceptionLogSave(tempList);
+        operationErrorLog('remove')
+      }
+    } catch {
+      //
+    }
+  }
+
+  /**
+   * 开始监听错误日志并上传
+   */
+  const startListenErrorLog = (params?: uploadType) => {
+    _defaultParams = Object.assign(_defaultParams, params);
+
+    console.log('mount useErrorLog');
+    window.addEventListener('error', _uploadErrorLog);
+
+    setTimeout(() => {
+      _initUpdaloadErrorLog()
+    }, 3000);
+  };
+
+  /**
+   * 停止监听
+   */
+  const stopListenErrorLog = () => {
+    window.removeEventListener('error', _uploadErrorLog);
+  };
+
+  /**
+   * 初始化需要监听的路由
+   */
+  const _listenRouter = () => {
+    _whiteBlanks = []
+
+    // 学校路由
+    const tempRouteSchool: string[] = []
+    if (state.platformType === "SCHOOL") {
+      schoolRouter.forEach((route: any) => {
+        if (route.children && route.children.length > 0) {
+          route.children.forEach(child => {
+            if (child.meta?.errorLog) {
+              tempRouteSchool.push(child.path)
+            }
+          });
+        }
+      })
+    }
+
+    // 老师路由
+    const tempRouteTeacher: string[] = []
+    if (state.platformType === "TEACHER") {
+      teacherRouter.forEach((route: any) => {
+        if (route.children && route.children.length > 0) {
+          route.children.forEach(child => {
+            if (child.meta?.errorLog) {
+              tempRouteSchool.push(child.path)
+            }
+          });
+        }
+      })
+    }
+
+    // 学生路由
+    const tempRouteStudent: string[] = []
+    if (state.platformType === "STUDENT") {
+      studentRouter.forEach((route: any) => {
+        if (route.children && route.children.length > 0) {
+          route.children.forEach(child => {
+            if (child.meta?.errorLog) {
+              tempRouteSchool.push(child.path)
+            }
+          });
+        }
+      })
+    }
+
+
+    _whiteBlanks.push(...tempRouteSchool, ...tempRouteTeacher, ...tempRouteStudent)
+  }
+
+  _listenRouter()
+
+  return {
+    startListenErrorLog,
+    stopListenErrorLog
+  };
+}

+ 12 - 1
src/router/routes-common.ts

@@ -1,5 +1,9 @@
 const paymentType = (window as any).paymentType
 import { RouteRecordRaw } from 'vue-router'
+/***
+ * 默认不记录错误日志
+ * errorLog: true, // 是否报错时记录信息
+ */
 
 // 需要登录的路由
 export const router: RouteRecordRaw[] = [
@@ -16,7 +20,8 @@ export const router: RouteRecordRaw[] = [
     name: 'courseList',
     component: () => import('@/views/courseList/index'),
     meta: {
-      title: '课程列表'
+      errorLog: true, // 是否报错时记录信息
+      title: '课程列表',
     }
   },
   {
@@ -24,6 +29,7 @@ export const router: RouteRecordRaw[] = [
     name: 'coursewarePlay',
     component: () => import('@/views/coursewarePlay'),
     meta: {
+      errorLog: true, // 是否报错时记录信息
       title: '课程播放'
     }
   },
@@ -32,6 +38,7 @@ export const router: RouteRecordRaw[] = [
     name: 'exerciseAfterClass',
     component: () => import('@/views/exercise-after-class/index'),
     meta: {
+      errorLog: true, // 是否报错时记录信息
       title: '观看视频'
     }
   },
@@ -120,6 +127,7 @@ export const router: RouteRecordRaw[] = [
     name: 'test-exercise',
     component: () => import('@/views/unit-test/test-exercise'),
     meta: {
+      errorLog: true, // 是否报错时记录信息
       title: '测试练习'
     }
   },
@@ -128,6 +136,7 @@ export const router: RouteRecordRaw[] = [
     name: 'practice-mode',
     component: () => import('@/views/unit-test/practice-mode'),
     meta: {
+      errorLog: true, // 是否报错时记录信息
       title: '练习模式'
     }
   },
@@ -136,6 +145,7 @@ export const router: RouteRecordRaw[] = [
     name: 'examination-mode',
     component: () => import('@/views/unit-test/examination-mode'),
     meta: {
+      errorLog: true, // 是否报错时记录信息
       title: '测试详情'
     }
   },
@@ -200,6 +210,7 @@ export const router: RouteRecordRaw[] = [
     path: '/creation',
     component: () => import('@/views/creation/index'),
     meta: {
+      errorLog: true, // 是否报错时记录信息
       title: '作品详情'
     }
   },

+ 4 - 0
src/router/routes-school.ts

@@ -235,6 +235,7 @@ export default [
         name: 'ranking-list',
         component: () => import('@/school/ranking-list/index'),
         meta: {
+          errorLog: true, // 是否报错时记录信息
           title: '排行榜'
         }
       },
@@ -291,6 +292,7 @@ export default [
         name: 'course-adjust',
         component: () => import('@/school/approval-manage/course-adjust'),
         meta: {
+          errorLog: true, // 是否报错时记录信息
           title: '课程调整'
         }
       },
@@ -331,6 +333,7 @@ export default [
         name: 'orchestra-story',
         component: () => import('@/school/orchestra-story/index'),
         meta: {
+          errorLog: true, // 是否报错时记录信息
           title: '乐团事迹'
         }
       },
@@ -339,6 +342,7 @@ export default [
         name: 'story-operation',
         component: () => import('@/school/orchestra-story/story-operation/index'),
         meta: {
+          errorLog: true, // 是否报错时记录信息
           title: '添加事迹'
         }
       },

+ 4 - 0
src/router/routes-student.ts

@@ -97,6 +97,7 @@ export default [
         name: 'memberCenter',
         component: () => import('@/student/member-center/index'),
         meta: {
+          errorLog: true, // 是否报错时记录信息
           title: '乐团Ai学练工具'
         }
       },
@@ -145,6 +146,7 @@ export default [
         name: 'ranking-list',
         component: () => import('@/student/ranking-list/index'),
         meta: {
+          errorLog: true, // 是否报错时记录信息
           title: '排行榜'
         }
       },
@@ -192,6 +194,7 @@ export default [
         name: 'preApply',
         component: () => import('@/student/music-group/pre-apply/index'),
         meta: {
+          errorLog: true, // 是否报错时记录信息
           title: '乐团报名'
         }
       },
@@ -200,6 +203,7 @@ export default [
         name: 'preGoodsApply',
         component: () => import('@/student/music-group/pre-goods-apply/index'),
         meta: {
+          errorLog: true, // 是否报错时记录信息
           title: '乐团报名'
         }
       },

+ 5 - 0
src/school/main.ts

@@ -11,6 +11,7 @@ import { state } from '@/state'
 import { browser, setAuth } from '@/helpers/utils'
 import Vue3Lottie from 'vue3-lottie'
 import 'vue3-lottie/dist/style.css'
+import useErrorLog from '../hooks/useErrorLog';
 import ResizeObserver from 'resize-observer-polyfill'
 
 // 增加判断如果不支持当前依赖再设置即可
@@ -76,4 +77,8 @@ if (state.platformType === 'STUDENT') {
 
 app.use(router)
 
+// 监听错误信息
+const errorLog = useErrorLog();
+errorLog.startListenErrorLog();
+
 app.mount('#app')

+ 5 - 0
src/student/main.ts

@@ -11,6 +11,7 @@ import { promisefiyPostMessage, postMessage } from '@/helpers/native-message'
 import { setAuth } from './music-group/layout/utils'
 import { browser } from '@/helpers/utils'
 import { state } from '@/state'
+import useErrorLog from '../hooks/useErrorLog';
 import ResizeObserver from 'resize-observer-polyfill'
 
 // 增加判断如果不支持当前依赖再设置即可
@@ -65,4 +66,8 @@ if (state.platformType === 'TEACHER') {
 const app = createApp(App).use(Vue3Lottie)
 app.use(router)
 
+// 监听错误信息
+const errorLog = useErrorLog();
+errorLog.startListenErrorLog();
+
 app.mount('#app')

+ 5 - 1
src/teacher/main.ts

@@ -9,7 +9,7 @@ import 'vant/lib/index.css'
 import '../styles/index.less'
 import { state } from '@/state'
 import { browser, setAuth } from '@/helpers/utils'
-
+import useErrorLog from '../hooks/useErrorLog';
 import ResizeObserver from 'resize-observer-polyfill'
 
 // 增加判断如果不支持当前依赖再设置即可
@@ -84,4 +84,8 @@ if (state.platformType === 'TEACHER') {
 
 app.use(router)
 
+// 监听错误信息
+const errorLog = useErrorLog();
+errorLog.startListenErrorLog();
+
 app.mount('#app')

+ 1 - 1
vite.config.ts

@@ -16,7 +16,7 @@ const proxyUrl = 'https://dev.lexiaoya.cn/'
 // const proxyUrl = 'http://47.98.131.38:8989/'
 // const proxyUrl = 'http://192.168.3.20:8989/' // 邹旋
 // const proxyUrl = 'http://192.168.3.143:8989/' // 尚科
-// const proxyUrl = 'http://192.168.3.26:8989/' // 刘俊驰
+// const proxyUrl = 'http://192.168.3.26:8989/' / 刘俊驰
 export default defineConfig({
   base: './',
   plugins: [