计划任务中断及清理.

This commit is contained in:
lijiahang
2024-04-12 17:23:59 +08:00
parent b78d03b751
commit 7e8e5d4d08
17 changed files with 206 additions and 58 deletions

View File

@@ -0,0 +1,80 @@
<template>
<a-select v-model:model-value="value as any"
:options="optionData"
:allow-search="true"
:loading="loading"
:disabled="loading"
:filter-option="labelFilter"
:allow-create="allowCreate"
placeholder="请选择计划任务" />
</template>
<script lang="ts">
export default {
name: 'execJobSelector'
};
</script>
<script lang="ts" setup>
import type { SelectOptionData } from '@arco-design/web-vue';
import { computed, onBeforeMount, ref } from 'vue';
import { useCacheStore } from '@/store';
import { labelFilter } from '@/types/form';
import useLoading from '@/hooks/loading';
const props = withDefaults(defineProps<Partial<{
modelValue: number;
name: string;
allowCreate: boolean;
}>>(), {
allowCreate: false,
});
const emits = defineEmits(['update:modelValue', 'update:name']);
const { loading, setLoading } = useLoading();
const cacheStore = useCacheStore();
const value = computed({
get() {
if (props.allowCreate) {
return props.modelValue || props.name;
} else {
return props.modelValue;
}
},
set(e) {
if (typeof e === 'string') {
emits('update:modelValue', null);
emits('update:name', e);
} else {
// 已有的值
emits('update:modelValue', e);
emits('update:name', null);
}
}
});
const optionData = ref<Array<SelectOptionData>>([]);
// 初始化选项
onBeforeMount(async () => {
setLoading(true);
try {
const dictKeys = await cacheStore.loadExecJobs();
optionData.value = dictKeys.map(s => {
return {
label: s.name,
value: s.id,
};
});
} catch (e) {
} finally {
setLoading(false);
}
});
</script>
<style lang="less" scoped>
</style>

View File

