Merge branch 'refs/heads/dev_1.0.0_beta2' into dev

This commit is contained in:
xlsea 2024-05-20 14:47:47 +08:00
commit 60d0c218d4
17 changed files with 432 additions and 201 deletions

View File

@ -112,5 +112,6 @@
"lint-staged": {
"*": "eslint --fix"
},
"website": "https://www.easyretry.com/pages/78ba75/"
"officialWebsite": "https://snailjob.opensnail.com",
"website": "https://snailjob.opensnail.com/pages/78ba75/"
}

View File

@ -0,0 +1,79 @@
<script setup lang="ts">
import { ref, watch } from 'vue';
import CronInput from '@sa/cron-input';
import { useAppStore } from '@/store/modules/app';
defineOptions({
name: 'JobTriggerInterval'
});
interface Props {
triggerType: Api.Common.TriggerType;
}
const model = defineModel<string>();
const props = defineProps<Props>();
const app = useAppStore();
/** 保存 `固定时间` 类型的 时间间隔 */
const interval = ref<number>(props.triggerType === 2 ? Number(model.value) : 60);
/** 保存 `CRON表达式` 类型的 表达式 */
const cron = ref<string>(props.triggerType === 3 ? model.value! : '* * * * * ?');
/** 监视 触发间隔 变化 */
watch(
interval,
val => {
if (props.triggerType === 2) {
model.value = `${val}`;
}
},
{ immediate: true }
);
/** 监视 cron 表达式变化 */
watch(
cron,
val => {
if (props.triggerType === 3) {
model.value = val;
}
},
{ immediate: true }
);
/** 根据不同 triggerType, 为model赋值 */
watch(
() => props.triggerType,
triggerType => {
if (triggerType === 2) {
model.value = `${interval.value}`;
} else if (triggerType === 3) {
model.value = cron.value;
} else {
model.value = '*';
}
},
{ immediate: true }
);
</script>
<template>
<div>
<NInputGroup v-if="triggerType === 2">
<NInputNumber v-model:value="interval" :placeholder="$t('page.jobTask.form.triggerInterval')" />
<NInputGroupLabel></NInputGroupLabel>
</NInputGroup>
<CronInput
v-else-if="triggerType === 3"
v-model="cron"
:placeholder="$t('page.jobTask.form.triggerInterval_CRON')"
:lang="app.locale"
/>
<NInput v-else-if="triggerType === 99" disabled />
</div>
</template>
<style scoped></style>

View File

