🔨 批量执行.
This commit is contained in:
@@ -2,14 +2,16 @@
|
|||||||
|
|
||||||
## v1.0.2
|
## v1.0.2
|
||||||
|
|
||||||
`2024-03-` `release`
|
`2024-03-22` `release`
|
||||||
|
|
||||||
* 🐞 修复 SFTP 加载失败后一直 loading
|
* 🐞 修复 SFTP 加载失败后一直 loading
|
||||||
|
* 🐞 修复 主机终端搜索框报错
|
||||||
* 🐞 修复 SSH 配置未启用还可以连接
|
* 🐞 修复 SSH 配置未启用还可以连接
|
||||||
* 🐞 修复 主机配置保存后无法修改状态
|
* 🐞 修复 主机配置保存后无法修改状态
|
||||||
* 🐞 修复 添加快捷命令时编辑器无代码提示
|
* 🐞 修复 添加快捷命令时编辑器无代码提示
|
||||||
* 🔨 修改 菜单路由命名逻辑修改
|
* 🔨 修改 菜单路由命名逻辑修改
|
||||||
* 🔨 优化 前端组件命名规范化
|
* 🔨 优化 前端组件命名规范化
|
||||||
|
* 🔨 优化 前端 emit 命名规范化
|
||||||
* 🌈 新增 双击终端会话 Tab 快速复制
|
* 🌈 新增 双击终端会话 Tab 快速复制
|
||||||
* 🌈 新增 批量执行命令
|
* 🌈 新增 批量执行命令
|
||||||
* 🌈 新增 命令执行日志
|
* 🌈 新增 命令执行日志
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ export function getExecLogPage(request: ExecLogQueryRequest) {
|
|||||||
* 查询执行记录
|
* 查询执行记录
|
||||||
*/
|
*/
|
||||||
export function getExecLog(id: number) {
|
export function getExecLog(id: number) {
|
||||||
return axios.get<ExecLogQueryResponse>('/asset/exec-log/query', { params: { id } });
|
return axios.get<ExecLogQueryResponse>('/asset/exec-log/get', { params: { id } });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,17 +3,21 @@
|
|||||||
title-align="start"
|
title-align="start"
|
||||||
title="执行日志"
|
title="执行日志"
|
||||||
width="94%"
|
width="94%"
|
||||||
:top="80"
|
:top="40"
|
||||||
:body-style="{ padding: '0' }"
|
:body-style="{ padding: '0', height: 'calc(100vh - 140px)', overflow: 'hidden' }"
|
||||||
:align-center="false"
|
:align-center="false"
|
||||||
:draggable="true"
|
:draggable="true"
|
||||||
:mask-closable="false"
|
:mask-closable="false"
|
||||||
:unmount-on-close="true"
|
:unmount-on-close="true"
|
||||||
:footer="false"
|
:footer="false"
|
||||||
@close="handleClose">
|
@close="handleClose">
|
||||||
<a-spin class="modal-body" :loading="loading">
|
<a-spin v-if="visible"
|
||||||
<!-- 日志面板 -->
|
class="modal-body"
|
||||||
<exec-log-panel ref="log" :visible-back="false" />
|
:loading="loading">
|
||||||
|
<div class="panel-wrapper">
|
||||||
|
<!-- 日志面板 -->
|
||||||
|
<exec-log-panel ref="log" :visible-back="false" />
|
||||||
|
</div>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</template>
|
</template>
|
||||||
@@ -36,7 +40,7 @@
|
|||||||
|
|
||||||
const log = ref();
|
const log = ref();
|
||||||
|
|
||||||
// TODO 测试卸载
|
// TODO 卸载
|
||||||
|
|
||||||
// 打开
|
// 打开
|
||||||
const open = async (id: number) => {
|
const open = async (id: number) => {
|
||||||
@@ -46,16 +50,18 @@
|
|||||||
// 获取执行日志
|
// 获取执行日志
|
||||||
const { data } = await getExecLog(id);
|
const { data } = await getExecLog(id);
|
||||||
// 打开日志
|
// 打开日志
|
||||||
nextTick(() => {
|
await nextTick(() => {
|
||||||
log.value.open(data);
|
log.value.open(data);
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
} finally {
|
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
defineExpose({ open });
|
||||||
|
|
||||||
// 关闭回调
|
// 关闭回调
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
handleClear();
|
handleClear();
|
||||||
@@ -65,6 +71,7 @@
|
|||||||
const handleClear = () => {
|
const handleClear = () => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
|
console.log('clear');
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
@@ -72,6 +79,39 @@
|
|||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.modal-body {
|
.modal-body {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(100vh - 140px);
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
padding: 0 12px 12px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.panel-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.exec-host-container) {
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
.host-header {
|
||||||
|
height: 38px;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.exec-host-items {
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100% - 38px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.log-header) {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<!-- 执行主机 -->
|
<!-- 执行主机 -->
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<!-- 表头 -->
|
<!-- 表头 -->
|
||||||
<div class="panel-header">
|
<div class="host-header">
|
||||||
<h3>执行主机</h3>
|
<h3>执行主机</h3>
|
||||||
<!-- 操作 -->
|
<!-- 操作 -->
|
||||||
<a-button v-if="visibleBack"
|
<a-button v-if="visibleBack"
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
</a-button>
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
<!-- 主机列表 -->
|
<!-- 主机列表 -->
|
||||||
<div class="exec-host-container">
|
<div class="exec-host-items">
|
||||||
<div v-for="item in hosts"
|
<div v-for="item in hosts"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
class="exec-host-item"
|
class="exec-host-item"
|
||||||
@@ -57,8 +57,27 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.exec-host-container {
|
|
||||||
margin-top: 4px;
|
.host-header {
|
||||||
|
width: 100%;
|
||||||
|
height: 28px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
h3, > span {
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
color: var(--color-text-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.exec-host-items {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: calc(100% - 32px);
|
width: calc(100% - 32px);
|
||||||
height: calc(100% - 68px);
|
height: calc(100% - 68px);
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="log-panel-container" v-if="command">
|
<div class="log-panel-container" v-if="execLog && appender">
|
||||||
<!-- 执行主机 -->
|
<!-- 执行主机 -->
|
||||||
<exec-host class="exec-host-container"
|
<exec-host class="exec-host-container"
|
||||||
:visibleBack="visibleBack"
|
:visibleBack="visibleBack"
|
||||||
:current="currentHostExecId"
|
:current="currentHostExecId"
|
||||||
:hosts="command.hosts"
|
:hosts="execLog.hosts"
|
||||||
@selected="selectedHost"
|
@selected="selectedHost"
|
||||||
@back="emits('back')" />
|
@back="emits('back')" />
|
||||||
<!-- 日志容器 -->
|
<!-- 日志容器 -->
|
||||||
<log-view ref="logView"
|
<log-view ref="logViewRef"
|
||||||
class="log-view-container"
|
class="log-view-container"
|
||||||
:current="currentHostExecId"
|
:current="currentHostExecId"
|
||||||
:command="command" />
|
:hosts="execLog.hosts"
|
||||||
|
:appender="appender" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -23,11 +24,13 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { ExecLogQueryResponse } from '@/api/exec/exec-log';
|
import type { ExecLogQueryResponse } from '@/api/exec/exec-log';
|
||||||
|
import type { ILogAppender } from './const';
|
||||||
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';
|
||||||
import ExecHost from './exec-host.vue';
|
import ExecHost from './exec-host.vue';
|
||||||
import LogView from './log-view.vue';
|
import LogView from './log-view.vue';
|
||||||
|
import LogAppender from '@/components/exec/log/panel/log-appender';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
visibleBack: boolean
|
visibleBack: boolean
|
||||||
@@ -35,15 +38,17 @@
|
|||||||
|
|
||||||
const emits = defineEmits(['back']);
|
const emits = defineEmits(['back']);
|
||||||
|
|
||||||
const logView = ref();
|
const logViewRef = ref();
|
||||||
const currentHostExecId = ref();
|
const currentHostExecId = ref();
|
||||||
const statusIntervalId = ref();
|
const statusIntervalId = ref();
|
||||||
const finishIntervalId = ref();
|
const finishIntervalId = ref();
|
||||||
const command = ref<ExecLogQueryResponse>();
|
const execLog = ref<ExecLogQueryResponse>();
|
||||||
|
const appender = ref<ILogAppender>();
|
||||||
|
|
||||||
// 打开
|
// 打开
|
||||||
const open = (record: ExecLogQueryResponse) => {
|
const open = (record: ExecLogQueryResponse) => {
|
||||||
command.value = record;
|
appender.value = new LogAppender({ execId: record.id });
|
||||||
|
execLog.value = record;
|
||||||
currentHostExecId.value = record.hosts[0].id;
|
currentHostExecId.value = record.hosts[0].id;
|
||||||
// 定时查询执行状态
|
// 定时查询执行状态
|
||||||
if (record.status === execStatus.WAITING ||
|
if (record.status === execStatus.WAITING ||
|
||||||
@@ -55,24 +60,24 @@
|
|||||||
}
|
}
|
||||||
// 打开日志
|
// 打开日志
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
logView.value?.open();
|
logViewRef.value?.open();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 加载状态
|
// 加载状态
|
||||||
const fetchTaskStatus = async () => {
|
const fetchTaskStatus = async () => {
|
||||||
if (!command.value) {
|
if (!execLog.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 加载状态
|
// 加载状态
|
||||||
const { data: { logList, hostList } } = await getExecLogStatus([command.value.id]);
|
const { data: { logList, hostList } } = await getExecLogStatus([execLog.value.id]);
|
||||||
if (logList.length) {
|
if (logList.length) {
|
||||||
command.value.status = logList[0].status;
|
execLog.value.status = logList[0].status;
|
||||||
command.value.startTime = logList[0].startTime;
|
execLog.value.startTime = logList[0].startTime;
|
||||||
command.value.finishTime = logList[0].finishTime;
|
execLog.value.finishTime = logList[0].finishTime;
|
||||||
}
|
}
|
||||||
// 设置主机状态
|
// 设置主机状态
|
||||||
for (let host of command.value.hosts) {
|
for (let host of execLog.value.hosts) {
|
||||||
const hostStatus = hostList.find(s => s.id === host.id);
|
const hostStatus = hostList.find(s => s.id === host.id);
|
||||||
if (hostStatus) {
|
if (hostStatus) {
|
||||||
host.status = hostStatus.status;
|
host.status = hostStatus.status;
|
||||||
@@ -85,15 +90,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 已完成跳过
|
// 已完成跳过
|
||||||
if (command.value.status === execStatus.COMPLETED ||
|
if (execLog.value.status === execStatus.COMPLETED ||
|
||||||
command.value.status === execStatus.FAILED) {
|
execLog.value.status === execStatus.FAILED) {
|
||||||
closeClient();
|
closeClient();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 设置完成时间
|
// 设置完成时间
|
||||||
const setTaskFinishTime = () => {
|
const setTaskFinishTime = () => {
|
||||||
const hosts = command.value?.hosts;
|
const hosts = execLog.value?.hosts;
|
||||||
if (!hosts) {
|
if (!hosts) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -118,18 +123,20 @@
|
|||||||
|
|
||||||
// 关闭连接
|
// 关闭连接
|
||||||
const closeClient = () => {
|
const closeClient = () => {
|
||||||
// 关闭日志
|
|
||||||
logView.value?.closeClient();
|
|
||||||
// 清理轮询
|
// 清理轮询
|
||||||
clearAllInterval();
|
clearAllInterval();
|
||||||
|
// 关闭 client
|
||||||
|
appender.value?.closeClient();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 清理并且关闭
|
// 清理并且关闭
|
||||||
const closeAll = () => {
|
const closeAll = () => {
|
||||||
// 关闭日志
|
// TODO
|
||||||
logView.value?.closeAll();
|
console.log('closeAll');
|
||||||
// 清理轮询
|
// 清理轮询
|
||||||
clearAllInterval();
|
clearAllInterval();
|
||||||
|
// 关闭 appender
|
||||||
|
appender.value?.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 清理轮询
|
// 清理轮询
|
||||||
|
|||||||
@@ -235,10 +235,10 @@ export default class LogAppender implements ILogAppender {
|
|||||||
closeView(): void {
|
closeView(): void {
|
||||||
// 关闭 terminal
|
// 关闭 terminal
|
||||||
Object.values(this.appenderRel).forEach(s => {
|
Object.values(this.appenderRel).forEach(s => {
|
||||||
s.terminal?.dispose();
|
|
||||||
if (s.addons) {
|
if (s.addons) {
|
||||||
Object.values(s.addons).forEach(s => s.dispose());
|
Object.values(s.addons).forEach(s => s.dispose());
|
||||||
}
|
}
|
||||||
|
s.terminal?.dispose();
|
||||||
});
|
});
|
||||||
// 移除自适应事件
|
// 移除自适应事件
|
||||||
removeEventListen(window, 'resize', this.fitAllFn);
|
removeEventListen(window, 'resize', this.fitAllFn);
|
||||||
@@ -246,8 +246,14 @@ export default class LogAppender implements ILogAppender {
|
|||||||
|
|
||||||
// 关闭
|
// 关闭
|
||||||
close(): void {
|
close(): void {
|
||||||
this.closeClient();
|
try {
|
||||||
this.closeView();
|
this.closeClient();
|
||||||
|
this.closeView();
|
||||||
|
} catch (ex) {
|
||||||
|
// TODO
|
||||||
|
console.log('errr');
|
||||||
|
console.error(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理消息
|
// 处理消息
|
||||||
|
|||||||
@@ -211,7 +211,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@header-height: 40px;
|
@header-height: 38px;
|
||||||
|
|
||||||
.log-header {
|
.log-header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<template v-if="appender">
|
<log-item class="log-item"
|
||||||
<log-item class="log-item"
|
v-show="current === host.id"
|
||||||
v-show="current === host.id"
|
v-for="host in hosts"
|
||||||
v-for="host in command.hosts"
|
:key="host.id"
|
||||||
:key="host.id"
|
:ref="addRef as unknown as VNodeRef"
|
||||||
:ref="addRef as unknown as VNodeRef"
|
:host="host"
|
||||||
:host="host"
|
:appender="appender" />
|
||||||
:appender="appender as ILogAppender" />
|
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -20,25 +18,24 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { VNodeRef } from 'vue';
|
import type { VNodeRef } from 'vue';
|
||||||
import type { ExecLogQueryResponse } from '@/api/exec/exec-log';
|
import type { ExecHostLogQueryResponse } 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, ref, watch } from 'vue';
|
||||||
import LogAppender from './log-appender';
|
|
||||||
import LogItem from './log-item.vue';
|
import LogItem from './log-item.vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
current: number;
|
current: number;
|
||||||
command: ExecLogQueryResponse;
|
hosts: Array<ExecHostLogQueryResponse>;
|
||||||
|
appender: ILogAppender;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const logRefs = ref<Array<LogDomRef>>([]);
|
const logRefs = ref<Array<LogDomRef>>([]);
|
||||||
const appender = ref<ILogAppender>();
|
|
||||||
|
|
||||||
// 切换标签
|
// 切换标签
|
||||||
watch(() => props.current, (val) => {
|
watch(() => props.current, (val) => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
appender.value?.setCurrent(val);
|
props.appender?.setCurrent(val);
|
||||||
}, 50);
|
}, 50);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -46,26 +43,16 @@
|
|||||||
// 打开
|
// 打开
|
||||||
const open = () => {
|
const open = () => {
|
||||||
nextTick(async () => {
|
nextTick(async () => {
|
||||||
if (appender.value) {
|
// TODO
|
||||||
|
console.log(props.appender);
|
||||||
|
if (props.appender) {
|
||||||
// 初始化
|
// 初始化
|
||||||
await appender.value.init(logRefs.value);
|
await props.appender.init(logRefs.value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 关闭客户端
|
defineExpose({ open });
|
||||||
const closeClient = () => {
|
|
||||||
appender.value?.closeClient();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 关闭全部
|
|
||||||
const closeAll = () => {
|
|
||||||
appender.value?.close();
|
|
||||||
logRefs.value = [];
|
|
||||||
appender.value = undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
defineExpose({ open, closeClient, closeAll });
|
|
||||||
|
|
||||||
// 添加 ref
|
// 添加 ref
|
||||||
const addRef = (ref: any) => {
|
const addRef = (ref: any) => {
|
||||||
@@ -81,10 +68,6 @@
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
onBeforeMount(() => {
|
|
||||||
appender.value = new LogAppender({ execId: props.command.id });
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|||||||
@@ -112,6 +112,7 @@
|
|||||||
const defaultForm = (): ExecCommandRequest => {
|
const defaultForm = (): ExecCommandRequest => {
|
||||||
return {
|
return {
|
||||||
command: '',
|
command: '',
|
||||||
|
timeout: 0,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -220,8 +221,8 @@
|
|||||||
@command-gap: @form-width + @history-width + 32px;
|
@command-gap: @form-width + @history-width + 32px;
|
||||||
|
|
||||||
.exec-container {
|
.exec-container {
|
||||||
width: calc(100% - 32px);
|
width: 100%;
|
||||||
height: calc(100% - 32px);
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -265,4 +266,23 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.panel-header) {
|
||||||
|
width: 100%;
|
||||||
|
height: 28px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
h3, > span {
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
color: var(--color-text-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="layout-container full">
|
<div class="layout-container full">
|
||||||
<!-- 执行面板 -->
|
<!-- 执行面板 -->
|
||||||
<exec-panel v-show="!logVisible"
|
<div v-show="!logVisible" class="panel-wrapper">
|
||||||
@submit="openLog" />
|
<exec-panel @submit="openLog" />
|
||||||
|
</div>
|
||||||
<!-- 执行日志 -->
|
<!-- 执行日志 -->
|
||||||
<exec-log-panel v-if="logVisible"
|
<div v-if="logVisible" class="panel-wrapper">
|
||||||
ref="log"
|
<exec-log-panel ref="log"
|
||||||
:visibleBack="true"
|
:visibleBack="true"
|
||||||
@back="setLogVisible(false)" />
|
@back="setLogVisible(false)" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -48,23 +50,10 @@
|
|||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
||||||
:deep(.panel-header) {
|
.panel-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 28px;
|
height: 100%;
|
||||||
margin-bottom: 4px;
|
position: relative;
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: flex-start;
|
|
||||||
|
|
||||||
h3, > span {
|
|
||||||
margin: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
color: var(--color-text-1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -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, $event.ctrlKey)">
|
@click="(e) => emits('viewLog', record.id, e.ctrlKey)">
|
||||||
日志
|
日志
|
||||||
</a-button>
|
</a-button>
|
||||||
<!-- 中断 -->
|
<!-- 中断 -->
|
||||||
|
|||||||
@@ -31,9 +31,6 @@
|
|||||||
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';
|
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();
|
||||||
|
|||||||
Reference in New Issue
Block a user