feat(sj_1.0.0): 定义job状态和操作原因

This commit is contained in:
opensnail 2024-04-24 21:44:33 +08:00
parent 32627dee23
commit d114a844ed
16 changed files with 336 additions and 104 deletions

View File

@ -0,0 +1,29 @@
<script setup lang="ts">
import { ref } from 'vue';
import { $t } from '@/locales';
import { translateOptions } from '@/utils/common';
import { operationReasonOptions } from '@/constants/business';
const operationReasonRef = ref<Api.Common.OperationReason>();
const emit = defineEmits<Emits>();
interface Emits {
(e: 'update:value', value: Api.Common.OperationReason): void;
}
const handleUpdate = (operationReason: Api.Common.OperationReason) => {
emit('update:value', operationReason);
};
</script>
<template>
<NSelect
v-model:value="operationReasonRef"
:placeholder="$t('common.jobOperationReason.form')"
:options="translateOptions(operationReasonOptions)"
clearable
@update:value="handleUpdate"
/>
</template>
<style scoped></style>

View File

@ -0,0 +1,29 @@
<script setup lang="ts">
import { ref } from 'vue';
import { $t } from '@/locales';
import { translateOptions } from '@/utils/common';
import { routeKeyRecordOptions } from '@/constants/business';
const routeKeyRef = ref<Api.Common.RouteKey>();
const emit = defineEmits<Emits>();
interface Emits {
(e: 'update:value', value: Api.Common.RouteKey): void;
}
const handleUpdate = (routeKey: Api.Common.RouteKey) => {
emit('update:value', routeKey);
};
</script>
<template>
<NSelect
v-model:value="routeKeyRef"
:placeholder="$t('common.routeKey.routeForm')"
:options="translateOptions(routeKeyRecordOptions)"
clearable
@update:value="handleUpdate"
/>
</template>
<style scoped></style>

View File

@ -0,0 +1,29 @@
<script setup lang="ts">
import { ref } from 'vue';
import { $t } from '@/locales';
import { translateOptions } from '@/utils/common';
import { taskBatchStatusRecordOptions } from '@/constants/business';
const taskBatchStatusRef = ref<Api.Common.TaskBatchStatus>();
const emit = defineEmits<Emits>();
interface Emits {
(e: 'update:value', value: Api.Common.TaskBatchStatus): void;
}
const handleUpdate = (taskBatchStatus: Api.Common.TaskBatchStatus) => {
emit('update:value', taskBatchStatus);
};
</script>
<template>
<NSelect
v-model:value="taskBatchStatusRef"
:placeholder="$t('common.taskBatchStatus.form')"
:options="translateOptions(taskBatchStatusRecordOptions)"
clearable
@update:value="handleUpdate"
/>
</template>
<style scoped></style>

View File

