feat: 新增批次详情卡片
This commit is contained in:
parent
2a913e4edd
commit
e82682b9c8
@ -10,6 +10,36 @@ export function fetchJobList(groupName: string) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function fetchJobLogList(params?: FlowApi.JobLog.JobLogSearchParams) {
|
||||||
|
return request<FlowApi.JobLog.JobLogList>({
|
||||||
|
url: '/job/log/list',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fetchJobDetail(id: string) {
|
||||||
|
return request<Flow.JobTaskType>({
|
||||||
|
url: `/job/${id}`,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fetchBatchDetail(id: string) {
|
||||||
|
return request<Flow.JobBatchType>({
|
||||||
|
url: `/job/batch/${id}`,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fetchTaskList(params: { groupName: string; taskBatchId: string; page?: number; pageSize?: number }) {
|
||||||
|
return request<Flow.JobBatchPage>({
|
||||||
|
url: '/job/task/list',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function fetchNodeRetry(nodeId: string, taskBatchId: string) {
|
export function fetchNodeRetry(nodeId: string, taskBatchId: string) {
|
||||||
return request<null>({
|
return request<null>({
|
||||||
url: `/workflow/node/retry/${nodeId}/${taskBatchId}`,
|
url: `/workflow/node/retry/${nodeId}/${taskBatchId}`,
|
||||||
@ -60,3 +90,10 @@ export function fetchWorkflowBatchInfo(id: string) {
|
|||||||
method: 'get'
|
method: 'get'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function fetchWorkflowNodeRetry(id: string, workflowNodeId: number) {
|
||||||
|
return request<null>({
|
||||||
|
url: `/workflow/node/retry/${workflowNodeId}/${id}`,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
376
packages/work-flow/src/components/detail-card.vue
Normal file
376
packages/work-flow/src/components/detail-card.vue
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
<script setup lang="tsx">
|
||||||
|
import { nextTick, ref, useSlots, watch } from 'vue';
|
||||||
|
import type { DataTableColumn } from 'naive-ui';
|
||||||
|
import { NButton, NTag } from 'naive-ui';
|
||||||
|
import { useFlowStore } from '../stores';
|
||||||
|
import { fetchBatchDetail, fetchJobDetail, fetchTaskList, fetchWorkflowNodeRetry } from '../api';
|
||||||
|
import { executorTypeRecord, operationReasonRecord, taskBatchStatusRecord } from '../constants/business';
|
||||||
|
import { $t } from '../locales';
|
||||||
|
import LogDrawer from './log-drawer.vue';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'DetailCard'
|
||||||
|
});
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
id?: string;
|
||||||
|
ids?: string[];
|
||||||
|
show?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
show: false,
|
||||||
|
ids: () => []
|
||||||
|
});
|
||||||
|
|
||||||
|
interface Emits {
|
||||||
|
(e: 'update:show', show: boolean): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
|
const slots = useSlots();
|
||||||
|
|
||||||
|
const store = useFlowStore();
|
||||||
|
const visible = ref(false);
|
||||||
|
const logOpen = ref(false);
|
||||||
|
const spinning = ref(false);
|
||||||
|
const loading = ref(false);
|
||||||
|
const currentIndex = ref(1);
|
||||||
|
const jobData = ref<Flow.JobTaskType>({});
|
||||||
|
const dataSource = ref<Flow.JobBatchType[]>([]);
|
||||||
|
|
||||||
|
const pagination = ref({
|
||||||
|
page: 1,
|
||||||
|
pageCount: 0,
|
||||||
|
pageSize: 10,
|
||||||
|
showSizePicker: true,
|
||||||
|
pageSizes: [10, 15, 20, 25, 30],
|
||||||
|
onUpdatePage: async (page: number) => {
|
||||||
|
pagination.value.page = page;
|
||||||
|
const id = props.ids[currentIndex.value - 1];
|
||||||
|
getBatchDetail(id);
|
||||||
|
getRows(id, page);
|
||||||
|
},
|
||||||
|
onUpdatePageSize: async (pageSize: number) => {
|
||||||
|
pagination.value.pageSize = pageSize;
|
||||||
|
const id = props.ids[currentIndex.value - 1];
|
||||||
|
getBatchDetail(id);
|
||||||
|
getRows(id, pagination.value.page);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.show,
|
||||||
|
val => {
|
||||||
|
visible.value = val;
|
||||||
|
if (val) {
|
||||||
|
onLoad();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
const onUpdateShow = () => {
|
||||||
|
emit('update:show', false);
|
||||||
|
};
|
||||||
|
|
||||||
|
async function getDetail(id: string) {
|
||||||
|
spinning.value = true;
|
||||||
|
const { data, error } = await fetchJobDetail(id);
|
||||||
|
if (!error) {
|
||||||
|
jobData.value = data;
|
||||||
|
spinning.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getBatchDetail(id: string) {
|
||||||
|
spinning.value = true;
|
||||||
|
const { data, error } = await fetchBatchDetail(id);
|
||||||
|
if (!error) {
|
||||||
|
jobData.value = data;
|
||||||
|
spinning.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getRows(id: string, page: number = 1) {
|
||||||
|
loading.value = true;
|
||||||
|
const { data, error } = await fetchTaskList({
|
||||||
|
groupName: store.groupName!,
|
||||||
|
taskBatchId: id ?? '0',
|
||||||
|
page,
|
||||||
|
pageSize: pagination.value.pageSize
|
||||||
|
});
|
||||||
|
if (!error) {
|
||||||
|
pagination.value.pageCount = data.total;
|
||||||
|
dataSource.value = data.data;
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const idList = ref<string[]>([]);
|
||||||
|
|
||||||
|
function onLoad() {
|
||||||
|
idList.value = props.ids;
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
if (props.ids.length > 0) {
|
||||||
|
getBatchDetail(props.ids[0]);
|
||||||
|
getRows(props.ids[0]);
|
||||||
|
} else if (props.id) {
|
||||||
|
idList.value = [jobData.value.taskBatchId!];
|
||||||
|
getDetail(props.id);
|
||||||
|
getRows(jobData.value.taskBatchId!);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const record = ref<Flow.JobTaskType>({});
|
||||||
|
|
||||||
|
const getLogRows = (task: Flow.JobTaskType) => {
|
||||||
|
record.value = task;
|
||||||
|
logOpen.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const retry = async (item: Flow.JobTaskType) => {
|
||||||
|
const { error } = await fetchWorkflowNodeRetry(store.id!, item.workflowNodeId!);
|
||||||
|
if (!error) {
|
||||||
|
window.$message?.success('执行重试成功');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const isRetry = (taskBatchStatus: number) => {
|
||||||
|
return taskBatchStatus === 4 || taskBatchStatus === 5 || taskBatchStatus === 6;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ThemeColor = 'default' | 'error' | 'primary' | 'info' | 'success' | 'warning';
|
||||||
|
|
||||||
|
const columns = ref<DataTableColumn<Flow.JobBatchType>[]>([
|
||||||
|
{
|
||||||
|
key: 'index',
|
||||||
|
title: '日志',
|
||||||
|
align: 'center',
|
||||||
|
width: 64,
|
||||||
|
render: row => {
|
||||||
|
return (
|
||||||
|
<NButton type="info" text onClick={() => getLogRows(row)}>
|
||||||
|
<span class="w-28px ws-break-spaces">{`查看\n日志`}</span>
|
||||||
|
</NButton>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
title: $t('snail.jobBatch.jobTask.id'),
|
||||||
|
align: 'left',
|
||||||
|
minWidth: 64
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'groupName',
|
||||||
|
title: $t('snail.jobBatch.jobTask.groupName'),
|
||||||
|
align: 'left',
|
||||||
|
minWidth: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'taskStatus',
|
||||||
|
title: $t('snail.jobBatch.jobTask.taskStatus'),
|
||||||
|
align: 'left',
|
||||||
|
minWidth: 80,
|
||||||
|
render: row => {
|
||||||
|
if (row.taskStatus === null) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const label = $t(taskBatchStatusRecord[row.taskStatus!]);
|
||||||
|
const tagMap: Record<number, ThemeColor> = {
|
||||||
|
1: 'info',
|
||||||
|
2: 'info',
|
||||||
|
3: 'info',
|
||||||
|
4: 'error',
|
||||||
|
5: 'error',
|
||||||
|
6: 'error'
|
||||||
|
};
|
||||||
|
return <NTag type={tagMap[row.taskStatus!]}>{label}</NTag>;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'clientInfo',
|
||||||
|
title: $t('snail.jobBatch.jobTask.clientInfo'),
|
||||||
|
align: 'left',
|
||||||
|
minWidth: 120,
|
||||||
|
render: row => {
|
||||||
|
if (row.clientInfo) {
|
||||||
|
const parts = row.clientInfo?.split('@');
|
||||||
|
const result = parts.length > 1 ? parts[1] : '';
|
||||||
|
return <div>{result}</div>;
|
||||||
|
}
|
||||||
|
return <div>{row.clientInfo}</div>;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'argsStr',
|
||||||
|
title: $t('snail.jobBatch.jobTask.argsStr'),
|
||||||
|
align: 'left',
|
||||||
|
minWidth: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'resultMessage',
|
||||||
|
title: $t('snail.jobBatch.jobTask.resultMessage'),
|
||||||
|
align: 'left',
|
||||||
|
minWidth: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'retryCount',
|
||||||
|
title: $t('snail.jobBatch.jobTask.retryCount'),
|
||||||
|
align: 'left',
|
||||||
|
minWidth: 64
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'createDt',
|
||||||
|
title: $t('snail.jobBatch.jobTask.createDt'),
|
||||||
|
align: 'left',
|
||||||
|
minWidth: 120
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
function tagColor(tagIndex: number) {
|
||||||
|
const tagMap: Record<number, ThemeColor> = {
|
||||||
|
0: 'error',
|
||||||
|
1: 'info',
|
||||||
|
2: 'success',
|
||||||
|
3: 'warning',
|
||||||
|
4: 'primary'
|
||||||
|
};
|
||||||
|
|
||||||
|
if (tagIndex === null || tagIndex < 0) {
|
||||||
|
return tagMap[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return tagMap[tagIndex % 5];
|
||||||
|
}
|
||||||
|
|
||||||
|
const onUpdatePage = (page: number) => {
|
||||||
|
currentIndex.value = page;
|
||||||
|
const id = props.ids[page - 1];
|
||||||
|
getBatchDetail(id);
|
||||||
|
getRows(id, page);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NDrawer v-model:show="visible" :width="800" display-directive="if" @update:show="onUpdateShow">
|
||||||
|
<NDrawerContent title="任务批次详情" closable>
|
||||||
|
<NTabs v-if="idList && idList.length > 0" v-model:value="currentIndex" type="segment" animated>
|
||||||
|
<NTabPane v-for="(item, index) in idList" :key="index" :name="index + 1" :tab="item">
|
||||||
|
<NDescriptions label-placement="top" bordered :column="2">
|
||||||
|
<NDescriptionsItem :label="$t('snail.jobBatch.groupName')">{{ jobData?.groupName }}</NDescriptionsItem>
|
||||||
|
|
||||||
|
<NDescriptionsItem :label="$t('snail.jobBatch.jobName')">{{ jobData?.jobName }}</NDescriptionsItem>
|
||||||
|
|
||||||
|
<NDescriptionsItem :label="$t('snail.jobBatch.taskBatchStatus')">
|
||||||
|
<NTag v-if="jobData.taskBatchStatus" :type="tagColor(jobData?.taskBatchStatus!)">
|
||||||
|
{{ $t(taskBatchStatusRecord[jobData?.taskBatchStatus]) }}
|
||||||
|
</NTag>
|
||||||
|
</NDescriptionsItem>
|
||||||
|
|
||||||
|
<NDescriptionsItem :label="$t('snail.jobBatch.executionAt')">
|
||||||
|
{{ jobData?.executionAt }}
|
||||||
|
</NDescriptionsItem>
|
||||||
|
|
||||||
|
<NDescriptionsItem :label="$t('snail.jobBatch.operationReason')">
|
||||||
|
<NTag v-if="jobData.operationReason" :type="tagColor(jobData?.operationReason!)">
|
||||||
|
{{ $t(operationReasonRecord[jobData.operationReason]) }}
|
||||||
|
</NTag>
|
||||||
|
</NDescriptionsItem>
|
||||||
|
|
||||||
|
<NDescriptionsItem v-if="!slots.default" :label="$t('snail.jobBatch.executorType')">
|
||||||
|
<NTag v-if="jobData.executorType" :type="tagColor(jobData?.executorType!)">
|
||||||
|
{{ $t(executorTypeRecord[jobData?.executorType!]) }}
|
||||||
|
</NTag>
|
||||||
|
</NDescriptionsItem>
|
||||||
|
|
||||||
|
<NDescriptionsItem :label="$t('snail.jobBatch.executorInfo')" :span="2">
|
||||||
|
{{ jobData?.executorInfo }}
|
||||||
|
</NDescriptionsItem>
|
||||||
|
<NDescriptionsItem :label="$t('snail.jobBatch.createDt')" :span="2">
|
||||||
|
{{ jobData?.createDt }}
|
||||||
|
</NDescriptionsItem>
|
||||||
|
</NDescriptions>
|
||||||
|
<slot></slot>
|
||||||
|
<NCard
|
||||||
|
:bordered="false"
|
||||||
|
size="small"
|
||||||
|
class="sm:flex-1-hidden card-wrapper"
|
||||||
|
:content-style="{ padding: 0 }"
|
||||||
|
:header-style="{ padding: 0 }"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<div class="header-border"><span class="pl-12px">任务项列表</span></div>
|
||||||
|
</template>
|
||||||
|
<template #header-extra>
|
||||||
|
<NTooltip trigger="hover">
|
||||||
|
<template #trigger>
|
||||||
|
<NButton text @click="getRows(item)">
|
||||||
|
<icon-ant-design:sync-outlined class="mr-16px text-20px font-bold" />
|
||||||
|
</NButton>
|
||||||
|
</template>
|
||||||
|
刷新
|
||||||
|
</NTooltip>
|
||||||
|
<NTooltip v-if="isRetry(jobData.taskBatchStatus!)" trigger="hover">
|
||||||
|
<template #trigger>
|
||||||
|
<NButton text>
|
||||||
|
<icon-ant-design:redo-outlined class="text-20px font-bold" @click="retry(jobData)" />
|
||||||
|
</NButton>
|
||||||
|
</template>
|
||||||
|
重试
|
||||||
|
</NTooltip>
|
||||||
|
</template>
|
||||||
|
<NDataTable
|
||||||
|
:columns="columns"
|
||||||
|
:data="dataSource"
|
||||||
|
:loading="loading"
|
||||||
|
:scroll="{ x: 1200 }"
|
||||||
|
remote
|
||||||
|
:row-key="row => row.id"
|
||||||
|
:pagination="pagination"
|
||||||
|
class="sm:h-full"
|
||||||
|
/>
|
||||||
|
</NCard>
|
||||||
|
</NTabPane>
|
||||||
|
</NTabs>
|
||||||
|
<template v-if="ids && ids.length > 1" #footer>
|
||||||
|
<NPagination
|
||||||
|
v-model:page="currentIndex"
|
||||||
|
class="text-center"
|
||||||
|
:page-size="1"
|
||||||
|
:page-count="ids.length"
|
||||||
|
@update:page="onUpdatePage"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</NDrawerContent>
|
||||||
|
</NDrawer>
|
||||||
|
<LogDrawer v-model:show="logOpen" title="日志详情" :task-data="record" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.empty {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: calc(100% - 88px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-border {
|
||||||
|
margin: 20px 0;
|
||||||
|
border-left: #1366ff 5px solid;
|
||||||
|
font-size: medium;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.n-tabs-nav) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.n-tab-pane) {
|
||||||
|
padding-top: 0 !important;
|
||||||
|
}
|
||||||
|
</style>
|
213
packages/work-flow/src/components/log-drawer.vue
Normal file
213
packages/work-flow/src/components/log-drawer.vue
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
<script setup lang="tsx">
|
||||||
|
import { NCollapse, NCollapseItem } from 'naive-ui';
|
||||||
|
import { defineComponent, onBeforeUnmount, ref, watch } from 'vue';
|
||||||
|
import { $t } from '../locales';
|
||||||
|
import { fetchJobLogList } from '../api';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'LogDrawer'
|
||||||
|
});
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
title?: string;
|
||||||
|
show?: boolean;
|
||||||
|
taskData: Flow.JobTaskType;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
title: $t('node.log.title'),
|
||||||
|
show: false,
|
||||||
|
modelValue: () => []
|
||||||
|
});
|
||||||
|
|
||||||
|
interface Emits {
|
||||||
|
(e: 'update:show', show: boolean): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
|
const visible = defineModel<boolean>('visible', {
|
||||||
|
default: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const ThrowableComponent = defineComponent({
|
||||||
|
props: {
|
||||||
|
throwable: String
|
||||||
|
},
|
||||||
|
setup(thProps) {
|
||||||
|
return () => {
|
||||||
|
if (!thProps.throwable) {
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
|
const firstLine = thProps.throwable.match(/^.+/m);
|
||||||
|
if (!firstLine) {
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
|
const restOfText = thProps.throwable.replace(/^.+(\n|$)/m, '');
|
||||||
|
return (
|
||||||
|
<NCollapse>
|
||||||
|
<NCollapseItem title={firstLine[0]} name="1">
|
||||||
|
{`${restOfText}`}
|
||||||
|
</NCollapseItem>
|
||||||
|
</NCollapse>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.show,
|
||||||
|
val => {
|
||||||
|
visible.value = val;
|
||||||
|
if (val) {
|
||||||
|
getLogList();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
const onUpdateShow = (value: boolean) => {
|
||||||
|
emit('update:show', value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const logList = ref<FlowApi.JobLog.JobMessage[]>([]);
|
||||||
|
const interval = ref<NodeJS.Timeout>();
|
||||||
|
const controller = new AbortController();
|
||||||
|
const finished = ref<boolean>(false);
|
||||||
|
let startId = '0';
|
||||||
|
let fromIndex: number = 0;
|
||||||
|
|
||||||
|
async function getLogList() {
|
||||||
|
const { data: logData, error } = await fetchJobLogList({
|
||||||
|
taskBatchId: props.taskData.taskBatchId!,
|
||||||
|
jobId: props.taskData.jobId!,
|
||||||
|
taskId: props.taskData.id!,
|
||||||
|
startId,
|
||||||
|
fromIndex,
|
||||||
|
size: 50
|
||||||
|
});
|
||||||
|
if (!error) {
|
||||||
|
finished.value = logData.finished;
|
||||||
|
startId = logData.nextStartId;
|
||||||
|
fromIndex = logData.fromIndex;
|
||||||
|
if (logData.message) {
|
||||||
|
logList.value.push(...logData.message);
|
||||||
|
logList.value.sort((a, b) => Number.parseInt(a.time_stamp, 10) - Number.parseInt(b.time_stamp, 10));
|
||||||
|
}
|
||||||
|
if (!finished.value) {
|
||||||
|
clearTimeout(interval.value);
|
||||||
|
interval.value = setTimeout(getLogList, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const stopLog = () => {
|
||||||
|
finished.value = true;
|
||||||
|
controller.abort();
|
||||||
|
clearTimeout(interval.value);
|
||||||
|
interval.value = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
stopLog();
|
||||||
|
});
|
||||||
|
|
||||||
|
function timestampToDate(timestamp: string): string {
|
||||||
|
const date = new Date(Number.parseInt(timestamp.toString(), 10));
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month =
|
||||||
|
(date.getMonth() + 1).toString().length === 1 ? `0${date.getMonth() + 1}` : (date.getMonth() + 1).toString();
|
||||||
|
const day = date.getDate().toString().length === 1 ? `0${date.getDate()}` : date.getDate().toString();
|
||||||
|
const hours = date.getHours().toString().length === 1 ? `0${date.getHours()}` : date.getHours().toString();
|
||||||
|
const minutes = date.getMinutes().toString().length === 1 ? `0${date.getMinutes()}` : date.getMinutes().toString();
|
||||||
|
const seconds = date.getSeconds().toString().length === 1 ? `0${date.getSeconds()}` : date.getSeconds().toString();
|
||||||
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${date.getMilliseconds()}`;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NDrawer v-model:show="visible" width="100%" display-directive="if" @update:show="onUpdateShow">
|
||||||
|
<NDrawerContent :title="title" closable>
|
||||||
|
<div class="snail-log bg-#fafafc p-16px dark:bg-#000">
|
||||||
|
<div class="snail-log-scrollbar">
|
||||||
|
<code>
|
||||||
|
<pre
|
||||||
|
v-for="(message, index) in logList"
|
||||||
|
:key="index"
|
||||||
|
><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>
|
||||||
|
</NDrawerContent>
|
||||||
|
</NDrawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.snail-log {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
&-scrollbar {
|
||||||
|
padding: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
@include scrollbar();
|
||||||
|
|
||||||
|
.n-divider:not(.n-divider--vertical) {
|
||||||
|
margin-top: 6px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-word;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333639;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
.snail-log {
|
||||||
|
background-color: #1e1f22;
|
||||||
|
|
||||||
|
pre {
|
||||||
|
color: #ffffffe6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-hljs {
|
||||||
|
&-time {
|
||||||
|
color: #2db7f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-level {
|
||||||
|
&-DEBUG {
|
||||||
|
color: #2647cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-INFO {
|
||||||
|
color: #5c962c;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-WARN {
|
||||||
|
color: #da9816;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-ERROR {
|
||||||
|
color: #dc3f41;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-thread {
|
||||||
|
color: #00a3a3;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-location {
|
||||||
|
color: #a771bf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -113,3 +113,28 @@ export const taskBatchStatusRecord: Record<Flow.TaskBatchStatus, FlowI18n.I18nKe
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const taskBatchStatusOptions = transformRecordToOption(taskBatchStatusRecord);
|
export const taskBatchStatusOptions = transformRecordToOption(taskBatchStatusRecord);
|
||||||
|
|
||||||
|
export const operationReasonRecord: Record<Flow.OperationReason, FlowI18n.I18nKey> = {
|
||||||
|
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<Flow.ExecutorType, FlowI18n.I18nKey> = {
|
||||||
|
1: 'snail.enum.executorType.java'
|
||||||
|
};
|
||||||
|
|
||||||
|
export const executorTypeRecordOptions = transformRecordToOption(executorTypeRecord);
|
||||||
|
@ -7,6 +7,7 @@ const local: FlowI18n.Schema = {
|
|||||||
retry: 'Retry',
|
retry: 'Retry',
|
||||||
ignore: 'Ignore',
|
ignore: 'Ignore',
|
||||||
stop: 'Stop',
|
stop: 'Stop',
|
||||||
|
refresh: 'Refresh',
|
||||||
form: {
|
form: {
|
||||||
groupName: 'Please select group',
|
groupName: 'Please select group',
|
||||||
workflowTip: 'Please configure workflow',
|
workflowTip: 'Please configure workflow',
|
||||||
@ -14,6 +15,26 @@ const local: FlowI18n.Schema = {
|
|||||||
stopMessage: 'Stop mission successful',
|
stopMessage: 'Stop mission successful',
|
||||||
taskTip: 'Please select task'
|
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: {
|
enum: {
|
||||||
failStrategy: {
|
failStrategy: {
|
||||||
skip: 'Skip',
|
skip: 'Skip',
|
||||||
@ -41,6 +62,26 @@ const local: FlowI18n.Schema = {
|
|||||||
triggerType: {
|
triggerType: {
|
||||||
time: 'Fixed Time',
|
time: 'Fixed Time',
|
||||||
cron: 'CRON Expressions'
|
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'
|
webhookTip: 'Please configure callback notifications'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
endNode: 'End Node'
|
endNode: 'End Node',
|
||||||
|
log: {
|
||||||
|
title: 'Log Detail'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ const local: FlowI18n.Schema = {
|
|||||||
retry: '重试',
|
retry: '重试',
|
||||||
ignore: '忽略',
|
ignore: '忽略',
|
||||||
stop: '停止',
|
stop: '停止',
|
||||||
|
refresh: '刷新',
|
||||||
form: {
|
form: {
|
||||||
groupName: '请选择组',
|
groupName: '请选择组',
|
||||||
workflowTip: '请配置工作流',
|
workflowTip: '请配置工作流',
|
||||||
@ -14,6 +15,26 @@ const local: FlowI18n.Schema = {
|
|||||||
stopMessage: '停止任务成功',
|
stopMessage: '停止任务成功',
|
||||||
taskTip: '请选择任务'
|
taskTip: '请选择任务'
|
||||||
},
|
},
|
||||||
|
jobBatch: {
|
||||||
|
groupName: '组名称',
|
||||||
|
jobName: '任务名称',
|
||||||
|
executorInfo: '执行器名称',
|
||||||
|
executorType: '执行器类型',
|
||||||
|
executionAt: '开始执行时间',
|
||||||
|
taskBatchStatus: '状态',
|
||||||
|
operationReason: '操作原因',
|
||||||
|
createDt: '创建时间',
|
||||||
|
jobTask: {
|
||||||
|
id: 'ID',
|
||||||
|
groupName: '组名称',
|
||||||
|
taskStatus: '状态',
|
||||||
|
clientInfo: '地址',
|
||||||
|
argsStr: '参数',
|
||||||
|
resultMessage: '结果',
|
||||||
|
retryCount: '重试次数',
|
||||||
|
createDt: '开始执行时间'
|
||||||
|
}
|
||||||
|
},
|
||||||
enum: {
|
enum: {
|
||||||
failStrategy: {
|
failStrategy: {
|
||||||
skip: '跳过',
|
skip: '跳过',
|
||||||
@ -41,6 +62,26 @@ const local: FlowI18n.Schema = {
|
|||||||
triggerType: {
|
triggerType: {
|
||||||
time: '固定时间',
|
time: '固定时间',
|
||||||
cron: 'CRON 表达式'
|
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: '请配置回调通知'
|
webhookTip: '请配置回调通知'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
endNode: '流程结束'
|
endNode: '流程结束',
|
||||||
|
log: {
|
||||||
|
title: '日志详情'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import { $t } from '../locales';
|
|||||||
import { failStrategyRecord, taskBatchStatusEnum } from '../constants/business';
|
import { failStrategyRecord, taskBatchStatusEnum } from '../constants/business';
|
||||||
import TaskDrawer from '../drawer/task-drawer.vue';
|
import TaskDrawer from '../drawer/task-drawer.vue';
|
||||||
import TaskDetail from '../detail/task-detail.vue';
|
import TaskDetail from '../detail/task-detail.vue';
|
||||||
|
import DetailCard from '../components/detail-card.vue';
|
||||||
import AddNode from './add-node.vue';
|
import AddNode from './add-node.vue';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -271,7 +272,7 @@ const isStop = (taskBatchStatus: number) => {
|
|||||||
v-model:len="nodeConfig.conditionNodes!.length"
|
v-model:len="nodeConfig.conditionNodes!.length"
|
||||||
@save="save"
|
@save="save"
|
||||||
/>
|
/>
|
||||||
<!-- <DetailCard v-if="store.type !== 0 && cardDrawer" :id="detailId" v-model:open="cardDrawer" :ids="detailIds" /> -->
|
<DetailCard v-if="store.type !== 0" :id="detailId" v-model:show="cardDrawer" :ids="detailIds" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
44
packages/work-flow/src/typings/api.d.ts
vendored
44
packages/work-flow/src/typings/api.d.ts
vendored
@ -5,4 +5,48 @@ declare namespace FlowApi {
|
|||||||
id: string;
|
id: string;
|
||||||
jobName: 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;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
78
packages/work-flow/src/typings/flow.d.ts
vendored
78
packages/work-flow/src/typings/flow.d.ts
vendored
@ -7,6 +7,8 @@ declare namespace Flow {
|
|||||||
type ContentType = 1 | 2;
|
type ContentType = 1 | 2;
|
||||||
type TriggerType = 2 | 3;
|
type TriggerType = 2 | 3;
|
||||||
type WorkFlowNodeStatus = 0 | 1;
|
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 = {
|
export type NodeDataType = {
|
||||||
@ -121,4 +123,80 @@ declare namespace Flow {
|
|||||||
/** 图标 */
|
/** 图标 */
|
||||||
icon: string;
|
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;
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
44
packages/work-flow/src/typings/i18n.d.ts
vendored
44
packages/work-flow/src/typings/i18n.d.ts
vendored
@ -9,6 +9,7 @@ declare namespace FlowI18n {
|
|||||||
retry: string;
|
retry: string;
|
||||||
ignore: string;
|
ignore: string;
|
||||||
stop: string;
|
stop: string;
|
||||||
|
refresh: string;
|
||||||
failStrategy: string;
|
failStrategy: string;
|
||||||
form: {
|
form: {
|
||||||
groupName: string;
|
groupName: string;
|
||||||
@ -17,6 +18,26 @@ declare namespace FlowI18n {
|
|||||||
stopMessage: string;
|
stopMessage: string;
|
||||||
taskTip: 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: {
|
enum: {
|
||||||
failStrategy: {
|
failStrategy: {
|
||||||
skip: string;
|
skip: string;
|
||||||
@ -45,6 +66,26 @@ declare namespace FlowI18n {
|
|||||||
time: string;
|
time: string;
|
||||||
cron: 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: {
|
node: {
|
||||||
@ -81,6 +122,9 @@ declare namespace FlowI18n {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
endNode: string;
|
endNode: string;
|
||||||
|
log: {
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import NodeWrap from './components/node-wrap.vue';
|
import NodeWrap from './node/node-wrap.vue';
|
||||||
import StartNode from './components/start-node.vue';
|
import StartNode from './node/start-node.vue';
|
||||||
import { $t } from './locales';
|
import { $t } from './locales';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
|
@ -5,7 +5,7 @@ import { localStg } from '@/utils/storage';
|
|||||||
import systemLogo from '@/assets/svg-icon/logo.svg?raw';
|
import systemLogo from '@/assets/svg-icon/logo.svg?raw';
|
||||||
|
|
||||||
export function setupLoading() {
|
export function setupLoading() {
|
||||||
const themeColor = localStg.get('themeColor') || '#22aae3';
|
const themeColor = localStg.get('themeColor') || '#1366FF';
|
||||||
|
|
||||||
const { r, g, b } = getRgb(themeColor);
|
const { r, g, b } = getRgb(themeColor);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user