|
@@ -0,0 +1,255 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="container">
|
|
|
|
|
+ <Breadcrumb :items="['日志记录', '请求日志']" />
|
|
|
|
|
+
|
|
|
|
|
+ <a-card title="请求日志">
|
|
|
|
|
+ <a-row>
|
|
|
|
|
+ <a-col :flex="1">
|
|
|
|
|
+ <a-form :model="queryData" :label-col-props="{ span: 6 }" :wrapper-col-props="{ span: 18 }"
|
|
|
|
|
+ label-align="left">
|
|
|
|
|
+ <a-row :gutter="16">
|
|
|
|
|
+ <a-col :span="8">
|
|
|
|
|
+ <a-form-item field="begin_time" label="开始时间">
|
|
|
|
|
+ <a-date-picker show-time format="YYYY-MM-DD HH:mm:ss"
|
|
|
|
|
+ v-model="queryData.begin_time" />
|
|
|
|
|
+ </a-form-item>
|
|
|
|
|
+ </a-col>
|
|
|
|
|
+ <a-col :span="8">
|
|
|
|
|
+ <a-form-item field="end_time" label="结束时间">
|
|
|
|
|
+ <a-date-picker show-time format="YYYY-MM-DD HH:mm:ss"
|
|
|
|
|
+ v-model="queryData.end_time" />
|
|
|
|
|
+ </a-form-item>
|
|
|
|
|
+ </a-col>
|
|
|
|
|
+ <a-col :span="8">
|
|
|
|
|
+ <a-form-item field="create_user" label="用户UUID">
|
|
|
|
|
+ <a-input v-model="queryData.create_user" />
|
|
|
|
|
+ </a-form-item>
|
|
|
|
|
+ </a-col>
|
|
|
|
|
+ </a-row>
|
|
|
|
|
+ </a-form>
|
|
|
|
|
+ </a-col>
|
|
|
|
|
+ <a-divider style="height: 84px" direction="vertical" />
|
|
|
|
|
+ <a-col :flex="'86px'" style="text-align: right">
|
|
|
|
|
+ <a-space direction="vertical" :size="18">
|
|
|
|
|
+ <a-button type="primary" @click="search">
|
|
|
|
|
+ <template #icon>
|
|
|
|
|
+ <icon-search />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ 搜索
|
|
|
|
|
+ </a-button>
|
|
|
|
|
+ <a-button @click="reset">
|
|
|
|
|
+ <template #icon>
|
|
|
|
|
+ <icon-refresh />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ 重置
|
|
|
|
|
+ </a-button>
|
|
|
|
|
+ </a-space>
|
|
|
|
|
+ </a-col>
|
|
|
|
|
+ </a-row>
|
|
|
|
|
+
|
|
|
|
|
+ <a-table :data="data" stripe hoverable column-resizable class="table" :loading="loading" :columns="columns"
|
|
|
|
|
+ :pagination="{
|
|
|
|
|
+ showPageSize: true,
|
|
|
|
|
+ showJumper: true,
|
|
|
|
|
+ showTotal: true,
|
|
|
|
|
+ pageSize: pagination.pagesize,
|
|
|
|
|
+ current: pagination.current,
|
|
|
|
|
+ total: pagination.total
|
|
|
|
|
+ }" @page-change="handlePageChange" @page-size-change="handlePageSizeChange">
|
|
|
|
|
+ <template #username="{ record }">
|
|
|
|
|
+ <a-avatar :size="35">
|
|
|
|
|
+ <IconUser v-if="!record.avatar" />
|
|
|
|
|
+ <img :alt="record.username ?? ''" :src="record.avatar" v-else />
|
|
|
|
|
+ </a-avatar>
|
|
|
|
|
+ {{ record.username }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template #time="{ record }">
|
|
|
|
|
+ {{ stramptoTime(record.create_time) }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template #optional="{ record }">
|
|
|
|
|
+ <a-button @click="showDetail(record)">查看详情</a-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </a-table>
|
|
|
|
|
+ </a-card>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <a-modal v-model:visible="showModal" @cancel="handleCancel" draggable>
|
|
|
|
|
+ <template #title>
|
|
|
|
|
+ 日志详情
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <a-descriptions :data="modalData" :column="1" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-modal>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script setup>
|
|
|
|
|
+import { ref, reactive, onMounted } from 'vue'
|
|
|
|
|
+import { adminGetReqLog } from '@/api/user'
|
|
|
|
|
+import { Notification } from '@arco-design/web-vue'
|
|
|
|
|
+
|
|
|
|
|
+const showModal = ref(false)
|
|
|
|
|
+const modalData = ref([])
|
|
|
|
|
+
|
|
|
|
|
+const queryData = reactive({
|
|
|
|
|
+ create_user: '',
|
|
|
|
|
+ begin_time: null,
|
|
|
|
|
+ end_time: null
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const pagination = reactive({
|
|
|
|
|
+ total: 0,
|
|
|
|
|
+ current: 1, // 默认从第1页开始
|
|
|
|
|
+ pagesize: 20
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const loading = ref(false)
|
|
|
|
|
+const data = ref([])
|
|
|
|
|
+
|
|
|
|
|
+const columns = [{
|
|
|
|
|
+ title: 'ID',
|
|
|
|
|
+ dataIndex: 'id',
|
|
|
|
|
+}, {
|
|
|
|
|
+ title: '操作人',
|
|
|
|
|
+ slotName: 'username'
|
|
|
|
|
+}, {
|
|
|
|
|
+ title: '访问路径',
|
|
|
|
|
+ dataIndex: 'url',
|
|
|
|
|
+}, {
|
|
|
|
|
+ title: '请求方法',
|
|
|
|
|
+ dataIndex: 'method',
|
|
|
|
|
+}, {
|
|
|
|
|
+ title: '请求IP',
|
|
|
|
|
+ dataIndex: 'ip',
|
|
|
|
|
+}, {
|
|
|
|
|
+ title: 'IP属地',
|
|
|
|
|
+ dataIndex: 'location',
|
|
|
|
|
+}, {
|
|
|
|
|
+ title: '操作时间',
|
|
|
|
|
+ slotName: 'time',
|
|
|
|
|
+}, {
|
|
|
|
|
+ title: '状态',
|
|
|
|
|
+ slotName: 'code'
|
|
|
|
|
+}, {
|
|
|
|
|
+ title: '操作',
|
|
|
|
|
+ slotName: 'optional'
|
|
|
|
|
+}
|
|
|
|
|
+]
|
|
|
|
|
+
|
|
|
|
|
+const search = () => {
|
|
|
|
|
+ pagination.current = 1
|
|
|
|
|
+ getLogList()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const reset = () => {
|
|
|
|
|
+ queryData.create_user = ''
|
|
|
|
|
+ queryData.begin_time = null
|
|
|
|
|
+ queryData.end_time = null
|
|
|
|
|
+ getLogList()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const handleCancel = () => {
|
|
|
|
|
+ showModal.value = false
|
|
|
|
|
+ modalData.value = []
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const showDetail = (record) => {
|
|
|
|
|
+ const data = [{
|
|
|
|
|
+ label: '操作人',
|
|
|
|
|
+ value: record.username,
|
|
|
|
|
+ }, {
|
|
|
|
|
+ label: '操作人UUID',
|
|
|
|
|
+ value: record.create_user,
|
|
|
|
|
+ }, {
|
|
|
|
|
+ label: '请求方式',
|
|
|
|
|
+ value: record.method
|
|
|
|
|
+ }, {
|
|
|
|
|
+ label: '请求路径',
|
|
|
|
|
+ value: record.url,
|
|
|
|
|
+ }, {
|
|
|
|
|
+ label: '请求IP',
|
|
|
|
|
+ value: record.ip
|
|
|
|
|
+ }, {
|
|
|
|
|
+ label: 'IP属地',
|
|
|
|
|
+ value: record.location
|
|
|
|
|
+ }, {
|
|
|
|
|
+ label: '请求数据',
|
|
|
|
|
+ value: JSON.stringify(record.reqData)
|
|
|
|
|
+ }, {
|
|
|
|
|
+ label: '响应数据',
|
|
|
|
|
+ value: JSON.stringify(record.resData)
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ label: '状态码',
|
|
|
|
|
+ value: record.code
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ label: '操作时间',
|
|
|
|
|
+ value: stramptoTime(record.create_time)
|
|
|
|
|
+ },
|
|
|
|
|
+ ]
|
|
|
|
|
+
|
|
|
|
|
+ modalData.value = data
|
|
|
|
|
+ showModal.value = true
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const getLogList = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ loading.value = true
|
|
|
|
|
+ const reqData = {
|
|
|
|
|
+ create_user: queryData.create_user,
|
|
|
|
|
+ begin_time: new Date(queryData.begin_time).getTime(),
|
|
|
|
|
+ end_time: new Date(queryData.end_time).getTime(),
|
|
|
|
|
+ pagesize: pagination.pagesize,
|
|
|
|
|
+ current: pagination.current
|
|
|
|
|
+ }
|
|
|
|
|
+ const res = await adminGetReqLog(reqData)
|
|
|
|
|
+ if (!res || res.code !== 0)
|
|
|
|
|
+ return Notification.error({
|
|
|
|
|
+ title: '获取日志数据失败!',
|
|
|
|
|
+ content: res?.msg ?? '请稍后再试'
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ data.value = res.data
|
|
|
|
|
+ pagination.total = res.pagination.total
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ Notification.error({
|
|
|
|
|
+ title: '获取日志数据失败!',
|
|
|
|
|
+ content: error.message || '请稍后再试'
|
|
|
|
|
+ })
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ loading.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 分页 - 页码变化
|
|
|
|
|
+const handlePageChange = (page) => {
|
|
|
|
|
+ pagination.current = page
|
|
|
|
|
+ getLogList()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 分页 - 每页条数变化
|
|
|
|
|
+const handlePageSizeChange = (size) => {
|
|
|
|
|
+ pagination.pagesize = size
|
|
|
|
|
+ pagination.current = 1 // 页大小变化后回到第一页
|
|
|
|
|
+ getLogList()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+onMounted(() => {
|
|
|
|
|
+ getLogList()
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const stramptoTime = (time) => {
|
|
|
|
|
+ return new Date(time).toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' })
|
|
|
|
|
+}
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped>
|
|
|
|
|
+.container {
|
|
|
|
|
+ padding: 0 20px 20px 20px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.table {
|
|
|
|
|
+ margin-top: 15px;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|