@ -116,11 +116,11 @@ export const backOffRecord: Record<Api.RetryScene.BackOff, App.I18n.I18nKey> = {
};
export const backOffRecordOptions = transformRecordToNumberOption(backOffRecord, true);
export const routeKeyRecord: Record<Api.RetryScene.RouteKey, App.I18n.I18nKey> = {
1: 'page.retryScene.routeKeyItem.consistentHash',
2: 'page.retryScene.routeKeyItem.random',
3: 'page.retryScene.routeKeyItem.lru',
4: 'page.retryScene.routeKeyItem.round'
export const routeKeyRecord: Record<Api.Common.RouteKey, App.I18n.I18nKey> = {
1: 'common.routeKey.items.consistentHash',
2: 'common.routeKey.items.random',
3: 'common.routeKey.items.lru',
4: 'common.routeKey.items.round'
};
export const routeKeyRecordOptions = transformRecordToNumberOption(routeKeyRecord, true);
@ -153,3 +153,40 @@ export const DelayLevel: Record<number, string> = {
25: '11h',
26: '12h'
};
export const triggerTypeRecord: Record<Api.Job.TriggerType, App.I18n.I18nKey> = {
2: 'page.jobTask.triggerTypeItem.fixed',
3: 'page.jobTask.triggerTypeItem.cron',
// 只会在定时任务中使用
99: 'page.jobTask.triggerTypeItem.workflow'
};
export const triggerTypeOptions = transformRecordToNumberOption(triggerTypeRecord, true);
export const taskBatchStatusRecord: Record<Api.Common.TaskBatchStatus, App.I18n.I18nKey> = {
1: 'common.taskBatchStatus.items.waiting',
2: 'common.taskBatchStatus.items.running',
3: 'common.taskBatchStatus.items.success',
4: 'common.taskBatchStatus.items.fail',
5: 'common.taskBatchStatus.items.stop',
6: 'common.taskBatchStatus.items.cancel'
};
export const taskBatchStatusRecordOptions = transformRecordToNumberOption(taskBatchStatusRecord, true);
export const operationReasonRecord: Record<Api.Common.OperationReason, App.I18n.I18nKey> = {
0: 'common.jobOperationReason.items.none',
1: 'common.jobOperationReason.items.taskExecutionTimeout',
2: 'common.jobOperationReason.items.notClient',
3: 'common.jobOperationReason.items.closed',
4: 'common.jobOperationReason.items.discard',
5: 'common.jobOperationReason.items.overlay',
6: 'common.jobOperationReason.items.notExecutionTask',
7: 'common.jobOperationReason.items.taskExecutionError',
8: 'common.jobOperationReason.items.mannerStop',
9: 'common.jobOperationReason.items.workflowConditionNodeExecutionError',
10: 'common.jobOperationReason.items.jobTaskInterrupted',
11: 'common.jobOperationReason.items.workflowCallbackNodeExecutionError',
12: 'common.jobOperationReason.items.workflowNodeNoRequired',
13: 'common.jobOperationReason.items.workflowNodeClosedSkipExecution',
14: 'common.jobOperationReason.items.workflowDecisionFailed'
};
export const operationReasonOptions = transformRecordToNumberOption(operationReasonRecord, true);

View File

@ -62,6 +62,49 @@ const local: App.I18n.Schema = {
callback: 'Callback task',
job: 'Job task',
workflow: 'Workflow'
},
routeKey: {
routeLabel: '路由策略',
routeForm: '请输入路由策略',
items: {
consistentHash: '一致性哈希',
random: '随机',
lru: 'LRU',
round: '轮询'
}
},
taskBatchStatus: {
label: '执行状态',
form: '请选择执行状态',
items: {
waiting: '待处理',
running: '运行中',
success: '处理成功',
fail: '处理失败',
stop: '任务停止',
cancel: '取消'
}
},
jobOperationReason: {
label: '操作原因',
form: '请选择执行状态',
items: {
none: '',
taskExecutionTimeout: '任务执行超时',
notClient: '无客户端节点',
closed: '任务已关闭',
discard: '任务丢弃',
overlay: '任务被覆盖',
notExecutionTask: '无可执行任务项',
taskExecutionError: '任务执行期间发生非预期异常',
mannerStop: '手动停止',
workflowConditionNodeExecutionError: '条件节点执行异常',
jobTaskInterrupted: '任务中断',
workflowCallbackNodeExecutionError: '回调节点执行异常',
workflowNodeNoRequired: '无需处理',
workflowNodeClosedSkipExecution: '节点关闭跳过执行',
workflowDecisionFailed: '判定未通过'
}
}
},
request: {
@ -695,12 +738,6 @@ const local: App.I18n.Schema = {
fixed: '固定时间',
cron: 'CRON表达式',
random: '随机等待'
},
routeKeyItem: {
consistentHash: '一致性哈希',
random: '随机',
lru: 'LRU',
round: '轮询'
}
},
workflowBatch: {
@ -778,7 +815,12 @@ const local: App.I18n.Schema = {
retryInterval: 'Please enter retry interval'
},
addJobTask: 'Add job task',
editJobTask: 'Edit job task'
editJobTask: 'Edit job task',
triggerTypeItem: {
fixed: '固定时间',
cron: 'CRON表达式',
workflow: '工作流'
}
}
},
form: {

View File

@ -62,6 +62,49 @@ const local: App.I18n.Schema = {
callback: '回调任务',
job: '定时任务',
workflow: '工作流'
},
routeKey: {
routeLabel: '路由策略',
routeForm: '请输入路由策略',
items: {
consistentHash: '一致性哈希',
random: '随机',
lru: 'LRU',
round: '轮询'
}
},
taskBatchStatus: {
label: '执行状态',
form: '请选择执行状态',
items: {
waiting: '待处理',
running: '运行中',
success: '处理成功',
fail: '处理失败',
stop: '任务停止',
cancel: '取消'
}
},
jobOperationReason: {
label: '操作原因',
form: '请选择执行状态',
items: {
none: '',
taskExecutionTimeout: '任务执行超时',
notClient: '无客户端节点',
closed: '任务已关闭',
discard: '任务丢弃',
overlay: '任务被覆盖',
notExecutionTask: '无可执行任务项',
taskExecutionError: '任务执行期间发生非预期异常',
mannerStop: '手动停止',
workflowConditionNodeExecutionError: '条件节点执行异常',
jobTaskInterrupted: '任务中断',
workflowCallbackNodeExecutionError: '回调节点执行异常',
workflowNodeNoRequired: '无需处理',
workflowNodeClosedSkipExecution: '节点关闭跳过执行',
workflowDecisionFailed: '判定未通过'
}
}
},
request: {
@ -691,12 +734,6 @@ const local: App.I18n.Schema = {
fixed: '固定时间',
cron: 'CRON表达式',
random: '随机等待'
},
routeKeyItem: {
consistentHash: '一致性哈希',
random: '随机',
lru: 'LRU',
round: '轮询'
}
},
workflow: {
@ -774,7 +811,12 @@ const local: App.I18n.Schema = {
retryInterval: '请输入重试间隔'
},
addJobTask: '新增定时任务',
editJobTask: '编辑定时任务'
editJobTask: '编辑定时任务',
triggerTypeItem: {
fixed: '固定时间',
cron: 'CRON表达式',
workflow: '工作流'
}
}
},
form: {

View File

@ -1,8 +1,8 @@
import { request } from '../request';
/** get JobTask page */
export function fetchGetJobTaskPage(params?: Api.JobTask.JobTaskSearchParams) {
return request<Api.JobTask.JobTaskList>({
export function fetchGetJobTaskPage(params?: Api.Job.JobSearchParams) {
return request<Api.Job.JobList>({
url: '/job/page/list',
method: 'get',
params
@ -10,7 +10,7 @@ export function fetchGetJobTaskPage(params?: Api.JobTask.JobTaskSearchParams) {
}
/** add JobTask */
export function fetchAddJobTask(params?: Api.JobTask.JobTask) {
export function fetchAddJobTask(params?: Api.Job.Job) {
return request<boolean>({
url: '/job/page/list',
method: 'post',
@ -19,7 +19,7 @@ export function fetchAddJobTask(params?: Api.JobTask.JobTask) {
}
/** edit JobTask */
export function fetchEditJobTask(params?: Api.JobTask.JobTask) {
export function fetchEditJobTask(params?: Api.Job.Job) {
return request<boolean>({
url: '/job/page/list',
method: 'put',

34
src/typings/api.d.ts vendored
View File

@ -69,6 +69,18 @@ declare namespace Api {
/** record status */
status?: EnableStatus | null;
} & T;
/** 1: 一致性Hash 2: 随机 3: LRU 4: 轮询 */
type RouteKey = 1 | 2 | 3 | 4;
/** 1、待处理 2、运行中 3、成功 4、失败 5、停止 6、取消 */
type TaskBatchStatus = 1 | 2 | 3 | 4 | 5 | 6;
/**
* 1 2 3JOB已关闭 4 5 6 7 8 9 10 11 12
* 13 14
*/
type OperationReason = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14;
}
/**
@ -730,7 +742,7 @@ declare namespace Api {
/** 退避策略 */
backOff: BackOff;
/** 路由策略 */
routeKey: RouteKey;
routeKey: Common.RouteKey;
/** 最大重试次数 */
maxRetryCount: number;
/** 间隔时间 */
@ -766,9 +778,6 @@ declare namespace Api {
/** 1: 延迟等级 2: 固定时间 3: CRON表达式 4: 随机等待 */
type BackOff = 1 | 2 | 3 | 4;
/** 1: 一致性Hash 2: 随机 3: LRU 4: 轮询 */
type RouteKey = 1 | 2 | 3 | 4;
}
/**
@ -791,7 +800,7 @@ declare namespace Api {
/** 状态 */
workflowStatus: EnableStatusNumber;
/** 触发类型 */
triggerType: number;
triggerType: Job.TriggerType;
/** 间隔时长 */
triggerInterval: string;
/** 超时时间 */
@ -812,11 +821,11 @@ declare namespace Api {
*
* backend api module: "jobTask"
*/
namespace JobTask {
namespace Job {
type CommonSearchParams = Pick<Common.PaginatingCommonParams, 'page' | 'size'>;
/** JobTask */
type JobTask = Common.CommonRecord<{
/** Job */
type Job = Common.CommonRecord<{
/** 组名称 */
groupName: string;
/** 任务名称 */
@ -858,9 +867,9 @@ declare namespace Api {
}>;
/** JobTask search params */
type JobTaskSearchParams = CommonType.RecordNullable<
type JobSearchParams = CommonType.RecordNullable<
Pick<
Api.JobTask.JobTask,
Api.Job.Job,
| 'groupName'
| 'jobName'
| 'argsStr'
@ -882,7 +891,10 @@ declare namespace Api {
>;
/** JobTask list */
type JobTaskList = Common.PaginatingQueryRecord<JobTask>;
type JobList = Common.PaginatingQueryRecord<Job>;
/** 2、固定时间 3、CRON表达式 99、工作流 */
type TriggerType = 2 | 3 | 99;
}
/**

54
src/typings/app.d.ts vendored
View File

@ -309,6 +309,49 @@ declare namespace App {
job: string;
workflow: string;
};
routeKey: {
routeLabel: string;
routeForm: string;
items: {
consistentHash: string;
random: string;
lru: string;
round: string;
};
};
taskBatchStatus: {
label: string;
form: string;
items: {
waiting: string;
running: string;
success: string;
fail: string;
stop: string;
cancel: string;
};
};
jobOperationReason: {
label: string;
form: string;
items: {
none: string;
taskExecutionTimeout: string;
notClient: string;
closed: string;
discard: string;
overlay: string;
notExecutionTask: string;
taskExecutionError: string;
mannerStop: string;
workflowConditionNodeExecutionError: string;
jobTaskInterrupted: string;
workflowCallbackNodeExecutionError: string;
workflowNodeNoRequired: string;
workflowNodeClosedSkipExecution: string;
workflowDecisionFailed: string;
};
};
};
request: {
logout: string;
@ -859,12 +902,6 @@ declare namespace App {
cron: string;
random: string;
};
routeKeyItem: {
consistentHash: string;
random: string;
lru: string;
round: string;
};
};
workflow: {
title: string;
@ -942,6 +979,11 @@ declare namespace App {
};
addJobTask: string;
editJobTask: string;
triggerTypeItem: {
fixed: string;
cron: string;
workflow: string;
};
};
};
form: {

View File

@ -13,7 +13,7 @@ interface Props {
/** the type of operation */
operateType: NaiveUI.TableOperateType;
/** the edit row data */
rowData?: Api.JobTask.JobTask | null;
rowData?: Api.Job.Job | null;
}
const props = defineProps<Props>();
@ -40,7 +40,7 @@ const title = computed(() => {
});
type Model = Pick<
Api.JobTask.JobTask,
Api.Job.Job,
| 'groupName'
| 'jobName'
| 'argsStr'

View File

@ -12,7 +12,7 @@ interface Emits {
const emit = defineEmits<Emits>();
const model = defineModel<Api.JobTask.JobTaskSearchParams>('model', { required: true });
const model = defineModel<Api.Job.JobSearchParams>('model', { required: true });
function reset() {
emit('reset');

View File

@ -3,14 +3,10 @@ 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';
import { $t } from '@/locales';
import { fetchAddRetryScene, fetchEditRetryScene, fetchGetAllGroupNameList } from '@/service/api';
import {
DelayLevel,
backOffRecordOptions,
enableStatusNumberOptions,
routeKeyRecordOptions
} from '@/constants/business';
import { DelayLevel, backOffRecordOptions, enableStatusNumberOptions } from '@/constants/business';
import { translateOptions, translateOptions2 } from '@/utils/common';
import { useAppStore } from '@/store/modules/app';
@ -265,13 +261,8 @@ watch(
clearable
/>
</NFormItem>
<NFormItem :label="$t('page.retryScene.routeKey')" path="routeKey">
<NSelect
v-model:value="model.routeKey"
:placeholder="$t('page.retryScene.form.routeKey')"
:options="translateOptions(routeKeyRecordOptions)"
clearable
/>
<NFormItem :label="$t('common.routeKey.routeLabel')" path="routeKey">
<RouteKey v-model:value="model.routeKey" />
</NFormItem>
<NFormItem :label="$t('page.retryScene.backOff')" path="backOff">
<NSelect

View File

@ -16,16 +16,6 @@ const emit = defineEmits<Emits>();
const model = defineModel<Api.RetryScene.SceneSearchParams>('model', { required: true });
/** 组列表 */
// const groupNameList = ref<string[]>([]);
/** 场景列表 */
// const sceneNameList = ref<string[]>([]);
// async function getGroupNameList() {
// const res = await fetchGetAllGroupNameList();
// groupNameList.value = res.data as string[];
// }
function reset() {
emit('reset');
}
@ -33,43 +23,14 @@ function reset() {
function search() {
emit('search');
}
// async function handleGroupNameUpdate(groupName: string) {
// if (groupName) {
// const res = await fetchGetRetrySceneList({ groupName });
// sceneNameList.value = res.data!.map((scene: Api.RetryScene.Scene) => scene.sceneName);
// } else {
// model.value.sceneName = '';
// sceneNameList.value = [];
// }
// }
// onMounted(() => {
// getGroupNameList();
// });
</script>
<template>
<SearchForm :model="model" @search="search" @reset="reset">
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryScene.groupName')" path="userName" class="pr-24px">
<!-- <NSelect-->
<!-- v-model:value="model.groupName"-->
<!-- :placeholder="$t('page.retryScene.form.groupName')"-->
<!-- :options="translateOptions2(groupNameList)"-->
<!-- clearable-->
<!-- filterable-->
<!-- @update:value="handleGroupNameUpdate"-->
<!-- />-->
<SelectGroup v-model="model.groupName" />
</NFormItemGi>
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryScene.sceneName')" path="userName" class="pr-24px">
<!-- <NSelect-->
<!-- v-model:value="model.sceneName"-->
<!-- :placeholder="$t('page.retryScene.form.sceneName')"-->
<!-- :options="translateOptions2(sceneNameList)"-->
<!-- clearable-->
<!-- />-->
<SelectScene v-model:value="model.sceneName" :group-name="model.groupName as string" />
</NFormItemGi>
</SearchForm>

View File

@ -2,6 +2,7 @@
import { ref } from 'vue';
import { $t } from '@/locales';
import SelectGroup from '@/components/common/select-group.vue';
import TaskBatchStatus from '@/components/common/task-batch-status.vue';
import { fetchGetWorkflowNameList } from '@/service/api';
@ -36,10 +37,10 @@ async function groupNameUpdate(groupName: string) {
<template>
<SearchForm :model="model" @search="search" @reset="reset">
<NFormItemGi span="24 s:12 m:6" :label="$t('page.workflowBatch.groupName')" path="userName" class="pr-24px">
<NFormItemGi span="24 s:12 m:6" :label="$t('page.workflowBatch.groupName')" path="groupName" class="pr-24px">
<SelectGroup v-model:value="model.groupName" @update:value="groupNameUpdate" />
</NFormItemGi>
<NFormItemGi span="24 s:12 m:6" :label="$t('page.workflowBatch.workflowName')" path="userName" class="pr-24px">
<NFormItemGi span="24 s:12 m:6" :label="$t('page.workflowBatch.workflowName')" path="workflowName" class="pr-24px">
<NSelect
v-model:value="model.workflowId"
:placeholder="$t('page.workflowBatch.form.workflowName')"
@ -50,8 +51,8 @@ async function groupNameUpdate(groupName: string) {
filterable
/>
</NFormItemGi>
<NFormItemGi span="24 s:12 m:6" :label="$t('page.workflowBatch.taskBatchStatus')" path="userName" class="pr-24px">
<NInput v-model:value="model.taskBatchStatus" :placeholder="$t('page.workflowBatch.form.taskBatchStatus')" />
<NFormItemGi span="24 s:12 m:6" :label="$t('common.taskBatchStatus.label')" path="taskBatchStatus" class="pr-24px">
<TaskBatchStatus v-model:value="model.taskBatchStatus" />
</NFormItemGi>
</SearchForm>
</template>

View File

@ -1,9 +1,10 @@
<script setup lang="tsx">
import { NButton, NPopconfirm } from 'naive-ui';
import { NButton, NPopconfirm, NTag } from 'naive-ui';
import { fetchGetWorkflowPageList } from '@/service/api';
import { $t } from '@/locales';
import { useAppStore } from '@/store/modules/app';
import { useTable, useTableOperate } from '@/hooks/common/table';
import { enableStatusNumberRecord, triggerTypeRecord } from '@/constants/business';
import WorkflowSearch from './modules/workflow-search.vue';
const appStore = useAppStore();
@ -53,13 +54,29 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
key: 'workflowStatus',
title: $t('page.workflow.workflowStatus'),
align: 'left',
minWidth: 120
minWidth: 120,
render: row => {
if (!row.workflowStatus) {
return null;
}
const label = $t(enableStatusNumberRecord[row.workflowStatus!]);
return <NTag type="primary">{label}</NTag>;
}
},
{
key: 'triggerType',
title: $t('page.workflow.triggerType'),
align: 'left',
minWidth: 120
minWidth: 120,
render: row => {
if (!row.triggerType) {
return null;
}
const label = $t(triggerTypeRecord[row.triggerType!]);
return <NTag type="primary">{label}</NTag>;
}
},
{
key: 'triggerInterval',

View File

@ -1,7 +1,7 @@
<script setup lang="ts">
import { $t } from '@/locales';
import { translateOptions } from '@/utils/common';
import { retryTaskStatusTypeOptions } from '@/constants/business';
import { enableStatusNumberOptions } from '@/constants/business';
import SelectGroup from '@/components/common/select-group.vue';
defineOptions({
@ -38,7 +38,7 @@ function search() {
<NSelect
v-model:value="model.workflowStatus"
:placeholder="$t('page.workflow.form.workflowStatus')"
:options="translateOptions(retryTaskStatusTypeOptions)"
:options="translateOptions(enableStatusNumberOptions)"
/>
</NFormItemGi>
</SearchForm>