feat(sj_map_reduce): 工作流批次详情新增实时刷新功能
This commit is contained in:
parent
8599258b1d
commit
0b78b17600
@ -32,21 +32,19 @@ const visible = defineModel<boolean>('show', {
|
|||||||
const syncTime = ref(1);
|
const syncTime = ref(1);
|
||||||
const logList = ref<Api.JobLog.JobMessage[]>([]);
|
const logList = ref<Api.JobLog.JobMessage[]>([]);
|
||||||
const interval = ref<NodeJS.Timeout>();
|
const interval = ref<NodeJS.Timeout>();
|
||||||
const controller = new AbortController();
|
let controller = new AbortController();
|
||||||
const finished = ref<boolean>(true);
|
const finished = ref<boolean>(true);
|
||||||
let startId = '0';
|
let startId = '0';
|
||||||
let fromIndex: number = 0;
|
let fromIndex: number = 0;
|
||||||
let axiosController = new AbortController();
|
|
||||||
|
|
||||||
const pauseLog = () => {
|
const pauseLog = () => {
|
||||||
finished.value = true;
|
finished.value = true;
|
||||||
controller.abort();
|
|
||||||
clearTimeout(interval.value);
|
clearTimeout(interval.value);
|
||||||
interval.value = undefined;
|
interval.value = undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
const stopLog = () => {
|
const stopLog = () => {
|
||||||
if (!finished.value) axiosController.abort();
|
if (!finished.value) controller.abort();
|
||||||
pauseLog();
|
pauseLog();
|
||||||
startId = '0';
|
startId = '0';
|
||||||
fromIndex = 0;
|
fromIndex = 0;
|
||||||
@ -68,7 +66,7 @@ async function getLogList() {
|
|||||||
fromIndex,
|
fromIndex,
|
||||||
size: 50
|
size: 50
|
||||||
},
|
},
|
||||||
axiosController
|
controller
|
||||||
);
|
);
|
||||||
logData = data;
|
logData = data;
|
||||||
logError = error;
|
logError = error;
|
||||||
@ -119,7 +117,7 @@ watch(
|
|||||||
|
|
||||||
if ((val || !props.drawer) && props.type && props.taskData) {
|
if ((val || !props.drawer) && props.type && props.taskData) {
|
||||||
finished.value = false;
|
finished.value = false;
|
||||||
axiosController = new AbortController();
|
controller = new AbortController();
|
||||||
await getLogList();
|
await getLogList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,7 +263,7 @@ const SnailLogComponent = defineComponent({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<NDrawer v-if="drawer" v-model:show="visible" width="100%" display-directive="if">
|
<NDrawer v-if="drawer" v-model:show="visible" width="100%" display-directive="if" :auto-focus="false">
|
||||||
<NDrawerContent closable>
|
<NDrawerContent closable>
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="flex-center">
|
<div class="flex-center">
|
||||||
@ -287,10 +285,10 @@ const SnailLogComponent = defineComponent({
|
|||||||
</NTooltip>
|
</NTooltip>
|
||||||
<span class="ml-6px">{{ title }}</span>
|
<span class="ml-6px">{{ title }}</span>
|
||||||
<ButtonIcon icon="hugeicons:share-01" tooltip-content="在新标签页打开" class="ml-6px" @click="openNewTab" />
|
<ButtonIcon icon="hugeicons:share-01" tooltip-content="在新标签页打开" class="ml-6px" @click="openNewTab" />
|
||||||
<NDropdown trigger="hover" :options="syncOptions" @select="handleSyncSelect">
|
<NDropdown trigger="hover" :options="syncOptions" width="trigger" @select="handleSyncSelect">
|
||||||
<NTooltip placement="right">
|
<NTooltip placement="right">
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<NButton quaternary class="ml-3px w-136px" @click="handleSyncSelect(-1)">
|
<NButton dashed class="ml-3px w-136px" @click="handleSyncSelect(-1)">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<div class="flex-center gap-8px">
|
<div class="flex-center gap-8px">
|
||||||
<icon-solar:refresh-outline class="text-18px" />
|
<icon-solar:refresh-outline class="text-18px" />
|
||||||
@ -311,10 +309,10 @@ const SnailLogComponent = defineComponent({
|
|||||||
<NCard v-else :bordered="false" :title="title" size="small" class="h-full sm:flex-1-hidden card-wrapper">
|
<NCard v-else :bordered="false" :title="title" size="small" class="h-full sm:flex-1-hidden card-wrapper">
|
||||||
<template #header-extra>
|
<template #header-extra>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<NDropdown trigger="hover" :options="syncOptions" @select="handleSyncSelect">
|
<NDropdown trigger="hover" :options="syncOptions" width="trigger" @select="handleSyncSelect">
|
||||||
<NTooltip placement="right">
|
<NTooltip placement="right">
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<NButton quaternary class="ml-3px w-136px" @click="handleSyncSelect(-1)">
|
<NButton dashed class="ml-3px w-136px" @click="handleSyncSelect(-1)">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<div class="flex-center gap-8px">
|
<div class="flex-center gap-8px">
|
||||||
<icon-solar:refresh-outline class="text-18px" />
|
<icon-solar:refresh-outline class="text-18px" />
|
||||||
|
@ -236,7 +236,7 @@ const onUpdatePage = (page: number) => {
|
|||||||
</NSpin>
|
</NSpin>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</NTabPane>
|
</NTabPane>
|
||||||
<NTabPane name="task">
|
<NTabPane name="task" :disabled="jobData.taskBatchStatus === 99">
|
||||||
<template #tab>
|
<template #tab>
|
||||||
<span>任务项列表</span>
|
<span>任务项列表</span>
|
||||||
</template>
|
</template>
|
||||||
@ -271,7 +271,7 @@ const onUpdatePage = (page: number) => {
|
|||||||
重试
|
重试
|
||||||
</NButton>
|
</NButton>
|
||||||
</template>
|
</template>
|
||||||
<JobTaskListTable class="mt-16px" :row-data="jobData as Api.JobBatch.JobBatch" @show-log="getLogRows" />
|
<JobTaskListTable class="mt-16px" :row-data="jobData as any" @show-log="getLogRows" />
|
||||||
</NCard>
|
</NCard>
|
||||||
</NTabPane>
|
</NTabPane>
|
||||||
</NTabs>
|
</NTabs>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, ref, watch } from 'vue';
|
import { onMounted, ref, useSlots, watch } from 'vue';
|
||||||
import VueDragResize from 'vue-drag-resize/src';
|
import VueDragResize from 'vue-drag-resize/src';
|
||||||
import { $t } from '@/locales';
|
import { $t } from '@/locales';
|
||||||
import NodeWrap from './modules/nodes/node-wrap.vue';
|
import NodeWrap from './modules/nodes/node-wrap.vue';
|
||||||
@ -29,6 +29,8 @@ interface Emits {
|
|||||||
|
|
||||||
const emit = defineEmits<Emits>();
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
|
const slots = useSlots();
|
||||||
|
|
||||||
const zoom = ref<number>(100);
|
const zoom = ref<number>(100);
|
||||||
const nodeData = ref<Workflow.NodeDataType>({});
|
const nodeData = ref<Workflow.NodeDataType>({});
|
||||||
|
|
||||||
@ -144,6 +146,9 @@ const onDragstop = () => {
|
|||||||
<NButton type="info" @click="save">保存</NButton>
|
<NButton type="info" @click="save">保存</NButton>
|
||||||
<NButton class="ml-16px" @click="cancel">取消</NButton>
|
<NButton class="ml-16px" @click="cancel">取消</NButton>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="disabled && slots.buttons" class="buttons">
|
||||||
|
<slot name="buttons"></slot>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</NAffix>
|
</NAffix>
|
||||||
<NSpin :show="spinning">
|
<NSpin :show="spinning">
|
||||||
|
2
src/typings/workflow.d.ts
vendored
2
src/typings/workflow.d.ts
vendored
@ -20,6 +20,8 @@ declare namespace Workflow {
|
|||||||
wfContexts?: { key: string; value: string | number | boolean; type: string }[];
|
wfContexts?: { key: string; value: string | number | boolean; type: string }[];
|
||||||
/** 工作流状态 */
|
/** 工作流状态 */
|
||||||
workflowStatus?: Api.Common.WorkFlowNodeStatus;
|
workflowStatus?: Api.Common.WorkFlowNodeStatus;
|
||||||
|
/** 工作流批次状态 */
|
||||||
|
workflowBatchStatus?: Api.Common.TaskBatchStatus;
|
||||||
/** 描述 */
|
/** 描述 */
|
||||||
description?: string;
|
description?: string;
|
||||||
/** 流程配置 */
|
/** 流程配置 */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, ref } from 'vue';
|
import { onBeforeUnmount, onMounted, ref } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import Workflow from '@/components/workflow';
|
import Workflow from '@/components/workflow';
|
||||||
import { useWorkflowStore } from '@/store/modules/workflow';
|
import { useWorkflowStore } from '@/store/modules/workflow';
|
||||||
@ -9,30 +9,144 @@ const store = useWorkflowStore();
|
|||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
const spinning = ref(false);
|
const spinning = ref(false);
|
||||||
|
|
||||||
const id: string = String(route.query.id);
|
const id: string = String(route.query.id);
|
||||||
|
|
||||||
const node = ref<Workflow.NodeDataType>({});
|
const node = ref<Workflow.NodeDataType>({});
|
||||||
|
const syncTime = ref(0);
|
||||||
|
const interval = ref<NodeJS.Timeout>();
|
||||||
|
const controller = new AbortController();
|
||||||
|
const finished = ref<boolean>(true);
|
||||||
|
|
||||||
|
const pauseBatch = () => {
|
||||||
|
finished.value = true;
|
||||||
|
controller.abort();
|
||||||
|
clearTimeout(interval.value);
|
||||||
|
interval.value = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const stopBatch = () => {
|
||||||
|
if (!finished.value) controller.abort();
|
||||||
|
pauseBatch();
|
||||||
|
node.value = {};
|
||||||
|
store.clear();
|
||||||
|
};
|
||||||
|
|
||||||
const getBatchDetail = async () => {
|
const getBatchDetail = async () => {
|
||||||
spinning.value = true;
|
spinning.value = true;
|
||||||
const { data, error } = await fetchWorkflowBatchInfo(id);
|
const { data, error } = await fetchWorkflowBatchInfo(id);
|
||||||
if (!error) {
|
if (!error) {
|
||||||
node.value = data;
|
node.value = data;
|
||||||
|
finished.value = !(data.workflowBatchStatus && [1, 2].includes(data.workflowBatchStatus));
|
||||||
|
if (!finished.value) {
|
||||||
|
clearTimeout(interval.value);
|
||||||
|
interval.value = setTimeout(getBatchDetail, syncTime.value * 1000);
|
||||||
|
}
|
||||||
|
} else if (error?.code !== 'ERR_CANCELED') {
|
||||||
|
stopBatch();
|
||||||
}
|
}
|
||||||
spinning.value = false;
|
spinning.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSyncSelect = async (time: number) => {
|
||||||
|
if (time === -1) {
|
||||||
|
if (finished.value) {
|
||||||
|
finished.value = false;
|
||||||
|
await getBatchDetail();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time === 0) {
|
||||||
|
pauseBatch();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
syncTime.value = time;
|
||||||
|
finished.value = false;
|
||||||
|
await getBatchDetail();
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
store.clear();
|
store.clear();
|
||||||
store.setType(2);
|
store.setType(2);
|
||||||
store.setId(id);
|
store.setId(id);
|
||||||
getBatchDetail();
|
getBatchDetail();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
stopBatch();
|
||||||
|
});
|
||||||
|
|
||||||
|
const syncOptions = ref([
|
||||||
|
{
|
||||||
|
label: 'Off',
|
||||||
|
key: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Auto(1s)',
|
||||||
|
key: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '5s',
|
||||||
|
key: 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '10s',
|
||||||
|
key: 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '30s',
|
||||||
|
key: 30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '1m',
|
||||||
|
key: 60
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '5m',
|
||||||
|
key: 300
|
||||||
|
}
|
||||||
|
]);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Workflow v-model="node" :spinning="spinning" disabled />
|
<Workflow v-model="node" :spinning="spinning" disabled>
|
||||||
|
<template #buttons>
|
||||||
|
<div class="flex-center">
|
||||||
|
<NDropdown trigger="hover" width="trigger" :options="syncOptions" @select="handleSyncSelect">
|
||||||
|
<NTooltip placement="left">
|
||||||
|
<template #trigger>
|
||||||
|
<NButton dashed class="mr-16px w-136px" @click="handleSyncSelect(-1)">
|
||||||
|
<template #icon>
|
||||||
|
<div class="flex-center gap-8px">
|
||||||
|
<icon-solar:refresh-outline class="text-18px" />
|
||||||
|
{{ syncOptions.filter(item => item.key === syncTime)[0].label }}
|
||||||
|
<SvgIcon icon="material-symbols:expand-more-rounded" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</NButton>
|
||||||
|
</template>
|
||||||
|
自动刷新频率
|
||||||
|
</NTooltip>
|
||||||
|
</NDropdown>
|
||||||
|
<NTooltip v-if="finished" placement="top">
|
||||||
|
<template #trigger>
|
||||||
|
<icon-material-symbols:check-circle class="text-20px color-success" />
|
||||||
|
</template>
|
||||||
|
流程批次加载完成
|
||||||
|
</NTooltip>
|
||||||
|
<NTooltip v-else>
|
||||||
|
<template #trigger>
|
||||||
|
<NSpin size="small">
|
||||||
|
<template #icon>
|
||||||
|
<icon-nonicons:loading-16 />
|
||||||
|
</template>
|
||||||
|
</NSpin>
|
||||||
|
</template>
|
||||||
|
流程批次正在加载
|
||||||
|
</NTooltip>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Workflow>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
Loading…
Reference in New Issue
Block a user