!168 Merge remote-tracking branch 'yudao/dev' into dev
Merge pull request !168 from Jason/devpull/164/MERGE
						commit
						4d491fbc6b
					
				|  | @ -35,7 +35,7 @@ export namespace BpmProcessInstanceApi { | ||||||
|     candidateStrategy?: BpmCandidateStrategyEnum; |     candidateStrategy?: BpmCandidateStrategyEnum; | ||||||
|     candidateUsers?: User[]; |     candidateUsers?: User[]; | ||||||
|     endTime?: Date; |     endTime?: Date; | ||||||
|     id: number; |     id: string; | ||||||
|     name: string; |     name: string; | ||||||
|     nodeType: BpmNodeTypeEnum; |     nodeType: BpmNodeTypeEnum; | ||||||
|     startTime?: Date; |     startTime?: Date; | ||||||
|  |  | ||||||
|  | @ -186,6 +186,12 @@ export const useApiSelect = (option: ApiSelectProps) => { | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       const buildSelect = () => { |       const buildSelect = () => { | ||||||
|  |         const { | ||||||
|  |           modelValue, | ||||||
|  |           'onUpdate:modelValue': onUpdateModelValue, | ||||||
|  |           ...restAttrs | ||||||
|  |         } = attrs; | ||||||
|  | 
 | ||||||
|         if (props.multiple) { |         if (props.multiple) { | ||||||
|           // fix:多写此步是为了解决 multiple 属性问题
 |           // fix:多写此步是为了解决 multiple 属性问题
 | ||||||
|           return ( |           return ( | ||||||
|  | @ -193,7 +199,9 @@ export const useApiSelect = (option: ApiSelectProps) => { | ||||||
|               class="w-full" |               class="w-full" | ||||||
|               loading={loading.value} |               loading={loading.value} | ||||||
|               mode="multiple" |               mode="multiple" | ||||||
|               {...attrs} |               onUpdate:value={onUpdateModelValue as any} | ||||||
|  |               value={modelValue as any} | ||||||
|  |               {...restAttrs} | ||||||
|               // TODO: remote 对等实现
 |               // TODO: remote 对等实现
 | ||||||
|               // remote={props.remote}
 |               // remote={props.remote}
 | ||||||
|               {...(props.remote && { remoteMethod })} |               {...(props.remote && { remoteMethod })} | ||||||
|  | @ -212,7 +220,9 @@ export const useApiSelect = (option: ApiSelectProps) => { | ||||||
|           <Select |           <Select | ||||||
|             class="w-full" |             class="w-full" | ||||||
|             loading={loading.value} |             loading={loading.value} | ||||||
|             {...attrs} |             onUpdate:value={onUpdateModelValue as any} | ||||||
|  |             value={modelValue as any} | ||||||
|  |             {...restAttrs} | ||||||
|             // TODO: @dhb52 remote 对等实现, 还是说没作用
 |             // TODO: @dhb52 remote 对等实现, 还是说没作用
 | ||||||
|             // remote={props.remote}
 |             // remote={props.remote}
 | ||||||
|             {...(props.remote && { remoteMethod })} |             {...(props.remote && { remoteMethod })} | ||||||
|  | @ -228,6 +238,11 @@ export const useApiSelect = (option: ApiSelectProps) => { | ||||||
|         ); |         ); | ||||||
|       }; |       }; | ||||||
|       const buildCheckbox = () => { |       const buildCheckbox = () => { | ||||||
|  |         const { | ||||||
|  |           modelValue, | ||||||
|  |           'onUpdate:modelValue': onUpdateModelValue, | ||||||
|  |           ...restAttrs | ||||||
|  |         } = attrs; | ||||||
|         if (isEmpty(options.value)) { |         if (isEmpty(options.value)) { | ||||||
|           options.value = [ |           options.value = [ | ||||||
|             { label: '选项1', value: '选项1' }, |             { label: '选项1', value: '选项1' }, | ||||||
|  | @ -235,7 +250,12 @@ export const useApiSelect = (option: ApiSelectProps) => { | ||||||
|           ]; |           ]; | ||||||
|         } |         } | ||||||
|         return ( |         return ( | ||||||
|           <CheckboxGroup class="w-full" {...attrs}> |           <CheckboxGroup | ||||||
|  |             class="w-full" | ||||||
|  |             onUpdate:value={onUpdateModelValue as any} | ||||||
|  |             value={modelValue as any} | ||||||
|  |             {...restAttrs} | ||||||
|  |           > | ||||||
|             {options.value.map( |             {options.value.map( | ||||||
|               (item: { label: any; value: any }, index: any) => ( |               (item: { label: any; value: any }, index: any) => ( | ||||||
|                 <Checkbox key={index} value={item.value}> |                 <Checkbox key={index} value={item.value}> | ||||||
|  | @ -247,6 +267,11 @@ export const useApiSelect = (option: ApiSelectProps) => { | ||||||
|         ); |         ); | ||||||
|       }; |       }; | ||||||
|       const buildRadio = () => { |       const buildRadio = () => { | ||||||
|  |         const { | ||||||
|  |           modelValue, | ||||||
|  |           'onUpdate:modelValue': onUpdateModelValue, | ||||||
|  |           ...restAttrs | ||||||
|  |         } = attrs; | ||||||
|         if (isEmpty(options.value)) { |         if (isEmpty(options.value)) { | ||||||
|           options.value = [ |           options.value = [ | ||||||
|             { label: '选项1', value: '选项1' }, |             { label: '选项1', value: '选项1' }, | ||||||
|  | @ -254,7 +279,12 @@ export const useApiSelect = (option: ApiSelectProps) => { | ||||||
|           ]; |           ]; | ||||||
|         } |         } | ||||||
|         return ( |         return ( | ||||||
|           <RadioGroup class="w-full" {...attrs}> |           <RadioGroup | ||||||
|  |             class="w-full" | ||||||
|  |             onUpdate:value={onUpdateModelValue as any} | ||||||
|  |             value={modelValue as any} | ||||||
|  |             {...restAttrs} | ||||||
|  |           > | ||||||
|             {options.value.map( |             {options.value.map( | ||||||
|               (item: { label: any; value: any }, index: any) => ( |               (item: { label: any; value: any }, index: any) => ( | ||||||
|                 <Radio key={index} value={item.value}> |                 <Radio key={index} value={item.value}> | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| import type { BpmProcessDefinitionApi } from '#/api/bpm/definition'; | import type { BpmProcessDefinitionApi } from '#/api/bpm/definition'; | ||||||
|  | import type { BpmProcessInstanceApi } from '#/api/bpm/processInstance'; | ||||||
| 
 | 
 | ||||||
| import { computed, nextTick, ref, watch } from 'vue'; | import { computed, nextTick, ref, watch } from 'vue'; | ||||||
| 
 | 
 | ||||||
|  | @ -20,7 +21,6 @@ import { | ||||||
|   BpmModelFormType, |   BpmModelFormType, | ||||||
|   BpmModelType, |   BpmModelType, | ||||||
|   BpmNodeIdEnum, |   BpmNodeIdEnum, | ||||||
|   BpmNodeTypeEnum, |  | ||||||
|   decodeFields, |   decodeFields, | ||||||
|   setConfAndFields2, |   setConfAndFields2, | ||||||
| } from '#/utils'; | } from '#/utils'; | ||||||
|  | @ -39,22 +39,6 @@ interface UserTask { | ||||||
|   name: string; |   name: string; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface ApprovalNodeInfo { |  | ||||||
|   id: number; |  | ||||||
|   name: string; |  | ||||||
|   candidateStrategy: BpmCandidateStrategyEnum; |  | ||||||
|   candidateUsers?: Array<{ |  | ||||||
|     avatar: string; |  | ||||||
|     id: number; |  | ||||||
|     nickname: string; |  | ||||||
|   }>; |  | ||||||
|   endTime?: Date; |  | ||||||
|   nodeType: BpmNodeTypeEnum; |  | ||||||
|   startTime?: Date; |  | ||||||
|   status: number; |  | ||||||
|   tasks: any[]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| defineOptions({ name: 'BpmProcessInstanceCreateForm' }); | defineOptions({ name: 'BpmProcessInstanceCreateForm' }); | ||||||
| 
 | 
 | ||||||
| const props = defineProps({ | const props = defineProps({ | ||||||
|  | @ -86,7 +70,7 @@ const bpmnXML = ref<string | undefined>(undefined); | ||||||
| const simpleJson = ref<string | undefined>(undefined); | const simpleJson = ref<string | undefined>(undefined); | ||||||
| const timelineRef = ref<any>(); | const timelineRef = ref<any>(); | ||||||
| const activeTab = ref('form'); | const activeTab = ref('form'); | ||||||
| const activityNodes = ref<ApprovalNodeInfo[]>([]); | const activityNodes = ref<BpmProcessInstanceApi.ApprovalNodeInfo[]>([]); | ||||||
| const processInstanceStartLoading = ref(false); | const processInstanceStartLoading = ref(false); | ||||||
| 
 | 
 | ||||||
| /** 提交按钮 */ | /** 提交按钮 */ | ||||||
|  | @ -217,7 +201,7 @@ async function getApprovalDetail(row: { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // 获取审批节点 |     // 获取审批节点 | ||||||
|     activityNodes.value = data.activityNodes as unknown as ApprovalNodeInfo[]; |     activityNodes.value = data.activityNodes; | ||||||
| 
 | 
 | ||||||
|     // 获取发起人自选的任务 |     // 获取发起人自选的任务 | ||||||
|     startUserSelectTasks.value = (data.activityNodes?.filter( |     startUserSelectTasks.value = (data.activityNodes?.filter( | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ import type { BpmProcessInstanceApi } from '#/api/bpm/processInstance'; | ||||||
| import { ref } from 'vue'; | import { ref } from 'vue'; | ||||||
| import { useRouter } from 'vue-router'; | import { useRouter } from 'vue-router'; | ||||||
| 
 | 
 | ||||||
|  | import { useVbenModal } from '@vben/common-ui'; | ||||||
| import { IconifyIcon } from '@vben/icons'; | import { IconifyIcon } from '@vben/icons'; | ||||||
| import { formatDateTime, isEmpty } from '@vben/utils'; | import { formatDateTime, isEmpty } from '@vben/utils'; | ||||||
| 
 | 
 | ||||||
|  | @ -102,7 +103,7 @@ const nodeTypeSvgMap = { | ||||||
|     color: '#14bb83', |     color: '#14bb83', | ||||||
|     icon: 'icon-park-outline:tree-diagram', |     icon: 'icon-park-outline:tree-diagram', | ||||||
|   }, |   }, | ||||||
| }; | } as Record<BpmNodeTypeEnum, { color: string; icon: string }>; | ||||||
| 
 | 
 | ||||||
| // 只有状态是 -1、0、1 才展示头像右小角状态小icon | // 只有状态是 -1、0、1 才展示头像右小角状态小icon | ||||||
| const onlyStatusIconShow = [-1, 0, 1]; | const onlyStatusIconShow = [-1, 0, 1]; | ||||||
|  | @ -150,21 +151,27 @@ function getApprovalNodeTime(node: BpmProcessInstanceApi.ApprovalNodeInfo) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // 选择自定义审批人 | // 选择自定义审批人 | ||||||
| const userSelectFormRef = ref(); | const [UserSelectModalComp, userSelectModalApi] = useVbenModal({ | ||||||
|  |   connectedComponent: UserSelectModal, | ||||||
|  |   destroyOnClose: true, | ||||||
|  | }); | ||||||
| const selectedActivityNodeId = ref<string>(); | const selectedActivityNodeId = ref<string>(); | ||||||
| const customApproveUsers = ref<Record<string, any[]>>({}); // key:activityId,value:用户列表 | const customApproveUsers = ref<Record<string, any[]>>({}); // key:activityId,value:用户列表 | ||||||
| 
 | 
 | ||||||
| // 打开选择用户弹窗 | // 打开选择用户弹窗 | ||||||
| const handleSelectUser = (activityId: string, selectedList: any[]) => { | const handleSelectUser = (activityId: string, selectedList: any[]) => { | ||||||
|   selectedActivityNodeId.value = activityId; |   selectedActivityNodeId.value = activityId; | ||||||
|   userSelectFormRef.value.open( |   userSelectModalApi | ||||||
|     selectedList?.length ? selectedList.map((item) => item.id) : [], |     .setData({ userIds: selectedList.map((item) => item.id) }) | ||||||
|   ); |     .open(); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // 选择用户完成 | // 选择用户完成 | ||||||
| const selectedUsers = ref<number[]>([]); | const selectedUsers = ref<number[]>([]); | ||||||
| function handleUserSelectConfirm(userList: any[]) { | function handleUserSelectConfirm(userList: any[]) { | ||||||
|  |   if (!selectedActivityNodeId.value) { | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|   customApproveUsers.value[selectedActivityNodeId.value] = userList || []; |   customApproveUsers.value[selectedActivityNodeId.value] = userList || []; | ||||||
| 
 | 
 | ||||||
|   emit('selectUserConfirm', selectedActivityNodeId.value, userList); |   emit('selectUserConfirm', selectedActivityNodeId.value, userList); | ||||||
|  | @ -289,8 +296,12 @@ function handleUserSelectCancel() { | ||||||
|                 type="primary" |                 type="primary" | ||||||
|                 size="middle" |                 size="middle" | ||||||
|                 ghost |                 ghost | ||||||
|  |                 class="flex items-center justify-center" | ||||||
|                 @click=" |                 @click=" | ||||||
|                   handleSelectUser(activity.id, customApproveUsers[activity.id]) |                   handleSelectUser( | ||||||
|  |                     activity.id, | ||||||
|  |                     customApproveUsers[activity.id] ?? [], | ||||||
|  |                   ) | ||||||
|                 " |                 " | ||||||
|               > |               > | ||||||
|                 <template #icon> |                 <template #icon> | ||||||
|  | @ -445,8 +456,7 @@ function handleUserSelectCancel() { | ||||||
|     </Timeline> |     </Timeline> | ||||||
| 
 | 
 | ||||||
|     <!-- 用户选择弹窗 --> |     <!-- 用户选择弹窗 --> | ||||||
|     <UserSelectModal |     <UserSelectModalComp | ||||||
|       ref="userSelectFormRef" |  | ||||||
|       v-model:value="selectedUsers" |       v-model:value="selectedUsers" | ||||||
|       :multiple="true" |       :multiple="true" | ||||||
|       title="选择用户" |       title="选择用户" | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 xingyu
						xingyu