feat: 主机连接日志.
This commit is contained in:
@@ -11,8 +11,10 @@ Authorization: {{token}}
|
||||
"type": "",
|
||||
"token": "",
|
||||
"status": "",
|
||||
"startTimeStart": "",
|
||||
"endTimeEnd": ""
|
||||
"startTimeRange": [
|
||||
"",
|
||||
""
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -36,6 +36,10 @@ public class HostConnectLogDO extends BaseDO {
|
||||
@TableField("user_id")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "用户名")
|
||||
@TableField("username")
|
||||
private String username;
|
||||
|
||||
@Schema(description = "主机id")
|
||||
@TableField("host_id")
|
||||
private Long hostId;
|
||||
|
||||
@@ -24,9 +24,18 @@ public class HostConnectLogCreateRequest extends PageRequest {
|
||||
@Schema(description = "用户id")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "用户名")
|
||||
private String username;
|
||||
|
||||
@Schema(description = "主机id")
|
||||
private Long hostId;
|
||||
|
||||
@Schema(description = "主机名称")
|
||||
private String hostName;
|
||||
|
||||
@Schema(description = "主机地址")
|
||||
private String hostAddress;
|
||||
|
||||
@Size(max = 128)
|
||||
@Schema(description = "token")
|
||||
private String token;
|
||||
|
||||
@@ -45,12 +45,8 @@ public class HostConnectLogQueryRequest extends PageRequest {
|
||||
@Schema(description = "状态")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "开始时间-开区间")
|
||||
@Schema(description = "开始时间-区间")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date startTimeStart;
|
||||
|
||||
@Schema(description = "开始时间-闭区间")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date startTimeEnd;
|
||||
private Date[] startTimeRange;
|
||||
|
||||
}
|
||||
|
||||
@@ -31,6 +31,9 @@ public class HostConnectLogVO implements Serializable {
|
||||
@Schema(description = "用户id")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "用户名")
|
||||
private String username;
|
||||
|
||||
@Schema(description = "主机id")
|
||||
private Long hostId;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.orion.ops.module.asset.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.orion.lang.define.wrapper.DataGrid;
|
||||
import com.orion.lang.utils.Arrays1;
|
||||
import com.orion.ops.framework.mybatis.core.query.Conditions;
|
||||
import com.orion.ops.module.asset.convert.HostConnectLogConvert;
|
||||
import com.orion.ops.module.asset.dao.HostConnectLogDAO;
|
||||
@@ -74,8 +75,8 @@ public class HostConnectLogServiceImpl implements HostConnectLogService {
|
||||
.eq(HostConnectLogDO::getType, request.getType())
|
||||
.like(HostConnectLogDO::getToken, request.getToken())
|
||||
.eq(HostConnectLogDO::getStatus, request.getStatus())
|
||||
.ge(HostConnectLogDO::getStartTime, request.getStartTimeStart())
|
||||
.le(HostConnectLogDO::getStartTime, request.getStartTimeEnd());
|
||||
.ge(HostConnectLogDO::getStartTime, Arrays1.getIfPresent(request.getStartTimeRange(), 0))
|
||||
.le(HostConnectLogDO::getStartTime, Arrays1.getIfPresent(request.getStartTimeRange(), 1));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<resultMap id="BaseResultMap" type="com.orion.ops.module.asset.entity.domain.HostConnectLogDO">
|
||||
<id column="id" property="id"/>
|
||||
<result column="user_id" property="userId"/>
|
||||
<result column="username" property="username"/>
|
||||
<result column="host_id" property="hostId"/>
|
||||
<result column="host_name" property="hostName"/>
|
||||
<result column="host_address" property="hostAddress"/>
|
||||
@@ -22,7 +23,7 @@
|
||||
|
||||
<!-- 通用查询结果列 -->
|
||||
<sql id="Base_Column_List">
|
||||
id, user_id, host_id, host_name, host_address, type, token, status, start_time, end_time, extra_info, create_time, update_time, deleted
|
||||
id, user_id, username, host_id, host_name, host_address, type, token, status, start_time, end_time, extra_info, create_time, update_time, deleted
|
||||
</sql>
|
||||
|
||||
</mapper>
|
||||
|
||||
@@ -44,12 +44,8 @@ public class OperatorLogQueryRequest extends PageRequest {
|
||||
@Schema(description = "操作结果 0失败 1成功")
|
||||
private Integer result;
|
||||
|
||||
@Schema(description = "开始时间-开区间")
|
||||
@Schema(description = "开始时间-区间")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date startTimeStart;
|
||||
|
||||
@Schema(description = "开始时间-闭区间")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date startTimeEnd;
|
||||
private Date[] startTimeRange;
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.orion.ops.module.infra.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.orion.lang.define.wrapper.DataGrid;
|
||||
import com.orion.lang.utils.Arrays1;
|
||||
import com.orion.ops.framework.biz.operator.log.core.model.OperatorLogModel;
|
||||
import com.orion.ops.framework.common.constant.Const;
|
||||
import com.orion.ops.module.infra.convert.OperatorLogConvert;
|
||||
@@ -77,8 +78,8 @@ public class OperatorLogServiceImpl implements OperatorLogService {
|
||||
.eq(OperatorLogDO::getModule, request.getModule())
|
||||
.eq(OperatorLogDO::getType, request.getType())
|
||||
.eq(OperatorLogDO::getResult, request.getResult())
|
||||
.ge(OperatorLogDO::getStartTime, request.getStartTimeStart())
|
||||
.le(OperatorLogDO::getStartTime, request.getStartTimeEnd())
|
||||
.ge(OperatorLogDO::getStartTime, Arrays1.getIfPresent(request.getStartTimeRange(), 0))
|
||||
.le(OperatorLogDO::getStartTime, Arrays1.getIfPresent(request.getStartTimeRange(), 1))
|
||||
.orderByDesc(OperatorLogDO::getId);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,8 +12,7 @@ export interface HostConnectLogQueryRequest extends Pagination {
|
||||
type?: string;
|
||||
token?: string;
|
||||
status?: string;
|
||||
startTimeStart?: string;
|
||||
startTimeEnd?: string;
|
||||
startTimeRange?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,8 +11,7 @@ export interface OperatorLogQueryRequest extends Pagination {
|
||||
type?: string;
|
||||
riskLevel?: string;
|
||||
result?: number;
|
||||
startTimeStart?: string;
|
||||
startTimeEnd?: string;
|
||||
startTimeRange?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
65
orion-ops-ui/src/components/asset/host/host-selector.vue
Normal file
65
orion-ops-ui/src/components/asset/host/host-selector.vue
Normal file
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<a-select v-model:model-value="value"
|
||||
:options="optionData"
|
||||
:loading="loading"
|
||||
placeholder="请选择主机"
|
||||
allow-clear />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'host-selector'
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { SelectOptionData } from '@arco-design/web-vue';
|
||||
import { computed, onBeforeMount, ref } from 'vue';
|
||||
import { useCacheStore } from '@/store';
|
||||
import useLoading from '@/hooks/loading';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: Number
|
||||
});
|
||||
|
||||
const emits = defineEmits(['update:modelValue']);
|
||||
|
||||
const { loading, setLoading } = useLoading();
|
||||
const cacheStore = useCacheStore();
|
||||
|
||||
const value = computed<number>({
|
||||
get() {
|
||||
return props.modelValue as number;
|
||||
},
|
||||
set(e) {
|
||||
if (e) {
|
||||
emits('update:modelValue', e);
|
||||
} else {
|
||||
emits('update:modelValue', null);
|
||||
}
|
||||
}
|
||||
});
|
||||
const optionData = ref<Array<SelectOptionData>>([]);
|
||||
|
||||
// 初始化选项
|
||||
onBeforeMount(async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const hosts = await cacheStore.loadHosts();
|
||||
optionData.value = hosts.map(s => {
|
||||
return {
|
||||
label: `${s.name} - ${s.address}`,
|
||||
value: s.id,
|
||||
};
|
||||
});
|
||||
} catch (e) {
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
</style>
|
||||
@@ -15,11 +15,13 @@
|
||||
</template>
|
||||
<!-- 数据 -->
|
||||
<template #item="{ item }">
|
||||
<a-list-item :title="`${item.name}(${item.code}) - ${item.address}`">
|
||||
<icon-desktop class="host-list-icon" />
|
||||
<span>{{ `${item.name}(${item.code}) - ` }}</span>
|
||||
<span class="span-blue">{{ item.address }}</span>
|
||||
</a-list-item>
|
||||
<a-tooltip :content="`${item.name} - ${item.address}`">
|
||||
<a-list-item>
|
||||
<icon-desktop class="host-list-icon" />
|
||||
<span>{{ `${item.name} - ` }}</span>
|
||||
<span class="span-blue">{{ item.address }}</span>
|
||||
</a-list-item>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-list>
|
||||
</template>
|
||||
|
||||
@@ -3,21 +3,21 @@
|
||||
<a-card class="general-card table-search-card">
|
||||
<a-query-header :model="formModel"
|
||||
label-align="left"
|
||||
:itemOptions="{ 5: { span: 2 } }"
|
||||
@submit="fetchTableData"
|
||||
@reset="reset"
|
||||
@reset="fetchTableData"
|
||||
@keyup.enter="() => fetchTableData()">
|
||||
<!-- 用户 -->
|
||||
<a-form-item field="userId" label="用户" label-col-flex="50px">
|
||||
<!-- 连接用户 -->
|
||||
<a-form-item field="userId" label="连接用户" label-col-flex="50px">
|
||||
<user-selector v-model="formModel.userId"
|
||||
placeholder="请选择用户"
|
||||
allow-clear />
|
||||
</a-form-item>
|
||||
<!-- 主机 -->
|
||||
<a-form-item field="hostId" label="主机" label-col-flex="50px">
|
||||
<a-input-number v-model="formModel.hostId"
|
||||
placeholder="FIXME 请输入主机"
|
||||
allow-clear
|
||||
hide-button />
|
||||
<!-- 连接主机 -->
|
||||
<a-form-item field="hostId" label="连接主机" label-col-flex="50px">
|
||||
<host-selector v-model="formModel.hostId"
|
||||
placeholder="请选择主机"
|
||||
allow-clear />
|
||||
</a-form-item>
|
||||
<!-- 主机地址 -->
|
||||
<a-form-item field="hostAddress" label="主机地址" label-col-flex="50px">
|
||||
@@ -35,12 +35,12 @@
|
||||
<a-input v-model="formModel.token" placeholder="请输入token" allow-clear />
|
||||
</a-form-item>
|
||||
<!-- 开始时间 -->
|
||||
<a-form-item field="startTime" label="开始时间" label-col-flex="50px">
|
||||
<a-range-picker v-model="timeRange"
|
||||
<a-form-item field="startTimeRange" label="开始时间" label-col-flex="50px">
|
||||
<a-range-picker v-model="formModel.startTimeRange"
|
||||
style="width: 100%"
|
||||
:time-picker-props="{ defaultValue: ['00:00:00', '23:59:59'] }"
|
||||
show-time
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
@ok="timeRangePicked" />
|
||||
format="YYYY-MM-DD HH:mm:ss" />
|
||||
</a-form-item>
|
||||
</a-query-header>
|
||||
</a-card>
|
||||
@@ -69,6 +69,14 @@
|
||||
@page-change="(page) => fetchTableData(page, pagination.pageSize)"
|
||||
@page-size-change="(size) => fetchTableData(1, size)"
|
||||
:bordered="false">
|
||||
<!-- 连接用户 -->
|
||||
<template #username="{ record }">
|
||||
{{ record.userId }} - {{ record.username }}
|
||||
</template>
|
||||
<!-- 连接主机 -->
|
||||
<template #hostName="{ record }">
|
||||
{{ record.hostId }} - {{ record.hostName }}
|
||||
</template>
|
||||
<!-- 主机地址 -->
|
||||
<template #hostAddress="{ record }">
|
||||
<span class="copy-left" title="复制" @click="copy(record.hostAddress)">
|
||||
@@ -104,6 +112,7 @@
|
||||
import { useDictStore } from '@/store';
|
||||
import useCopy from '@/hooks/copy';
|
||||
import UserSelector from '@/components/user/user/user-selector.vue';
|
||||
import HostSelector from '@/components/asset/host/host-selector.vue';
|
||||
|
||||
const emits = defineEmits(['openAdd', 'openUpdate']);
|
||||
|
||||
@@ -114,7 +123,6 @@
|
||||
const { toOptions, getDictValue } = useDictStore();
|
||||
const { copy } = useCopy();
|
||||
|
||||
const timeRange = ref<string[]>([]);
|
||||
const formModel = reactive<HostConnectLogQueryRequest>({
|
||||
userId: undefined,
|
||||
hostId: undefined,
|
||||
@@ -122,16 +130,9 @@
|
||||
type: undefined,
|
||||
token: undefined,
|
||||
status: undefined,
|
||||
startTimeStart: undefined,
|
||||
startTimeEnd: undefined,
|
||||
startTimeRange: undefined,
|
||||
});
|
||||
|
||||
// 选择时间
|
||||
const timeRangePicked = (e: string[]) => {
|
||||
formModel.startTimeStart = e[0];
|
||||
formModel.startTimeEnd = e[1];
|
||||
};
|
||||
|
||||
// 加载数据
|
||||
const doFetchTableData = async (request: HostConnectLogQueryRequest) => {
|
||||
try {
|
||||
@@ -152,14 +153,6 @@
|
||||
doFetchTableData({ page, limit, ...form });
|
||||
};
|
||||
|
||||
// 重置
|
||||
const reset = () => {
|
||||
timeRange.value = [];
|
||||
formModel.startTimeStart = undefined;
|
||||
formModel.startTimeEnd = undefined;
|
||||
fetchTableData();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
fetchTableData();
|
||||
});
|
||||
|
||||
@@ -10,19 +10,14 @@ const columns = [
|
||||
align: 'left',
|
||||
fixed: 'left',
|
||||
}, {
|
||||
title: '用户id',
|
||||
dataIndex: 'userId',
|
||||
slotName: 'userId',
|
||||
width: 110,
|
||||
title: '连接用户',
|
||||
dataIndex: 'username',
|
||||
slotName: 'username',
|
||||
align: 'left',
|
||||
ellipsis: true,
|
||||
tooltip: true,
|
||||
}, {
|
||||
title: '主机id',
|
||||
dataIndex: 'hostId',
|
||||
slotName: 'hostId',
|
||||
width: 110,
|
||||
align: 'left',
|
||||
}, {
|
||||
title: '主机名称',
|
||||
title: '连接主机',
|
||||
dataIndex: 'hostName',
|
||||
slotName: 'hostName',
|
||||
align: 'left',
|
||||
@@ -48,8 +43,7 @@ const columns = [
|
||||
dataIndex: 'status',
|
||||
slotName: 'status',
|
||||
align: 'left',
|
||||
ellipsis: true,
|
||||
tooltip: true,
|
||||
width: 90,
|
||||
}, {
|
||||
title: '开始时间',
|
||||
dataIndex: 'startTime',
|
||||
|
||||
@@ -94,8 +94,8 @@
|
||||
const renderLabel = (label: string) => {
|
||||
const last = label.lastIndexOf('-');
|
||||
const prefix = label.substring(0, last - 1);
|
||||
const ip = label.substring(last + 2, label.length);
|
||||
return `${prefix} - <span class="span-blue">${ip}</span>`;
|
||||
const address = label.substring(last + 2, label.length);
|
||||
return `${prefix} - <span class="span-blue">${address}</span>`;
|
||||
};
|
||||
|
||||
// 查询组内数据
|
||||
@@ -121,7 +121,7 @@
|
||||
data.value = hosts.map(s => {
|
||||
return {
|
||||
value: String(s.id),
|
||||
label: `${s.name} (${s.code}) - ${s.address}`,
|
||||
label: `${s.name} - ${s.address}`,
|
||||
disabled: false
|
||||
};
|
||||
});
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<!-- 返回 -->
|
||||
<a-tab-pane key="back" v-if="userId">
|
||||
<template #title>
|
||||
<icon-arrow-left style="font-size: 16px" />
|
||||
<icon-left style="font-size: 16px; padding-top: 2px;" />
|
||||
返回
|
||||
</template>
|
||||
</a-tab-pane>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<template>
|
||||
<a-query-header :model="formModel"
|
||||
label-align="left"
|
||||
:itemOptions="{ [visibleUser ? 5 : 4]: { span: 2 } }"
|
||||
@submit="submit"
|
||||
@reset="reset"
|
||||
@reset="submit"
|
||||
@keyup.enter="submit">
|
||||
<!-- 操作用户 -->
|
||||
<a-form-item v-if="visibleUser"
|
||||
@@ -47,12 +48,12 @@
|
||||
allow-clear />
|
||||
</a-form-item>
|
||||
<!-- 执行时间 -->
|
||||
<a-form-item field="startTime" label="执行时间" label-col-flex="50px">
|
||||
<a-range-picker v-model="timeRange"
|
||||
<a-form-item field="startTimeRange" label="执行时间" label-col-flex="50px">
|
||||
<a-range-picker v-model="formModel.startTimeRange"
|
||||
style="width: 100%"
|
||||
:time-picker-props="{ defaultValue: ['00:00:00', '23:59:59'] }"
|
||||
show-time
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
@ok="timeRangePicked" />
|
||||
format="YYYY-MM-DD HH:mm:ss" />
|
||||
</a-form-item>
|
||||
</a-query-header>
|
||||
</template>
|
||||
@@ -84,23 +85,15 @@
|
||||
const { loading, setLoading } = useLoading();
|
||||
const { $state: dictState, toOptions } = useDictStore();
|
||||
|
||||
const timeRange = ref<string[]>([]);
|
||||
const typeOptions = ref<SelectOptionData[]>(toOptions(operatorLogTypeKey));
|
||||
const formModel = reactive<OperatorLogQueryRequest>({
|
||||
module: undefined,
|
||||
type: undefined,
|
||||
riskLevel: undefined,
|
||||
result: undefined,
|
||||
startTimeStart: undefined,
|
||||
startTimeEnd: undefined,
|
||||
startTimeRange: undefined,
|
||||
});
|
||||
|
||||
// 选择时间
|
||||
const timeRangePicked = (e: string[]) => {
|
||||
formModel.startTimeStart = e[0];
|
||||
formModel.startTimeEnd = e[1];
|
||||
};
|
||||
|
||||
// 选择类型
|
||||
const selectedModule = (module: string) => {
|
||||
if (!module) {
|
||||
@@ -118,14 +111,6 @@
|
||||
}
|
||||
};
|
||||
|
||||
// 重置
|
||||
const reset = () => {
|
||||
timeRange.value = [];
|
||||
formModel.startTimeStart = undefined;
|
||||
formModel.startTimeEnd = undefined;
|
||||
submit();
|
||||
};
|
||||
|
||||
// 切换页码
|
||||
const submit = () => {
|
||||
emits('submit', { ...formModel });
|
||||
|
||||
Reference in New Issue
Block a user