mirror of
				https://github.com/continew-org/continew-admin-ui.git
				synced 2025-11-04 10:57:08 +08:00 
			
		
		
		
	refactor: 系统管理/系统日志 => 系统监控/系统日志
This commit is contained in:
		@@ -1 +1,2 @@
 | 
				
			|||||||
export * from './online'
 | 
					export * from './online'
 | 
				
			||||||
 | 
					export * from './log'
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										24
									
								
								src/apis/monitor/log.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/apis/monitor/log.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					import http from '@/utils/http'
 | 
				
			||||||
 | 
					import type * as Monitor from './type'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const BASE_URL = '/system/log'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @desc 查询日志列表 */
 | 
				
			||||||
 | 
					export function listLog(query: Monitor.LogPageQuery) {
 | 
				
			||||||
 | 
					  return http.get<PageRes<Monitor.LogResp[]>>(`${BASE_URL}`, query)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @desc 查询日志详情 */
 | 
				
			||||||
 | 
					export function getLog(id: string) {
 | 
				
			||||||
 | 
					  return http.get<Monitor.LogDetailResp>(`${BASE_URL}/${id}`)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @desc 导出登录日志 */
 | 
				
			||||||
 | 
					export function exportLoginLog(query: Monitor.LogQuery) {
 | 
				
			||||||
 | 
					  return http.download<any>(`${BASE_URL}/export/login`, query)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @desc 导出操作日志 */
 | 
				
			||||||
 | 
					export function exportOperationLog(query: Monitor.LogQuery) {
 | 
				
			||||||
 | 
					  return http.download<any>(`${BASE_URL}/export/operation`, query)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -13,8 +13,43 @@ export interface OnlineUserResp {
 | 
				
			|||||||
  createUserString: string
 | 
					  createUserString: string
 | 
				
			||||||
  createTime: string
 | 
					  createTime: string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
export interface OnlineUserQuery extends PageQuery {
 | 
					export interface OnlineUserQuery extends PageQuery {
 | 
				
			||||||
  nickname?: string
 | 
					  nickname?: string
 | 
				
			||||||
  loginTime?: string
 | 
					  loginTime?: string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 系统日志类型 */
 | 
				
			||||||
 | 
					export interface LogResp {
 | 
				
			||||||
 | 
					  id: string
 | 
				
			||||||
 | 
					  description: string
 | 
				
			||||||
 | 
					  module: string
 | 
				
			||||||
 | 
					  timeTaken: number
 | 
				
			||||||
 | 
					  ip: string
 | 
				
			||||||
 | 
					  address: string
 | 
				
			||||||
 | 
					  browser: string
 | 
				
			||||||
 | 
					  os: string
 | 
				
			||||||
 | 
					  status: number
 | 
				
			||||||
 | 
					  errorMsg: string
 | 
				
			||||||
 | 
					  createUserString: string
 | 
				
			||||||
 | 
					  createTime: string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					export interface LogDetailResp extends LogResp {
 | 
				
			||||||
 | 
					  traceId: string
 | 
				
			||||||
 | 
					  requestUrl: string
 | 
				
			||||||
 | 
					  requestMethod: string
 | 
				
			||||||
 | 
					  requestHeaders: string
 | 
				
			||||||
 | 
					  requestBody: string
 | 
				
			||||||
 | 
					  statusCode: number
 | 
				
			||||||
 | 
					  responseHeaders: string
 | 
				
			||||||
 | 
					  responseBody: string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					export interface LogQuery{
 | 
				
			||||||
 | 
					  description?: string
 | 
				
			||||||
 | 
					  module?: string
 | 
				
			||||||
 | 
					  ip?: string
 | 
				
			||||||
 | 
					  createUserString?: string
 | 
				
			||||||
 | 
					  createTime?: string
 | 
				
			||||||
 | 
					  status?: number
 | 
				
			||||||
 | 
					  sort: Array<string>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					export interface LogPageQuery extends PageQuery, LogQuery {}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@ export * from './user'
 | 
				
			|||||||
export * from './role'
 | 
					export * from './role'
 | 
				
			||||||
export * from './menu'
 | 
					export * from './menu'
 | 
				
			||||||
export * from './dept'
 | 
					export * from './dept'
 | 
				
			||||||
export * from './log'
 | 
					export * from '../monitor/log'
 | 
				
			||||||
export * from './dict'
 | 
					export * from './dict'
 | 
				
			||||||
export * from './file'
 | 
					export * from './file'
 | 
				
			||||||
export * from './storage'
 | 
					export * from './storage'
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,22 +0,0 @@
 | 
				
			|||||||
import http from '@/utils/http'
 | 
					 | 
				
			||||||
import type * as System from './type'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const BASE_URL = '/system/log'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** @desc 查询日志列表 */
 | 
					 | 
				
			||||||
export function listLog(query: System.PageLogQuery) {
 | 
					 | 
				
			||||||
  return http.get<PageRes<System.LogResp[]>>(`${BASE_URL}`, query)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** @desc 查询日志详情 */
 | 
					 | 
				
			||||||
export function getLog(id: string) {
 | 
					 | 
				
			||||||
  return http.get<System.LogDetailResp>(`${BASE_URL}/${id}`)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
/** @desc 导出日志列表 */
 | 
					 | 
				
			||||||
export function exportLog(query: System.LogQuery) {
 | 
					 | 
				
			||||||
  return http.download<any>(`${BASE_URL}/export/login`, query)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
/**@desc 导出操作日志 */
 | 
					 | 
				
			||||||
export function exportOperateLog(query: System.LogQuery) {
 | 
					 | 
				
			||||||
  return http.download<any>(`${BASE_URL}/export/operation`, query)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -119,43 +119,6 @@ export interface DeptQuery {
 | 
				
			|||||||
  sort: Array<string>
 | 
					  sort: Array<string>
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 系统日志类型 */
 | 
					 | 
				
			||||||
export interface LogResp {
 | 
					 | 
				
			||||||
  id: string
 | 
					 | 
				
			||||||
  description: string
 | 
					 | 
				
			||||||
  module: string
 | 
					 | 
				
			||||||
  timeTaken: number
 | 
					 | 
				
			||||||
  ip: string
 | 
					 | 
				
			||||||
  address: string
 | 
					 | 
				
			||||||
  browser: string
 | 
					 | 
				
			||||||
  os: string
 | 
					 | 
				
			||||||
  status: number
 | 
					 | 
				
			||||||
  errorMsg: string
 | 
					 | 
				
			||||||
  createUserString: string
 | 
					 | 
				
			||||||
  createTime: string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
export interface LogDetailResp extends LogResp {
 | 
					 | 
				
			||||||
  traceId: string
 | 
					 | 
				
			||||||
  requestUrl: string
 | 
					 | 
				
			||||||
  requestMethod: string
 | 
					 | 
				
			||||||
  requestHeaders: string
 | 
					 | 
				
			||||||
  requestBody: string
 | 
					 | 
				
			||||||
  statusCode: number
 | 
					 | 
				
			||||||
  responseHeaders: string
 | 
					 | 
				
			||||||
  responseBody: string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
// 系统日志分页查询条件
 | 
					 | 
				
			||||||
export interface PageLogQuery extends PageQuery,LogQuery{}
 | 
					 | 
				
			||||||
// 系统日志查询条件
 | 
					 | 
				
			||||||
export interface LogQuery{
 | 
					 | 
				
			||||||
  description?: string
 | 
					 | 
				
			||||||
  module?: string
 | 
					 | 
				
			||||||
  ip?: string
 | 
					 | 
				
			||||||
  createUserString?: string
 | 
					 | 
				
			||||||
  createTime?: string
 | 
					 | 
				
			||||||
  status?: number
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 系统字典类型 */
 | 
					/** 系统字典类型 */
 | 
				
			||||||
export interface DictResp {
 | 
					export interface DictResp {
 | 
				
			||||||
  id: string
 | 
					  id: string
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div class="json_prettt_container">
 | 
					  <div class="json_pretty_container">
 | 
				
			||||||
    <vue-json-pretty
 | 
					    <vue-json-pretty
 | 
				
			||||||
      :path="'res'"
 | 
					      :path="'res'"
 | 
				
			||||||
      :data="JSONObject"
 | 
					      :data="JSONObject"
 | 
				
			||||||
@@ -8,22 +8,28 @@
 | 
				
			|||||||
    <icon-copy class="copy_icon" @click="onCopy(JSONObject)" />
 | 
					    <icon-copy class="copy_icon" @click="onCopy(JSONObject)" />
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import VueJsonPretty from 'vue-json-pretty'
 | 
					import VueJsonPretty from 'vue-json-pretty'
 | 
				
			||||||
import 'vue-json-pretty/lib/styles.css'
 | 
					import 'vue-json-pretty/lib/styles.css'
 | 
				
			||||||
import { copyText } from '@/utils'
 | 
					import { copyText } from '@/utils'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
defineOptions({ name: 'JsonPretty', inheritAttrs: false })
 | 
					defineOptions({ name: 'JsonPretty', inheritAttrs: false })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const props = defineProps<{
 | 
					const props = defineProps<{
 | 
				
			||||||
  josn: string
 | 
					  json: string
 | 
				
			||||||
}>()
 | 
					}>()
 | 
				
			||||||
const JSONObject = computed(()=>JSON.parse(props?.josn))
 | 
					
 | 
				
			||||||
 | 
					const JSONObject = computed(() => JSON.parse(props?.json))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 拷贝
 | 
				
			||||||
const onCopy = (data: object) => {
 | 
					const onCopy = (data: object) => {
 | 
				
			||||||
  copyText(JSON.stringify(data))
 | 
					  copyText(JSON.stringify(data))
 | 
				
			||||||
  console.log('copyObject',data)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style lang="scss" scoped>
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
.json_prettt_container{
 | 
					.json_pretty_container{
 | 
				
			||||||
  width: 100%;
 | 
					  width: 100%;
 | 
				
			||||||
  height: 100%;
 | 
					  height: 100%;
 | 
				
			||||||
  overflow: auto;
 | 
					  overflow: auto;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,8 +6,8 @@
 | 
				
			|||||||
    :loading="loading"
 | 
					    :loading="loading"
 | 
				
			||||||
    :scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
 | 
					    :scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
 | 
				
			||||||
    :pagination="pagination"
 | 
					    :pagination="pagination"
 | 
				
			||||||
    @filterChange="filterChange"
 | 
					 | 
				
			||||||
    :disabledTools="['setting']"
 | 
					    :disabledTools="['setting']"
 | 
				
			||||||
 | 
					    @filterChange="filterChange"
 | 
				
			||||||
    @refresh="search"
 | 
					    @refresh="search"
 | 
				
			||||||
  >
 | 
					  >
 | 
				
			||||||
    <template #custom-left>
 | 
					    <template #custom-left>
 | 
				
			||||||
@@ -22,7 +22,7 @@
 | 
				
			|||||||
    </template>
 | 
					    </template>
 | 
				
			||||||
    <template #custom-right>
 | 
					    <template #custom-right>
 | 
				
			||||||
      <a-tooltip content="导出">
 | 
					      <a-tooltip content="导出">
 | 
				
			||||||
        <a-button @click="onExportFile">
 | 
					        <a-button @click="onExport">
 | 
				
			||||||
          <template #icon>
 | 
					          <template #icon>
 | 
				
			||||||
            <icon-download />
 | 
					            <icon-download />
 | 
				
			||||||
          </template>
 | 
					          </template>
 | 
				
			||||||
@@ -45,22 +45,13 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { listLog,exportLog } from '@/apis'
 | 
					import { exportLoginLog, listLog } from '@/apis'
 | 
				
			||||||
import type { TableInstance } from '@arco-design/web-vue'
 | 
					import type { TableInstance } from '@arco-design/web-vue'
 | 
				
			||||||
import DateRangePicker from '@/components/DateRangePicker/index.vue'
 | 
					import DateRangePicker from '@/components/DateRangePicker/index.vue'
 | 
				
			||||||
import { useTable } from '@/hooks'
 | 
					import { useTable, useDownload } from '@/hooks'
 | 
				
			||||||
import {useDownload} from '@/hooks'
 | 
					
 | 
				
			||||||
defineOptions({ name: 'LoginLog' })
 | 
					defineOptions({ name: 'LoginLog' })
 | 
				
			||||||
const filterChange = (values,record)=>{
 | 
					
 | 
				
			||||||
  try {
 | 
					 | 
				
			||||||
    const slotName = columns[values.split('_').pop()].slotName as string
 | 
					 | 
				
			||||||
    const value = record.join(',')
 | 
					 | 
				
			||||||
    queryForm[slotName] = value
 | 
					 | 
				
			||||||
    search()
 | 
					 | 
				
			||||||
  } catch (error) {
 | 
					 | 
				
			||||||
    search()
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
const columns: TableInstance['columns'] = [
 | 
					const columns: TableInstance['columns'] = [
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    title: '序号',
 | 
					    title: '序号',
 | 
				
			||||||
@@ -95,10 +86,7 @@ const columns: TableInstance['columns'] = [
 | 
				
			|||||||
  { title: '浏览器', dataIndex: 'browser', ellipsis: true, tooltip: true },
 | 
					  { title: '浏览器', dataIndex: 'browser', ellipsis: true, tooltip: true },
 | 
				
			||||||
  { title: '终端系统', dataIndex: 'os', ellipsis: true, tooltip: true }
 | 
					  { title: '终端系统', dataIndex: 'os', ellipsis: true, tooltip: true }
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
//导出登录日志
 | 
					
 | 
				
			||||||
const onExportFile = ()=>{
 | 
					 | 
				
			||||||
  useDownload(()=>exportLog(queryForm))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
const queryForm = reactive({
 | 
					const queryForm = reactive({
 | 
				
			||||||
  module: '登录',
 | 
					  module: '登录',
 | 
				
			||||||
  ip: undefined,
 | 
					  ip: undefined,
 | 
				
			||||||
@@ -123,6 +111,22 @@ const reset = () => {
 | 
				
			|||||||
  queryForm.status = undefined
 | 
					  queryForm.status = undefined
 | 
				
			||||||
  search()
 | 
					  search()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 导出
 | 
				
			||||||
 | 
					const onExport = () => {
 | 
				
			||||||
 | 
					  useDownload(() => exportLoginLog(queryForm))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 过滤查询
 | 
				
			||||||
 | 
					const filterChange = (dataIndex, filteredValues) => {
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    const slotName = columns[dataIndex.split('_').pop()].slotName as string
 | 
				
			||||||
 | 
					    queryForm[slotName] = filteredValues.join(',')
 | 
				
			||||||
 | 
					    search()
 | 
				
			||||||
 | 
					  } catch (error) {
 | 
				
			||||||
 | 
					    search()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style lang="scss" scoped></style>
 | 
					<style lang="scss" scoped></style>
 | 
				
			||||||
@@ -7,8 +7,8 @@
 | 
				
			|||||||
    :scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
 | 
					    :scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
 | 
				
			||||||
    :pagination="pagination"
 | 
					    :pagination="pagination"
 | 
				
			||||||
    column-resizable
 | 
					    column-resizable
 | 
				
			||||||
    @filterChange="filterChange"
 | 
					 | 
				
			||||||
    :disabledTools="['setting']"
 | 
					    :disabledTools="['setting']"
 | 
				
			||||||
 | 
					    @filterChange="filterChange"
 | 
				
			||||||
    @refresh="search"
 | 
					    @refresh="search"
 | 
				
			||||||
  >
 | 
					  >
 | 
				
			||||||
    <template #custom-left>
 | 
					    <template #custom-left>
 | 
				
			||||||
@@ -22,8 +22,8 @@
 | 
				
			|||||||
      <a-button @click="reset">重置</a-button>
 | 
					      <a-button @click="reset">重置</a-button>
 | 
				
			||||||
    </template>
 | 
					    </template>
 | 
				
			||||||
    <template #custom-right>
 | 
					    <template #custom-right>
 | 
				
			||||||
      <a-tooltip content="导出" @click="onExportFile">
 | 
					      <a-tooltip content="导出">
 | 
				
			||||||
        <a-button>
 | 
					        <a-button @click="onExport">
 | 
				
			||||||
          <template #icon>
 | 
					          <template #icon>
 | 
				
			||||||
            <icon-download />
 | 
					            <icon-download />
 | 
				
			||||||
          </template>
 | 
					          </template>
 | 
				
			||||||
@@ -56,23 +56,14 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { listLog, type LogResp,exportOperateLog } from '@/apis'
 | 
					import { listLog, exportOperationLog, type LogResp } from '@/apis'
 | 
				
			||||||
import type { TableInstance } from '@arco-design/web-vue'
 | 
					import type { TableInstance } from '@arco-design/web-vue'
 | 
				
			||||||
import DateRangePicker from '@/components/DateRangePicker/index.vue'
 | 
					import DateRangePicker from '@/components/DateRangePicker/index.vue'
 | 
				
			||||||
import OperationLogDetailDrawer from './OperationLogDetailDrawer.vue'
 | 
					import OperationLogDetailDrawer from './OperationLogDetailDrawer.vue'
 | 
				
			||||||
import { useDownload, useTable } from '@/hooks'
 | 
					import { useTable, useDownload } from '@/hooks'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
defineOptions({ name: 'OperationLog' })
 | 
					defineOptions({ name: 'OperationLog' })
 | 
				
			||||||
const filterChange = (values,record)=>{
 | 
					
 | 
				
			||||||
  try {
 | 
					 | 
				
			||||||
    const slotName = columns[values.split('_').pop()].slotName as string
 | 
					 | 
				
			||||||
    const value = record.join(',')
 | 
					 | 
				
			||||||
    queryForm[slotName] = value
 | 
					 | 
				
			||||||
    search()
 | 
					 | 
				
			||||||
  } catch (error) {
 | 
					 | 
				
			||||||
    search()
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
const columns: TableInstance['columns'] = [
 | 
					const columns: TableInstance['columns'] = [
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    title: '序号',
 | 
					    title: '序号',
 | 
				
			||||||
@@ -109,10 +100,7 @@ const columns: TableInstance['columns'] = [
 | 
				
			|||||||
  { title: '浏览器', dataIndex: 'browser', ellipsis: true, tooltip: true },
 | 
					  { title: '浏览器', dataIndex: 'browser', ellipsis: true, tooltip: true },
 | 
				
			||||||
  { title: '终端系统', dataIndex: 'os', ellipsis: true, tooltip: true }
 | 
					  { title: '终端系统', dataIndex: 'os', ellipsis: true, tooltip: true }
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
//导出操作日志
 | 
					
 | 
				
			||||||
const onExportFile = ()=>{
 | 
					 | 
				
			||||||
  useDownload(()=>exportOperateLog(queryForm))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
const queryForm = reactive({
 | 
					const queryForm = reactive({
 | 
				
			||||||
  description: undefined,
 | 
					  description: undefined,
 | 
				
			||||||
  ip: undefined,
 | 
					  ip: undefined,
 | 
				
			||||||
@@ -139,6 +127,22 @@ const reset = () => {
 | 
				
			|||||||
  search()
 | 
					  search()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 导出
 | 
				
			||||||
 | 
					const onExport = () => {
 | 
				
			||||||
 | 
					  useDownload(() => exportOperationLog(queryForm))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 过滤查询
 | 
				
			||||||
 | 
					const filterChange = (dataIndex, filteredValues) => {
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    const slotName = columns[dataIndex.split('_').pop()].slotName as string
 | 
				
			||||||
 | 
					    queryForm[slotName] = filteredValues.join(',')
 | 
				
			||||||
 | 
					    search()
 | 
				
			||||||
 | 
					  } catch (error) {
 | 
				
			||||||
 | 
					    search()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const OperationLogDetailDrawerRef = ref<InstanceType<typeof OperationLogDetailDrawer>>()
 | 
					const OperationLogDetailDrawerRef = ref<InstanceType<typeof OperationLogDetailDrawer>>()
 | 
				
			||||||
// 查询详情
 | 
					// 查询详情
 | 
				
			||||||
const openDetail = (item: LogResp) => {
 | 
					const openDetail = (item: LogResp) => {
 | 
				
			||||||
							
								
								
									
										106
									
								
								src/views/monitor/log/OperationLogDetailDrawer.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								src/views/monitor/log/OperationLogDetailDrawer.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,106 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <a-drawer v-model:visible="visible" title="日志详情" :width="720" :footer="false">
 | 
				
			||||||
 | 
					    <a-descriptions title="基本信息" :column="2" size="large" class="general-description">
 | 
				
			||||||
 | 
					      <a-descriptions-item label="日志 ID">{{ dataDetail?.id }}</a-descriptions-item>
 | 
				
			||||||
 | 
					      <a-descriptions-item label="Trace ID" >{{ dataDetail?.traceId }}<TextCopy :value="dataDetail?.traceId" /></a-descriptions-item>
 | 
				
			||||||
 | 
					      <a-descriptions-item label="操作人">{{ dataDetail?.createUserString }}</a-descriptions-item>
 | 
				
			||||||
 | 
					      <a-descriptions-item label="操作时间">{{ dataDetail?.createTime }}</a-descriptions-item>
 | 
				
			||||||
 | 
					      <a-descriptions-item label="操作内容">{{ dataDetail?.description }}</a-descriptions-item>
 | 
				
			||||||
 | 
					      <a-descriptions-item label="所属模块">{{ dataDetail?.module }}</a-descriptions-item>
 | 
				
			||||||
 | 
					      <a-descriptions-item label="操作 IP">{{ dataDetail?.ip }}</a-descriptions-item>
 | 
				
			||||||
 | 
					      <a-descriptions-item label="操作地点">{{ dataDetail?.address }}</a-descriptions-item>
 | 
				
			||||||
 | 
					      <a-descriptions-item label="浏览器">{{ dataDetail?.browser }}</a-descriptions-item>
 | 
				
			||||||
 | 
					      <a-descriptions-item label="终端系统">{{ dataDetail?.os }}</a-descriptions-item>
 | 
				
			||||||
 | 
					      <a-descriptions-item label="状态">
 | 
				
			||||||
 | 
					        <a-tag v-if="dataDetail?.status === 1" color="green">成功</a-tag>
 | 
				
			||||||
 | 
					        <a-tag v-else color="red">失败</a-tag>
 | 
				
			||||||
 | 
					      </a-descriptions-item>
 | 
				
			||||||
 | 
					      <a-descriptions-item label="耗时">
 | 
				
			||||||
 | 
					        <a-tag v-if="dataDetail?.timeTaken > 500" color="red">
 | 
				
			||||||
 | 
					          {{ dataDetail?.timeTaken }}ms
 | 
				
			||||||
 | 
					        </a-tag>
 | 
				
			||||||
 | 
					        <a-tag v-else-if="dataDetail?.timeTaken > 200" color="orange">
 | 
				
			||||||
 | 
					          {{ dataDetail?.timeTaken }}ms
 | 
				
			||||||
 | 
					        </a-tag>
 | 
				
			||||||
 | 
					        <a-tag v-else color="green">{{ dataDetail?.timeTaken }} ms</a-tag>
 | 
				
			||||||
 | 
					      </a-descriptions-item>
 | 
				
			||||||
 | 
					      <a-descriptions-item label="请求 URI" :span="2">
 | 
				
			||||||
 | 
					        {{ dataDetail?.requestUrl }}<TextCopy :value="dataDetail?.requestUrl" />
 | 
				
			||||||
 | 
					      </a-descriptions-item>
 | 
				
			||||||
 | 
					    </a-descriptions>
 | 
				
			||||||
 | 
					    <a-descriptions
 | 
				
			||||||
 | 
					      title="响应信息"
 | 
				
			||||||
 | 
					      :column="2"
 | 
				
			||||||
 | 
					      size="large"
 | 
				
			||||||
 | 
					      class="general-description http"
 | 
				
			||||||
 | 
					      style="margin-top: 20px; position: relative"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <a-descriptions-item :span="2">
 | 
				
			||||||
 | 
					        <a-tabs type="card">
 | 
				
			||||||
 | 
					          <a-tab-pane key="1" title="响应头">
 | 
				
			||||||
 | 
					            <JsonPretty v-if="dataDetail?.responseHeaders" :json="dataDetail?.responseHeaders" />
 | 
				
			||||||
 | 
					            <span v-else>无</span>
 | 
				
			||||||
 | 
					          </a-tab-pane>
 | 
				
			||||||
 | 
					          <a-tab-pane key="2" title="响应体">
 | 
				
			||||||
 | 
					            <JsonPretty v-if="dataDetail?.responseBody" :json="dataDetail?.responseBody" />
 | 
				
			||||||
 | 
					            <span v-else>无</span>
 | 
				
			||||||
 | 
					          </a-tab-pane>
 | 
				
			||||||
 | 
					        </a-tabs>
 | 
				
			||||||
 | 
					      </a-descriptions-item>
 | 
				
			||||||
 | 
					    </a-descriptions>
 | 
				
			||||||
 | 
					    <a-descriptions
 | 
				
			||||||
 | 
					      title="请求信息"
 | 
				
			||||||
 | 
					      :column="2"
 | 
				
			||||||
 | 
					      size="large"
 | 
				
			||||||
 | 
					      class="general-description http"
 | 
				
			||||||
 | 
					      style="margin-top: 20px; position: relative"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <a-descriptions-item :span="2">
 | 
				
			||||||
 | 
					        <a-tabs type="card">
 | 
				
			||||||
 | 
					          <a-tab-pane key="1" title="请求头">
 | 
				
			||||||
 | 
					            <JsonPretty v-if="dataDetail?.requestHeaders" :json="dataDetail?.requestHeaders" />
 | 
				
			||||||
 | 
					            <span v-else>无</span>
 | 
				
			||||||
 | 
					          </a-tab-pane>
 | 
				
			||||||
 | 
					          <a-tab-pane key="2" title="请求体">
 | 
				
			||||||
 | 
					            <JsonPretty v-if="dataDetail?.requestBody" :json="dataDetail?.requestBody" />
 | 
				
			||||||
 | 
					            <span v-else>无</span>
 | 
				
			||||||
 | 
					          </a-tab-pane>
 | 
				
			||||||
 | 
					        </a-tabs>
 | 
				
			||||||
 | 
					      </a-descriptions-item>
 | 
				
			||||||
 | 
					    </a-descriptions>
 | 
				
			||||||
 | 
					  </a-drawer>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" setup>
 | 
				
			||||||
 | 
					import { getLog, type LogDetailResp } from '@/apis'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const dataId = ref('')
 | 
				
			||||||
 | 
					const dataDetail = ref<LogDetailResp>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 查询详情
 | 
				
			||||||
 | 
					const getDataDetail = async () => {
 | 
				
			||||||
 | 
					  const res = await getLog(dataId.value)
 | 
				
			||||||
 | 
					  dataDetail.value = res.data
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const visible = ref(false)
 | 
				
			||||||
 | 
					// 打开详情
 | 
				
			||||||
 | 
					const open = async (id: string) => {
 | 
				
			||||||
 | 
					  dataId.value = id
 | 
				
			||||||
 | 
					  await getDataDetail()
 | 
				
			||||||
 | 
					  visible.value = true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					defineExpose({ open })
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.http :deep(.arco-descriptions-item-label-block) {
 | 
				
			||||||
 | 
					  padding-right: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:deep(.arco-tabs-content) {
 | 
				
			||||||
 | 
					  padding-top: 5px;
 | 
				
			||||||
 | 
					  padding-left: 15px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@@ -6,7 +6,7 @@
 | 
				
			|||||||
        <a-tab-pane key="2" title="操作日志" />
 | 
					        <a-tab-pane key="2" title="操作日志" />
 | 
				
			||||||
      </a-tabs>
 | 
					      </a-tabs>
 | 
				
			||||||
      <keep-alive>
 | 
					      <keep-alive>
 | 
				
			||||||
          <component :is="PaneMap[activeKey]"></component>
 | 
					          <component :is="PaneMap[activeKey]" />
 | 
				
			||||||
      </keep-alive>
 | 
					      </keep-alive>
 | 
				
			||||||
    </a-card>
 | 
					    </a-card>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
@@ -15,12 +15,15 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import LoginLog from './LoginLog.vue'
 | 
					import LoginLog from './LoginLog.vue'
 | 
				
			||||||
import OperationLog from './OperationLog.vue'
 | 
					import OperationLog from './OperationLog.vue'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const route = useRoute()
 | 
					const route = useRoute()
 | 
				
			||||||
const router = useRouter()
 | 
					const router = useRouter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const PaneMap: Record<string, Component> = {
 | 
					const PaneMap: Record<string, Component> = {
 | 
				
			||||||
  '1': LoginLog,
 | 
					  '1': LoginLog,
 | 
				
			||||||
  '2': OperationLog
 | 
					  '2': OperationLog
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const activeKey = ref('1')
 | 
					const activeKey = ref('1')
 | 
				
			||||||
watch(
 | 
					watch(
 | 
				
			||||||
  () => route.query,
 | 
					  () => route.query,
 | 
				
			||||||
@@ -31,6 +34,7 @@ watch(
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  { immediate: true }
 | 
					  { immediate: true }
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const change = (key: string | number) => {
 | 
					const change = (key: string | number) => {
 | 
				
			||||||
  activeKey.value = key as string
 | 
					  activeKey.value = key as string
 | 
				
			||||||
  router.replace({ path: route.path, query: { tabKey: key } })
 | 
					  router.replace({ path: route.path, query: { tabKey: key } })
 | 
				
			||||||
@@ -1,105 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
  <a-drawer v-model:visible="visible" title="日志详情" :width="720" :footer="false">
 | 
					 | 
				
			||||||
    <a-descriptions title="基本信息" :column="2" size="large" class="general-description">
 | 
					 | 
				
			||||||
      <a-descriptions-item label="日志 ID">{{ operationLog?.id }}</a-descriptions-item>
 | 
					 | 
				
			||||||
      <a-descriptions-item label="Trace ID" >{{ operationLog?.traceId }}<TextCopy :value="operationLog?.traceId"/></a-descriptions-item>
 | 
					 | 
				
			||||||
      <a-descriptions-item label="操作人">{{ operationLog?.createUserString }}</a-descriptions-item>
 | 
					 | 
				
			||||||
      <a-descriptions-item label="操作时间">{{ operationLog?.createTime }}</a-descriptions-item>
 | 
					 | 
				
			||||||
      <a-descriptions-item label="操作内容">{{ operationLog?.description }}</a-descriptions-item>
 | 
					 | 
				
			||||||
      <a-descriptions-item label="所属模块">{{ operationLog?.module }}</a-descriptions-item>
 | 
					 | 
				
			||||||
      <a-descriptions-item label="操作 IP">{{ operationLog?.ip }}</a-descriptions-item>
 | 
					 | 
				
			||||||
      <a-descriptions-item label="操作地点">{{ operationLog?.address }}</a-descriptions-item>
 | 
					 | 
				
			||||||
      <a-descriptions-item label="浏览器">{{ operationLog?.browser }}</a-descriptions-item>
 | 
					 | 
				
			||||||
      <a-descriptions-item label="终端系统">{{ operationLog?.os }}</a-descriptions-item>
 | 
					 | 
				
			||||||
      <a-descriptions-item label="状态">
 | 
					 | 
				
			||||||
        <a-tag v-if="operationLog?.status === 1" color="green">成功</a-tag>
 | 
					 | 
				
			||||||
        <a-tag v-else color="red">失败</a-tag>
 | 
					 | 
				
			||||||
      </a-descriptions-item>
 | 
					 | 
				
			||||||
      <a-descriptions-item label="耗时">
 | 
					 | 
				
			||||||
        <a-tag v-if="operationLog?.timeTaken > 500" color="red">
 | 
					 | 
				
			||||||
          {{ operationLog?.timeTaken }}ms
 | 
					 | 
				
			||||||
        </a-tag>
 | 
					 | 
				
			||||||
        <a-tag v-else-if="operationLog?.timeTaken > 200" color="orange">
 | 
					 | 
				
			||||||
          {{ operationLog?.timeTaken }}ms
 | 
					 | 
				
			||||||
        </a-tag>
 | 
					 | 
				
			||||||
        <a-tag v-else color="green">{{ operationLog?.timeTaken }} ms</a-tag>
 | 
					 | 
				
			||||||
      </a-descriptions-item>
 | 
					 | 
				
			||||||
      <a-descriptions-item label="请求 URI" :span="2">
 | 
					 | 
				
			||||||
        {{ operationLog?.requestUrl }}<TextCopy :value="operationLog?.requestUrl"/>
 | 
					 | 
				
			||||||
      </a-descriptions-item>
 | 
					 | 
				
			||||||
    </a-descriptions>
 | 
					 | 
				
			||||||
    <a-descriptions
 | 
					 | 
				
			||||||
      title="响应信息"
 | 
					 | 
				
			||||||
      :column="2"
 | 
					 | 
				
			||||||
      size="large"
 | 
					 | 
				
			||||||
      class="general-description http"
 | 
					 | 
				
			||||||
      style="margin-top: 20px; position: relative"
 | 
					 | 
				
			||||||
    >
 | 
					 | 
				
			||||||
      <a-descriptions-item :span="2">
 | 
					 | 
				
			||||||
        <a-tabs type="card">
 | 
					 | 
				
			||||||
          <a-tab-pane key="1" title="响应头">
 | 
					 | 
				
			||||||
            <JsonPretty v-if="operationLog?.responseHeaders" :josn="operationLog?.responseHeaders"/>
 | 
					 | 
				
			||||||
            <span v-else>无</span>
 | 
					 | 
				
			||||||
          </a-tab-pane>
 | 
					 | 
				
			||||||
          <a-tab-pane key="2" title="响应体">
 | 
					 | 
				
			||||||
            <JsonPretty v-if="operationLog?.responseBody" :josn="operationLog?.responseBody"/>
 | 
					 | 
				
			||||||
            <span v-else>无</span>
 | 
					 | 
				
			||||||
          </a-tab-pane>
 | 
					 | 
				
			||||||
        </a-tabs>
 | 
					 | 
				
			||||||
      </a-descriptions-item>
 | 
					 | 
				
			||||||
    </a-descriptions>
 | 
					 | 
				
			||||||
    <a-descriptions
 | 
					 | 
				
			||||||
      title="请求信息"
 | 
					 | 
				
			||||||
      :column="2"
 | 
					 | 
				
			||||||
      size="large"
 | 
					 | 
				
			||||||
      class="general-description http"
 | 
					 | 
				
			||||||
      style="margin-top: 20px; position: relative"
 | 
					 | 
				
			||||||
    >
 | 
					 | 
				
			||||||
      <a-descriptions-item :span="2">
 | 
					 | 
				
			||||||
        <a-tabs type="card">
 | 
					 | 
				
			||||||
          <a-tab-pane key="1" title="请求头">
 | 
					 | 
				
			||||||
            <JsonPretty v-if="operationLog?.requestHeaders" :josn="operationLog?.requestHeaders"/>
 | 
					 | 
				
			||||||
            <span v-else>无</span>
 | 
					 | 
				
			||||||
          </a-tab-pane>
 | 
					 | 
				
			||||||
          <a-tab-pane key="2" title="请求体">
 | 
					 | 
				
			||||||
            <JsonPretty v-if="operationLog?.requestBody" :josn="operationLog?.requestBody"/>
 | 
					 | 
				
			||||||
            <span v-else>无</span>
 | 
					 | 
				
			||||||
          </a-tab-pane>
 | 
					 | 
				
			||||||
        </a-tabs>
 | 
					 | 
				
			||||||
      </a-descriptions-item>
 | 
					 | 
				
			||||||
    </a-descriptions>
 | 
					 | 
				
			||||||
  </a-drawer>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script lang="ts" setup>
 | 
					 | 
				
			||||||
import { getLog, type LogDetailResp } from '@/apis'
 | 
					 | 
				
			||||||
import JsonPretty from '@/components/JsonPretty/index.vue'
 | 
					 | 
				
			||||||
const logId = ref('')
 | 
					 | 
				
			||||||
const operationLog = ref<LogDetailResp | null>()
 | 
					 | 
				
			||||||
// 查询详情
 | 
					 | 
				
			||||||
const getOperationLogDetail = async () => {
 | 
					 | 
				
			||||||
  const res = await getLog(logId.value)
 | 
					 | 
				
			||||||
  operationLog.value = res.data
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const visible = ref(false)
 | 
					 | 
				
			||||||
// 打开详情
 | 
					 | 
				
			||||||
const open = async (id: string) => {
 | 
					 | 
				
			||||||
  logId.value = id
 | 
					 | 
				
			||||||
  await getOperationLogDetail()
 | 
					 | 
				
			||||||
  visible.value = true
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
defineExpose({ open })
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style lang="scss" scoped>
 | 
					 | 
				
			||||||
.http :deep(.arco-descriptions-item-label-block) {
 | 
					 | 
				
			||||||
  padding-right: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
:deep(.arco-tabs-content) {
 | 
					 | 
				
			||||||
  padding-top: 5px;
 | 
					 | 
				
			||||||
  padding-left: 15px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user