wip: 任务批次-初稿

This commit is contained in:
dhb52 2024-04-26 01:06:58 +08:00
parent 1c2feafe79
commit 71b28e2a9b
11 changed files with 283 additions and 2 deletions

View File

@ -268,6 +268,7 @@ const local: App.I18n.Schema = {
workflow_batch: 'Workflow Batch',
job: 'Schedule Task Management',
job_task: 'Schedule Task List',
job_batch: 'Schedule Task Batch List',
'manage_user-detail': 'User Detail',
manage_role: 'Role Manage',
manage_menu: 'Menu Manage',
@ -367,6 +368,7 @@ const local: App.I18n.Schema = {
retryTask: 'Retry Task',
retryTaskTip: 'Total task volume: retry/callback task volume',
jobTask: 'Job Task',
jobBatch: 'Job Batch',
jobTaskTip: 'Success rate: total completion/total dispatch amount',
onlineServiceCount: 'Online Machine',
onlineServiceTip: 'Always online machines: the sum of clients and servers registered to the system',
@ -882,6 +884,19 @@ const local: App.I18n.Schema = {
cron: 'CRON表达式',
workflow: '工作流'
}
},
jobBatch: {
title: 'Job Batch List',
groupName: 'Group name',
jobName: 'Job name',
executionAt: 'Start execution time',
taskBatchStatus: 'Task Batch Status',
operationReason: 'Reason for operation',
form: {
groupName: 'Please enter group name',
jobName: 'Please enter job name',
taskBatchStatus: 'Please enter state'
}
}
},
form: {

View File

@ -269,6 +269,7 @@ const local: App.I18n.Schema = {
workflow_batch: '执行批次',
job: '定时任务',
job_task: '任务管理',
job_batch: '执行批次',
'manage_user-detail': '用户详情',
manage_role: '角色管理',
manage_menu: '菜单管理',
@ -364,6 +365,7 @@ const local: App.I18n.Schema = {
retryTask: '重试任务',
retryTaskTip: '总任务量: 重试/回调任务量',
jobTask: '定时任务',
jobBatch: '任务批次',
jobTaskTip: '成功率:总完成/总调度量',
onlineServiceCount: '总在线机器',
onlineServiceTip: '总在线机器:注册到系统的客户端和服务端之和',
@ -878,6 +880,19 @@ const local: App.I18n.Schema = {
cron: 'CRON表达式',
workflow: '工作流'
}
},
jobBatch: {
title: '任务批次列表',
groupName: '组名称',
jobName: '任务名称',
executionAt: '开始执行时间',
taskBatchStatus: '状态',
operationReason: '操作原因',
form: {
groupName: '请输入组名称',
jobName: '请输入任务名称',
taskBatchStatus: '请输入状态'
}
}
},
form: {

View File

@ -31,6 +31,7 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
group: () => import("@/views/group/index.vue"),
home: () => import("@/views/home/index.vue"),
job_task: () => import("@/views/job/task/index.vue"),
job_batch: () => import("@/views/job/batch/index.vue"),
manage_menu: () => import("@/views/manage/menu/index.vue"),
manage_role: () => import("@/views/manage/role/index.vue"),
"manage_user-detail": () => import("@/views/manage/user-detail/[id].vue"),

View File

@ -211,6 +211,16 @@ export const generatedRoutes: GeneratedRoute[] = [
i18nKey: 'route.job_task',
icon: 'octicon:tasklist'
}
},
{
name: 'job_batch',
path: '/job/batch',
component: 'view.job_batch',
meta: {
title: 'job_batch',
i18nKey: 'route.job_batch',
icon: 'carbon:batch-job'
}
}
]
},

View File

