😎优化请求日志页面

This commit is contained in:
zuohuaijun 2025-08-28 11:09:59 +08:00
parent 625af173ea
commit 1d62e2f6ce
3 changed files with 74 additions and 51 deletions

View File

@ -81,7 +81,7 @@
"vue-router": "^4.5.1", "vue-router": "^4.5.1",
"vue-signature-pad": "^3.0.2", "vue-signature-pad": "^3.0.2",
"vue3-tree-org": "^4.2.2", "vue3-tree-org": "^4.2.2",
"vxe-pc-ui": "^4.9.5", "vxe-pc-ui": "^4.9.6",
"vxe-table": "^4.16.1", "vxe-table": "^4.16.1",
"xe-utils": "^3.7.8", "xe-utils": "^3.7.8",
"xlsx-js-style": "^1.2.0" "xlsx-js-style": "^1.2.0"
@ -96,7 +96,7 @@
"@typescript-eslint/eslint-plugin": "^8.41.0", "@typescript-eslint/eslint-plugin": "^8.41.0",
"@typescript-eslint/parser": "^8.41.0", "@typescript-eslint/parser": "^8.41.0",
"@vitejs/plugin-vue": "^6.0.1", "@vitejs/plugin-vue": "^6.0.1",
"@vitejs/plugin-vue-jsx": "^5.1.0", "@vitejs/plugin-vue-jsx": "^5.1.1",
"@vue/compiler-sfc": "^3.5.20", "@vue/compiler-sfc": "^3.5.20",
"cli-progress": "^3.12.0", "cli-progress": "^3.12.0",
"code-inspector-plugin": "^1.2.6", "code-inspector-plugin": "^1.2.6",

View File

