mirror of
https://github.com/bjdgyc/anylink.git
synced 2025-08-08 06:32:04 +08:00
新增用户活动日志
This commit is contained in:
321
web/src/components/audit/Access.vue
Normal file
321
web/src/components/audit/Access.vue
Normal file
@@ -0,0 +1,321 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form :model="searchForm" :rules="rules" ref="searchForm" :inline="true" class="search-form">
|
||||
<el-form-item label="用户名:" prop="username">
|
||||
<el-input size="mini" v-model="searchForm.username" clearable style="width: 130px" @keydown.enter.native="searchEnterFun"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="源IP地址:" prop="src">
|
||||
<el-input size="mini" v-model="searchForm.src" clearable style="width: 130px" @keydown.enter.native="searchEnterFun"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="目的IP地址:" prop="dst">
|
||||
<el-input size="mini" v-model="searchForm.dst" clearable style="width: 130px" @keydown.enter.native="searchEnterFun"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="目的端口:" prop="dst_port">
|
||||
<el-input size="mini" v-model="searchForm.dst_port" clearable style="width: 80px" @keydown.enter.native="searchEnterFun"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="访问协议:">
|
||||
<el-select size="mini" v-model="searchForm.access_proto" clearable placeholder="请选择" style="width: 100px">
|
||||
<el-option v-for="(item,index) in access_proto" :key="index" :label="item.text" :value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="日期范围:">
|
||||
<el-date-picker
|
||||
v-model="searchForm.date"
|
||||
type="datetimerange"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
size="mini"
|
||||
align="left"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
:default-time="['00:00:00', '23:59:59']">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="详情:">
|
||||
<el-input size="mini" v-model="searchForm.info" placeholder="请输入关键字" clearable style="width: 200px" @keydown.enter.native="searchEnterFun"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="primary"
|
||||
icon="el-icon-search"
|
||||
@click="handleSearch">搜索
|
||||
</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
icon="el-icon-refresh"
|
||||
@click="rest">重置搜索
|
||||
</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
icon="el-icon-download"
|
||||
@click="handleExport">导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-table
|
||||
ref="multipleTable"
|
||||
:data="tableData"
|
||||
v-loading="loading"
|
||||
element-loading-text="玩命加载中"
|
||||
element-loading-spinner="el-icon-loading"
|
||||
:default-sort="{ prop: 'id', order: 'descending' }"
|
||||
@sort-change="sortChange"
|
||||
:header-cell-style="{backgroundColor:'#fcfcfc'}"
|
||||
border>
|
||||
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="ID"
|
||||
sortable="custom"
|
||||
width="100">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="username"
|
||||
label="用户名"
|
||||
width="140">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="src"
|
||||
label="源IP地址"
|
||||
width="140">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="dst"
|
||||
label="目的IP地址"
|
||||
width="140">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="dst_port"
|
||||
label="目的端口"
|
||||
width="85">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="access_proto"
|
||||
label="访问协议"
|
||||
width="80"
|
||||
:formatter="protoFormat">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="info"
|
||||
label="详情">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="created_at"
|
||||
label="创建时间"
|
||||
width="160"
|
||||
:formatter="tableDateFormat">
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="sh-20"></div>
|
||||
|
||||
<el-pagination
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
:pager-count="11"
|
||||
:current-page.sync="currentPage"
|
||||
@current-change="pageChange"
|
||||
:total="count">
|
||||
</el-pagination>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from "axios";
|
||||
|
||||
export default {
|
||||
name: "auditAccess",
|
||||
mixins: [],
|
||||
data() {
|
||||
return {
|
||||
tableData: [],
|
||||
count: 10,
|
||||
currentPage: 1,
|
||||
idSort: 1,
|
||||
activeName: "first",
|
||||
accessProtoArr:["", "UDP", "TCP", "HTTPS", "HTTP"],
|
||||
defSearchForm: {username:'', src:'', dst:'', dst_port:'', access_proto:'', info:'', date:["",""]},
|
||||
searchForm: {},
|
||||
access_proto: [
|
||||
{ text: 'UDP', value: '1' },
|
||||
{ text: 'TCP', value: '2' },
|
||||
{ text: 'HTTPS', value: '3' },
|
||||
{ text: 'HTTP', value: '4' },
|
||||
],
|
||||
maxExportNum: 1000000,
|
||||
loading: false,
|
||||
rules: {
|
||||
username: [
|
||||
{max: 30, message: '长度小于 30 个字符', trigger: 'blur'}
|
||||
],
|
||||
src: [
|
||||
{ message: '请输入正确的IP地址', validator: this.validateIP, trigger: 'blur' },
|
||||
],
|
||||
dst: [
|
||||
{ message: '请输入正确的IP地址', validator: this.validateIP, trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
idSort: {
|
||||
handler(newValue, oldValue) {
|
||||
if (newValue != oldValue) {
|
||||
this.getData(1);
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
setSearchData() {
|
||||
this.searchForm = JSON.parse(JSON.stringify(this.defSearchForm));
|
||||
},
|
||||
handleSearch() {
|
||||
this.$refs["searchForm"].validate((valid) => {
|
||||
if (!valid) {
|
||||
console.log('error submit!!');
|
||||
return false;
|
||||
}
|
||||
this.getData(1)
|
||||
})
|
||||
},
|
||||
searchEnterFun(e) {
|
||||
var keyCode = window.event ? e.keyCode : e.which;
|
||||
if (keyCode == 13) {
|
||||
this.handleSearch()
|
||||
}
|
||||
},
|
||||
getData(p) {
|
||||
this.loading = true
|
||||
if (! this.searchForm.date) {
|
||||
this.searchForm.date = ["", ""];
|
||||
}
|
||||
this.searchForm.sort = this.idSort
|
||||
axios.get('/set/audit/list', {
|
||||
params: {
|
||||
page: p,
|
||||
search: this.searchForm,
|
||||
}
|
||||
}).then(resp => {
|
||||
var data = resp.data.data
|
||||
console.log(data);
|
||||
this.tableData = data.datas;
|
||||
this.count = data.count
|
||||
this.loading = false
|
||||
this.currentPage = p;
|
||||
}).catch(error => {
|
||||
this.$message.error('哦,请求出错');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
pageChange(p) {
|
||||
this.getData(p)
|
||||
},
|
||||
handleExport() {
|
||||
if (this.count > this.maxExportNum) {
|
||||
var formatNum = (this.maxExportNum + "").replace(/\d{1,3}(?=(\d{3})+$)/g,function(s){
|
||||
return s+','
|
||||
})
|
||||
this.$message.error("你导出的数据量超过" + formatNum + "条,请调整搜索条件,再导出");
|
||||
return ;
|
||||
}
|
||||
if (! this.searchForm.date) {
|
||||
this.searchForm.date = ["", ""];
|
||||
}
|
||||
const exporting = this.$loading({
|
||||
lock: true,
|
||||
text: '玩命导出中,请稍等片刻...',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
});
|
||||
axios.get('/set/audit/export', {
|
||||
params: {
|
||||
search: this.searchForm,
|
||||
}
|
||||
}).then(resp => {
|
||||
var rdata = resp.data
|
||||
if (rdata.code && rdata.code != 0) {
|
||||
exporting.close();
|
||||
this.$message.error(rdata.msg);
|
||||
return ;
|
||||
}
|
||||
exporting.close();
|
||||
this.$message.success("成功导出CSV文件")
|
||||
let csvData = 'data:text/csv;charset=utf-8,\uFEFF' + rdata
|
||||
this.createDownLoadClick(csvData, `anylink_audit_log_` + Date.parse(new Date()) + `.csv`)
|
||||
}).catch(error => {
|
||||
exporting.close();
|
||||
this.$message.error('哦,请求出错');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
createDownLoadClick(content, fileName) {
|
||||
const link = document.createElement('a')
|
||||
link.href = encodeURI(content)
|
||||
link.download = fileName
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
},
|
||||
protoFormat(row) {
|
||||
var access_proto = row.access_proto
|
||||
if (row.access_proto == 0) {
|
||||
switch (row.protocol) {
|
||||
case 6: access_proto = 2; break;
|
||||
case 17: access_proto = 1; break;
|
||||
}
|
||||
}
|
||||
return this.accessProtoArr[access_proto]
|
||||
},
|
||||
rest() {
|
||||
console.log("rest");
|
||||
this.setSearchData();
|
||||
this.handleSearch();
|
||||
},
|
||||
validateIP(rule, value, callback) {
|
||||
if (value === '' || typeof value === 'undefined' || value == null) {
|
||||
callback()
|
||||
} else {
|
||||
const reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
|
||||
if ((!reg.test(value)) && value !== '') {
|
||||
callback(new Error('请输入正确的IP地址'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
},
|
||||
sortChange(column) {
|
||||
let { order } = column;
|
||||
if (order === 'ascending') {
|
||||
this.idSort = 2;
|
||||
} else {
|
||||
this.idSort = 1;
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.el-form-item {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.el-table {
|
||||
font-size: 12px;
|
||||
}
|
||||
.search-form >>> .el-form-item__label {
|
||||
font-size: 12px;
|
||||
}
|
||||
/deep/ .el-table th {
|
||||
padding: 5px 0;
|
||||
}
|
||||
</style>
|
256
web/src/components/audit/ActLog.vue
Normal file
256
web/src/components/audit/ActLog.vue
Normal file
@@ -0,0 +1,256 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form :model="searchForm" ref="searchForm" :inline="true" class="search-form">
|
||||
<el-form-item>
|
||||
<el-input size="mini" v-model="searchForm.username" clearable placeholder="请输入用户名" style="width: 130px" @keydown.enter.native="searchEnterFun"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-date-picker
|
||||
v-model="searchForm.sdate"
|
||||
type="date"
|
||||
size="mini"
|
||||
placeholder="开始日期"
|
||||
format="yyyy-MM-dd"
|
||||
value-format="yyyy-MM-dd"
|
||||
style="width: 130px"
|
||||
>
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-date-picker
|
||||
v-model="searchForm.edate"
|
||||
type="date"
|
||||
size="mini"
|
||||
placeholder="结束日期"
|
||||
format="yyyy-MM-dd"
|
||||
value-format="yyyy-MM-dd"
|
||||
style="width: 130px"
|
||||
>
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item >
|
||||
<el-select size="mini" v-model="searchForm.status" clearable placeholder="操作类型" style="width: 130px">
|
||||
<el-option v-for="(item,index) in statusOps" :key="index" :label="item.value" :value="item.key+1">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-select size="mini" v-model="searchForm.os" clearable placeholder="操作系统" style="width: 130px">
|
||||
<el-option v-for="(value,item,index) in osOps" :key="index" :label="value" :value="item+1">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="primary"
|
||||
icon="el-icon-search"
|
||||
@click="handleSearch">搜索
|
||||
</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
icon="el-icon-refresh"
|
||||
@click="rest">重置搜索
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-table
|
||||
ref="multipleTable"
|
||||
:data="tableData"
|
||||
:default-sort="{ prop: 'id', order: 'descending' }"
|
||||
@sort-change="sortChange"
|
||||
:header-cell-style="{backgroundColor:'#fcfcfc'}"
|
||||
border>
|
||||
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="ID"
|
||||
sortable="custom"
|
||||
width="60">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="username"
|
||||
label="用户名"
|
||||
width="80">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="group_name"
|
||||
label="登陆组"
|
||||
width="100">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="status"
|
||||
label="操作类型"
|
||||
width="92">
|
||||
<template slot-scope="{ row }">
|
||||
<span v-for="(item, index) in statusOps" :key="index">
|
||||
<el-tag size="small" v-if="row.status == item.key" disable-transitions :type="item.tag">{{item.value}}</el-tag>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="os"
|
||||
label="操作系统"
|
||||
width="82">
|
||||
<template slot-scope="{ row }">
|
||||
<span v-for="(value, item, index) in osOps" :key="index">
|
||||
{{ row.os == item? value: "" }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="client"
|
||||
label="客户端"
|
||||
width="100">
|
||||
<template slot-scope="{ row }">
|
||||
<span v-for="(value, item, index) in clientOps" :key="index">
|
||||
{{ row.client == item? value: "" }}
|
||||
</span>
|
||||
{{ row.version }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="ip_addr"
|
||||
label="内网IP"
|
||||
width="120">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="remote_addr"
|
||||
label="外网IP"
|
||||
width="120">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="info"
|
||||
label="详情">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="created_at"
|
||||
label="操作时间"
|
||||
width="130"
|
||||
:formatter="tableDateFormat">
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="sh-20"></div>
|
||||
<el-pagination
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
:pager-count="11"
|
||||
@current-change="pageChange"
|
||||
:current-page="page"
|
||||
:total="count">
|
||||
</el-pagination>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from "axios";
|
||||
|
||||
export default {
|
||||
name: "List",
|
||||
components: {},
|
||||
mixins: [],
|
||||
created() {
|
||||
this.$emit('update:route_path', this.$route.path)
|
||||
this.$emit('update:route_name', ['用户信息', '登入日志'])
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
page: 1,
|
||||
grouNames: [],
|
||||
tableData: [],
|
||||
idSort: 1,
|
||||
count: 10,
|
||||
searchForm: {username:'', sdate:'', edate:'', status:'', os:''},
|
||||
statusOps:[],
|
||||
osOps:[],
|
||||
clientOps:[],
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
idSort: {
|
||||
handler(newValue, oldValue) {
|
||||
if (newValue != oldValue) {
|
||||
this.getData(1);
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleSearch() {
|
||||
this.getData(1)
|
||||
},
|
||||
pageChange(p) {
|
||||
this.getData(p)
|
||||
},
|
||||
searchEnterFun(e) {
|
||||
var keyCode = window.event ? e.keyCode : e.which;
|
||||
if (keyCode == 13) {
|
||||
this.handleSearch()
|
||||
}
|
||||
},
|
||||
getData(page) {
|
||||
console.log(this.searchForm)
|
||||
this.page = page
|
||||
axios.get('/user/act_log/list', {
|
||||
params: {
|
||||
page: page,
|
||||
username: this.searchForm.username || '',
|
||||
sdate: this.searchForm.sdate || '',
|
||||
edate: this.searchForm.edate || '',
|
||||
status: this.searchForm.status || '',
|
||||
os: this.searchForm.os || '',
|
||||
sort: this.idSort,
|
||||
}
|
||||
}).then(resp => {
|
||||
var data = resp.data.data
|
||||
console.log(data);
|
||||
this.tableData = data.datas;
|
||||
this.count = data.count
|
||||
this.statusOps = data.statusOps
|
||||
this.osOps = data.osOps
|
||||
this.clientOps = data.clientOps
|
||||
}).catch(error => {
|
||||
this.$message.error('哦,请求出错');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
rest() {
|
||||
console.log("rest");
|
||||
this.searchForm.username = "";
|
||||
this.searchForm.sdate = "";
|
||||
this.searchForm.edate = "";
|
||||
this.searchForm.status = "";
|
||||
this.searchForm.os = "";
|
||||
this.handleSearch();
|
||||
},
|
||||
sortChange(column) {
|
||||
let { order } = column;
|
||||
if (order === 'ascending') {
|
||||
this.idSort = 2;
|
||||
} else {
|
||||
this.idSort = 1;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.el-form-item {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.el-table {
|
||||
font-size: 12px;
|
||||
}
|
||||
.search-form >>> .el-form-item__label {
|
||||
font-size: 12px;
|
||||
}
|
||||
/deep/ .el-table th {
|
||||
padding: 5px 0;
|
||||
}
|
||||
/deep/ .el-table td {
|
||||
padding: 5px 0;
|
||||
}
|
||||
</style>
|
@@ -1,300 +1,61 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-card>
|
||||
<el-form :model="searchForm" :rules="rules" ref="searchForm" :inline="true" class="form-inner-error">
|
||||
<el-form-item label="用户名:" prop="username">
|
||||
<el-input size="small" v-model="searchForm.username" style="width: 130px" @keydown.enter.native="searchEnterFun"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="源IP地址:" prop="src">
|
||||
<el-input size="small" v-model="searchForm.src" style="width: 130px" @keydown.enter.native="searchEnterFun"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="目的IP地址:" prop="dst">
|
||||
<el-input size="small" v-model="searchForm.dst" style="width: 130px" @keydown.enter.native="searchEnterFun"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="目的端口:" prop="dst_port">
|
||||
<el-input size="small" v-model="searchForm.dst_port" style="width: 80px" @keydown.enter.native="searchEnterFun"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="访问协议:">
|
||||
<el-select size="small" v-model="searchForm.access_proto" style="width: 100px">
|
||||
<el-option v-for="(item,index) in access_proto" :key="index" :label="item.text" :value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<div>
|
||||
<el-form-item label="日期范围:">
|
||||
<el-date-picker
|
||||
v-model="searchForm.date"
|
||||
type="datetimerange"
|
||||
size="small"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
range-separator="~"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期">
|
||||
>
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="详情:">
|
||||
<el-input size="small" v-model="searchForm.info" placeholder="请输入关键字" style="width: 200px" @keydown.enter.native="searchEnterFun"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
icon="el-icon-search"
|
||||
@click="handleSearch">搜索
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
icon="el-icon-refresh"
|
||||
@click="rest">重置搜索
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
icon="el-icon-download"
|
||||
@click="handleExport">导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
|
||||
<el-table
|
||||
ref="multipleTable"
|
||||
:data="tableData"
|
||||
v-loading="loading"
|
||||
element-loading-text="玩命加载中"
|
||||
element-loading-spinner="el-icon-loading"
|
||||
border>
|
||||
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="ID"
|
||||
width="100">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="username"
|
||||
label="用户名"
|
||||
width="140">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="src"
|
||||
label="源IP地址"
|
||||
width="140">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="dst"
|
||||
label="目的IP地址"
|
||||
width="140">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="dst_port"
|
||||
label="目的端口"
|
||||
width="85">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="access_proto"
|
||||
label="访问协议"
|
||||
width="80"
|
||||
:formatter="protoFormat">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="info"
|
||||
label="详情">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="created_at"
|
||||
label="创建时间"
|
||||
width="150"
|
||||
:formatter="tableDateFormat">
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="sh-20"></div>
|
||||
|
||||
<el-pagination
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
:pager-count="11"
|
||||
@current-change="pageChange"
|
||||
:total="count">
|
||||
</el-pagination>
|
||||
|
||||
</el-card>
|
||||
|
||||
<el-card>
|
||||
<el-tabs v-model="activeName" @tab-click="handleClick">
|
||||
<el-tab-pane label="用户访问日志" name="access_audit">
|
||||
<AuditAccess ref="auditAccess"></AuditAccess>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="用户活动日志" name="act_log">
|
||||
<AuditActLog ref="auditActLog"></AuditActLog>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from "axios";
|
||||
import AuditAccess from "../../components/audit/Access";
|
||||
import AuditActLog from "../../components/audit/ActLog";
|
||||
|
||||
export default {
|
||||
name: "Audit",
|
||||
components: {},
|
||||
components:{
|
||||
AuditAccess,
|
||||
AuditActLog
|
||||
},
|
||||
mixins: [],
|
||||
mounted() {
|
||||
this.upTab();
|
||||
},
|
||||
created() {
|
||||
this.$emit('update:route_path', this.$route.path)
|
||||
this.$emit('update:route_name', ['基础信息', '审计日志'])
|
||||
},
|
||||
mounted() {
|
||||
this.getData(1)
|
||||
this.setSearchData()
|
||||
this.$emit('update:route_name', ['基础信息', '审计日志'])
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tableData: [],
|
||||
count: 10,
|
||||
nowIndex: 0,
|
||||
accessProtoArr:["", "UDP", "TCP", "HTTPS", "HTTP"],
|
||||
defSearchForm: {username:'', src:'', dst:'', dst_port:'', access_proto:'', info:'', date:["",""]},
|
||||
searchForm: {},
|
||||
access_proto: [
|
||||
{ text: '请选择', value: '' },
|
||||
{ text: 'UDP', value: '1' },
|
||||
{ text: 'TCP', value: '2' },
|
||||
{ text: 'HTTPS', value: '3' },
|
||||
{ text: 'HTTP', value: '4' },
|
||||
],
|
||||
maxExportNum: 1000000,
|
||||
loading: false,
|
||||
rules: {
|
||||
username: [
|
||||
{max: 30, message: '长度小于 30 个字符', trigger: 'blur'}
|
||||
],
|
||||
src: [
|
||||
{ message: '请输入正确的IP地址', validator: this.validateIP, trigger: 'blur' },
|
||||
],
|
||||
dst: [
|
||||
{ message: '请输入正确的IP地址', validator: this.validateIP, trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
activeName: "access_audit",
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setSearchData() {
|
||||
this.searchForm = JSON.parse(JSON.stringify(this.defSearchForm));
|
||||
},
|
||||
handleSearch() {
|
||||
this.$refs["searchForm"].validate((valid) => {
|
||||
if (!valid) {
|
||||
console.log('error submit!!');
|
||||
return false;
|
||||
}
|
||||
this.getData(1)
|
||||
})
|
||||
},
|
||||
searchEnterFun(e) {
|
||||
var keyCode = window.event ? e.keyCode : e.which;
|
||||
if (keyCode == 13) {
|
||||
this.handleSearch()
|
||||
}
|
||||
},
|
||||
getData(p) {
|
||||
this.loading = true
|
||||
if (! this.searchForm.date) {
|
||||
this.searchForm.date = ["", ""];
|
||||
}
|
||||
axios.get('/set/audit/list', {
|
||||
params: {
|
||||
page: p,
|
||||
search: this.searchForm,
|
||||
}
|
||||
}).then(resp => {
|
||||
var data = resp.data.data
|
||||
console.log(data);
|
||||
this.tableData = data.datas;
|
||||
this.count = data.count
|
||||
this.loading = false
|
||||
}).catch(error => {
|
||||
this.$message.error('哦,请求出错');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
pageChange(p) {
|
||||
this.getData(p)
|
||||
},
|
||||
handleExport() {
|
||||
if (this.count > this.maxExportNum) {
|
||||
var formatNum = (this.maxExportNum + "").replace(/\d{1,3}(?=(\d{3})+$)/g,function(s){
|
||||
return s+','
|
||||
})
|
||||
this.$message.error("你导出的数据量超过" + formatNum + "条,请调整搜索条件,再导出");
|
||||
return ;
|
||||
methods: {
|
||||
upTab() {
|
||||
var tabname = this.$route.query.tabname
|
||||
if (tabname) {
|
||||
this.activeName = tabname
|
||||
}
|
||||
if (! this.searchForm.date) {
|
||||
this.searchForm.date = ["", ""];
|
||||
}
|
||||
const exporting = this.$loading({
|
||||
lock: true,
|
||||
text: '玩命导出中,请稍等片刻...',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
});
|
||||
axios.get('/set/audit/export', {
|
||||
params: {
|
||||
search: this.searchForm,
|
||||
}
|
||||
}).then(resp => {
|
||||
var rdata = resp.data
|
||||
if (rdata.code && rdata.code != 0) {
|
||||
exporting.close();
|
||||
this.$message.error(rdata.msg);
|
||||
return ;
|
||||
}
|
||||
exporting.close();
|
||||
this.$message.success("成功导出CSV文件")
|
||||
let csvData = 'data:text/csv;charset=utf-8,\uFEFF' + rdata
|
||||
this.createDownLoadClick(csvData, `anylink_audit_log_` + Date.parse(new Date()) + `.csv`)
|
||||
}).catch(error => {
|
||||
exporting.close();
|
||||
this.$message.error('哦,请求出错');
|
||||
console.log(error);
|
||||
});
|
||||
this.handleClick(this.activeName)
|
||||
},
|
||||
createDownLoadClick(content, fileName) {
|
||||
const link = document.createElement('a')
|
||||
link.href = encodeURI(content)
|
||||
link.download = fileName
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
handleClick() {
|
||||
switch (this.activeName) {
|
||||
case "access_audit":
|
||||
this.$refs.auditAccess.setSearchData()
|
||||
this.$refs.auditAccess.getData(1)
|
||||
break
|
||||
case "act_log":
|
||||
this.$refs.auditActLog.getData(1)
|
||||
break
|
||||
}
|
||||
this.$router.push({path: this.$route.path, query: {tabname: this.activeName}})
|
||||
},
|
||||
protoFormat(row) {
|
||||
var access_proto = row.access_proto
|
||||
if (row.access_proto == 0) {
|
||||
switch (row.protocol) {
|
||||
case 6: access_proto = 2; break;
|
||||
case 17: access_proto = 1; break;
|
||||
}
|
||||
}
|
||||
return this.accessProtoArr[access_proto]
|
||||
},
|
||||
rest() {
|
||||
console.log("rest");
|
||||
this.setSearchData();
|
||||
this.handleSearch();
|
||||
},
|
||||
validateIP(rule, value, callback) {
|
||||
if (value === '' || typeof value === 'undefined' || value == null) {
|
||||
callback()
|
||||
} else {
|
||||
const reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
|
||||
if ((!reg.test(value)) && value !== '') {
|
||||
callback(new Error('请输入正确的IP地址'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
Reference in New Issue
Block a user