@@ -1,3 +1,6 @@
// 执行类型
export type ExecType = 'BATCH' | 'JOB';
// 批量执行状态 // 批量执行状态
export const execStatus = { export const execStatus = {
// 等待中 // 等待中

View File

@@ -16,7 +16,9 @@
:loading="loading"> :loading="loading">
<div class="panel-wrapper"> <div class="panel-wrapper">
<!-- 日志面板 --> <!-- 日志面板 -->
<exec-log-panel ref="log" :visible-back="false" /> <exec-log-panel ref="log"
:type="type"
:visible-back="false" />
</div> </div>
</a-spin> </a-spin>
</a-modal> </a-modal>
@@ -29,12 +31,18 @@
</script> </script>
<script lang="ts" setup> <script lang="ts" setup>
import type { ExecType } from '../const';
import useVisible from '@/hooks/visible'; import useVisible from '@/hooks/visible';
import useLoading from '@/hooks/loading'; import useLoading from '@/hooks/loading';
import { nextTick, ref } from 'vue'; import { nextTick, ref } from 'vue';
import { getExecCommandLog } from '@/api/exec/exec-command-log'; import { getExecCommandLog } from '@/api/exec/exec-command-log';
import { getExecJobLog } from '@/api/exec/exec-job-log';
import ExecLogPanel from '../panel/index.vue'; import ExecLogPanel from '../panel/index.vue';
const props = defineProps<{
type: ExecType;
}>();
const { visible, setVisible } = useVisible(); const { visible, setVisible } = useVisible();
const { loading, setLoading } = useLoading(); const { loading, setLoading } = useLoading();
@@ -46,7 +54,15 @@
setLoading(true); setLoading(true);
try { try {
// 获取执行日志 // 获取执行日志
const { data } = await getExecCommandLog(id); let detailGetter;
if (props.type === 'BATCH') {
// 批量执行日志
detailGetter = getExecCommandLog(id);
} else {
// 计划任务日志
detailGetter = getExecJobLog(id);
}
const { data } = await detailGetter;
// 打开日志 // 打开日志
await nextTick(() => { await nextTick(() => {
setTimeout(() => { setTimeout(() => {

View File

@@ -10,8 +10,9 @@
<!-- 日志容器 --> <!-- 日志容器 -->
<log-view ref="logViewRef" <log-view ref="logViewRef"
class="log-view-container" class="log-view-container"
:type="type"
:current="currentHostExecId" :current="currentHostExecId"
:hosts="execLog.hosts" :exec-log="execLog"
:appender="appender" /> :appender="appender" />
</div> </div>
</template> </template>
@@ -25,16 +26,19 @@
<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 './appender-const'; import type { ILogAppender } from './appender-const';
import type { ExecType } from '../const';
import { onUnmounted, ref, nextTick, onMounted } from 'vue'; import { onUnmounted, ref, nextTick, onMounted } from 'vue';
import { getExecCommandLogStatus } from '@/api/exec/exec-command-log'; import { getExecCommandLogStatus } from '@/api/exec/exec-command-log';
import { getExecJobLogStatus } from '@/api/exec/exec-job-log';
import { dictKeys, execHostStatus, execStatus } from '../const'; import { dictKeys, execHostStatus, execStatus } from '../const';
import { useDictStore } from '@/store'; import { useDictStore } from '@/store';
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'; import LogAppender from './log-appender';
const props = defineProps<{ const props = defineProps<{
visibleBack: boolean visibleBack: boolean;
type: ExecType;
}>(); }>();
const emits = defineEmits(['back']); const emits = defineEmits(['back']);
@@ -48,7 +52,7 @@
// 打开 // 打开
const open = (record: ExecLogQueryResponse) => { const open = (record: ExecLogQueryResponse) => {
appender.value = new LogAppender({ execId: record.id }); appender.value = new LogAppender(props.type, { execId: record.id });
execLog.value = record; execLog.value = record;
currentHostExecId.value = record.hosts[0].id; currentHostExecId.value = record.hosts[0].id;
// 定时查询执行状态 // 定时查询执行状态
@@ -71,7 +75,15 @@
return; return;
} }
// 加载状态 // 加载状态
const { data: { logList, hostList } } = await getExecCommandLogStatus([execLog.value.id]); let statusGetter;
if (props.type === 'BATCH') {
// 批量执行日志状态
statusGetter = getExecCommandLogStatus([execLog.value.id]);
} else {
// 计划任务日志状态
statusGetter = getExecJobLogStatus([execLog.value.id]);
}
const { data: { logList, hostList } } = await statusGetter;
if (logList.length) { if (logList.length) {
execLog.value.status = logList[0].status; execLog.value.status = logList[0].status;
execLog.value.startTime = logList[0].startTime; execLog.value.startTime = logList[0].startTime;

View File

@@ -1,7 +1,9 @@
import type { ILogAppender, LogAddons, LogAppenderConf, LogDomRef } from './appender-const'; import type { ILogAppender, LogAddons, LogAppenderConf, LogDomRef } from './appender-const';
import { LogAppenderOptions } from './appender-const'; import { LogAppenderOptions } from './appender-const';
import type { ExecType } from '../const';
import type { ExecLogTailRequest } from '@/api/exec/exec-log'; import type { ExecLogTailRequest } from '@/api/exec/exec-log';
import { getExecCommandLogTailToken } from '@/api/exec/exec-command-log'; import { getExecCommandLogTailToken } from '@/api/exec/exec-command-log';
import { getExecJobLogTailToken } from '@/api/exec/exec-job-log';
import { webSocketBaseUrl } from '@/utils/env'; import { webSocketBaseUrl } from '@/utils/env';
import { Message } from '@arco-design/web-vue'; import { Message } from '@arco-design/web-vue';
import { createWebSocket } from '@/utils'; import { createWebSocket } from '@/utils';
@@ -29,8 +31,11 @@ export default class LogAppender implements ILogAppender {
private readonly fitAllFn: () => {}; private readonly fitAllFn: () => {};
constructor(config: ExecLogTailRequest) { private readonly type: ExecType;
constructor(type: ExecType, config: ExecLogTailRequest) {
this.current = undefined as unknown as LogAppenderConf; this.current = undefined as unknown as LogAppenderConf;
this.type = type;
this.config = config; this.config = config;
this.appenderRel = {}; this.appenderRel = {};
this.fitAllFn = useDebounceFn(this.fitAll).bind(this); this.fitAllFn = useDebounceFn(this.fitAll).bind(this);
@@ -141,8 +146,16 @@ export default class LogAppender implements ILogAppender {
// 初始化 client // 初始化 client
async openClient() { async openClient() {
let tokenMaker;
// 获取 token // 获取 token
const { data } = await getExecCommandLogTailToken(this.config); if (this.type === 'BATCH') {
// 获取批量执行日志 token
tokenMaker = getExecCommandLogTailToken(this.config);
} else {
// 获取计划任务日志 token
tokenMaker = getExecJobLogTailToken(this.config);
}
const { data } = await tokenMaker;
// 打开会话 // 打开会话
try { try {
this.client = await createWebSocket(`${webSocketBaseUrl}/exec/log/${data}`); this.client = await createWebSocket(`${webSocketBaseUrl}/exec/log/${data}`);

View File

@@ -4,6 +4,10 @@
<div class="log-header"> <div class="log-header">
<!-- 左侧信息 --> <!-- 左侧信息 -->
<a-space class="log-header-left" :size="12"> <a-space class="log-header-left" :size="12">
<!-- 执行序列 -->
<a-tag v-if="execLog.execSeq" color="green">
#{{ execLog.execSeq }}
</a-tag>
<!-- 状态 --> <!-- 状态 -->
<a-tag :color="getDictValue(execHostStatusKey, host.status, 'color')"> <a-tag :color="getDictValue(execHostStatusKey, host.status, 'color')">
{{ getDictValue(execHostStatusKey, host.status) }} {{ getDictValue(execHostStatusKey, host.status) }}
@@ -160,20 +164,24 @@
</script> </script>
<script lang="ts" setup> <script lang="ts" setup>
import type { ExecHostLogQueryResponse } from '@/api/exec/exec-log'; import type { ExecLogQueryResponse, ExecHostLogQueryResponse } from '@/api/exec/exec-log';
import type { ILogAppender } from './appender-const'; import type { ILogAppender } from './appender-const';
import type { ExecType } from '../const';
import { ref } from 'vue'; import { ref } from 'vue';
import { execHostStatus, execHostStatusKey } from '../const'; import { execHostStatus, execHostStatusKey } from '../const';
import { formatDuration } from '@/utils'; import { formatDuration } from '@/utils';
import { useDictStore } from '@/store'; import { useDictStore } from '@/store';
import { downloadExecCommandLogFile } from '@/api/exec/exec-command-log'; import { downloadExecCommandLogFile } from '@/api/exec/exec-command-log';
import { downloadExecJobLogFile } from '@/api/exec/exec-job-log';
import { downloadFile } from '@/utils/file'; import { downloadFile } from '@/utils/file';
import XtermSearchModal from '@/components/xtrem/search-modal/index.vue'; import XtermSearchModal from '@/components/xtrem/search-modal/index.vue';
import 'xterm/css/xterm.css'; import 'xterm/css/xterm.css';
const props = defineProps<{ const props = defineProps<{
type: ExecType;
execLog: ExecLogQueryResponse;
host: ExecHostLogQueryResponse; host: ExecHostLogQueryResponse;
appender: ILogAppender appender: ILogAppender;
}>(); }>();
const { getDictValue } = useDictStore(); const { getDictValue } = useDictStore();
@@ -204,7 +212,17 @@
// 下载文件 // 下载文件
const downloadLogFile = async (id: number) => { const downloadLogFile = async (id: number) => {
const data = await downloadExecCommandLogFile(id); // 获取日志文件
let fileGetter;
if (props.type === 'BATCH') {
// 下载批量执行日志
fileGetter = downloadExecCommandLogFile(id);
} else {
// 下载计划任务日志
fileGetter = downloadExecJobLogFile(id);
}
// 瞎子啊
const data = await fileGetter;
downloadFile(data); downloadFile(data);
}; };

View File

@@ -2,10 +2,12 @@
<div class="container"> <div class="container">
<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 execLog.hosts"
:key="host.id" :key="host.id"
:ref="addRef as unknown as VNodeRef" :ref="addRef as unknown as VNodeRef"
:type="type"
:host="host" :host="host"
:exec-log="execLog"
:appender="appender" /> :appender="appender" />
</div> </div>
</template> </template>
@@ -19,14 +21,16 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { VNodeRef } from 'vue'; import type { VNodeRef } from 'vue';
import type { LogDomRef, ILogAppender } from './appender-const'; import type { LogDomRef, ILogAppender } from './appender-const';
import type { ExecHostLogQueryResponse } from '@/api/exec/exec-log'; import type { ExecLogQueryResponse } from '@/api/exec/exec-log';
import type { ExecType } from '../const';
import { nextTick, ref, watch } from 'vue'; import { nextTick, ref, watch } from 'vue';
import LogItem from './log-item.vue'; import LogItem from './log-item.vue';
const props = defineProps<{ const props = defineProps<{
current: number; current: number;
hosts: Array<ExecHostLogQueryResponse>; execLog: ExecLogQueryResponse;
appender: ILogAppender; appender: ILogAppender;
type: ExecType;
}>(); }>();
const logRefs = ref<Array<LogDomRef>>([]); const logRefs = ref<Array<LogDomRef>>([]);

View File

@@ -13,12 +13,14 @@ import { getHostGroupTree } from '@/api/asset/host-group';
import { getMenuList } from '@/api/system/menu'; import { getMenuList } from '@/api/system/menu';
import { getCurrentAuthorizedHostIdentity, getCurrentAuthorizedHostKey } from '@/api/asset/asset-authorized-data'; import { getCurrentAuthorizedHostIdentity, getCurrentAuthorizedHostKey } from '@/api/asset/asset-authorized-data';
import { getCommandSnippetGroupList } from '@/api/asset/command-snippet-group'; import { getCommandSnippetGroupList } from '@/api/asset/command-snippet-group';
import { getExecJobList } from '@/api/exec/exec-job';
export type CacheType = 'users' | 'menus' | 'roles' export type CacheType = 'users' | 'menus' | 'roles'
| 'hosts' | 'hostGroups' | 'hostKeys' | 'hostIdentities' | 'hosts' | 'hostGroups' | 'hostKeys' | 'hostIdentities'
| 'dictKeys' | 'dictKeys'
| 'authorizedHostKeys' | 'authorizedHostIdentities' | 'authorizedHostKeys' | 'authorizedHostIdentities'
| 'commandSnippetGroups' | 'commandSnippetGroups'
| 'execJob'
| string | string
export default defineStore('cache', { export default defineStore('cache', {
@@ -118,5 +120,10 @@ export default defineStore('cache', {
return await this.load('commandSnippetGroups', getCommandSnippetGroupList, force); return await this.load('commandSnippetGroups', getCommandSnippetGroupList, force);
}, },
// 获取执行计划列表
async loadExecJobs(force = false) {
return await this.load('execJob', getExecJobList, force);
},
} }
}); });

View File

@@ -1,7 +1,9 @@
<template> <template>
<div class="container"> <div class="container">
<div class="wrapper"> <div class="wrapper">
<exec-log-panel ref="log" :visible-back="false" /> <exec-log-panel ref="log"
type="BATCH"
:visible-back="false" />
</div> </div>
</div> </div>
</template> </template>

View File

@@ -10,7 +10,8 @@
<exec-command-log-clear-modal ref="clearModal" <exec-command-log-clear-modal ref="clearModal"
@clear="clearCallback" /> @clear="clearCallback" />
<!-- 执行日志模态框 --> <!-- 执行日志模态框 -->
<exec-log-panel-modal ref="logModal" /> <exec-log-panel-modal ref="logModal"
type="BATCH" />
<!-- json 模态框 --> <!-- json 模态框 -->
<json-editor-modal ref="jsonModal" <json-editor-modal ref="jsonModal"
:esc-to-close="true" /> :esc-to-close="true" />

View File

@@ -7,6 +7,7 @@
<!-- 执行日志 --> <!-- 执行日志 -->
<div v-if="logVisible" class="panel-wrapper"> <div v-if="logVisible" class="panel-wrapper">
<exec-log-panel ref="log" <exec-log-panel ref="log"
type="BATCH"
:visibleBack="true" :visibleBack="true"
@back="setLogVisible(false)" /> @back="setLogVisible(false)" />
</div> </div>

View File

@@ -1,7 +1,9 @@
<template> <template>
<div class="container"> <div class="container">
<div class="wrapper"> <div class="wrapper">
<exec-log-panel ref="log" :visible-back="false" /> <exec-log-panel ref="log"
type="JOB"
:visible-back="false" />
</div> </div>
</div> </div>
</template> </template>

View File

@@ -103,17 +103,17 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { ExecLogQueryResponse, ExecHostLogQueryResponse } from '@/api/exec/exec-log'; import type { ExecLogQueryResponse, ExecHostLogQueryResponse } from '@/api/exec/exec-log';
import { deleteExecJobHostLog } from '@/api/exec/exec-job-log'; import { deleteExecJobHostLog } from '@/api/exec/exec-job-log';
import { Message } from '@arco-design/web-vue'; import { interruptHostExecJob } from '@/api/exec/exec-job-log';
import useLoading from '@/hooks/loading';
import columns from '../../exec-command-log/types/host-table.columns';
import { execHostStatusKey, execHostStatus } from '@/components/exec/log/const'; import { execHostStatusKey, execHostStatus } from '@/components/exec/log/const';
import { useDictStore } from '@/store'; import { useDictStore } from '@/store';
import useLoading from '@/hooks/loading';
import columns from '../../exec-command-log/types/host-table.columns';
import { useExpandable } from '@/types/table'; import { useExpandable } from '@/types/table';
import { dateFormat, formatDuration } from '@/utils'; import { dateFormat, formatDuration } from '@/utils';
// import { interruptHostExecJob } from '@/api/exec/exec-job';
import { downloadExecJobLogFile } from '@/api/exec/exec-job-log'; import { downloadExecJobLogFile } from '@/api/exec/exec-job-log';
import { copy } from '@/hooks/copy'; import { copy } from '@/hooks/copy';
import { downloadFile } from '@/utils/file'; import { downloadFile } from '@/utils/file';
import { Message } from '@arco-design/web-vue';
const props = defineProps<{ const props = defineProps<{
row: ExecLogQueryResponse; row: ExecLogQueryResponse;
@@ -136,9 +136,9 @@
try { try {
setLoading(true); setLoading(true);
// 调用中断接口 // 调用中断接口
// await interruptHostExecJob({ await interruptHostExecJob({
// hostLogId: record.id hostLogId: record.id
// }); });
Message.success('已中断'); Message.success('已中断');
record.status = execHostStatus.INTERRUPTED; record.status = execHostStatus.INTERRUPTED;
} catch (e) { } catch (e) {

View File

@@ -2,7 +2,7 @@
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form" body-class="modal-form"
title-align="start" title-align="start"
title="清空批量执行日志" title="清空计划任务日志"
:align-center="false" :align-center="false"
:draggable="true" :draggable="true"
:mask-closable="false" :mask-closable="false"
@@ -25,16 +25,11 @@
show-time show-time
format="YYYY-MM-DD HH:mm:ss" /> format="YYYY-MM-DD HH:mm:ss" />
</a-form-item> </a-form-item>
<!-- 执行用户 --> <!-- 计划任务 -->
<a-form-item field="userId" label="执行用户"> <a-form-item field="sourceId" label="计划任务">
<user-selector v-model="formModel.userId" <exec-job-selector v-model:model-value="formModel.sourceId"
placeholder="请选择执行用户" v-model:name="formModel.description"
allow-clear /> allow-create
</a-form-item>
<!-- 执行描述 -->
<a-form-item field="description" label="执行描述">
<a-input v-model="formModel.description"
placeholder="请输入执行描述"
allow-clear /> allow-clear />
</a-form-item> </a-form-item>
<!-- 执行命令 --> <!-- 执行命令 -->
@@ -69,7 +64,7 @@
import { getExecJobLogCount, clearExecJobLog } from '@/api/exec/exec-job-log'; import { getExecJobLogCount, clearExecJobLog } from '@/api/exec/exec-job-log';
import { Message, Modal } from '@arco-design/web-vue'; import { Message, Modal } from '@arco-design/web-vue';
import { useDictStore } from '@/store'; import { useDictStore } from '@/store';
import UserSelector from '@/components/user/user/selector/index.vue'; import ExecJobSelector from '@/components/exec/job/selector/index.vue';
const emits = defineEmits(['clear']); const emits = defineEmits(['clear']);
@@ -83,7 +78,7 @@
const defaultForm = (): ExecLogQueryRequest => { const defaultForm = (): ExecLogQueryRequest => {
return { return {
id: undefined, id: undefined,
userId: undefined, sourceId: undefined,
description: undefined, description: undefined,
command: undefined, command: undefined,
status: undefined, status: undefined,
@@ -103,6 +98,7 @@
}; };
defineExpose({ open }); defineExpose({ open });
// 确定 // 确定
const handlerOk = async () => { const handlerOk = async () => {
setLoading(true); setLoading(true);

View File

@@ -3,14 +3,14 @@
<a-card class="general-card table-search-card"> <a-card class="general-card table-search-card">
<query-header :model="formModel" <query-header :model="formModel"
label-align="left" label-align="left"
:itemOptions="{ 5: { span: 2 } }" :itemOptions="{ 4: { span: 2 } }"
@submit="fetchTableData" @submit="fetchTableData"
@reset="fetchTableData" @reset="fetchTableData"
@keyup.enter="() => fetchTableData()"> @keyup.enter="() => fetchTableData()">
<!-- 执行描述 --> <!-- 任务名称 -->
<a-form-item field="description" label="执行描述"> <a-form-item field="description" label="任务名称">
<a-input v-model="formModel.description" <a-input v-model="formModel.description"
placeholder="请输入执行描述" placeholder="请输入任务名称"
allow-clear /> allow-clear />
</a-form-item> </a-form-item>
<!-- 执行状态 --> <!-- 执行状态 -->
@@ -20,12 +20,6 @@
placeholder="请选择执行状态" placeholder="请选择执行状态"
allow-clear /> allow-clear />
</a-form-item> </a-form-item>
<!-- 执行用户 -->
<a-form-item field="userId" label="执行用户">
<user-selector v-model="formModel.userId"
placeholder="请选择执行用户"
allow-clear />
</a-form-item>
<!-- 执行命令 --> <!-- 执行命令 -->
<a-form-item field="command" label="执行命令"> <a-form-item field="command" label="执行命令">
<a-input v-model="formModel.command" <a-input v-model="formModel.command"
@@ -212,8 +206,7 @@
import { useExpandable, usePagination, useRowSelection } from '@/types/table'; import { useExpandable, usePagination, useRowSelection } from '@/types/table';
import { useDictStore } from '@/store'; import { useDictStore } from '@/store';
import { dateFormat, formatDuration } from '@/utils'; import { dateFormat, formatDuration } from '@/utils';
// import { interruptExecJob } from '@/api/exec/exec-job'; import { interruptExecJob } from '@/api/exec/exec-job-log';
import UserSelector from '@/components/user/user/selector/index.vue';
import ExecJobHostLogTable from './exec-job-host-log-table.vue'; import ExecJobHostLogTable from './exec-job-host-log-table.vue';
const emits = defineEmits(['viewCommand', 'viewParams', 'viewLog', 'openClear']); const emits = defineEmits(['viewCommand', 'viewParams', 'viewLog', 'openClear']);
@@ -230,7 +223,6 @@
const tableRenderData = ref<ExecLogQueryResponse[]>([]); const tableRenderData = ref<ExecLogQueryResponse[]>([]);
const formModel = reactive<ExecLogQueryRequest>({ const formModel = reactive<ExecLogQueryRequest>({
id: undefined, id: undefined,
userId: undefined,
description: undefined, description: undefined,
command: undefined, command: undefined,
status: undefined, status: undefined,
@@ -239,7 +231,7 @@
// 打开清理 // 打开清理
const openClear = () => { const openClear = () => {
emits('openClear', { ...formModel, id: undefined }); emits('openClear', { ...formModel, id: undefined, description: undefined });
}; };
// 删除选中行 // 删除选中行
@@ -281,9 +273,9 @@
try { try {
setLoading(true); setLoading(true);
// 调用中断接口 // 调用中断接口
// await interruptExecJob({ await interruptExecJob({
// logId: record.id logId: record.id
// }); });
Message.success('已中断'); Message.success('已中断');
record.status = execStatus.COMPLETED; record.status = execStatus.COMPLETED;
} catch (e) { } catch (e) {

View File

@@ -10,7 +10,8 @@
<exec-job-log-clear-modal ref="clearModal" <exec-job-log-clear-modal ref="clearModal"
@clear="clearCallback" /> @clear="clearCallback" />
<!-- 执行日志模态框 --> <!-- 执行日志模态框 -->
<exec-log-panel-modal ref="logModal" /> <exec-log-panel-modal ref="logModal"
type="JOB" />
<!-- json 模态框 --> <!-- json 模态框 -->
<json-editor-modal ref="jsonModal" <json-editor-modal ref="jsonModal"
:esc-to-close="true" /> :esc-to-close="true" />

View File

@@ -88,6 +88,7 @@
</script> </script>
<script lang="ts" setup> <script lang="ts" setup>
import type { DictKeyQueryResponse } from '@/api/system/dict-key';
import type { DictValueUpdateRequest } from '@/api/system/dict-value'; import type { DictValueUpdateRequest } from '@/api/system/dict-value';
import type { ExtraParamType } from '../../dict-key/types/const'; import type { ExtraParamType } from '../../dict-key/types/const';
import { ref } from 'vue'; import { ref } from 'vue';
@@ -97,7 +98,6 @@
import { createDictValue, updateDictValue } from '@/api/system/dict-value'; import { createDictValue, updateDictValue } from '@/api/system/dict-value';
import { Message } from '@arco-design/web-vue'; import { Message } from '@arco-design/web-vue';
import { ValueType, sortStep } from '../../dict-key/types/const'; import { ValueType, sortStep } from '../../dict-key/types/const';
import { DictKeyQueryResponse } from '@/api/system/dict-key';
import { useCacheStore } from '@/store'; import { useCacheStore } from '@/store';
import DictKeySelector from '@/components/system/dict-key/selector/index.vue'; import DictKeySelector from '@/components/system/dict-key/selector/index.vue';