Merge branch 'dev' of https://gitee.com/yudaocode/yudao-ui-admin-vben into dev
commit
84f441684f
|
@ -9,6 +9,8 @@ export namespace BpmProcessDefinitionApi {
|
||||||
version: number;
|
version: number;
|
||||||
deploymentTime: number;
|
deploymentTime: number;
|
||||||
suspensionState: number;
|
suspensionState: number;
|
||||||
|
modelType: number;
|
||||||
|
modelId: string;
|
||||||
formType?: number;
|
formType?: number;
|
||||||
bpmnXml?: string;
|
bpmnXml?: string;
|
||||||
simpleModel?: string;
|
simpleModel?: string;
|
||||||
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { DataNode } from 'ant-design-vue/es/tree';
|
||||||
|
|
||||||
|
import type { SystemDeptApi } from '#/api/system/dept';
|
||||||
|
|
||||||
|
import { defineProps, ref } from 'vue';
|
||||||
|
|
||||||
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
|
import { handleTree } from '@vben/utils';
|
||||||
|
|
||||||
|
import { Button, Card, Col, Row, Tree } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { getSimpleDeptList } from '#/api/system/dept';
|
||||||
|
|
||||||
|
defineOptions({ name: 'DeptSelectModal' });
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
// 取消按钮文本
|
||||||
|
cancelText?: string;
|
||||||
|
// checkable 状态下节点选择完全受控
|
||||||
|
checkStrictly?: boolean;
|
||||||
|
// 确认按钮文本
|
||||||
|
confirmText?: string;
|
||||||
|
// 是否支持多选
|
||||||
|
multiple?: boolean;
|
||||||
|
// 标题
|
||||||
|
title?: string;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
cancelText: '取消',
|
||||||
|
checkStrictly: false,
|
||||||
|
confirmText: '确认',
|
||||||
|
multiple: true,
|
||||||
|
title: '部门选择',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
confirm: [deptList: SystemDeptApi.Dept[]];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 对话框配置
|
||||||
|
const [Modal, modalApi] = useVbenModal({
|
||||||
|
title: props.title,
|
||||||
|
async onOpenChange(isOpen: boolean) {
|
||||||
|
if (!isOpen) {
|
||||||
|
resetData();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
modalApi.setState({ loading: true });
|
||||||
|
try {
|
||||||
|
deptData.value = await getSimpleDeptList();
|
||||||
|
deptTree.value = handleTree(deptData.value) as DataNode[];
|
||||||
|
} finally {
|
||||||
|
modalApi.setState({ loading: false });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
destroyOnClose: true,
|
||||||
|
});
|
||||||
|
type checkedKeys = number[] | { checked: number[]; halfChecked: number[] };
|
||||||
|
// 部门树形结构
|
||||||
|
const deptTree = ref<DataNode[]>([]);
|
||||||
|
// 选中的部门 ID 列表
|
||||||
|
const selectedDeptIds = ref<checkedKeys>([]);
|
||||||
|
// 部门数据
|
||||||
|
const deptData = ref<SystemDeptApi.Dept[]>([]);
|
||||||
|
|
||||||
|
/** 打开对话框 */
|
||||||
|
const open = async (selectedList?: SystemDeptApi.Dept[]) => {
|
||||||
|
modalApi.open();
|
||||||
|
// // 设置已选择的部门
|
||||||
|
if (selectedList?.length) {
|
||||||
|
const selectedIds = selectedList
|
||||||
|
.map((dept) => dept.id)
|
||||||
|
.filter((id): id is number => id !== undefined);
|
||||||
|
selectedDeptIds.value = props.checkStrictly
|
||||||
|
? {
|
||||||
|
checked: selectedIds,
|
||||||
|
halfChecked: [],
|
||||||
|
}
|
||||||
|
: selectedIds;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 处理选中状态变化 */
|
||||||
|
const handleCheck = () => {
|
||||||
|
if (!props.multiple) {
|
||||||
|
// 单选模式下,只保留最后选择的节点
|
||||||
|
if (Array.isArray(selectedDeptIds.value)) {
|
||||||
|
const lastSelectedId =
|
||||||
|
selectedDeptIds.value[selectedDeptIds.value.length - 1];
|
||||||
|
if (lastSelectedId) {
|
||||||
|
selectedDeptIds.value = [lastSelectedId];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// checkStrictly 为 true 时,selectedDeptIds 是一个对象
|
||||||
|
const checked = selectedDeptIds.value.checked || [];
|
||||||
|
if (checked.length > 0) {
|
||||||
|
const lastSelectedId = checked[checked.length - 1];
|
||||||
|
selectedDeptIds.value = {
|
||||||
|
checked: [lastSelectedId!],
|
||||||
|
halfChecked: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 提交选择 */
|
||||||
|
const handleConfirm = async () => {
|
||||||
|
// 获取选中的部门ID
|
||||||
|
const selectedIds: number[] = Array.isArray(selectedDeptIds.value)
|
||||||
|
? selectedDeptIds.value
|
||||||
|
: selectedDeptIds.value.checked || [];
|
||||||
|
const deptArray = deptData.value.filter((dept) =>
|
||||||
|
selectedIds.includes(dept.id!),
|
||||||
|
);
|
||||||
|
// 关闭并提示
|
||||||
|
await modalApi.close();
|
||||||
|
emit('confirm', deptArray);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
modalApi.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 重置数据 */
|
||||||
|
const resetData = () => {
|
||||||
|
deptTree.value = [];
|
||||||
|
selectedDeptIds.value = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 提供 open 方法,用于打开对话框 */
|
||||||
|
defineExpose({ open });
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<Modal>
|
||||||
|
<Row class="h-full">
|
||||||
|
<Col :span="24">
|
||||||
|
<Card class="h-full">
|
||||||
|
<Tree
|
||||||
|
:tree-data="deptTree"
|
||||||
|
v-if="deptTree.length > 0"
|
||||||
|
v-model:checked-keys="selectedDeptIds"
|
||||||
|
:checkable="true"
|
||||||
|
:check-strictly="checkStrictly"
|
||||||
|
:field-names="{ title: 'name', key: 'id' }"
|
||||||
|
:default-expand-all="true"
|
||||||
|
@check="handleCheck"
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<template #footer>
|
||||||
|
<Button @click="handleCancel">{{ cancelText }}</Button>
|
||||||
|
<Button type="primary" @click="handleConfirm">{{ confirmText }}</Button>
|
||||||
|
</template>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
|
@ -0,0 +1 @@
|
||||||
|
export { default as DeptSelectModal } from './dept-select-modal.vue';
|
|
@ -62,6 +62,18 @@ const routes: RouteRecordRaw[] = [
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'manager/model/create',
|
||||||
|
component: () => import('#/views/bpm/model/form/index.vue'),
|
||||||
|
name: 'BpmModelCreate',
|
||||||
|
meta: {
|
||||||
|
title: '创建流程',
|
||||||
|
activePath: '/bpm/manager/model',
|
||||||
|
icon: 'carbon:flow-connection',
|
||||||
|
hideInMenu: true,
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -0,0 +1,494 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { BpmCategoryApi } from '#/api/bpm/category';
|
||||||
|
import type { BpmProcessDefinitionApi } from '#/api/bpm/definition';
|
||||||
|
import type { SystemDeptApi } from '#/api/system/dept';
|
||||||
|
import type { SystemUserApi } from '#/api/system/user';
|
||||||
|
|
||||||
|
import { onBeforeUnmount, onMounted, provide, ref, watch } from 'vue';
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
import { confirm, Page } from '@vben/common-ui';
|
||||||
|
import { useTabs } from '@vben/hooks';
|
||||||
|
import { ArrowLeft } from '@vben/icons';
|
||||||
|
import { useUserStore } from '@vben/stores';
|
||||||
|
|
||||||
|
import { Button, Card, message } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { getCategorySimpleList } from '#/api/bpm/category';
|
||||||
|
import { getProcessDefinition } from '#/api/bpm/definition';
|
||||||
|
import {
|
||||||
|
createModel,
|
||||||
|
deployModel,
|
||||||
|
getModel,
|
||||||
|
updateModel,
|
||||||
|
} from '#/api/bpm/model';
|
||||||
|
import { getSimpleDeptList } from '#/api/system/dept';
|
||||||
|
import { getSimpleUserList } from '#/api/system/user';
|
||||||
|
|
||||||
|
import BasicInfo from './modules/basic-info.vue';
|
||||||
|
|
||||||
|
defineOptions({ name: 'BpmModelCreate' });
|
||||||
|
|
||||||
|
// TODO 这个常量是不是所有 apps 都可以使用, 放 @utils/constant.ts 不能共享, @芋艿 这些常量放哪里合适!
|
||||||
|
const BpmModelType = {
|
||||||
|
BPMN: 10, // BPMN 设计器
|
||||||
|
SIMPLE: 20, // 简易设计器
|
||||||
|
};
|
||||||
|
|
||||||
|
const BpmModelFormType = {
|
||||||
|
NORMAL: 10, // 流程表单
|
||||||
|
CUSTOM: 20, // 业务表单
|
||||||
|
};
|
||||||
|
|
||||||
|
const BpmAutoApproveType = {
|
||||||
|
NONE: 0, // 不自动通过
|
||||||
|
APPROVE_ALL: 1, // 仅审批一次,后续重复的审批节点均自动通过
|
||||||
|
APPROVE_SEQUENT: 2, // 仅针对连续审批的节点自动通过
|
||||||
|
};
|
||||||
|
|
||||||
|
// 流程定义类型
|
||||||
|
type BpmProcessDefinitionType = Omit<
|
||||||
|
BpmProcessDefinitionApi.ProcessDefinitionVO,
|
||||||
|
'modelId' | 'modelType'
|
||||||
|
> & {
|
||||||
|
id?: string;
|
||||||
|
type?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
// 基础信息组件引用
|
||||||
|
const basicInfoRef = ref();
|
||||||
|
|
||||||
|
/** 步骤校验函数 */
|
||||||
|
const validateBasic = async () => {
|
||||||
|
await basicInfoRef.value?.validate();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 表单设计校验 */
|
||||||
|
const validateForm = async () => {
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 流程设计校验 */
|
||||||
|
const validateProcess = async () => {
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
|
||||||
|
const currentStep = ref(-1); // 步骤控制。-1 用于,一开始全部不展示等当前页面数据初始化完成
|
||||||
|
|
||||||
|
const steps = [
|
||||||
|
{ title: '基本信息', validator: validateBasic },
|
||||||
|
{ title: '表单设计', validator: validateForm },
|
||||||
|
{ title: '流程设计', validator: validateProcess },
|
||||||
|
{ title: '更多设置', validator: null },
|
||||||
|
];
|
||||||
|
|
||||||
|
// 表单数据
|
||||||
|
const formData: any = ref({
|
||||||
|
id: undefined,
|
||||||
|
name: '',
|
||||||
|
key: '',
|
||||||
|
category: undefined,
|
||||||
|
icon: undefined,
|
||||||
|
description: '',
|
||||||
|
type: BpmModelType.BPMN,
|
||||||
|
formType: BpmModelFormType.NORMAL,
|
||||||
|
formId: '',
|
||||||
|
formCustomCreatePath: '',
|
||||||
|
formCustomViewPath: '',
|
||||||
|
visible: true,
|
||||||
|
startUserType: undefined,
|
||||||
|
startUserIds: [],
|
||||||
|
startDeptIds: [],
|
||||||
|
managerUserIds: [],
|
||||||
|
allowCancelRunningProcess: true,
|
||||||
|
processIdRule: {
|
||||||
|
enable: false,
|
||||||
|
prefix: '',
|
||||||
|
infix: '',
|
||||||
|
postfix: '',
|
||||||
|
length: 5,
|
||||||
|
},
|
||||||
|
autoApprovalType: BpmAutoApproveType.NONE,
|
||||||
|
titleSetting: {
|
||||||
|
enable: false,
|
||||||
|
title: '',
|
||||||
|
},
|
||||||
|
summarySetting: {
|
||||||
|
enable: false,
|
||||||
|
summary: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 流程数据
|
||||||
|
const processData = ref<any>();
|
||||||
|
|
||||||
|
provide('processData', processData);
|
||||||
|
provide('modelData', formData);
|
||||||
|
|
||||||
|
// 数据列表
|
||||||
|
// const formList = ref([])
|
||||||
|
const categoryList = ref<BpmCategoryApi.CategoryVO[]>([]);
|
||||||
|
const userList = ref<SystemUserApi.User[]>([]);
|
||||||
|
const deptList = ref<SystemDeptApi.Dept[]>([]);
|
||||||
|
|
||||||
|
/** 初始化数据 */
|
||||||
|
const actionType = route.params.type as string;
|
||||||
|
const initData = async () => {
|
||||||
|
if (actionType === 'definition') {
|
||||||
|
// 情况一:流程定义场景(恢复)
|
||||||
|
const definitionId = route.params.id as string;
|
||||||
|
const data = await getProcessDefinition(definitionId);
|
||||||
|
const processDefinition: BpmProcessDefinitionType = data;
|
||||||
|
// 将 definition => model
|
||||||
|
processDefinition.type = data.modelType;
|
||||||
|
processDefinition.id = data.modelId;
|
||||||
|
if (data.simpleModel) {
|
||||||
|
processDefinition.simpleModel = JSON.parse(data.simpleModel);
|
||||||
|
}
|
||||||
|
formData.value = processDefinition;
|
||||||
|
|
||||||
|
// 设置 startUserType
|
||||||
|
if (formData.value.startUserIds?.length > 0) {
|
||||||
|
formData.value.startUserType = 1;
|
||||||
|
} else if (formData.value.startDeptIds?.length > 0) {
|
||||||
|
formData.value.startUserType = 2;
|
||||||
|
} else {
|
||||||
|
formData.value.startUserType = 0;
|
||||||
|
}
|
||||||
|
} else if (['copy', 'update'].includes(actionType)) {
|
||||||
|
// 情况二:修改场景/复制场景
|
||||||
|
const modelId = route.params.id as string;
|
||||||
|
formData.value = await getModel(modelId);
|
||||||
|
|
||||||
|
// 设置 startUserType
|
||||||
|
if (formData.value.startUserIds?.length > 0) {
|
||||||
|
formData.value.startUserType = 1;
|
||||||
|
} else if (formData.value.startDeptIds?.length > 0) {
|
||||||
|
formData.value.startUserType = 2;
|
||||||
|
} else {
|
||||||
|
formData.value.startUserType = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 特殊:复制场景
|
||||||
|
if (route.params.type === 'copy') {
|
||||||
|
delete formData.value.id;
|
||||||
|
formData.value.name += '副本';
|
||||||
|
formData.value.key += '_copy';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 情况三:新增场景
|
||||||
|
formData.value.startUserType = 0; // 全体
|
||||||
|
formData.value.managerUserIds.push(userStore.userInfo?.userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO 获取表单列表
|
||||||
|
// formList.value = await getFormSimpleList()
|
||||||
|
categoryList.value = await getCategorySimpleList();
|
||||||
|
// 获取用户列表
|
||||||
|
userList.value = await getSimpleUserList();
|
||||||
|
// 获取部门列表
|
||||||
|
deptList.value = await getSimpleDeptList();
|
||||||
|
|
||||||
|
// 最终,设置 currentStep 切换到第一步
|
||||||
|
currentStep.value = 0;
|
||||||
|
|
||||||
|
// TODO 兼容,以前未配置更多设置的流程
|
||||||
|
// extraSettingsRef.value.initData()
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 根据类型切换流程数据 */
|
||||||
|
watch(
|
||||||
|
async () => formData.value.type,
|
||||||
|
() => {
|
||||||
|
if (formData.value.type === BpmModelType.BPMN) {
|
||||||
|
processData.value = formData.value.bpmnXml;
|
||||||
|
} else if (formData.value.type === BpmModelType.SIMPLE) {
|
||||||
|
processData.value = formData.value.simpleModel;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
/** 校验所有步骤数据是否完整 */
|
||||||
|
const validateAllSteps = async () => {
|
||||||
|
// 基本信息校验
|
||||||
|
try {
|
||||||
|
await validateBasic();
|
||||||
|
} catch {
|
||||||
|
currentStep.value = 0;
|
||||||
|
throw new Error('请完善基本信息');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表单设计校验
|
||||||
|
try {
|
||||||
|
await validateForm();
|
||||||
|
} catch {
|
||||||
|
currentStep.value = 1;
|
||||||
|
throw new Error('请完善自定义表单信息');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 流程设计校验 TODO
|
||||||
|
|
||||||
|
try {
|
||||||
|
await validateProcess();
|
||||||
|
} catch {
|
||||||
|
currentStep.value = 2;
|
||||||
|
throw new Error('请设计流程');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表单设计校验
|
||||||
|
try {
|
||||||
|
await validateProcess();
|
||||||
|
} catch {
|
||||||
|
currentStep.value = 2;
|
||||||
|
throw new Error('请设计流程');
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 保存操作 */
|
||||||
|
const handleSave = async () => {
|
||||||
|
try {
|
||||||
|
// 保存前校验所有步骤的数据
|
||||||
|
await validateAllSteps();
|
||||||
|
|
||||||
|
// 更新表单数据
|
||||||
|
const modelData = {
|
||||||
|
...formData.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (actionType) {
|
||||||
|
case 'copy': {
|
||||||
|
// 情况三:复制场景
|
||||||
|
formData.value.id = await createModel(modelData);
|
||||||
|
// 提示成功
|
||||||
|
message.success('复制成功,可点击【发布】按钮,进行发布模型');
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'definition': {
|
||||||
|
// 情况一:流程定义场景(恢复)
|
||||||
|
await updateModel(modelData);
|
||||||
|
// 提示成功
|
||||||
|
message.success('恢复成功,可点击【发布】按钮,进行发布模型');
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'update': {
|
||||||
|
// 修改场景
|
||||||
|
await updateModel(modelData);
|
||||||
|
// 提示成功
|
||||||
|
message.success('修改成功,可点击【发布】按钮,进行发布模型');
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// 情况四:新增场景
|
||||||
|
formData.value.id = await createModel(modelData);
|
||||||
|
// 提示成功
|
||||||
|
message.success('新建成功,可点击【发布】按钮,进行发布模型');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回列表页(排除更新的情况)
|
||||||
|
if (actionType !== 'update') {
|
||||||
|
await router.push({ name: 'BpmModel' });
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('保存失败:', error);
|
||||||
|
message.warning(error.message || '请完善所有步骤的必填信息');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 发布操作 */
|
||||||
|
const handleDeploy = async () => {
|
||||||
|
try {
|
||||||
|
// 修改场景下直接发布,新增场景下需要先确认
|
||||||
|
if (!formData.value.id) {
|
||||||
|
await confirm('是否确认发布该流程?');
|
||||||
|
}
|
||||||
|
// 校验所有步骤
|
||||||
|
await validateAllSteps();
|
||||||
|
|
||||||
|
// 更新表单数据
|
||||||
|
const modelData = {
|
||||||
|
...formData.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 先保存所有数据
|
||||||
|
if (formData.value.id) {
|
||||||
|
await updateModel(modelData);
|
||||||
|
} else {
|
||||||
|
const result = await createModel(modelData);
|
||||||
|
formData.value.id = result.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发布
|
||||||
|
await deployModel(formData.value.id);
|
||||||
|
message.success('发布成功');
|
||||||
|
// TODO 返回列表页
|
||||||
|
await router.push({ name: 'BpmModel' });
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('发布失败:', error);
|
||||||
|
message.warning(error.message || '发布失败');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 步骤切换处理 */
|
||||||
|
const handleStepClick = async (index: number) => {
|
||||||
|
try {
|
||||||
|
if (index !== 0) {
|
||||||
|
await validateBasic();
|
||||||
|
}
|
||||||
|
if (index !== 1) {
|
||||||
|
await validateForm();
|
||||||
|
}
|
||||||
|
if (index !== 2) {
|
||||||
|
await validateProcess();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换步骤
|
||||||
|
currentStep.value = index;
|
||||||
|
|
||||||
|
// 如果切换到流程设计步骤,等待组件渲染完成后刷新设计器
|
||||||
|
if (index === 2) {
|
||||||
|
// TODO 后续加
|
||||||
|
// await nextTick();
|
||||||
|
// // 等待更长时间确保组件完全初始化
|
||||||
|
// await new Promise((resolve) => setTimeout(resolve, 200));
|
||||||
|
// if (processDesignRef.value?.refresh) {
|
||||||
|
// await processDesignRef.value.refresh();
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('步骤切换失败:', error);
|
||||||
|
message.warning('请先完善当前步骤必填信息');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const tabs = useTabs();
|
||||||
|
|
||||||
|
/** 返回列表页 */
|
||||||
|
const handleBack = () => {
|
||||||
|
// 关闭当前页签
|
||||||
|
tabs.closeCurrentTab();
|
||||||
|
// 跳转到列表页,使用路径, 目前后端的路由 name: 'name'+ menuId
|
||||||
|
router.push({ path: '/bpm/manager/model' });
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 初始化 */
|
||||||
|
onMounted(async () => {
|
||||||
|
await initData();
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 添加组件卸载前的清理 */
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
// 清理所有的引用
|
||||||
|
basicInfoRef.value = null;
|
||||||
|
// TODO 后续加
|
||||||
|
// formDesignRef.value = null;
|
||||||
|
// processDesignRef.value = null;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Page auto-content-height>
|
||||||
|
<div class="mx-auto">
|
||||||
|
<!-- 头部导航栏 -->
|
||||||
|
<div
|
||||||
|
class="absolute inset-x-0 top-0 z-10 flex h-12 items-center border-b bg-white px-5"
|
||||||
|
>
|
||||||
|
<!-- 左侧标题 -->
|
||||||
|
<div class="flex w-[200px] items-center overflow-hidden">
|
||||||
|
<ArrowLeft
|
||||||
|
class="size-5 flex-shrink-0 cursor-pointer"
|
||||||
|
@click="handleBack"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ml-2.5 truncate text-base"
|
||||||
|
:title="formData.name || '创建流程'"
|
||||||
|
>
|
||||||
|
{{ formData.name || '创建流程' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 步骤条 -->
|
||||||
|
<div class="flex h-full flex-1 items-center justify-center">
|
||||||
|
<div class="flex h-full w-[400px] items-center justify-between">
|
||||||
|
<div
|
||||||
|
v-for="(step, index) in steps"
|
||||||
|
:key="index"
|
||||||
|
class="relative mx-[15px] flex h-full cursor-pointer items-center"
|
||||||
|
:class="[
|
||||||
|
currentStep === index
|
||||||
|
? 'border-b-2 border-solid border-blue-500 text-blue-500'
|
||||||
|
: 'text-gray-500',
|
||||||
|
]"
|
||||||
|
@click="handleStepClick(index)"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mr-2 flex h-7 w-7 items-center justify-center rounded-full border-2 border-solid text-[15px]"
|
||||||
|
:class="[
|
||||||
|
currentStep === index
|
||||||
|
? 'border-blue-500 bg-blue-500 text-white'
|
||||||
|
: 'border-gray-300 bg-white text-gray-500',
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
{{ index + 1 }}
|
||||||
|
</div>
|
||||||
|
<span class="whitespace-nowrap text-base font-bold">{{
|
||||||
|
step.title
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 右侧按钮 -->
|
||||||
|
<div class="flex w-[200px] items-center justify-end gap-2">
|
||||||
|
<Button
|
||||||
|
v-if="actionType === 'update'"
|
||||||
|
type="primary"
|
||||||
|
@click="handleDeploy"
|
||||||
|
>
|
||||||
|
发 布
|
||||||
|
</Button>
|
||||||
|
<Button type="primary" @click="handleSave">
|
||||||
|
<span v-if="actionType === 'definition'">恢 复</span>
|
||||||
|
<span v-else>保 存</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 主体内容 -->
|
||||||
|
<Card :body-style="{ padding: '10px' }" class="mb-4">
|
||||||
|
<div class="mt-[50px]">
|
||||||
|
<!-- 第一步:基本信息 -->
|
||||||
|
<div v-if="currentStep === 0" class="mx-auto w-[560px]">
|
||||||
|
<BasicInfo
|
||||||
|
v-model="formData"
|
||||||
|
:category-list="categoryList"
|
||||||
|
:user-list="userList"
|
||||||
|
:dept-list="deptList"
|
||||||
|
ref="basicInfoRef"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 第二步:表单设计 TODO -->
|
||||||
|
|
||||||
|
<!-- 第三步:流程设计 TODO -->
|
||||||
|
|
||||||
|
<!-- 第四步:更多设置 TODO -->
|
||||||
|
<div v-show="currentStep === 3" class="mx-auto w-[700px]"></div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</Page>
|
||||||
|
</template>
|
|
@ -0,0 +1,455 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { Rule } from 'ant-design-vue/es/form';
|
||||||
|
import type { SelectValue } from 'ant-design-vue/es/select';
|
||||||
|
|
||||||
|
import type { PropType } from 'vue';
|
||||||
|
|
||||||
|
import type { BpmCategoryApi } from '#/api/bpm/category';
|
||||||
|
import type { SystemDeptApi } from '#/api/system/dept';
|
||||||
|
import type { SystemUserApi } from '#/api/system/user';
|
||||||
|
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
|
||||||
|
import { IconifyIcon, Plus, ShieldQuestion, X } from '@vben/icons';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Avatar,
|
||||||
|
Button,
|
||||||
|
Form,
|
||||||
|
Input,
|
||||||
|
Radio,
|
||||||
|
Select,
|
||||||
|
Tooltip,
|
||||||
|
} from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { DeptSelectModal } from '#/components/dept-select-modal';
|
||||||
|
import { ImageUpload } from '#/components/upload';
|
||||||
|
import { UserSelectModal } from '#/components/user-select-modal';
|
||||||
|
import { DICT_TYPE, getBoolDictOptions, getIntDictOptions } from '#/utils';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
categoryList: {
|
||||||
|
type: Array as PropType<BpmCategoryApi.CategoryVO[]>,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
userList: {
|
||||||
|
type: Array as PropType<SystemUserApi.User[]>,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
deptList: {
|
||||||
|
type: Array as PropType<SystemDeptApi.Dept[]>,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表单引用
|
||||||
|
const formRef = ref();
|
||||||
|
|
||||||
|
// 选中的发起人
|
||||||
|
const selectedStartUsers = ref<SystemUserApi.User[]>([]);
|
||||||
|
|
||||||
|
// 选中的发起部门
|
||||||
|
const selectedStartDepts = ref<SystemDeptApi.Dept[]>([]);
|
||||||
|
|
||||||
|
// 选中的流程管理员
|
||||||
|
const selectedManagerUsers = ref<SystemUserApi.User[]>([]);
|
||||||
|
const userSelectFormRef = ref();
|
||||||
|
const deptSelectFormRef = ref();
|
||||||
|
const currentSelectType = ref<'manager' | 'start'>('start');
|
||||||
|
// 选中的用户
|
||||||
|
const selectedUsers = ref<number[]>();
|
||||||
|
|
||||||
|
const rules: Record<string, Rule[]> = {
|
||||||
|
name: [{ required: true, message: '流程名称不能为空', trigger: 'blur' }],
|
||||||
|
key: [{ required: true, message: '流程标识不能为空', trigger: 'blur' }],
|
||||||
|
category: [{ required: true, message: '流程分类不能为空', trigger: 'blur' }],
|
||||||
|
type: [{ required: true, message: '流程类型不能为空', trigger: 'blur' }],
|
||||||
|
visible: [{ required: true, message: '是否可见不能为空', trigger: 'blur' }],
|
||||||
|
managerUserIds: [
|
||||||
|
{ required: true, message: '流程管理员不能为空', trigger: 'blur' },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
// 创建本地数据副本
|
||||||
|
const modelData = defineModel<any>();
|
||||||
|
|
||||||
|
// 初始化选中的用户
|
||||||
|
watch(
|
||||||
|
() => modelData.value,
|
||||||
|
(newVal) => {
|
||||||
|
selectedStartUsers.value = newVal.startUserIds?.length
|
||||||
|
? (props.userList.filter((user: SystemUserApi.User) =>
|
||||||
|
newVal.startUserIds.includes(user.id),
|
||||||
|
) as SystemUserApi.User[])
|
||||||
|
: [];
|
||||||
|
selectedStartDepts.value = newVal.startDeptIds?.length
|
||||||
|
? (props.deptList.filter((dept: SystemDeptApi.Dept) =>
|
||||||
|
newVal.startDeptIds.includes(dept.id),
|
||||||
|
) as SystemDeptApi.Dept[])
|
||||||
|
: [];
|
||||||
|
selectedManagerUsers.value = newVal.managerUserIds?.length
|
||||||
|
? (props.userList.filter((user: SystemUserApi.User) =>
|
||||||
|
newVal.managerUserIds.includes(user.id),
|
||||||
|
) as SystemUserApi.User[])
|
||||||
|
: [];
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
/** 打开发起人选择 */
|
||||||
|
const openStartUserSelect = () => {
|
||||||
|
currentSelectType.value = 'start';
|
||||||
|
selectedUsers.value = selectedStartUsers.value.map(
|
||||||
|
(user) => user.id,
|
||||||
|
) as number[];
|
||||||
|
userSelectFormRef.value.open(selectedUsers.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 打开部门选择 */
|
||||||
|
const openStartDeptSelect = () => {
|
||||||
|
deptSelectFormRef.value.open(selectedStartDepts.value);
|
||||||
|
};
|
||||||
|
/** 处理部门选择确认 */
|
||||||
|
const handleDeptSelectConfirm = (depts: SystemDeptApi.Dept[]) => {
|
||||||
|
modelData.value = {
|
||||||
|
...modelData.value,
|
||||||
|
startDeptIds: depts.map((d) => d.id),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 打开管理员选择 */
|
||||||
|
const openManagerUserSelect = () => {
|
||||||
|
currentSelectType.value = 'manager';
|
||||||
|
selectedUsers.value = selectedManagerUsers.value.map(
|
||||||
|
(user) => user.id,
|
||||||
|
) as number[];
|
||||||
|
userSelectFormRef.value.open(selectedUsers.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 处理用户选择确认 */
|
||||||
|
const handleUserSelectConfirm = (userList: SystemUserApi.User[]) => {
|
||||||
|
modelData.value =
|
||||||
|
currentSelectType.value === 'start'
|
||||||
|
? {
|
||||||
|
...modelData.value,
|
||||||
|
startUserIds: userList.map((u) => u.id),
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
...modelData.value,
|
||||||
|
managerUserIds: userList.map((u) => u.id),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 用户选择弹窗关闭 */
|
||||||
|
const handleUserSelectClosed = () => {
|
||||||
|
selectedUsers.value = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 用户选择弹窗取消 */
|
||||||
|
const handleUserSelectCancel = () => {
|
||||||
|
selectedUsers.value = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 处理发起人类型变化 */
|
||||||
|
const handleStartUserTypeChange = (value: SelectValue) => {
|
||||||
|
const numValue = Number(value);
|
||||||
|
switch (numValue) {
|
||||||
|
case 0: {
|
||||||
|
modelData.value = {
|
||||||
|
...modelData.value,
|
||||||
|
startUserIds: [],
|
||||||
|
startDeptIds: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
modelData.value = {
|
||||||
|
...modelData.value,
|
||||||
|
startDeptIds: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
modelData.value = {
|
||||||
|
...modelData.value,
|
||||||
|
startUserIds: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 移除发起人 */
|
||||||
|
const handleRemoveStartUser = (user: SystemUserApi.User) => {
|
||||||
|
modelData.value = {
|
||||||
|
...modelData.value,
|
||||||
|
startUserIds: modelData.value.startUserIds.filter(
|
||||||
|
(id: number) => id !== user.id,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 移除部门 */
|
||||||
|
const handleRemoveStartDept = (dept: SystemDeptApi.Dept) => {
|
||||||
|
modelData.value = {
|
||||||
|
...modelData.value,
|
||||||
|
startDeptIds: modelData.value.startDeptIds.filter(
|
||||||
|
(id: number) => id !== dept.id,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 移除管理员 */
|
||||||
|
const handleRemoveManagerUser = (user: SystemUserApi.User) => {
|
||||||
|
modelData.value = {
|
||||||
|
...modelData.value,
|
||||||
|
managerUserIds: modelData.value.managerUserIds.filter(
|
||||||
|
(id: number) => id !== user.id,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 表单校验 */
|
||||||
|
const validate = async () => {
|
||||||
|
await formRef.value?.validate();
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
validate,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Form
|
||||||
|
ref="formRef"
|
||||||
|
:model="modelData"
|
||||||
|
:rules="rules"
|
||||||
|
:label-col="{ span: 6 }"
|
||||||
|
:wrapper-col="{ span: 18 }"
|
||||||
|
class="mt-5"
|
||||||
|
>
|
||||||
|
<Form.Item label="流程标识" name="key" class="mb-5">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<Input
|
||||||
|
class="w-full"
|
||||||
|
v-model:value="modelData.key"
|
||||||
|
:disabled="!!modelData.id"
|
||||||
|
placeholder="请输入流程标识,以字母或下划线开头"
|
||||||
|
/>
|
||||||
|
<Tooltip
|
||||||
|
:title="
|
||||||
|
modelData.id ? '流程标识不可修改!' : '新建后,流程标识不可修改!'
|
||||||
|
"
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<ShieldQuestion class="ml-1 text-gray-500" />
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="流程名称" name="name" class="mb-5">
|
||||||
|
<Input
|
||||||
|
v-model:value="modelData.name"
|
||||||
|
:disabled="!!modelData.id"
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入流程名称"
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="流程分类" name="category" class="mb-5">
|
||||||
|
<Select
|
||||||
|
class="w-full"
|
||||||
|
v-model:value="modelData.category"
|
||||||
|
allow-clear
|
||||||
|
placeholder="请选择流程分类"
|
||||||
|
>
|
||||||
|
<Select.Option
|
||||||
|
v-for="category in categoryList"
|
||||||
|
:key="category.code"
|
||||||
|
:value="category.code"
|
||||||
|
>
|
||||||
|
{{ category.name }}
|
||||||
|
</Select.Option>
|
||||||
|
</Select>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="流程图标" class="mb-5">
|
||||||
|
<ImageUpload v-model:value="modelData.icon" />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="流程描述" name="description" class="mb-5">
|
||||||
|
<Input.TextArea v-model:value="modelData.description" allow-clear />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="流程类型" name="type" class="mb-5">
|
||||||
|
<Radio.Group v-model:value="modelData.type">
|
||||||
|
<Radio
|
||||||
|
v-for="dict in getIntDictOptions(DICT_TYPE.BPM_MODEL_TYPE)"
|
||||||
|
:key="dict.value"
|
||||||
|
:value="dict.value"
|
||||||
|
>
|
||||||
|
{{ dict.label }}
|
||||||
|
</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="是否可见" name="visible" class="mb-5">
|
||||||
|
<Radio.Group v-model:value="modelData.visible">
|
||||||
|
<Radio
|
||||||
|
v-for="(dict, index) in getBoolDictOptions(
|
||||||
|
DICT_TYPE.INFRA_BOOLEAN_STRING,
|
||||||
|
)"
|
||||||
|
:key="index"
|
||||||
|
:value="dict.value"
|
||||||
|
>
|
||||||
|
{{ dict.label }}
|
||||||
|
</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="谁可以发起" name="startUserType" class="mb-5">
|
||||||
|
<Select
|
||||||
|
v-model:value="modelData.startUserType"
|
||||||
|
placeholder="请选择谁可以发起"
|
||||||
|
@change="handleStartUserTypeChange"
|
||||||
|
>
|
||||||
|
<Select.Option :value="0">全员</Select.Option>
|
||||||
|
<Select.Option :value="1">指定人员</Select.Option>
|
||||||
|
<Select.Option :value="2">指定部门</Select.Option>
|
||||||
|
</Select>
|
||||||
|
<div
|
||||||
|
v-if="modelData.startUserType === 1"
|
||||||
|
class="mt-2 flex flex-wrap gap-2"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="user in selectedStartUsers"
|
||||||
|
:key="user.id"
|
||||||
|
class="relative flex h-9 items-center rounded-full bg-gray-100 pr-2"
|
||||||
|
>
|
||||||
|
<Avatar
|
||||||
|
class="m-1"
|
||||||
|
:size="28"
|
||||||
|
v-if="user.avatar"
|
||||||
|
:src="user.avatar"
|
||||||
|
/>
|
||||||
|
<Avatar class="m-1" :size="28" v-else>
|
||||||
|
{{ user.nickname?.substring(0, 1) }}
|
||||||
|
</Avatar>
|
||||||
|
{{ user.nickname }}
|
||||||
|
<X
|
||||||
|
class="ml-2 size-4 cursor-pointer text-gray-400 hover:text-red-500"
|
||||||
|
@click="handleRemoveStartUser(user)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
@click="openStartUserSelect"
|
||||||
|
class="flex items-center"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<IconifyIcon icon="mdi:account-plus-outline" class="size-[18px]" />
|
||||||
|
</template>
|
||||||
|
选择人员
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="modelData.startUserType === 2"
|
||||||
|
class="mt-2 flex flex-wrap gap-2"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="dept in selectedStartDepts"
|
||||||
|
:key="dept.id"
|
||||||
|
class="relative flex h-9 items-center rounded-full bg-gray-100 pr-2"
|
||||||
|
>
|
||||||
|
<IconifyIcon icon="ep:office-building" class="size-6 px-1" />
|
||||||
|
{{ dept.name }}
|
||||||
|
<X
|
||||||
|
class="ml-2 size-4 cursor-pointer text-gray-400 hover:text-red-500"
|
||||||
|
@click="handleRemoveStartDept(dept)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
@click="openStartDeptSelect"
|
||||||
|
class="flex items-center"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<Plus class="size-[18px]" />
|
||||||
|
</template>
|
||||||
|
选择部门
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="流程管理员" name="managerUserIds" class="mb-5">
|
||||||
|
<div class="flex flex-wrap gap-2">
|
||||||
|
<div
|
||||||
|
v-for="user in selectedManagerUsers"
|
||||||
|
:key="user.id"
|
||||||
|
class="relative flex h-9 items-center rounded-full bg-gray-100 pr-2"
|
||||||
|
>
|
||||||
|
<Avatar
|
||||||
|
class="m-1"
|
||||||
|
:size="28"
|
||||||
|
v-if="user.avatar"
|
||||||
|
:src="user.avatar"
|
||||||
|
/>
|
||||||
|
<Avatar class="m-1" :size="28" v-else>
|
||||||
|
{{ user.nickname?.substring(0, 1) }}
|
||||||
|
</Avatar>
|
||||||
|
{{ user.nickname }}
|
||||||
|
<X
|
||||||
|
class="ml-2 size-4 cursor-pointer text-gray-400 hover:text-red-500"
|
||||||
|
@click="handleRemoveManagerUser(user)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
@click="openManagerUserSelect"
|
||||||
|
class="flex items-center"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<IconifyIcon icon="mdi:account-plus-outline" class="size-[18px]" />
|
||||||
|
</template>
|
||||||
|
选择人员
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
<!-- 用户选择弹窗 -->
|
||||||
|
<UserSelectModal
|
||||||
|
ref="userSelectFormRef"
|
||||||
|
v-model:value="selectedUsers"
|
||||||
|
:multiple="true"
|
||||||
|
title="选择用户"
|
||||||
|
@confirm="handleUserSelectConfirm"
|
||||||
|
@closed="handleUserSelectClosed"
|
||||||
|
@cancel="handleUserSelectCancel"
|
||||||
|
/>
|
||||||
|
<!-- 部门选择对话框 -->
|
||||||
|
<DeptSelectModal
|
||||||
|
ref="deptSelectFormRef"
|
||||||
|
title="发起人部门选择"
|
||||||
|
:check-strictly="true"
|
||||||
|
@confirm="handleDeptSelectConfirm"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.bg-gray-100 {
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #e6e8eb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-img-placeholder {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #fafafa;
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #1890ff !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -25,6 +25,7 @@ import {
|
||||||
updateCategorySortBatch,
|
updateCategorySortBatch,
|
||||||
} from '#/api/bpm/category';
|
} from '#/api/bpm/category';
|
||||||
import { getModelList } from '#/api/bpm/model';
|
import { getModelList } from '#/api/bpm/model';
|
||||||
|
import { router } from '#/router';
|
||||||
|
|
||||||
// 流程分类对话框
|
// 流程分类对话框
|
||||||
import CategoryForm from '../category/modules/form.vue';
|
import CategoryForm from '../category/modules/form.vue';
|
||||||
|
@ -35,7 +36,6 @@ const [CategoryFormModal, categoryFormModalApi] = useVbenModal({
|
||||||
connectedComponent: CategoryForm,
|
connectedComponent: CategoryForm,
|
||||||
destroyOnClose: true,
|
destroyOnClose: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 模型列表加载状态
|
// 模型列表加载状态
|
||||||
const modelListSpinning = refAutoReset(false, 3000);
|
const modelListSpinning = refAutoReset(false, 3000);
|
||||||
// 保存排序状态
|
// 保存排序状态
|
||||||
|
@ -103,7 +103,9 @@ const handleQuery = () => {
|
||||||
|
|
||||||
/** 新增模型 */
|
/** 新增模型 */
|
||||||
const createModel = () => {
|
const createModel = () => {
|
||||||
// TODO 新增模型
|
router.push({
|
||||||
|
name: 'BpmModelCreate',
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 处理下拉菜单命令 */
|
/** 处理下拉菜单命令 */
|
||||||
|
@ -160,6 +162,8 @@ const handleCategorySortSubmit = async () => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Page auto-content-height>
|
<Page auto-content-height>
|
||||||
|
<!-- 流程分类表单弹窗 -->
|
||||||
|
<CategoryFormModal @success="getList" />
|
||||||
<Card
|
<Card
|
||||||
:body-style="{ padding: '10px' }"
|
:body-style="{ padding: '10px' }"
|
||||||
class="mb-4"
|
class="mb-4"
|
||||||
|
@ -249,7 +253,4 @@ const handleCategorySortSubmit = async () => {
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
||||||
<!-- 流程分类表单弹窗 -->
|
|
||||||
<CategoryFormModal @success="getList" />
|
|
||||||
</template>
|
</template>
|
||||||
|
|
Loading…
Reference in New Issue