<script lang="ts" setup>
|
import type { ActionItem, BasicColumn } from '@jnpf/ui/vxeTable';
|
|
import { computed, nextTick, reactive, toRefs, watch } from 'vue';
|
|
import { useMessage } from '@jnpf/hooks';
|
import { useDrawer } from '@jnpf/ui/drawer';
|
import { BasicForm, useForm } from '@jnpf/ui/form';
|
import { BasicPopup, usePopupInner } from '@jnpf/ui/popup';
|
import { BasicVxeTable, TableAction, useVxeTable } from '@jnpf/ui/vxeTable';
|
|
import dayjs from 'dayjs';
|
|
import { batchDelLog, delLog, getLogList } from '#/api/system/log';
|
import { $t } from '#/locales';
|
import LogDetail from '#/views/sysLog/requestLog/Detail.vue';
|
|
defineOptions({ name: 'DataInterfaceLog' });
|
|
interface State {
|
searchInfo: any;
|
interfaceId: string;
|
title: string;
|
activeKey: string;
|
}
|
|
const { createMessage, createConfirm } = useMessage();
|
const state = reactive<State>({
|
searchInfo: {},
|
interfaceId: '',
|
title: '',
|
activeKey: '5',
|
});
|
const { title, activeKey } = toRefs(state);
|
const requestTableColumns: BasicColumn[] = [
|
{ title: '请求时间', dataIndex: 'creatorTime', width: 150, format: 'date|YYYY-MM-DD HH:mm:ss' },
|
{ title: '用户', dataIndex: 'userName', width: 120 },
|
{ title: 'IP地址', dataIndex: 'ipAddress', width: 120 },
|
{ title: '地点', dataIndex: 'ipAddressName', width: 120 },
|
{ title: '浏览器', dataIndex: 'browser', width: 120 },
|
{ title: '操作系统', dataIndex: 'platForm', width: 120 },
|
{ title: '请求方式', dataIndex: 'requestMethod', width: 80 },
|
{ title: '耗时(毫秒)', dataIndex: 'requestDuration', width: 90, align: 'center' },
|
{ title: '请求地址', dataIndex: 'requestUrl', minWidth: 200 },
|
];
|
const errorTableColumns: BasicColumn[] = [
|
{ title: '操作时间', dataIndex: 'creatorTime', width: 150, format: 'date|YYYY-MM-DD HH:mm:ss' },
|
{ title: '用户', dataIndex: 'userName', width: 120 },
|
{ title: 'IP地址', dataIndex: 'ipAddress', width: 160 },
|
{ title: '地点', dataIndex: 'ipAddressName', width: 120 },
|
{ title: '浏览器', dataIndex: 'browser', width: 120 },
|
{ title: '操作系统', dataIndex: 'platForm', width: 120 },
|
{ title: '请求方式', dataIndex: 'requestMethod', width: 80 },
|
{ title: '请求地址', dataIndex: 'requestUrl', minWidth: 200 },
|
];
|
const useTableAttrs: any = {
|
api: getLogList,
|
rowSelection: { type: 'checkbox' },
|
immediate: false,
|
clickToRowSelect: false,
|
clearSelectOnPageChange: true,
|
};
|
const actionColumn = {
|
width: 60,
|
title: '操作',
|
dataIndex: 'action',
|
};
|
const [registerRequestTable, { reload: reloadRequestTable, getSelectRows: getRequestSelectRows }] = useVxeTable({ ...useTableAttrs, actionColumn });
|
const [registerErrorTable, { reload: reloadErrorTable, getSelectRows: getErrorSelectRows }] = useVxeTable({ ...useTableAttrs, actionColumn });
|
const [registerDetail, { openDrawer }] = useDrawer();
|
const [registerPopup] = usePopupInner(init);
|
const [registerForm] = useForm({
|
baseColProps: { span: 6 },
|
showActionButtonGroup: true,
|
showAdvancedButton: true,
|
compact: true,
|
fieldMapToTime: [['pickerVal', ['startTime', 'endTime']]],
|
});
|
const getSearchInfo = computed(() => ({ category: state.activeKey, dataInterFaceId: state.interfaceId, ...state.searchInfo }));
|
const getSchemasForm = computed<any>(() => {
|
const searchForm = [
|
{
|
field: 'keyword',
|
label: $t('common.keyword'),
|
component: 'Input',
|
componentProps: {
|
placeholder: $t('common.enterKeyword'),
|
submitOnPressEnter: true,
|
},
|
},
|
{
|
field: 'requestMethod',
|
label: '请求方式',
|
component: 'Select',
|
componentProps: {
|
placeholder: '请选择',
|
options: [
|
{ fullName: 'GET', id: 'GET' },
|
{ fullName: 'POST', id: 'POST' },
|
{ fullName: 'PUT', id: 'PUT' },
|
{ fullName: 'DELETE', id: 'DELETE' },
|
],
|
},
|
},
|
{
|
field: 'pickerVal',
|
label: state.activeKey == '5' ? '请求时间' : '操作时间',
|
component: 'DateRange',
|
componentProps: {
|
format: 'YYYY-MM-DD HH:mm:ss',
|
showTime: { defaultValue: [dayjs('00:00:00', 'HH:mm:ss'), dayjs('23:59:59', 'HH:mm:ss')] },
|
placeholder: ['开始时间', '结束时间'],
|
},
|
},
|
];
|
return searchForm;
|
});
|
|
watch(
|
() => state.activeKey,
|
() => {
|
nextTick(() => reload());
|
},
|
);
|
|
function handleSubmit(data) {
|
const obj = {};
|
for (const [key, value] of Object.entries(data)) {
|
if (value || value == 0) {
|
if (Array.isArray(value)) {
|
if (value.length) obj[key] = value;
|
} else {
|
obj[key] = value;
|
}
|
}
|
}
|
state.searchInfo = obj;
|
handleSearch();
|
}
|
function handleReset() {
|
state.searchInfo = {};
|
handleSearch();
|
}
|
function handleSearch() {
|
nextTick(() => {
|
reload();
|
});
|
}
|
function init(data) {
|
state.interfaceId = data.id || '';
|
state.title = data.fullName || '';
|
state.activeKey = '5';
|
state.searchInfo = {};
|
handleSearch();
|
}
|
function reload() {
|
if (state.activeKey === '5') reloadRequestTable({ page: 1 });
|
if (state.activeKey === '4') reloadErrorTable({ page: 1 });
|
}
|
function getSelectData() {
|
if (state.activeKey === '5') return getRequestSelectRows();
|
if (state.activeKey === '4') return getErrorSelectRows();
|
}
|
function handleDelete() {
|
const list: any[] = getSelectData() || [];
|
if (!list.length) return createMessage.error($t('common.selectDataTip'));
|
const query = {
|
ids: list.map((item) => item.id),
|
};
|
createConfirm({
|
iconType: 'warning',
|
title: $t('common.tipTitle'),
|
content: $t('common.batchDelTip'),
|
onOk: () => {
|
delLog(query).then((res) => {
|
createMessage.success(res.msg);
|
reload();
|
});
|
},
|
});
|
}
|
function handleDelAll() {
|
createConfirm({
|
iconType: 'warning',
|
title: $t('common.tipTitle'),
|
content: '此操作会将所有日志删除,是否继续?',
|
onOk: () => {
|
batchDelLog(state.activeKey, state.interfaceId).then((res) => {
|
createMessage.success(res.msg);
|
reload();
|
});
|
},
|
});
|
}
|
function getTableActions(record): ActionItem[] {
|
return [
|
{
|
label: $t('common.detailText'),
|
onClick: toDetail.bind(null, record.id),
|
},
|
];
|
}
|
function toDetail(id) {
|
openDrawer(true, { id, activeKey: state.activeKey });
|
}
|
</script>
|
<template>
|
<BasicPopup v-bind="$attrs" @register="registerPopup" :title="title" class="full-popup">
|
<div class="flex h-full flex-col">
|
<div class="jnpf-content-wrapper-search-box ml-[10px] mt-[10px]">
|
<BasicForm class="search-form" :schemas="getSchemasForm" @register="registerForm" @submit="handleSubmit" @reset="handleReset" />
|
</div>
|
<a-tabs v-model:active-key="activeKey" class="jnpf-content-wrapper-tabs flex-1" destroy-inactive-tab-pane>
|
<a-tab-pane key="5" tab="请求日志">
|
<BasicVxeTable @register="registerRequestTable" :columns="requestTableColumns" :search-info="getSearchInfo">
|
<template #tableTitle>
|
<a-button type="error" pre-icon="icon-ym icon-ym-btn-clearn" @click="handleDelete">{{ $t('common.delText') }}</a-button>
|
<a-button type="link" danger @click="handleDelAll">一键清空</a-button>
|
</template>
|
<template #action="{ record }">
|
<TableAction :actions="getTableActions(record)" />
|
</template>
|
</BasicVxeTable>
|
</a-tab-pane>
|
<a-tab-pane key="4" tab="异常日志">
|
<BasicVxeTable @register="registerErrorTable" :columns="errorTableColumns" :search-info="getSearchInfo">
|
<template #tableTitle>
|
<a-button type="error" pre-icon="icon-ym icon-ym-btn-clearn" @click="handleDelete">{{ $t('common.delText') }}</a-button>
|
<a-button type="link" danger @click="handleDelAll">一键清空</a-button>
|
</template>
|
<template #action="{ record }">
|
<TableAction :actions="getTableActions(record)" />
|
</template>
|
</BasicVxeTable>
|
</a-tab-pane>
|
</a-tabs>
|
</div>
|
</BasicPopup>
|
<LogDetail @register="registerDetail" />
|
</template>
|
<style lang="scss" scoped>
|
.jnpf-content-wrapper-tabs {
|
:deep(.ant-tabs-content) {
|
height: 100%;
|
}
|
}
|
</style>
|