⚡ 优化执行逻辑.
This commit is contained in:
@@ -9,7 +9,7 @@ import com.orion.ops.module.asset.entity.request.exec.ExecCommandRequest;
|
|||||||
import com.orion.ops.module.asset.entity.request.exec.ExecInterruptRequest;
|
import com.orion.ops.module.asset.entity.request.exec.ExecInterruptRequest;
|
||||||
import com.orion.ops.module.asset.entity.request.exec.ExecLogTailRequest;
|
import com.orion.ops.module.asset.entity.request.exec.ExecLogTailRequest;
|
||||||
import com.orion.ops.module.asset.entity.request.exec.ReExecCommandRequest;
|
import com.orion.ops.module.asset.entity.request.exec.ReExecCommandRequest;
|
||||||
import com.orion.ops.module.asset.entity.vo.ExecCommandVO;
|
import com.orion.ops.module.asset.entity.vo.ExecLogVO;
|
||||||
import com.orion.ops.module.asset.service.ExecService;
|
import com.orion.ops.module.asset.service.ExecService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
@@ -44,7 +44,7 @@ public class ExecController {
|
|||||||
@PostMapping("/exec-command")
|
@PostMapping("/exec-command")
|
||||||
@Operation(summary = "批量执行命令")
|
@Operation(summary = "批量执行命令")
|
||||||
@PreAuthorize("@ss.hasPermission('asset:exec:exec-command')")
|
@PreAuthorize("@ss.hasPermission('asset:exec:exec-command')")
|
||||||
public ExecCommandVO execCommand(@Validated @RequestBody ExecCommandRequest request) {
|
public ExecLogVO execCommand(@Validated @RequestBody ExecCommandRequest request) {
|
||||||
return execService.execCommand(request);
|
return execService.execCommand(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ public class ExecController {
|
|||||||
@PostMapping("/re-exec-command")
|
@PostMapping("/re-exec-command")
|
||||||
@Operation(summary = "重新执行命令")
|
@Operation(summary = "重新执行命令")
|
||||||
@PreAuthorize("@ss.hasPermission('asset:exec:exec-command')")
|
@PreAuthorize("@ss.hasPermission('asset:exec:exec-command')")
|
||||||
public ExecCommandVO reExecCommand(@Validated @RequestBody ReExecCommandRequest request) {
|
public ExecLogVO reExecCommand(@Validated @RequestBody ReExecCommandRequest request) {
|
||||||
return execService.reExecCommand(request.getLogId());
|
return execService.reExecCommand(request.getLogId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,14 @@ public class ExecLogController {
|
|||||||
return execLogService.getExecLogPage(request);
|
return execLogService.getExecLogPage(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@IgnoreLog(IgnoreLogMode.RET)
|
||||||
|
@GetMapping("/get")
|
||||||
|
@Operation(summary = "查询执行日志")
|
||||||
|
@PreAuthorize("@ss.hasPermission('asset:exec-log:query')")
|
||||||
|
public ExecLogVO getExecLog(@RequestParam("id") Long id) {
|
||||||
|
return execLogService.getExecLog(id, ExecSourceEnum.BATCH.name());
|
||||||
|
}
|
||||||
|
|
||||||
@IgnoreLog(IgnoreLogMode.RET)
|
@IgnoreLog(IgnoreLogMode.RET)
|
||||||
@GetMapping("/host-list")
|
@GetMapping("/host-list")
|
||||||
@Operation(summary = "查询全部执行主机日志")
|
@Operation(summary = "查询全部执行主机日志")
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
package com.orion.ops.module.asset.entity.vo;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 命令执行主机 视图响应对象
|
|
||||||
*
|
|
||||||
* @author Jiahang Li
|
|
||||||
* @version 1.0.0
|
|
||||||
* @since 2024/3/11 14:57
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
@Schema(name = "ExecCommandHostVO", description = "命令执行主机 视图响应对象")
|
|
||||||
public class ExecCommandHostVO implements Serializable {
|
|
||||||
|
|
||||||
@Schema(description = "id")
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@Schema(description = "hostId")
|
|
||||||
private Long hostId;
|
|
||||||
|
|
||||||
@Schema(description = "主机名称")
|
|
||||||
private String hostName;
|
|
||||||
|
|
||||||
@Schema(description = "主机地址")
|
|
||||||
private String hostAddress;
|
|
||||||
|
|
||||||
@Schema(description = "执行状态")
|
|
||||||
private String status;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package com.orion.ops.module.asset.entity.vo;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 命令执行 视图响应对象
|
|
||||||
*
|
|
||||||
* @author Jiahang Li
|
|
||||||
* @version 1.0.0
|
|
||||||
* @since 2024/3/11 14:57
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
@Schema(name = "ExecCommandVO", description = "命令执行 视图响应对象")
|
|
||||||
public class ExecCommandVO implements Serializable {
|
|
||||||
|
|
||||||
@Schema(description = "id")
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@Schema(description = "执行状态")
|
|
||||||
private String status;
|
|
||||||
|
|
||||||
@Schema(description = "主机 id 映射")
|
|
||||||
private List<ExecCommandHostVO> hosts;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -59,4 +59,7 @@ public class ExecLogVO implements Serializable {
|
|||||||
@Schema(description = "执行主机id")
|
@Schema(description = "执行主机id")
|
||||||
private List<Long> hostIdList;
|
private List<Long> hostIdList;
|
||||||
|
|
||||||
|
@Schema(description = "执行主机")
|
||||||
|
private List<ExecHostLogVO> hosts;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,15 @@ public interface ExecLogService {
|
|||||||
*/
|
*/
|
||||||
DataGrid<ExecLogVO> getExecLogPage(ExecLogQueryRequest request);
|
DataGrid<ExecLogVO> getExecLogPage(ExecLogQueryRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取执行日志
|
||||||
|
*
|
||||||
|
* @param id id
|
||||||
|
* @param source source
|
||||||
|
* @return row
|
||||||
|
*/
|
||||||
|
ExecLogVO getExecLog(Long id, String source);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取执行历史
|
* 获取执行历史
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package com.orion.ops.module.asset.service;
|
|||||||
import com.orion.ops.module.asset.entity.dto.ExecLogTailDTO;
|
import com.orion.ops.module.asset.entity.dto.ExecLogTailDTO;
|
||||||
import com.orion.ops.module.asset.entity.request.exec.ExecCommandRequest;
|
import com.orion.ops.module.asset.entity.request.exec.ExecCommandRequest;
|
||||||
import com.orion.ops.module.asset.entity.request.exec.ExecLogTailRequest;
|
import com.orion.ops.module.asset.entity.request.exec.ExecLogTailRequest;
|
||||||
import com.orion.ops.module.asset.entity.vo.ExecCommandVO;
|
import com.orion.ops.module.asset.entity.vo.ExecLogVO;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ public interface ExecService {
|
|||||||
* @param request request
|
* @param request request
|
||||||
* @return result
|
* @return result
|
||||||
*/
|
*/
|
||||||
ExecCommandVO execCommand(ExecCommandRequest request);
|
ExecLogVO execCommand(ExecCommandRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重新执行命令
|
* 重新执行命令
|
||||||
@@ -30,7 +30,7 @@ public interface ExecService {
|
|||||||
* @param id id
|
* @param id id
|
||||||
* @return result
|
* @return result
|
||||||
*/
|
*/
|
||||||
ExecCommandVO reExecCommand(Long id);
|
ExecLogVO reExecCommand(Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 中断命令执行
|
* 中断命令执行
|
||||||
|
|||||||
@@ -65,6 +65,24 @@ public class ExecLogServiceImpl implements ExecLogService {
|
|||||||
.dataGrid(ExecLogConvert.MAPPER::to);
|
.dataGrid(ExecLogConvert.MAPPER::to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExecLogVO getExecLog(Long id, String source) {
|
||||||
|
// 查询执行日志
|
||||||
|
ExecLogDO row = execLogDAO.of()
|
||||||
|
.createValidateWrapper()
|
||||||
|
.eq(ExecLogDO::getId, id)
|
||||||
|
.eq(ExecLogDO::getSource, source)
|
||||||
|
.then()
|
||||||
|
.getOne();
|
||||||
|
Valid.notNull(row, ErrorMessage.LOG_ABSENT);
|
||||||
|
// 查询执行主机
|
||||||
|
List<ExecHostLogDO> hosts = execHostLogDAO.selectByLogId(id);
|
||||||
|
// 返回
|
||||||
|
ExecLogVO vo = ExecLogConvert.MAPPER.to(row);
|
||||||
|
vo.setHosts(ExecHostLogConvert.MAPPER.to(hosts));
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ExecLogVO> getExecHistory(ExecLogQueryRequest request) {
|
public List<ExecLogVO> getExecHistory(ExecLogQueryRequest request) {
|
||||||
// 查询执行记录
|
// 查询执行记录
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ import com.orion.ops.framework.common.security.LoginUser;
|
|||||||
import com.orion.ops.framework.common.utils.Valid;
|
import com.orion.ops.framework.common.utils.Valid;
|
||||||
import com.orion.ops.framework.redis.core.utils.RedisStrings;
|
import com.orion.ops.framework.redis.core.utils.RedisStrings;
|
||||||
import com.orion.ops.framework.security.core.utils.SecurityUtils;
|
import com.orion.ops.framework.security.core.utils.SecurityUtils;
|
||||||
|
import com.orion.ops.module.asset.convert.ExecHostLogConvert;
|
||||||
|
import com.orion.ops.module.asset.convert.ExecLogConvert;
|
||||||
import com.orion.ops.module.asset.dao.ExecHostLogDAO;
|
import com.orion.ops.module.asset.dao.ExecHostLogDAO;
|
||||||
import com.orion.ops.module.asset.dao.ExecLogDAO;
|
import com.orion.ops.module.asset.dao.ExecLogDAO;
|
||||||
import com.orion.ops.module.asset.dao.HostDAO;
|
import com.orion.ops.module.asset.dao.HostDAO;
|
||||||
@@ -35,8 +37,8 @@ import com.orion.ops.module.asset.entity.dto.ExecLogTailDTO;
|
|||||||
import com.orion.ops.module.asset.entity.dto.ExecParameterSchemaDTO;
|
import com.orion.ops.module.asset.entity.dto.ExecParameterSchemaDTO;
|
||||||
import com.orion.ops.module.asset.entity.request.exec.ExecCommandRequest;
|
import com.orion.ops.module.asset.entity.request.exec.ExecCommandRequest;
|
||||||
import com.orion.ops.module.asset.entity.request.exec.ExecLogTailRequest;
|
import com.orion.ops.module.asset.entity.request.exec.ExecLogTailRequest;
|
||||||
import com.orion.ops.module.asset.entity.vo.ExecCommandHostVO;
|
import com.orion.ops.module.asset.entity.vo.ExecHostLogVO;
|
||||||
import com.orion.ops.module.asset.entity.vo.ExecCommandVO;
|
import com.orion.ops.module.asset.entity.vo.ExecLogVO;
|
||||||
import com.orion.ops.module.asset.entity.vo.HostConfigVO;
|
import com.orion.ops.module.asset.entity.vo.HostConfigVO;
|
||||||
import com.orion.ops.module.asset.enums.ExecHostStatusEnum;
|
import com.orion.ops.module.asset.enums.ExecHostStatusEnum;
|
||||||
import com.orion.ops.module.asset.enums.ExecSourceEnum;
|
import com.orion.ops.module.asset.enums.ExecSourceEnum;
|
||||||
@@ -102,7 +104,7 @@ public class ExecServiceImpl implements ExecService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public ExecCommandVO execCommand(ExecCommandRequest request) {
|
public ExecLogVO execCommand(ExecCommandRequest request) {
|
||||||
log.info("ExecService.startExecCommand start params: {}", JSON.toJSONString(request));
|
log.info("ExecService.startExecCommand start params: {}", JSON.toJSONString(request));
|
||||||
LoginUser user = Objects.requireNonNull(SecurityUtils.getLoginUser());
|
LoginUser user = Objects.requireNonNull(SecurityUtils.getLoginUser());
|
||||||
Long userId = user.getId();
|
Long userId = user.getId();
|
||||||
@@ -156,25 +158,15 @@ public class ExecServiceImpl implements ExecService {
|
|||||||
// 开始执行
|
// 开始执行
|
||||||
this.startExec(execLog, execHostLogs);
|
this.startExec(execLog, execHostLogs);
|
||||||
// 返回
|
// 返回
|
||||||
List<ExecCommandHostVO> hostResult = execHostLogs.stream()
|
ExecLogVO result = ExecLogConvert.MAPPER.to(execLog);
|
||||||
.map(s -> ExecCommandHostVO.builder()
|
List<ExecHostLogVO> resultHosts = ExecHostLogConvert.MAPPER.to(execHostLogs);
|
||||||
.id(s.getId())
|
result.setHosts(resultHosts);
|
||||||
.hostId(s.getHostId())
|
return result;
|
||||||
.hostName(s.getHostName())
|
|
||||||
.hostAddress(s.getHostAddress())
|
|
||||||
.status(s.getStatus())
|
|
||||||
.build())
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
return ExecCommandVO.builder()
|
|
||||||
.id(execId)
|
|
||||||
.status(execLog.getStatus())
|
|
||||||
.hosts(hostResult)
|
|
||||||
.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public ExecCommandVO reExecCommand(Long logId) {
|
public ExecLogVO reExecCommand(Long logId) {
|
||||||
log.info("ExecService.reExecCommand start logId: {}", logId);
|
log.info("ExecService.reExecCommand start logId: {}", logId);
|
||||||
// 获取执行记录
|
// 获取执行记录
|
||||||
ExecLogDO execLog = execLogDAO.selectById(logId);
|
ExecLogDO execLog = execLogDAO.selectById(logId);
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ export interface ExecLogQueryResponse extends TableData, ExecLogQueryExtraRespon
|
|||||||
startTime: number;
|
startTime: number;
|
||||||
finishTime: number;
|
finishTime: number;
|
||||||
hostIdList: Array<number>;
|
hostIdList: Array<number>;
|
||||||
|
hosts: Array<ExecHostLogQueryResponse>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,6 +73,13 @@ export function getExecLogPage(request: ExecLogQueryRequest) {
|
|||||||
return axios.post<DataGrid<ExecLogQueryResponse>>('/asset/exec-log/query', request);
|
return axios.post<DataGrid<ExecLogQueryResponse>>('/asset/exec-log/query', request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询执行记录
|
||||||
|
*/
|
||||||
|
export function getExecLog(id: number) {
|
||||||
|
return axios.get<ExecLogQueryResponse>('/asset/exec-log/query', { params: { id } });
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询主机执行记录
|
* 查询主机执行记录
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type { ExecLogQueryResponse } from './exec-log';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,44 +29,18 @@ export interface ExecTailRequest {
|
|||||||
hostExecIdList?: Array<number>;
|
hostExecIdList?: Array<number>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行命令响应
|
|
||||||
*/
|
|
||||||
export interface ExecCommandResponse {
|
|
||||||
id: number;
|
|
||||||
status: string;
|
|
||||||
startTime: number;
|
|
||||||
finishTime: number;
|
|
||||||
hosts: Array<ExecCommandHostResponse>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行命令主机响应
|
|
||||||
*/
|
|
||||||
export interface ExecCommandHostResponse {
|
|
||||||
id: number;
|
|
||||||
hostId: number;
|
|
||||||
hostName: string;
|
|
||||||
hostAddress: string;
|
|
||||||
status: string;
|
|
||||||
exitStatus: number;
|
|
||||||
errorMessage: string;
|
|
||||||
startTime: number;
|
|
||||||
finishTime: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量执行命令
|
* 批量执行命令
|
||||||
*/
|
*/
|
||||||
export function batchExecCommand(request: ExecCommandRequest) {
|
export function batchExecCommand(request: ExecCommandRequest) {
|
||||||
return axios.post<ExecCommandResponse>('/asset/exec/exec-command', request);
|
return axios.post<ExecLogQueryResponse>('/asset/exec/exec-command', request);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重新执行命令
|
* 重新执行命令
|
||||||
*/
|
*/
|
||||||
export function reExecCommand(request: ExecCommandRequest) {
|
export function reExecCommand(request: ExecCommandRequest) {
|
||||||
return axios.post<ExecCommandResponse>('/asset/exec/re-exec-command', request);
|
return axios.post<ExecLogQueryResponse>('/asset/exec/re-exec-command', request);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
77
orion-ops-ui/src/components/exec/log/panel-modal/index.vue
Normal file
77
orion-ops-ui/src/components/exec/log/panel-modal/index.vue
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
<template>
|
||||||
|
<a-modal v-model:visible="visible"
|
||||||
|
title-align="start"
|
||||||
|
title="执行日志"
|
||||||
|
width="94%"
|
||||||
|
:top="80"
|
||||||
|
:body-style="{ padding: '0' }"
|
||||||
|
:align-center="false"
|
||||||
|
:draggable="true"
|
||||||
|
:mask-closable="false"
|
||||||
|
:unmount-on-close="true"
|
||||||
|
:footer="false"
|
||||||
|
@close="handleClose">
|
||||||
|
<a-spin class="modal-body" :loading="loading">
|
||||||
|
<!-- 日志面板 -->
|
||||||
|
<exec-log-panel ref="log" :visible-back="false" />
|
||||||
|
</a-spin>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'execLogPanelModal'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import useVisible from '@/hooks/visible';
|
||||||
|
import useLoading from '@/hooks/loading';
|
||||||
|
import { nextTick, ref } from 'vue';
|
||||||
|
import { getExecLog } from '@/api/exec/exec-log';
|
||||||
|
import ExecLogPanel from '../panel/index.vue';
|
||||||
|
|
||||||
|
const { visible, setVisible } = useVisible();
|
||||||
|
const { loading, setLoading } = useLoading();
|
||||||
|
|
||||||
|
const log = ref();
|
||||||
|
|
||||||
|
// TODO 测试卸载
|
||||||
|
|
||||||
|
// 打开
|
||||||
|
const open = async (id: number) => {
|
||||||
|
setVisible(true);
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
// 获取执行日志
|
||||||
|
const { data } = await getExecLog(id);
|
||||||
|
// 打开日志
|
||||||
|
nextTick(() => {
|
||||||
|
log.value.open(data);
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
} finally {
|
||||||
|
setVisible(false);
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭回调
|
||||||
|
const handleClose = () => {
|
||||||
|
handleClear();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 清空
|
||||||
|
const handleClear = () => {
|
||||||
|
setLoading(false);
|
||||||
|
setVisible(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.modal-body {
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100vh - 140px);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -41,14 +41,14 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { ExecCommandHostResponse } from '@/api/exec/exec';
|
import type { ExecHostLogQueryResponse } from '@/api/exec/exec-log';
|
||||||
import { useDictStore } from '@/store';
|
import { useDictStore } from '@/store';
|
||||||
import { execHostStatusKey } from './const';
|
import { execHostStatusKey } from './const';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
visibleBack: boolean;
|
visibleBack: boolean;
|
||||||
current: number;
|
current: number;
|
||||||
hosts: Array<ExecCommandHostResponse>;
|
hosts: Array<ExecHostLogQueryResponse>;
|
||||||
}>();
|
}>();
|
||||||
const emits = defineEmits(['back', 'selected']);
|
const emits = defineEmits(['back', 'selected']);
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { ExecCommandResponse } from '@/api/exec/exec';
|
import type { ExecLogQueryResponse } from '@/api/exec/exec-log';
|
||||||
import { onUnmounted, ref, nextTick } from 'vue';
|
import { onUnmounted, ref, nextTick } from 'vue';
|
||||||
import { getExecLogStatus } from '@/api/exec/exec-log';
|
import { getExecLogStatus } from '@/api/exec/exec-log';
|
||||||
import { execHostStatus, execStatus } from './const';
|
import { execHostStatus, execStatus } from './const';
|
||||||
@@ -39,16 +39,20 @@
|
|||||||
const currentHostExecId = ref();
|
const currentHostExecId = ref();
|
||||||
const statusIntervalId = ref();
|
const statusIntervalId = ref();
|
||||||
const finishIntervalId = ref();
|
const finishIntervalId = ref();
|
||||||
const command = ref<ExecCommandResponse>();
|
const command = ref<ExecLogQueryResponse>();
|
||||||
|
|
||||||
// 打开
|
// 打开
|
||||||
const open = (record: ExecCommandResponse) => {
|
const open = (record: ExecLogQueryResponse) => {
|
||||||
command.value = record;
|
command.value = record;
|
||||||
currentHostExecId.value = record.hosts[0].id;
|
currentHostExecId.value = record.hosts[0].id;
|
||||||
|
// 定时查询执行状态
|
||||||
|
if (record.status === execStatus.WAITING ||
|
||||||
|
record.status === execStatus.RUNNING) {
|
||||||
// 注册状态轮询
|
// 注册状态轮询
|
||||||
statusIntervalId.value = setInterval(fetchTaskStatus, 5000);
|
statusIntervalId.value = setInterval(fetchTaskStatus, 5000);
|
||||||
// 注册完成时间轮询
|
// 注册完成时间轮询
|
||||||
finishIntervalId.value = setInterval(setTaskFinishTime, 1000);
|
finishIntervalId.value = setInterval(setTaskFinishTime, 1000);
|
||||||
|
}
|
||||||
// 打开日志
|
// 打开日志
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
logView.value?.open();
|
logView.value?.open();
|
||||||
|
|||||||
@@ -160,7 +160,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { ExecCommandHostResponse } from '@/api/exec/exec';
|
import type { ExecHostLogQueryResponse } from '@/api/exec/exec-log';
|
||||||
import type { ILogAppender } from './const';
|
import type { ILogAppender } from './const';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { execHostStatus, execHostStatusKey } from './const';
|
import { execHostStatus, execHostStatusKey } from './const';
|
||||||
@@ -172,7 +172,7 @@
|
|||||||
import 'xterm/css/xterm.css';
|
import 'xterm/css/xterm.css';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
host: ExecCommandHostResponse;
|
host: ExecHostLogQueryResponse;
|
||||||
appender: ILogAppender
|
appender: ILogAppender
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { VNodeRef } from 'vue';
|
import type { VNodeRef } from 'vue';
|
||||||
import type { ExecCommandResponse } from '@/api/exec/exec';
|
import type { ExecLogQueryResponse } from '@/api/exec/exec-log';
|
||||||
import type { LogDomRef, ILogAppender } from './const';
|
import type { LogDomRef, ILogAppender } from './const';
|
||||||
import { nextTick, onBeforeMount, ref, watch } from 'vue';
|
import { nextTick, onBeforeMount, ref, watch } from 'vue';
|
||||||
import LogAppender from './log-appender';
|
import LogAppender from './log-appender';
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
current: number;
|
current: number;
|
||||||
command: ExecCommandResponse;
|
command: ExecLogQueryResponse;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const logRefs = ref<Array<LogDomRef>>([]);
|
const logRefs = ref<Array<LogDomRef>>([]);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { ExecCommandResponse } from '@/api/exec/exec';
|
import type { ExecLogQueryResponse } from '@/api/exec/exec-log';
|
||||||
import { nextTick, onMounted, ref } from 'vue';
|
import { nextTick, onMounted, ref } from 'vue';
|
||||||
import useVisible from '@/hooks/visible';
|
import useVisible from '@/hooks/visible';
|
||||||
import { useDictStore } from '@/store';
|
import { useDictStore } from '@/store';
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
const log = ref();
|
const log = ref();
|
||||||
|
|
||||||
// 打开日志
|
// 打开日志
|
||||||
const openLog = (record: ExecCommandResponse) => {
|
const openLog = (record: ExecLogQueryResponse) => {
|
||||||
setLogVisible(true);
|
setLogVisible(true);
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
log.value.open(record);
|
log.value.open(record);
|
||||||
|
|||||||
@@ -163,7 +163,7 @@
|
|||||||
<a-button v-permission="['asset:exec:exec-command']"
|
<a-button v-permission="['asset:exec:exec-command']"
|
||||||
type="text"
|
type="text"
|
||||||
size="mini"
|
size="mini"
|
||||||
@click="emits('viewLog', record.id)">
|
@click="() => emits('viewLog', record.id, $event.ctrlKey)">
|
||||||
日志
|
日志
|
||||||
</a-button>
|
</a-button>
|
||||||
<!-- 中断 -->
|
<!-- 中断 -->
|
||||||
@@ -221,8 +221,6 @@
|
|||||||
|
|
||||||
const emits = defineEmits(['viewCommand', 'viewParams', 'viewLog', 'openClear']);
|
const emits = defineEmits(['viewCommand', 'viewParams', 'viewLog', 'openClear']);
|
||||||
|
|
||||||
// TODO 日志 ctrl日志
|
|
||||||
|
|
||||||
const pagination = usePagination();
|
const pagination = usePagination();
|
||||||
const rowSelection = useRowSelection();
|
const rowSelection = useRowSelection();
|
||||||
const expandable = useExpandable();
|
const expandable = useExpandable();
|
||||||
|
|||||||
@@ -4,10 +4,13 @@
|
|||||||
<exec-log-table ref="tableRef"
|
<exec-log-table ref="tableRef"
|
||||||
@view-command="viewCommand"
|
@view-command="viewCommand"
|
||||||
@view-params="viewParams"
|
@view-params="viewParams"
|
||||||
|
@view-log="viewLog"
|
||||||
@open-clear="openClearModal" />
|
@open-clear="openClearModal" />
|
||||||
<!-- 清理模态框 -->
|
<!-- 清理模态框 -->
|
||||||
<exec-log-clear-modal ref="clearModal"
|
<exec-log-clear-modal ref="clearModal"
|
||||||
@clear="clearCallback" />
|
@clear="clearCallback" />
|
||||||
|
<!-- 执行日志模态框 -->
|
||||||
|
<exec-log-panel-modal ref="logModal" />
|
||||||
<!-- json 模态框 -->
|
<!-- json 模态框 -->
|
||||||
<json-editor-modal ref="jsonModal"
|
<json-editor-modal ref="jsonModal"
|
||||||
:esc-to-close="true" />
|
:esc-to-close="true" />
|
||||||
@@ -32,9 +35,11 @@
|
|||||||
import ExecLogClearModal from './components/exec-log-clear-modal.vue';
|
import ExecLogClearModal from './components/exec-log-clear-modal.vue';
|
||||||
import JsonEditorModal from '@/components/view/json-editor/modal/index.vue';
|
import JsonEditorModal from '@/components/view/json-editor/modal/index.vue';
|
||||||
import ShellEditorModal from '@/components/view/shell-editor/modal/index.vue';
|
import ShellEditorModal from '@/components/view/shell-editor/modal/index.vue';
|
||||||
|
import ExecLogPanelModal from '@/components/exec/log/panel-modal/index.vue';
|
||||||
|
|
||||||
const render = ref(false);
|
const render = ref(false);
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
|
const logModal = ref();
|
||||||
const clearModal = ref();
|
const clearModal = ref();
|
||||||
const jsonModal = ref();
|
const jsonModal = ref();
|
||||||
const shellModal = ref();
|
const shellModal = ref();
|
||||||
@@ -54,6 +59,15 @@
|
|||||||
jsonModal.value.open(JSON.parse(data));
|
jsonModal.value.open(JSON.parse(data));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 查看日志
|
||||||
|
const viewLog = (id: number, newWindow: boolean) => {
|
||||||
|
if (newWindow) {
|
||||||
|
// TODO openLog
|
||||||
|
} else {
|
||||||
|
logModal.value.open(id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 清理回调
|
// 清理回调
|
||||||
const clearCallback = () => {
|
const clearCallback = () => {
|
||||||
tableRef.value.fetchTableData();
|
tableRef.value.fetchTableData();
|
||||||
|
|||||||
@@ -79,9 +79,6 @@
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
<!-- 主机模态框 -->
|
|
||||||
<authorized-host-modal ref="hostModal"
|
|
||||||
@selected="setSelectedHost" />
|
|
||||||
</a-drawer>
|
</a-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -102,14 +99,14 @@
|
|||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
import { batchExecCommand } from '@/api/exec/exec';
|
import { batchExecCommand } from '@/api/exec/exec';
|
||||||
import ExecEditor from '@/components/view/exec-editor/index.vue';
|
import ExecEditor from '@/components/view/exec-editor/index.vue';
|
||||||
import AuthorizedHostModal from '@/components/asset/host/authorized-host-modal/index.vue';
|
|
||||||
|
const emits = defineEmits(['openHost']);
|
||||||
|
|
||||||
const { visible, setVisible } = useVisible();
|
const { visible, setVisible } = useVisible();
|
||||||
const { loading, setLoading } = useLoading();
|
const { loading, setLoading } = useLoading();
|
||||||
|
|
||||||
const formRef = ref<any>();
|
const formRef = ref<any>();
|
||||||
const parameterFormRef = ref<any>();
|
const parameterFormRef = ref<any>();
|
||||||
const hostModal = ref<any>();
|
|
||||||
const formModel = ref<ExecCommandRequest>({});
|
const formModel = ref<ExecCommandRequest>({});
|
||||||
const parameterFormModel = ref<Record<string, any>>({});
|
const parameterFormModel = ref<Record<string, any>>({});
|
||||||
const parameterSchema = ref<Array<TemplateParam>>([]);
|
const parameterSchema = ref<Array<TemplateParam>>([]);
|
||||||
@@ -142,18 +139,18 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
defineExpose({ open });
|
|
||||||
|
|
||||||
// 打开选择主机
|
|
||||||
const openSelectHost = () => {
|
|
||||||
hostModal.value.open(formModel.value.hostIdList);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 设置选中主机
|
// 设置选中主机
|
||||||
const setSelectedHost = (hosts: Array<number>) => {
|
const setSelectedHost = (hosts: Array<number>) => {
|
||||||
formModel.value.hostIdList = hosts;
|
formModel.value.hostIdList = hosts;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
defineExpose({ open, setSelectedHost });
|
||||||
|
|
||||||
|
// 打开选择主机
|
||||||
|
const openSelectHost = () => {
|
||||||
|
emits('openHost', formModel.value.hostIdList);
|
||||||
|
};
|
||||||
|
|
||||||
// 确定
|
// 确定
|
||||||
const handlerOk = async () => {
|
const handlerOk = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|||||||
@@ -2,15 +2,19 @@
|
|||||||
<div class="layout-container" v-if="render">
|
<div class="layout-container" v-if="render">
|
||||||
<!-- 列表-表格 -->
|
<!-- 列表-表格 -->
|
||||||
<exec-template-table ref="table"
|
<exec-template-table ref="table"
|
||||||
@open-exec="e => execModal.open(e)"
|
@open-exec="(e) => execModal.open(e)"
|
||||||
@openAdd="() => drawer.openAdd()"
|
@openAdd="() => drawer.openAdd()"
|
||||||
@openUpdate="(e) => drawer.openUpdate(e)" />
|
@openUpdate="(e) => drawer.openUpdate(e)" />
|
||||||
<!-- 添加修改模态框 -->
|
<!-- 添加修改模态框 -->
|
||||||
<exec-template-form-drawer ref="drawer"
|
<exec-template-form-drawer ref="drawer"
|
||||||
@added="modalAddCallback"
|
@added="modalAddCallback"
|
||||||
@updated="modalUpdateCallback" />
|
@updated="modalUpdateCallback" />
|
||||||
|
<!-- 主机模态框 -->
|
||||||
|
<authorized-host-modal ref="hostModal"
|
||||||
|
@selected="(e) => execModal.setSelectedHost(e)" />
|
||||||
<!-- 执行模态框 -->
|
<!-- 执行模态框 -->
|
||||||
<exec-template-exec-drawer ref="execModal" />
|
<exec-template-exec-drawer ref="execModal"
|
||||||
|
@open-host="(e) => hostModal.open(e)" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -25,10 +29,15 @@
|
|||||||
import ExecTemplateTable from './components/exec-template-table.vue';
|
import ExecTemplateTable from './components/exec-template-table.vue';
|
||||||
import ExecTemplateFormDrawer from './components/exec-template-form-drawer.vue';
|
import ExecTemplateFormDrawer from './components/exec-template-form-drawer.vue';
|
||||||
import ExecTemplateExecDrawer from './components/exec-template-exec-drawer.vue';
|
import ExecTemplateExecDrawer from './components/exec-template-exec-drawer.vue';
|
||||||
|
import AuthorizedHostModal from '@/components/asset/host/authorized-host-modal/index.vue';
|
||||||
|
|
||||||
|
// TODO TEST 选择主机
|
||||||
|
// TODO openAdd openUpdate 脊柱
|
||||||
|
|
||||||
const render = ref(false);
|
const render = ref(false);
|
||||||
const table = ref();
|
const table = ref();
|
||||||
const drawer = ref();
|
const drawer = ref();
|
||||||
|
const hostModal = ref();
|
||||||
const execModal = ref();
|
const execModal = ref();
|
||||||
|
|
||||||
// 添加回调
|
// 添加回调
|
||||||
|
|||||||
Reference in New Issue
Block a user