提交 | 用户 | 时间
|
c9a6f7
|
1 |
<template> |
H |
2 |
<el-form ref="formRef" :model="modelData" :rules="rules" label-width="120px" class="mt-20px"> |
|
3 |
<el-form-item label="流程标识" prop="key" class="mb-20px"> |
|
4 |
<div class="flex items-center"> |
|
5 |
<el-input |
|
6 |
class="!w-440px" |
|
7 |
v-model="modelData.key" |
|
8 |
:disabled="!!modelData.id" |
|
9 |
placeholder="请输入流标标识" |
|
10 |
/> |
|
11 |
<el-tooltip |
|
12 |
class="item" |
|
13 |
:content="modelData.id ? '流程标识不可修改!' : '新建后,流程标识不可修改!'" |
|
14 |
effect="light" |
|
15 |
placement="top" |
|
16 |
> |
|
17 |
<Icon icon="ep:question-filled" class="ml-5px" /> |
|
18 |
</el-tooltip> |
|
19 |
</div> |
|
20 |
</el-form-item> |
|
21 |
<el-form-item label="流程名称" prop="name" class="mb-20px"> |
|
22 |
<el-input |
|
23 |
v-model="modelData.name" |
|
24 |
:disabled="!!modelData.id" |
|
25 |
clearable |
|
26 |
placeholder="请输入流程名称" |
|
27 |
/> |
|
28 |
</el-form-item> |
|
29 |
<el-form-item label="流程分类" prop="category" class="mb-20px"> |
|
30 |
<el-select |
|
31 |
class="!w-full" |
|
32 |
v-model="modelData.category" |
|
33 |
clearable |
|
34 |
placeholder="请选择流程分类" |
|
35 |
> |
|
36 |
<el-option |
|
37 |
v-for="category in categoryList" |
|
38 |
:key="category.code" |
|
39 |
:label="category.name" |
|
40 |
:value="category.code" |
|
41 |
/> |
|
42 |
</el-select> |
|
43 |
</el-form-item> |
|
44 |
<el-form-item label="流程图标" prop="icon" class="mb-20px"> |
|
45 |
<UploadImg v-model="modelData.icon" :limit="1" height="64px" width="64px" /> |
|
46 |
</el-form-item> |
|
47 |
<el-form-item label="流程描述" prop="description" class="mb-20px"> |
|
48 |
<el-input v-model="modelData.description" clearable type="textarea" /> |
|
49 |
</el-form-item> |
|
50 |
<el-form-item label="流程类型" prop="type" class="mb-20px"> |
|
51 |
<el-radio-group v-model="modelData.type"> |
|
52 |
<el-radio |
|
53 |
v-for="dict in getIntDictOptions(DICT_TYPE.BPM_MODEL_TYPE)" |
|
54 |
:key="dict.value" |
|
55 |
:value="dict.value" |
|
56 |
> |
|
57 |
{{ dict.label }} |
|
58 |
</el-radio> |
|
59 |
</el-radio-group> |
|
60 |
</el-form-item> |
|
61 |
<el-form-item label="是否可见" prop="visible" class="mb-20px"> |
|
62 |
<el-radio-group v-model="modelData.visible"> |
|
63 |
<el-radio |
|
64 |
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" |
|
65 |
:key="dict.value" |
|
66 |
:value="dict.value" |
|
67 |
> |
|
68 |
{{ dict.label }} |
|
69 |
</el-radio> |
|
70 |
</el-radio-group> |
|
71 |
</el-form-item> |
|
72 |
<el-form-item label="谁可以发起" prop="startUserType" class="mb-20px"> |
|
73 |
<el-select |
|
74 |
v-model="modelData.startUserType" |
|
75 |
placeholder="请选择谁可以发起" |
|
76 |
@change="handleStartUserTypeChange" |
|
77 |
> |
|
78 |
<el-option label="全员" :value="0" /> |
|
79 |
<el-option label="指定人员" :value="1" /> |
|
80 |
<el-option label="均不可提交" :value="2" /> |
|
81 |
</el-select> |
|
82 |
<div v-if="modelData.startUserType === 1" class="mt-2 flex flex-wrap gap-2"> |
|
83 |
<div |
|
84 |
v-for="user in selectedStartUsers" |
|
85 |
:key="user.id" |
|
86 |
class="bg-gray-100 h-35px rounded-3xl flex items-center pr-8px dark:color-gray-600 position-relative" |
|
87 |
> |
|
88 |
<el-avatar class="!m-5px" :size="28" v-if="user.avatar" :src="user.avatar" /> |
|
89 |
<el-avatar class="!m-5px" :size="28" v-else> |
|
90 |
{{ user.nickname.substring(0, 1) }} |
|
91 |
</el-avatar> |
|
92 |
{{ user.nickname }} |
|
93 |
<Icon |
|
94 |
icon="ep:close" |
|
95 |
class="ml-2 cursor-pointer hover:text-red-500" |
|
96 |
@click="handleRemoveStartUser(user)" |
|
97 |
/> |
|
98 |
</div> |
|
99 |
<el-button type="primary" link @click="openStartUserSelect"> |
|
100 |
<Icon icon="ep:plus" />选择人员 |
|
101 |
</el-button> |
|
102 |
</div> |
|
103 |
</el-form-item> |
|
104 |
<el-form-item label="流程管理员" prop="managerUserType" class="mb-20px"> |
|
105 |
<el-select |
|
106 |
v-model="modelData.managerUserType" |
|
107 |
placeholder="请选择流程管理员" |
|
108 |
@change="handleManagerUserTypeChange" |
|
109 |
> |
|
110 |
<el-option label="全员" :value="0" /> |
|
111 |
<el-option label="指定人员" :value="1" /> |
|
112 |
<el-option label="均不可提交" :value="2" /> |
|
113 |
</el-select> |
|
114 |
<div v-if="modelData.managerUserType === 1" class="mt-2 flex flex-wrap gap-2"> |
|
115 |
<div |
|
116 |
v-for="user in selectedManagerUsers" |
|
117 |
:key="user.id" |
|
118 |
class="bg-gray-100 h-35px rounded-3xl flex items-center pr-8px dark:color-gray-600 position-relative" |
|
119 |
> |
|
120 |
<el-avatar class="!m-5px" :size="28" v-if="user.avatar" :src="user.avatar" /> |
|
121 |
<el-avatar class="!m-5px" :size="28" v-else> |
|
122 |
{{ user.nickname.substring(0, 1) }} |
|
123 |
</el-avatar> |
|
124 |
{{ user.nickname }} |
|
125 |
<Icon |
|
126 |
icon="ep:close" |
|
127 |
class="ml-2 cursor-pointer hover:text-red-500" |
|
128 |
@click="handleRemoveManagerUser(user)" |
|
129 |
/> |
|
130 |
</div> |
|
131 |
<el-button type="primary" link @click="openManagerUserSelect"> |
|
132 |
<Icon icon="ep:plus" />选择人员 |
|
133 |
</el-button> |
|
134 |
</div> |
|
135 |
</el-form-item> |
|
136 |
</el-form> |
|
137 |
|
|
138 |
<!-- 用户选择弹窗 --> |
|
139 |
<UserSelectForm ref="userSelectFormRef" @confirm="handleUserSelectConfirm" /> |
|
140 |
</template> |
|
141 |
|
|
142 |
<script lang="ts" setup> |
|
143 |
import { DICT_TYPE, getBoolDictOptions, getIntDictOptions } from '@/utils/dict' |
|
144 |
import { UserVO } from '@/api/system/user' |
|
145 |
|
|
146 |
const props = defineProps({ |
|
147 |
modelValue: { |
|
148 |
type: Object, |
|
149 |
required: true |
|
150 |
}, |
|
151 |
categoryList: { |
|
152 |
type: Array, |
|
153 |
required: true |
|
154 |
}, |
|
155 |
userList: { |
|
156 |
type: Array, |
|
157 |
required: true |
|
158 |
} |
|
159 |
}) |
|
160 |
|
|
161 |
const emit = defineEmits(['update:modelValue']) |
|
162 |
|
|
163 |
const formRef = ref() |
|
164 |
const selectedStartUsers = ref<UserVO[]>([]) |
|
165 |
const selectedManagerUsers = ref<UserVO[]>([]) |
|
166 |
const userSelectFormRef = ref() |
|
167 |
const currentSelectType = ref<'start' | 'manager'>('start') |
|
168 |
|
|
169 |
const rules = { |
|
170 |
name: [{ required: true, message: '流程名称不能为空', trigger: 'blur' }], |
|
171 |
key: [{ required: true, message: '流程标识不能为空', trigger: 'blur' }], |
|
172 |
category: [{ required: true, message: '流程分类不能为空', trigger: 'blur' }], |
|
173 |
icon: [{ required: true, message: '流程图标不能为空', trigger: 'blur' }], |
|
174 |
type: [{ required: true, message: '是否可见不能为空', trigger: 'blur' }], |
|
175 |
visible: [{ required: true, message: '是否可见不能为空', trigger: 'blur' }], |
|
176 |
managerUserIds: [{ required: true, message: '流程管理员不能为空', trigger: 'blur' }] |
|
177 |
} |
|
178 |
|
|
179 |
// 创建本地数据副本 |
|
180 |
const modelData = computed({ |
|
181 |
get: () => props.modelValue, |
|
182 |
set: (val) => emit('update:modelValue', val) |
|
183 |
}) |
|
184 |
|
|
185 |
// 初始化选中的用户 |
|
186 |
watch( |
|
187 |
() => props.modelValue, |
|
188 |
(newVal) => { |
|
189 |
if (newVal.startUserIds?.length) { |
|
190 |
selectedStartUsers.value = props.userList.filter((user: UserVO) => |
|
191 |
newVal.startUserIds.includes(user.id) |
|
192 |
) as UserVO[] |
|
193 |
} |
|
194 |
if (newVal.managerUserIds?.length) { |
|
195 |
selectedManagerUsers.value = props.userList.filter((user: UserVO) => |
|
196 |
newVal.managerUserIds.includes(user.id) |
|
197 |
) as UserVO[] |
|
198 |
} |
|
199 |
}, |
|
200 |
{ immediate: true } |
|
201 |
) |
|
202 |
|
|
203 |
/** 打开发起人选择 */ |
|
204 |
const openStartUserSelect = () => { |
|
205 |
currentSelectType.value = 'start' |
|
206 |
userSelectFormRef.value.open(0, selectedStartUsers.value) |
|
207 |
} |
|
208 |
|
|
209 |
/** 打开管理员选择 */ |
|
210 |
const openManagerUserSelect = () => { |
|
211 |
currentSelectType.value = 'manager' |
|
212 |
userSelectFormRef.value.open(0, selectedManagerUsers.value) |
|
213 |
} |
|
214 |
|
|
215 |
/** 处理用户选择确认 */ |
|
216 |
const handleUserSelectConfirm = (_, users: UserVO[]) => { |
|
217 |
if (currentSelectType.value === 'start') { |
|
218 |
selectedStartUsers.value = users |
|
219 |
emit('update:modelValue', { |
|
220 |
...modelData.value, |
|
221 |
startUserIds: users.map((u) => u.id) |
|
222 |
}) |
|
223 |
} else { |
|
224 |
selectedManagerUsers.value = users |
|
225 |
emit('update:modelValue', { |
|
226 |
...modelData.value, |
|
227 |
managerUserIds: users.map((u) => u.id) |
|
228 |
}) |
|
229 |
} |
|
230 |
} |
|
231 |
|
|
232 |
/** 处理发起人类型变化 */ |
|
233 |
const handleStartUserTypeChange = (value: number) => { |
|
234 |
if (value !== 1) { |
|
235 |
selectedStartUsers.value = [] |
|
236 |
emit('update:modelValue', { |
|
237 |
...modelData.value, |
|
238 |
startUserIds: [] |
|
239 |
}) |
|
240 |
} |
|
241 |
} |
|
242 |
|
|
243 |
/** 处理管理员类型变化 */ |
|
244 |
const handleManagerUserTypeChange = (value: number) => { |
|
245 |
if (value !== 1) { |
|
246 |
selectedManagerUsers.value = [] |
|
247 |
emit('update:modelValue', { |
|
248 |
...modelData.value, |
|
249 |
managerUserIds: [] |
|
250 |
}) |
|
251 |
} |
|
252 |
} |
|
253 |
|
|
254 |
/** 移除发起人 */ |
|
255 |
const handleRemoveStartUser = (user: UserVO) => { |
|
256 |
selectedStartUsers.value = selectedStartUsers.value.filter((u) => u.id !== user.id) |
|
257 |
emit('update:modelValue', { |
|
258 |
...modelData.value, |
|
259 |
startUserIds: modelData.value.startUserIds.filter((id: number) => id !== user.id) |
|
260 |
}) |
|
261 |
} |
|
262 |
|
|
263 |
/** 移除管理员 */ |
|
264 |
const handleRemoveManagerUser = (user: UserVO) => { |
|
265 |
selectedManagerUsers.value = selectedManagerUsers.value.filter((u) => u.id !== user.id) |
|
266 |
emit('update:modelValue', { |
|
267 |
...modelData.value, |
|
268 |
managerUserIds: modelData.value.managerUserIds.filter((id: number) => id !== user.id) |
|
269 |
}) |
|
270 |
} |
|
271 |
|
|
272 |
/** 表单校验 */ |
|
273 |
const validate = async () => { |
|
274 |
await formRef.value?.validate() |
|
275 |
} |
|
276 |
|
|
277 |
defineExpose({ |
|
278 |
validate |
|
279 |
}) |
|
280 |
</script> |
|
281 |
|
|
282 |
<style lang="scss" scoped> |
|
283 |
.bg-gray-100 { |
|
284 |
background-color: #f5f7fa; |
|
285 |
transition: all 0.3s; |
|
286 |
|
|
287 |
&:hover { |
|
288 |
background-color: #e6e8eb; |
|
289 |
} |
|
290 |
|
|
291 |
.ep-close { |
|
292 |
font-size: 14px; |
|
293 |
color: #909399; |
|
294 |
transition: color 0.3s; |
|
295 |
|
|
296 |
&:hover { |
|
297 |
color: #f56c6c; |
|
298 |
} |
|
299 |
} |
|
300 |
} |
|
301 |
</style> |