Merge branch 'refs/heads/dev_1.0.0_beta2' into dev
This commit is contained in:
commit
60d0c218d4
@ -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/"
|
||||
}
|
||||
|
79
src/components/common/job-trigger-interval.vue
Normal file
79
src/components/common/job-trigger-interval.vue
Normal 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>
|
@ -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">
|
||||
|
@ -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%';
|
||||
}
|
||||
|
76
src/components/common/scene-trigger-interval.vue
Normal file
76
src/components/common/scene-trigger-interval.vue
Normal 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>
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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',
|
||||
|
@ -953,7 +953,7 @@ const local: App.I18n.Schema = {
|
||||
triggerType: '触发类型',
|
||||
triggerInterval: '间隔时长',
|
||||
blockStrategy: '阻塞策略',
|
||||
executorTimeout: '超时时间',
|
||||
executorTimeout: '超时时间(秒)',
|
||||
maxRetryTimes: '最大重试次数',
|
||||
retryInterval: '重试间隔',
|
||||
taskType: '任务类型',
|
||||
|
4
src/typings/api.d.ts
vendored
4
src/typings/api.d.ts
vendored
@ -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;
|
||||
|
@ -20,7 +20,7 @@ interface FormModel {
|
||||
|
||||
const model: FormModel = reactive({
|
||||
userName: 'admin',
|
||||
password: '654321'
|
||||
password: 'admin'
|
||||
});
|
||||
|
||||
type RuleKey = Extract<keyof FormModel, 'userName' | 'password'>;
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user