cron 生成组件.

This commit is contained in:
lijiahang
2024-05-21 13:15:25 +08:00
parent 4f0f320fcd
commit cce511c4b4
45 changed files with 105 additions and 57 deletions

View File

@@ -16,9 +16,9 @@
### v2.0.1 ### v2.0.1
`2024-05-2` `release` `2024-05-21` `release`
* 🩰 修改 logo * ⭐ 添加 cron 组件
* 🐞 修复 批量执行后日志偶尔不展示的问题 * 🐞 修复 批量执行后日志偶尔不展示的问题
* 🐞 修复 批量上传进度条显示异常的问题 * 🐞 修复 批量上传进度条显示异常的问题

View File

@@ -2,12 +2,10 @@
* 终端背景图片 * 终端背景图片
* 资产授权 UI 改版 * 资产授权 UI 改版
* RDP 远程桌面
* 接入 config 后端动态配置 * 接入 config 后端动态配置
* 文档中巡检模板 * 文档中巡检模板
* 导入快捷命令 * 导入快捷命令
* 导入命令模板 * 导入命令模板
* 使用 vite press 开发文档
## 已知问题 ## 已知问题

View File

@@ -8,7 +8,7 @@
:cancel-button-props="{ disabled: loading }" :cancel-button-props="{ disabled: loading }"
:on-before-ok="handlerOk" :on-before-ok="handlerOk"
@cancel="handleClose"> @cancel="handleClose">
<a-spin class="full modal-form-small" :loading="loading"> <a-spin class="full drawer-form-small" :loading="loading">
<a-form :model="formModel" <a-form :model="formModel"
ref="formRef" ref="formRef"
label-align="right" label-align="right"

View File

@@ -94,8 +94,10 @@ public class WebSocketSyncSession implements WebSocketSession {
} }
@Override @Override
public synchronized void sendMessage(WebSocketMessage<?> message) throws IOException { public void sendMessage(WebSocketMessage<?> message) throws IOException {
this.delegate.sendMessage(message); synchronized (this.delegate) {
this.delegate.sendMessage(message);
}
} }
@Override @Override

View File

@@ -70,8 +70,15 @@ public class WebSockets {
return; return;
} }
try { try {
// 发送消息 if (session instanceof WebSocketSyncSession) {
session.sendMessage(new TextMessage(message)); // 发送消息
session.sendMessage(new TextMessage(message));
} else {
synchronized (session) {
// 发送消息
session.sendMessage(new TextMessage(message));
}
}
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
// 并发异常 // 并发异常
log.error("发送消息失败, 准备进行重试 {}", Exceptions.getDigest(e)); log.error("发送消息失败, 准备进行重试 {}", Exceptions.getDigest(e));

View File

@@ -5,7 +5,6 @@ import com.orion.ext.tail.delay.DelayTrackerListener;
import com.orion.ext.tail.mode.FileNotFoundMode; import com.orion.ext.tail.mode.FileNotFoundMode;
import com.orion.ext.tail.mode.FileOffsetMode; import com.orion.ext.tail.mode.FileOffsetMode;
import com.orion.spring.SpringHolder; import com.orion.spring.SpringHolder;
import com.orion.visor.framework.common.constant.Const;
import com.orion.visor.framework.websocket.core.utils.WebSockets; import com.orion.visor.framework.websocket.core.utils.WebSockets;
import com.orion.visor.module.asset.define.config.AppTrackerConfig; import com.orion.visor.module.asset.define.config.AppTrackerConfig;
import com.orion.visor.module.asset.entity.dto.ExecHostLogTailDTO; import com.orion.visor.module.asset.entity.dto.ExecHostLogTailDTO;
@@ -84,16 +83,9 @@ public class ExecLogTracker implements IExecLogTracker {
String message = config.getId() + LogConst.SEPARATOR + new String(bytes, 0, len); String message = config.getId() + LogConst.SEPARATOR + new String(bytes, 0, len);
try { try {
WebSockets.sendText(session, message); WebSockets.sendText(session, message);
return;
} catch (Exception e) { } catch (Exception e) {
log.error("ExecLogTracker.send error", e); log.error("ExecLogTracker.send error", e);
} }
// 重试
try {
WebSockets.retrySendText(session, message, Const.MS_100);
} catch (Exception e) {
log.error("ExecLogTracker.resend error fk", e);
}
} }
@Override @Override

