mirror of
https://github.com/chansee97/nova-admin.git
synced 2026-04-29 18:15:42 +08:00
refactor: remove oper-log module
This commit is contained in:
parent
21b6b5874d
commit
67651d7a3f
32
package.json
32
package.json
@ -47,27 +47,27 @@
|
||||
"sizecheck": "npx vite-bundle-visualizer"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vueuse/core": "^13.7.0",
|
||||
"@vueuse/core": "^14.1.0",
|
||||
"alova": "^3.3.4",
|
||||
"array-to-tree": "^3.3.2",
|
||||
"colord": "^2.9.3",
|
||||
"echarts": "^6.0.0",
|
||||
"md-editor-v3": "^5.6.1",
|
||||
"pinia": "^3.0.3",
|
||||
"pinia-plugin-persistedstate": "^4.5.0",
|
||||
"pro-naive-ui": "^3.1.1",
|
||||
"pinia": "^3.0.4",
|
||||
"pinia-plugin-persistedstate": "^4.7.1",
|
||||
"pro-naive-ui": "^3.2.0",
|
||||
"quill": "^2.0.3",
|
||||
"radash": "^12.1.1",
|
||||
"vue": "^3.5.20",
|
||||
"vue-draggable-plus": "^0.6.0",
|
||||
"vue-i18n": "^11.1.11",
|
||||
"vue-router": "^4.5.1"
|
||||
"vue": "^3.5.26",
|
||||
"vue-draggable-plus": "^0.6.1",
|
||||
"vue-i18n": "^11.2.8",
|
||||
"vue-router": "^4.6.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^5.0.0",
|
||||
"@iconify-json/icon-park-outline": "^1.2.2",
|
||||
"@iconify/vue": "^5.0.0",
|
||||
"@types/node": "^24.1.0",
|
||||
"@types/node": "^25.0.8",
|
||||
"@vitejs/plugin-vue": "^6.0.1",
|
||||
"@vitejs/plugin-vue-jsx": "^5.0.1",
|
||||
"eslint": "^9.29.0",
|
||||
@ -78,15 +78,15 @@
|
||||
"simple-git-hooks": "^2.13.1",
|
||||
"typescript": "^5.8.3",
|
||||
"unocss": "^66.3.3",
|
||||
"unplugin-auto-import": "^19.3.0",
|
||||
"unplugin-icons": "^22.2.0",
|
||||
"unplugin-vue-components": "^28.8.0",
|
||||
"vite": "^7.0.6",
|
||||
"unplugin-auto-import": "^21.0.0",
|
||||
"unplugin-icons": "^23.0.1",
|
||||
"unplugin-vue-components": "^31.0.0",
|
||||
"vite": "^7.3.1",
|
||||
"vite-bundle-visualizer": "^1.2.1",
|
||||
"vite-plugin-auto-proxy": "^1.0.1",
|
||||
"vite-plugin-auto-proxy": "^1.0.2",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-vue-devtools": "8.0.0",
|
||||
"vue-tsc": "^3.0.5"
|
||||
"vite-plugin-vue-devtools": "8.0.5",
|
||||
"vue-tsc": "^3.2.2"
|
||||
},
|
||||
"simple-git-hooks": {
|
||||
"pre-commit": "pnpm lint-staged"
|
||||
|
||||
@ -1,31 +0,0 @@
|
||||
import { request } from '@/utils/alova'
|
||||
|
||||
export interface OperLogQueryParams extends Api.PageParams {
|
||||
}
|
||||
/**
|
||||
* 分页查询操作日志列表
|
||||
*/
|
||||
export function getOperLogPage(params: OperLogQueryParams) {
|
||||
return request.Get<Api.ListResponse<Entity.OperLog>>('/oper-log', { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取操作日志详情
|
||||
*/
|
||||
export function getOperLogDetail(id: number) {
|
||||
return request.Get<Entity.OperLog>(`/oper-log/${id}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除操作日志
|
||||
*/
|
||||
export function deleteOperLog(ids: string) {
|
||||
return request.Delete(`/oper-log/${ids}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空操作日志
|
||||
*/
|
||||
export function clearOperLog() {
|
||||
return request.Delete('/oper-log/clean')
|
||||
}
|
||||
75
src/typings/entities/oper-log.d.ts
vendored
75
src/typings/entities/oper-log.d.ts
vendored
@ -1,75 +0,0 @@
|
||||
declare namespace Entity {
|
||||
/**
|
||||
* 操作日志
|
||||
*/
|
||||
interface OperLog {
|
||||
/**
|
||||
* 日志编号
|
||||
*/
|
||||
id: number
|
||||
/**
|
||||
* 模块标题
|
||||
*/
|
||||
title: string
|
||||
/**
|
||||
* 方法名称
|
||||
*/
|
||||
method: string
|
||||
/**
|
||||
* 请求方式
|
||||
*/
|
||||
requestMethod: string
|
||||
/**
|
||||
* 操作人员
|
||||
*/
|
||||
operName: string
|
||||
/**
|
||||
* 部门名称
|
||||
*/
|
||||
deptName: string
|
||||
/**
|
||||
* 请求URL
|
||||
*/
|
||||
operUrl: string
|
||||
/**
|
||||
* 主机地址
|
||||
*/
|
||||
operIp: string
|
||||
/**
|
||||
* 操作地点
|
||||
*/
|
||||
operLocation: string
|
||||
/**
|
||||
* 浏览器类型
|
||||
*/
|
||||
browser: string
|
||||
/**
|
||||
* 操作系统
|
||||
*/
|
||||
os: string
|
||||
/**
|
||||
* 请求参数
|
||||
*/
|
||||
operParam: string
|
||||
/**
|
||||
* 返回参数
|
||||
*/
|
||||
jsonResult: string
|
||||
/**
|
||||
* 操作状态(0正常 1异常)
|
||||
*/
|
||||
status: number
|
||||
/**
|
||||
* 错误消息
|
||||
*/
|
||||
errorMsg: string
|
||||
/**
|
||||
* 消耗时间
|
||||
*/
|
||||
costTime: string
|
||||
/**
|
||||
* 操作时间
|
||||
*/
|
||||
operTime: Date
|
||||
}
|
||||
}
|
||||
@ -1,168 +0,0 @@
|
||||
import type { DataTableColumns } from 'naive-ui'
|
||||
import { NButton, NSpace, NTag } from 'naive-ui'
|
||||
import type { ProSearchFormColumns } from 'pro-naive-ui'
|
||||
import { renderProCopyableText } from 'pro-naive-ui'
|
||||
|
||||
// 操作日志搜索表单数据类型
|
||||
export interface OperationLogSearchFormData {
|
||||
operUrl?: string
|
||||
title?: string
|
||||
operName?: string
|
||||
businessType?: number
|
||||
status?: 0 | 1
|
||||
operTime?: [string, string]
|
||||
}
|
||||
|
||||
// 操作日志搜索表单列配置
|
||||
export const searchColumns: ProSearchFormColumns<OperationLogSearchFormData> = [
|
||||
{
|
||||
title: '操作地址',
|
||||
path: 'operUrl',
|
||||
field: 'input',
|
||||
fieldProps: {
|
||||
clearable: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '系统模块',
|
||||
path: 'title',
|
||||
field: 'input',
|
||||
fieldProps: {
|
||||
clearable: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '操作人员',
|
||||
path: 'operName',
|
||||
field: 'input',
|
||||
fieldProps: {
|
||||
clearable: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
path: 'status',
|
||||
field: 'select',
|
||||
fieldProps: {
|
||||
clearable: true,
|
||||
options: [
|
||||
{ label: '正常', value: 0 },
|
||||
{ label: '异常', value: 1 },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '操作时间',
|
||||
path: 'operTime',
|
||||
field: 'date-time-range',
|
||||
fieldProps: {
|
||||
clearable: true,
|
||||
format: 'yyyy-MM-dd',
|
||||
valueFormat: 'yyyy-MM-dd HH:mm:ss',
|
||||
defaultTime: ['00:00:00', '23:59:59'],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
// 表格列配置
|
||||
export function createTableColumns(options: {
|
||||
onView: (row: Entity.OperLog) => void
|
||||
onDelete: (operId: number) => void
|
||||
}): DataTableColumns<Entity.OperLog> {
|
||||
const { onView, onDelete } = options
|
||||
|
||||
return [
|
||||
{
|
||||
type: 'selection',
|
||||
width: 55,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '系统模块',
|
||||
key: 'title',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
ellipsis: {
|
||||
tooltip: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '操作人员',
|
||||
key: 'operName',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
ellipsis: {
|
||||
tooltip: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '主机地址',
|
||||
key: 'operIp',
|
||||
width: 130,
|
||||
align: 'center',
|
||||
render: row => renderProCopyableText(row.operIp),
|
||||
},
|
||||
{
|
||||
title: '操作地点',
|
||||
key: 'operLocation',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
ellipsis: {
|
||||
tooltip: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '操作状态',
|
||||
key: 'status',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
render: (row) => {
|
||||
return (
|
||||
<NTag type={row.status === 0 ? 'success' : 'error'} bordered={false}>
|
||||
{row.status === 0 ? '正常' : '异常'}
|
||||
</NTag>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '操作日期',
|
||||
key: 'operTime',
|
||||
width: 180,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '消耗时间',
|
||||
key: 'costTime',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
render: row => `${row.costTime}`,
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'actions',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
fixed: 'right',
|
||||
render: (row) => {
|
||||
return (
|
||||
<NSpace justify="center">
|
||||
<NButton
|
||||
text
|
||||
type="primary"
|
||||
onClick={() => onView(row)}
|
||||
>
|
||||
详细
|
||||
</NButton>
|
||||
<NButton
|
||||
text
|
||||
type="error"
|
||||
onClick={() => onDelete(row.id)}
|
||||
>
|
||||
删除
|
||||
</NButton>
|
||||
</NSpace>
|
||||
)
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -1,119 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { useBoolean } from '@/hooks'
|
||||
|
||||
const { bool: visible, setTrue: showModal, setFalse: hideModal } = useBoolean(false)
|
||||
|
||||
const operationLog = ref<Entity.OperLog | null>(null)
|
||||
|
||||
// 打开弹窗
|
||||
function openModal(row: Entity.OperLog) {
|
||||
operationLog.value = row
|
||||
showModal()
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
function closeModal() {
|
||||
hideModal()
|
||||
operationLog.value = null
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
openModal,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-modal
|
||||
v-model:show="visible"
|
||||
preset="card"
|
||||
title="操作日志详细"
|
||||
class="w-4/5 max-w-4xl"
|
||||
:mask-closable="false"
|
||||
>
|
||||
<div v-if="operationLog" class="space-y-4">
|
||||
<!-- 基本信息 -->
|
||||
<n-card title="基本信息" size="small">
|
||||
<n-descriptions :column="3" label-placement="left" size="small">
|
||||
<n-descriptions-item label="日志编号">
|
||||
{{ operationLog.id }}
|
||||
</n-descriptions-item>
|
||||
<n-descriptions-item label="系统模块">
|
||||
{{ operationLog.title }}
|
||||
</n-descriptions-item>
|
||||
<n-descriptions-item label="部门名称">
|
||||
{{ operationLog.deptName || '-' }}
|
||||
</n-descriptions-item>
|
||||
<n-descriptions-item label="操作状态">
|
||||
<n-tag size="small">
|
||||
{{ operationLog.status === 0 ? '正常' : '异常' }}
|
||||
</n-tag>
|
||||
</n-descriptions-item>
|
||||
<n-descriptions-item label="消耗时间">
|
||||
{{ `${operationLog.costTime}ms` }}
|
||||
</n-descriptions-item>
|
||||
<n-descriptions-item label="操作时间">
|
||||
{{ operationLog.operTime }}
|
||||
</n-descriptions-item>
|
||||
</n-descriptions>
|
||||
</n-card>
|
||||
|
||||
<!-- 请求信息 -->
|
||||
<n-card title="请求信息" size="small">
|
||||
<n-descriptions :column="2" label-placement="left" size="small">
|
||||
<n-descriptions-item label="调用方法" :span="2">
|
||||
<n-text code>
|
||||
{{ operationLog.method }}
|
||||
</n-text>
|
||||
</n-descriptions-item>
|
||||
<n-descriptions-item label="请求地址">
|
||||
<n-text code>
|
||||
{{ operationLog.operUrl }}
|
||||
</n-text>
|
||||
</n-descriptions-item>
|
||||
<n-descriptions-item label="请求方式">
|
||||
<n-tag size="small">
|
||||
{{ operationLog.requestMethod }}
|
||||
</n-tag>
|
||||
</n-descriptions-item>
|
||||
<n-descriptions-item label="主机地址">
|
||||
{{ operationLog.operIp }}
|
||||
</n-descriptions-item>
|
||||
<n-descriptions-item label="操作地点">
|
||||
{{ operationLog.operLocation }}
|
||||
</n-descriptions-item>
|
||||
</n-descriptions>
|
||||
</n-card>
|
||||
|
||||
<!-- 请求参数 -->
|
||||
<pro-card title="请求参数" size="small" :show="false">
|
||||
<n-scrollbar style="max-height: 200px">
|
||||
<pre>{{ JSON.parse(operationLog.operParam) }}</pre>
|
||||
</n-scrollbar>
|
||||
</pro-card>
|
||||
|
||||
<!-- 返回结果 -->
|
||||
<pro-card title="返回结果" size="small">
|
||||
<n-scrollbar style="max-height: 200px">
|
||||
<pre>{{ operationLog.jsonResult }}</pre>
|
||||
</n-scrollbar>
|
||||
</pro-card>
|
||||
|
||||
<!-- 异常信息 -->
|
||||
<n-card v-if="operationLog.status === 1" title="异常信息" size="small">
|
||||
<n-scrollbar style="max-height: 200px">
|
||||
<n-text type="error">
|
||||
{{ operationLog.errorMsg || '无异常信息' }}
|
||||
</n-text>
|
||||
</n-scrollbar>
|
||||
</n-card>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<div class="flex justify-end">
|
||||
<n-button @click="closeModal">
|
||||
关闭
|
||||
</n-button>
|
||||
</div>
|
||||
</template>
|
||||
</n-modal>
|
||||
</template>
|
||||
@ -1,170 +0,0 @@
|
||||
<script setup lang="tsx">
|
||||
import { createProSearchForm, useNDataTable } from 'pro-naive-ui'
|
||||
import {
|
||||
clearOperLog,
|
||||
deleteOperLog,
|
||||
getOperLogPage,
|
||||
} from '@/api/monitor/oper-log'
|
||||
import type { OperLogQueryParams } from '@/api/monitor/oper-log'
|
||||
import { createTableColumns, searchColumns } from './columns'
|
||||
import type { OperationLogSearchFormData } from './columns'
|
||||
|
||||
// 导入子组件
|
||||
import DetailModal from './components/DetailModal.vue'
|
||||
|
||||
// 弹窗引用
|
||||
const detailModalRef = ref()
|
||||
|
||||
// 创建搜索表单
|
||||
const searchForm = createProSearchForm<OperationLogSearchFormData>({
|
||||
defaultCollapsed: true,
|
||||
initialValues: {
|
||||
},
|
||||
})
|
||||
|
||||
// 使用useNDataTable
|
||||
const {
|
||||
table: {
|
||||
tableProps,
|
||||
},
|
||||
search: {
|
||||
proSearchFormProps,
|
||||
searchLoading,
|
||||
},
|
||||
refresh,
|
||||
} = useNDataTable(getList, {
|
||||
form: searchForm,
|
||||
})
|
||||
|
||||
// 批量删除相关
|
||||
const checkedRowKeys = ref<(number)[]>([])
|
||||
|
||||
/** 查询操作日志列表 */
|
||||
interface Result {
|
||||
total: number
|
||||
list: Entity.OperLog[]
|
||||
}
|
||||
async function getList({ current, pageSize }: any, formData: OperationLogSearchFormData): Promise<Result> {
|
||||
try {
|
||||
const params: OperLogQueryParams = {
|
||||
pageNum: current,
|
||||
pageSize,
|
||||
...formData,
|
||||
}
|
||||
|
||||
return getOperLogPage(params).then(res => res.data)
|
||||
}
|
||||
catch (error) {
|
||||
console.error('获取操作日志列表失败:', error)
|
||||
return {
|
||||
total: 0,
|
||||
list: [],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 查看详情 */
|
||||
function handleView(row: Entity.OperLog) {
|
||||
detailModalRef.value?.openModal(row)
|
||||
}
|
||||
|
||||
/** 删除操作日志 */
|
||||
async function handleDelete(operId: number | number[]) {
|
||||
const isBatch = Array.isArray(operId)
|
||||
const ids = isBatch ? operId.join(',') : operId.toString()
|
||||
|
||||
window.$dialog.warning({
|
||||
title: '确认删除',
|
||||
content: isBatch
|
||||
? `是否确认删除选中的 ${operId.length} 条操作日志?`
|
||||
: '是否确认删除该条操作日志?',
|
||||
positiveText: '确定删除',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
try {
|
||||
await deleteOperLog(ids)
|
||||
window.$message.success('删除成功')
|
||||
if (isBatch) {
|
||||
// 清空选中项
|
||||
checkedRowKeys.value = []
|
||||
}
|
||||
refresh()
|
||||
}
|
||||
catch (error) {
|
||||
console.error('删除操作日志失败:', error)
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/** 清空操作日志 */
|
||||
async function handleClean() {
|
||||
window.$dialog.warning({
|
||||
title: '确认清空',
|
||||
content: '是否确认清空所有操作日志数据?此操作不可恢复!',
|
||||
positiveText: '确定清空',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
try {
|
||||
await clearOperLog()
|
||||
window.$message.success('清空成功')
|
||||
refresh()
|
||||
}
|
||||
catch (error) {
|
||||
console.error('清空操作日志失败:', error)
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
// 创建表格列配置
|
||||
const columns = createTableColumns({
|
||||
onView: handleView,
|
||||
onDelete: handleDelete,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-space vertical>
|
||||
<n-card>
|
||||
<pro-search-form
|
||||
v-bind="proSearchFormProps"
|
||||
:form="searchForm"
|
||||
:columns="searchColumns"
|
||||
/>
|
||||
</n-card>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<pro-data-table
|
||||
v-bind="tableProps"
|
||||
v-model:checked-row-keys="checkedRowKeys"
|
||||
:columns="columns"
|
||||
row-key="id"
|
||||
:loading="searchLoading"
|
||||
title=" "
|
||||
>
|
||||
<template #toolbar>
|
||||
<n-flex>
|
||||
<n-button
|
||||
type="error"
|
||||
:disabled="checkedRowKeys.length === 0"
|
||||
@click="handleDelete(checkedRowKeys.map(id => Number(id)))"
|
||||
>
|
||||
<template #icon>
|
||||
<icon-park-outline-delete />
|
||||
</template>
|
||||
删除
|
||||
</n-button>
|
||||
<n-button type="warning" @click="handleClean">
|
||||
<template #icon>
|
||||
<icon-park-outline-clear />
|
||||
</template>
|
||||
清空
|
||||
</n-button>
|
||||
</n-flex>
|
||||
</template>
|
||||
</pro-data-table>
|
||||
|
||||
<!-- 详情弹窗 -->
|
||||
<DetailModal ref="detailModalRef" />
|
||||
</n-space>
|
||||
</template>
|
||||
Loading…
x
Reference in New Issue
Block a user