@ -95,7 +95,7 @@ function timestampToDate(timestamp: string): string {
<pre
v-for="(message, index) in modelValue"
:key="index"
><NDivider v-if="index !== 0" /><span class="log-hljs-time">{{timestampToDate(message.time_stamp)}}</span><span :class="`log-hljs-level-${message.level}`">{{`\t${message.level}\t`}}</span><span class="log-hljs-thread">{{`[${message.thread}]\t`}}</span><span class="log-hljs-location">{{`${message.location}: \n`}}</span> -<span class="pl-6px">{{`${message.message}\n`}}</span><ThrowableComponent :throwable="message.throwable" /></pre>
><NDivider v-if="index !== 0" /><span class="log-hljs-time inline-block">{{timestampToDate(message.time_stamp)}}</span><span :class="`log-hljs-level-${message.level}`" class="ml-12px mr-12px inline-block">{{`${message.level}`}}</span><span class="log-hljs-thread mr-12px inline-block">{{ `[${message.host}:${message.port}]` }}</span><span class="log-hljs-thread mr-12px inline-block">{{`[${message.thread}]`}}</span><span class="log-hljs-location">{{`${message.location}: \n`}}</span> -<span class="pl-6px">{{`${message.message}`}}</span><ThrowableComponent :throwable="message.throwable" /></pre>
</code>
</div>
</div>
@ -107,11 +107,10 @@ function timestampToDate(timestamp: string): string {
<pre
v-for="(message, index) in modelValue"
:key="index"
><NDivider v-if="index !== 0" /><span class="log-hljs-time">{{timestampToDate(message.time_stamp)}}</span><span :class="`log-hljs-level-${message.level}`">{{`\t${message.level}\t`}}</span><span class="log-hljs-thread">{{`[${message.thread}]\t`}}</span><span class="log-hljs-location">{{`${message.location}: \n`}}</span> -<span class="pl-6px">{{`${message.message}\n`}}</span><ThrowableComponent :throwable="message.throwable" /></pre>
><NDivider v-if="index !== 0" /><span class="log-hljs-time">{{timestampToDate(message.time_stamp)}}</span><span :class="`log-hljs-level-${message.level}`">{{`\t${message.level}\t`}}</span><span class="log-hljs-thread">{{ `[${message.host}:${message.port}]\t` }}</span><span class="log-hljs-thread">{{`[${message.thread}]\t`}}</span><span class="log-hljs-location">{{`${message.location}: \n`}}</span> -<span class="pl-6px">{{`${message.message}\n`}}</span><ThrowableComponent :throwable="message.throwable" /></pre>
</code>
</div>
</div>
<NEmpty v-else class="h-full" />
</template>
<style scoped lang="scss">

View File

@ -7,9 +7,10 @@ defineOptions({
});
interface Props {
title?: string;
title: string;
minSize?: number;
}
const props = defineProps<Props>();
const props = withDefaults(defineProps<Props>(), { minSize: 360 });
interface Emits {
(e: 'update:modelValue', modelValue: boolean): void;
@ -25,8 +26,8 @@ const appStore = useAppStore();
const state = reactive({ width: 0 });
const isFullscreen = ref(false);
const drawerWidth = computed(() => {
const maxMinWidth = 360;
const maxMaxWidth = 600;
const maxMinWidth = props.minSize;
const maxMaxWidth = Math.max(props.minSize, 600);
if (appStore.isMobile) {
return state.width * 0.9 >= maxMinWidth ? `${maxMinWidth}px` : '90%';
}

View File

@ -0,0 +1,76 @@
<script setup lang="ts">
import { ref, watch } from 'vue';
import CronInput from '@sa/cron-input';
import { useAppStore } from '@/store/modules/app';
defineOptions({
name: 'SceneTriggerInterval'
});
interface Props {
backOff: Api.RetryScene.BackOff;
}
const model = defineModel<string>();
const props = defineProps<Props>();
const app = useAppStore();
/** 保存 `固定时间` 类型的 时间间隔 */
const interval = ref<number>(props.backOff === 2 || props.backOff === 4 ? Number(model.value) : 60);
/** 保存 `CRON表达式` 类型的 表达式 */
const cron = ref<string>(props.backOff === 3 ? model.value! : '* * * * * ?');
const delayLevelDesc = ref('10s,15s,30s,35s,40s,50s,1m,2m,4m,6m,8m,10m,20m,40m,1h,2h,3h,4h,5h,6h,7h,8h,9h,10h,11h,12h');
/** 监视 触发间隔 变化 */
watch(
interval,
val => {
if (props.backOff === 2 || props.backOff === 4) {
model.value = `${val}`;
}
},
{ immediate: true }
);
/** 监视 cron表达式 变化 */
watch(
cron,
val => {
if (props.backOff === 3) {
model.value = val;
}
},
{ immediate: true }
);
/** 根据不同 backOff 对model赋值 */
watch(
() => props.backOff,
backOff => {
if (backOff === 2 || backOff === 4) {
model.value = `${interval.value}`;
} else if (backOff === 3) {
model.value = cron.value;
} else {
model.value = '*';
}
},
{ immediate: true }
);
</script>
<template>
<CronInput v-if="backOff === 3" v-model="cron" :lang="app.locale" />
<NInputNumber
v-else-if="backOff === 2 || backOff === 4"
v-model:value="interval"
:placeholder="$t('page.retryScene.form.triggerInterval')"
clearable
/>
<NInput v-else v-model:value="delayLevelDesc" type="textarea" :autosize="{ minRows: 1, maxRows: 3 }" readonly />
</template>
<style scoped></style>

View File

@ -45,6 +45,10 @@ const headerMenus = computed(() => {
return [];
});
const href = (url: string) => {
window.open(url, '_blank');
};
</script>
<template>
@ -58,6 +62,27 @@ const headerMenus = computed(() => {
<div class="h-full flex-y-center justify-end">
<NamespaceSelect />
<GlobalSearch />
<ButtonIcon
v-if="!appStore.isMobile"
class="color-#c71d23"
tooltip-content="Gitee"
icon="simple-icons:gitee"
@click="href('https://gitee.com/aizuda/snail-job')"
/>
<ButtonIcon
v-if="!appStore.isMobile"
tooltip-content="Github"
class="color-#010409 dark:color-#e6edf3"
icon="simple-icons:github"
@click="href('https://github.com/aizuda/snail-job')"
/>
<ButtonIcon
v-if="!appStore.isMobile"
tooltip-content="Document"
class="color-#272636 dark:color-#f0f2f5"
icon="material-symbols:unknown-document-outline"
@click="href('https://snailjob.opensnail.com/')"
/>
<FullScreen v-if="!appStore.isMobile" :full="isFullscreen" @click="toggle" />
<LangSwitch :lang="appStore.locale" :lang-options="appStore.localeOptions" @change-lang="appStore.changeLocale" />
<ThemeSchemaSwitch

View File

@ -17,8 +17,8 @@ withDefaults(defineProps<Props>(), {
<template>
<RouterLink to="/" class="w-full flex-center nowrap-hidden">
<SystemLogo class="text-32px text-primary" />
<h2 v-show="showTitle" class="pl-8px text-16px text-primary font-bold transition duration-300 ease-in-out">
<SystemLogo class="text-36px text-primary" />
<h2 v-show="showTitle" class="pl-8px text-27px text-primary font-bold transition duration-300 ease-in-out">
{{ $t('system.title') }}
</h2>
</RouterLink>

View File

@ -946,7 +946,7 @@ const local: App.I18n.Schema = {
triggerType: 'Trigger type',
triggerInterval: 'Interval duration',
blockStrategy: 'Blocking strategy',
executorTimeout: 'Overtime time',
executorTimeout: 'Overtime time(s)',
maxRetryTimes: 'Maximum number of retries',
retryInterval: 'Retry interval',
taskType: 'Task type',

View File

@ -953,7 +953,7 @@ const local: App.I18n.Schema = {
triggerType: '触发类型',
triggerInterval: '间隔时长',
blockStrategy: '阻塞策略',
executorTimeout: '超时时间',
executorTimeout: '超时时间(秒)',
maxRetryTimes: '最大重试次数',
retryInterval: '重试间隔',
taskType: '任务类型',

View File

@ -812,7 +812,7 @@ declare namespace Api {
/** 最大重试次数 */
maxRetryCount: number;
/** 间隔时间 */
triggerInterval: number;
triggerInterval: string;
/** 调用链超时时间 */
deadlineRequest: number;
/** 超时时间 */
@ -1212,6 +1212,8 @@ declare namespace Api {
type JobMessage = {
level: JobLevel;
host: string;
port: string;
location: string;
message: string;
thread: string;

View File

@ -20,7 +20,7 @@ interface FormModel {
const model: FormModel = reactive({
userName: 'admin',
password: '654321'
password: 'admin'
});
type RuleKey = Extract<keyof FormModel, 'userName' | 'password'>;

View File

@ -48,7 +48,7 @@ const latestBuildTime = BUILD_TIME;
<NCard :title="$t('page.about.projectInfo.title')" :bordered="false" size="small" segmented class="card-wrapper">
<NDescriptions label-placement="left" bordered size="small" :column="column">
<NDescriptionsItem :label="$t('page.about.projectInfo.officialWebsite')">
<a class="text-primary" :href="pkg.website" target="_blank" rel="noopener noreferrer">
<a class="text-primary" :href="pkg.officialWebsite" target="_blank" rel="noopener noreferrer">
{{ $t('page.about.projectInfo.officialWebsite') }}
</a>
</NDescriptionsItem>

View File

@ -139,7 +139,7 @@ const createColumns = (): DataTableColumns<Api.Dashboard.Task> => [
title: $t('page.home.retryTab.task.total'),
key: 'total',
align: 'center',
render: row => <span class="retry-table-number">{row.run}</span>
render: row => <span class="retry-table-number">{row.total}</span>
}
];

View File

@ -1,6 +1,5 @@
<script setup lang="ts">
import { computed, reactive, watch } from 'vue';
import CronInput from '@sa/cron-input';
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import OperateDrawer from '@/components/common/operate-drawer.vue';
import { $t } from '@/locales';
@ -10,6 +9,7 @@ import RouteKey from '@/components/common/route-key.vue';
import ExecutorType from '@/components/common/executor-type.vue';
import TaskType from '@/components/common/task-type.vue';
import CodeMirror from '@/components/common/code-mirror.vue';
import JobTriggerInterval from '@/components/common/job-trigger-interval.vue';
defineOptions({
name: 'JobTaskOperateDrawer'
@ -271,7 +271,7 @@ watch(visible, () => {
</script>
<template>
<OperateDrawer v-model="visible" :title="title" @handle-submit="handleSubmit">
<OperateDrawer v-model="visible" :title="title" :min-size="480" @handle-submit="handleSubmit">
<NForm ref="formRef" :model="model" :rules="rules">
<NFormItem :label="$t('page.jobTask.jobName')" path="jobName">
<NInput
@ -281,27 +281,39 @@ watch(visible, () => {
:placeholder="$t('page.jobTask.form.jobName')"
/>
</NFormItem>
<NFormItem :label="$t('page.jobTask.groupName')" path="groupName">
<SelectGroup v-model:value="model.groupName" />
</NFormItem>
<NFormItem :label="$t('page.jobTask.jobStatus')" path="jobStatus">
<NRadioGroup v-model:value="model.jobStatus" name="jobStatus">
<NSpace>
<NRadio
v-for="item in enableStatusNumberOptions"
:key="item.value"
:value="item.value"
:label="$t(item.label)"
/>
</NSpace>
</NRadioGroup>
</NFormItem>
<NFormItem :label="$t('page.jobTask.executorType')" path="executorType">
<ExecutorType v-model:value="model.executorType" />
</NFormItem>
<NFormItem :label="$t('page.jobTask.executorInfo')" path="executorInfo">
<NInput v-model:value="model.executorInfo" :placeholder="$t('page.jobTask.form.executorInfo')" />
</NFormItem>
<NGrid cols="2 s:1 m:2" responsive="screen" x-gap="20">
<NGi>
<NFormItem :label="$t('page.jobTask.groupName')" path="groupName">
<SelectGroup v-model:value="model.groupName" />
</NFormItem>
</NGi>
<NGi>
<NFormItem :label="$t('page.jobTask.jobStatus')" path="jobStatus">
<NRadioGroup v-model:value="model.jobStatus" name="jobStatus">
<NSpace>
<NRadio
v-for="item in enableStatusNumberOptions"
:key="item.value"
:value="item.value"
:label="$t(item.label)"
/>
</NSpace>
</NRadioGroup>
</NFormItem>
</NGi>
</NGrid>
<NGrid cols="2 s:1 m:2" responsive="screen" x-gap="20">
<NGi>
<NFormItem :label="$t('page.jobTask.executorType')" path="executorType">
<ExecutorType v-model:value="model.executorType" />
</NFormItem>
</NGi>
<NGi>
<NFormItem :label="$t('page.jobTask.executorInfo')" path="executorInfo">
<NInput v-model:value="model.executorInfo" :placeholder="$t('page.jobTask.form.executorInfo')" />
</NFormItem>
</NGi>
</NGrid>
<NFormItem :label="$t('page.jobTask.taskType')" path="taskType">
<TaskType v-model:value="model.taskType" :placeholder="$t('page.jobTask.form.taskType')" />
</NFormItem>
@ -336,68 +348,84 @@ watch(visible, () => {
</NCard>
<CodeMirror v-else v-model="model.argsStr" lang="json" :placeholder="$t('page.jobTask.form.argsStr')" />
</NFormItem>
<NFormItem :label="$t('page.jobTask.routeKey')" path="routeKey">
<RouteKey v-model:value="model.routeKey" :task-type="model.taskType" />
</NFormItem>
<NFormItem :label="$t('page.jobTask.blockStrategy')" path="blockStrategy">
<BlockStrategy v-model:value="model.blockStrategy" />
</NFormItem>
<NFormItem :label="$t('page.jobTask.triggerType')" path="triggerType">
<TriggerType
v-model:value="model.triggerType"
:placeholder="$t('page.jobTask.form.triggerType')"
@update:value="model.triggerInterval = ''"
/>
</NFormItem>
<NFormItem :label="$t('page.jobTask.triggerInterval')" path="triggerInterval">
<NInput
v-if="model.triggerType === 2"
v-model:value="model.triggerInterval"
:placeholder="$t('page.jobTask.form.triggerInterval')"
/>
<CronInput
v-else-if="model.triggerType === 3"
v-model:value="model.triggerInterval"
:placeholder="$t('page.jobTask.form.triggerInterval_CRON')"
/>
<NInput v-else-if="model.triggerType === 99" v-model:value="model.triggerInterval" disabled />
</NFormItem>
<NFormItem :label="$t('page.jobTask.executorTimeout')" path="executorTimeout">
<NInputNumber
v-model:value="model.executorTimeout"
:min="1"
:max="60"
:placeholder="$t('page.jobTask.form.executorTimeout')"
clearable
/>
</NFormItem>
<NFormItem :label="$t('page.jobTask.maxRetryTimes')" path="maxRetryTimes">
<NInputNumber
v-model:value="model.maxRetryTimes"
:min="1"
:max="60"
:placeholder="$t('page.jobTask.form.maxRetryTimes')"
clearable
/>
</NFormItem>
<NFormItem :label="$t('page.jobTask.retryInterval')" path="retryInterval">
<NInputNumber
v-model:value="model.retryInterval"
:min="1"
:max="60"
:placeholder="$t('page.jobTask.form.retryInterval')"
clearable
/>
</NFormItem>
<NFormItem :label="$t('page.jobTask.parallelNum')" path="parallelNum">
<NInputNumber
v-model:value="model.parallelNum"
:min="1"
:max="60"
:placeholder="$t('page.jobTask.form.parallelNum')"
clearable
/>
</NFormItem>
<NGrid cols="2 s:1 m:2" responsive="screen" x-gap="20">
<NGi>
<NFormItem :label="$t('page.jobTask.routeKey')" path="routeKey">
<RouteKey v-model:value="model.routeKey" :task-type="model.taskType" />
</NFormItem>
</NGi>
<NGi>
<NFormItem :label="$t('page.jobTask.blockStrategy')" path="blockStrategy">
<BlockStrategy v-model:value="model.blockStrategy" />
</NFormItem>
</NGi>
</NGrid>
<NGrid cols="2 s:1 m:2" responsive="screen" x-gap="20">
<NGi>
<NFormItem :label="$t('page.jobTask.triggerType')" path="triggerType">
<TriggerType
v-model:value="model.triggerType"
:placeholder="$t('page.jobTask.form.triggerType')"
@update:value="model.triggerInterval = ''"
/>
</NFormItem>
</NGi>
<NGi>
<NFormItem :label="$t('page.jobTask.triggerInterval')" path="triggerInterval">
<JobTriggerInterval v-model="model.triggerInterval" :trigger-type="model.triggerType" />
</NFormItem>
</NGi>
</NGrid>
<NGrid cols="2 s:1 m:2" responsive="screen" x-gap="20">
<NGi>
<NFormItem :label="$t('page.jobTask.executorTimeout')" path="executorTimeout">
<NInputGroup>
<NInputNumber
v-model:value="model.executorTimeout"
:min="1"
:max="99999999"
:placeholder="$t('page.jobTask.form.executorTimeout')"
clearable
/>
</NInputGroup>
</NFormItem>
</NGi>
<NGi>
<NFormItem :label="$t('page.jobTask.maxRetryTimes')" path="maxRetryTimes">
<NInputNumber
v-model:value="model.maxRetryTimes"
:min="1"
:max="999"
:placeholder="$t('page.jobTask.form.maxRetryTimes')"
clearable
/>
</NFormItem>
</NGi>
</NGrid>
<NGrid cols="2 s:1 m:2" responsive="screen" x-gap="20">
<NGi>
<NFormItem :label="$t('page.jobTask.retryInterval')" path="retryInterval">
<NInputNumber
v-model:value="model.retryInterval"
:min="1"
:max="99999999"
:placeholder="$t('page.jobTask.form.retryInterval')"
clearable
/>
</NFormItem>
</NGi>
<NGi>
<NFormItem :label="$t('page.jobTask.parallelNum')" path="parallelNum">
<NInputNumber
v-model:value="model.parallelNum"
:min="1"
:max="999"
:placeholder="$t('page.jobTask.form.parallelNum')"
clearable
/>
</NFormItem>
</NGi>
</NGrid>
<NFormItem :label="$t('page.jobTask.description')" path="description">
<NInput v-model:value="model.description" type="textarea" :placeholder="$t('page.jobTask.form.description')" />
</NFormItem>

View File

@ -102,7 +102,8 @@ onBeforeUnmount(() => {
</NDescriptions>
</NTabPane>
<NTabPane :name="1" :tab="$t('page.log.title')" display-directive="if">
<LogDrawer v-model="logList" :drawer="false" />
<LogDrawer v-if="logList.length > 0" v-model="logList" :drawer="false" />
<NEmpty v-else class="h-full" />
</NTabPane>
</NTabs>
</DetailDrawer>

View File

@ -1,6 +1,5 @@
<script setup lang="ts">
import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue';
import CronInput from '@sa/cron-input';
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import OperateDrawer from '@/components/common/operate-drawer.vue';
import RouteKey from '@/components/common/route-key.vue';
@ -8,7 +7,6 @@ import { $t } from '@/locales';
import { fetchAddRetryScene, fetchEditRetryScene, fetchGetAllGroupNameList } from '@/service/api';
import { DelayLevel, backOffRecordOptions, enableStatusNumberOptions } from '@/constants/business';
import { translateOptions, translateOptions2 } from '@/utils/common';
import { useAppStore } from '@/store/modules/app';
defineOptions({
name: 'SceneOperateDrawer'
@ -21,7 +19,6 @@ interface Props {
rowData?: Api.RetryScene.Scene | null;
}
const app = useAppStore();
const groupNameList = ref<string[]>([]);
const delayLevelDesc = ref<string>('10s');
@ -72,7 +69,7 @@ function createDefaultModel(): Model {
sceneStatus: 1,
backOff: 2,
maxRetryCount: 1,
triggerInterval: 60,
triggerInterval: '60',
deadlineRequest: 60000,
executorTimeout: 60,
description: '',
@ -155,7 +152,7 @@ async function handleSubmit() {
routeKey,
description
} = model;
fetchAddRetryScene({
const { error } = await fetchAddRetryScene({
groupName,
sceneName,
sceneStatus,
@ -167,6 +164,8 @@ async function handleSubmit() {
routeKey,
description
});
if (error) return;
window.$message?.success($t('common.addSuccess'));
}
if (props.operateType === 'edit') {
@ -183,7 +182,7 @@ async function handleSubmit() {
routeKey,
description
} = model;
fetchEditRetryScene({
const { error } = await fetchEditRetryScene({
id,
groupName,
sceneName,
@ -196,8 +195,9 @@ async function handleSubmit() {
routeKey,
description
});
if (error) return;
window.$message?.success($t('common.updateSuccess'));
}
window.$message?.success($t('common.updateSuccess'));
closeDrawer();
emit('submitted');
}
@ -229,7 +229,7 @@ watch(
</script>
<template>
<OperateDrawer v-model="visible" :title="title" @handle-submit="handleSubmit">
<OperateDrawer v-model="visible" :title="title" :min-size="480" @handle-submit="handleSubmit">
<NForm ref="formRef" :model="model" :rules="rules">
<NFormItem :label="$t('page.retryScene.sceneName')" path="sceneName">
<NInput
@ -240,97 +240,115 @@ watch(
:placeholder="$t('page.retryScene.form.sceneName')"
/>
</NFormItem>
<NFormItem :label="$t('page.retryScene.groupName')" path="groupName">
<NSelect
v-model:value="model.groupName"
:disabled="props.operateType === 'edit'"
:placeholder="$t('page.retryScene.form.groupName')"
:options="translateOptions2(groupNameList)"
clearable
/>
</NFormItem>
<NFormItem :label="$t('common.routeKey.routeLabel')" path="routeKey">
<RouteKey v-model:value="model.routeKey" />
</NFormItem>
<NFormItem :label="$t('page.retryScene.maxRetryCount')" path="maxRetryCount">
<NInputNumber
v-model:value="model.maxRetryCount"
:min="1"
:max="model.backOff === 1 ? 26 : 9999999"
:placeholder="$t('page.retryScene.form.maxRetryCount')"
clearable
/>
</NFormItem>
<NFormItem :label="$t('page.retryScene.executorTimeout')" path="executorTimeout">
<NInputNumber
v-model:value="model.executorTimeout"
:min="1"
:max="60"
:placeholder="$t('page.retryScene.form.executorTimeout')"
clearable
/>
</NFormItem>
<NFormItem :label="$t('page.retryScene.deadlineRequest')" path="deadlineRequest">
<NInputNumber
v-model:value="model.deadlineRequest"
:min="100"
:max="60000"
:placeholder="$t('page.retryScene.form.deadlineRequest')"
clearable
/>
</NFormItem>
<NFormItem :label="$t('page.retryScene.backOff')" path="backOff">
<NSelect
v-model:value="model.backOff"
:placeholder="$t('page.retryScene.form.backOff')"
:options="translateOptions(backOffRecordOptions)"
clearable
/>
</NFormItem>
<NFormItem path="triggerInterval">
<CronInput v-if="model.backOff === 3" v-model:value="model.triggerInterval as any" :lang="app.locale" />
<NInputNumber
v-else-if="model.backOff === 2 || model.backOff === 4"
v-model:value="model.triggerInterval as any"
:placeholder="$t('page.retryScene.form.triggerInterval')"
clearable
/>
<NInput v-else v-model:value="delayLevelDesc" type="textarea" :autosize="{ minRows: 1, maxRows: 3 }" readonly />
<template #label>
<div class="flex-center">
{{ $t('page.retryScene.triggerInterval') }}
<NTooltip v-if="model.backOff === 1" trigger="hover">
<template #trigger>
<NButton text class="ml-6px">
<SvgIcon icon="ant-design:info-circle-outlined" class="mb-1px text-16px" />
</NButton>
</template>
延迟等级是参考RocketMQ的messageDelayLevel设计实现具体延迟时间如下:
10s,15s,30s,35s,40s,50s,1m,2m,4m,6m,8m,10m,20m,40m,1h,2h,3h,4h,5h,6h,7h,8h,9h,10h,11h,12h
<br />
<NText strong>执行逻辑:</NText>
<NUl align-text>
<NLi>第一次执行间隔10s</NLi>
<NLi>第二次执行间隔15s</NLi>
<NLi>l第二次执行间隔30s</NLi>
<NLi>........... 依次类推</NLi>
</NUl>
</NTooltip>
</div>
</template>
</NFormItem>
<NFormItem :label="$t('page.retryScene.sceneStatus')" path="sceneStatus">
<NRadioGroup v-model:value="model.sceneStatus" name="sceneStatus">
<NSpace>
<NRadio
v-for="item in enableStatusNumberOptions"
:key="item.value"
:value="item.value"
:label="$t(item.label)"
<NGrid cols="2 s:1 m:2" responsive="screen" x-gap="20">
<NGi>
<NFormItem :label="$t('page.retryScene.groupName')" path="groupName">
<NSelect
v-model:value="model.groupName"
:disabled="props.operateType === 'edit'"
:placeholder="$t('page.retryScene.form.groupName')"
:options="translateOptions2(groupNameList)"
clearable
/>
</NSpace>
</NRadioGroup>
</NFormItem>
</NFormItem>
</NGi>
<NGi>
<NFormItem :label="$t('page.retryScene.sceneStatus')" path="sceneStatus">
<NRadioGroup v-model:value="model.sceneStatus" name="sceneStatus">
<NSpace>
<NRadio
v-for="item in enableStatusNumberOptions"
:key="item.value"
:value="item.value"
:label="$t(item.label)"
/>
</NSpace>
</NRadioGroup>
</NFormItem>
</NGi>
</NGrid>
<NGrid cols="2 s:1 m:2" responsive="screen" x-gap="20">
<NGi>
<NFormItem :label="$t('common.routeKey.routeLabel')" path="routeKey">
<RouteKey v-model:value="model.routeKey" />
</NFormItem>
</NGi>
<NGi>
<NFormItem :label="$t('page.retryScene.maxRetryCount')" path="maxRetryCount">
<NInputNumber
v-model:value="model.maxRetryCount"
:min="1"
:max="model.backOff === 1 ? 26 : 9999999"
:placeholder="$t('page.retryScene.form.maxRetryCount')"
clearable
/>
</NFormItem>
</NGi>
</NGrid>
<NGrid cols="2 s:1 m:2" responsive="screen" x-gap="20">
<NGi>
<NFormItem :label="$t('page.retryScene.backOff')" path="backOff">
<NSelect
v-model:value="model.backOff"
:placeholder="$t('page.retryScene.form.backOff')"
:options="translateOptions(backOffRecordOptions)"
clearable
/>
</NFormItem>
</NGi>
<NGi>
<NFormItem path="triggerInterval">
<SceneTriggerInterval v-model="model.triggerInterval" :back-off="model.backOff" />
<template #label>
<div class="flex-center">
{{ $t('page.retryScene.triggerInterval') }}
<NTooltip v-if="model.backOff === 1" trigger="hover">
<template #trigger>
<NButton text class="ml-6px">
<SvgIcon icon="ant-design:info-circle-outlined" class="mb-1px text-16px" />
</NButton>
</template>
延迟等级是参考RocketMQ的messageDelayLevel设计实现具体延迟时间如下:
10s,15s,30s,35s,40s,50s,1m,2m,4m,6m,8m,10m,20m,40m,1h,2h,3h,4h,5h,6h,7h,8h,9h,10h,11h,12h
<br />
<NText strong>执行逻辑:</NText>
<NUl align-text>
<NLi>第一次执行间隔10s</NLi>
<NLi>第二次执行间隔15s</NLi>
<NLi>l第二次执行间隔30s</NLi>
<NLi>........... 依次类推</NLi>
</NUl>
</NTooltip>
</div>
</template>
</NFormItem>
</NGi>
</NGrid>
<NGrid cols="2 s:1 m:2" responsive="screen" x-gap="20">
<NGi>
<NFormItem :label="$t('page.retryScene.executorTimeout')" path="executorTimeout">
<NInputNumber
v-model:value="model.executorTimeout"
:min="1"
:max="60"
:placeholder="$t('page.retryScene.form.executorTimeout')"
clearable
/>
</NFormItem>
</NGi>
<NGi>
<NFormItem :label="$t('page.retryScene.deadlineRequest')" path="deadlineRequest">
<NInputNumber
v-model:value="model.deadlineRequest"
:min="100"
:max="60000"
:placeholder="$t('page.retryScene.form.deadlineRequest')"
clearable
/>
</NFormItem>
</NGi>
</NGrid>
<NFormItem :label="$t('page.retryScene.description')" path="description">
<NInput
v-model:value="model.description"

View File

@ -109,7 +109,8 @@ onBeforeUnmount(() => {
</NDescriptions>
</NTabPane>
<NTabPane :name="1" :tab="$t('page.log.title')" display-directive="if">
<LogDrawer v-model="logList" :drawer="false" />
<LogDrawer v-if="logList.length > 0" v-model="logList" :drawer="false" />
<NEmpty v-else class="h-full" />
</NTabPane>
</NTabs>
</OperateDrawer>