日志管理
This commit is contained in:
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
"daterange",
|
"daterange",
|
||||||
|
"logdata",
|
||||||
"resourcedata",
|
"resourcedata",
|
||||||
"resourcename",
|
"resourcename",
|
||||||
"rmark"
|
"rmark"
|
||||||
|
|||||||
13
frontend/src/api/log/interface/index.ts
Normal file
13
frontend/src/api/log/interface/index.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// 日志管理模块
|
||||||
|
export namespace Log {
|
||||||
|
// 日志列表
|
||||||
|
export interface LogList {
|
||||||
|
id: string;//日志表Id
|
||||||
|
content: string;//日志内容
|
||||||
|
user:string;//操作用户
|
||||||
|
record_Time:string;//记录时间
|
||||||
|
type:string;//日志类型
|
||||||
|
level:string;//日志等级
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
62
frontend/src/api/log/logData.ts
Normal file
62
frontend/src/api/log/logData.ts
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import type {Log} from "./interface"
|
||||||
|
|
||||||
|
const logdata = ref<Log.LogList[]>([
|
||||||
|
{
|
||||||
|
'id': '1',
|
||||||
|
'content': 'Admin用户09:35:47,790 登录系统',
|
||||||
|
'user':'Admin',
|
||||||
|
'record_Time':'2024-10-16 12:13:14',
|
||||||
|
'type':'操作日志',
|
||||||
|
'level':'/',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id': '2',
|
||||||
|
'content': 'Admin用户09:35:47,891 新建设备 “模拟式装置1”',
|
||||||
|
'user':'Admin',
|
||||||
|
'record_Time':'2024-10-16 12:13:14',
|
||||||
|
'type':'操作日志',
|
||||||
|
'level':'/',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id': '3',
|
||||||
|
'content': 'User用户 09:35:56,391 新建设备 “模拟式装置2”',
|
||||||
|
'user':'User',
|
||||||
|
'record_Time':'2024-10-16 12:13:14',
|
||||||
|
'type':'操作日志',
|
||||||
|
'level':'/',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id': '4',
|
||||||
|
'content': 'Admin用户09:35:59,977 对 “模拟式装置1”开始进行自动检测',
|
||||||
|
'user':'Admin',
|
||||||
|
'record_Time':'2024-10-16 12:13:14',
|
||||||
|
'type':'操作日志',
|
||||||
|
'level':'/',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id': '5',
|
||||||
|
'content': 'User用户09:36:02,229 对 “模拟式装置2”开始进行自动检测',
|
||||||
|
'user':'User',
|
||||||
|
'record_Time':'2024-10-16 12:13:14',
|
||||||
|
'type':'操作日志',
|
||||||
|
'level':'/',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id': '6',
|
||||||
|
'content': 'DKLN源回复报文异常,已丢弃。报文长度为XX,内容为:“XXXXXXX”',
|
||||||
|
'user':'Admin',
|
||||||
|
'record_Time':'2024-10-16 12:13:14',
|
||||||
|
'type':'告警日志',
|
||||||
|
'level':'WARN(警告)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id': '7',
|
||||||
|
'content': 'IP:192.168.1.205 的装置第1通道触发QVVR01报告失败',
|
||||||
|
'user':'AA',
|
||||||
|
'record_Time':'2024-10-16 12:13:14',
|
||||||
|
'type':'告警日志',
|
||||||
|
'level':'ERROR(一般错误)',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
export default logdata
|
||||||
@@ -244,6 +244,7 @@ const resourcedata = ref<Resource.ResResourceList[]>([
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
export default resourcedata
|
export default resourcedata
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- 查询表单 -->
|
<!-- 查询表单 -->
|
||||||
<SearchForm
|
<SearchForm
|
||||||
v-show="isShowSearch"
|
v-show="isShowSearch"
|
||||||
|
|||||||
36
frontend/src/components/TimeControl/index.scss
Normal file
36
frontend/src/components/TimeControl/index.scss
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/* 添加样式 */
|
||||||
|
.time-control {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin:0 0 0 300px ; /* 使整体居中 */
|
||||||
|
}
|
||||||
|
.select {
|
||||||
|
margin-right: 10px; /* 下拉框右侧间距 */
|
||||||
|
width: 90px; /* 下拉框宽度 */
|
||||||
|
}
|
||||||
|
.date-display {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 10px; /* 日期选择器右侧间距 */
|
||||||
|
width: 250px;
|
||||||
|
}
|
||||||
|
.date-picker {
|
||||||
|
margin-right: 10px; /* 日期选择器之间的间距 */
|
||||||
|
}
|
||||||
|
.triangle-button {
|
||||||
|
margin:0 2px; /* 设置左右间距 */
|
||||||
|
}
|
||||||
|
.left_triangle {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-top: 10px solid transparent; /* 上边透明 */
|
||||||
|
border-bottom: 10px solid transparent; /* 下边透明 */
|
||||||
|
border-right: 15px solid white; /* 左边为白色 */
|
||||||
|
}
|
||||||
|
.right_triangle {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-top: 10px solid transparent; /* 上边透明 */
|
||||||
|
border-bottom: 10px solid transparent; /* 下边透明 */
|
||||||
|
border-left: 15px solid white; /* 左边为白色 */
|
||||||
|
}
|
||||||
188
frontend/src/components/TimeControl/index.vue
Normal file
188
frontend/src/components/TimeControl/index.vue
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
<template>
|
||||||
|
<div class="time-control" >
|
||||||
|
<el-select
|
||||||
|
class="select"
|
||||||
|
v-model="timeUnit"
|
||||||
|
placeholder="选择时间单位"
|
||||||
|
@change="handleChange"
|
||||||
|
>
|
||||||
|
<el-option label="按日" value="日"></el-option>
|
||||||
|
<el-option label="按周" value="周"></el-option>
|
||||||
|
<el-option label="按月" value="月"></el-option>
|
||||||
|
<el-option label="按季度" value="季度"></el-option>
|
||||||
|
<el-option label="按年" value="年"></el-option>
|
||||||
|
<el-option label="自定义" value="自定义"></el-option>
|
||||||
|
</el-select>
|
||||||
|
|
||||||
|
<div class="date-display"><!-- 禁用时间选择器 -->
|
||||||
|
<el-date-picker
|
||||||
|
class="date-picker"
|
||||||
|
v-model="startDate"
|
||||||
|
type="date"
|
||||||
|
placeholder="起始时间"
|
||||||
|
:readonly="timeUnit != '自定义'"
|
||||||
|
></el-date-picker>
|
||||||
|
<el-text>~</el-text>
|
||||||
|
<el-date-picker
|
||||||
|
class="date-picker"
|
||||||
|
v-model="endDate"
|
||||||
|
type="date"
|
||||||
|
placeholder="结束时间"
|
||||||
|
:readonly="timeUnit !== '自定义'"
|
||||||
|
></el-date-picker>
|
||||||
|
</div>
|
||||||
|
<div class="date-display" v-if="timeUnit !== '自定义'">
|
||||||
|
<el-button
|
||||||
|
style="width: 10px;"
|
||||||
|
class="triangle-button"
|
||||||
|
type="primary"
|
||||||
|
@click="prevPeriod"
|
||||||
|
>
|
||||||
|
<div class="left_triangle"></div>
|
||||||
|
</el-button>
|
||||||
|
<el-button class="triangle-button" type="primary" @click="goToCurrent">
|
||||||
|
本{{ timeUnit }}
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
style="width: 10px;"
|
||||||
|
class="triangle-button"
|
||||||
|
type="primary"
|
||||||
|
@click="nextPeriod"
|
||||||
|
:disabled="isNextDisabled"
|
||||||
|
>
|
||||||
|
<div class="right_triangle"></div>
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
timeUnit: '周', // 默认选择按周
|
||||||
|
startDate: null, // 起始日期
|
||||||
|
endDate: null, // 结束日期
|
||||||
|
isNextDisabled: false, // 控制下一周期按钮的禁用状态
|
||||||
|
today: new Date() // 当前日期
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
// 组件创建时更新日期范围
|
||||||
|
this.updateDateRange();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleChange(value) {
|
||||||
|
// 根据选择的时间单位处理日期变化
|
||||||
|
if (value !== '自定义') {
|
||||||
|
this.updateDateRange();
|
||||||
|
} else {
|
||||||
|
// 自定义选项逻辑
|
||||||
|
this.startDate = new Date();
|
||||||
|
this.endDate = new Date();
|
||||||
|
}
|
||||||
|
this.updateNextButtonStatus();
|
||||||
|
},
|
||||||
|
updateDateRange() {
|
||||||
|
const today = this.today;
|
||||||
|
// 根据选择的时间单位计算起始和结束日期
|
||||||
|
if (this.timeUnit === '日') {
|
||||||
|
this.startDate = today;
|
||||||
|
this.endDate = today;
|
||||||
|
} else if (this.timeUnit === '周') {
|
||||||
|
this.startDate = this.getStartOfWeek(today);
|
||||||
|
this.endDate = this.getEndOfWeek(today);
|
||||||
|
} else if (this.timeUnit === '月') {
|
||||||
|
this.startDate = new Date(today.getFullYear(), today.getMonth(), 1);
|
||||||
|
this.endDate = new Date(today.getFullYear(), today.getMonth() + 1, 0);
|
||||||
|
} else if (this.timeUnit === '季度') {
|
||||||
|
const quarter = Math.floor(today.getMonth() / 3);
|
||||||
|
this.startDate = new Date(today.getFullYear(), quarter * 3, 1);
|
||||||
|
this.endDate = new Date(today.getFullYear(), quarter * 3 + 3, 0);
|
||||||
|
} else if (this.timeUnit === '年') {
|
||||||
|
this.startDate = new Date(today.getFullYear(), 0, 1);
|
||||||
|
this.endDate = new Date(today.getFullYear(), 11, 31);
|
||||||
|
}
|
||||||
|
this.updateNextButtonStatus();
|
||||||
|
},
|
||||||
|
getStartOfWeek(date) {
|
||||||
|
const startOfWeek = new Date(date);
|
||||||
|
const day = startOfWeek.getDay();
|
||||||
|
const diff = day === 0 ? -6 : 1 - day; // 星期天的情况
|
||||||
|
startOfWeek.setDate(startOfWeek.getDate() + diff);
|
||||||
|
return startOfWeek;
|
||||||
|
},
|
||||||
|
getEndOfWeek(date) {
|
||||||
|
const endOfWeek = new Date(date);
|
||||||
|
const day = endOfWeek.getDay();
|
||||||
|
const diff = day === 0 ? 0 : 7 - day; // 星期天的情况
|
||||||
|
endOfWeek.setDate(endOfWeek.getDate() + diff);
|
||||||
|
return endOfWeek;
|
||||||
|
},
|
||||||
|
prevPeriod() {
|
||||||
|
const prevStartDate = new Date(this.startDate);
|
||||||
|
const prevEndDate = new Date(this.endDate);
|
||||||
|
|
||||||
|
if (this.timeUnit === '日') {
|
||||||
|
prevStartDate.setDate(prevStartDate.getDate() - 1);
|
||||||
|
prevEndDate.setDate(prevEndDate.getDate() - 1);
|
||||||
|
} else if (this.timeUnit === '周') {
|
||||||
|
prevStartDate.setDate(prevStartDate.getDate() - 7);
|
||||||
|
prevEndDate.setDate(prevEndDate.getDate() - 7);
|
||||||
|
} else if (this.timeUnit === '月') {
|
||||||
|
prevStartDate.setMonth(prevStartDate.getMonth() - 1);
|
||||||
|
prevEndDate.setMonth(prevEndDate.getMonth() - 1);
|
||||||
|
} else if (this.timeUnit === '季度') {
|
||||||
|
prevStartDate.setMonth(prevStartDate.getMonth() - 3);
|
||||||
|
prevEndDate.setMonth(prevEndDate.getMonth() - 3);
|
||||||
|
} else if (this.timeUnit === '年') {
|
||||||
|
prevStartDate.setFullYear(prevStartDate.getFullYear() - 1);
|
||||||
|
prevEndDate.setFullYear(prevEndDate.getFullYear() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.startDate = prevStartDate;
|
||||||
|
this.endDate = prevEndDate;
|
||||||
|
this.updateNextButtonStatus();
|
||||||
|
},
|
||||||
|
goToCurrent() {
|
||||||
|
if (this.timeUnit !== '自定义') {
|
||||||
|
this.updateDateRange(); // 更新为当前选择时间单位的时间范围
|
||||||
|
}
|
||||||
|
},
|
||||||
|
nextPeriod() {
|
||||||
|
const nextStartDate = new Date(this.startDate);
|
||||||
|
const nextEndDate = new Date(this.endDate);
|
||||||
|
|
||||||
|
if (this.timeUnit === '日') {
|
||||||
|
nextStartDate.setDate(nextStartDate.getDate() + 1);
|
||||||
|
nextEndDate.setDate(nextEndDate.getDate() + 1);
|
||||||
|
} else if (this.timeUnit === '周') {
|
||||||
|
nextStartDate.setDate(nextStartDate.getDate() + 7);
|
||||||
|
nextEndDate.setDate(nextEndDate.getDate() + 7);
|
||||||
|
} else if (this.timeUnit === '月') {
|
||||||
|
nextStartDate.setMonth(nextStartDate.getMonth() + 1);
|
||||||
|
nextEndDate.setMonth(nextEndDate.getMonth() + 1);
|
||||||
|
} else if (this.timeUnit === '季度') {
|
||||||
|
nextStartDate.setMonth(nextStartDate.getMonth() + 3);
|
||||||
|
nextEndDate.setMonth(nextStartDate.getMonth() + 3);
|
||||||
|
} else if (this.timeUnit === '年') {
|
||||||
|
nextStartDate.setFullYear(nextStartDate.getFullYear() + 1);
|
||||||
|
nextEndDate.setFullYear(nextEndDate.getFullYear() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.startDate = nextStartDate;
|
||||||
|
this.endDate = nextEndDate;
|
||||||
|
this.updateNextButtonStatus();
|
||||||
|
},
|
||||||
|
updateNextButtonStatus() {
|
||||||
|
// 更新下一个按钮的禁用状态
|
||||||
|
const maxDate = new Date(); // 假设最新日期为今天
|
||||||
|
this.isNextDisabled = this.endDate > maxDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import "./index.scss";
|
||||||
|
</style>
|
||||||
@@ -177,9 +177,21 @@ const openEditDialog = (resource: Resource.ResResourceList) => {
|
|||||||
};
|
};
|
||||||
//批量删除
|
//批量删除
|
||||||
const handleDelList =()=>{
|
const handleDelList =()=>{
|
||||||
|
ElMessageBox.confirm(
|
||||||
|
`是否删除所选菜单信息?`, // 使用模板字符串来插值
|
||||||
|
'温馨提示',
|
||||||
|
{
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(() => {
|
||||||
resourceData.value = resourceData.value.filter(item => !multipleSelection.value.includes(item.id));
|
resourceData.value = resourceData.value.filter(item => !multipleSelection.value.includes(item.id));
|
||||||
multipleSelection.value = []; // Clear selected rows
|
multipleSelection.value = []; // Clear selected rows
|
||||||
ElMessage.success("批量删除成功");
|
ElMessage.success("批量删除成功");
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
// 删除资源
|
// 删除资源
|
||||||
const deleteResource = (params: Resource.ResResourceList) => {
|
const deleteResource = (params: Resource.ResResourceList) => {
|
||||||
|
|||||||
82
frontend/src/views/log/index.vue
Normal file
82
frontend/src/views/log/index.vue
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
<template>
|
||||||
|
<div class='table-box'>
|
||||||
|
<ProTable
|
||||||
|
ref='proTable'
|
||||||
|
:columns='columns'
|
||||||
|
:data='logData'
|
||||||
|
@selection-change="handleSelectionChange"
|
||||||
|
type="selection"
|
||||||
|
>
|
||||||
|
<!-- 表格 header 按钮 -->
|
||||||
|
<template #tableHeader>
|
||||||
|
<el-button type='primary' :icon='Upload'>导出csv</el-button>
|
||||||
|
</template>
|
||||||
|
</ProTable>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<script setup lang='tsx' name='useProTable'>
|
||||||
|
import TimeControl from '@/components/TimeControl/index.vue'; // 根据实际路径调整
|
||||||
|
import { defineComponent,ref ,reactive} from 'vue'
|
||||||
|
import {type Log } from '@/api/log/interface'
|
||||||
|
import ProTable from '@/components/ProTable/index.vue'
|
||||||
|
import {Upload} from '@element-plus/icons-vue'
|
||||||
|
import logDataList from '@/api/log/logData'
|
||||||
|
import type { ColumnProps, ProTableInstance } from '@/components/ProTable/interface'
|
||||||
|
let multipleSelection = ref<string[]>([]);
|
||||||
|
const logData = logDataList
|
||||||
|
|
||||||
|
// ProTable 实例
|
||||||
|
const proTable = ref<ProTableInstance>()
|
||||||
|
// 表格配置项
|
||||||
|
const columns = reactive<ColumnProps<Log.LogList>[]>([
|
||||||
|
{ type: 'selection', fixed: 'left', width: 50 },
|
||||||
|
{
|
||||||
|
prop: 'content',
|
||||||
|
label: '内容',
|
||||||
|
width: 600,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'record_Time',
|
||||||
|
label: '记录时间',
|
||||||
|
width: 180,
|
||||||
|
search: {
|
||||||
|
// 自定义 search 显示内容
|
||||||
|
render: ({ searchParam }) => {
|
||||||
|
return (
|
||||||
|
<div class='flx-center'>
|
||||||
|
<TimeControl/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'user',
|
||||||
|
label: '操作用户',
|
||||||
|
search: { el: 'select', props: { filterable: true } },
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
prop: 'type',
|
||||||
|
label: '日志类型',
|
||||||
|
search: { el: 'select', props: { filterable: true } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'level',
|
||||||
|
label: '日志等级',
|
||||||
|
search: { el: 'select', props: { filterable: true } },
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
//选中
|
||||||
|
// 处理选择变化
|
||||||
|
const handleSelectionChange = (selection:Log.LogList[]) => {
|
||||||
|
multipleSelection.value = selection.map(row => row.id); // 更新选中的行
|
||||||
|
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user