!108 Merge remote-tracking branch 'yudao/dev' into dev

Merge pull request !108 from Jason/dev
pull/109/MERGE
xingyu 2025-05-19 06:07:43 +00:00 committed by Gitee
commit ab0bcd8fbc
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
3 changed files with 215 additions and 19 deletions

View File

@ -1,6 +1,7 @@
<script setup lang="ts">
import type { BpmCategoryApi } from '#/api/bpm/category';
import type { BpmProcessDefinitionApi } from '#/api/bpm/definition';
import type { BpmFormApi } from '#/api/bpm/form';
import type { SystemDeptApi } from '#/api/system/dept';
import type { SystemUserApi } from '#/api/system/user';
@ -16,6 +17,7 @@ import { Button, Card, message } from 'ant-design-vue';
import { getCategorySimpleList } from '#/api/bpm/category';
import { getProcessDefinition } from '#/api/bpm/definition';
import { getFormSimpleList } from '#/api/bpm/form';
import {
createModel,
deployModel,
@ -26,6 +28,7 @@ import { getSimpleDeptList } from '#/api/system/dept';
import { getSimpleUserList } from '#/api/system/user';
import BasicInfo from './modules/basic-info.vue';
import FormDesign from './modules/form-design.vue';
defineOptions({ name: 'BpmModelCreate' });
@ -62,7 +65,9 @@ const route = useRoute();
const userStore = useUserStore();
//
const basicInfoRef = ref();
const basicInfoRef = ref<InstanceType<typeof BasicInfo>>();
//
const formDesignRef = ref<InstanceType<typeof FormDesign>>();
/** 步骤校验函数 */
const validateBasic = async () => {
@ -71,7 +76,7 @@ const validateBasic = async () => {
/** 表单设计校验 */
const validateForm = async () => {
// TODO
await formDesignRef.value?.validate();
};
/** 流程设计校验 */
@ -132,7 +137,7 @@ provide('processData', processData);
provide('modelData', formData);
//
// const formList = ref([])
const formList = ref<BpmFormApi.FormVO[]>([]);
const categoryList = ref<BpmCategoryApi.CategoryVO[]>([]);
const userList = ref<SystemUserApi.User[]>([]);
const deptList = ref<SystemDeptApi.Dept[]>([]);
@ -187,8 +192,8 @@ const initData = async () => {
formData.value.managerUserIds.push(userStore.userInfo?.userId);
}
// TODO
// formList.value = await getFormSimpleList()
//
formList.value = await getFormSimpleList();
categoryList.value = await getCategorySimpleList();
//
userList.value = await getSimpleUserList();
@ -393,9 +398,8 @@ onMounted(async () => {
/** 添加组件卸载前的清理 */
onBeforeUnmount(() => {
//
basicInfoRef.value = null;
// TODO
// formDesignRef.value = null;
basicInfoRef.value = undefined;
formDesignRef.value = undefined;
// processDesignRef.value = null;
});
</script>
@ -471,7 +475,7 @@ onBeforeUnmount(() => {
<Card :body-style="{ padding: '10px' }" class="mb-4">
<div class="mt-[50px]">
<!-- 第一步基本信息 -->
<div v-if="currentStep === 0" class="mx-auto w-[560px]">
<div v-if="currentStep === 0" class="mx-auto w-4/6">
<BasicInfo
v-model="formData"
:category-list="categoryList"
@ -480,13 +484,19 @@ onBeforeUnmount(() => {
ref="basicInfoRef"
/>
</div>
<!-- 第二步表单设计 TODO -->
<!-- 第二步表单设计 -->
<div v-show="currentStep === 1" class="mx-auto w-4/6">
<FormDesign
v-model="formData"
:form-list="formList"
ref="formDesignRef"
/>
</div>
<!-- 第三步流程设计 TODO -->
<!-- 第四步更多设置 TODO -->
<div v-show="currentStep === 3" class="mx-auto w-[700px]"></div>
<div v-show="currentStep === 3" class="mx-auto w-4/6"></div>
</div>
</Card>
</div>

View File

@ -10,7 +10,7 @@ import type { SystemUserApi } from '#/api/system/user';
import { ref, watch } from 'vue';
import { IconifyIcon, Plus, ShieldQuestion, X } from '@vben/icons';
import { CircleHelp, IconifyIcon, Plus, X } from '@vben/icons';
import {
Avatar,
@ -65,6 +65,7 @@ const rules: Record<string, Rule[]> = {
category: [{ required: true, message: '流程分类不能为空', trigger: 'blur' }],
type: [{ required: true, message: '流程类型不能为空', trigger: 'blur' }],
visible: [{ required: true, message: '是否可见不能为空', trigger: 'blur' }],
// TODO
managerUserIds: [
{ required: true, message: '流程管理员不能为空', trigger: 'blur' },
],
@ -219,9 +220,7 @@ const validate = async () => {
await formRef.value?.validate();
};
defineExpose({
validate,
});
defineExpose({ validate });
</script>
<template>
@ -229,8 +228,8 @@ defineExpose({
ref="formRef"
:model="modelData"
:rules="rules"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 18 }"
:label-col="{ span: 4 }"
:wrapper-col="{ span: 20 }"
class="mt-5"
>
<Form.Item label="流程标识" name="key" class="mb-5">
@ -247,7 +246,7 @@ defineExpose({
"
placement="top"
>
<ShieldQuestion class="ml-1 text-gray-500" />
<CircleHelp class="ml-1 size-5 text-gray-900" />
</Tooltip>
</div>
</Form.Item>

View File

@ -0,0 +1,187 @@
<script lang="ts" setup>
import type { Rule } from 'ant-design-vue/es/form';
import type { BpmFormApi } from '#/api/bpm/form';
import { ref, watch } from 'vue';
import { CircleHelp } from '@vben/icons';
import FormCreate from '@form-create/ant-design-vue';
import {
Form,
FormItem,
Input,
Radio,
RadioGroup,
Select,
SelectOption,
Tooltip,
} from 'ant-design-vue';
import { getFormDetail } from '#/api/bpm/form';
import {
BpmModelFormType,
DICT_TYPE,
getDictOptions,
setConfAndFields2,
} from '#/utils';
const props = defineProps({
formList: {
type: Array<BpmFormApi.FormVO>,
required: true,
},
});
const formRef = ref();
//
const modelData = defineModel<any>();
//
const formPreview = ref({
formData: {} as any,
rule: [],
option: {
submitBtn: false,
resetBtn: false,
formData: {},
},
});
/** 监听表单ID变化加载表单数据 */
watch(
() => modelData.value.formId,
async (newFormId) => {
if (newFormId && modelData.value.formType === BpmModelFormType.NORMAL) {
const data = await getFormDetail(newFormId);
setConfAndFields2(formPreview.value, data.conf, data.fields);
//
formPreview.value.rule.forEach((item: any) => {
item.props = { ...item.props, disabled: true };
});
} else {
formPreview.value.rule = [];
}
},
{ immediate: true },
);
const rules: Record<string, Rule[]> = {
formType: [{ required: true, message: '表单类型不能为空', trigger: 'blur' }],
formId: [{ required: true, message: '流程表单不能为空', trigger: 'blur' }],
formCustomCreatePath: [
{ required: true, message: '表单提交路由不能为空', trigger: 'blur' },
],
formCustomViewPath: [
{ required: true, message: '表单查看地址不能为空', trigger: 'blur' },
],
};
/** 表单校验 */
const validate = async () => {
await formRef.value?.validate();
};
defineExpose({ validate });
</script>
<template>
<Form
ref="formRef"
:model="modelData"
:rules="rules"
:label-col="{ span: 4 }"
:wrapper-col="{ span: 20 }"
class="mt-5"
>
<FormItem label="表单类型" name="formType" class="mb-5">
<RadioGroup v-model:value="modelData.formType">
<Radio
v-for="dict in getDictOptions(
DICT_TYPE.BPM_MODEL_FORM_TYPE,
'number',
)"
:key="dict.value as string"
:value="dict.value"
>
{{ dict.label }}
</Radio>
</RadioGroup>
</FormItem>
<FormItem
v-if="modelData.formType === BpmModelFormType.NORMAL"
label="流程表单"
name="formId"
class="mb-5"
>
<Select v-model:value="modelData.formId" clearable>
<SelectOption
v-for="form in props.formList"
:key="form.id"
:value="form.id"
>
{{ form.name }}
</SelectOption>
>
</Select>
</FormItem>
<FormItem
v-if="modelData.formType === BpmModelFormType.CUSTOM"
label="表单提交路由"
name="formCustomCreatePath"
class="mb-5"
>
<div class="flex items-center">
<Input
v-model:value="modelData.formCustomCreatePath"
placeholder="请输入表单提交路由"
/>
<Tooltip
title="自定义表单的提交路径,使用 Vue 的路由地址, 例如说: bpm/oa/leave/create.vue"
placement="top"
>
<CircleHelp class="ml-1 size-5 text-gray-900" />
</Tooltip>
</div>
</FormItem>
<FormItem
v-if="modelData.formType === BpmModelFormType.CUSTOM"
label="表单查看地址"
name="formCustomViewPath"
class="mb-5"
>
<div class="flex items-center">
<Input
v-model:value="modelData.formCustomViewPath"
placeholder="请输入表单查看的组件地址"
/>
<Tooltip
title="自定义表单的查看组件地址,使用 Vue 的组件地址例如说bpm/oa/leave/detail.vue"
placement="top"
>
<CircleHelp class="ml-1 size-5 text-gray-900" />
</Tooltip>
</div>
</FormItem>
<!-- 表单预览 -->
<div
v-if="
modelData.formType === BpmModelFormType.NORMAL &&
modelData.formId &&
formPreview.rule.length > 0
"
class="mb-5 mt-7 rounded-sm border border-solid border-gray-200 p-5"
>
<div class="mb-[15px] flex items-center">
<div class="mr-[10px] h-[15px] w-[4px] bg-[#1890ff]"></div>
<span class="text-[15px] font-bold">表单预览</span>
</div>
<FormCreate
v-model:api="formPreview.formData"
:rule="formPreview.rule"
:option="formPreview.option"
/>
</div>
</Form>
</template>