From 838592253a98d3fef281e84b0d3ab7ddff6b8e2c Mon Sep 17 00:00:00 2001 From: dap1 <15891557205@163.com> Date: Sat, 10 Jun 2023 13:04:32 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=E6=93=8D=E4=BD=9C=E6=97=A5?= =?UTF-8?q?=E6=9C=9F=E8=AF=A6=E6=83=85=E6=9F=A5=E7=9C=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Table/src/hooks/useRender.ts | 20 +++ src/views/system/operatelog/LogInfoModal.vue | 27 ++++ src/views/system/operatelog/index.vue | 31 ++++- .../system/operatelog/operateLog.data.ts | 116 ++++++++++++++++-- 4 files changed, 181 insertions(+), 13 deletions(-) create mode 100644 src/views/system/operatelog/LogInfoModal.vue diff --git a/src/components/Table/src/hooks/useRender.ts b/src/components/Table/src/hooks/useRender.ts index a7e4eb1a..af1bc4a4 100644 --- a/src/components/Table/src/hooks/useRender.ts +++ b/src/components/Table/src/hooks/useRender.ts @@ -5,6 +5,7 @@ import { isArray, isString } from '@/utils/is' import { DictTag } from '@/components/DictTag' import { Icon } from '@/components/Icon' import TableImg from '../components/TableImg.vue' +import { JsonPreview } from '@/components/CodeEditor' export const useRender = { /** @@ -112,5 +113,24 @@ export const useRender = { if (text) { return h(Icon, { icon: text }) } + }, + /** + * 使用JsonPreview组件 方便预览JSON + * @param json json字符串/obj + * @returns 能转为json返回JsonPreview 否则返回自身 + */ + renderJsonPreview: (json: any) => { + if (!json) return '' + if (typeof json === 'object') { + return h(JsonPreview, { data: json }) + } + if (typeof json === 'string') { + try { + const data = JSON.parse(json) + return h(JsonPreview, { data }) + } catch (e) { + return json + } + } } } diff --git a/src/views/system/operatelog/LogInfoModal.vue b/src/views/system/operatelog/LogInfoModal.vue new file mode 100644 index 00000000..63d1971b --- /dev/null +++ b/src/views/system/operatelog/LogInfoModal.vue @@ -0,0 +1,27 @@ +<template> + <BasicModal v-bind="$attrs" title="操作日志详情" @register="registerModalInner"> + <Description @register="registerDescription" /> + </BasicModal> +</template> + +<script setup lang="ts"> +import { BasicModal, useModalInner } from '@/components/Modal' +import { Description, useDescription } from '@/components/Description/index' +import { ref } from 'vue' +import { infoSchema } from './operateLog.data' + +defineOptions({ name: 'OperLogInfoModal' }) + +const logData = ref() +const [registerModalInner] = useModalInner((record: Recordable) => { + logData.value = record +}) + +const [registerDescription] = useDescription({ + column: 1, + schema: infoSchema, + data: logData +}) +</script> + +<style scoped></style> diff --git a/src/views/system/operatelog/index.vue b/src/views/system/operatelog/index.vue index c5f28a83..93fbd163 100644 --- a/src/views/system/operatelog/index.vue +++ b/src/views/system/operatelog/index.vue @@ -4,16 +4,32 @@ <template #toolbar> <a-button type="warning" :preIcon="IconEnum.EXPORT" @click="handleExport"> {{ t('action.export') }} </a-button> </template> + <template #bodyCell="{ column, record }"> + <template v-if="column.key === 'action'"> + <TableAction + :actions="[ + { + icon: IconEnum.VIEW, + label: t('action.detail'), + onClick: handleShowInfo.bind(null, record) + } + ]" + /> + </template> + </template> </BasicTable> + <OperLogInfoModal @register="registerModal" /> </div> </template> <script lang="ts" setup> import { useI18n } from '@/hooks/web/useI18n' import { useMessage } from '@/hooks/web/useMessage' import { IconEnum } from '@/enums/appEnum' -import { BasicTable, useTable } from '@/components/Table' +import { BasicTable, useTable, TableAction } from '@/components/Table' import { OperateLogPageReqVO, exportOperateLog, getOperateLogPage } from '@/api/system/operatelog' import { columns, searchFormSchema } from './operateLog.data' +import { useModal } from '@/components/Modal' +import OperLogInfoModal from './LogInfoModal.vue' defineOptions({ name: 'SystemOperateLog' }) @@ -26,7 +42,13 @@ const [registerTable, { getForm }] = useTable({ formConfig: { labelWidth: 120, schemas: searchFormSchema }, useSearchForm: true, showTableSetting: true, - showIndexColumn: false + showIndexColumn: false, + actionColumn: { + width: 140, + title: t('common.action'), + dataIndex: 'action', + fixed: 'right' + } }) async function handleExport() { @@ -40,4 +62,9 @@ async function handleExport() { } }) } + +const [registerModal, { openModal }] = useModal() +function handleShowInfo(record: Recordable) { + openModal(true, record) +} </script> diff --git a/src/views/system/operatelog/operateLog.data.ts b/src/views/system/operatelog/operateLog.data.ts index 8e0473c4..d509b9e3 100644 --- a/src/views/system/operatelog/operateLog.data.ts +++ b/src/views/system/operatelog/operateLog.data.ts @@ -1,5 +1,6 @@ import { BasicColumn, FormSchema, useRender } from '@/components/Table' import { DICT_TYPE, getDictOptions } from '@/utils/dict' +import { DescItem } from '@/components/Description/index' export const columns: BasicColumn[] = [ { @@ -10,7 +11,7 @@ export const columns: BasicColumn[] = [ { title: '操作模块', dataIndex: 'module', - width: 120 + width: 200 }, { title: '操作名', @@ -20,7 +21,7 @@ export const columns: BasicColumn[] = [ { title: '操作类型', dataIndex: 'type', - width: 180, + width: 120, customRender: ({ text }) => { return useRender.renderDict(text, DICT_TYPE.SYSTEM_OPERATE_TYPE) } @@ -30,10 +31,14 @@ export const columns: BasicColumn[] = [ dataIndex: 'userNickname', width: 120 }, + // { + // title: 'userAgent', + // dataIndex: 'userAgent', + // width: 400 + // }, { - title: 'userAgent', - dataIndex: 'userAgent', - width: 400 + title: '请求路径', + dataIndex: 'requestUrl' }, { title: '操作结果', @@ -44,19 +49,19 @@ export const columns: BasicColumn[] = [ } }, { - title: '操作日期', - dataIndex: 'startTime', + title: '执行时长', + dataIndex: 'duration', width: 180, customRender: ({ text }) => { - return useRender.renderDate(text) + return useRender.renderText(text, 'ms') } }, { - title: '执行时长', - dataIndex: 'duration', + title: '操作日期', + dataIndex: 'startTime', width: 180, customRender: ({ text }) => { - return useRender.renderText(text, 'ms') + return useRender.renderDate(text) } } ] @@ -102,3 +107,92 @@ export const searchFormSchema: FormSchema[] = [ colProps: { span: 8 } } ] + +const httpMethods = [ + { value: 'GET', color: '#108ee9' }, + { value: 'POST', color: '#2db7f5' }, + { value: 'PUT', color: 'warning' }, + { value: 'DELETE', color: '#f50' } +] + +export const infoSchema: DescItem[] = [ + { + field: 'module', + label: '操作模块' + }, + { + field: 'name', + label: '操作名' + }, + { + field: 'userNickname', + label: '操作人', + render(_, data) { + const { userNickname, userId } = data + return useRender.renderText(userNickname, 'uid: ' + userId) + } + }, + { + field: 'resultCode', + label: '请求结果', + render(value) { + return useRender.renderTag(value === 0 ? '成功' : '失败', value === 0 ? '#87d068' : '#f50') + } + }, + { + field: 'resultMsg', + label: '响应信息', + show(data) { + return data && data.resultMsg && data.resultMsg !== '' + } + }, + { + field: 'userIp', + label: '请求ip' + }, + { + field: 'startTime', + label: '请求时间', + render(value) { + return useRender.renderDate(value) + } + }, + { + field: 'requestUrl', + label: '请求路径' + }, + { + field: 'requestMethod', + label: '请求方法', + render(value) { + const current = httpMethods.find((item) => item.value === value.toUpperCase()) + if (current) { + return useRender.renderTag(value, current.color) + } + return value + } + }, + { + field: 'javaMethod', + label: '操作方法', + labelMinWidth: 80 + }, + { + field: 'javaMethodArgs', + label: '请求参数', + render(value) { + return useRender.renderJsonPreview(value) + } + }, + { + field: 'userAgent', + label: 'userAgent' + }, + { + field: 'duration', + label: '请求耗时', + render(value) { + return useRender.renderText(value, 'ms') + } + } +] From 02d0c92e8993f2f0c2bee36fb2f1914b6410f7f8 Mon Sep 17 00:00:00 2001 From: dap1 <15891557205@163.com> Date: Sat, 10 Jun 2023 13:47:57 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=E5=AD=97=E5=85=B8=E6=A0=87?= =?UTF-8?q?=E7=AD=BE=E4=BF=AE=E6=94=B9=E6=94=AF=E6=8C=81=E9=A2=84=E8=A7=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/system/dict/dict.data.ts | 126 ++++++++++++++++------------- 1 file changed, 71 insertions(+), 55 deletions(-) diff --git a/src/views/system/dict/dict.data.ts b/src/views/system/dict/dict.data.ts index b1173b99..1d21ed9e 100644 --- a/src/views/system/dict/dict.data.ts +++ b/src/views/system/dict/dict.data.ts @@ -1,6 +1,74 @@ import { BasicColumn, FormSchema, useRender } from '@/components/Table' import { DICT_TYPE, getDictOptions } from '@/utils/dict' +const options = [ + { + value: '', + label: '无' + }, + { + value: 'processing', + label: '主要' + }, + { + value: 'success', + label: '成功' + }, + { + value: 'default', + label: '默认' + }, + { + value: 'warning', + label: '警告' + }, + { + value: 'error', + label: '危险' + }, + { + value: 'pink', + label: 'pink' + }, + { + value: 'red', + label: 'red' + }, + { + value: 'orange', + label: 'orange' + }, + { + value: 'green', + label: 'green' + }, + { + value: 'cyan', + label: 'cyan' + }, + { + value: 'blue', + label: 'blue' + }, + { + value: 'purple', + label: 'purple' + } +] + +function previewOptions() { + return options.map((option) => { + const { value, label } = option + if (value === '') { + return option + } + return { + label: useRender.renderTag(label, value), + value + } + }) +} + export const dataColumns: BasicColumn[] = [ { title: '字典编码', @@ -119,67 +187,15 @@ export const dataFormSchema: FormSchema[] = [ field: 'colorType', component: 'Select', componentProps: { - options: [ - { - value: '', - label: '空' - }, - { - value: 'processing', - label: '主要' - }, - { - value: 'success', - label: '成功' - }, - { - value: 'default', - label: '默认' - }, - { - value: 'warning', - label: '警告' - }, - { - value: 'error', - label: '危险' - }, - { - value: 'pink', - label: 'pink' - }, - { - value: 'red', - label: 'red' - }, - { - value: 'orange', - label: 'orange' - }, - { - value: 'green', - label: 'green' - }, - { - value: 'cyan', - label: 'cyan' - }, - { - value: 'blue', - label: 'blue' - }, - { - value: 'purple', - label: 'purple' - } - ] + options: previewOptions() } }, { label: 'CSS Class', field: 'cssClass', component: 'Input', - helpMessage: '输入hex模式的颜色,例如#108ee9' + helpMessage: '输入hex模式的颜色, 例如#108ee9', + rules: [{ required: false, message: '输入正确的16进制颜色', pattern: /^#([0-9a-fA-F]{3}){1,2}$/, trigger: 'blur' }] }, { label: '备注', From dae144ccf9ad27f7599a97463924562d8cbf5cf6 Mon Sep 17 00:00:00 2001 From: dap1 <15891557205@163.com> Date: Sat, 10 Jun 2023 20:03:00 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20=E4=B8=80=E4=BA=9B=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E7=9A=84=E8=AF=A6=E6=83=85=E6=9F=A5=E7=9C=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../infra/apiAccessLog/AccessLogModal.vue | 27 ++++ .../infra/apiAccessLog/apiAccessLog.data.ts | 104 ++++++++++++- src/views/infra/apiAccessLog/index.vue | 31 +++- src/views/infra/apiErrorLog/ErrorLogModal.vue | 27 ++++ .../infra/apiErrorLog/apiErrorLog.data.ts | 139 ++++++++++++++++++ src/views/infra/apiErrorLog/index.vue | 15 +- .../system/operatelog/operateLog.data.ts | 25 ++-- 7 files changed, 353 insertions(+), 15 deletions(-) create mode 100644 src/views/infra/apiAccessLog/AccessLogModal.vue create mode 100644 src/views/infra/apiErrorLog/ErrorLogModal.vue diff --git a/src/views/infra/apiAccessLog/AccessLogModal.vue b/src/views/infra/apiAccessLog/AccessLogModal.vue new file mode 100644 index 00000000..45a65715 --- /dev/null +++ b/src/views/infra/apiAccessLog/AccessLogModal.vue @@ -0,0 +1,27 @@ +<template> + <BasicModal v-bind="$attrs" title="访问日志详情" @register="registerModalInner" @ok="closeModal" width="800px"> + <Description @register="registerDescription" /> + </BasicModal> +</template> + +<script setup lang="ts"> +import { BasicModal, useModalInner } from '@/components/Modal' +import { Description, useDescription } from '@/components/Description/index' +import { ref } from 'vue' +import { infoSchema } from './apiAccessLog.data' + +defineOptions({ name: 'AcessLogModal' }) + +const logData = ref() +const [registerModalInner, { closeModal }] = useModalInner((record: Recordable) => { + logData.value = record +}) + +const [registerDescription] = useDescription({ + column: 1, + schema: infoSchema, + data: logData +}) +</script> + +<style scoped></style> diff --git a/src/views/infra/apiAccessLog/apiAccessLog.data.ts b/src/views/infra/apiAccessLog/apiAccessLog.data.ts index 12bb65a2..eae52ff0 100644 --- a/src/views/infra/apiAccessLog/apiAccessLog.data.ts +++ b/src/views/infra/apiAccessLog/apiAccessLog.data.ts @@ -1,5 +1,7 @@ import { BasicColumn, FormSchema, useRender } from '@/components/Table' import { DICT_TYPE, getDictOptions } from '@/utils/dict' +import { DescItem } from '@/components/Description/index' +import { h } from 'vue' export const columns: BasicColumn[] = [ { @@ -58,7 +60,7 @@ export const columns: BasicColumn[] = [ ellipsis: true, customRender: ({ record }) => { const success = record.resultCode === 0 - return useRender.renderTag(success ? '成功' : '失败(' + record.resultMsg + ')', success ? '#87d068' : '#f50') + return useRender.renderTag(success ? '成功' : '失败', success ? '#87d068' : '#f50') } } ] @@ -110,3 +112,103 @@ export const searchFormSchema: FormSchema[] = [ colProps: { span: 8 } } ] + +const httpMethods = [ + { value: 'GET', color: '#108ee9' }, + { value: 'POST', color: '#2db7f5' }, + { value: 'PUT', color: 'warning' }, + { value: 'DELETE', color: '#f50' } +] + +export const infoSchema: DescItem[] = [ + { + label: '日志id', + field: 'id' + }, + { + label: '链路id', + field: 'traceId', + show: (data) => data && data.traceId && data.traceId !== '' + }, + { + label: '应用名称', + field: 'applicationName', + labelMinWidth: 100 + }, + { + field: 'userId', + label: '用户id', + render(value, data) { + const tag = useRender.renderDict(data.userType, DICT_TYPE.USER_TYPE) + const uidTag = useRender.renderTag('uid: ' + value) + return h('span', {}, [tag, uidTag]) + } + }, + { + field: 'resultCode', + label: '请求结果', + render(value) { + return useRender.renderTag(value === 0 ? '成功' : '失败', value === 0 ? '#87d068' : '#f50') + } + }, + { + field: 'resultMsg', + label: '响应信息', + show(data) { + return data && data.resultMsg && data.resultMsg !== '' + }, + render(value) { + return h('span', { style: { color: 'red', fontWeight: 'bold' } }, value) + } + }, + { + field: 'userIp', + label: '请求ip' + }, + { + field: 'userAgent', + label: 'userAgent' + }, + { + field: 'beginTime', + label: '请求时间', + render(value) { + return useRender.renderDate(value) + } + }, + { + field: 'requestUrl', + label: '请求路径', + render(_, data) { + if (!data) { + return '' + } + const { requestMethod, requestUrl } = data + const current = httpMethods.find((item) => item.value === requestMethod.toUpperCase()) + const methodTag = current ? useRender.renderTag(requestMethod, current.color) : requestMethod + return h('span', {}, [methodTag, requestUrl]) + } + }, + { + field: 'beginTime', + label: '请求开始时间', + render(value) { + return useRender.renderDate(value) + } + }, + { + field: 'endTime', + label: '请求结束时间', + render(value) { + return useRender.renderDate(value) + } + }, + { + field: 'duration', + label: '请求耗时', + render(value) { + // 为0的话需要转为string 否则不会显示 + return useRender.renderText(String(value), 'ms') + } + } +] diff --git a/src/views/infra/apiAccessLog/index.vue b/src/views/infra/apiAccessLog/index.vue index ce222317..dd9ee2ec 100644 --- a/src/views/infra/apiAccessLog/index.vue +++ b/src/views/infra/apiAccessLog/index.vue @@ -6,16 +6,32 @@ {{ t('action.export') }} </a-button> </template> + <template #bodyCell="{ column, record }"> + <template v-if="column.key === 'action'"> + <TableAction + :actions="[ + { + icon: IconEnum.VIEW, + label: t('action.detail'), + onClick: handleShowInfo.bind(null, record) + } + ]" + /> + </template> + </template> </BasicTable> + <AccessLogModal @register="registerModal" /> </div> </template> <script lang="ts" setup> import { useI18n } from '@/hooks/web/useI18n' import { useMessage } from '@/hooks/web/useMessage' -import { BasicTable, useTable } from '@/components/Table' +import { BasicTable, useTable, TableAction } from '@/components/Table' import { IconEnum } from '@/enums/appEnum' import { getApiAccessLogPage, exportApiAccessLog, ApiAccessLogExportReqVO } from '@/api/infra/apiAccessLog' import { columns, searchFormSchema } from './apiAccessLog.data' +import { useModal } from '@/components/Modal' +import AccessLogModal from './AccessLogModal.vue' defineOptions({ name: 'InfraApiErrorLog' }) @@ -28,9 +44,20 @@ const [registerTable, { getForm }] = useTable({ formConfig: { labelWidth: 120, schemas: searchFormSchema }, useSearchForm: true, showTableSetting: true, - showIndexColumn: false + showIndexColumn: false, + actionColumn: { + width: 120, + title: t('common.action'), + dataIndex: 'action', + fixed: 'right' + } }) +const [registerModal, { openModal }] = useModal() +function handleShowInfo(record: Recordable) { + openModal(true, record) +} + async function handleExport() { createConfirm({ title: t('common.exportTitle'), diff --git a/src/views/infra/apiErrorLog/ErrorLogModal.vue b/src/views/infra/apiErrorLog/ErrorLogModal.vue new file mode 100644 index 00000000..c3be60c2 --- /dev/null +++ b/src/views/infra/apiErrorLog/ErrorLogModal.vue @@ -0,0 +1,27 @@ +<template> + <BasicModal v-bind="$attrs" title="错误日志详情" @register="registerModalInner" @ok="closeModal" width="800px"> + <Description @register="registerDescription" /> + </BasicModal> +</template> + +<script setup lang="ts"> +import { BasicModal, useModalInner } from '@/components/Modal' +import { Description, useDescription } from '@/components/Description/index' +import { ref } from 'vue' +import { infoSchema } from './apiErrorLog.data' + +defineOptions({ name: 'ErrorLogModal' }) + +const logData = ref() +const [registerModalInner, { closeModal }] = useModalInner((record: Recordable) => { + logData.value = record +}) + +const [registerDescription] = useDescription({ + column: 1, + schema: infoSchema, + data: logData +}) +</script> + +<style scoped></style> diff --git a/src/views/infra/apiErrorLog/apiErrorLog.data.ts b/src/views/infra/apiErrorLog/apiErrorLog.data.ts index f3191681..bdc55f71 100644 --- a/src/views/infra/apiErrorLog/apiErrorLog.data.ts +++ b/src/views/infra/apiErrorLog/apiErrorLog.data.ts @@ -1,5 +1,8 @@ import { BasicColumn, FormSchema, useRender } from '@/components/Table' import { DICT_TYPE, getDictOptions } from '@/utils/dict' +import { Textarea } from 'ant-design-vue' +import { h } from 'vue' +import { DescItem } from '@/components/Description/index' export const columns: BasicColumn[] = [ { @@ -108,3 +111,139 @@ export const searchFormSchema: FormSchema[] = [ colProps: { span: 8 } } ] + +function renderText(value: string, color: string, bold = true) { + return h('span', { style: { color, fontWeight: bold ? 'bold' : 'normal' } }, value) +} + +const httpMethods = [ + { value: 'GET', color: '#108ee9' }, + { value: 'POST', color: '#2db7f5' }, + { value: 'PUT', color: 'warning' }, + { value: 'DELETE', color: '#f50' } +] + +export const infoSchema: DescItem[] = [ + { + field: 'id', + label: '异常id' + }, + { + field: 'traceId', + label: '链路ID', + show(data) { + return data && data.traceId && data.traceId !== '' + } + }, + { + field: 'applicationName', + label: '应用名称', + labelMinWidth: 100 + }, + { + field: 'processStatus', + label: '处理状态', + render(_, data) { + const { processStatus, processUserId } = data + const tag = useRender.renderDict(processStatus, DICT_TYPE.INFRA_API_ERROR_LOG_PROCESS_STATUS) + if (!processUserId) { + return tag + } + const uidTag = useRender.renderTag('uid: ' + processUserId) + return h('span', {}, [tag, uidTag]) + } + }, + { + field: 'processTime', + label: '处理时间', + show(data) { + return data && data.processTime && data.processTime !== '' + }, + render(value) { + return useRender.renderDate(value) + } + }, + { + field: 'userId', + label: '用户id', + render(value, data) { + const tag = useRender.renderDict(data.userType, DICT_TYPE.USER_TYPE) + const uidTag = useRender.renderTag('uid: ' + value) + return h('span', {}, [tag, uidTag]) + } + }, + { + field: 'userIp', + label: 'ip地址' + }, + { + field: 'requestUrl', + label: '请求地址', + render(_, data) { + if (data) { + const { requestMethod } = data + const current = httpMethods.find((item) => item.value === requestMethod) + const tag = current ? useRender.renderTag(requestMethod, current.color) : requestMethod + return h('span', {}, [tag, data.requestUrl]) + } + } + }, + { + field: 'requestParams', + label: '请求参数', + render(value) { + return useRender.renderJsonPreview(value) + } + }, + { + field: 'userAgent', + label: 'userAgent' + }, + { + field: 'exceptionTime', + label: '异常时间', + render(value) { + return useRender.renderDate(value) + } + }, + { + field: 'exceptionClassName', + label: '异常类名/方法', + render(_, data) { + if (data) { + return renderText(data.exceptionClassName + ' / ' + data.exceptionMethodName, 'red') + } + } + }, + { + field: 'exceptionMessage', + label: '异常信息', + render(value) { + return renderText(value, 'red') + } + }, + { + field: 'exceptionFileName', + label: '异常文件名', + render(_, data) { + if (data) { + return useRender.renderText(data.exceptionFileName, 'Line: ' + data.exceptionLineNumber) + } + } + }, + { + field: 'exceptionName', + label: '异常名称' + }, + { + field: 'exceptionRootCauseMessage', + label: '异常信息' + }, + { + field: 'exceptionStackTrace', + label: '异常堆栈', + render(value) { + return h(Textarea, { value, readonly: true, style: { minHeight: '300px' } }) + } + } +] diff --git a/src/views/infra/apiErrorLog/index.vue b/src/views/infra/apiErrorLog/index.vue index b018151c..ddd53998 100644 --- a/src/views/infra/apiErrorLog/index.vue +++ b/src/views/infra/apiErrorLog/index.vue @@ -10,6 +10,11 @@ <template v-if="column.key === 'action'"> <TableAction :actions="[ + { + icon: IconEnum.VIEW, + label: t('action.detail'), + onClick: handleShowInfo.bind(null, record) + }, { icon: IconEnum.EDIT, label: '已处理', @@ -29,6 +34,7 @@ </template> </template> </BasicTable> + <ErrorLogModal @register="registerModal" /> </div> </template> <script lang="ts" setup> @@ -39,6 +45,8 @@ import { useMessage } from '@/hooks/web/useMessage' import { BasicTable, useTable, TableAction } from '@/components/Table' import { updateApiErrorLogProcess, getApiErrorLogPage, exportApiErrorLog, ApiErrorLogExportReqVO } from '@/api/infra/apiErrorLog' import { columns, searchFormSchema } from './apiErrorLog.data' +import { useModal } from '@/components/Modal' +import ErrorLogModal from './ErrorLogModal.vue' defineOptions({ name: 'InfraApiErrorLog' }) @@ -53,13 +61,18 @@ const [registerTable, { getForm, reload }] = useTable({ showTableSetting: true, showIndexColumn: false, actionColumn: { - width: 180, + width: 220, title: t('common.action'), dataIndex: 'action', fixed: 'right' } }) +const [registerModal, { openModal }] = useModal() +function handleShowInfo(record: Recordable) { + openModal(true, record) +} + function handleProcessClick(record, processStatus: number, type: string) { createConfirm({ iconType: 'warning', diff --git a/src/views/system/operatelog/operateLog.data.ts b/src/views/system/operatelog/operateLog.data.ts index d509b9e3..f6bffe7e 100644 --- a/src/views/system/operatelog/operateLog.data.ts +++ b/src/views/system/operatelog/operateLog.data.ts @@ -1,6 +1,7 @@ import { BasicColumn, FormSchema, useRender } from '@/components/Table' import { DICT_TYPE, getDictOptions } from '@/utils/dict' import { DescItem } from '@/components/Description/index' +import { h } from 'vue' export const columns: BasicColumn[] = [ { @@ -129,7 +130,8 @@ export const infoSchema: DescItem[] = [ label: '操作人', render(_, data) { const { userNickname, userId } = data - return useRender.renderText(userNickname, 'uid: ' + userId) + // return useRender.renderText(userNickname, 'uid: ' + userId) + return useRender.renderTags([userNickname, 'uid: ' + userId]) } }, { @@ -144,6 +146,9 @@ export const infoSchema: DescItem[] = [ label: '响应信息', show(data) { return data && data.resultMsg && data.resultMsg !== '' + }, + render(value) { + return h('span', { style: { color: 'red', fontWeight: 'bold' } }, value) } }, { @@ -159,17 +164,15 @@ export const infoSchema: DescItem[] = [ }, { field: 'requestUrl', - label: '请求路径' - }, - { - field: 'requestMethod', - label: '请求方法', - render(value) { - const current = httpMethods.find((item) => item.value === value.toUpperCase()) - if (current) { - return useRender.renderTag(value, current.color) + label: '请求路径', + render(_, data) { + if (!data) { + return '' } - return value + const { requestMethod, requestUrl } = data + const current = httpMethods.find((item) => item.value === requestMethod.toUpperCase()) + const methodTag = current ? useRender.renderTag(requestMethod, current.color) : requestMethod + return h('span', {}, [methodTag, requestUrl]) } }, { From ebadd364ca4dc318cdd1d484f86a3f2118bd00a4 Mon Sep 17 00:00:00 2001 From: dap1 <15891557205@163.com> Date: Sat, 10 Jun 2023 20:07:57 +0800 Subject: [PATCH 4/5] =?UTF-8?q?fix:=20=E8=AF=B7=E6=B1=82=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E6=BC=8F=E6=8E=89=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/infra/apiAccessLog/apiAccessLog.data.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/views/infra/apiAccessLog/apiAccessLog.data.ts b/src/views/infra/apiAccessLog/apiAccessLog.data.ts index eae52ff0..21926cc1 100644 --- a/src/views/infra/apiAccessLog/apiAccessLog.data.ts +++ b/src/views/infra/apiAccessLog/apiAccessLog.data.ts @@ -189,6 +189,13 @@ export const infoSchema: DescItem[] = [ return h('span', {}, [methodTag, requestUrl]) } }, + { + field: 'requestParams', + label: '请求参数', + render(value) { + return useRender.renderJsonPreview(value) + } + }, { field: 'beginTime', label: '请求开始时间', From f5dc15f2bbbb8f4a75a326e9c1929140c93e4121 Mon Sep 17 00:00:00 2001 From: dap1 <15891557205@163.com> Date: Sat, 10 Jun 2023 20:11:58 +0800 Subject: [PATCH 5/5] =?UTF-8?q?fix:=20=E6=93=8D=E4=BD=9C=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E5=85=B3=E9=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/system/operatelog/LogInfoModal.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/system/operatelog/LogInfoModal.vue b/src/views/system/operatelog/LogInfoModal.vue index 63d1971b..263ceea3 100644 --- a/src/views/system/operatelog/LogInfoModal.vue +++ b/src/views/system/operatelog/LogInfoModal.vue @@ -1,5 +1,5 @@ <template> - <BasicModal v-bind="$attrs" title="操作日志详情" @register="registerModalInner"> + <BasicModal v-bind="$attrs" title="操作日志详情" @register="registerModalInner" @ok="closeModal" width="800px"> <Description @register="registerDescription" /> </BasicModal> </template> @@ -13,7 +13,7 @@ import { infoSchema } from './operateLog.data' defineOptions({ name: 'OperLogInfoModal' }) const logData = ref() -const [registerModalInner] = useModalInner((record: Recordable) => { +const [registerModalInner, { closeModal }] = useModalInner((record: Recordable) => { logData.value = record })