From 6c000a9f933f43a072d52790efc22bbcc8238eee Mon Sep 17 00:00:00 2001 From: hwh <332078369@qq.com> Date: 星期五, 23 八月 2024 09:08:01 +0800 Subject: [PATCH] 日志文件 --- .gitignore | 2 Web/src/views/system/log/vislog/index.vue | 183 ++++++++++++ Web/src/views/system/log/exlog/index.vue | 279 ++++++++++++++++++ Web/src/views/system/log/oplog/index.vue | 270 ++++++++++++++++++ Web/src/views/system/log/difflog/index.vue | 147 +++++++++ 5 files changed, 880 insertions(+), 1 deletions(-) diff --git a/.gitignore b/.gitignore index 9491a2f..10d1295 100644 --- a/.gitignore +++ b/.gitignore @@ -141,7 +141,6 @@ # AxoCover is a Code Coverage Tool .axoCover/* !.axoCover/settings.json - # Coverlet is a free, cross platform Code Coverage Tool coverage*.json coverage*.xml @@ -200,6 +199,7 @@ **/[Pp]ackages/* # except build/, which is used as an MSBuild target. !**/[Pp]ackages/build/ +!**/system/log/ # Uncomment if necessary however generally it will be regenerated when needed #!**/[Pp]ackages/repositories.config # NuGet v3's project.json files produces more ignorable files diff --git a/Web/src/views/system/log/difflog/index.vue b/Web/src/views/system/log/difflog/index.vue new file mode 100644 index 0000000..6e90187 --- /dev/null +++ b/Web/src/views/system/log/difflog/index.vue @@ -0,0 +1,147 @@ +<template> + <div class="sys-difflog-container"> + <el-card shadow="hover" :body-style="{ paddingBottom: '0' }"> + <el-form :model="state.queryParams" ref="queryForm" :inline="true"> + <el-form-item label="寮�濮嬫椂闂�"> + <el-date-picker v-model="state.queryParams.startTime" type="datetime" placeholder="寮�濮嬫椂闂�" value-format="YYYY-MM-DD HH:mm:ss" :shortcuts="shortcuts" /> + </el-form-item> + <el-form-item label="缁撴潫鏃堕棿"> + <el-date-picker v-model="state.queryParams.endTime" type="datetime" placeholder="缁撴潫鏃堕棿" value-format="YYYY-MM-DD HH:mm:ss" :shortcuts="shortcuts" /> + </el-form-item> + <el-form-item> + <el-button-group> + <el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysDifflog:page'"> 鏌ヨ </el-button> + <el-button icon="ele-Refresh" @click="resetQuery"> 閲嶇疆 </el-button> + </el-button-group> + </el-form-item> + <el-form-item> + <el-button icon="ele-DeleteFilled" type="danger" @click="clearLog" v-auth="'sysDifflog:clear'"> 娓呯┖ </el-button> + </el-form-item> + </el-form> + </el-card> + + <el-card class="full-table" shadow="hover" style="margin-top: 5px"> + <el-table :data="state.logData" style="width: 100%" v-loading="state.loading" border> + <el-table-column type="index" label="搴忓彿" width="55" align="center" /> + <el-table-column prop="diffType" label="宸紓鎿嶄綔" header-align="center" show-overflow-tooltip /> + <el-table-column prop="sql" label="Sql璇彞" header-align="center" show-overflow-tooltip /> + <el-table-column prop="parameters" label="鍙傛暟" header-align="center" show-overflow-tooltip /> + <el-table-column prop="elapsed" label="鑰楁椂(ms)" header-align="center" show-overflow-tooltip /> + <el-table-column prop="message" label="鏃ュ織娑堟伅" header-align="center" show-overflow-tooltip /> + <el-table-column prop="beforeData" label="鎿嶄綔鍓嶈褰�" header-align="center" show-overflow-tooltip /> + <el-table-column prop="afterData" label="鎿嶄綔鍚庤褰�" header-align="center" show-overflow-tooltip /> + <el-table-column prop="businessData" label="涓氬姟瀵硅薄" header-align="center" show-overflow-tooltip /> + <el-table-column prop="createTime" label="鎿嶄綔鏃堕棿" align="center" show-overflow-tooltip /> + </el-table> + <el-pagination + v-model:currentPage="state.tableParams.page" + v-model:page-size="state.tableParams.pageSize" + :total="state.tableParams.total" + :page-sizes="[10, 20, 50, 100]" + size="small" + background + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + layout="total, sizes, prev, pager, next, jumper" + /> + </el-card> + </div> +</template> + +<script lang="ts" setup name="sysDiffLog"> +import { onMounted, reactive } from 'vue'; +import { ElMessage } from 'element-plus'; + +import { getAPI } from '/@/utils/axios-utils'; +import { SysLogDiffApi } from '/@/api-services/api'; +import { SysLogDiff } from '/@/api-services/models'; + +const state = reactive({ + loading: false, + queryParams: { + startTime: undefined, + endTime: undefined, + }, + tableParams: { + page: 1, + pageSize: 10, + total: 0 as any, + }, + logData: [] as Array<SysLogDiff>, +}); + +onMounted(async () => { + handleQuery(); +}); + +// 鏌ヨ鎿嶄綔 +const handleQuery = async () => { + if (state.queryParams.startTime == null) state.queryParams.startTime = undefined; + if (state.queryParams.endTime == null) state.queryParams.endTime = undefined; + + state.loading = true; + let params = Object.assign(state.queryParams, state.tableParams); + var res = await getAPI(SysLogDiffApi).apiSysLogDiffPagePost(params); + state.logData = res.data.result?.items ?? []; + state.tableParams.total = res.data.result?.total; + state.loading = false; +}; + +// 閲嶇疆鎿嶄綔 +const resetQuery = () => { + state.queryParams.startTime = undefined; + state.queryParams.endTime = undefined; + handleQuery(); +}; + +// 娓呯┖鏃ュ織 +const clearLog = async () => { + state.loading = true; + await getAPI(SysLogDiffApi).apiSysLogDiffClearPost(); + state.loading = false; + + ElMessage.success('娓呯┖鎴愬姛'); + handleQuery(); +}; + +// 鏀瑰彉椤甸潰瀹归噺 +const handleSizeChange = (val: number) => { + state.tableParams.pageSize = val; + handleQuery(); +}; + +// 鏀瑰彉椤电爜搴忓彿 +const handleCurrentChange = (val: number) => { + state.tableParams.page = val; + handleQuery(); +}; + +const shortcuts = [ + { + text: '浠婂ぉ', + value: new Date(), + }, + { + text: '鏄ㄥぉ', + value: () => { + const date = new Date(); + date.setTime(date.getTime() - 3600 * 1000 * 24); + return date; + }, + }, + { + text: '涓婂懆', + value: () => { + const date = new Date(); + date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); + return date; + }, + }, +]; +</script> + +<style lang="scss" scoped> +.el-popper { + max-width: 60%; +} +</style> diff --git a/Web/src/views/system/log/exlog/index.vue b/Web/src/views/system/log/exlog/index.vue new file mode 100644 index 0000000..0349115 --- /dev/null +++ b/Web/src/views/system/log/exlog/index.vue @@ -0,0 +1,279 @@ +<template> + <div class="sys-exlog-container" v-loading="state.loading"> + <el-card shadow="hover" :body-style="{ paddingBottom: '0' }"> + <el-form :model="state.queryParams" ref="queryForm" :inline="true"> + <el-form-item label="寮�濮嬫椂闂�"> + <el-date-picker v-model="state.queryParams.startTime" type="datetime" placeholder="寮�濮嬫椂闂�" value-format="YYYY-MM-DD HH:mm:ss" :shortcuts="shortcuts" /> + </el-form-item> + <el-form-item label="缁撴潫鏃堕棿"> + <el-date-picker v-model="state.queryParams.endTime" type="datetime" placeholder="缁撴潫鏃堕棿" value-format="YYYY-MM-DD HH:mm:ss" :shortcuts="shortcuts" /> + </el-form-item> + <el-form-item label="妯″潡鍚嶇О"> + <el-input v-model="state.queryParams.controllerName" placeholder="妯″潡鍚嶇О" clearable /> + </el-form-item> + <el-form-item label="鏂规硶鍚嶇О"> + <el-input v-model="state.queryParams.actionName" placeholder="鏂规硶鍚嶇О" clearable /> + </el-form-item> + <el-form-item label="璐﹀彿鍚嶇О"> + <el-input v-model="state.queryParams.account" placeholder="璐﹀彿鍚嶇О" clearable /> + </el-form-item> + <el-form-item label="鐘舵��"> + <el-select v-model="state.queryParams.status" placeholder="鐘舵��" clearable> + <el-option label="鎴愬姛" :value="200" /> + <el-option label="澶辫触" :value="400" /> + </el-select> + </el-form-item> + <el-form-item label="鑰楁椂"> + <el-input v-model="state.queryParams.elapsed" placeholder="鑰楁椂>?MS" clearable /> + </el-form-item> + <el-form-item label="IP鍦板潃"> + <el-input v-model="state.queryParams.remoteIp" placeholder="IP鍦板潃" clearable /> + </el-form-item> + <el-form-item> + <el-button-group> + <el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysExlog:page'"> 鏌ヨ </el-button> + <el-button icon="ele-Refresh" @click="resetQuery"> 閲嶇疆 </el-button> + </el-button-group> + </el-form-item> + <el-form-item> + <el-button icon="ele-DeleteFilled" type="danger" @click="clearLog" v-auth="'sysExlog:clear'"> 娓呯┖ </el-button> + <el-button icon="ele-FolderOpened" @click="exportLog" v-auth="'sysExlog:export'"> 瀵煎嚭 </el-button> + </el-form-item> + </el-form> + </el-card> + + <el-card class="full-table" shadow="hover" style="margin-top: 5px"> + <el-table :data="state.logData" @sort-change="sortChange" style="width: 100%" border :row-class-name="tableRowClassName"> + <el-table-column type="index" label="搴忓彿" width="55" align="center" /> + <el-table-column prop="controllerName" label="妯″潡鍚嶇О" width="100" header-align="center" show-overflow-tooltip /> + <el-table-column prop="displayTitle" label="鏄剧ず鍚嶇О" width="150" header-align="center" show-overflow-tooltip /> + <el-table-column prop="actionName" label="鏂规硶鍚嶇О" width="100" header-align="center" show-overflow-tooltip /> + <el-table-column prop="httpMethod" label="璇锋眰鏂瑰紡" width="90" align="center" show-overflow-tooltip /> + <el-table-column prop="requestUrl" label="璇锋眰鍦板潃" width="300" header-align="center" show-overflow-tooltip /> + <!-- <el-table-column prop="requestParam" label="璇锋眰鍙傛暟" show-overflow-tooltip /> + <el-table-column prop="returnResult" label="杩斿洖缁撴灉" show-overflow-tooltip /> --> + <el-table-column prop="logLevel" label="绾у埆" width="70" align="center" show-overflow-tooltip> + <template #default="scope"> + <el-tag v-if="scope.row.logLevel === 1">璋冭瘯</el-tag> + <el-tag v-else-if="scope.row.logLevel === 2">娑堟伅</el-tag> + <el-tag v-else-if="scope.row.logLevel === 3">璀﹀憡</el-tag> + <el-tag v-else-if="scope.row.logLevel === 4">閿欒</el-tag> + <el-tag v-else>鍏朵粬</el-tag> + </template> + </el-table-column> + <el-table-column prop="eventId" label="浜嬩欢Id" width="70" align="center" show-overflow-tooltip /> + <el-table-column prop="threadId" label="绾跨▼Id" sortable="custom" width="90" align="center" show-overflow-tooltip /> + <el-table-column prop="traceId" label="璇锋眰璺熻釜Id" width="150" header-align="center" sortable="custom" show-overflow-tooltip /> + <el-table-column prop="account" label="璐﹀彿鍚嶇О" width="100" align="center" show-overflow-tooltip /> + <el-table-column prop="realName" label="鐪熷疄濮撳悕" width="100" align="center" show-overflow-tooltip /> + <el-table-column prop="remoteIp" label="IP鍦板潃" width="120" align="center" show-overflow-tooltip /> + <el-table-column prop="location" label="鐧诲綍鍦扮偣" width="150" align="center" show-overflow-tooltip /> + <el-table-column prop="longitude" label="缁忓害" min-width="100" align="center" show-overflow-tooltip /> + <el-table-column prop="latitude" label="绾害" min-width="100" align="center" show-overflow-tooltip /> + <el-table-column prop="browser" label="娴忚鍣�" width="160" align="center" show-overflow-tooltip /> + <el-table-column prop="os" label="鎿嶄綔绯荤粺" width="120" align="center" show-overflow-tooltip /> + <el-table-column prop="status" label="鐘舵��" width="70" align="center" show-overflow-tooltip> + <template #default="scope"> + <el-tag type="success" v-if="scope.row.status === '200'">鎴愬姛</el-tag> + <el-tag type="danger" v-else>澶辫触</el-tag> + </template> + </el-table-column> + <el-table-column prop="elapsed" label="鑰楁椂(ms)" width="90" align="center" show-overflow-tooltip /> + <el-table-column prop="exception" label="寮傚父瀵硅薄" width="150" header-align="center" show-overflow-tooltip /> + <!-- <el-table-column prop="message" label="鏃ュ織娑堟伅" width="160" fixed="right" show-overflow-tooltip /> --> + <el-table-column prop="logDateTime" label="鏃ュ織鏃堕棿" width="160" align="center" fixed="right" show-overflow-tooltip /> + <el-table-column label="鎿嶄綔" width="80" align="center" fixed="right" show-overflow-tooltip> + <template #default="scope"> + <el-button icon="ele-InfoFilled" size="small" text type="primary" @click="viewDetail(scope.row)" v-auth="'sysOplog:page'">璇︽儏 </el-button> + </template> + </el-table-column> + </el-table> + <el-pagination + v-model:currentPage="state.tableParams.page" + v-model:page-size="state.tableParams.pageSize" + :total="state.tableParams.total" + :page-sizes="[10, 20, 50, 100]" + size="small" + background + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + layout="total, sizes, prev, pager, next, jumper" + /> + </el-card> + <el-dialog v-model="state.dialogVisible" draggable fullscreen> + <template #header> + <div style="color: #fff"> + <el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Document /> </el-icon> + <span> 鏃ュ織璇︽儏 </span> + </div> + </template> + <pre v-loading="state.loadingDetail">{{ state.content }}</pre> + </el-dialog> + </div> +</template> + +<script lang="ts" setup name="sysExLog"> +import { onMounted, reactive } from 'vue'; +import { ElMessage } from 'element-plus'; +import { downloadByData, getFileName } from '/@/utils/download'; + +import { getAPI } from '/@/utils/axios-utils'; +import { SysLogExApi } from '/@/api-services/api'; +import { SysLogEx } from '/@/api-services/models'; + +const state = reactive({ + loading: false, + loadingDetail: false, + queryParams: { + startTime: undefined, + endTime: undefined, + status: undefined, + controllerName: undefined, + actionName: undefined, + account: undefined, + elapsed: undefined, + remoteIp: undefined, + }, + tableParams: { + page: 1, + pageSize: 20, + field: 'createTime', // 榛樿鐨勬帓搴忓瓧娈� + order: 'descending', // 鎺掑簭鏂瑰悜 + descStr: 'descending', // 闄嶅簭鎺掑簭鐨勫叧閿瓧绗� + total: 0 as any, + }, + logData: [] as Array<SysLogEx>, + dialogVisible: false, + content: '', +}); + +onMounted(async () => { + handleQuery(); +}); + +// 鏌ヨ鎿嶄綔 +const handleQuery = async () => { + if (state.queryParams.startTime == null) state.queryParams.startTime = undefined; + if (state.queryParams.endTime == null) state.queryParams.endTime = undefined; + if (state.queryParams.status == null) state.queryParams.status = undefined; + if (state.queryParams.controllerName == null) state.queryParams.controllerName = undefined; + if (state.queryParams.actionName == null) state.queryParams.actionName = undefined; + if (state.queryParams.account == null) state.queryParams.account = undefined; + if (state.queryParams.elapsed == null) state.queryParams.elapsed = undefined; + if (state.queryParams.remoteIp == null) state.queryParams.remoteIp = undefined; + + state.loading = true; + let params = Object.assign(state.queryParams, state.tableParams); + var res = await getAPI(SysLogExApi).apiSysLogExPagePost(params); + state.logData = res.data.result?.items ?? []; + state.tableParams.total = res.data.result?.total; + state.loading = false; +}; + +// 閲嶇疆鎿嶄綔 +const resetQuery = () => { + state.queryParams.startTime = undefined; + state.queryParams.endTime = undefined; + state.queryParams.status = undefined; + state.queryParams.controllerName = undefined; + state.queryParams.actionName = undefined; + state.queryParams.account = undefined; + state.queryParams.elapsed = undefined; + state.queryParams.remoteIp = undefined; + handleQuery(); +}; + +// 娓呯┖鏃ュ織 +const clearLog = async () => { + state.loading = true; + await getAPI(SysLogExApi).apiSysLogExClearPost(); + state.loading = false; + + ElMessage.success('娓呯┖鎴愬姛'); + handleQuery(); +}; + +// 瀵煎嚭鏃ュ織 +const exportLog = async () => { + state.loading = true; + var res = await getAPI(SysLogExApi).apiSysLogExExportPost(state.queryParams, { responseType: 'blob' }); + state.loading = false; + + var fileName = getFileName(res.headers); + downloadByData(res.data as any, fileName); +}; + +// 鏀瑰彉椤甸潰瀹归噺 +const handleSizeChange = (val: number) => { + state.tableParams.pageSize = val; + handleQuery(); +}; + +// 鏀瑰彉椤电爜搴忓彿 +const handleCurrentChange = (val: number) => { + state.tableParams.page = val; + handleQuery(); +}; + +// 鏌ョ湅璇︽儏 +const viewDetail = async (row: any) => { + state.content = ''; + state.dialogVisible = true; + state.loadingDetail = true; + var res = await getAPI(SysLogExApi).apiSysLogExDetailIdGet(row.id); + row.message = res.data.result?.message ?? ''; + state.content = row.message; + state.loadingDetail = false; +}; + +// 璁剧疆琛岄鑹� +const tableRowClassName = (row: any) => { + return row.row.exception != null ? 'warning-row' : ''; +}; + +const shortcuts = [ + { + text: '浠婂ぉ', + value: new Date(), + }, + { + text: '鏄ㄥぉ', + value: () => { + const date = new Date(); + date.setTime(date.getTime() - 3600 * 1000 * 24); + return date; + }, + }, + { + text: '涓婂懆', + value: () => { + const date = new Date(); + date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); + return date; + }, + }, +]; + +// 鍒楁帓搴� +const sortChange = (column: any) => { + state.tableParams.field = column.prop; + state.tableParams.order = column.order; + handleQuery(); +}; +</script> + +<style lang="scss" scoped> +.el-popper { + max-width: 60%; +} +pre { + white-space: break-spaces; + line-height: 20px; +} +.el-table .warning-row { + --el-table-tr-bg-color: var(--el-color-warning-light-9); +} +.el-table .success-row { + --el-table-tr-bg-color: var(--el-color-success-light-9); +} +</style> diff --git a/Web/src/views/system/log/oplog/index.vue b/Web/src/views/system/log/oplog/index.vue new file mode 100644 index 0000000..799bce0 --- /dev/null +++ b/Web/src/views/system/log/oplog/index.vue @@ -0,0 +1,270 @@ +<template> + <div class="sys-oplog-container" v-loading="state.loading"> + <el-card shadow="hover" :body-style="{ paddingBottom: '0' }"> + <el-form :model="state.queryParams" ref="queryForm" :inline="true"> + <el-form-item label="寮�濮嬫椂闂�"> + <el-date-picker v-model="state.queryParams.startTime" type="datetime" placeholder="寮�濮嬫椂闂�" value-format="YYYY-MM-DD HH:mm:ss" :shortcuts="shortcuts" /> + </el-form-item> + <el-form-item label="缁撴潫鏃堕棿"> + <el-date-picker v-model="state.queryParams.endTime" type="datetime" placeholder="缁撴潫鏃堕棿" value-format="YYYY-MM-DD HH:mm:ss" :shortcuts="shortcuts" /> + </el-form-item> + <el-form-item label="妯″潡鍚嶇О"> + <el-input v-model="state.queryParams.controllerName" placeholder="妯″潡鍚嶇О" clearable /> + </el-form-item> + <el-form-item label="鏂规硶鍚嶇О"> + <el-input v-model="state.queryParams.actionName" placeholder="鏂规硶鍚嶇О" clearable /> + </el-form-item> + <el-form-item label="璐﹀彿鍚嶇О"> + <el-input v-model="state.queryParams.account" placeholder="璐﹀彿鍚嶇О" clearable /> + </el-form-item> + <el-form-item label="鑰楁椂"> + <el-input v-model="state.queryParams.elapsed" placeholder="鑰楁椂>?MS" clearable /> + </el-form-item> + <el-form-item label="IP鍦板潃"> + <el-input v-model="state.queryParams.remoteIp" placeholder="IP鍦板潃" clearable /> + </el-form-item> + <el-form-item> + <el-button-group> + <el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysOplog:page'"> 鏌ヨ </el-button> + <el-button icon="ele-Refresh" @click="resetQuery"> 閲嶇疆 </el-button> + </el-button-group> + </el-form-item> + <el-form-item> + <el-button icon="ele-DeleteFilled" type="danger" @click="clearLog" v-auth="'sysOplog:clear'"> 娓呯┖ </el-button> + <el-button icon="ele-FolderOpened" @click="exportLog" v-auth="'sysOplog:export'"> 瀵煎嚭 </el-button> + </el-form-item> + </el-form> + </el-card> + + <el-card class="full-table" shadow="hover" style="margin-top: 5px"> + <el-table :data="state.logData" @sort-change="sortChange" style="width: 100%" border :row-class-name="tableRowClassName"> + <el-table-column type="index" label="搴忓彿" width="55" align="center" /> + <el-table-column prop="controllerName" label="妯″潡鍚嶇О" min-width="120" header-align="center" show-overflow-tooltip /> + <el-table-column prop="displayTitle" label="鏄剧ず鍚嶇О" width="170" header-align="center" show-overflow-tooltip /> + <el-table-column prop="actionName" label="鏂规硶鍚嶇О" width="150" header-align="center" show-overflow-tooltip /> + <el-table-column prop="httpMethod" label="璇锋眰鏂瑰紡" width="90" align="center" show-overflow-tooltip /> + <el-table-column prop="requestUrl" label="璇锋眰鍦板潃" width="300" header-align="center" show-overflow-tooltip /> + <!-- <el-table-column prop="requestParam" label="璇锋眰鍙傛暟" show-overflow-tooltip /> + <el-table-column prop="returnResult" label="杩斿洖缁撴灉" show-overflow-tooltip /> --> + <el-table-column prop="logLevel" label="绾у埆" width="70" align="center" show-overflow-tooltip> + <template #default="scope"> + <el-tag v-if="scope.row.logLevel === 1">璋冭瘯</el-tag> + <el-tag v-else-if="scope.row.logLevel === 2">娑堟伅</el-tag> + <el-tag v-else-if="scope.row.logLevel === 3">璀﹀憡</el-tag> + <el-tag v-else-if="scope.row.logLevel === 4">閿欒</el-tag> + <el-tag v-else>鍏朵粬</el-tag> + </template> + </el-table-column> + <el-table-column prop="eventId" label="浜嬩欢Id" width="70" align="center" show-overflow-tooltip /> + <el-table-column prop="threadId" label="绾跨▼Id" sortable="custom" width="90" align="center" show-overflow-tooltip /> + <el-table-column prop="traceId" label="璇锋眰璺熻釜Id" width="150" header-align="center" sortable="custom" show-overflow-tooltip /> + <el-table-column prop="account" label="璐﹀彿鍚嶇О" width="100" align="center" show-overflow-tooltip /> + <el-table-column prop="realName" label="鐪熷疄濮撳悕" width="100" align="center" show-overflow-tooltip /> + <el-table-column prop="remoteIp" label="IP鍦板潃" min-width="120" align="center" show-overflow-tooltip /> + <el-table-column prop="location" label="鐧诲綍鍦扮偣" min-width="150" align="center" show-overflow-tooltip /> + <el-table-column prop="longitude" label="缁忓害" min-width="100" align="center" show-overflow-tooltip /> + <el-table-column prop="latitude" label="绾害" min-width="100" align="center" show-overflow-tooltip /> + <el-table-column prop="browser" label="娴忚鍣�" min-width="150" align="center" show-overflow-tooltip /> + <el-table-column prop="os" label="鎿嶄綔绯荤粺" width="120" align="center" show-overflow-tooltip /> + <el-table-column prop="status" label="鐘舵��" width="70" align="center" show-overflow-tooltip> + <template #default="scope"> + <el-tag type="success" v-if="scope.row.status === '200'">鎴愬姛</el-tag> + <el-tag type="danger" v-else>澶辫触</el-tag> + </template> + </el-table-column> + <el-table-column prop="elapsed" label="鑰楁椂(ms)" width="90" align="center" show-overflow-tooltip /> + <!-- <el-table-column prop="exception" label="寮傚父瀵硅薄" width="150" show-overflow-tooltip /> --> + <!-- <el-table-column prop="message" label="鏃ュ織娑堟伅" width="160" fixed="right" show-overflow-tooltip /> --> + <el-table-column prop="logDateTime" label="鏃ュ織鏃堕棿" width="160" align="center" fixed="right" show-overflow-tooltip /> + <el-table-column label="鎿嶄綔" width="80" align="center" fixed="right" show-overflow-tooltip> + <template #default="scope"> + <el-button icon="ele-InfoFilled" size="small" text type="primary" @click="viewDetail(scope.row)" v-auth="'sysOplog:page'">璇︽儏 </el-button> + </template> + </el-table-column> + </el-table> + <el-pagination + v-model:currentPage="state.tableParams.page" + v-model:page-size="state.tableParams.pageSize" + :total="state.tableParams.total" + :page-sizes="[10, 20, 50, 100]" + size="small" + background + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + layout="total, sizes, prev, pager, next, jumper" + /> + </el-card> + <el-dialog v-model="state.dialogVisible" draggable fullscreen> + <template #header> + <div style="color: #fff"> + <el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Document /> </el-icon> + <span> 鏃ュ織璇︽儏 </span> + </div> + </template> + <pre v-loading="state.loadingDetail">{{ state.content }}</pre> + </el-dialog> + </div> +</template> + +<script lang="ts" setup name="sysOpLog"> +import { onMounted, reactive } from 'vue'; +import { ElMessage } from 'element-plus'; +import { downloadByData, getFileName } from '/@/utils/download'; + +import { getAPI } from '/@/utils/axios-utils'; +import { SysLogOpApi } from '/@/api-services/api'; +import { SysLogOp } from '/@/api-services/models'; + +const state = reactive({ + loading: false, + loadingDetail: false, + queryParams: { + startTime: undefined, + endTime: undefined, + controllerName: undefined, + actionName: undefined, + account: undefined, + elapsed: undefined, + remoteIp: undefined, + }, + tableParams: { + page: 1, + pageSize: 20, + field: 'createTime', // 榛樿鐨勬帓搴忓瓧娈� + order: 'descending', // 鎺掑簭鏂瑰悜 + descStr: 'descending', // 闄嶅簭鎺掑簭鐨勫叧閿瓧绗� + total: 0 as any, + }, + logData: [] as Array<SysLogOp>, + dialogVisible: false, + content: '', +}); + +onMounted(async () => { + handleQuery(); +}); + +// 鏌ヨ鎿嶄綔 +const handleQuery = async () => { + if (state.queryParams.startTime == null) state.queryParams.startTime = undefined; + if (state.queryParams.endTime == null) state.queryParams.endTime = undefined; + if (state.queryParams.controllerName == null) state.queryParams.controllerName = undefined; + if (state.queryParams.actionName == null) state.queryParams.actionName = undefined; + if (state.queryParams.account == null) state.queryParams.account = undefined; + if (state.queryParams.elapsed == null) state.queryParams.elapsed = undefined; + if (state.queryParams.remoteIp == null) state.queryParams.remoteIp = undefined; + + state.loading = true; + let params = Object.assign(state.queryParams, state.tableParams); + var res = await getAPI(SysLogOpApi).apiSysLogOpPagePost(params); + state.logData = res.data.result?.items ?? []; + state.tableParams.total = res.data.result?.total; + state.loading = false; +}; + +// 閲嶇疆鎿嶄綔 +const resetQuery = () => { + state.queryParams.startTime = undefined; + state.queryParams.endTime = undefined; + state.queryParams.controllerName = undefined; + state.queryParams.actionName = undefined; + state.queryParams.account = undefined; + state.queryParams.elapsed = undefined; + state.queryParams.remoteIp = undefined; + handleQuery(); +}; + +// 娓呯┖鏃ュ織 +const clearLog = async () => { + state.loading = true; + await getAPI(SysLogOpApi).apiSysLogOpClearPost(); + state.loading = false; + + ElMessage.success('娓呯┖鎴愬姛'); + handleQuery(); +}; + +// 瀵煎嚭鏃ュ織 +const exportLog = async () => { + state.loading = true; + var res = await getAPI(SysLogOpApi).apiSysLogOpExportPost(state.queryParams, { responseType: 'blob' }); + state.loading = false; + + var fileName = getFileName(res.headers); + downloadByData(res.data as any, fileName); +}; + +// 鏀瑰彉椤甸潰瀹归噺 +const handleSizeChange = (val: number) => { + state.tableParams.pageSize = val; + handleQuery(); +}; + +// 鏀瑰彉椤电爜搴忓彿 +const handleCurrentChange = (val: number) => { + state.tableParams.page = val; + handleQuery(); +}; + +// 鏌ョ湅璇︽儏 +const viewDetail = async (row: any) => { + state.content = ''; + state.dialogVisible = true; + state.loadingDetail = true; + var res = await getAPI(SysLogOpApi).apiSysLogOpDetailIdGet(row.id); + row.message = res.data.result?.message ?? ''; + state.content = row.message; + state.loadingDetail = false; +}; + +// 璁剧疆琛岄鑹� +const tableRowClassName = (row: any) => { + return row.row.exception != null ? 'warning-row' : ''; +}; + +const shortcuts = [ + { + text: '浠婂ぉ', + value: new Date(), + }, + { + text: '鏄ㄥぉ', + value: () => { + const date = new Date(); + date.setTime(date.getTime() - 3600 * 1000 * 24); + return date; + }, + }, + { + text: '涓婂懆', + value: () => { + const date = new Date(); + date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); + return date; + }, + }, +]; + +// 鍒楁帓搴� +const sortChange = (column: any) => { + state.tableParams.field = column.prop; + state.tableParams.order = column.order; + handleQuery(); +}; +</script> + +<style lang="scss" scoped> +.el-popper { + max-width: 60%; +} +pre { + white-space: break-spaces; + line-height: 20px; +} +.el-table .warning-row { + --el-table-tr-bg-color: var(--el-color-warning-light-9); +} +.el-table .success-row { + --el-table-tr-bg-color: var(--el-color-success-light-9); +} +</style> diff --git a/Web/src/views/system/log/vislog/index.vue b/Web/src/views/system/log/vislog/index.vue new file mode 100644 index 0000000..28f0c1a --- /dev/null +++ b/Web/src/views/system/log/vislog/index.vue @@ -0,0 +1,183 @@ +<template> + <div class="sys-vislog-container"> + <el-card shadow="hover" :body-style="{ paddingBottom: '0' }"> + <el-form :model="state.queryParams" ref="queryForm" :inline="true"> + <el-form-item label="寮�濮嬫椂闂�"> + <el-date-picker v-model="state.queryParams.startTime" type="datetime" placeholder="寮�濮嬫椂闂�" value-format="YYYY-MM-DD HH:mm:ss" :shortcuts="shortcuts" /> + </el-form-item> + <el-form-item label="缁撴潫鏃堕棿" prop="code"> + <el-date-picker v-model="state.queryParams.endTime" type="datetime" placeholder="缁撴潫鏃堕棿" value-format="YYYY-MM-DD HH:mm:ss" :shortcuts="shortcuts" /> + </el-form-item> + <el-form-item label="鏂规硶鍚嶇О"> + <el-input v-model="state.queryParams.actionName" placeholder="鏂规硶鍚嶇О" clearable /> + </el-form-item> + <el-form-item label="璐﹀彿鍚嶇О"> + <el-input v-model="state.queryParams.account" placeholder="璐﹀彿鍚嶇О" clearable /> + </el-form-item> + <el-form-item label="鐘舵��"> + <el-select v-model="state.queryParams.status" placeholder="鐘舵��" clearable> + <el-option label="鎴愬姛" :value="200" /> + <el-option label="澶辫触" :value="400" /> + </el-select> + </el-form-item> + <el-form-item label="鑰楁椂"> + <el-input v-model="state.queryParams.elapsed" placeholder="鑰楁椂>?MS" clearable /> + </el-form-item> + <el-form-item label="IP鍦板潃"> + <el-input v-model="state.queryParams.remoteIp" placeholder="IP鍦板潃" clearable /> + </el-form-item> + <el-form-item> + <el-button-group> + <el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysVislog:page'"> 鏌ヨ </el-button> + <el-button icon="ele-Refresh" @click="resetQuery"> 閲嶇疆 </el-button> + </el-button-group> + </el-form-item> + <el-form-item> + <el-button icon="ele-DeleteFilled" type="danger" @click="clearLog" v-auth="'sysVislog:clear'" disabled> 娓呯┖ </el-button> + </el-form-item> + </el-form> + </el-card> + + <el-card class="full-table" shadow="hover" style="margin-top: 5px"> + <el-table :data="state.logData" style="width: 100%" v-loading="state.loading" border> + <el-table-column type="index" label="搴忓彿" width="55" align="center" /> + <el-table-column prop="displayTitle" label="鏄剧ず鍚嶇О" width="150" align="center" show-overflow-tooltip /> + <el-table-column prop="actionName" label="鏂规硶鍚嶇О" width="150" header-align="center" show-overflow-tooltip /> + <el-table-column prop="account" label="璐﹀彿鍚嶇О" width="100" align="center" show-overflow-tooltip /> + <el-table-column prop="realName" label="鐪熷疄濮撳悕" width="100" align="center" show-overflow-tooltip /> + <el-table-column prop="remoteIp" label="IP鍦板潃" min-width="120" align="center" show-overflow-tooltip /> + <el-table-column prop="location" label="鐧诲綍鍦扮偣" min-width="150" align="center" show-overflow-tooltip /> + <el-table-column prop="longitude" label="缁忓害" min-width="100" align="center" show-overflow-tooltip /> + <el-table-column prop="latitude" label="绾害" min-width="100" align="center" show-overflow-tooltip /> + <el-table-column prop="browser" label="娴忚鍣�" min-width="150" align="center" show-overflow-tooltip /> + <el-table-column prop="os" label="鎿嶄綔绯荤粺" width="120" align="center" show-overflow-tooltip /> + <el-table-column prop="status" label="鐘舵��" width="70" align="center" show-overflow-tooltip> + <template #default="scope"> + <el-tag type="success" v-if="scope.row.status === '200'">鎴愬姛</el-tag> + <el-tag type="danger" v-else>澶辫触</el-tag> + </template> + </el-table-column> + <el-table-column prop="elapsed" label="鑰楁椂(ms)" width="90" align="center" show-overflow-tooltip /> + <el-table-column prop="logDateTime" label="鏃ュ織鏃堕棿" width="160" align="center" fixed="right" show-overflow-tooltip /> + </el-table> + <el-pagination + v-model:currentPage="state.tableParams.page" + v-model:page-size="state.tableParams.pageSize" + :total="state.tableParams.total" + :page-sizes="[10, 20, 50, 100]" + size="small" + background + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + layout="total, sizes, prev, pager, next, jumper" + /> + </el-card> + </div> +</template> + +<script lang="ts" setup name="sysVisLog"> +import { onMounted, reactive } from 'vue'; +import { ElMessage } from 'element-plus'; + +import { getAPI } from '/@/utils/axios-utils'; +import { SysLogVisApi } from '/@/api-services/api'; +import { SysLogVis } from '/@/api-services/models'; + +const state = reactive({ + loading: false, + queryParams: { + startTime: undefined, + endTime: undefined, + status: undefined, + actionName: undefined, + account: undefined, + elapsed: undefined, + remoteIp: undefined, + }, + tableParams: { + page: 1, + pageSize: 20, + total: 0 as any, + }, + logData: [] as Array<SysLogVis>, +}); + +onMounted(async () => { + handleQuery(); +}); + +// 鏌ヨ鎿嶄綔 +const handleQuery = async () => { + if (state.queryParams.startTime == null) state.queryParams.startTime = undefined; + if (state.queryParams.endTime == null) state.queryParams.endTime = undefined; + if (state.queryParams.status == null) state.queryParams.status = undefined; + if (state.queryParams.actionName == null) state.queryParams.actionName = undefined; + if (state.queryParams.account == null) state.queryParams.account = undefined; + if (state.queryParams.elapsed == null) state.queryParams.elapsed = undefined; + if (state.queryParams.remoteIp == null) state.queryParams.remoteIp = undefined; + + state.loading = true; + let params = Object.assign(state.queryParams, state.tableParams); + var res = await getAPI(SysLogVisApi).apiSysLogVisPagePost(params); + state.logData = res.data.result?.items ?? []; + state.tableParams.total = res.data.result?.total; + state.loading = false; +}; + +// 閲嶇疆鎿嶄綔 +const resetQuery = () => { + state.queryParams.startTime = undefined; + state.queryParams.endTime = undefined; + state.queryParams.status = undefined; + state.queryParams.actionName = undefined; + state.queryParams.account = undefined; + state.queryParams.elapsed = undefined; + state.queryParams.remoteIp = undefined; + handleQuery(); +}; + +// 娓呯┖鏃ュ織 +const clearLog = async () => { + state.loading = true; + await getAPI(SysLogVisApi).apiSysLogVisClearPost(); + state.loading = false; + + ElMessage.success('娓呯┖鎴愬姛'); + handleQuery(); +}; + +// 鏀瑰彉椤甸潰瀹归噺 +const handleSizeChange = (val: number) => { + state.tableParams.pageSize = val; + handleQuery(); +}; + +// 鏀瑰彉椤电爜搴忓彿 +const handleCurrentChange = (val: number) => { + state.tableParams.page = val; + handleQuery(); +}; + +const shortcuts = [ + { + text: '浠婂ぉ', + value: new Date(), + }, + { + text: '鏄ㄥぉ', + value: () => { + const date = new Date(); + date.setTime(date.getTime() - 3600 * 1000 * 24); + return date; + }, + }, + { + text: '涓婂懆', + value: () => { + const date = new Date(); + date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); + return date; + }, + }, +]; +</script> -- Gitblit v1.8.0