diff --git a/apps/web-antd/src/api/infra/api-access-log/index.ts b/apps/web-antd/src/api/infra/api-access-log/index.ts new file mode 100644 index 000000000..4eb727fb7 --- /dev/null +++ b/apps/web-antd/src/api/infra/api-access-log/index.ts @@ -0,0 +1,42 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace InfraApiAccessLogApi { + /** API 访问日志信息 */ + export interface SystemApiAccessLog { + id: number; + traceId: string; + userId: number; + userType: number; + applicationName: string; + requestMethod: string; + requestParams: string; + responseBody: string; + requestUrl: string; + userIp: string; + userAgent: string; + operateModule: string; + operateName: string; + operateType: number; + beginTime: string; + endTime: string; + duration: number; + resultCode: number; + resultMsg: string; + createTime: string; + } +} + +/** 查询 API 访问日志列表 */ +export function getApiAccessLogPage(params: PageParam) { + return requestClient.get>( + '/infra/api-access-log/page', + { params } + ); +} + +/** 导出 API 访问日志 */ +export function exportApiAccessLog(params: any) { + return requestClient.download('/infra/api-access-log/export-excel', { params }); +} diff --git a/apps/web-antd/src/api/infra/api-error-log/index.ts b/apps/web-antd/src/api/infra/api-error-log/index.ts new file mode 100644 index 000000000..dcca22c5f --- /dev/null +++ b/apps/web-antd/src/api/infra/api-error-log/index.ts @@ -0,0 +1,51 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace InfraApiErrorLogApi { + /** API 错误日志信息 */ + export interface SystemApiErrorLog { + id: number; + traceId: string; + userId: number; + userType: number; + applicationName: string; + requestMethod: string; + requestParams: string; + requestUrl: string; + userIp: string; + userAgent: string; + exceptionTime: string; + exceptionName: string; + exceptionMessage: string; + exceptionRootCauseMessage: string; + exceptionStackTrace: string; + exceptionClassName: string; + exceptionFileName: string; + exceptionMethodName: string; + exceptionLineNumber: number; + processUserId: number; + processStatus: number; + processTime: string; + resultCode: number; + createTime: string; + } +} + +/** 查询 API 错误日志列表 */ +export function getApiErrorLogPage(params: PageParam) { + return requestClient.get>( + '/infra/api-error-log/page', + { params } + ); +} + +/** 更新 API 错误日志的处理状态 */ +export function updateApiErrorLogStatus(id: number, processStatus: number) { + return requestClient.put(`/infra/api-error-log/update-status?id=${id}&processStatus=${processStatus}`); +} + +/** 导出 API 错误日志 */ +export function exportApiErrorLog(params: any) { + return requestClient.download('/infra/api-error-log/export-excel', { params }); +} diff --git a/apps/web-antd/src/api/system/permission/index.ts b/apps/web-antd/src/api/system/permission/index.ts index 9039d9a05..fe958a04c 100644 --- a/apps/web-antd/src/api/system/permission/index.ts +++ b/apps/web-antd/src/api/system/permission/index.ts @@ -2,19 +2,19 @@ import { requestClient } from '#/api/request'; export namespace SystemPermissionApi { /** 分配用户角色请求 */ - export interface AssignUserRoleReqVO { + export interface SystemAssignUserRoleReqVO { userId: number; roleIds: number[]; } /** 分配角色菜单请求 */ - export interface AssignRoleMenuReqVO { + export interface SystemAssignRoleMenuReqVO { roleId: number; menuIds: number[]; } /** 分配角色数据权限请求 */ - export interface AssignRoleDataScopeReqVO { + export interface SystemAssignRoleDataScopeReqVO { roleId: number; dataScope: number; dataScopeDeptIds: number[]; @@ -30,14 +30,14 @@ export async function getRoleMenuList(roleId: number) { /** 赋予角色菜单权限 */ export async function assignRoleMenu( - data: SystemPermissionApi.AssignRoleMenuReqVO, + data: SystemPermissionApi.SystemAssignRoleMenuReqVO, ) { return requestClient.post('/system/permission/assign-role-menu', data); } /** 赋予角色数据权限 */ export async function assignRoleDataScope( - data: SystemPermissionApi.AssignRoleDataScopeReqVO, + data: SystemPermissionApi.SystemAssignRoleDataScopeReqVO, ) { return requestClient.post('/system/permission/assign-role-data-scope', data); } @@ -51,7 +51,7 @@ export async function getUserRoleList(userId: number) { /** 赋予用户角色 */ export async function assignUserRole( - data: SystemPermissionApi.AssignUserRoleReqVO, + data: SystemPermissionApi.SystemAssignUserRoleReqVO, ) { return requestClient.post('/system/permission/assign-user-role', data); } diff --git a/apps/web-antd/src/views/infra/apiAccessLog/data.ts b/apps/web-antd/src/views/infra/apiAccessLog/data.ts new file mode 100644 index 000000000..a4879e1e5 --- /dev/null +++ b/apps/web-antd/src/views/infra/apiAccessLog/data.ts @@ -0,0 +1,175 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { InfraApiAccessLogApi } from '#/api/infra/api-access-log'; + +import {DICT_TYPE, getDictOptions} from '#/utils/dict'; +import { getRangePickerDefaultProps } from '#/utils/date'; +import { useAccess } from '@vben/access'; + +const { hasAccessByCodes } = useAccess(); + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'userId', + label: '用户编号', + component: 'Input', + componentProps: { + allowClear: true, + placeholder: '请输入用户编号', + }, + }, + { + fieldName: 'userType', + label: '用户类型', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.USER_TYPE, 'number'), + allowClear: true, + placeholder: '请选择用户类型', + }, + }, + { + fieldName: 'applicationName', + label: '应用名', + component: 'Input', + componentProps: { + allowClear: true, + placeholder: '请输入应用名', + }, + }, + { + fieldName: 'beginTime', + label: '请求时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + { + fieldName: 'duration', + label: '执行时长', + component: 'Input', + componentProps: { + allowClear: true, + placeholder: '请输入执行时长', + }, + }, + { + fieldName: 'resultCode', + label: '结果码', + component: 'Input', + componentProps: { + allowClear: true, + placeholder: '请输入结果码', + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + onActionClick: OnActionClickFn, +): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '日志编号', + minWidth: 100, + }, + { + field: 'userId', + title: '用户编号', + minWidth: 100, + }, + { + field: 'userType', + title: '用户类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.USER_TYPE }, + }, + }, + { + field: 'applicationName', + title: '应用名', + minWidth: 150, + }, + { + field: 'requestMethod', + title: '请求方法', + minWidth: 80, + }, + { + field: 'requestUrl', + title: '请求地址', + minWidth: 300, + }, + { + field: 'beginTime', + title: '请求时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'duration', + title: '执行时长', + minWidth: 120, + formatter: ({ row }) => `${row.duration} ms`, + }, + { + field: 'resultCode', + title: '操作结果', + minWidth: 150, + formatter: ({ row }) => { + return row.resultCode === 0 + ? '成功' + : `失败(${row.resultMsg})`; + }, + }, + { + field: 'operateModule', + title: '操作模块', + minWidth: 150, + }, + { + field: 'operateName', + title: '操作名', + minWidth: 220, + }, + { + field: 'operateType', + title: '操作类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_OPERATE_TYPE }, + }, + }, + { + field: 'operation', + title: '操作', + minWidth: 80, + align: 'center', + fixed: 'right', + cellRender: { + attrs: { + nameField: 'id', + nameTitle: 'API访问日志', + onClick: onActionClick, + }, + name: 'CellOperation', + options: [ + { + code: 'view', + text: '详情', + show: hasAccessByCodes(['infra:api-access-log:query']), + }, + ], + }, + }, + ]; +} diff --git a/apps/web-antd/src/views/infra/apiAccessLog/index.vue b/apps/web-antd/src/views/infra/apiAccessLog/index.vue new file mode 100644 index 000000000..6c3c11c18 --- /dev/null +++ b/apps/web-antd/src/views/infra/apiAccessLog/index.vue @@ -0,0 +1,96 @@ + + + \ No newline at end of file diff --git a/apps/web-antd/src/views/infra/apiAccessLog/modules/detail.vue b/apps/web-antd/src/views/infra/apiAccessLog/modules/detail.vue new file mode 100644 index 000000000..1459d3270 --- /dev/null +++ b/apps/web-antd/src/views/infra/apiAccessLog/modules/detail.vue @@ -0,0 +1,86 @@ + + + diff --git a/apps/web-antd/src/views/infra/apiErrorLog/data.ts b/apps/web-antd/src/views/infra/apiErrorLog/data.ts new file mode 100644 index 000000000..62460520c --- /dev/null +++ b/apps/web-antd/src/views/infra/apiErrorLog/data.ts @@ -0,0 +1,164 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { InfraApiErrorLogApi } from '#/api/infra/api-error-log'; + +import {DICT_TYPE, getDictOptions} from '#/utils/dict'; +import { getRangePickerDefaultProps } from '#/utils/date'; +import { useAccess } from '@vben/access'; +import { InfraApiErrorLogProcessStatusEnum } from '#/utils/constants'; + +const { hasAccessByCodes } = useAccess(); + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'userId', + label: '用户编号', + component: 'Input', + componentProps: { + allowClear: true, + placeholder: '请输入用户编号', + }, + }, + { + fieldName: 'userType', + label: '用户类型', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.USER_TYPE, 'number'), + allowClear: true, + placeholder: '请选择用户类型', + }, + }, + { + fieldName: 'applicationName', + label: '应用名', + component: 'Input', + componentProps: { + allowClear: true, + placeholder: '请输入应用名', + }, + }, + { + fieldName: 'exceptionTime', + label: '异常时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + { + fieldName: 'processStatus', + label: '处理状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.INFRA_API_ERROR_LOG_PROCESS_STATUS, 'number'), + allowClear: true, + placeholder: '请选择处理状态', + }, + defaultValue: InfraApiErrorLogProcessStatusEnum.INIT, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + onActionClick: OnActionClickFn, +): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '日志编号', + minWidth: 100, + }, + { + field: 'userId', + title: '用户编号', + minWidth: 100, + }, + { + field: 'userType', + title: '用户类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.USER_TYPE }, + }, + }, + { + field: 'applicationName', + title: '应用名', + minWidth: 150, + }, + { + field: 'requestMethod', + title: '请求方法', + minWidth: 80, + }, + { + field: 'requestUrl', + title: '请求地址', + minWidth: 200, + }, + { + field: 'exceptionTime', + title: '异常发生时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'exceptionName', + title: '异常名', + minWidth: 180, + }, + { + field: 'processStatus', + title: '处理状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_API_ERROR_LOG_PROCESS_STATUS }, + }, + }, + { + field: 'operation', + title: '操作', + minWidth: 200, + align: 'center', + fixed: 'right', + cellRender: { + attrs: { + nameField: 'id', + nameTitle: 'API错误日志', + onClick: onActionClick, + }, + name: 'CellOperation', + options: [ + { + code: 'view', + text: '详情', + show: hasAccessByCodes(['infra:api-error-log:query']), + }, + { + code: 'done', + text: '已处理', + show: (row: InfraApiErrorLogApi.SystemApiErrorLog) => { + return row.processStatus === InfraApiErrorLogProcessStatusEnum.INIT && + hasAccessByCodes(['infra:api-error-log:update-status']); + }, + }, + { + code: 'ignore', + text: '已忽略', + show: (row: InfraApiErrorLogApi.SystemApiErrorLog) => { + return row.processStatus === InfraApiErrorLogProcessStatusEnum.INIT && + hasAccessByCodes(['infra:api-error-log:update-status']); + }, + }, + ], + }, + }, + ]; +} diff --git a/apps/web-antd/src/views/infra/apiErrorLog/index.vue b/apps/web-antd/src/views/infra/apiErrorLog/index.vue new file mode 100644 index 000000000..b996e0608 --- /dev/null +++ b/apps/web-antd/src/views/infra/apiErrorLog/index.vue @@ -0,0 +1,122 @@ + + + \ No newline at end of file diff --git a/apps/web-antd/src/views/infra/apiErrorLog/modules/detail.vue b/apps/web-antd/src/views/infra/apiErrorLog/modules/detail.vue new file mode 100644 index 000000000..934d3391f --- /dev/null +++ b/apps/web-antd/src/views/infra/apiErrorLog/modules/detail.vue @@ -0,0 +1,89 @@ + + +