Prechádzať zdrojové kódy

Merge branch 'iteration-20240511-errorlog' into online

lex 1 rok pred
rodič
commit
1cc3cdc208
4 zmenil súbory, kde vykonal 207 pridanie a 67 odobranie
  1. 14 14
      .editorconfig
  2. 2 1
      public/version.json
  3. 132 0
      src/hooks/useErrorLog/index.ts
  4. 59 52
      src/main.ts

+ 14 - 14
.editorconfig

@@ -1,14 +1,14 @@
-# http://editorconfig.org
-root = true
-
-[*]
-charset = utf-8
-indent_style = space
-indent_size = 2
-end_of_line = CRLF
-insert_final_newline = true
-trim_trailing_whitespace = true
-
-[*.md]
-insert_final_newline = false
-trim_trailing_whitespace = false
+# http://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+end_of_line = crlf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+insert_final_newline = false
+trim_trailing_whitespace = false

+ 2 - 1
public/version.json

@@ -1 +1,2 @@
-{"version":1715840129614}
+{ "version": 1715840129614 }
+

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

@@ -0,0 +1,132 @@
+import { state } from '@/state';
+import dayjs from 'dayjs';
+import request from '/src/utils/request';
+
+/** 错误信息列表 */
+export const api_sysExceptionLogSave = (params: any): Promise<any> => {
+  return request.post('/edu-app/sysExceptionLog/save', {
+    data: params
+  });
+};
+
+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() {
+  const _whiteBlanks = [
+    '/classroom/login',
+    '/classroom/',
+    '/classroom/Home',
+    '/classroom/prepare-lessons',
+    '/classroom/classDetail',
+    '/classroom/classStudentDetail',
+    '/classroom/studentDetail',
+    '/classroom/afterWorkDetail',
+    '/classroom/classStudentRecode',
+    '/classroom/xiaoku-ai',
+    '/classroom/xiaoku-music',
+    '/classroom/natural-resources',
+    '/classroom/notation',
+    '/classroom/content-instruments-detail',
+    '/classroom/content-music-detail',
+    '/classroom/homework-record-detail',
+    '/classroom/attend-class'
+  ];
+
+  let _defaultParams = {
+    clientType: 'TEACHER',
+    phone: '',
+    userAgent: '',
+    appType: 'WEB',
+    content: '',
+    exceptionType: 'ERROR',
+    exceptionTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
+    deviceType: null,
+    deviceVersion: null
+  };
+
+  const _uploadErrorLog = async (event: any) => {
+    try {
+      state.user.data.phone;
+
+      /*
+        日志上报: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 = [
+        'kt.colexiu.com',
+        'test.kt.colexiu.com',
+        'dev.kt.colexiu.com'
+      ];
+      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);
+      await api_sysExceptionLogSave(params);
+    } catch {
+      //
+    }
+  };
+  /**
+   * 开始监听错误日志并上传
+   */
+  const startListenErrorLog = (params?: uploadType) => {
+    _defaultParams = Object.assign(_defaultParams, params);
+    console.log('mount useErrorLog');
+    window.addEventListener('error', _uploadErrorLog);
+  };
+
+  /**
+   * 停止监听
+   */
+  const stopListenErrorLog = () => {
+    window.removeEventListener('error', _uploadErrorLog);
+  };
+
+  return {
+    startListenErrorLog,
+    stopListenErrorLog
+  };
+}

+ 59 - 52
src/main.ts

@@ -1,52 +1,59 @@
-import { createApp } from 'vue';
-import App from './App';
-import router, { parseQuery, setupRouter } from './router/index';
-import dayjs from 'dayjs';
-import { setupNaive } from './plugins';
-import { setupStore } from './store';
-import 'dayjs/locale/zh-cn';
-import './styles/index.less';
-import './utils/rem';
-import { storage } from './utils/storage';
-import { ACCESS_TOKEN_ADMIN } from './store/mutation-types';
-
-async function setupApp() {
-  // 处理token
-  const authLoadNum = sessionStorage.getItem('authLoadNum');
-
-  if (location.search && authLoadNum !== '1') {
-    const parse = location.search.substring(1, location.search.length);
-    const result = parseQuery(parse);
-    if (result.Authorization) {
-      const ex = 7 * 24 * 60 * 60 * 1000;
-      storage.set(ACCESS_TOKEN_ADMIN, result.Authorization, ex);
-      sessionStorage.setItem('authLoadNum', '1');
-      sessionStorage.setItem('authSource', result.source?.toString() || '');
-    }
-    console.log(result, 'result');
-  } else {
-    sessionStorage.removeItem('authLoadNum');
-    storage.remove(ACCESS_TOKEN_ADMIN);
-  }
-  // app loading
-  // const appLoading = createApp(AppLoading);
-  // appLoading.mount('#appLoading');
-  const app = createApp(App);
-
-  setupNaive(app);
-
-  // store plugin: pinia
-  setupStore(app);
-
-  setupRouter(app);
-
-  dayjs.locale('zh-ch');
-
-  // app.use(router);
-  await router.isReady();
-
-  // mount app
-  app.mount('#app');
-}
-
-setupApp();
+import { createApp } from 'vue';
+import App from './App';
+import router, { parseQuery, setupRouter } from './router/index';
+import dayjs from 'dayjs';
+import { setupNaive } from './plugins';
+import { setupStore } from './store';
+import 'dayjs/locale/zh-cn';
+import './styles/index.less';
+import './utils/rem';
+import { storage } from './utils/storage';
+import { ACCESS_TOKEN_ADMIN } from './store/mutation-types';
+import useErrorLog from './hooks/useErrorLog';
+
+async function setupApp() {
+  // 处理token
+  const authLoadNum = sessionStorage.getItem('authLoadNum');
+
+  if (location.search && authLoadNum !== '1') {
+    const parse = location.search.substring(1, location.search.length);
+    const result = parseQuery(parse);
+    if (result.Authorization) {
+      const ex = 7 * 24 * 60 * 60 * 1000;
+      storage.set(ACCESS_TOKEN_ADMIN, result.Authorization, ex);
+      sessionStorage.setItem('authLoadNum', '1');
+      sessionStorage.setItem('authSource', result.source?.toString() || '');
+    }
+    console.log(result, 'result');
+  } else {
+    sessionStorage.removeItem('authLoadNum');
+    storage.remove(ACCESS_TOKEN_ADMIN);
+  }
+  // app loading
+  // const appLoading = createApp(AppLoading);
+  // appLoading.mount('#appLoading');
+  const app = createApp(App);
+
+  setupNaive(app);
+
+  // store plugin: pinia
+  setupStore(app);
+
+  setupRouter(app);
+
+  dayjs.locale('zh-ch');
+
+  // app.use(router);
+  await router.isReady();
+
+  // 监听错误信息
+
+  const errorLog = useErrorLog();
+  errorLog.startListenErrorLog();
+
+  // mount app
+
+  app.mount('#app');
+}
+
+setupApp();