2 changed files with 713 additions and 0 deletions
@ -0,0 +1,15 @@ |
|||
import { createAPI } from "@/utils/httpRequest.js"; |
|||
|
|||
// ===================================== 接口日志管理 =====================================
|
|||
// 查询接口日志列表
|
|||
export const searchApiLogs = data => createAPI(`/sys/interfaceLog/list`,'post',data) |
|||
|
|||
// 查询接口参数(主表+明细)
|
|||
export const getApiLogParams = data => createAPI(`/sys/interfaceLog/getParams`,'post',data) |
|||
|
|||
// 删除接口日志
|
|||
export const deleteApiLogs = data => createAPI(`/sys/interfaceLog/delete`,'post',data) |
|||
|
|||
// 重试接口
|
|||
export const retryApiLogs = data => createAPI(`/sys/interfaceLog/retry`,'post',data) |
|||
|
|||
@ -0,0 +1,698 @@ |
|||
<template> |
|||
<div class="mod-config"> |
|||
<!-- 条件查询 --> |
|||
<el-card :class="['search-card', { 'collapsed': !searchExpanded }]" shadow="hover"> |
|||
<div slot="header" class="search-header"> |
|||
<div class="header-left"> |
|||
<i class="el-icon-search"></i> |
|||
<span class="header-title">接口日志查询</span> |
|||
</div> |
|||
<div class="header-right"> |
|||
<el-button |
|||
type="text" |
|||
size="small" |
|||
@click="toggleSearchExpand" |
|||
class="collapse-btn"> |
|||
<i :class="searchExpanded ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"></i> |
|||
{{ searchExpanded ? '收起' : '展开' }} |
|||
</el-button> |
|||
</div> |
|||
</div> |
|||
|
|||
<el-form |
|||
:model="searchForm" |
|||
label-width="110px" |
|||
class="search-form" |
|||
@keyup.enter.native="getDataList"> |
|||
|
|||
<!-- 所有查询条件 - 可展开/收起 --> |
|||
<template v-if="searchExpanded"> |
|||
<!-- 第一行 --> |
|||
<el-row :gutter="20"> |
|||
<el-col :span="6"> |
|||
<el-form-item label="接口名称"> |
|||
<el-input |
|||
v-model="searchForm.interfaceName" |
|||
placeholder="请输入接口名称" |
|||
clearable |
|||
prefix-icon="el-icon-document"> |
|||
</el-input> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="6"> |
|||
<el-form-item label="请求ID"> |
|||
<el-input |
|||
v-model="searchForm.requestId" |
|||
placeholder="请输入请求ID" |
|||
clearable |
|||
prefix-icon="el-icon-key"> |
|||
</el-input> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="6"> |
|||
<el-form-item label="关联单据号"> |
|||
<el-input |
|||
v-model="searchForm.reDocumentNo" |
|||
placeholder="请输入关联单据号" |
|||
clearable> |
|||
</el-input> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="6"> |
|||
<el-form-item label="关联单据类型"> |
|||
<el-input |
|||
v-model="searchForm.reDocumentType" |
|||
placeholder="请输入关联单据类型" |
|||
clearable> |
|||
</el-input> |
|||
</el-form-item> |
|||
</el-col> |
|||
</el-row> |
|||
|
|||
<!-- 第二行 --> |
|||
<el-row :gutter="20"> |
|||
<el-col :span="6"> |
|||
<el-form-item label="状态码"> |
|||
<el-input |
|||
v-model="searchForm.statusCode" |
|||
placeholder="请输入状态码" |
|||
clearable> |
|||
</el-input> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="6"> |
|||
<el-form-item label="来源系统"> |
|||
<el-input |
|||
v-model="searchForm.sourceSystem" |
|||
placeholder="请输入来源系统" |
|||
clearable> |
|||
</el-input> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="6"> |
|||
<el-form-item label="目标系统"> |
|||
<el-input |
|||
v-model="searchForm.targetSystem" |
|||
placeholder="请输入目标系统" |
|||
clearable> |
|||
</el-input> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="6"> |
|||
<el-form-item label="是否需要重试"> |
|||
<el-select v-model="searchForm.needRetryFlag" placeholder="请选择" clearable> |
|||
<el-option label="是" :value="1"></el-option> |
|||
<el-option label="否" :value="0"></el-option> |
|||
</el-select> |
|||
</el-form-item> |
|||
</el-col> |
|||
</el-row> |
|||
|
|||
<!-- 第三行 --> |
|||
<el-row :gutter="20"> |
|||
<el-col :span="12"> |
|||
<el-form-item label="创建时间"> |
|||
<el-date-picker |
|||
v-model="searchForm.dateRange" |
|||
type="daterange" |
|||
range-separator="至" |
|||
start-placeholder="开始日期" |
|||
end-placeholder="结束日期" |
|||
value-format="yyyy-MM-dd" |
|||
style="width: 100%"> |
|||
</el-date-picker> |
|||
</el-form-item> |
|||
</el-col> |
|||
</el-row> |
|||
</template> |
|||
|
|||
<!-- 操作按钮区域 --> |
|||
<div class="search-actions"> |
|||
<div class="action-left"> |
|||
<el-button type="primary" @click="getDataList" icon="el-icon-search">查询</el-button> |
|||
<el-button @click="resetSearch" icon="el-icon-refresh-left">重置</el-button> |
|||
</div> |
|||
</div> |
|||
</el-form> |
|||
</el-card> |
|||
|
|||
<!-- 表格操作按钮 --> |
|||
<div class="table-actions"> |
|||
<el-button |
|||
v-if="dataListSelections.length > 0" |
|||
type="danger" |
|||
@click="deleteHandle()" |
|||
icon="el-icon-delete" |
|||
size="small"> |
|||
批量删除 |
|||
</el-button> |
|||
<el-button |
|||
v-if="dataListSelections.length > 0" |
|||
type="success" |
|||
@click="retryHandle()" |
|||
icon="el-icon-refresh" |
|||
size="small"> |
|||
批量重试 |
|||
</el-button> |
|||
</div> |
|||
|
|||
<!-- 数据表格 --> |
|||
<el-table |
|||
:height="tableHeight" |
|||
:data="dataList" |
|||
border |
|||
v-loading="dataListLoading" |
|||
@selection-change="selectionChangeHandle" |
|||
style="width: 100%;"> |
|||
<el-table-column |
|||
type="selection" |
|||
header-align="center" |
|||
align="center" |
|||
width="50"> |
|||
</el-table-column> |
|||
<el-table-column |
|||
prop="id" |
|||
header-align="center" |
|||
align="center" |
|||
label="ID" |
|||
width="80"> |
|||
</el-table-column> |
|||
<el-table-column |
|||
prop="requestId" |
|||
header-align="center" |
|||
align="center" |
|||
label="请求ID" |
|||
width="200"> |
|||
</el-table-column> |
|||
<el-table-column |
|||
prop="interfaceName" |
|||
header-align="center" |
|||
align="center" |
|||
label="接口名称" |
|||
min-width="150"> |
|||
</el-table-column> |
|||
<el-table-column |
|||
prop="reDocumentNo" |
|||
header-align="center" |
|||
align="center" |
|||
label="关联单据号" |
|||
min-width="120"> |
|||
</el-table-column> |
|||
<el-table-column |
|||
prop="reDocumentType" |
|||
header-align="center" |
|||
align="center" |
|||
label="关联单据类型" |
|||
min-width="120"> |
|||
</el-table-column> |
|||
<el-table-column |
|||
prop="statusCode" |
|||
header-align="center" |
|||
align="center" |
|||
label="状态码" |
|||
width="100"> |
|||
<template slot-scope="scope"> |
|||
<el-tag :type="scope.row.statusCode === '200' ? 'success' : 'danger'"> |
|||
{{ scope.row.statusCode }} |
|||
</el-tag> |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column |
|||
prop="message" |
|||
header-align="center" |
|||
align="center" |
|||
label="消息" |
|||
min-width="150" |
|||
show-overflow-tooltip> |
|||
</el-table-column> |
|||
<el-table-column |
|||
prop="sourceSystem" |
|||
header-align="center" |
|||
align="center" |
|||
label="来源系统" |
|||
width="100"> |
|||
</el-table-column> |
|||
<el-table-column |
|||
prop="targetSystem" |
|||
header-align="center" |
|||
align="center" |
|||
label="目标系统" |
|||
width="100"> |
|||
</el-table-column> |
|||
<el-table-column |
|||
prop="retryCount" |
|||
header-align="center" |
|||
align="center" |
|||
label="重试次数" |
|||
width="90"> |
|||
</el-table-column> |
|||
<el-table-column |
|||
prop="createdDate" |
|||
header-align="center" |
|||
align="center" |
|||
label="创建时间" |
|||
width="155"> |
|||
</el-table-column> |
|||
<el-table-column |
|||
fixed="right" |
|||
header-align="center" |
|||
align="center" |
|||
width="100" |
|||
label="操作"> |
|||
<template slot-scope="scope"> |
|||
<el-button type="text" size="small" @click="viewParamsHandle(scope.row)"> |
|||
接口参数 |
|||
</el-button> |
|||
</template> |
|||
</el-table-column> |
|||
</el-table> |
|||
|
|||
<!-- 分页 --> |
|||
<el-pagination |
|||
@size-change="sizeChangeHandle" |
|||
@current-change="currentChangeHandle" |
|||
:current-page="pageIndex" |
|||
:page-sizes="[10, 20, 50, 100, 200]" |
|||
:page-size="pageSize" |
|||
:total="totalPage" |
|||
layout="total, sizes, prev, pager, next, jumper" |
|||
style="margin-top: 0px;"> |
|||
</el-pagination> |
|||
|
|||
<!-- 接口参数对话框 --> |
|||
<el-dialog |
|||
title="接口参数详情" |
|||
:visible.sync="paramsDialogVisible" |
|||
width="60%" |
|||
:close-on-click-modal="false"> |
|||
<div class="json-viewer"> |
|||
<pre>{{ formattedParams }}</pre> |
|||
</div> |
|||
<span slot="footer" class="dialog-footer"> |
|||
<el-button @click="paramsDialogVisible = false">关 闭</el-button> |
|||
<el-button type="primary" @click="copyParams">复制参数</el-button> |
|||
</span> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { searchApiLogs, getApiLogParams, deleteApiLogs, retryApiLogs } from '@/api/sys/interface-log' |
|||
|
|||
export default { |
|||
data() { |
|||
return { |
|||
searchExpanded: false, |
|||
searchForm: { |
|||
interfaceName: '', |
|||
requestId: '', |
|||
reDocumentNo: '', |
|||
reDocumentType: '', |
|||
statusCode: '', |
|||
sourceSystem: '', |
|||
targetSystem: '', |
|||
needRetryFlag: null, |
|||
dateRange: [] |
|||
}, |
|||
dataList: [], |
|||
pageIndex: 1, |
|||
pageSize: 20, |
|||
totalPage: 0, |
|||
dataListLoading: false, |
|||
dataListSelections: [], |
|||
paramsDialogVisible: false, |
|||
currentParams: null, |
|||
tableHeight: 200 |
|||
} |
|||
}, |
|||
computed: { |
|||
formattedParams() { |
|||
if (!this.currentParams) return '' |
|||
return JSON.stringify(this.currentParams, null, 2) |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.$nextTick(() => { |
|||
this.tableHeight = window.innerHeight - 280 |
|||
}) |
|||
this.getDataList() |
|||
}, |
|||
methods: { |
|||
// 切换搜索框展开/收起 |
|||
toggleSearchExpand() { |
|||
this.searchExpanded = !this.searchExpanded |
|||
}, |
|||
|
|||
// 获取数据列表 |
|||
getDataList() { |
|||
this.dataListLoading = true |
|||
const params = { |
|||
page: this.pageIndex, |
|||
limit: this.pageSize, |
|||
...this.searchForm |
|||
} |
|||
|
|||
// 处理日期范围 |
|||
if (this.searchForm.dateRange && this.searchForm.dateRange.length === 2) { |
|||
params.startDate = this.searchForm.dateRange[0] |
|||
params.endDate = this.searchForm.dateRange[1] |
|||
} |
|||
delete params.dateRange |
|||
|
|||
searchApiLogs(params).then(({ data }) => { |
|||
if (data && data.code === 0) { |
|||
this.dataList = data.page.list |
|||
this.totalPage = data.page.totalCount |
|||
} else { |
|||
this.dataList = [] |
|||
this.totalPage = 0 |
|||
} |
|||
this.dataListLoading = false |
|||
}).catch(() => { |
|||
this.dataListLoading = false |
|||
}) |
|||
}, |
|||
|
|||
// 重置查询 |
|||
resetSearch() { |
|||
this.searchForm = { |
|||
interfaceName: '', |
|||
requestId: '', |
|||
reDocumentNo: '', |
|||
reDocumentType: '', |
|||
statusCode: '', |
|||
sourceSystem: '', |
|||
targetSystem: '', |
|||
needRetryFlag: null, |
|||
dateRange: [] |
|||
} |
|||
this.pageIndex = 1 |
|||
this.getDataList() |
|||
}, |
|||
|
|||
// 每页数 |
|||
sizeChangeHandle(val) { |
|||
this.pageSize = val |
|||
this.pageIndex = 1 |
|||
this.getDataList() |
|||
}, |
|||
|
|||
// 当前页 |
|||
currentChangeHandle(val) { |
|||
this.pageIndex = val |
|||
this.getDataList() |
|||
}, |
|||
|
|||
// 多选 |
|||
selectionChangeHandle(val) { |
|||
this.dataListSelections = val |
|||
}, |
|||
|
|||
// 查看接口参数 |
|||
viewParamsHandle(row) { |
|||
const params = { |
|||
site: row.site, |
|||
buNo: row.buNo, |
|||
requestId: row.requestId, |
|||
requestGroupId: row.requestGroupId |
|||
} |
|||
|
|||
getApiLogParams(params).then(({ data }) => { |
|||
if (data && data.code === 0) { |
|||
this.currentParams = data.params |
|||
this.paramsDialogVisible = true |
|||
} else { |
|||
this.$message.error(data.msg || '获取接口参数失败') |
|||
} |
|||
}) |
|||
}, |
|||
|
|||
// 复制参数 |
|||
copyParams() { |
|||
const textarea = document.createElement('textarea') |
|||
textarea.value = this.formattedParams |
|||
document.body.appendChild(textarea) |
|||
textarea.select() |
|||
document.execCommand('copy') |
|||
document.body.removeChild(textarea) |
|||
this.$message.success('复制成功') |
|||
}, |
|||
|
|||
// 删除 |
|||
deleteHandle() { |
|||
const ids = this.dataListSelections.map(item => item.id) |
|||
this.$confirm('确定要删除选中的记录吗?', '提示', { |
|||
confirmButtonText: '确定', |
|||
cancelButtonText: '取消', |
|||
type: 'warning' |
|||
}).then(() => { |
|||
deleteApiLogs({ ids }).then(({ data }) => { |
|||
if (data && data.code === 0) { |
|||
this.$message.success('删除成功') |
|||
this.getDataList() |
|||
} else { |
|||
this.$message.error(data.msg || '删除失败') |
|||
} |
|||
}) |
|||
}) |
|||
}, |
|||
|
|||
// 重试 |
|||
retryHandle() { |
|||
const ids = this.dataListSelections.map(item => item.id) |
|||
this.$confirm('确定要重试选中的接口吗?', '提示', { |
|||
confirmButtonText: '确定', |
|||
cancelButtonText: '取消', |
|||
type: 'warning' |
|||
}).then(() => { |
|||
retryApiLogs({ ids }).then(({ data }) => { |
|||
if (data && data.code === 0) { |
|||
this.$message.success('重试成功') |
|||
this.getDataList() |
|||
} else { |
|||
this.$message.error(data.msg || '重试失败') |
|||
} |
|||
}) |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
/* 搜索卡片样式 */ |
|||
.search-card { |
|||
margin-bottom: 16px; |
|||
border-radius: 8px; |
|||
overflow: hidden; |
|||
transition: all 0.3s ease; |
|||
} |
|||
|
|||
.search-card:hover { |
|||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); |
|||
} |
|||
|
|||
.search-card /deep/ .el-card__header { |
|||
padding: 5px 20px; |
|||
background: linear-gradient(135deg, #9ac3d0 20%, #b6c7dd 80%); |
|||
border-bottom: none; |
|||
} |
|||
|
|||
.search-header { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
} |
|||
|
|||
.header-left { |
|||
display: flex; |
|||
align-items: center; |
|||
color: #fff; |
|||
} |
|||
|
|||
.header-left i { |
|||
font-size: 16px; |
|||
margin-right: 8px; |
|||
} |
|||
|
|||
.header-title { |
|||
font-size: 14px; |
|||
font-weight: 600; |
|||
letter-spacing: 0.5px; |
|||
} |
|||
|
|||
.header-right { |
|||
color: #fff; |
|||
} |
|||
|
|||
.collapse-btn { |
|||
color: #fff; |
|||
font-weight: 500; |
|||
transition: all 0.3s ease; |
|||
} |
|||
|
|||
.collapse-btn:hover { |
|||
color: #f0f0f0; |
|||
transform: translateY(-1px); |
|||
} |
|||
|
|||
.collapse-btn i { |
|||
transition: transform 0.3s ease; |
|||
} |
|||
|
|||
/* 搜索表单样式 */ |
|||
.search-form { |
|||
padding: 10px 0; |
|||
min-height: 0; |
|||
} |
|||
|
|||
/* 卡片主体样式 */ |
|||
.search-card /deep/ .el-card__body { |
|||
padding: 10px; |
|||
transition: all 0.3s ease; |
|||
} |
|||
|
|||
/* 收起时的样式 */ |
|||
.search-card.collapsed /deep/ .el-card__body { |
|||
padding: 10px 20px; |
|||
} |
|||
|
|||
.search-form /deep/ .el-form-item { |
|||
margin-bottom: 18px; |
|||
} |
|||
|
|||
.search-form /deep/ .el-form-item__label { |
|||
font-weight: 500; |
|||
color: #606266; |
|||
padding-bottom: 6px; |
|||
} |
|||
|
|||
.search-form /deep/ .el-input__inner, |
|||
.search-form /deep/ .el-textarea__inner { |
|||
border-radius: 6px; |
|||
border: 1px solid #DCDFE6; |
|||
transition: all 0.3s ease; |
|||
} |
|||
|
|||
.search-form /deep/ .el-input__inner:focus, |
|||
.search-form /deep/ .el-textarea__inner:focus { |
|||
border-color: #667eea; |
|||
box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.1); |
|||
} |
|||
|
|||
.search-form /deep/ .el-select { |
|||
width: 100%; |
|||
} |
|||
|
|||
.search-form /deep/ .el-date-editor.el-input { |
|||
width: 100%; |
|||
} |
|||
|
|||
/* 操作按钮区域 */ |
|||
.search-actions { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
padding: 8px 0 2px 0; |
|||
} |
|||
|
|||
/* 展开时显示上边框 */ |
|||
.search-card:not(.collapsed) .search-actions { |
|||
border-top: 1px solid #f0f0f0; |
|||
margin-top: 8px; |
|||
} |
|||
|
|||
/* 收起时不显示上边框和上边距 */ |
|||
.search-card.collapsed .search-actions { |
|||
border-top: none; |
|||
margin-top: 0; |
|||
padding-top: 0; |
|||
} |
|||
|
|||
.action-left, |
|||
.action-right { |
|||
display: flex; |
|||
gap: 8px; |
|||
} |
|||
|
|||
.search-actions .el-button { |
|||
border-radius: 4px; |
|||
padding: 5px 10px; |
|||
font-size: 12px; |
|||
font-weight: 500; |
|||
transition: all 0.3s ease; |
|||
} |
|||
|
|||
.search-actions .el-button:hover { |
|||
transform: translateY(-2px); |
|||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); |
|||
} |
|||
|
|||
.search-actions .el-button--primary { |
|||
background: #60aeff; |
|||
border-color: #60aeff; |
|||
} |
|||
|
|||
.search-actions .el-button--primary:hover { |
|||
background: #7dbdff; |
|||
border-color: #7dbdff; |
|||
} |
|||
|
|||
/* 表格操作按钮区域 */ |
|||
.table-actions { |
|||
margin-bottom: 8px; |
|||
margin-top: 8px; |
|||
} |
|||
|
|||
.table-actions .el-button { |
|||
border-radius: 4px; |
|||
font-weight: 500; |
|||
transition: all 0.3s ease; |
|||
} |
|||
|
|||
.table-actions .el-button:hover { |
|||
transform: translateY(-2px); |
|||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); |
|||
} |
|||
|
|||
/* 响应式设计 */ |
|||
@media (max-width: 1200px) { |
|||
.search-actions { |
|||
flex-direction: column; |
|||
gap: 10px; |
|||
} |
|||
|
|||
.action-left, |
|||
.action-right { |
|||
width: 100%; |
|||
justify-content: center; |
|||
} |
|||
} |
|||
|
|||
/* 表格样式 */ |
|||
.el-table /deep/ .cell { |
|||
height: auto; |
|||
line-height: 1.5; |
|||
} |
|||
|
|||
/* JSON查看器样式 */ |
|||
.json-viewer { |
|||
max-height: 500px; |
|||
overflow: auto; |
|||
background-color: #f5f5f5; |
|||
border: 1px solid #e0e0e0; |
|||
border-radius: 4px; |
|||
padding: 15px; |
|||
} |
|||
|
|||
.json-viewer pre { |
|||
margin: 0; |
|||
font-family: 'Courier New', Courier, monospace; |
|||
font-size: 13px; |
|||
line-height: 1.6; |
|||
color: #333; |
|||
white-space: pre-wrap; |
|||
word-wrap: break-word; |
|||
} |
|||
</style> |
|||
|
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue