feat: [工作流] Simple 模型 - 审批人节点监听器配置
parent
8e111921dd
commit
db63d80338
|
@ -0,0 +1,228 @@
|
|||
<script setup lang="ts">
|
||||
import type { HttpRequestParam } from '../../../consts';
|
||||
|
||||
import { Plus, Trash2 } from '@vben/icons';
|
||||
|
||||
import {
|
||||
Button,
|
||||
Col,
|
||||
FormItem,
|
||||
Input,
|
||||
Row,
|
||||
Select,
|
||||
SelectOption,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
import {
|
||||
BPM_HTTP_REQUEST_PARAM_TYPES,
|
||||
BpmHttpRequestParamTypeEnum,
|
||||
} from '../../../consts';
|
||||
import { useFormFieldsAndStartUser } from '../../../helpers';
|
||||
|
||||
defineOptions({ name: 'HttpRequestParamSetting' });
|
||||
|
||||
const props = defineProps({
|
||||
header: {
|
||||
type: Array as () => HttpRequestParam[],
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
body: {
|
||||
type: Array as () => HttpRequestParam[],
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
bind: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
// 流程表单字段,发起人字段
|
||||
const formFieldOptions = useFormFieldsAndStartUser();
|
||||
|
||||
/** 添加请求配置项 */
|
||||
const addHttpRequestParam = (arr: HttpRequestParam[]) => {
|
||||
arr.push({
|
||||
key: '',
|
||||
type: BpmHttpRequestParamTypeEnum.FIXED_VALUE,
|
||||
value: '',
|
||||
});
|
||||
};
|
||||
|
||||
/** 删除请求配置项 */
|
||||
const deleteHttpRequestParam = (arr: HttpRequestParam[], index: number) => {
|
||||
arr.splice(index, 1);
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<FormItem
|
||||
label="请求头"
|
||||
:label-col="{ span: 24 }"
|
||||
:wrapper-col="{ span: 24 }"
|
||||
>
|
||||
<Row :gutter="8" v-for="(item, index) in props.header" :key="index">
|
||||
<Col :span="7">
|
||||
<FormItem
|
||||
:name="`${bind}.header.${index}.key`"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: '参数名不能为空',
|
||||
trigger: 'blur',
|
||||
}"
|
||||
>
|
||||
<Input placeholder="参数名不能为空" v-model:value="item.key" />
|
||||
</FormItem>
|
||||
</Col>
|
||||
<Col :span="5">
|
||||
<Select v-model:value="item.type">
|
||||
<SelectOption
|
||||
v-for="types in BPM_HTTP_REQUEST_PARAM_TYPES"
|
||||
:key="types.value"
|
||||
:label="types.label"
|
||||
:value="types.value"
|
||||
>
|
||||
{{ types.label }}
|
||||
</SelectOption>
|
||||
</Select>
|
||||
</Col>
|
||||
<Col :span="10">
|
||||
<FormItem
|
||||
:name="`${bind}.header.${index}.value`"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: '参数值不能为空',
|
||||
trigger: 'blur',
|
||||
}"
|
||||
v-if="item.type === BpmHttpRequestParamTypeEnum.FIXED_VALUE"
|
||||
>
|
||||
<Input placeholder="请求头" v-model:value="item.value" />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
:name="`${bind}.header.${index}.value`"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: '参数值不能为空',
|
||||
trigger: 'change',
|
||||
}"
|
||||
v-if="item.type === BpmHttpRequestParamTypeEnum.FROM_FORM"
|
||||
>
|
||||
<Select v-model:value="item.value" placeholder="请选择表单字段">
|
||||
<SelectOption
|
||||
v-for="(field, fIdx) in formFieldOptions"
|
||||
:key="fIdx"
|
||||
:label="field.title"
|
||||
:value="field.field"
|
||||
:disabled="!field.required"
|
||||
>
|
||||
{{ field.title }}
|
||||
</SelectOption>
|
||||
</Select>
|
||||
</FormItem>
|
||||
</Col>
|
||||
<Col :span="2">
|
||||
<div class="flex h-[32px] items-center">
|
||||
<Trash2
|
||||
class="size-4 cursor-pointer text-red-500"
|
||||
@click="deleteHttpRequestParam(props.header, index)"
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
<Button
|
||||
type="link"
|
||||
@click="addHttpRequestParam(props.header)"
|
||||
class="flex items-center"
|
||||
>
|
||||
<template #icon>
|
||||
<Plus class="size-[18px]" />
|
||||
</template>
|
||||
添加一行
|
||||
</Button>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label="请求体"
|
||||
:label-col="{ span: 24 }"
|
||||
:wrapper-col="{ span: 24 }"
|
||||
>
|
||||
<Row :gutter="8" v-for="(item, index) in props.body" :key="index">
|
||||
<Col :span="7">
|
||||
<FormItem
|
||||
:name="`${bind}.body.${index}.key`"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: '参数名不能为空',
|
||||
trigger: 'blur',
|
||||
}"
|
||||
>
|
||||
<Input placeholder="参数名" v-model:value="item.key" />
|
||||
</FormItem>
|
||||
</Col>
|
||||
<Col :span="5">
|
||||
<Select v-model:value="item.type">
|
||||
<SelectOption
|
||||
v-for="types in BPM_HTTP_REQUEST_PARAM_TYPES"
|
||||
:key="types.value"
|
||||
:label="types.label"
|
||||
:value="types.value"
|
||||
>
|
||||
{{ types.label }}
|
||||
</SelectOption>
|
||||
</Select>
|
||||
</Col>
|
||||
<Col :span="10">
|
||||
<FormItem
|
||||
:name="`${bind}.body.${index}.value`"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: '参数值不能为空',
|
||||
trigger: 'blur',
|
||||
}"
|
||||
v-if="item.type === BpmHttpRequestParamTypeEnum.FIXED_VALUE"
|
||||
>
|
||||
<Input placeholder="参数值" v-model:value="item.value" />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
:name="`${bind}.body.${index}.value`"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: '参数值不能为空',
|
||||
trigger: 'change',
|
||||
}"
|
||||
v-if="item.type === BpmHttpRequestParamTypeEnum.FROM_FORM"
|
||||
>
|
||||
<Select v-model:value="item.value" placeholder="请选择表单字段">
|
||||
<SelectOption
|
||||
v-for="(field, fIdx) in formFieldOptions"
|
||||
:key="fIdx"
|
||||
:label="field.title"
|
||||
:value="field.field"
|
||||
:disabled="!field.required"
|
||||
>
|
||||
{{ field.title }}
|
||||
</SelectOption>
|
||||
</Select>
|
||||
</FormItem>
|
||||
</Col>
|
||||
<Col :span="2">
|
||||
<div class="flex h-[32px] items-center">
|
||||
<Trash2
|
||||
class="size-4 cursor-pointer text-red-500"
|
||||
@click="deleteHttpRequestParam(props.body, index)"
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
<Button
|
||||
type="link"
|
||||
@click="addHttpRequestParam(props.body)"
|
||||
class="flex items-center"
|
||||
>
|
||||
<template #icon>
|
||||
<Plus class="size-[18px]" />
|
||||
</template>
|
||||
添加一行
|
||||
</Button>
|
||||
</FormItem>
|
||||
</template>
|
||||
<style lang="scss" scoped></style>
|
|
@ -0,0 +1,107 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import {
|
||||
Alert,
|
||||
Divider,
|
||||
Form,
|
||||
FormItem,
|
||||
Input,
|
||||
Switch,
|
||||
TypographyText,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
import HttpRequestParamSetting from './http-request-param-setting.vue';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
formFieldOptions: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
const listenerFormRef = ref();
|
||||
const configForm = computed({
|
||||
get() {
|
||||
return props.modelValue;
|
||||
},
|
||||
set(newValue) {
|
||||
emit('update:modelValue', newValue);
|
||||
},
|
||||
});
|
||||
const taskListener = ref([
|
||||
{
|
||||
name: '创建任务',
|
||||
type: 'Create',
|
||||
},
|
||||
{
|
||||
name: '指派任务执行人员',
|
||||
type: 'Assign',
|
||||
},
|
||||
{
|
||||
name: '完成任务',
|
||||
type: 'Complete',
|
||||
},
|
||||
]);
|
||||
|
||||
const validate = async () => {
|
||||
if (!listenerFormRef.value) return false;
|
||||
return await listenerFormRef.value.validate();
|
||||
};
|
||||
|
||||
defineExpose({ validate });
|
||||
</script>
|
||||
<template>
|
||||
<Form ref="listenerFormRef" :model="configForm" :label-col="{ span: 24 }">
|
||||
<div
|
||||
v-for="(listener, listenerIdx) in taskListener"
|
||||
:key="listenerIdx"
|
||||
class="pl-2"
|
||||
>
|
||||
<Divider orientation="left">
|
||||
<TypographyText tag="b" size="large">
|
||||
{{ listener.name }}
|
||||
</TypographyText>
|
||||
</Divider>
|
||||
<FormItem>
|
||||
<Switch
|
||||
v-model:checked="configForm[`task${listener.type}ListenerEnable`]"
|
||||
checked-children="开启"
|
||||
un-checked-children="关闭"
|
||||
/>
|
||||
</FormItem>
|
||||
<div v-if="configForm[`task${listener.type}ListenerEnable`]">
|
||||
<FormItem>
|
||||
<Alert
|
||||
message="仅支持 POST 请求,以请求体方式接收参数"
|
||||
type="warning"
|
||||
show-icon
|
||||
:closable="false"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label="请求地址"
|
||||
:name="`task${listener.type}ListenerPath`"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: '请求地址不能为空',
|
||||
trigger: 'blur',
|
||||
}"
|
||||
>
|
||||
<Input
|
||||
v-model:value="configForm[`task${listener.type}ListenerPath`]"
|
||||
/>
|
||||
</FormItem>
|
||||
<HttpRequestParamSetting
|
||||
:header="configForm[`task${listener.type}Listener`].header"
|
||||
:body="configForm[`task${listener.type}Listener`].body"
|
||||
:bind="`task${listener.type}Listener`"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
</template>
|
|
@ -34,7 +34,6 @@ import {
|
|||
TypographyText,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
// TODO import { defaultProps4AntTree } from '#/utils/tree';
|
||||
import {
|
||||
APPROVE_METHODS,
|
||||
APPROVE_TYPE,
|
||||
|
@ -65,10 +64,9 @@ import {
|
|||
useNodeName,
|
||||
useWatchNode,
|
||||
} from '../../helpers';
|
||||
import UserTaskListener from './modules/user-task-listener.vue';
|
||||
import { convertTimeUnit, getApproveTypeText } from './utils';
|
||||
|
||||
// TODO import UserTaskListener from './components/UserTaskListener.vue';
|
||||
|
||||
defineOptions({ name: 'UserTaskNodeConfig' });
|
||||
const props = defineProps({
|
||||
flowNode: {
|
||||
|
@ -233,8 +231,7 @@ const {
|
|||
cTimeoutMaxRemindCount,
|
||||
} = useTimeoutHandler();
|
||||
|
||||
// TODO 监听器待实现
|
||||
// const userTaskListenerRef = ref();
|
||||
const userTaskListenerRef = ref();
|
||||
|
||||
/** 节点类型名称 */
|
||||
const nodeTypeName = computed(() => {
|
||||
|
@ -253,25 +250,20 @@ const saveConfig = async () => {
|
|||
drawerApi.close();
|
||||
return true;
|
||||
}
|
||||
// TODO 监听器待实现
|
||||
// activeTabName.value = 'listener';
|
||||
// await nextTick();
|
||||
activeTabName.value = 'user';
|
||||
|
||||
if (!formRef.value) return false;
|
||||
// TODO 监听器待实现
|
||||
// if (!userTaskListenerRef.value) return false;
|
||||
// const valid =
|
||||
// (await formRef.value.validate()) &&
|
||||
// (await userTaskListenerRef.value.validate());
|
||||
if (!userTaskListenerRef.value) return false;
|
||||
|
||||
if (!(await formRef.value.validate())) {
|
||||
activeTabName.value = 'user';
|
||||
// 校验监听器页面, TODO 在别的Tab 好像跳不到这个页面
|
||||
if (!(await userTaskListenerRef.value.validate())) {
|
||||
activeTabName.value = 'listener';
|
||||
return false;
|
||||
}
|
||||
// 校验审批人页面
|
||||
if (!(await formRef.value.validate())) {
|
||||
// TODO 好像走不到这里
|
||||
activeTabName.value = 'user';
|
||||
return false;
|
||||
}
|
||||
// TODO 监听器待实现
|
||||
// if (!(await userTaskListenerRef.value.validate())) {
|
||||
// activeTabName.value = 'listener';
|
||||
// }
|
||||
|
||||
const showText = getShowText();
|
||||
if (!showText) return false;
|
||||
|
@ -658,10 +650,14 @@ onMounted(() => {
|
|||
label="指定部门"
|
||||
name="deptIds"
|
||||
>
|
||||
<!-- TODO :replace-fields="defaultProps4AntTree" -->
|
||||
<TreeSelect
|
||||
v-model:value="configForm.deptIds"
|
||||
:tree-data="deptTreeOptions"
|
||||
:field-names="{
|
||||
label: 'name',
|
||||
value: 'id',
|
||||
children: 'children',
|
||||
}"
|
||||
empty-text="加载中,请稍后"
|
||||
multiple
|
||||
node-key="id"
|
||||
|
@ -1226,13 +1222,11 @@ onMounted(() => {
|
|||
</div>
|
||||
</TabPane>
|
||||
<TabPane tab="监听器" key="listener">
|
||||
<!-- TODO 待实现 -->
|
||||
<span>待实现</span>
|
||||
<!-- <UserTaskListener
|
||||
<UserTaskListener
|
||||
ref="userTaskListenerRef"
|
||||
v-model:value="configForm"
|
||||
v-model="configForm"
|
||||
:form-field-options="formFieldOptions"
|
||||
/> -->
|
||||
/>
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
<template #footer>
|
||||
|
|
Loading…
Reference in New Issue