Browse Source

feat(vben5): 增加系统日志模块

pull/1175/head
colin 12 months ago
parent
commit
bbc5219fcf
  1. 5
      apps/vben5/apps/app-antd/src/locales/langs/en-US/abp.json
  2. 5
      apps/vben5/apps/app-antd/src/locales/langs/zh-CN/abp.json
  3. 11
      apps/vben5/apps/app-antd/src/router/routes/modules/abp.ts
  4. 15
      apps/vben5/apps/app-antd/src/views/auditing/loggings/index.vue
  5. 1
      apps/vben5/packages/@abp/auditing/src/api/index.ts
  6. 38
      apps/vben5/packages/@abp/auditing/src/api/useLoggingsApi.ts
  7. 3
      apps/vben5/packages/@abp/auditing/src/components/audit-logs/AuditLogTable.vue
  8. 1
      apps/vben5/packages/@abp/auditing/src/components/index.ts
  9. 138
      apps/vben5/packages/@abp/auditing/src/components/loggings/LoggingDrawer.vue
  10. 345
      apps/vben5/packages/@abp/auditing/src/components/loggings/LoggingTable.vue
  11. 4
      apps/vben5/packages/@abp/auditing/src/constants/permissions.ts
  12. 1
      apps/vben5/packages/@abp/auditing/src/types/index.ts
  13. 65
      apps/vben5/packages/@abp/auditing/src/types/loggings.ts

5
apps/vben5/apps/app-antd/src/locales/langs/en-US/abp.json