@ -114,14 +114,14 @@ function transformElegantRouteToVueRoute(
}
}
// add redirect to child
if (children?.length && !vueRoute.redirect) {
vueRoute.redirect = {
name: children[0].name
};
}
if (children?.length) {
const childRoutes = children.flatMap(child => transformElegantRouteToVueRoute(child, layouts, views));
@ -165,6 +165,7 @@ const routeMap: RouteMap = {
"home": "/home",
"job": "/job",
"job_task": "/job/task",
"job_batch": "/job/batch",
"login": "/login/:module(pwd-login)?",
"manage": "/manage",
"manage_menu": "/manage/menu",

View File

@ -10,3 +10,4 @@ export * from './retry-task';
export * from './retry';
export * from './workflow';
export * from './job';
export * from './job-batch';

View File

@ -0,0 +1,10 @@
import { request } from '../request';
/** get Job page */
export function fetchGetJobBatchList(params?: Api.JobBatch.JobBatchSearchParams) {
return request<Api.JobBatch.JobBatchList>({
url: '/job/batch/list',
method: 'get',
params
});
}

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

@ -916,6 +916,53 @@ declare namespace Api {
type TriggerType = 2 | 3 | 99;
}
/**
* namespace JobBatch
*
* backend api module: "jobBatch"
*/
namespace JobBatch {
type CommonSearchParams = Pick<Common.PaginatingCommonParams, 'page' | 'size'>;
/** JobBatch */
type JobBatch = Common.CommonRecord<{
/** 组名称 */
groupName: string;
/** 任务名称 */
jobName: string;
/** 工作流节点名称 */
nodeName: string;
/** 任务信息id */
jobId: string;
/** 状态 */
taskBatchStatus: Common.TaskBatchStatus;
/** 开始执行时间 */
executionAt: string;
/** 操作原因 */
operationReason: Common.OperationReason;
/** 执行器类型 */
executorType: Common.ExecutorType;
/** 执行器名称 */
executorInfo: string;
/** 工作流的回调节点信息 */
callback: object;
/** 名称 */
decision: object;
/** 工作流批次id */
workflowTaskBatchId: string;
/** 工作流节点id */
workflowNodeId: string;
}>;
/** JobBatch search params */
type JobBatchSearchParams = CommonType.RecordNullable<
Pick<Api.JobBatch.JobBatch, 'groupName' | 'jobName' | 'taskBatchStatus'> & CommonSearchParams
>;
/** JobBatch list */
type JobBatchList = Common.PaginatingQueryRecord<JobBatch>;
}
/**
* namespace WorkflowBatch
*

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

@ -529,6 +529,7 @@ declare namespace App {
retryTask: string;
retryTaskTip: string;
jobTask: string;
jobBatch: string;
jobTaskTip: string;
onlineServiceCount: string;
onlineServiceTip: string;
@ -1045,6 +1046,19 @@ declare namespace App {
workflow: string;
};
};
jobBatch: {
title: string;
groupName: string;
jobName: string;
executionAt: string;
taskBatchStatus: string;
operationReason: string;
form: {
groupName: string;
jobName: string;
taskBatchStatus: string;
};
};
};
form: {
required: string;

View File

@ -0,0 +1,126 @@
<script setup lang="tsx">
import { NButton, NTag } from 'naive-ui';
import { fetchGetJobBatchList } from '@/service/api';
import { $t } from '@/locales';
import { useAppStore } from '@/store/modules/app';
import { useTable } from '@/hooks/common/table';
import { operationReasonRecord } from '@/constants/business';
import JobBatchSearch from './modules/job-batch-search.vue';
const appStore = useAppStore();
const { columns, data, getData, loading, mobilePagination, searchParams, resetSearchParams } = useTable({
apiFn: fetchGetJobBatchList,
apiParams: {
page: 1,
size: 10,
groupName: null,
jobName: null,
taskBatchStatus: null
},
columns: () => [
{
key: 'id',
title: $t('common.index'),
align: 'center',
width: 64
},
{
key: 'groupName',
title: $t('page.jobBatch.groupName'),
align: 'left',
minWidth: 120
},
{
key: 'jobName',
title: $t('page.jobBatch.jobName'),
align: 'center',
minWidth: 120
},
{
key: 'executionAt',
title: $t('page.jobBatch.executionAt'),
align: 'center',
minWidth: 120
},
{
key: 'operationReason',
title: $t('page.jobBatch.operationReason'),
align: 'center',
minWidth: 120,
render: row => {
if (row.operationReason === null) {
return null;
}
const tagMap: Record<Api.Common.OperationReason, NaiveUI.ThemeColor> = {
0: 'default',
1: 'default',
2: 'error',
3: 'default',
4: 'default',
5: 'default',
6: 'default',
7: 'default',
8: 'default',
9: 'default',
10: 'default',
11: 'default',
12: 'default',
13: 'default',
14: 'default'
};
const label = $t(operationReasonRecord[row.operationReason!]);
return <NTag type={tagMap[row.operationReason!]}>{label}</NTag>;
}
},
{
key: 'operate',
title: $t('common.operate'),
align: 'center',
width: 130,
render: row => (
<div class="flex-center gap-8px">
<NButton type="primary" ghost size="small" onClick={() => detail(row.id!)}>
{$t('common.detail')}
</NButton>
</div>
)
}
]
});
function detail(id: string) {
console.log(id);
}
</script>
<template>
<div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
<JobBatchSearch v-model:model="searchParams" @reset="resetSearchParams" @search="getData" />
<NCard
:title="$t('page.jobBatch.title')"
:bordered="false"
size="small"
class="sm:flex-1-hidden card-wrapper"
header-class="view-card-header"
>
<template #header-extra>
<TableHeaderOperation :loading="loading" :show-delete="false" :show-add="false" @refresh="getData" />
</template>
<NDataTable
:columns="columns"
:data="data"
:flex-height="!appStore.isMobile"
:scroll-x="962"
:loading="loading"
remote
:row-key="row => row.id"
:pagination="mobilePagination"
class="sm:h-full"
/>
</NCard>
</div>
</template>
<style scoped></style>

View File

@ -0,0 +1,41 @@
<script setup lang="ts">
import TaskBatchStatus from '@/components/common/task-batch-status.vue';
import { $t } from '@/locales';
defineOptions({
name: 'JobBatchSearch'
});
interface Emits {
(e: 'reset'): void;
(e: 'search'): void;
}
const emit = defineEmits<Emits>();
const model = defineModel<Api.JobBatch.JobBatchSearchParams>('model', { required: true });
function reset() {
emit('reset');
}
function search() {
emit('search');
}
</script>
<template>
<SearchForm :model="model" @search="search" @reset="reset">
<NFormItemGi span="24 s:12 m:6" :label="$t('page.jobBatch.groupName')" path="groupName" class="pr-24px">
<NInput v-model:value="model.groupName" :placeholder="$t('page.jobBatch.form.groupName')" />
</NFormItemGi>
<NFormItemGi span="24 s:12 m:6" :label="$t('page.jobBatch.jobName')" path="jobName" class="pr-24px">
<NInput v-model:value="model.jobName" :placeholder="$t('page.jobBatch.form.jobName')" />
</NFormItemGi>
<NFormItemGi span="24 s:12 m:6" :label="$t('page.jobBatch.taskBatchStatus')" path="taskBatchStatus" class="pr-24px">
<TaskBatchStatus v-model:value="model.taskBatchStatus" />
</NFormItemGi>
</SearchForm>
</template>
<style scoped></style>