Browse Source

[Feat 0000] 开发对接用户页面浏览日志功能

houzekong 4 days ago
parent
commit
300fe5c266

+ 10 - 2
src/router/guard/permissionGuard.ts

@@ -277,7 +277,15 @@ export function createPermissionGuard(router: Router) {
     }
   });
 
-  router.afterEach(async (to, from) => {
-    await addBrowseLog(to, from, [...whitePathList, PAGE_NOT_FOUND_ROUTE]);
+  router.afterEach((to, from) => {
+    addBrowseLog(to, from, [...whitePathList, PAGE_NOT_FOUND_ROUTE.path]);
   });
+
+  window.addEventListener(
+    'beforeunload',
+    () => {
+      addBrowseLog(PAGE_NOT_FOUND_ROUTE, router.currentRoute.value, [PAGE_NOT_FOUND_ROUTE.path]);
+    },
+    { once: true }
+  );
 }

+ 61 - 59
src/router/helper/menuHelper.ts

@@ -3,12 +3,11 @@ import type { MenuModule, Menu, AppRouteRecordRaw } from '/@/router/types';
 import { findPath, treeMap } from '/@/utils/helper/treeHelper';
 import { cloneDeep } from 'lodash-es';
 import { isUrl } from '/@/utils/is';
-import { RouteParams } from 'vue-router';
+import { RouteLocationNormalized, RouteParams } from 'vue-router';
 import { toRaw } from 'vue';
 import { defHttp } from '/@/utils/http/axios';
-import { useUserStoreWithOut } from '/@/store/modules/user';
+import { Form } from 'ant-design-vue';
 
-let currentRouter = '';
 export function getAllParentPath<T = Recordable>(treeData: T[], path: string) {
   const menuList = findPath(treeData, (n) => n.path === path) as Menu[];
   return (menuList || []).map((item) => item.path);
@@ -99,62 +98,65 @@ export function configureDynamicParamsMenu(menu: Menu, params: RouteParams) {
   menu.children?.forEach((item) => configureDynamicParamsMenu(item, params));
 }
 
-export async function addBrowseLog(to, from, whitePathList) {
-  const userStore = useUserStoreWithOut();
-  const token = userStore.getToken;
-  if (token) {
-    let currentBrowseId = '';
-    if (to.path !== '/sys/log/addBrowseLog') {
-      const url = '/sys/log/addBrowseLog';
+export async function addBrowseLog(
+  to: AppRouteRecordRaw | RouteLocationNormalized,
+  from: AppRouteRecordRaw | RouteLocationNormalized,
+  ignorePaths: string[]
+): Promise<void> {
+  // 在尝试添加浏览器记录时,应该先发出一个结束上次记录的请求(如有)再发出一个开发此次记录的请求
+  const url = '/sys/log/addBrowseLog';
 
-      // 生成时间戳函数
-      const formatTimestamp = () => {
-        const date = new Date();
-        return [
-          date.getFullYear(),
-          String(date.getMonth() + 1).padStart(2, '0'),
-          String(date.getDate()).padStart(2, '0'),
-          String(date.getHours()).padStart(2, '0'),
-          String(date.getMinutes()).padStart(2, '0'),
-          String(date.getSeconds()).padStart(2, '0'),
-          String(date.getMilliseconds()).padStart(3, '0'),
-        ].join('');
-      };
-      // 2. 记录新页面进入日志
-      currentBrowseId = formatTimestamp();
-      if (!currentRouter && !whitePathList.includes(to.path)) {
-        currentRouter = to.fullPath;
-        try {
-          await defHttp.post({
-            url,
-            params: {
-              browseId: currentBrowseId,
-              isEnd: false,
-              method: to.fullPath,
-            },
-          });
-          console.log('进入页面日志记录成功');
-        } catch (e) {
-          console.error('进入页面日志记录失败:', e);
-        }
-      } else {
-        if (from.fullPath === currentRouter) {
-          try {
-            currentRouter = '';
-            await defHttp.post({
-              url,
-              params: {
-                browseId: currentBrowseId,
-                isEnd: true,
-                method: from.fullPath,
-              },
-            });
-            console.log('进入页面日志记录成功');
-          } catch (e) {
-            console.error('进入页面日志记录失败:', e);
-          }
-        }
-      }
-    }
+  // meta.browseId 是该方法动态添加的内容,可用于判断该路径是否记录
+  if (from.meta.browseId) {
+    await defHttp.post({
+      url,
+      params: {
+        browseId: from.meta.browseId,
+        isEnd: true,
+        method: from.fullPath,
+      },
+    });
   }
+  if (!ignorePaths.includes(to.path)) {
+    const timestamp = Date.now();
+    to.meta.browseId = timestamp;
+    await defHttp.post({
+      url,
+      params: {
+        browseId: timestamp,
+        isEnd: false,
+        method: to.fullPath,
+      },
+    });
+  }
+  // if (to.path !== '/sys/log/addBrowseLog') {
+
+  //   // 2. 记录新页面进入日志
+  //   currentBrowseId = formatTimestamp();
+  //   if (!currentRouter) {
+  //     currentRouter = to.fullPath;
+  //     try {
+  //       console.log('进入页面日志记录成功');
+  //     } catch (e) {
+  //       console.error('进入页面日志记录失败:', e);
+  //     }
+  //   } else {
+  //     if (from.fullPath === currentRouter) {
+  //       try {
+  //         currentRouter = '';
+  //         await defHttp.post({
+  //           url,
+  //           params: {
+  //             browseId: currentBrowseId,
+  //             isEnd: true,
+  //             method: from.fullPath,
+  //           },
+  //         });
+  //         console.log('进入页面日志记录成功');
+  //       } catch (e) {
+  //         console.error('进入页面日志记录失败:', e);
+  //       }
+  //     }
+  //   }
+  // }
 }

+ 52 - 52
src/router/index.ts

@@ -23,59 +23,59 @@ export const router = createRouter({
 
 // TODO 【QQYUN-4517】【表单设计器】记录分享路由守卫测试
 // 存储当前页面的browseId(用于关联离开/进入日志)
-const currentBrowseId = '';
-router.beforeEach(async (to, from, next) => {
-  if (to.path === '/sys/log/addBrowseLog') {
-    // const url = '/sys/log/addBrowseLog';
-    // const currentPath = to.fullPath;
-    // // 生成时间戳函数
-    // const formatTimestamp = () => {
-    //   const date = new Date();
-    //   return [
-    //     date.getFullYear(),
-    //     String(date.getMonth() + 1).padStart(2, '0'),
-    //     String(date.getDate()).padStart(2, '0'),
-    //     String(date.getHours()).padStart(2, '0'),
-    //     String(date.getMinutes()).padStart(2, '0'),
-    //     String(date.getSeconds()).padStart(2, '0'),
-    //     String(date.getMilliseconds()).padStart(3, '0'),
-    //   ].join('');
-    // };
-    // // 1. 如果存在上一个页面的browseId,发送离开日志
-    // if (currentBrowseId && from.fullPath !== '/') {
-    //   try {
-    //     await defHttp.post({
-    //       url,
-    //       params: {
-    //         browseId: currentBrowseId,
-    //         isEnd: true,
-    //         method: from.fullPath,
-    //       },
-    //     });
-    //     console.log('离开页面日志记录成功');
-    //   } catch (e) {
-    //     console.error('离开页面日志记录失败:', e);
-    //   }
-    // }
-    // // 2. 记录新页面进入日志
-    // currentBrowseId = formatTimestamp();
-    // try {
-    //   await defHttp.post({
-    //     url,
-    //     params: {
-    //       browseId: currentBrowseId,
-    //       isEnd: false,
-    //       method: to.fullPath,
-    //     },
-    //   });
-    //   console.log('进入页面日志记录成功');
-    // } catch (e) {
-    //   console.error('进入页面日志记录失败:', e);
-    // }
-  }
+// const currentBrowseId = '';
+// router.beforeEach(async (to, from, next) => {
+//   if (to.path === '/sys/log/addBrowseLog') {
+//     // const url = '/sys/log/addBrowseLog';
+//     // const currentPath = to.fullPath;
+//     // // 生成时间戳函数
+//     // const formatTimestamp = () => {
+//     //   const date = new Date();
+//     //   return [
+//     //     date.getFullYear(),
+//     //     String(date.getMonth() + 1).padStart(2, '0'),
+//     //     String(date.getDate()).padStart(2, '0'),
+//     //     String(date.getHours()).padStart(2, '0'),
+//     //     String(date.getMinutes()).padStart(2, '0'),
+//     //     String(date.getSeconds()).padStart(2, '0'),
+//     //     String(date.getMilliseconds()).padStart(3, '0'),
+//     //   ].join('');
+//     // };
+//     // // 1. 如果存在上一个页面的browseId,发送离开日志
+//     // if (currentBrowseId && from.fullPath !== '/') {
+//     //   try {
+//     //     await defHttp.post({
+//     //       url,
+//     //       params: {
+//     //         browseId: currentBrowseId,
+//     //         isEnd: true,
+//     //         method: from.fullPath,
+//     //       },
+//     //     });
+//     //     console.log('离开页面日志记录成功');
+//     //   } catch (e) {
+//     //     console.error('离开页面日志记录失败:', e);
+//     //   }
+//     // }
+//     // // 2. 记录新页面进入日志
+//     // currentBrowseId = formatTimestamp();
+//     // try {
+//     //   await defHttp.post({
+//     //     url,
+//     //     params: {
+//     //       browseId: currentBrowseId,
+//     //       isEnd: false,
+//     //       method: to.fullPath,
+//     //     },
+//     //   });
+//     //   console.log('进入页面日志记录成功');
+//     // } catch (e) {
+//     //   console.error('进入页面日志记录失败:', e);
+//     // }
+//   }
 
-  next();
-});
+//   next();
+// });
 
 // reset router
 export function resetRouter() {

+ 12 - 5
src/views/monitor/log/index.vue

@@ -4,6 +4,7 @@
       <a-tabs defaultActiveKey="1" @change="tabChange" size="small">
         <a-tab-pane tab="登录日志" key="1" />
         <a-tab-pane tab="操作日志" key="2" />
+        <a-tab-pane tab="浏览日志" key="3" />
       </a-tabs>
     </template>
     <template #expandedRowRender="{ record }">
@@ -24,7 +25,7 @@
   import { ref } from 'vue';
   import { BasicTable, useTable, TableAction } from '/@/components/Table';
   import { getLogList } from './log.api';
-  import { columns, searchFormSchema, operationLogColumn } from './log.data';
+  import { columns, searchFormSchema, operationLogColumn, browserColumn } from './log.data';
   import { useMessage } from '/@/hooks/web/useMessage';
   import { useListPage } from '/@/hooks/system/useListPage';
   const { createMessage } = useMessage();
@@ -55,10 +56,16 @@
   function tabChange(key) {
     searchInfo.logType = key;
     //update-begin---author:wangshuai ---date:20220506  for:[VUEN-943]vue3日志管理列表翻译不对------------
-    if (key == '1') {
-      logColumns.value = columns;
-    } else {
-      logColumns.value = operationLogColumn;
+    switch (key) {
+      case '1':
+        logColumns.value = columns;
+        break;
+      case '2':
+        logColumns.value = operationLogColumn;
+        break;
+      case '3':
+        logColumns.value = browserColumn;
+        break;
     }
     //update-end---author:wangshuai ---date:20220506  for:[VUEN-943]vue3日志管理列表翻译不对--------------
     reload();

+ 41 - 0
src/views/monitor/log/log.data.ts

@@ -71,3 +71,44 @@ export const searchFormSchema: FormSchema[] = [
     },
   },
 ];
+
+export const browserColumn: BasicColumn[] = [
+  {
+    title: '日志内容',
+    dataIndex: 'logContent',
+    width: 100,
+    align: 'left',
+  },
+  {
+    title: '操作人ID',
+    dataIndex: 'userid',
+    width: 80,
+  },
+  {
+    title: '操作人',
+    dataIndex: 'username',
+    width: 80,
+  },
+  {
+    title: 'IP',
+    dataIndex: 'ip',
+    width: 80,
+  },
+  {
+    title: '耗时(秒)',
+    dataIndex: 'costTime',
+    width: 80,
+  },
+  {
+    title: '创建时间',
+    dataIndex: 'createTime',
+    sorter: true,
+    width: 80,
+  },
+  {
+    title: '结束时间',
+    dataIndex: 'endTime',
+    sorter: true,
+    width: 80,
+  },
+];