@ -22,7 +22,6 @@
"claimTypes": "Claim Types",
"securityLogs": "Security Logs",
"organizationUnits": "Organization Units",
"auditLogs": "Audit Logs",
"sessions": "Sessions"
},
"permissions": {
@ -55,7 +54,9 @@
"dataProtection": {
"title": "Data Protection",
"entityTypeInfos": "Entity Type Infos"
}
},
"auditLogs": "Audit Logs",
"loggings": "System Logs"
},
"openiddict": {
"title": "OpenIddict",

5
apps/vben5/apps/app-antd/src/locales/langs/zh-CN/abp.json

@ -22,7 +22,6 @@
"claimTypes": "身份标识",
"securityLogs": "安全日志",
"organizationUnits": "组织机构",
"auditLogs": "审计日志",
"sessions": "会话管理"
},
"permissions": {
@ -55,7 +54,9 @@
"dataProtection": {
"title": "数据权限",
"entityTypeInfos": "实体列表"
}
},
"auditLogs": "审计日志",
"loggings": "系统日志"
},
"openiddict": {
"title": "OpenIddict",

11
apps/vben5/apps/app-antd/src/router/routes/modules/abp.ts

@ -237,13 +237,22 @@ const routes: RouteRecordRaw[] = [
},
{
meta: {
title: $t('abp.manage.identity.auditLogs'),
title: $t('abp.manage.auditLogs'),
icon: 'fluent-mdl2:compliance-audit',
},
name: 'AuditingAuditLogs',
path: '/manage/audit-logs',
component: () => import('#/views/auditing/audit-logs/index.vue'),
},
{
meta: {
title: $t('abp.manage.loggings'),
icon: 'icon-park-outline:log',
},
name: 'AuditingLoggings',
path: '/manage/sys-logs',
component: () => import('#/views/auditing/loggings/index.vue'),
},
{
meta: {
title: $t('abp.manage.notifications.title'),

15
apps/vben5/apps/app-antd/src/views/auditing/loggings/index.vue

@ -0,0 +1,15 @@
<script lang="ts" setup>
import { Page } from '@vben/common-ui';
import { LoggingTable } from '@abp/auditing';
defineOptions({
name: 'AuditingLoggings',
});
</script>
<template>
<Page>
<LoggingTable />
</Page>
</template>

1
apps/vben5/packages/@abp/auditing/src/api/index.ts

@ -1,2 +1,3 @@
export { useAuditLogsApi } from './useAuditLogsApi';
export { useEntityChangesApi } from './useEntityChangesApi';
export { useLoggingsApi } from './useLoggingsApi';

38
apps/vben5/packages/@abp/auditing/src/api/useLoggingsApi.ts

@ -0,0 +1,38 @@
import type { PagedResultDto } from '@abp/core';
import type { LogDto, LogGetListInput } from '../types/loggings';
import { useRequest } from '@abp/request';
export function useLoggingsApi() {
const { cancel, request } = useRequest();
/**
*
* @param id id
*/
function getApi(id: string): Promise<LogDto> {
return request<LogDto>(`/api/auditing/logging/${id}`, {
method: 'GET',
});
}
/**
*
* @param input
*/
function getPagedListApi(
input: LogGetListInput,
): Promise<PagedResultDto<LogDto>> {
return request<PagedResultDto<LogDto>>('/api/auditing/logging', {
method: 'GET',
params: input,
});
}
return {
cancel,
getApi,
getPagedListApi,
};
}

3
apps/vben5/packages/@abp/auditing/src/components/audit-logs/AuditLogTable.vue

@ -41,6 +41,9 @@ const formOptions: VbenFormProps = {
schema: [
{
component: 'RangePicker',
componentProps: {
showTime: true,
},
fieldName: 'executionTime',
formItemClass: 'col-span-2 items-baseline',
label: $t('AbpAuditLogging.ExecutionTime'),

1
apps/vben5/packages/@abp/auditing/src/components/index.ts

@ -1,2 +1,3 @@
export { default as AuditLogTable } from './audit-logs/AuditLogTable.vue';
export { default as EntityChangeDrawer } from './entity-changes/EntityChangeDrawer.vue';
export { default as LoggingTable } from './loggings/LoggingTable.vue';

138
apps/vben5/packages/@abp/auditing/src/components/loggings/LoggingDrawer.vue

@ -0,0 +1,138 @@
<script setup lang="ts">
import type { LogDto, LogLevel } from '../../types/loggings';
import { ref } from 'vue';
import { useVbenDrawer } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { formatToDateTime } from '@abp/core';
import { Descriptions, Tabs, Tag } from 'ant-design-vue';
import { useLoggingsApi } from '../../api/useLoggingsApi';
defineOptions({
name: 'LoggingDrawer',
});
defineProps<{
logLevelOptions: { color: string; label: string; value: LogLevel }[];
}>();
const TabPane = Tabs.TabPane;
const DescriptionsItem = Descriptions.Item;
const activedTab = ref('basic');
const logModel = ref<LogDto>({} as LogDto);
const { getApi } = useLoggingsApi();
const [Drawer, drawerApi] = useVbenDrawer({
class: 'w-auto',
onCancel() {
drawerApi.close();
},
onConfirm: async () => {
drawerApi.close();
},
onOpenChange: async (isOpen: boolean) => {
if (isOpen) {
try {
logModel.value = {} as LogDto;
drawerApi.setState({ loading: true });
const dto = drawerApi.getData<LogDto>();
await onGet(dto.fields.id);
} finally {
drawerApi.setState({ loading: false });
}
}
},
title: $t('AbpAuditLogging.AuditLog'),
});
async function onGet(id: string) {
const dto = await getApi(id);
logModel.value = dto;
}
</script>
<template>
<Drawer>
<div style="width: 800px">
<Tabs v-model="activedTab">
<TabPane key="basic" :tab="$t('AbpAuditLogging.Operation')">
<Descriptions
:colon="false"
:column="1"
bordered
size="small"
:label-style="{ minWidth: '110px' }"
>
<DescriptionsItem :label="$t('AbpAuditLogging.TimeStamp')">
{{ formatToDateTime(logModel.timeStamp) }}
</DescriptionsItem>
<DescriptionsItem :label="$t('AbpAuditLogging.Level')">
<Tag :color="logLevelOptions[logModel.level]?.color">
{{ logLevelOptions[logModel.level]?.label }}
</Tag>
</DescriptionsItem>
<DescriptionsItem :label="$t('AbpAuditLogging.Message')" :span="2">
{{ logModel.message }}
</DescriptionsItem>
</Descriptions>
</TabPane>
<TabPane key="fields" :tab="$t('AbpAuditLogging.Fields')">
<Descriptions
:colon="false"
:column="1"
bordered
size="small"
:label-style="{ minWidth: '110px' }"
>
<DescriptionsItem :label="$t('AbpAuditLogging.ApplicationName')">
{{ logModel.fields.application }}
</DescriptionsItem>
<DescriptionsItem :label="$t('AbpAuditLogging.MachineName')">
{{ logModel.fields.machineName }}
</DescriptionsItem>
<DescriptionsItem :label="$t('AbpAuditLogging.Environment')">
{{ logModel.fields.environment }}
</DescriptionsItem>
<DescriptionsItem :label="$t('AbpAuditLogging.ProcessId')">
{{ logModel.fields.processId }}
</DescriptionsItem>
<DescriptionsItem :label="$t('AbpAuditLogging.ThreadId')">
{{ logModel.fields.threadId }}
</DescriptionsItem>
<DescriptionsItem :label="$t('AbpAuditLogging.Context')">
{{ logModel.fields.context }}
</DescriptionsItem>
<DescriptionsItem :label="$t('AbpAuditLogging.ActionId')">
{{ logModel.fields.actionId }}
</DescriptionsItem>
<DescriptionsItem :label="$t('AbpAuditLogging.MethodName')">
{{ logModel.fields.actionName }}
</DescriptionsItem>
<DescriptionsItem :label="$t('AbpAuditLogging.RequestId')">
{{ logModel.fields.requestId }}
</DescriptionsItem>
<DescriptionsItem :label="$t('AbpAuditLogging.RequestPath')">
{{ logModel.fields.requestPath }}
</DescriptionsItem>
<DescriptionsItem :label="$t('AbpAuditLogging.ConnectionId')">
{{ logModel.fields.connectionId }}
</DescriptionsItem>
<DescriptionsItem :label="$t('AbpAuditLogging.CorrelationId')">
{{ logModel.fields.correlationId }}
</DescriptionsItem>
<DescriptionsItem :label="$t('AbpAuditLogging.ClientId')">
{{ logModel.fields.clientId }}
</DescriptionsItem>
<DescriptionsItem :label="$t('AbpAuditLogging.UserId')">
{{ logModel.fields.userId }}
</DescriptionsItem>
</Descriptions>
</TabPane>
</Tabs>
</div>
</Drawer>
</template>
<style scoped></style>

345
apps/vben5/packages/@abp/auditing/src/components/loggings/LoggingTable.vue

@ -0,0 +1,345 @@
<script setup lang="ts">
import type { SortOrder } from '@abp/core';
import type { VxeGridListeners, VxeGridProps } from '@abp/ui';
import type { VbenFormProps } from '@vben/common-ui';
import type { LogDto } from '../../types/loggings';
import { defineAsyncComponent, h, reactive, ref } from 'vue';
import { useVbenDrawer } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { formatToDateTime } from '@abp/core';
import { useVbenVxeGrid } from '@abp/ui';
import { EditOutlined } from '@ant-design/icons-vue';
import { Button, Tag } from 'ant-design-vue';
import { useLoggingsApi } from '../../api/useLoggingsApi';
import { SystemLogPermissions } from '../../constants/permissions';
import { LogLevel } from '../../types/loggings';
defineOptions({
name: 'LoggingTable',
});
const { getPagedListApi } = useLoggingsApi();
const selectedKeys = ref<string[]>([]);
const logLevelOptions = reactive([
{
color: 'purple',
label: 'Trace',
value: LogLevel.Trace,
},
{
color: 'blue',
label: 'Debug',
value: LogLevel.Debug,
},
{
color: 'green',
label: 'Information',
value: LogLevel.Information,
},
{
color: 'orange',
label: 'Warning',
value: LogLevel.Warning,
},
{
color: 'red',
label: 'Error',
value: LogLevel.Error,
},
{
color: '#f50',
label: 'Critical',
value: LogLevel.Critical,
},
{
color: '',
label: 'None',
value: LogLevel.None,
},
]);
const formOptions: VbenFormProps = {
//
collapsed: true,
collapsedRows: 2,
fieldMappingTime: [
[
'timeStamp',
['startTime', 'endTime'],
['YYYY-MM-DD HH:mm:ss', 'YYYY-MM-DD HH:mm:ss'],
],
],
schema: [
{
component: 'Select',
componentProps: {
options: logLevelOptions,
},
fieldName: 'level',
label: $t('AbpAuditLogging.Level'),
},
{
component: 'RangePicker',
componentProps: {
showTime: true,
},
fieldName: 'timeStamp',
formItemClass: 'col-span-2 items-baseline',
label: $t('AbpAuditLogging.TimeStamp'),
},
{
component: 'Input',
fieldName: 'application',
label: $t('AbpAuditLogging.ApplicationName'),
},
{
component: 'Input',
fieldName: 'machineName',
label: $t('AbpAuditLogging.MachineName'),
},
{
component: 'Input',
fieldName: 'environment',
label: $t('AbpAuditLogging.Environment'),
},
{
component: 'Input',
fieldName: 'requestId',
formItemClass: 'col-span-2 items-baseline',
label: $t('AbpAuditLogging.RequestId'),
},
{
component: 'Input',
fieldName: 'requestPath',
formItemClass: 'col-span-2 items-baseline',
label: $t('AbpAuditLogging.RequestPath'),
labelWidth: 150,
},
{
component: 'Input',
fieldName: 'correlationId',
formItemClass: 'col-span-2 items-baseline',
label: $t('AbpAuditLogging.CorrelationId'),
},
{
component: 'Checkbox',
componentProps: {
render: () => {
return h('span', $t('AbpAuditLogging.HasException'));
},
},
fieldName: 'hasException',
label: $t('AbpAuditLogging.HasException'),
},
],
//
showCollapseButton: true,
//
submitOnEnter: true,
wrapperClass: 'grid-cols-4',
};
const gridOptions: VxeGridProps<LogDto> = {
columns: [
{
align: 'left',
field: 'applicationName',
formatter: ({ row }) => {
return row.fields?.application;
},
sortable: true,
title: $t('AbpAuditLogging.ApplicationName'),
width: 150,
},
{
align: 'left',
field: 'timeStamp',
formatter: ({ cellValue }) => {
return cellValue ? formatToDateTime(cellValue) : cellValue;
},
sortable: true,
title: $t('AbpAuditLogging.TimeStamp'),
width: 150,
},
{
align: 'left',
field: 'level',
slots: { default: 'level' },
sortable: true,
title: $t('AbpAuditLogging.Level'),
width: 120,
},
{
align: 'left',
field: 'message',
sortable: true,
title: $t('AbpAuditLogging.Message'),
width: 500,
},
{
align: 'left',
field: 'machineName',
formatter: ({ row }) => {
return row.fields?.machineName;
},
sortable: true,
title: $t('AbpAuditLogging.MachineName'),
width: 140,
},
{
align: 'left',
field: 'environment',
formatter: ({ row }) => {
return row.fields?.environment;
},
sortable: true,
title: $t('AbpAuditLogging.Environment'),
width: 150,
},
{
align: 'left',
field: 'requestId',
formatter: ({ row }) => {
return row.fields?.requestId;
},
sortable: true,
title: $t('AbpAuditLogging.RequestId'),
width: 200,
},
{
align: 'left',
field: 'requestPath',
formatter: ({ row }) => {
return row.fields?.requestPath;
},
sortable: true,
title: $t('AbpAuditLogging.RequestPath'),
width: 300,
},
{
align: 'left',
field: 'connectionId',
formatter: ({ row }) => {
return row.fields?.connectionId;
},
sortable: true,
title: $t('AbpAuditLogging.ConnectionId'),
width: 150,
},
{
align: 'left',
field: 'correlationId',
formatter: ({ row }) => {
return row.fields?.correlationId;
},
sortable: true,
title: $t('AbpAuditLogging.CorrelationId'),
width: 240,
},
{
field: 'action',
fixed: 'right',
slots: { default: 'action' },
title: $t('AbpUi.Actions'),
width: 180,
},
],
exportConfig: {},
keepSource: true,
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
return await getPagedListApi({
maxResultCount: page.pageSize,
skipCount: (page.currentPage - 1) * page.pageSize,
...formValues,
});
},
},
response: {
total: 'totalCount',
list: 'items',
},
},
sortConfig: {
remote: true,
},
toolbarConfig: {
custom: true,
export: true,
// import: true,
refresh: true,
zoom: true,
},
};
const gridEvents: VxeGridListeners<LogDto> = {
checkboxAll: (params) => {
selectedKeys.value = params.records.map((x) => x.fields.id);
},
checkboxChange: (params) => {
selectedKeys.value = params.records.map((x) => x.fields.id);
},
sortChange: onSort,
};
const [Grid, gridApi] = useVbenVxeGrid({
formOptions,
gridEvents,
gridOptions,
});
const [LoggingDrawer, logDrawerApi] = useVbenDrawer({
connectedComponent: defineAsyncComponent(() => import('./LoggingDrawer.vue')),
});
function onUpdate(row: LogDto) {
logDrawerApi.setData(row);
logDrawerApi.open();
}
function onSort(params: { field: string; order: SortOrder }) {
const sorting = params.order ? `${params.field} ${params.order}` : undefined;
gridApi.query({ sorting });
}
function onFilter(field: string, value: any) {
gridApi.formApi.setFieldValue(field, value);
gridApi.formApi.validateAndSubmitForm();
}
</script>
<template>
<Grid :table-title="$t('AbpAuditLogging.Logging')">
<template #level="{ row }">
<Tag :color="logLevelOptions[row.level]?.color">
<a
class="link"
href="javaScript:void(0);"
@click="onFilter('level', row.level)"
>{{ logLevelOptions[row.level]?.label }}
</a>
</Tag>
</template>
<template #action="{ row }">
<div class="flex flex-row">
<Button
:icon="h(EditOutlined)"
block
type="link"
v-access:code="[SystemLogPermissions.Default]"
@click="onUpdate(row)"
>
{{ $t('AbpAuditLogging.ShowLogDialog') }}
</Button>
</div>
</template>
</Grid>
<LoggingDrawer :log-level-options="logLevelOptions" />
</template>
<style lang="scss" scoped></style>

4
apps/vben5/packages/@abp/auditing/src/constants/permissions.ts

@ -4,3 +4,7 @@ export const AuditLogPermissions = {
/** 删除 */
Delete: 'AbpAuditing.AuditLog.Delete',
};
/** 系统日志权限 */
export const SystemLogPermissions = {
Default: 'AbpAuditing.SystemLog',
};

1
apps/vben5/packages/@abp/auditing/src/types/index.ts

@ -1,2 +1,3 @@
export * from './audit-logs';
export * from './entity-changes';
export * from './loggings';

65
apps/vben5/packages/@abp/auditing/src/types/loggings.ts

@ -0,0 +1,65 @@
interface LogExceptionDto {
class?: string;
depth?: number;
helpUrl?: string;
hResult?: number;
message?: string;
source?: string;
stackTrace?: string;
}
interface LogFieldDto {
actionId?: string;
actionName?: string;
application?: string;
clientId?: string;
connectionId?: string;
context?: string;
correlationId?: string;
environment?: string;
id: string;
machineName?: string;
processId?: number;
requestId?: string;
requestPath?: string;
threadId?: number;
userId?: string;
}
enum LogLevel {
Critical = 5,
Debug = 1,
Error = 4,
Information = 2,
None = 6,
Trace = 0,
Warning = 3,
}
interface LogDto {
exceptions: LogExceptionDto[];
fields: LogFieldDto;
level: LogLevel;
message: string;
timeStamp: Date;
}
interface LogGetListInput {
application?: string;
context?: string;
correlationId?: string;
endTime?: Date;
environment?: string;
hasException?: boolean;
level?: LogLevel;
machineName?: string;
processId?: number;
requestId?: string;
requestPath?: string;
startTime?: Date;
threadId?: number;
}
export type { LogDto, LogExceptionDto, LogFieldDto, LogGetListInput };
export { LogLevel };
Loading…
Cancel
Save