View File

@@ -66,6 +66,11 @@
} }
} }
// -- drawer
.drawer-form-small{
padding: 20px 20px 2px 20px;
}
// -- modal // -- modal
.modal-form-small { .modal-form-small {
.arco-modal-header { .arco-modal-header {

View File

@@ -99,7 +99,7 @@
:placeholder="placeholder" :placeholder="placeholder"
@change="onInputCronChange"> @change="onInputCronChange">
<template #prepend> <template #prepend>
<span class="allow-click">Expression</span> <span class="allow-click">表达式</span>
</template> </template>
<template #append> <template #append>
<span class="allow-click span-blue" <span class="allow-click span-blue"
@@ -124,7 +124,7 @@
<script lang="ts"> <script lang="ts">
export default { export default {
name: 'cronInput' name: 'cronGeneratorInput'
}; };
</script> </script>

View File

@@ -3,7 +3,7 @@
modal-class="modal-form-small" modal-class="modal-form-small"
title-align="start" title-align="start"
title="cron 生成器" title="cron 生成器"
:top="16" :top="32"
:width="780" :width="780"
:align-center="false" :align-center="false"
:draggable="true" :draggable="true"
@@ -11,7 +11,7 @@
:unmount-on-close="true" :unmount-on-close="true"
:body-style="{ padding: '4px 16px 8px 16px' }"> :body-style="{ padding: '4px 16px 8px 16px' }">
<!-- cron 输入框 --> <!-- cron 输入框 -->
<cron-input v-model="cronExpression" /> <cron-generator-input v-model="cronExpression" />
<!-- 页脚--> <!-- 页脚-->
<template #footer> <template #footer>
<a-button size="small" @click="handlerClose">关闭</a-button> <a-button size="small" @click="handlerClose">关闭</a-button>
@@ -26,14 +26,14 @@
<script lang="ts"> <script lang="ts">
export default { export default {
name: 'cronModal' name: 'cronGeneratorModal'
}; };
</script> </script>
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from 'vue'; import { ref } from 'vue';
import useVisible from '@/hooks/visible'; import useVisible from '@/hooks/visible';
import CronInput from '@/components/data/cron/input/index.vue'; import CronGeneratorInput from '../generator-input/index.vue';
const { visible, setVisible } = useVisible(); const { visible, setVisible } = useVisible();

View File

@@ -32,7 +32,7 @@
<script lang="ts"> <script lang="ts">
export default { export default {
name: 'nextCronModal' name: 'cronNextModal'
}; };
</script> </script>

View File

@@ -1,6 +1,6 @@
<template> <template>
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form-large" modal-class="modal-form-large"
title-align="start" title-align="start"
title="重置密码" title="重置密码"
:top="120" :top="120"

View File

@@ -1,6 +1,6 @@
<template> <template>
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form-large" modal-class="modal-form-large"
title-align="start" title-align="start"
title="清空主机连接日志" title="清空主机连接日志"
:align-center="false" :align-center="false"

View File

@@ -1,6 +1,6 @@
<template> <template>
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form-large" modal-class="modal-form-large"
title-align="start" title-align="start"
:title="title" :title="title"
:top="80" :top="80"
@@ -52,7 +52,8 @@
<!-- 主机密钥 --> <!-- 主机密钥 -->
<a-form-item v-if="formModel.type === IdentityType.KEY" <a-form-item v-if="formModel.type === IdentityType.KEY"
field="keyId" field="keyId"
label="主机密钥"> label="主机密钥"
:hide-asterisk="true">
<host-key-selector v-model="formModel.keyId" /> <host-key-selector v-model="formModel.keyId" />
</a-form-item> </a-form-item>
</a-form> </a-form>

View File

@@ -8,7 +8,7 @@
:cancel-button-props="{ disabled: loading }" :cancel-button-props="{ disabled: loading }"
:on-before-ok="handlerOk" :on-before-ok="handlerOk"
@cancel="handleClose"> @cancel="handleClose">
<a-spin class="full modal-form-small" :loading="loading"> <a-spin class="full drawer-form-small" :loading="loading">
<a-alert class="keygen-alert"> <a-alert class="keygen-alert">
请使用 ssh-keygen -m PEM -t rsa 生成密钥 请使用 ssh-keygen -m PEM -t rsa 生成密钥
</a-alert> </a-alert>

View File

@@ -1,6 +1,6 @@
<template> <template>
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form-large" modal-class="modal-form-large"
title-align="start" title-align="start"
:title="title" :title="title"
:top="80" :top="80"

View File

@@ -1,6 +1,6 @@
<template> <template>
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form-large" modal-class="modal-form-large"
title-align="start" title-align="start"
title="清空批量执行日志" title="清空批量执行日志"
:align-center="false" :align-center="false"

View File

@@ -9,7 +9,7 @@
:cancel-button-props="{ disabled: loading }" :cancel-button-props="{ disabled: loading }"
:on-before-ok="handlerOk" :on-before-ok="handlerOk"
@cancel="handleClose"> @cancel="handleClose">
<a-spin class="full modal-form-small" :loading="loading"> <a-spin class="full drawer-form-small" :loading="loading">
<!-- 命令表单 --> <!-- 命令表单 -->
<a-form :model="formModel" <a-form :model="formModel"
ref="formRef" ref="formRef"

View File

@@ -9,7 +9,7 @@
:cancel-button-props="{ disabled: loading }" :cancel-button-props="{ disabled: loading }"
:on-before-ok="handlerOk" :on-before-ok="handlerOk"
@cancel="handleClose"> @cancel="handleClose">
<a-spin class="full modal-form-small" :loading="loading"> <a-spin class="full drawer-form-small" :loading="loading">
<a-form :model="formModel" <a-form :model="formModel"
ref="formRef" ref="formRef"
label-align="right" label-align="right"

View File

@@ -1,6 +1,6 @@
<template> <template>
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form-large" modal-class="modal-form-large"
title-align="start" title-align="start"
title="清理上传任务" title="清理上传任务"
:top="80" :top="80"

View File

@@ -1,6 +1,6 @@
<template> <template>
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form-large" modal-class="modal-form-large"
title-align="start" title-align="start"
title="修改权限" title="修改权限"
:align-center="false" :align-center="false"

View File

@@ -1,6 +1,6 @@
<template> <template>
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form-large" modal-class="modal-form-large"
title-align="start" title-align="start"
:title="touch ? '创建文件' : '创建文件夹'" :title="touch ? '创建文件' : '创建文件夹'"
:align-center="false" :align-center="false"

View File

@@ -1,6 +1,6 @@
<template> <template>
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form-large" modal-class="modal-form-large"
title-align="start" title-align="start"
title="移动文件" title="移动文件"
:align-center="false" :align-center="false"

View File

@@ -165,11 +165,11 @@
} }
&-left { &-left {
border-right: 1px solid var(--color-bg-content); border-right: 1px var(--color-bg-content) solid;
} }
&-right { &-right {
border-left: 1px solid var(--color-bg-content); border-left: 1px var(--color-bg-content) solid;
} }
&-content { &-content {

View File

@@ -1,6 +1,6 @@
<template> <template>
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form-large" modal-class="modal-form-large"
title-align="start" title-align="start"
title="清空计划任务日志" title="清空计划任务日志"
:align-center="false" :align-center="false"

View File

@@ -9,7 +9,7 @@
:cancel-button-props="{ disabled: loading }" :cancel-button-props="{ disabled: loading }"
:on-before-ok="handlerOk" :on-before-ok="handlerOk"
@cancel="handleClose"> @cancel="handleClose">
<a-spin class="full modal-form-small" :loading="loading"> <a-spin class="full drawer-form-small" :loading="loading">
<a-form :model="formModel" <a-form :model="formModel"
ref="formRef" ref="formRef"
label-align="right" label-align="right"
@@ -51,7 +51,12 @@
placeholder="请输入 cron 表达式" placeholder="请输入 cron 表达式"
allow-clear> allow-clear>
<template #append> <template #append>
<span class="span-blue pointer usn" <span class="span-blue usn cron-action-item"
title="生成 cron 表达式"
@click="emits('genCron', formModel.expression)">
生成
</span>
<span class="span-blue usn cron-action-item"
title="获取 cron 下次执行时间" title="获取 cron 下次执行时间"
@click="emits('testCron', formModel.expression)"> @click="emits('testCron', formModel.expression)">
测试 测试
@@ -142,7 +147,7 @@
import { useDictStore } from '@/store'; import { useDictStore } from '@/store';
import ExecEditor from '@/components/view/exec-editor/index.vue'; import ExecEditor from '@/components/view/exec-editor/index.vue';
const emits = defineEmits(['added', 'updated', 'openHost', 'openTemplate', 'testCron']); const emits = defineEmits(['added', 'updated', 'openHost', 'openTemplate', 'testCron', 'genCron']);
const { visible, setVisible } = useVisible(); const { visible, setVisible } = useVisible();
const { loading, setLoading } = useLoading(); const { loading, setLoading } = useLoading();
@@ -205,6 +210,11 @@
}; };
}; };
// 设置表达式
const setExpression = (expression: string) => {
formModel.value.expression = expression;
};
// 设置选中主机 // 设置选中主机
const setSelectedHost = (hosts: Array<number>) => { const setSelectedHost = (hosts: Array<number>) => {
formModel.value.hostIdList = hosts; formModel.value.hostIdList = hosts;
@@ -231,7 +241,7 @@
} }
}; };
defineExpose({ openAdd, openUpdate, setSelectedHost, setWithTemplate }); defineExpose({ openAdd, openUpdate, setSelectedHost, setWithTemplate, setExpression });
// 打开选择主机 // 打开选择主机
const openSelectHost = () => { const openSelectHost = () => {
@@ -320,4 +330,26 @@
height: calc(100vh - 264px); height: calc(100vh - 264px);
} }
:deep(.arco-input-append) {
padding: 0 !important;
}
.cron-action-item {
width: 100%;
height: 100%;
padding: 0 12px;
display: flex;
cursor: pointer;
align-items: center;
transition: background-color .2s;
&:hover {
background: var(--color-fill-3);
}
&:first-child {
border-right: 1px var(--color-neutral-3) solid;
}
}
</style> </style>

