提交 | 用户 | 时间
820397 1 <template>
H 2
3   <ContentWrap>
4     <!-- 搜索工作栏 -->
5     <el-form
6       class="-mb-15px"
7       :model="queryParams"
8       ref="queryFormRef"
9       :inline="true"
10       label-width="68px"
11     >
3e359e 12       <el-form-item label="" prop="name">
820397 13         <el-input
H 14           v-model="queryParams.name"
15           placeholder="请输入流程名称"
16           clearable
17           @keyup.enter="handleQuery"
18           class="!w-240px"
19         />
20       </el-form-item>
3e359e 21
H 22       <el-form-item>
23         <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
820397 24       </el-form-item>
3e359e 25
H 26       <!-- TODO @ tuituji:style 可以使用 unocss -->
27       <el-form-item label="" prop="category" :style="{ position: 'absolute', right: '130px' }">
28         <!-- TODO @tuituji:应该选择好分类,就触发搜索啦。 -->
820397 29         <el-select
H 30           v-model="queryParams.category"
31           placeholder="请选择流程分类"
32           clearable
3e359e 33           class="!w-155px"
820397 34         >
H 35           <el-option
36             v-for="category in categoryList"
37             :key="category.code"
38             :label="category.name"
39             :value="category.code"
40           />
41         </el-select>
42       </el-form-item>
3e359e 43
H 44       <!-- 高级筛选 -->
45       <!-- TODO @ tuituji:style 可以使用 unocss -->
46       <el-form-item :style="{ position: 'absolute', right: '0px' }">
47         <el-button v-popover="popoverRef" v-click-outside="onClickOutside" :icon="List">
48           高级筛选
820397 49         </el-button>
3e359e 50         <el-popover
H 51           ref="popoverRef"
52           trigger="click"
53           virtual-triggering
54           persistent
55           :width="400"
56           :show-arrow="false"
57           placement="bottom-end"
58         >
59           <el-form-item label="流程发起人" class="bold-label" label-position="top" prop="category">
60             <el-select
61               v-model="queryParams.category"
62               placeholder="请选择流程发起人"
63               clearable
64               class="!w-390px"
65             >
66               <el-option
67                 v-for="category in categoryList"
68                 :key="category.code"
69                 :label="category.name"
70                 :value="category.code"
71               />
72             </el-select>
73           </el-form-item>
74           <el-form-item
75             label="所属流程"
76             class="bold-label"
77             label-position="top"
78             prop="processDefinitionKey"
79           >
80             <el-input
81               v-model="queryParams.processDefinitionKey"
82               placeholder="请输入流程定义的标识"
83               clearable
84               @keyup.enter="handleQuery"
85               class="!w-390px"
86             />
87           </el-form-item>
88           <el-form-item label="流程状态" class="bold-label" label-position="top" prop="status">
89             <el-select
90               v-model="queryParams.status"
91               placeholder="请选择流程状态"
92               clearable
93               class="!w-390px"
94             >
95               <el-option
96                 v-for="dict in getIntDictOptions(DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS)"
97                 :key="dict.value"
98                 :label="dict.label"
99                 :value="dict.value"
100               />
101             </el-select>
102           </el-form-item>
103           <el-form-item label="发起时间" class="bold-label" label-position="top" prop="createTime">
104             <el-date-picker
105               v-model="queryParams.createTime"
106               value-format="YYYY-MM-DD HH:mm:ss"
107               type="daterange"
108               start-placeholder="开始日期"
109               end-placeholder="结束日期"
110               :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
111               class="!w-240px"
112             />
113           </el-form-item>
114         </el-popover>
115         <!-- TODO @tuituji:这里应该有确认,和取消、清空搜索条件,三个按钮。 -->
820397 116       </el-form-item>
H 117     </el-form>
118   </ContentWrap>
119
120   <!-- 列表 -->
121   <ContentWrap>
122     <el-table v-loading="loading" :data="list">
123       <el-table-column label="流程名称" align="center" prop="name" min-width="200px" fixed="left" />
124       <el-table-column
125         label="流程分类"
126         align="center"
127         prop="categoryName"
128         min-width="100"
129         fixed="left"
130       />
3e359e 131       <!-- TODO @芋艿:摘要 -->
H 132       <!-- TODO @tuituji:流程状态。可见需求文档里  -->
820397 133       <el-table-column label="流程状态" prop="status" width="120">
H 134         <template #default="scope">
135           <dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS" :value="scope.row.status" />
136         </template>
137       </el-table-column>
138       <el-table-column
139         label="发起时间"
140         align="center"
141         prop="startTime"
142         width="180"
143         :formatter="dateFormatter"
144       />
145       <el-table-column
146         label="结束时间"
147         align="center"
148         prop="endTime"
149         width="180"
150         :formatter="dateFormatter"
151       />
3e359e 152       <!--<el-table-column align="center" label="耗时" prop="durationInMillis" width="160">
820397 153         <template #default="scope">
H 154           {{ scope.row.durationInMillis > 0 ? formatPast2(scope.row.durationInMillis) : '-' }}
155         </template>
156       </el-table-column>
157       <el-table-column label="当前审批任务" align="center" prop="tasks" min-width="120px">
158         <template #default="scope">
159           <el-button type="primary" v-for="task in scope.row.tasks" :key="task.id" link>
160             <span>{{ task.name }}</span>
161           </el-button>
162         </template>
163       </el-table-column>
3e359e 164       -->
820397 165       <el-table-column label="操作" align="center" fixed="right" width="180">
H 166         <template #default="scope">
167           <el-button
168             link
169             type="primary"
170             v-hasPermi="['bpm:process-instance:cancel']"
171             @click="handleDetail(scope.row)"
172           >
173             详情
174           </el-button>
175           <el-button
176             link
177             type="primary"
178             v-if="scope.row.status === 1"
179             v-hasPermi="['bpm:process-instance:query']"
180             @click="handleCancel(scope.row)"
181           >
182             取消
183           </el-button>
184           <el-button link type="primary" v-else @click="handleCreate(scope.row)">
185             重新发起
186           </el-button>
187         </template>
188       </el-table-column>
189     </el-table>
190     <!-- 分页 -->
191     <Pagination
192       :total="total"
193       v-model:page="queryParams.pageNo"
194       v-model:limit="queryParams.pageSize"
195       @pagination="getList"
196     />
197   </ContentWrap>
198 </template>
199 <script lang="ts" setup>
3e359e 200 // TODO @tuituji:List 改成 <Icon icon="ep:plus" class="mr-5px" /> 类似这种组件哈。
H 201 import { List } from '@element-plus/icons-vue'
820397 202 import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
3e359e 203 import { dateFormatter } from '@/utils/formatTime'
820397 204 import { ElMessageBox } from 'element-plus'
H 205 import * as ProcessInstanceApi from '@/api/bpm/processInstance'
3e359e 206 import { CategoryApi, CategoryVO } from '@/api/bpm/category'
820397 207 import { ProcessInstanceVO } from '@/api/bpm/processInstance'
H 208 import * as DefinitionApi from '@/api/bpm/definition'
209
210 defineOptions({ name: 'BpmProcessInstanceMy' })
211
212 const router = useRouter() // 路由
213 const message = useMessage() // 消息弹窗
214 const { t } = useI18n() // 国际化
215
216 const loading = ref(true) // 列表的加载中
217 const total = ref(0) // 列表的总页数
218 const list = ref([]) // 列表的数据
219 const queryParams = reactive({
220   pageNo: 1,
221   pageSize: 10,
222   name: '',
3e359e 223   processDefinitionKey: undefined,
820397 224   category: undefined,
H 225   status: undefined,
226   createTime: []
227 })
228 const queryFormRef = ref() // 搜索的表单
3e359e 229 const categoryList = ref<CategoryVO[]>([]) // 流程分类列表
820397 230
H 231 /** 查询列表 */
232 const getList = async () => {
233   loading.value = true
234   try {
235     const data = await ProcessInstanceApi.getProcessInstanceMyPage(queryParams)
236     list.value = data.list
237     total.value = data.total
238   } finally {
239     loading.value = false
240   }
241 }
242
243 /** 搜索按钮操作 */
244 const handleQuery = () => {
245   queryParams.pageNo = 1
246   getList()
247 }
248
249 /** 重置按钮操作 */
250 const resetQuery = () => {
251   queryFormRef.value.resetFields()
252   handleQuery()
253 }
254
255 /** 发起流程操作 **/
256 const handleCreate = async (row?: ProcessInstanceVO) => {
257   // 如果是【业务表单】,不支持重新发起
258   if (row?.id) {
259     const processDefinitionDetail = await DefinitionApi.getProcessDefinition(
260       row.processDefinitionId
261     )
262     if (processDefinitionDetail.formType === 20) {
263       message.error('重新发起流程失败,原因:该流程使用业务表单,不支持重新发起')
264       return
265     }
266   }
267   // 跳转发起流程界面
268   await router.push({
269     name: 'BpmProcessInstanceCreate',
270     query: { processInstanceId: row?.id }
271   })
272 }
273
274 /** 查看详情 */
275 const handleDetail = (row) => {
276   router.push({
277     name: 'BpmProcessInstanceDetail',
278     query: {
279       id: row.id
280     }
281   })
282 }
283
284 /** 取消按钮操作 */
285 const handleCancel = async (row) => {
286   // 二次确认
287   const { value } = await ElMessageBox.prompt('请输入取消原因', '取消流程', {
288     confirmButtonText: t('common.ok'),
289     cancelButtonText: t('common.cancel'),
290     inputPattern: /^[\s\S]*.*\S[\s\S]*$/, // 判断非空,且非空格
291     inputErrorMessage: '取消原因不能为空'
292   })
293   // 发起取消
294   await ProcessInstanceApi.cancelProcessInstanceByStartUser(row.id, value)
295   message.success('取消成功')
296   // 刷新列表
297   await getList()
298 }
299
3e359e 300 // TODO @tuituji:这个 import 是不是没用哈?
H 301 import { ClickOutside as vClickOutside } from 'element-plus'
302
303 // TODO @tuituji:onClickAdvancedSearch。方法名叫这个,会更好一些哇?打开高级搜索。
304 const popoverRef = ref()
305 const onClickOutside = () => {
306   unref(popoverRef).popperRef?.delayHide?.()
307 }
308
820397 309 /** 激活时 **/
H 310 onActivated(() => {
311   getList()
312 })
313
314 /** 初始化 **/
315 onMounted(async () => {
316   await getList()
317   categoryList.value = await CategoryApi.getCategorySimpleList()
318 })
319 </script>
3e359e 320 <style>
H 321 .bold-label .el-form-item__label {
322   font-weight: bold; /* 将字体加粗 */
323 }
324 </style>