@ -8,42 +8,60 @@
</template> </template>
<el-scrollbar height="calc(100vh - 250px)"> <el-scrollbar height="calc(100vh - 250px)">
<el-form :model="data" label-width="auto"> <el-form :model="data" label-width="auto">
<el-tabs v-model="state.selectedTabName"> <el-descriptions :column="3" :label-width="80" border>
<el-tab-pane label="请求信息"> <el-descriptions-item label="请求地址" :width="380">
<el-form-item label="客户端"> {{ data.requestUrl?.indexOf('?') == -1 ? data.requestUrl : data.requestUrl?.substring(0, data.requestUrl.indexOf('?')) }}
{{ data.httpClientName }} </el-descriptions-item>
</el-form-item> <el-descriptions-item :span="2" label="状态码">
<el-form-item label="接口描述"> {{ data.statusCode }}
{{ data.httpApiDesc }} </el-descriptions-item>
</el-form-item> <el-descriptions-item label="客户端">
<el-form-item label="请求地址"> {{ data.httpClientName }}
{{ data.requestUrl?.indexOf('?') == -1 ? data.requestUrl : data.requestUrl?.substring(0, data.requestUrl.indexOf('?')) }} </el-descriptions-item>
</el-form-item> <el-descriptions-item :span="2" label="接口描述">
<el-form-item label="Query参数" v-if="data.requestUrl?.indexOf('?') != -1"> {{ data.httpApiDesc }}
<el-row v-for="(value, key, index) in queryObject"> </el-descriptions-item>
<span class="query-key">{{ key }}</span> = <span class="query-value">{{ value }}</span <el-descriptions-item label="开始时间">
>& {{ data.startTime }}
</el-row> </el-descriptions-item>
</el-form-item> <el-descriptions-item label="结束时间">
<el-form-item label="请求头"> {{ data.endTime }}
<vue-json-pretty :data="data.requestHeaders" showLength showIcon showLineNumber showSelectController /> </el-descriptions-item>
</el-form-item> <el-descriptions-item label="耗时"> {{ data.elapsed }} ms </el-descriptions-item>
<el-form-item label="请求体"> <el-descriptions-item label="创建人">
<vue-json-pretty :data="data.requestBody" showLength showIcon showLineNumber showSelectController /> {{ data.createUserName }}
</el-form-item> </el-descriptions-item>
</el-tab-pane> <el-descriptions-item :span="2" label="创建时间">
<el-tab-pane label="响应信息"> {{ data.createTime }}
<el-form-item label="响应头"> </el-descriptions-item>
<vue-json-pretty :data="data.responseHeaders" showLength showIcon showLineNumber showSelectController /> <el-descriptions-item :span="3" label="请求头" class-name="row-line">
</el-form-item> <vue-json-pretty :data="data.requestHeaders" showLength showIcon showLineNumber showSelectController />
<el-form-item label="响应体"> </el-descriptions-item>
<vue-json-pretty :data="data.responseBody" showLength showIcon showLineNumber showSelectController /> <el-descriptions-item :span="3" label="请求参数" class-name="row-line" v-if="data.requestUrl?.indexOf('?') != -1">
</el-form-item> <el-row v-for="(value, key, index) in queryObject">
</el-tab-pane> <span class="query-key">{{ key }}</span> = <span class="query-value">{{ value }}</span
<el-tab-pane label="异常信息" v-if="data.exception"> >&
</el-row>
</el-descriptions-item>
<el-descriptions-item :span="3" label="请求体" class-name="row-line">
<vue-json-pretty :data="data.requestBody" showLength showIcon showLineNumber showSelectController />
</el-descriptions-item>
<el-descriptions-item :span="3" label="请求明文" class-name="row-line" v-if="data.requestBodyPlaintext">
<vue-json-pretty :data="data.requestBodyPlaintext" showLength showIcon showLineNumber showSelectController />
</el-descriptions-item>
<el-descriptions-item :span="3" label="响应头" class-name="row-line">
<vue-json-pretty :data="data.responseHeaders" showLength showIcon showLineNumber showSelectController />
</el-descriptions-item>
<el-descriptions-item :span="3" label="响应体" class-name="row-line">
<vue-json-pretty :data="data.responseBody" showLength showIcon showLineNumber showSelectController />
</el-descriptions-item>
<el-descriptions-item :span="3" label="响应明文" class-name="row-line" v-if="data.responseBodyPlaintext">
<vue-json-pretty :data="data.responseBodyPlaintext" showLength showIcon showLineNumber showSelectController />
</el-descriptions-item>
<el-descriptions-item :span="3" label="异常信息" class-name="row-line" v-if="data.exception">
<vue-json-pretty :data="data.exception" showLength showIcon showLineNumber showSelectController /> <vue-json-pretty :data="data.exception" showLength showIcon showLineNumber showSelectController />
</el-tab-pane> </el-descriptions-item>
</el-tabs> </el-descriptions>
</el-form> </el-form>
</el-scrollbar> </el-scrollbar>
<template #footer> <template #footer>
@ -52,27 +70,27 @@
</el-dialog> </el-dialog>
</template> </template>
<!-- 远程请求日志 -->
<script lang="ts" setup> <script lang="ts" setup>
import { ref, reactive, computed } from 'vue'; import { ref, reactive, computed } from 'vue';
import { StringToObj } from '/@/utils/json-utils'; import { StringToObj } from '/@/utils/json-utils';
import { SysLogHttp } from '/@/api-services/system/models'; import { SysLogHttp } from '/@/api-services/system/models';
import VueJsonPretty from 'vue-json-pretty'; import VueJsonPretty from 'vue-json-pretty';
const data = ref<SysLogHttp>({});
const state = reactive({ const state = reactive({
visible: false, visible: false,
selectedTabName: '0',
}); });
const data = ref<SysLogHttp>({});
const openDialog = (row: any) => { const openDialog = (row: any) => {
state.visible = true; state.visible = true;
state.selectedTabName = '0';
Object.assign(data.value, row); Object.assign(data.value, row);
data.value.requestUrl = StringToObj(row.requestUrl); data.value.requestUrl = StringToObj(row.requestUrl);
data.value.requestHeaders = StringToObj(row.requestHeaders); data.value.requestHeaders = StringToObj(row.requestHeaders);
data.value.requestBody = StringToObj(row.requestBody); data.value.requestBody = StringToObj(row.requestBody);
data.value.requestBodyPlaintext = StringToObj(row.requestBodyPlaintext);
data.value.responseHeaders = StringToObj(row.responseHeaders); data.value.responseHeaders = StringToObj(row.responseHeaders);
data.value.responseBody = StringToObj(row.responseBody); data.value.responseBody = StringToObj(row.responseBody);
data.value.responseBodyPlaintext = StringToObj(row.responseBodyPlaintext);
data.value.exception = StringToObj(row.exception); data.value.exception = StringToObj(row.exception);
}; };
@ -90,4 +108,7 @@ defineExpose({
.query-key { .query-key {
color: #d55fde; color: #d55fde;
} }
:deep(td.row-line) {
border-bottom: 1.5px solid #dadadd !important;
}
</style> </style>

View File

@ -3,7 +3,6 @@
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px' }"> <el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px' }">
<scEcharts v-if="echartsOption.series.data" height="200px" :option="echartsOption" @clickData="clickData"></scEcharts> <scEcharts v-if="echartsOption.series.data" height="200px" :option="echartsOption" @clickData="clickData"></scEcharts>
</el-card> </el-card>
<el-card shadow="hover" :body-style="{ padding: '5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }"> <el-card shadow="hover" :body-style="{ padding: '5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" label-width="auto" style="flex: 1 1 0%"> <el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" label-width="auto" style="flex: 1 1 0%">
<el-row :gutter="10"> <el-row :gutter="10">
@ -122,21 +121,23 @@
</div> </div>
</template> </template>
<!-- 请求日志 --> <!-- 远程请求日志 -->
<script lang="ts" setup name="sysLogHttp"> <script lang="ts" setup name="sysLogHttp">
import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { Local } from '/@/utils/storage'; import { Local } from '/@/utils/storage';
import { getAPI } from '/@/utils/axios-utils';
import { useVxeTable } from '/@/hooks/useVxeTableOptionsHook'; import { useVxeTable } from '/@/hooks/useVxeTableOptionsHook';
import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
import { VxeGridInstance, VxeGridListeners, VxeGridPropTypes } from 'vxe-table'; import { VxeGridInstance, VxeGridListeners, VxeGridPropTypes } from 'vxe-table';
import { PageLogHttpInput, PageLogHttpOutput } from '/@/api-services/system/models';
import { SysLogHttpApi } from '/@/api-services/system/api';
import ModifyRecord from '/@/components/table/modifyRecord.vue';
import commonFunction from '/@/utils/commonFunction'; import commonFunction from '/@/utils/commonFunction';
import logDetail from './component/logDetail.vue';
import 'vue-json-pretty/lib/styles.css'; import 'vue-json-pretty/lib/styles.css';
import logDetail from './component/logDetail.vue';
import ModifyRecord from '/@/components/table/modifyRecord.vue';
import { getAPI } from '/@/utils/axios-utils';
import { SysLogHttpApi } from '/@/api-services/system/api';
import { PageLogHttpInput, PageLogHttpOutput } from '/@/api-services/system/models';
const scEcharts = defineAsyncComponent(() => import('/@/components/scEcharts/index.vue')); const scEcharts = defineAsyncComponent(() => import('/@/components/scEcharts/index.vue'));
const commonFun = commonFunction(); const commonFun = commonFunction();
@ -163,11 +164,11 @@ const options = useVxeTable<PageLogHttpOutput>(
// { type: 'checkbox', width: 40, fixed: 'left' }, // { type: 'checkbox', width: 40, fixed: 'left' },
{ field: 'seq', type: 'seq', title: '序号', width: 60, fixed: 'left' }, { field: 'seq', type: 'seq', title: '序号', width: 60, fixed: 'left' },
{ field: 'createTime', title: '创建时间', minWidth: 150, showOverflow: 'tooltip' }, { field: 'createTime', title: '创建时间', minWidth: 150, showOverflow: 'tooltip' },
{ field: 'httpApiDesc', title: '接口描述', minWidth: 150, showOverflow: 'tooltip' },
{ field: 'httpClientName', title: '客户端', minWidth: 110, showOverflow: 'tooltip' }, { field: 'httpClientName', title: '客户端', minWidth: 110, showOverflow: 'tooltip' },
{ field: 'actionName', title: '模块名', minWidth: 110, showOverflow: 'tooltip' }, { field: 'actionName', title: '模块名', minWidth: 110, showOverflow: 'tooltip' },
{ field: 'httpMethod', title: '请求方式', minWidth: 60, showOverflow: 'tooltip' }, { field: 'httpMethod', title: '请求方式', minWidth: 60, showOverflow: 'tooltip' },
{ field: 'isSuccessStatusCode', title: '是否成功', minWidth: 60, showOverflow: 'tooltip', slots: { default: 'row_isSuccessStatusCode' } }, { field: 'isSuccessStatusCode', title: '是否成功', minWidth: 60, showOverflow: 'tooltip', slots: { default: 'row_isSuccessStatusCode' } },
{ field: 'httpApiDesc', title: '接口描述', minWidth: 150, showOverflow: 'tooltip' },
{ field: 'requestUrl', title: '请求地址', minWidth: 150, align: 'left', showOverflow: 'tooltip', slots: { default: 'row_requestUrl' } }, { field: 'requestUrl', title: '请求地址', minWidth: 150, align: 'left', showOverflow: 'tooltip', slots: { default: 'row_requestUrl' } },
{ field: 'requestHeaders', title: '请求头', minWidth: 150, showOverflow: 'tooltip' }, { field: 'requestHeaders', title: '请求头', minWidth: 150, showOverflow: 'tooltip' },
{ field: 'requestBody', title: '请求体', minWidth: 150, showOverflow: 'tooltip', slots: { default: 'row_requestBody' } }, { field: 'requestBody', title: '请求体', minWidth: 150, showOverflow: 'tooltip', slots: { default: 'row_requestBody' } },
@ -316,6 +317,7 @@ const clickData = (e: any) => {
state.queryParams.createTimeRange.push(new Date(endTime)); state.queryParams.createTimeRange.push(new Date(endTime));
xGrid.value?.commitProxy('query'); xGrid.value?.commitProxy('query');
}; };
// //
const getYearDayStatsData = async () => { const getYearDayStatsData = async () => {
let data = [] as any; let data = [] as any;
@ -350,4 +352,4 @@ const gridEvents: VxeGridListeners<PageLogHttpOutput> = {
}; };
</script> </script>
<style lang="scss" scoped></style> <style lang="less" scoped></style>