feat: 工作流新增任务表单抽屉
This commit is contained in:
commit
9b79d41ecb
@ -40,7 +40,7 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NPopover trigger="click" placement="bottom-start">
|
||||
<NPopover class="cron-popover" trigger="click" placement="bottom-start">
|
||||
<template #trigger>
|
||||
<NInput v-bind="attrs" v-model:value="cron" />
|
||||
</template>
|
||||
@ -49,10 +49,7 @@ defineExpose({
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.n-popover {
|
||||
.cron-popover {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.n-popover .n-popover-shared .n-popover-arrow-wrapper .n-popover-arrow {
|
||||
}
|
||||
</style>
|
||||
|
@ -39,6 +39,14 @@ export function fetchAddWorkflow(data: Flow.NodeDataType) {
|
||||
});
|
||||
}
|
||||
|
||||
export function fetchUpdateWorkflow(data: Flow.NodeDataType) {
|
||||
return request<null>({
|
||||
url: `/workflow`,
|
||||
method: 'put',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
export function fetchWorkflowInfo(id: string) {
|
||||
return request<Flow.NodeDataType>({
|
||||
url: `/workflow/${id}`,
|
||||
|
60
packages/work-flow/src/common/editable-input.vue
Normal file
60
packages/work-flow/src/common/editable-input.vue
Normal file
@ -0,0 +1,60 @@
|
||||
<script setup lang="ts">
|
||||
import type { InputInst } from 'naive-ui';
|
||||
import { nextTick, ref, watch } from 'vue';
|
||||
|
||||
defineOptions({
|
||||
name: 'EditableInput'
|
||||
});
|
||||
|
||||
interface Props {
|
||||
modelValue?: string;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
interface Emits {
|
||||
(e: 'update:modelValue', modelValue: string): void;
|
||||
}
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const inputRef = ref<InputInst>();
|
||||
const value = ref();
|
||||
const idEdit = ref<boolean>(false);
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
val => {
|
||||
value.value = val;
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
const edit = () => {
|
||||
idEdit.value = true;
|
||||
nextTick(() => {
|
||||
inputRef.value?.focus();
|
||||
});
|
||||
};
|
||||
|
||||
const save = () => {
|
||||
emit('update:modelValue', value.value!);
|
||||
idEdit.value = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NInput v-if="idEdit" ref="inputRef" v-model:value="value" type="text" @blur="save" />
|
||||
<NEllipsis v-else>
|
||||
<span class="flex items-center">
|
||||
{{ value }}
|
||||
<NButton text type="info" class="m-l-6px" @click="edit">
|
||||
<template #icon>
|
||||
<icon-ant-design:edit-outlined class="text-icon" />
|
||||
</template>
|
||||
</NButton>
|
||||
</span>
|
||||
</NEllipsis>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
@ -156,7 +156,7 @@ const getClass = (item: Flow.ConditionNodeType) => {
|
||||
<template v-if="item.callback?.webhook">
|
||||
<div class="flex justify-between">
|
||||
<span class="content_label">Webhook:</span>
|
||||
<NEllipsis class="w-116px">{{ item.callback.webhook }}</NEllipsis>
|
||||
<NEllipsis class="max-w-116px">{{ item.callback.webhook }}</NEllipsis>
|
||||
</div>
|
||||
<div>
|
||||
<span class="content_label">{{ $t('node.callback.conditionNodes.contentType') }}:</span>
|
||||
|
@ -88,18 +88,18 @@ const show = () => {
|
||||
</div>
|
||||
<div v-if="nodeData.groupName" class="content">
|
||||
<div>
|
||||
<span class="content_label">{{ $t('snail.groupName') }}:</span>
|
||||
<NEllipsis class="w-135px">
|
||||
<span class="content_label">{{ $t('snail.groupName') }}: </span>
|
||||
<NEllipsis class="max-w-132px">
|
||||
{{ nodeData.groupName }}
|
||||
</NEllipsis>
|
||||
</div>
|
||||
<div>
|
||||
<span class="content_label">{{ $t('snail.blockStrategy') }}:</span>
|
||||
{{ blockStrategyRecord[nodeData.blockStrategy!] }}
|
||||
<span class="content_label">{{ $t('snail.blockStrategy') }}: </span>
|
||||
{{ $t(blockStrategyRecord[nodeData.blockStrategy!]) }}
|
||||
</div>
|
||||
<div>.........</div>
|
||||
</div>
|
||||
<div v-else class="content">
|
||||
<div v-else class="content min-h-85px">
|
||||
<span class="placeholder">{{ $t('snail.form.workflowTip') }}</span>
|
||||
</div>
|
||||
<NTooltip v-if="store.type === 2" trigger="hover">
|
||||
|
@ -5,6 +5,7 @@ import { fetchNodeRetry, fetchNodeStop } from '../api';
|
||||
import { useFlowStore } from '../stores';
|
||||
import { $t } from '../locales';
|
||||
import { failStrategyRecord, taskBatchStatusEnum } from '../constants/business';
|
||||
import TaskDrawer from '../drawer/task-drawer.vue';
|
||||
import AddNode from './add-node.vue';
|
||||
|
||||
defineOptions({
|
||||
@ -93,15 +94,15 @@ const index = ref<number>(0);
|
||||
const drawer = ref<boolean>(false);
|
||||
const form = ref<Flow.ConditionNodeType>({});
|
||||
|
||||
// const save = (val: Flow.ConditionNodeType) => {
|
||||
// const oldLevel = nodeConfig.value.conditionNodes![index.value].priorityLevel;
|
||||
// const newLevel = val.priorityLevel;
|
||||
// nodeConfig.value.conditionNodes![index.value] = val;
|
||||
// if (oldLevel !== newLevel) {
|
||||
// arrTransfer(index.value, newLevel! - oldLevel!);
|
||||
// }
|
||||
// emit('update:modelValue', nodeConfig.value);
|
||||
// };
|
||||
const save = (val: Flow.ConditionNodeType) => {
|
||||
const oldLevel = nodeConfig.value.conditionNodes![index.value].priorityLevel;
|
||||
const newLevel = val.priorityLevel;
|
||||
nodeConfig.value.conditionNodes![index.value] = val;
|
||||
if (oldLevel !== newLevel) {
|
||||
arrTransfer(index.value, newLevel! - oldLevel!);
|
||||
}
|
||||
emit('update:modelValue', nodeConfig.value);
|
||||
};
|
||||
|
||||
const show = (currentIndex: number) => {
|
||||
if (!props.disabled) {
|
||||
@ -214,16 +215,18 @@ const isStop = (taskBatchStatus: number) => {
|
||||
<span class="priority-title">{{ $t('node.priority') }}{{ item.priorityLevel }}</span>
|
||||
<icon-ant-design:close-outlined v-if="!disabled" class="close" @click.stop="delTerm(i)" />
|
||||
</div>
|
||||
<div class="content min-h-81px">
|
||||
<div class="content min-h-72px">
|
||||
<div v-if="!item.jobTask?.jobId" class="placeholder">{{ $t('snail.form.taskTip') }}</div>
|
||||
<template v-if="item.jobTask?.jobId">
|
||||
<div>
|
||||
<span class="content_label">{{ $t('snail.taskName') }}:</span>
|
||||
<NEllipsis class="w-126px">{{ `${item.jobTask?.jobName}(${item.jobTask?.jobId})` }}</NEllipsis>
|
||||
<span class="content_label">{{ $t('snail.taskName') }}: </span>
|
||||
<NEllipsis class="max-w-123px">
|
||||
{{ `${item.jobTask?.jobName}(${item.jobTask?.jobId})` }}
|
||||
</NEllipsis>
|
||||
</div>
|
||||
<div>
|
||||
<span class="content_label">{{ $t('snail.failStrategy') }} :</span>
|
||||
{{ failStrategyRecord[item.failStrategy!] }}
|
||||
<span class="content_label">{{ $t('snail.failStrategy') }}: </span>
|
||||
{{ $t(failStrategyRecord[item.failStrategy!]) }}
|
||||
</div>
|
||||
<div>.........</div>
|
||||
</template>
|
||||
@ -266,16 +269,15 @@ const isStop = (taskBatchStatus: number) => {
|
||||
</div>
|
||||
</div>
|
||||
<AddNode v-if="nodeConfig.conditionNodes!.length > 1" v-model="nodeConfig.childNode!" :disabled="disabled" />
|
||||
<!--
|
||||
<TaskDrawer
|
||||
v-if="store.type === 0 && drawer"
|
||||
|
||||
<TaskDrawer
|
||||
v-if="store.type === 0"
|
||||
v-model:open="drawer"
|
||||
v-model="form"
|
||||
v-model:len="nodeConfig.conditionNodes!.length"
|
||||
@save="save"
|
||||
/>
|
||||
<DetailCard v-if="store.type !== 0 && cardDrawer" :id="detailId" v-model:open="cardDrawer" :ids="detailIds" />
|
||||
-->
|
||||
<!-- <DetailCard v-if="store.type !== 0 && cardDrawer" :id="detailId" v-model:open="cardDrawer" :ids="detailIds" /> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -44,8 +44,8 @@ export const triggerTypeRecord: Record<Flow.TriggerType, string> = {
|
||||
export const triggerTypeOptions = transformRecordToOption(triggerTypeRecord);
|
||||
|
||||
export const workFlowNodeStatusRecord: Record<Flow.WorkFlowNodeStatus, string> = {
|
||||
0: '关闭',
|
||||
1: '开启'
|
||||
0: 'snail.enum.workFlowNodeStatus.close',
|
||||
1: 'snail.enum.workFlowNodeStatus.open'
|
||||
};
|
||||
|
||||
export const workFlowNodeStatusOptions = transformRecordToOption(workFlowNodeStatusRecord);
|
||||
|
@ -7,9 +7,10 @@ import { $t } from '../locales';
|
||||
import { fetchGroupNameList } from '../api';
|
||||
import { isNotNull } from '../utils/common';
|
||||
import { useFlowStore } from '../stores';
|
||||
import EditableInput from '../common/editable-input.vue';
|
||||
|
||||
defineOptions({
|
||||
name: 'StartDetail'
|
||||
name: 'StartDrawer'
|
||||
});
|
||||
|
||||
interface Props {
|
||||
@ -49,6 +50,9 @@ watch(
|
||||
() => props.modelValue,
|
||||
val => {
|
||||
form.value = val;
|
||||
if (val.triggerType === 2) {
|
||||
form.value.triggerInterval = Number(val.triggerInterval);
|
||||
}
|
||||
if (val.workflowName) {
|
||||
title = val.workflowName;
|
||||
} else if (val.groupName) {
|
||||
@ -92,7 +96,7 @@ const typeChange = (value: number) => {
|
||||
if (value === 1) {
|
||||
form.value.triggerInterval = '* * * * * ?';
|
||||
} else if (value === 2) {
|
||||
form.value.triggerInterval = '60';
|
||||
form.value.triggerInterval = 60;
|
||||
}
|
||||
};
|
||||
|
||||
@ -116,10 +120,10 @@ const rules: Record<RuleKey, FormItemRule> = {
|
||||
<template>
|
||||
<NDrawer v-model:show="drawer" display-directive="if" :width="610" @after-leave="close">
|
||||
<NDrawerContent :title="title">
|
||||
<template #header>
|
||||
<EditableInput v-model="form.workflowName" class="max-w-570px min-w-570px" />
|
||||
</template>
|
||||
<NForm ref="formRef" :model="form" :rules="rules" label-align="left" label-width="100px">
|
||||
<NFormItem path="workflowName" label="工作流名称">
|
||||
<NInput v-model:value="form.workflowName" placeholder="请输入工作流名称" />
|
||||
</NFormItem>
|
||||
<NFormItem path="groupName" label="组名称">
|
||||
<NSelect
|
||||
v-model:value="form.groupName"
|
||||
@ -177,8 +181,8 @@ const rules: Record<RuleKey, FormItemRule> = {
|
||||
<NRadioGroup v-model:value="form.blockStrategy">
|
||||
<NSpace>
|
||||
<NRadio
|
||||
v-for="options in blockStrategyOptions"
|
||||
:key="options.value"
|
||||
v-for="(options, index) in blockStrategyOptions"
|
||||
:key="index"
|
||||
:label="$t(options.label)"
|
||||
:value="options.value"
|
||||
/>
|
||||
@ -191,8 +195,8 @@ const rules: Record<RuleKey, FormItemRule> = {
|
||||
<NRadioGroup v-model:value="form.workflowStatus">
|
||||
<NSpace>
|
||||
<NRadio
|
||||
v-for="options in workFlowNodeStatusOptions"
|
||||
:key="options.value"
|
||||
v-for="(options, index) in workFlowNodeStatusOptions"
|
||||
:key="index"
|
||||
:label="$t(options.label)"
|
||||
:value="options.value"
|
||||
/>
|
||||
|
164
packages/work-flow/src/drawer/task-drawer.vue
Normal file
164
packages/work-flow/src/drawer/task-drawer.vue
Normal file
@ -0,0 +1,164 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue';
|
||||
import { type FormInst, useMessage } from 'naive-ui';
|
||||
import { useFlowStore } from '../stores';
|
||||
import { $t } from '../locales';
|
||||
import { failStrategyOptions, workFlowNodeStatusOptions } from '../constants/business';
|
||||
import EditableInput from '../common/editable-input.vue';
|
||||
|
||||
defineOptions({
|
||||
name: 'TaskDrawer'
|
||||
});
|
||||
|
||||
interface Props {
|
||||
modelValue?: Flow.ConditionNodeType;
|
||||
open?: boolean;
|
||||
len?: number;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
open: false,
|
||||
len: 0,
|
||||
modelValue: () => ({})
|
||||
});
|
||||
|
||||
interface Emits {
|
||||
(e: 'update:open', open: boolean): void;
|
||||
(e: 'save', form: Flow.ConditionNodeType): void;
|
||||
}
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const store = useFlowStore();
|
||||
const message = useMessage();
|
||||
const drawer = ref<boolean>(false);
|
||||
const form = ref<Flow.ConditionNodeType>({});
|
||||
const jobList = ref<{ id: string; jobName: string }[]>([]);
|
||||
|
||||
watch(
|
||||
() => store.jobList,
|
||||
val => {
|
||||
jobList.value = val;
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.open,
|
||||
val => {
|
||||
drawer.value = val;
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
val => {
|
||||
form.value = val;
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
|
||||
const formRef = ref<FormInst>();
|
||||
|
||||
const close = () => {
|
||||
emit('update:open', false);
|
||||
drawer.value = false;
|
||||
};
|
||||
|
||||
const save = () => {
|
||||
formRef.value?.validate(errors => {
|
||||
if (!errors) {
|
||||
close();
|
||||
emit('save', form.value);
|
||||
} else {
|
||||
message.warning('请检查表单信息');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const rules = {
|
||||
failStrategy: [{ required: true, message: '请选择失败策略' }],
|
||||
workflowNodeStatus: [{ required: true, message: '请选择工作流状态' }],
|
||||
jobTask: {
|
||||
jobId: [{ required: true, message: '请选择任务' }]
|
||||
}
|
||||
};
|
||||
|
||||
const jobTaskChange = (_: string, option: { label: string; value: number }) => {
|
||||
form.value.jobTask!.jobName = option.label;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NDrawer v-model:show="drawer" display-directive="if" :width="500" @after-leave="close">
|
||||
<NDrawerContent>
|
||||
<template #header>
|
||||
<div class="w-460px flex-center">
|
||||
<EditableInput v-model="form.nodeName" class="mr-16px max-w-320px min-w-320px" />
|
||||
|
||||
<NSelect
|
||||
v-model:value="form.priorityLevel"
|
||||
class="max-w-110px"
|
||||
:options="
|
||||
Array(len)
|
||||
.fill(0)
|
||||
.map((_, index) => {
|
||||
return {
|
||||
label: '优先级 ' + (index + 1),
|
||||
value: index + 1
|
||||
};
|
||||
})
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<NForm ref="formRef" :model="form" :rules="rules" label-align="left" label-width="100px">
|
||||
<NFormItem path="jobTask.jobId" label="所属任务" placeholder="请选择任务">
|
||||
<NSelect
|
||||
v-model:value="form.jobTask!.jobId"
|
||||
:options="
|
||||
jobList.map(job => {
|
||||
return {
|
||||
label: job.jobName,
|
||||
value: job.id
|
||||
};
|
||||
})
|
||||
"
|
||||
@update:value="jobTaskChange"
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem path="failStrategy" label="失败策略">
|
||||
<NRadioGroup v-model:value="form.failStrategy">
|
||||
<NSpace>
|
||||
<NRadio
|
||||
v-for="(options, index) in failStrategyOptions"
|
||||
:key="index"
|
||||
:label="$t(options.label)"
|
||||
:value="options.value"
|
||||
/>
|
||||
</NSpace>
|
||||
</NRadioGroup>
|
||||
</NFormItem>
|
||||
<NFormItem path="workflowNodeStatus" label="节点状态">
|
||||
<NRadioGroup v-model:value="form.workflowNodeStatus">
|
||||
<NSpace>
|
||||
<NRadio
|
||||
v-for="(options, index) in workFlowNodeStatusOptions"
|
||||
:key="index"
|
||||
:label="$t(options.label)"
|
||||
:value="options.value"
|
||||
/>
|
||||
</NSpace>
|
||||
</NRadioGroup>
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
|
||||
<template #footer>
|
||||
<NButton type="primary" @click="save">保存</NButton>
|
||||
<NButton class="ml-12px" @click="close">取消</NButton>
|
||||
</template>
|
||||
</NDrawerContent>
|
||||
</NDrawer>
|
||||
</template>
|
@ -33,6 +33,14 @@ const local: FlowI18n.Schema = {
|
||||
cancel: 'Cancel',
|
||||
decisionFailed: 'Decision Failed',
|
||||
skip: 'Skip'
|
||||
},
|
||||
workFlowNodeStatus: {
|
||||
open: 'Open',
|
||||
close: 'Close'
|
||||
},
|
||||
triggerType: {
|
||||
time: 'Fixed Time',
|
||||
cron: 'CRON Expressions'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -33,6 +33,14 @@ const local: FlowI18n.Schema = {
|
||||
cancel: '取消',
|
||||
decisionFailed: '判定未通过',
|
||||
skip: '跳过'
|
||||
},
|
||||
workFlowNodeStatus: {
|
||||
open: '开启',
|
||||
close: '关闭'
|
||||
},
|
||||
triggerType: {
|
||||
time: '固定时间',
|
||||
cron: 'CRON 表达式'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -595,7 +595,7 @@
|
||||
}
|
||||
|
||||
.end-node .end-node-text {
|
||||
color: #ccc;
|
||||
color: #d6d6d6;
|
||||
}
|
||||
|
||||
.auto-judge .sort-left:hover,
|
||||
@ -608,4 +608,8 @@
|
||||
.add-branch {
|
||||
background-color: #3e5a2d;
|
||||
}
|
||||
|
||||
.content {
|
||||
color: #d6d6d6;
|
||||
}
|
||||
}
|
||||
|
8
packages/work-flow/src/typings/i18n.d.ts
vendored
8
packages/work-flow/src/typings/i18n.d.ts
vendored
@ -37,6 +37,14 @@ declare namespace FlowI18n {
|
||||
decisionFailed: string;
|
||||
skip: string;
|
||||
};
|
||||
workFlowNodeStatus: {
|
||||
open: string;
|
||||
close: string;
|
||||
};
|
||||
triggerType: {
|
||||
time: string;
|
||||
cron: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
node: {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { BACKEND_ERROR_CODE, createFlatRequest } from '@sa/axios';
|
||||
import { localStg } from './storage';
|
||||
|
||||
const baseURL = '/proxy-default';
|
||||
const baseURL = '/snail-job';
|
||||
|
||||
export const request = createFlatRequest<Service.Response>(
|
||||
{
|
||||
|
@ -66,7 +66,7 @@ export function getServiceBaseURL(env: Env.ImportMeta, isProxy: boolean) {
|
||||
*/
|
||||
function createProxyPattern(key?: App.Service.OtherBaseURLKey) {
|
||||
if (!key) {
|
||||
return '/proxy-default';
|
||||
return '/snail-job';
|
||||
}
|
||||
|
||||
return `/proxy-${key}`;
|
||||
|
@ -9,6 +9,8 @@ defineOptions({
|
||||
name: 'PwdLogin'
|
||||
});
|
||||
|
||||
const devMode = import.meta.env.DEV;
|
||||
|
||||
const authStore = useAuthStore();
|
||||
const { formRef, validate } = useNaiveForm();
|
||||
const { defaultRequiredRule } = useFormRules();
|
||||
@ -19,8 +21,8 @@ interface FormModel {
|
||||
}
|
||||
|
||||
const model: FormModel = reactive({
|
||||
userName: 'admin',
|
||||
password: 'admin'
|
||||
userName: devMode ? 'admin' : '',
|
||||
password: devMode ? 'admin' : ''
|
||||
});
|
||||
|
||||
type RuleKey = Extract<keyof FormModel, 'userName' | 'password'>;
|
||||
|
@ -52,7 +52,7 @@ const model: Model = reactive(createDefaultModel());
|
||||
function createDefaultModel(): Model {
|
||||
return {
|
||||
groupName: '',
|
||||
token: generateToken(32),
|
||||
token: import.meta.env.VITE_APP_DEFAULT_TOKEN || '',
|
||||
groupStatus: 1,
|
||||
description: '',
|
||||
idGeneratorMode: 2,
|
||||
|
@ -351,11 +351,7 @@ watch(visible, () => {
|
||||
<NGrid cols="2 s:1 m:2" responsive="screen" x-gap="20">
|
||||
<NGi>
|
||||
<NFormItem :label="$t('page.jobTask.triggerType')" path="triggerType">
|
||||
<TriggerType
|
||||
v-model:value="model.triggerType"
|
||||
:placeholder="$t('page.jobTask.form.triggerType')"
|
||||
@update:value="model.triggerInterval = ''"
|
||||
/>
|
||||
<TriggerType v-model:value="model.triggerType" :placeholder="$t('page.jobTask.form.triggerType')" />
|
||||
</NFormItem>
|
||||
</NGi>
|
||||
<NGi>
|
||||
|
@ -28,13 +28,8 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
|
||||
taskBatchStatus: null
|
||||
},
|
||||
columns: () => [
|
||||
// {
|
||||
// type: 'selection',
|
||||
// align: 'center',
|
||||
// width: 48
|
||||
// },
|
||||
{
|
||||
key: 'index',
|
||||
key: 'id',
|
||||
title: $t('common.index'),
|
||||
align: 'center',
|
||||
width: 120
|
||||
|
@ -2,6 +2,7 @@
|
||||
import { onMounted, ref } from 'vue';
|
||||
import Workflow, { flowFetch, flowStores } from '@sa/workflow';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { $t } from '@/locales';
|
||||
|
||||
const store = flowStores.useFlowStore();
|
||||
const router = useRouter();
|
||||
@ -16,6 +17,7 @@ onMounted(() => {
|
||||
});
|
||||
|
||||
const node = ref<Flow.NodeDataType>({
|
||||
workflowName: `Workflow ${new Date().getTime()}`,
|
||||
workflowStatus: 1,
|
||||
blockStrategy: 1,
|
||||
description: undefined,
|
||||
@ -25,7 +27,7 @@ const node = ref<Flow.NodeDataType>({
|
||||
const save = async () => {
|
||||
const { error } = await flowFetch.fetchAddWorkflow(node.value);
|
||||
if (!error) {
|
||||
window.$message?.success('工作流新增成功');
|
||||
window.$message?.info($t('common.addSuccess'));
|
||||
router.push('/workflow/task');
|
||||
}
|
||||
};
|
||||
|
@ -1,17 +1,52 @@
|
||||
<script setup lang="ts">
|
||||
import WorkFlowIframe from '../modules/workflow-iframe.vue';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import Workflow, { flowFetch, flowStores } from '@sa/workflow';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { $t } from '@/locales';
|
||||
|
||||
defineOptions({
|
||||
name: 'WorkFlowEdit'
|
||||
const store = flowStores.useFlowStore();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const spinning = ref(false);
|
||||
const disabled = ref(false);
|
||||
|
||||
const id: string = String(route.query.id);
|
||||
|
||||
const node = ref<Flow.NodeDataType>({});
|
||||
|
||||
const getDetail = async () => {
|
||||
spinning.value = true;
|
||||
const { data, error } = await flowFetch.fetchWorkflowInfo(id);
|
||||
if (!error) {
|
||||
node.value = data;
|
||||
}
|
||||
spinning.value = false;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
store.clear();
|
||||
store.setType(0);
|
||||
store.setId(id);
|
||||
getDetail();
|
||||
disabled.value = false;
|
||||
});
|
||||
|
||||
const update = async () => {
|
||||
const { error } = await flowFetch.fetchUpdateWorkflow(node.value);
|
||||
if (!error) {
|
||||
window.$message?.info($t('common.updateSuccess'));
|
||||
router.push({ path: '/workflow/task' });
|
||||
}
|
||||
};
|
||||
|
||||
const cancel = () => {
|
||||
router.push('/workflow/task');
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="iframe"><WorkFlowIframe value="D7Rzd7Oe" /></div>
|
||||
<Workflow v-model="node" :spinning="spinning" :disabled="disabled" @save="update" @cancel="cancel" />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.iframe {
|
||||
padding: 0 !important;
|
||||
}
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
@ -81,7 +81,7 @@ onActivated(() => {
|
||||
<iframe
|
||||
ref="iframeRef"
|
||||
class="size-full"
|
||||
:src="`${mode === 'prod' ? baseUrl : ''}/lib/index.html?id=${id}&mode=${mode}&x1c2Hdd6=${value}`"
|
||||
:src="`${mode === 'prod' ? baseUrl + '/' : '/'}lib/index.html?id=${id}&mode=${mode}&x1c2Hdd6=${value}`"
|
||||
/>
|
||||
</NSpin>
|
||||
</template>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script setup lang="tsx">
|
||||
import { NButton, NButtonGroup, NPopconfirm, NPopover, NTag } from 'naive-ui';
|
||||
import { NButton, NDropdown, NPopconfirm, NTag } from 'naive-ui';
|
||||
import { useRouter } from 'vue-router';
|
||||
import {
|
||||
fetchDelWorkflow,
|
||||
@ -38,7 +38,7 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
|
||||
// width: 48
|
||||
// },
|
||||
{
|
||||
key: 'index',
|
||||
key: 'id',
|
||||
title: $t('common.index'),
|
||||
align: 'center',
|
||||
width: 120
|
||||
@ -129,17 +129,50 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
|
||||
fixed: 'right',
|
||||
width: 200,
|
||||
render: row => {
|
||||
const options = [
|
||||
{
|
||||
label: $t('common.execute'),
|
||||
key: 'execute',
|
||||
click: () => execute(row.id!)
|
||||
},
|
||||
{
|
||||
type: 'divider',
|
||||
key: 'd1'
|
||||
},
|
||||
{
|
||||
label: $t('common.copy'),
|
||||
key: 'copy',
|
||||
click: () => copy(row.id!)
|
||||
},
|
||||
{
|
||||
type: 'divider',
|
||||
key: 'd2'
|
||||
},
|
||||
{
|
||||
label: $t('common.batchList'),
|
||||
key: 'batchList',
|
||||
click: () => batch(row.id!)
|
||||
}
|
||||
];
|
||||
|
||||
function onSelect(key: string) {
|
||||
options.filter(o => o.key === key)[0].click!();
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="flex-center gap-8px">
|
||||
<NButton type="warning" ghost size="small" onClick={() => edit(row.id!)}>
|
||||
<NButton text type="warning" ghost size="small" onClick={() => edit(row.id!)}>
|
||||
{$t('common.edit')}
|
||||
</NButton>
|
||||
|
||||
<n-divider vertical />
|
||||
|
||||
{hasAuth('R_ADMIN') ? (
|
||||
<NPopconfirm onPositiveClick={() => handleDelete(row.id!)}>
|
||||
{{
|
||||
default: () => $t('common.confirmDelete'),
|
||||
trigger: () => (
|
||||
<NButton type="error" ghost size="small">
|
||||
<NButton text type="error" ghost size="small">
|
||||
{$t('common.delete')}
|
||||
</NButton>
|
||||
)
|
||||
@ -149,30 +182,17 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
|
||||
''
|
||||
)}
|
||||
|
||||
<NPopover trigger="click" placement="bottom" raw show-arrow={false} class="b-rd-6px bg-#fff dark:bg-#000">
|
||||
<n-divider vertical />
|
||||
|
||||
<NDropdown trigger="click" show-arrow={false} options={options} size="small" on-select={onSelect}>
|
||||
{{
|
||||
trigger: () => (
|
||||
<NButton type="primary" ghost size="small">
|
||||
default: () => (
|
||||
<NButton text type="primary" ghost size="small">
|
||||
更多
|
||||
</NButton>
|
||||
),
|
||||
default: () => (
|
||||
<div>
|
||||
<NButtonGroup vertical>
|
||||
<NButton type="primary" ghost size="small" onClick={() => execute(row.id!)}>
|
||||
{$t('common.execute')}
|
||||
</NButton>
|
||||
<NButton type="primary" ghost size="small" onClick={() => copy(row.id!)}>
|
||||
{$t('common.copy')}
|
||||
</NButton>
|
||||
<NButton type="success" ghost size="small" onClick={() => batch(row.id!)}>
|
||||
{$t('common.batchList')}
|
||||
</NButton>
|
||||
</NButtonGroup>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</NPopover>
|
||||
</NDropdown>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -188,8 +208,6 @@ const {
|
||||
|
||||
async function handleBatchDelete() {
|
||||
// request
|
||||
console.log(checkedRowKeys.value);
|
||||
|
||||
onBatchDeleted();
|
||||
}
|
||||
|
||||
@ -207,7 +225,7 @@ function edit(id: string) {
|
||||
}
|
||||
|
||||
function handleAdd() {
|
||||
router.push({ path: '/workflow/form/edit' });
|
||||
router.push({ path: '/workflow/form/add' });
|
||||
}
|
||||
|
||||
function detail(id: string) {
|
||||
|
Loading…
Reference in New Issue
Block a user