View File

@@ -12,11 +12,15 @@
@updated="modalUpdateCallback" @updated="modalUpdateCallback"
@open-host="(e) => hostModal.open(e)" @open-host="(e) => hostModal.open(e)"
@open-template="() => templateModal.open()" @open-template="() => templateModal.open()"
@test-cron="openNextCron" /> @test-cron="openNextCron"
@gen-cron="openGeneratorCron" />
<!-- 任务详情模态框 --> <!-- 任务详情模态框 -->
<exec-job-detail-drawer ref="detail" /> <exec-job-detail-drawer ref="detail" />
<!-- cron 执行时间模态框 --> <!-- cron 执行时间模态框 -->
<next-cron-modal ref="nextCron" /> <cron-next-modal ref="nextCron" />
<!-- cron 生成模态框 -->
<cron-generator-modal ref="genModal"
@ok="(e) => drawer.setExpression(e)" />
<!-- 执行模板模态框 --> <!-- 执行模板模态框 -->
<exec-template-modal ref="templateModal" <exec-template-modal ref="templateModal"
@selected="(e) => drawer.setWithTemplate(e)" /> @selected="(e) => drawer.setWithTemplate(e)" />
@@ -40,14 +44,16 @@
import ExecJobFormDrawer from './components/exec-job-form-drawer.vue'; import ExecJobFormDrawer from './components/exec-job-form-drawer.vue';
import ExecJobDetailDrawer from './components/exec-job-detail-drawer.vue'; import ExecJobDetailDrawer from './components/exec-job-detail-drawer.vue';
import AuthorizedHostModal from '@/components/asset/host/authorized-host-modal/index.vue'; import AuthorizedHostModal from '@/components/asset/host/authorized-host-modal/index.vue';
import NextCronModal from '@/components/meta/expression/next-cron-modal/index.vue';
import ExecTemplateModal from '@/components/exec/template/modal/index.vue'; import ExecTemplateModal from '@/components/exec/template/modal/index.vue';
import CronNextModal from '@/components/meta/cron/next-modal/index.vue';
import CronGeneratorModal from '@/components/meta/cron/generator-model/index.vue';
const render = ref(false); const render = ref(false);
const table = ref(); const table = ref();
const drawer = ref(); const drawer = ref();
const detail = ref(); const detail = ref();
const nextCron = ref(); const nextCron = ref();
const genModal = ref();
const templateModal = ref(); const templateModal = ref();
const hostModal = ref(); const hostModal = ref();
@@ -66,6 +72,11 @@
nextCron.value.open({ expression: cron, times: CronNextTimes }); nextCron.value.open({ expression: cron, times: CronNextTimes });
}; };
// 打开生成表达式
const openGeneratorCron = (cron: string) => {
genModal.value.open(cron);
};
onBeforeMount(async () => { onBeforeMount(async () => {
const dictStore = useDictStore(); const dictStore = useDictStore();
await dictStore.loadKeys(dictKeys); await dictStore.loadKeys(dictKeys);

View File

@@ -1,6 +1,6 @@
<template> <template>
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form-large" modal-class="modal-form-large"
title-align="start" title-align="start"
:title="title" :title="title"
:top="80" :top="80"

View File

@@ -1,6 +1,6 @@
<template> <template>
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form-large" modal-class="modal-form-large"
title-align="start" title-align="start"
:title="title" :title="title"
:top="80" :top="80"

View File

@@ -1,6 +1,6 @@
<template> <template>
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form-large" modal-class="modal-form-large"
title-align="start" title-align="start"
:title="title" :title="title"
:top="30" :top="30"

View File

@@ -1,6 +1,6 @@
<template> <template>
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form-large" modal-class="modal-form-large"
title-align="start" title-align="start"
title="清空操作日志" title="清空操作日志"
:align-center="false" :align-center="false"

View File

@@ -1,6 +1,6 @@
<template> <template>
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form-large" modal-class="modal-form-large"
title-align="start" title-align="start"
:title="title" :title="title"
:top="80" :top="80"

View File

@@ -1,6 +1,6 @@
<template> <template>
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form-small" modal-class="modal-form-large"
title-align="start" title-align="start"
title="分配菜单" title="分配菜单"
width="80%" width="80%"
@@ -15,7 +15,7 @@
:on-before-ok="handlerOk" :on-before-ok="handlerOk"
@close="handleClose"> @close="handleClose">
<div class="role-menu-wrapper"> <div class="role-menu-wrapper">
<a-spin :loading="loading"> <a-spin class="full" :loading="loading">
<a-alert class="usn mb8"> <a-alert class="usn mb8">
<span>{{ roleRecord.name }} {{ roleRecord.code }}</span> <span>{{ roleRecord.name }} {{ roleRecord.code }}</span>
<span class="mx8">-</span> <span class="mx8">-</span>

View File

@@ -1,6 +1,6 @@
<template> <template>
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form-large" modal-class="modal-form-large"
title-align="start" title-align="start"
:title="title" :title="title"
:top="80" :top="80"

View File

@@ -1,6 +1,6 @@
<template> <template>
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form-large" modal-class="modal-form-large"
title-align="start" title-align="start"
title="分配角色" title="分配角色"
:top="120" :top="120"

View File

@@ -1,6 +1,6 @@
<template> <template>
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form-large" modal-class="modal-form-large"
title-align="start" title-align="start"
title="重置密码" title="重置密码"
:top="120" :top="120"