diff --git a/packages/work-flow/src/api/index.ts b/packages/work-flow/src/api/index.ts index 4e8fbb1..3476e39 100644 --- a/packages/work-flow/src/api/index.ts +++ b/packages/work-flow/src/api/index.ts @@ -10,6 +10,36 @@ export function fetchJobList(groupName: string) { }); } +export function fetchJobLogList(params?: FlowApi.JobLog.JobLogSearchParams) { + return request({ + url: '/job/log/list', + method: 'get', + params + }); +} + +export function fetchJobDetail(id: string) { + return request({ + url: `/job/${id}`, + method: 'get' + }); +} + +export function fetchBatchDetail(id: string) { + return request({ + url: `/job/batch/${id}`, + method: 'get' + }); +} + +export function fetchTaskList(params: { groupName: string; taskBatchId: string; page?: number; pageSize?: number }) { + return request({ + url: '/job/task/list', + method: 'get', + params + }); +} + export function fetchNodeRetry(nodeId: string, taskBatchId: string) { return request({ url: `/workflow/node/retry/${nodeId}/${taskBatchId}`, @@ -60,3 +90,10 @@ export function fetchWorkflowBatchInfo(id: string) { method: 'get' }); } + +export function fetchWorkflowNodeRetry(id: string, workflowNodeId: number) { + return request({ + url: `/workflow/node/retry/${workflowNodeId}/${id}`, + method: 'get' + }); +} diff --git a/packages/work-flow/src/components/detail-card.vue b/packages/work-flow/src/components/detail-card.vue new file mode 100644 index 0000000..12220b2 --- /dev/null +++ b/packages/work-flow/src/components/detail-card.vue @@ -0,0 +1,376 @@ + + + + + diff --git a/packages/work-flow/src/components/log-drawer.vue b/packages/work-flow/src/components/log-drawer.vue new file mode 100644 index 0000000..56b8ed4 --- /dev/null +++ b/packages/work-flow/src/components/log-drawer.vue @@ -0,0 +1,213 @@ + + + + + diff --git a/packages/work-flow/src/constants/business.ts b/packages/work-flow/src/constants/business.ts index dc55fcb..500d8bb 100644 --- a/packages/work-flow/src/constants/business.ts +++ b/packages/work-flow/src/constants/business.ts @@ -113,3 +113,28 @@ export const taskBatchStatusRecord: Record = { + 0: 'snail.enum.jobOperationReason.none', + 1: 'snail.enum.jobOperationReason.taskExecutionTimeout', + 2: 'snail.enum.jobOperationReason.notClient', + 3: 'snail.enum.jobOperationReason.closed', + 4: 'snail.enum.jobOperationReason.discard', + 5: 'snail.enum.jobOperationReason.overlay', + 6: 'snail.enum.jobOperationReason.notExecutionTask', + 7: 'snail.enum.jobOperationReason.taskExecutionError', + 8: 'snail.enum.jobOperationReason.mannerStop', + 9: 'snail.enum.jobOperationReason.workflowConditionNodeExecutionError', + 10: 'snail.enum.jobOperationReason.jobTaskInterrupted', + 11: 'snail.enum.jobOperationReason.workflowCallbackNodeExecutionError', + 12: 'snail.enum.jobOperationReason.workflowNodeNoRequired', + 13: 'snail.enum.jobOperationReason.workflowNodeClosedSkipExecution', + 14: 'snail.enum.jobOperationReason.workflowDecisionFailed' +}; +export const operationReasonOptions = transformRecordToOption(operationReasonRecord); + +export const executorTypeRecord: Record = { + 1: 'snail.enum.executorType.java' +}; + +export const executorTypeRecordOptions = transformRecordToOption(executorTypeRecord); diff --git a/packages/work-flow/src/locales/langs/en-us.ts b/packages/work-flow/src/locales/langs/en-us.ts index f2e9c11..f6c32ec 100644 --- a/packages/work-flow/src/locales/langs/en-us.ts +++ b/packages/work-flow/src/locales/langs/en-us.ts @@ -7,6 +7,7 @@ const local: FlowI18n.Schema = { retry: 'Retry', ignore: 'Ignore', stop: 'Stop', + refresh: 'Refresh', form: { groupName: 'Please select group', workflowTip: 'Please configure workflow', @@ -14,6 +15,26 @@ const local: FlowI18n.Schema = { stopMessage: 'Stop mission successful', taskTip: 'Please select task' }, + jobBatch: { + groupName: 'Group name', + jobName: 'Job name', + executorInfo: 'Executor Name', + executorType: 'Executor type', + executionAt: 'Start execution time', + taskBatchStatus: 'Task Batch Status', + operationReason: 'Reason for operation', + createDt: 'Create time', + jobTask: { + id: 'ID', + groupName: 'Group name', + taskStatus: 'Status', + clientInfo: 'Client address', + argsStr: 'Argument string', + resultMessage: 'Result message', + retryCount: 'Number of retries', + createDt: 'Create time' + } + }, enum: { failStrategy: { skip: 'Skip', @@ -41,6 +62,26 @@ const local: FlowI18n.Schema = { triggerType: { time: 'Fixed Time', cron: 'CRON Expressions' + }, + jobOperationReason: { + none: 'None', + taskExecutionTimeout: 'Task execution timeout', + notClient: 'No client', + closed: 'Job closed', + discard: 'Job discard', + overlay: 'Job overlapped', + notExecutionTask: 'No execution task', + taskExecutionError: 'Execution error', + mannerStop: 'Manual stop', + workflowConditionNodeExecutionError: 'Condition node execution error', + jobTaskInterrupted: 'Job interrupted', + workflowCallbackNodeExecutionError: 'Callback node execution error', + workflowNodeNoRequired: 'No process required', + workflowNodeClosedSkipExecution: 'Node closed, skip execution', + workflowDecisionFailed: 'Workflow decision failed' + }, + executorType: { + java: 'Java' } } }, @@ -79,7 +120,10 @@ const local: FlowI18n.Schema = { webhookTip: 'Please configure callback notifications' } }, - endNode: 'End Node' + endNode: 'End Node', + log: { + title: 'Log Detail' + } } }; diff --git a/packages/work-flow/src/locales/langs/zh-cn.ts b/packages/work-flow/src/locales/langs/zh-cn.ts index 9113c0b..8ddc111 100644 --- a/packages/work-flow/src/locales/langs/zh-cn.ts +++ b/packages/work-flow/src/locales/langs/zh-cn.ts @@ -7,6 +7,7 @@ const local: FlowI18n.Schema = { retry: '重试', ignore: '忽略', stop: '停止', + refresh: '刷新', form: { groupName: '请选择组', workflowTip: '请配置工作流', @@ -14,6 +15,26 @@ const local: FlowI18n.Schema = { stopMessage: '停止任务成功', taskTip: '请选择任务' }, + jobBatch: { + groupName: '组名称', + jobName: '任务名称', + executorInfo: '执行器名称', + executorType: '执行器类型', + executionAt: '开始执行时间', + taskBatchStatus: '状态', + operationReason: '操作原因', + createDt: '创建时间', + jobTask: { + id: 'ID', + groupName: '组名称', + taskStatus: '状态', + clientInfo: '地址', + argsStr: '参数', + resultMessage: '结果', + retryCount: '重试次数', + createDt: '开始执行时间' + } + }, enum: { failStrategy: { skip: '跳过', @@ -41,6 +62,26 @@ const local: FlowI18n.Schema = { triggerType: { time: '固定时间', cron: 'CRON 表达式' + }, + jobOperationReason: { + none: '无', + taskExecutionTimeout: '任务执行超时', + notClient: '无客户端节点', + closed: '任务已关闭', + discard: '任务丢弃', + overlay: '任务被覆盖', + notExecutionTask: '无可执行任务项', + taskExecutionError: '任务执行期间发生非预期异常', + mannerStop: '手动停止', + workflowConditionNodeExecutionError: '条件节点执行异常', + jobTaskInterrupted: '任务中断', + workflowCallbackNodeExecutionError: '回调节点执行异常', + workflowNodeNoRequired: '无需处理', + workflowNodeClosedSkipExecution: '节点关闭跳过执行', + workflowDecisionFailed: '判定未通过' + }, + executorType: { + java: 'Java' } } }, @@ -77,7 +118,10 @@ const local: FlowI18n.Schema = { webhookTip: '请配置回调通知' } }, - endNode: '流程结束' + endNode: '流程结束', + log: { + title: '日志详情' + } } }; diff --git a/packages/work-flow/src/components/add-node.vue b/packages/work-flow/src/node/add-node.vue similarity index 100% rename from packages/work-flow/src/components/add-node.vue rename to packages/work-flow/src/node/add-node.vue diff --git a/packages/work-flow/src/components/branch-node.vue b/packages/work-flow/src/node/branch-node.vue similarity index 100% rename from packages/work-flow/src/components/branch-node.vue rename to packages/work-flow/src/node/branch-node.vue diff --git a/packages/work-flow/src/components/callback-node.vue b/packages/work-flow/src/node/callback-node.vue similarity index 100% rename from packages/work-flow/src/components/callback-node.vue rename to packages/work-flow/src/node/callback-node.vue diff --git a/packages/work-flow/src/components/node-wrap.vue b/packages/work-flow/src/node/node-wrap.vue similarity index 100% rename from packages/work-flow/src/components/node-wrap.vue rename to packages/work-flow/src/node/node-wrap.vue diff --git a/packages/work-flow/src/components/start-node.vue b/packages/work-flow/src/node/start-node.vue similarity index 100% rename from packages/work-flow/src/components/start-node.vue rename to packages/work-flow/src/node/start-node.vue diff --git a/packages/work-flow/src/components/task-node.vue b/packages/work-flow/src/node/task-node.vue similarity index 98% rename from packages/work-flow/src/components/task-node.vue rename to packages/work-flow/src/node/task-node.vue index a987096..4908cf2 100644 --- a/packages/work-flow/src/components/task-node.vue +++ b/packages/work-flow/src/node/task-node.vue @@ -7,6 +7,7 @@ import { $t } from '../locales'; import { failStrategyRecord, taskBatchStatusEnum } from '../constants/business'; import TaskDrawer from '../drawer/task-drawer.vue'; import TaskDetail from '../detail/task-detail.vue'; +import DetailCard from '../components/detail-card.vue'; import AddNode from './add-node.vue'; defineOptions({ @@ -271,7 +272,7 @@ const isStop = (taskBatchStatus: number) => { v-model:len="nodeConfig.conditionNodes!.length" @save="save" /> - + diff --git a/packages/work-flow/src/typings/api.d.ts b/packages/work-flow/src/typings/api.d.ts index fa29c10..bf0b3e8 100644 --- a/packages/work-flow/src/typings/api.d.ts +++ b/packages/work-flow/src/typings/api.d.ts @@ -5,4 +5,48 @@ declare namespace FlowApi { id: string; jobName: string; }; + + /** + * namespace JobLog + * + * backend api module: "JobLog" + */ + namespace JobLog { + type JobLevel = 'INFO' | 'WARN' | 'ERROR' | 'DEBUG'; + + type JobLogSearchParams = { + taskBatchId: string; + jobId: string; + taskId: string; + } & LogSearchParams; + + type RetryLogSearchParams = { + groupName: string; + uniqueId: string; + } & LogSearchParams; + + type LogSearchParams = { + startId: string; + fromIndex: number; + size: number; + }; + + type JobLogList = { + finished: boolean; + fromIndex: number; + message: JobMessage[]; + nextStartId: string; + }; + + type JobMessage = { + level: JobLevel; + host: string; + port: string; + location: string; + message: string; + thread: string; + ['time_stamp']: string; + throwable: string; + }; + } } diff --git a/packages/work-flow/src/typings/flow.d.ts b/packages/work-flow/src/typings/flow.d.ts index 81d6c8f..49666eb 100644 --- a/packages/work-flow/src/typings/flow.d.ts +++ b/packages/work-flow/src/typings/flow.d.ts @@ -7,6 +7,8 @@ declare namespace Flow { type ContentType = 1 | 2; type TriggerType = 2 | 3; type WorkFlowNodeStatus = 0 | 1; + type ExecutorType = 1; + type OperationReason = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14; /** 组 */ export type NodeDataType = { @@ -121,4 +123,80 @@ declare namespace Flow { /** 图标 */ icon: string; }; + + /** 定时任务详情 */ + export type JobTaskType = { + /** 定时任务 ID */ + id?: string; + /** 组名称 */ + groupName?: string; + /** 任务信息 ID */ + jobId?: string; + /** 任务名称 */ + jobName?: string; + /** 节点名称 */ + nodeName?: string; + /** 任务实例 ID */ + taskBatchId?: string; + /** 状态 */ + jobStatus?: number; + /** 状态 */ + taskBatchStatus?: Flow.TaskBatchStatus; + /** 执行器类型 */ + executorType?: ExecutorType; + /** 操作原因 */ + operationReason?: OperationReason; + /** 开始执行时间 */ + executionAt?: string; + /** 执行器名称 */ + executorInfo?: string; + /** 创建时间 */ + createDt?: string; + /** 工作流节点ID */ + workflowNodeId?: number; + /** 工作流任务批次ID */ + workflowTaskBatchId?: number; + }; + + /** 任务项列表 */ + export type JobBatchType = { + /** ID */ + id?: string; + /** 任务 ID */ + jobId?: string; + /** 组名称 */ + groupName?: string; + /** 地址 */ + clientInfo?: string; + /** 参数 */ + argsStr?: string; + /** 结果 */ + resultMessage?: string; + /** 重试次数 */ + retryCount?: string; + /** 开始执行时间 */ + createDt?: string; + /** 任务批次 ID */ + taskBatchId?: string; + /** 任务状态 ID */ + taskStatus?: TaskBatchStatus; + }; + + export type JobBatchPage = { + total: number; + data: JobTaskType[]; + }; + + /** 任务日志 */ + export type JobLogType = {}; + + /** Tag */ + export type JobTagType = { + [key: number | string]: { + /** 名称 */ + name: string; + /** 颜色 */ + color: string; + }; + }; } diff --git a/packages/work-flow/src/typings/i18n.d.ts b/packages/work-flow/src/typings/i18n.d.ts index e0de5c4..bb5285a 100644 --- a/packages/work-flow/src/typings/i18n.d.ts +++ b/packages/work-flow/src/typings/i18n.d.ts @@ -9,6 +9,7 @@ declare namespace FlowI18n { retry: string; ignore: string; stop: string; + refresh: string; failStrategy: string; form: { groupName: string; @@ -17,6 +18,26 @@ declare namespace FlowI18n { stopMessage: string; taskTip: string; }; + jobBatch: { + groupName: string; + jobName: string; + executorInfo: string; + executorType: string; + executionAt: string; + taskBatchStatus: string; + operationReason: string; + createDt: string; + jobTask: { + id: string; + groupName: string; + taskStatus: string; + clientInfo: string; + argsStr: string; + resultMessage: string; + retryCount: string; + createDt: string; + }; + }; enum: { failStrategy: { skip: string; @@ -45,6 +66,26 @@ declare namespace FlowI18n { time: string; cron: string; }; + jobOperationReason: { + 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; + }; + executorType: { + java: string; + }; }; }; node: { @@ -81,6 +122,9 @@ declare namespace FlowI18n { }; }; endNode: string; + log: { + title: string; + }; }; }; diff --git a/packages/work-flow/src/workflow.vue b/packages/work-flow/src/workflow.vue index 46d7d44..6cac93f 100644 --- a/packages/work-flow/src/workflow.vue +++ b/packages/work-flow/src/workflow.vue @@ -1,7 +1,7 @@