!88 合并flowable工作流功能
* merge 合并dev * add 添加抄送查询 * add 添加我的已办 * add 添加抄送 * add 添加附件下载 * update 优化类型 * Merge remote-tracking branch 'origin/future/flowable' into future/flowable * fix 修复 流程设计器打包部署报错问题 * add 添加审批附件上传 * update 修复固定值未在xml显示问题 * update 修复跳转条件回显Object问题 * update 优化面板文件名称 * update 调整key * remove 移除旧设计器,添加xml保存 * update 增加任务面板提示 * update 优化xml预览和svg预览 * update 优化xml预览和svg预览 * update 优化模型设计 * update 优化设计器 * update 优化设计器 * update 优化设计器 * update 删除旧设计器 * update 删除console.log * add 添加模型接口 * update 优化预览xml和svg样式被修改问题 * update 优化属性面板,增加展开动画 * update 去除开发模式 * update 优化任务栏样式 * update 优化图标渲染样式 * update 增加BpmnFactory类型 * update 增加BpmnFactory * update 移除users和group * update 移除无用类型 * update 优化页面类型 * update 去除多余属性 * update 完善流程线 * update 增加复杂网关 * update 完善流程 * update 完善网关 * update 优化网关汉化 * update 优化过期时间选择 * update 支持多实例 * update 增加类容提示 * update 支持选择组 * update 新增角色api * update 优化roleSelect 选中未确定,再次打开还保留选中的问题 * update 优化userSelect 选中未确定,再次打开还保留选中的问题 * update 优化userSelect 选中未确定,再次打开还保留选中的问题 * update 去掉modeler store多余属性 bpmnModel * update 优化属性面板,当面板未选中时默认展示流程面板 * update 优化TaskPanel类型,去掉roles属性 * update 优化用户api * update 优化用户选择器 * update 优化执行监听器 * update 优化任务监听器 * update 优化usePanel方法 * update 选人优化 * update 增加扩展节点信息 * update 增加usePanel默认方法 * update 去除处理事件 * update 扩展flowable userinfo属性 * update 全局modeler 改为非响应式 * update 增加hooks方法 * update 修改命名 * update 修改面板formData来源 * update 重写用户任务面板选择逻辑 * update 重写用户任务面板选择逻辑 * update 修改用户选择组件获取数据逻辑 * update 修改枚举类型 * update 修改默认配置列 * update 增加修改节点方法 * update 调整预览窗口大小 * update 优化用户选择组件 返回值 * update 优化用户选择组件 * update 新增通过ids 获取用户信息 * update 重写task面板选人 未完成 * update 升级用户选择 支持多选配置 * update 升级bpmnjs依赖版本 * update 增加useDialog类型 * update 调整全局样式 * update 代码高亮设置 * update 优化领用,归还加载 * update 增加选择角色 * update 新增角色选择组件 * update 新增过期时间选择组件 * update 调整任务面板样式 * update 调整全局dialog header 增加分割线 * update 代码高亮设置 * update 调整面板位置 * update 封装用户选择组件 * update 移除所有的节点描述 * update 删除分类 * update 调整面板位置 * update 修改命名,增加自定义渲染 * update 修改命名,增加自定义渲染 * update 增加 Element类型定义 * update 调整样式 * update 移除bpmn panel依赖,升级bpmn.js依赖到最新,修改汉化包 * update 调整类型声明文件 * update 调整类型声明文件 * update 优化面板工具 * update 优化面板工具 * Merge remote-tracking branch 'origin/future/flowable' into future/flowable * update 优化面板工具 * Merge branch 'future/flowable' of https://gitee.com/JavaLionLi/plus-ui… * add 添加修改办理人 * update 优化面板工具 * update 初始化流程数据 * Merge remote-tracking branch 'origin/future/flowable' into future/flowable * add 流程设计面板 * update 调整初始化xml * add 任务面板 * add 新增bpmn.js * update 优化request请求类判断请求头方式 * update 流程定义预览 优化 * update 流程定义预览 优化 * update 去掉console.log * update 优化工作流代码 * fix 修复待办任务 重置查询条件失效问题 * add 增加待办任务 接口类型,优化页面 * add 增加vite 启动预编译css * fix 修复i18n无感刷新问题 * Merge branch 'dev' into future/flowable * update 调整选择请假事件 * Merge branch 'dev' into future/flowable * 同步dev代码 * Merge branch 'dev' into future/flowable * 合并dev * remove 设计器无用代码 调整请假查询 * update 调整请假申请 * update 移动请假表单包结构,调整设计器选择引用表单请求错误 * remove 移除动态表单 * update 调整流程办理 * Merge branch 'dev' into future/flowable * Merge branch 'dev' into future/flowable * Merge branch 'dev' into future/flowable * Merge branch 'dev' into future/flowable * 合并 * update 调整请假申请流程提交 * update 修改业务单据流程提交 * update 调整业务单据流程提交 * 优化代码 * 优化工作流代码缩进 * 项目格式化配置修改 * 调整代码缩进 * Merge branch 'ts' into future/flowable * add 添加动态表单提交流程 * add 添加动态表单单据 * add 新增流程定义与表单关联 * update 调整点击左侧部门查询人员,部门刷新问题 * update 调整按钮图标 * 调整错别字 * update 调整流程定义图片预览 * add 添加流程实例迁移版本 * fix 修复我的单据无法提交问题 * Merge branch 'ts' into future/flowable * remove 还原代码后端解决 * update 流程设计器中分配发起人变量错误,先移除 * fix 修复设计器无法编辑问题 * update 调整设计器请求头 * Merge branch 'ts' into future/flowable * Merge branch 'ts' into future/flowable * add 添加流程定义历史列表 * update 审批记录v2改为v3 * update 调整请假必填项 * add 添加请假申请示例,添加流程定义文件部署 * update 移除流程表单 formConfig 属性,表单配置信息都放一起便于使用。 * add 添加任务加签,减签 * update 调整流程作废 * update 优化流程状态 * add 添加任务驳回 * add 添加查询当前租户所有待办,已办任务 * add 增加审批意见 * add 添加流程办理弹窗确认组件 * add 添加任务作废理由 * update 调整流程实例,流程定义检索 * add 添加我的单据页面 * add 添加任务归还认领 * add 添加流程实例,流程定义分类查询 * add 添加模型分类查询 * add 添加流程分类 * Merge remote-tracking branch 'origin/future/flowable' into future/flowable * add 添加流程表单管理页面 * add 集成vForm动态表单组件 * update xml调整超出滚动 * add 添加已办列表 * add 添加单据状态 * update 优化流程实例删除 * fix 修复流程实例查询挂起状态错误 * update 调整流程实例挂起激活状态 * add 添加流程实例列表 * update 调整流程定义弹窗提示 * add 添加流程定义列表,添加流程图,xml预览,添加简单流程启动,办理 * 调整审批记录悬浮逻辑 * 删除无用代码 * add 添加节点悬浮信息 * 调整流程预览 * 调整流程追踪 * add 添加审批记录 * add 模型设计的types * update 修改排版 * add lang=ts * update 修改ele的废弃api * fix调整审批记录图片不显示问题 * add 添加任务待办,流程图 * 调整设计器关闭 * add 添加待办 * remove 删除无用代码 * update types * 添加模型token验证 * 隐藏设计器验证按钮,隐藏表单,案例,应用程序等 * 添加模型部署 * 添加画图接口token,优化画图接口 * 添加工作流模型新增,修改,查询,删除,画图工具
This commit is contained in:
		
							
								
								
									
										263
									
								
								src/views/workflow/category/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								src/views/workflow/category/index.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,263 @@ | ||||
| <template> | ||||
|   <div class="p-2"> | ||||
|     <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> | ||||
|       <div v-show="showSearch" class="search"> | ||||
|         <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> | ||||
|           <el-form-item label="分类名称" prop="categoryName"> | ||||
|             <el-input v-model="queryParams.categoryName" placeholder="请输入分类名称" clearable @keyup.enter="handleQuery" /> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="分类编码" prop="categoryCode"> | ||||
|             <el-input v-model="queryParams.categoryCode" placeholder="请输入分类编码" clearable @keyup.enter="handleQuery" /> | ||||
|           </el-form-item> | ||||
|           <el-form-item> | ||||
|             <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> | ||||
|             <el-button icon="Refresh" @click="resetQuery">重置</el-button> | ||||
|           </el-form-item> | ||||
|         </el-form> | ||||
|       </div> | ||||
|     </transition> | ||||
|  | ||||
|     <el-card shadow="never"> | ||||
|       <template #header> | ||||
|         <el-row :gutter="10" class="mb8"> | ||||
|           <el-col :span="1.5"> | ||||
|             <el-button v-hasPermi="['workflow:category:add']" type="primary" plain icon="Plus" @click="handleAdd()">新增</el-button> | ||||
|           </el-col> | ||||
|           <el-col :span="1.5"> | ||||
|             <el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">展开/折叠</el-button> | ||||
|           </el-col> | ||||
|           <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> | ||||
|         </el-row> | ||||
|       </template> | ||||
|       <el-table | ||||
|         ref="categoryTableRef" | ||||
|         v-loading="loading" | ||||
|         :data="categoryList" | ||||
|         row-key="id" | ||||
|         :default-expand-all="isExpandAll" | ||||
|         :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" | ||||
|       > | ||||
|         <el-table-column label="分类名称" prop="categoryName" /> | ||||
|         <el-table-column label="分类编码" align="center" prop="categoryCode" /> | ||||
|         <el-table-column label="排序" align="center" prop="sortNum" /> | ||||
|         <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> | ||||
|           <template #default="scope"> | ||||
|             <el-tooltip content="修改" placement="top"> | ||||
|               <el-button v-hasPermi="['workflow:category:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)" /> | ||||
|             </el-tooltip> | ||||
|             <el-tooltip content="新增" placement="top"> | ||||
|               <el-button v-hasPermi="['workflow:category:add']" link type="primary" icon="Plus" @click="handleAdd(scope.row)" /> | ||||
|             </el-tooltip> | ||||
|             <el-tooltip content="删除" placement="top"> | ||||
|               <el-button v-hasPermi="['workflow:category:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)" /> | ||||
|             </el-tooltip> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|     </el-card> | ||||
|     <!-- 添加或修改流程分类对话框 --> | ||||
|     <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body> | ||||
|       <el-form ref="categoryFormRef" v-loading="loading" :model="form" :rules="rules" label-width="80px"> | ||||
|         <el-form-item label="父级分类" prop="parentId"> | ||||
|           <el-tree-select | ||||
|             v-model="form.parentId" | ||||
|             :data="categoryOptions" | ||||
|             :props="{ value: 'id', label: 'categoryName', children: 'children' }" | ||||
|             value-key="id" | ||||
|             placeholder="请选择父级id" | ||||
|             check-strictly | ||||
|           /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="分类名称" prop="categoryName"> | ||||
|           <el-input v-model="form.categoryName" placeholder="请输入分类名称" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="分类编码" prop="categoryCode"> | ||||
|           <el-input v-model="form.categoryCode" placeholder="请输入分类编码" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="排序" prop="sortNum"> | ||||
|           <el-input-number v-model="form.sortNum" placeholder="请输入排序" controls-position="right" :min="0" /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <div class="dialog-footer"> | ||||
|           <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button> | ||||
|           <el-button @click="cancel">取 消</el-button> | ||||
|         </div> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script setup name="Category" lang="ts"> | ||||
| import { listCategory, getCategory, delCategory, addCategory, updateCategory } from '@/api/workflow/category'; | ||||
| import { CategoryVO, CategoryQuery, CategoryForm } from '@/api/workflow/category/types'; | ||||
|  | ||||
| type CategoryOption = { | ||||
|   id: number; | ||||
|   categoryName: string; | ||||
|   children?: CategoryOption[]; | ||||
| }; | ||||
|  | ||||
| const { proxy } = getCurrentInstance() as ComponentInternalInstance; | ||||
|  | ||||
| const categoryList = ref<CategoryVO[]>([]); | ||||
| const categoryOptions = ref<CategoryOption[]>([]); | ||||
| const buttonLoading = ref(false); | ||||
| const showSearch = ref(true); | ||||
| const isExpandAll = ref(true); | ||||
| const loading = ref(false); | ||||
|  | ||||
| const queryFormRef = ref<ElFormInstance>(); | ||||
| const categoryFormRef = ref<ElFormInstance>(); | ||||
| const categoryTableRef = ref<ElTableInstance>(); | ||||
|  | ||||
| const dialog = reactive<DialogOption>({ | ||||
|   visible: false, | ||||
|   title: '' | ||||
| }); | ||||
|  | ||||
| const initFormData: CategoryForm = { | ||||
|   id: undefined, | ||||
|   categoryName: undefined, | ||||
|   categoryCode: undefined, | ||||
|   parentId: undefined, | ||||
|   sortNum: 0 | ||||
| }; | ||||
|  | ||||
| const data = reactive<PageData<CategoryForm, CategoryQuery>>({ | ||||
|   form: { ...initFormData }, | ||||
|   queryParams: { | ||||
|     pageNum: 1, | ||||
|     pageSize: 10, | ||||
|     categoryName: undefined, | ||||
|     categoryCode: undefined | ||||
|   }, | ||||
|   rules: { | ||||
|     id: [{ required: true, message: '主键不能为空', trigger: 'blur' }], | ||||
|     categoryName: [{ required: true, message: '分类名称不能为空', trigger: 'blur' }], | ||||
|     categoryCode: [{ required: true, message: '分类编码不能为空', trigger: 'blur' }], | ||||
|     parentId: [{ required: true, message: '父级id不能为空', trigger: 'blur' }] | ||||
|   } | ||||
| }); | ||||
|  | ||||
| const { queryParams, form, rules } = toRefs(data); | ||||
|  | ||||
| /** 查询流程分类列表 */ | ||||
| const getList = async () => { | ||||
|   loading.value = true; | ||||
|   const res = await listCategory(queryParams.value); | ||||
|   const data = proxy?.handleTree<CategoryVO>(res.data, 'id', 'parentId'); | ||||
|   if (data) { | ||||
|     categoryList.value = data; | ||||
|     loading.value = false; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| /** 查询流程分类下拉树结构 */ | ||||
| const getTreeselect = async () => { | ||||
|   const res = await listCategory(); | ||||
|   categoryOptions.value = []; | ||||
|   const data: CategoryOption = { id: 0, categoryName: '顶级节点', children: [] }; | ||||
|   data.children = proxy?.handleTree<CategoryOption>(res.data, 'id', 'parentId'); | ||||
|   categoryOptions.value.push(data); | ||||
| }; | ||||
|  | ||||
| // 取消按钮 | ||||
| const cancel = () => { | ||||
|   reset(); | ||||
|   dialog.visible = false; | ||||
| }; | ||||
|  | ||||
| // 表单重置 | ||||
| const reset = () => { | ||||
|   form.value = { ...initFormData }; | ||||
|   categoryFormRef.value?.resetFields(); | ||||
| }; | ||||
|  | ||||
| /** 搜索按钮操作 */ | ||||
| const handleQuery = () => { | ||||
|   getList(); | ||||
| }; | ||||
|  | ||||
| /** 重置按钮操作 */ | ||||
| const resetQuery = () => { | ||||
|   queryFormRef.value?.resetFields(); | ||||
|   handleQuery(); | ||||
| }; | ||||
|  | ||||
| /** 新增按钮操作 */ | ||||
| const handleAdd = (row?: CategoryVO) => { | ||||
|   dialog.visible = true; | ||||
|   dialog.title = '添加流程分类'; | ||||
|   nextTick(() => { | ||||
|     reset(); | ||||
|     getTreeselect(); | ||||
|     if (row != null && row.id) { | ||||
|       form.value.parentId = row.id; | ||||
|     } else { | ||||
|       form.value.parentId = 0; | ||||
|     } | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| /** 展开/折叠操作 */ | ||||
| const handleToggleExpandAll = () => { | ||||
|   isExpandAll.value = !isExpandAll.value; | ||||
|   toggleExpandAll(categoryList.value, isExpandAll.value); | ||||
| }; | ||||
|  | ||||
| /** 展开/折叠操作 */ | ||||
| const toggleExpandAll = (data: CategoryVO[], status: boolean) => { | ||||
|   data.forEach((item) => { | ||||
|     categoryTableRef.value?.toggleRowExpansion(item, status); | ||||
|     if (item.children && item.children.length > 0) toggleExpandAll(item.children, status); | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| /** 修改按钮操作 */ | ||||
| const handleUpdate = (row: CategoryVO) => { | ||||
|   loading.value = true; | ||||
|   dialog.visible = true; | ||||
|   dialog.title = '修改流程分类'; | ||||
|   nextTick(async () => { | ||||
|     reset(); | ||||
|     await getTreeselect(); | ||||
|     if (row != null) { | ||||
|       form.value.parentId = row.id; | ||||
|     } | ||||
|     const res = await getCategory(row.id); | ||||
|     loading.value = false; | ||||
|     Object.assign(form.value, res.data); | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| /** 提交按钮 */ | ||||
| const submitForm = () => { | ||||
|   categoryFormRef.value.validate(async (valid: boolean) => { | ||||
|     if (valid) { | ||||
|       buttonLoading.value = true; | ||||
|       if (form.value.id) { | ||||
|         await updateCategory(form.value).finally(() => (buttonLoading.value = false)); | ||||
|       } else { | ||||
|         await addCategory(form.value).finally(() => (buttonLoading.value = false)); | ||||
|       } | ||||
|       proxy?.$modal.msgSuccess('操作成功'); | ||||
|       dialog.visible = false; | ||||
|       await getList(); | ||||
|     } | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| /** 删除按钮操作 */ | ||||
| const handleDelete = async (row: CategoryVO) => { | ||||
|   await proxy?.$modal.confirm('是否确认删除流程分类编号为"' + row.id + '"的数据项?'); | ||||
|   loading.value = true; | ||||
|   await delCategory(row.id).finally(() => (loading.value = false)); | ||||
|   await getList(); | ||||
|   proxy?.$modal.msgSuccess('删除成功'); | ||||
| }; | ||||
|  | ||||
| onMounted(() => { | ||||
|   getList(); | ||||
| }); | ||||
| </script> | ||||
							
								
								
									
										381
									
								
								src/views/workflow/leave/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										381
									
								
								src/views/workflow/leave/index.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,381 @@ | ||||
| <template> | ||||
|   <div class="p-2"> | ||||
|     <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> | ||||
|       <div v-show="showSearch" class="search"> | ||||
|         <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> | ||||
|           <el-form-item label="请假天数" prop="startLeaveDays"> | ||||
|             <el-input v-model="queryParams.startLeaveDays" placeholder="请输入请假天数" clearable @keyup.enter="handleQuery" /> | ||||
|           </el-form-item> | ||||
|           <el-form-item prop="endLeaveDays"> 至 </el-form-item> | ||||
|           <el-form-item prop="endLeaveDays"> | ||||
|             <el-input v-model="queryParams.endLeaveDays" placeholder="请输入请假天数" clearable @keyup.enter="handleQuery" /> | ||||
|           </el-form-item> | ||||
|           <el-form-item> | ||||
|             <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> | ||||
|             <el-button icon="Refresh" @click="resetQuery">重置</el-button> | ||||
|           </el-form-item> | ||||
|         </el-form> | ||||
|       </div> | ||||
|     </transition> | ||||
|  | ||||
|     <el-card shadow="never"> | ||||
|       <template #header> | ||||
|         <el-row :gutter="10" class="mb8"> | ||||
|           <el-col :span="1.5"> | ||||
|             <el-button v-hasPermi="['demo:leave:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button> | ||||
|           </el-col> | ||||
|           <el-col :span="1.5"> | ||||
|             <el-button v-hasPermi="['demo:leave:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button> | ||||
|           </el-col> | ||||
|           <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> | ||||
|         </el-row> | ||||
|       </template> | ||||
|  | ||||
|       <el-table v-loading="loading" :data="leaveList" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column type="selection" width="55" align="center" /> | ||||
|         <el-table-column v-if="false" label="主键" align="center" prop="id" /> | ||||
|         <el-table-column label="请假类型" align="center"> | ||||
|           <template #default="scope"> | ||||
|             <el-tag>{{ options.find((e) => e.value === scope.row.leaveType)?.label }}</el-tag> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="开始时间" align="center" prop="startDate"> | ||||
|           <template #default="scope"> | ||||
|             <span>{{ parseTime(scope.row.startDate, '{y}-{m}-{d}') }}</span> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="结束时间" align="center" prop="endDate"> | ||||
|           <template #default="scope"> | ||||
|             <span>{{ parseTime(scope.row.endDate, '{y}-{m}-{d}') }}</span> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="请假天数" align="center" prop="leaveDays" /> | ||||
|         <el-table-column label="请假原因" align="center" prop="remark" /> | ||||
|         <el-table-column align="center" prop="businessStatusName" label="流程状态" min-width="70"> | ||||
|           <template #default="scope"> | ||||
|             <el-tag type="success">{{ scope.row.processInstanceVo.businessStatusName }}</el-tag> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> | ||||
|           <template #default="scope"> | ||||
|             <el-tooltip | ||||
|               v-if=" | ||||
|                 scope.row.processInstanceVo.businessStatus === 'draft' || | ||||
|                 scope.row.processInstanceVo.businessStatus === 'cancel' || | ||||
|                 scope.row.processInstanceVo.businessStatus === 'back' | ||||
|               " | ||||
|               content="修改" | ||||
|               placement="top" | ||||
|             > | ||||
|               <el-button v-hasPermi="['demo:leave:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button> | ||||
|             </el-tooltip> | ||||
|             <el-tooltip | ||||
|               v-if=" | ||||
|                 scope.row.processInstanceVo.businessStatus === 'draft' || | ||||
|                 scope.row.processInstanceVo.businessStatus === 'cancel' || | ||||
|                 scope.row.processInstanceVo.businessStatus === 'back' | ||||
|               " | ||||
|               content="删除" | ||||
|               placement="top" | ||||
|             > | ||||
|               <el-button v-hasPermi="['demo:leave:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button> | ||||
|             </el-tooltip> | ||||
|             <el-tooltip v-if="scope.row.processInstanceVo.businessStatus === 'waiting'" content="撤销" placement="top"> | ||||
|               <el-button link type="primary" icon="Notification" @click="handleCancelProcessApply(scope.row.processInstanceVo.id)"></el-button> | ||||
|             </el-tooltip> | ||||
|             <el-tooltip v-if="scope.row.processInstanceVo.businessStatus === 'waiting'" content="审批记录" placement="top"> | ||||
|               <el-button link type="primary" icon="Document" @click="handleApprovalRecord(scope.row.processInstanceVo.id)"></el-button> | ||||
|             </el-tooltip> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|  | ||||
|       <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> | ||||
|     </el-card> | ||||
|     <!-- 添加或修改请假对话框 --> | ||||
|     <el-dialog v-model="dialog.visible" :title="dialog.title" width="800px" append-to-body> | ||||
|       <el-form ref="leaveFormRef" v-loading="loading" :model="form" :rules="rules" label-width="80px"> | ||||
|         <el-form-item label="请假类型" prop="leaveType"> | ||||
|           <el-select v-model="form.leaveType" placeholder="请选择请假类型" style="width: 100%"> | ||||
|             <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="请假时间"> | ||||
|           <el-date-picker | ||||
|             v-model="leaveTime" | ||||
|             type="daterange" | ||||
|             range-separator="To" | ||||
|             start-placeholder="开始时间" | ||||
|             end-placeholder="结束时间" | ||||
|             @change="changeLeaveTime()" | ||||
|           /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="请假天数" prop="leaveDays"> | ||||
|           <el-input v-model="form.leaveDays" disabled type="number" placeholder="请输入请假天数" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="请假原因" prop="remark"> | ||||
|           <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请输入请假原因" /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <div class="dialog-footer"> | ||||
|           <el-button :loading="buttonLoading" type="info" @click="submitForm('draft')">暂 存</el-button> | ||||
|           <el-button :loading="buttonLoading" type="primary" @click="submitForm('submit')">提 交</el-button> | ||||
|           <el-button @click="cancel">取 消</el-button> | ||||
|         </div> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|     <!-- 提交组件 --> | ||||
|     <submitVerify ref="submitVerifyRef" :task-variables="taskVariables" @submit-callback="submitCallback" /> | ||||
|     <!-- 审批记录 --> | ||||
|     <approvalRecord ref="approvalRecordRef" /> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script setup name="Leave" lang="ts"> | ||||
| import { addLeave, delLeave, getLeave, listLeave, updateLeave } from '@/api/workflow/leave'; | ||||
| import { cancelProcessApply } from '@/api/workflow/processInstance'; | ||||
| import { LeaveForm, LeaveQuery, LeaveVO } from '@/api/workflow/leave/types'; | ||||
| import { startWorkFlow } from '@/api/workflow/task'; | ||||
| import SubmitVerify from '@/components/Process/submitVerify.vue'; | ||||
| import ApprovalRecord from '@/components/Process/approvalRecord.vue'; | ||||
| import { AxiosResponse } from 'axios'; | ||||
|  | ||||
| const { proxy } = getCurrentInstance() as ComponentInternalInstance; | ||||
|  | ||||
| const leaveList = ref<LeaveVO[]>([]); | ||||
| const buttonLoading = ref(false); | ||||
| const loading = ref(true); | ||||
| const showSearch = ref(true); | ||||
| const ids = ref<Array<string | number>>([]); | ||||
| const single = ref(true); | ||||
| const multiple = ref(true); | ||||
| const total = ref(0); | ||||
| const leaveTime = ref<Array<string>>([]); | ||||
| const options = [ | ||||
|   { | ||||
|     value: '1', | ||||
|     label: '事假' | ||||
|   }, | ||||
|   { | ||||
|     value: '2', | ||||
|     label: '调休' | ||||
|   }, | ||||
|   { | ||||
|     value: '3', | ||||
|     label: '病假' | ||||
|   }, | ||||
|   { | ||||
|     value: '4', | ||||
|     label: '婚假' | ||||
|   } | ||||
| ]; | ||||
| //提交组件 | ||||
| const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>(); | ||||
| //审批记录组件 | ||||
| const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>(); | ||||
|  | ||||
| const queryFormRef = ref<ElFormInstance>(); | ||||
| const leaveFormRef = ref<ElFormInstance>(); | ||||
|  | ||||
| const submitFormData = ref<Record<string, any>>({ | ||||
|   businessKey: '', | ||||
|   processKey: '', | ||||
|   variables: {} | ||||
| }); | ||||
| const taskVariables = ref<Record<string, any>>({}); | ||||
|  | ||||
| const dialog = reactive<DialogOption>({ | ||||
|   visible: false, | ||||
|   title: '' | ||||
| }); | ||||
|  | ||||
| const initFormData: LeaveForm = { | ||||
|   id: undefined, | ||||
|   leaveType: undefined, | ||||
|   startDate: undefined, | ||||
|   endDate: undefined, | ||||
|   leaveDays: undefined, | ||||
|   remark: undefined | ||||
| }; | ||||
| const data = reactive<PageData<LeaveForm, LeaveQuery>>({ | ||||
|   form: { ...initFormData }, | ||||
|   queryParams: { | ||||
|     pageNum: 1, | ||||
|     pageSize: 10, | ||||
|     startLeaveDays: undefined, | ||||
|     endLeaveDays: undefined | ||||
|   }, | ||||
|   rules: { | ||||
|     id: [{ required: true, message: '主键不能为空', trigger: 'blur' }], | ||||
|     leaveType: [{ required: true, message: '请假类型不能为空', trigger: 'blur' }], | ||||
|     leaveTime: [{ required: true, message: '请假时间不能为空', trigger: 'blur' }], | ||||
|     leaveDays: [{ required: true, message: '请假天数不能为空', trigger: 'blur' }] | ||||
|   } | ||||
| }); | ||||
|  | ||||
| const { queryParams, form, rules } = toRefs(data); | ||||
|  | ||||
| /** 查询请假列表 */ | ||||
| const getList = async () => { | ||||
|   loading.value = true; | ||||
|   const res = await listLeave(queryParams.value); | ||||
|   leaveList.value = res.rows; | ||||
|   total.value = res.total; | ||||
|   loading.value = false; | ||||
| }; | ||||
|  | ||||
| /** 取消按钮 */ | ||||
| const cancel = () => { | ||||
|   reset(); | ||||
|   dialog.visible = false; | ||||
| }; | ||||
|  | ||||
| /** 表单重置 */ | ||||
| const reset = () => { | ||||
|   form.value = { ...initFormData }; | ||||
|   leaveTime.value = []; | ||||
|   leaveFormRef.value?.resetFields(); | ||||
| }; | ||||
|  | ||||
| /** 搜索按钮操作 */ | ||||
| const handleQuery = () => { | ||||
|   queryParams.value.pageNum = 1; | ||||
|   getList(); | ||||
| }; | ||||
|  | ||||
| /** 重置按钮操作 */ | ||||
| const resetQuery = () => { | ||||
|   queryFormRef.value?.resetFields(); | ||||
|   handleQuery(); | ||||
| }; | ||||
|  | ||||
| /** 多选框选中数据 */ | ||||
| const handleSelectionChange = (selection: LeaveVO[]) => { | ||||
|   ids.value = selection.map((item) => item.id); | ||||
|   single.value = selection.length != 1; | ||||
|   multiple.value = !selection.length; | ||||
| }; | ||||
|  | ||||
| /** 新增按钮操作 */ | ||||
| const handleAdd = () => { | ||||
|   dialog.visible = true; | ||||
|   dialog.title = '添加请假申请'; | ||||
|   nextTick(() => { | ||||
|     reset(); | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| const changeLeaveTime = () => { | ||||
|   const startDate = new Date(leaveTime.value[0]).getTime(); | ||||
|   const endDate = new Date(leaveTime.value[1]).getTime(); | ||||
|   const diffInMilliseconds = endDate - startDate; | ||||
|   form.value.leaveDays = Math.floor(diffInMilliseconds / (1000 * 60 * 60 * 24)); | ||||
| }; | ||||
| /** 修改按钮操作 */ | ||||
| const handleUpdate = (row?: LeaveVO) => { | ||||
|   buttonLoading.value = false; | ||||
|   dialog.visible = true; | ||||
|   dialog.title = '修改请假申请'; | ||||
|   nextTick(async () => { | ||||
|     reset(); | ||||
|     const _id = row?.id || ids.value[0]; | ||||
|     const res = await getLeave(_id); | ||||
|     Object.assign(form.value, res.data); | ||||
|     leaveTime.value = []; | ||||
|     leaveTime.value.push(form.value.startDate); | ||||
|     leaveTime.value.push(form.value.endDate); | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| /** 提交按钮 */ | ||||
| const submitForm = (status: string) => { | ||||
|   if (leaveTime.value.length === 0) { | ||||
|     proxy?.$modal.msgError('请假时间不能为空'); | ||||
|     return; | ||||
|   } | ||||
|   leaveFormRef.value?.validate(async (valid: boolean) => { | ||||
|     form.value.startDate = leaveTime.value[0]; | ||||
|     form.value.endDate = leaveTime.value[1]; | ||||
|     if (valid) { | ||||
|       buttonLoading.value = true; | ||||
|       let res: AxiosResponse<LeaveVO>; | ||||
|       if (form.value.id) { | ||||
|         res = await updateLeave(form.value); | ||||
|       } else { | ||||
|         res = await addLeave(form.value); | ||||
|       } | ||||
|       form.value = res.data; | ||||
|       if (status === 'draft') { | ||||
|         buttonLoading.value = false; | ||||
|         proxy?.$modal.msgSuccess('暂存成功'); | ||||
|         dialog.visible = false; | ||||
|         await getList(); | ||||
|       } else { | ||||
|         await handleStartWorkFlow(res.data); | ||||
|       } | ||||
|     } | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| /** 删除按钮操作 */ | ||||
| const handleDelete = async (row?: LeaveVO) => { | ||||
|   const _ids = row?.id || ids.value; | ||||
|   await proxy?.$modal.confirm('是否确认删除请假编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false)); | ||||
|   await delLeave(_ids); | ||||
|   proxy?.$modal.msgSuccess('删除成功'); | ||||
|   await getList(); | ||||
| }; | ||||
|  | ||||
| /** 导出按钮操作 */ | ||||
| const handleExport = () => { | ||||
|   proxy?.download( | ||||
|     'demo/leave/export', | ||||
|     { | ||||
|       ...queryParams.value | ||||
|     }, | ||||
|     `leave_${new Date().getTime()}.xlsx` | ||||
|   ); | ||||
| }; | ||||
|  | ||||
| //提交申请 | ||||
| const handleStartWorkFlow = async (data: LeaveVO) => { | ||||
|   submitFormData.value.processKey = 'leave7'; | ||||
|   submitFormData.value.businessKey = data.id; | ||||
|   //流程变量 | ||||
|   taskVariables.value = { | ||||
|     entity: data, | ||||
|     leaveDays: data.leaveDays, | ||||
|     userList: [1, 2], | ||||
|     userList2: [1, 2] | ||||
|   }; | ||||
|   submitFormData.value.variables = taskVariables.value; | ||||
|   const resp = await startWorkFlow(submitFormData.value); | ||||
|   if (submitVerifyRef.value) { | ||||
|     buttonLoading.value = false; | ||||
|     submitVerifyRef.value.openDialog(resp.data.taskId); | ||||
|   } | ||||
| }; | ||||
| //审批记录 | ||||
| const handleApprovalRecord = (id: string) => { | ||||
|   if (approvalRecordRef.value) { | ||||
|     approvalRecordRef.value.init(id); | ||||
|   } | ||||
| }; | ||||
| //提交回调 | ||||
| const submitCallback = async () => { | ||||
|   dialog.visible = false; | ||||
|   handleQuery(); | ||||
| }; | ||||
| /** 撤销按钮操作 */ | ||||
| const handleCancelProcessApply = async (id: string) => { | ||||
|   await proxy?.$modal.confirm('是否确认撤销当前单据?'); | ||||
|   loading.value = true; | ||||
|   await cancelProcessApply(id).finally(() => (loading.value = false)); | ||||
|   await getList(); | ||||
|   proxy?.$modal.msgSuccess('撤销成功'); | ||||
| }; | ||||
| onMounted(() => { | ||||
|   getList(); | ||||
| }); | ||||
| </script> | ||||
							
								
								
									
										65
									
								
								src/views/workflow/model/design.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/views/workflow/model/design.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,65 @@ | ||||
| <template> | ||||
|   <div class="design"> | ||||
|     <el-dialog v-model="visible" width="100%" fullscreen :title="title"> | ||||
|       <div class="modeler"> | ||||
|         <bpmn-design ref="bpmnDesignRef" @save-call-back="saveCallBack"></bpmn-design> | ||||
|       </div> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup name="Design"> | ||||
| import { getInfo, editModelXml } from '@/api/workflow/model'; | ||||
|  | ||||
| const { proxy } = getCurrentInstance() as ComponentInternalInstance; | ||||
|  | ||||
| import { ModelForm } from '@/api/workflow/model/types'; | ||||
| import BpmnDesign from '@/components/BpmnDesign'; | ||||
| import useDialog from '@/hooks/useDialog'; | ||||
| const bpmnDesignRef = ref<InstanceType<typeof BpmnDesign>>(); | ||||
| const modelForm = ref<ModelForm>(); | ||||
| const emit = defineEmits(['closeCallBack']); | ||||
| const { visible, title } = useDialog({ | ||||
|   title: '编辑流程' | ||||
| }); | ||||
| const modelId = ref(''); | ||||
| const open = async (id) => { | ||||
|   visible.value = true; | ||||
|   modelId.value = id; | ||||
|   const { data } = await getInfo(id); | ||||
|   modelForm.value = data; | ||||
|   bpmnDesignRef.value.initDiagram(modelForm.value.xml); | ||||
| }; | ||||
| //保存模型 | ||||
| const saveCallBack = async (data) => { | ||||
|   await proxy?.$modal.confirm('是否确认保存?'); | ||||
|   modelForm.value.id = modelId.value; | ||||
|   modelForm.value.xml = data.xml; | ||||
|   modelForm.value.svg = data.svg; | ||||
|   modelForm.value.key = data.key; | ||||
|   modelForm.value.name = data.name; | ||||
|   editModelXml(modelForm.value).then((res) => { | ||||
|     if (res.code === 200) { | ||||
|       visible.value = false; | ||||
|       proxy?.$modal.msgSuccess('保存成功'); | ||||
|       emit('closeCallBack', data); | ||||
|     } | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * 对外暴露子组件方法 | ||||
|  */ | ||||
| defineExpose({ | ||||
|   open | ||||
| }); | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .design { | ||||
|   :deep(.el-dialog .el-dialog__body) { | ||||
|     max-height: 100% !important; | ||||
|     min-height: calc(100vh - 50px); | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										360
									
								
								src/views/workflow/model/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										360
									
								
								src/views/workflow/model/index.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,360 @@ | ||||
| <template> | ||||
|   <div class="p-2"> | ||||
|     <el-row :gutter="20"> | ||||
|       <!-- 流程分类树 --> | ||||
|       <el-col :lg="4" :xs="24" style=""> | ||||
|         <el-card shadow="hover"> | ||||
|           <el-input v-model="categoryName" placeholder="请输入流程分类名" prefix-icon="Search" clearable /> | ||||
|           <el-tree | ||||
|             ref="categoryTreeRef" | ||||
|             class="mt-2" | ||||
|             node-key="id" | ||||
|             :data="categoryOptions" | ||||
|             :props="{ label: 'categoryName', children: 'children' }" | ||||
|             :expand-on-click-node="false" | ||||
|             :filter-node-method="filterNode" | ||||
|             highlight-current | ||||
|             default-expand-all | ||||
|             @node-click="handleNodeClick" | ||||
|           ></el-tree> | ||||
|         </el-card> | ||||
|       </el-col> | ||||
|       <el-col :lg="20" :xs="24"> | ||||
|         <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> | ||||
|           <div v-show="showSearch" class="mb-[10px]"> | ||||
|             <el-card shadow="hover"> | ||||
|               <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true" label-width="80px"> | ||||
|                 <el-form-item label="模型名称" prop="name"> | ||||
|                   <el-input v-model="queryParams.name" placeholder="请输入模型名称" clearable @keyup.enter="handleQuery" /> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="模型KEY" prop="key"> | ||||
|                   <el-input v-model="queryParams.key" placeholder="请输入模型KEY" clearable @keyup.enter="handleQuery" /> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item> | ||||
|                   <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> | ||||
|                   <el-button icon="Refresh" @click="resetQuery">重置</el-button> | ||||
|                 </el-form-item> | ||||
|               </el-form> | ||||
|             </el-card> | ||||
|           </div> | ||||
|         </transition> | ||||
|         <el-card shadow="hover"> | ||||
|           <template #header> | ||||
|             <el-row :gutter="10" class="mb8"> | ||||
|               <el-col :span="1.5"> | ||||
|                 <el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button> | ||||
|               </el-col> | ||||
|               <el-col :span="1.5"> | ||||
|                 <el-button type="success" plain icon="Edit" :disabled="multiple" @click="handleUpdate()">修改</el-button> | ||||
|               </el-col> | ||||
|               <el-col :span="1.5"> | ||||
|                 <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">删除</el-button> | ||||
|               </el-col> | ||||
|               <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> | ||||
|             </el-row> | ||||
|           </template> | ||||
|  | ||||
|           <el-table v-loading="loading" :data="modelList" @selection-change="handleSelectionChange"> | ||||
|             <el-table-column type="selection" width="55" align="center" /> | ||||
|             <el-table-column fixed align="center" type="index" label="序号" width="50"></el-table-column> | ||||
|             <el-table-column fixed align="center" prop="name" label="模型名称"></el-table-column> | ||||
|             <el-table-column align="center" prop="key" label="模型KEY"></el-table-column> | ||||
|             <el-table-column align="center" prop="version" label="版本号" width="90"> | ||||
|               <template #default="scope"> v{{ scope.row.version }}.0</template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="center" prop="metaInfo" label="备注说明" min-width="130"></el-table-column> | ||||
|             <el-table-column align="center" prop="createTime" label="创建时间" width="160"></el-table-column> | ||||
|             <el-table-column align="center" prop="lastUpdateTime" label="更新时间" width="160"></el-table-column> | ||||
|             <el-table-column fixed="right" label="操作" align="center" width="180" class-name="small-padding fixed-width"> | ||||
|               <template #default="scope"> | ||||
|                 <el-row :gutter="10" class="mb8"> | ||||
|                   <el-col :span="1.5"> | ||||
|                     <el-button link type="primary" size="small" icon="Pointer" @click="clickDesign(scope.row.id)">设计流程</el-button> | ||||
|                   </el-col> | ||||
|                   <el-col :span="1.5"> | ||||
|                     <el-button link type="primary" size="small" icon="Download" @click="clickExportZip(scope.row)">导出</el-button> | ||||
|                   </el-col> | ||||
|                 </el-row> | ||||
|                 <el-row :gutter="10" class="mb8"> | ||||
|                   <el-col :span="1.5"> | ||||
|                     <el-button link type="primary" size="small" icon="ScaleToOriginal" @click="clickDeploy(scope.row.id, scope.row.key)"> | ||||
|                       流程部署 | ||||
|                     </el-button> | ||||
|                   </el-col> | ||||
|                   <el-col :span="1.5"> | ||||
|                     <el-button link type="primary" size="small" icon="Delete" @click="handleDelete(scope.row)">删除</el-button> | ||||
|                   </el-col> | ||||
|                 </el-row> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|           </el-table> | ||||
|           <pagination | ||||
|             v-show="total > 0" | ||||
|             v-model:page="queryParams.pageNum" | ||||
|             v-model:limit="queryParams.pageSize" | ||||
|             :total="total" | ||||
|             @pagination="getList" | ||||
|           /> | ||||
|         </el-card> | ||||
|       </el-col> | ||||
|     </el-row> | ||||
|     <!-- 设计流程开始 --> | ||||
|     <Design ref="designRef" @close-call-back="handleQuery"></Design> | ||||
|     <!-- 设计流程结束 --> | ||||
|     <!-- 添加模型对话框 --> | ||||
|     <el-dialog v-model="dialog.visible" :title="dialog.title" width="650px" append-to-body :close-on-click-modal="false"> | ||||
|       <el-form ref="formRef" :model="form" :rules="rules" label-width="100px"> | ||||
|         <el-form-item label="模型名称:" prop="name"> | ||||
|           <el-input v-model="form.name" :disabled="ids && ids.length > 0" maxlength="20" show-word-limit /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="模型KEY:" prop="key"> | ||||
|           <el-input v-model="form.key" :disabled="ids && ids.length > 0" maxlength="20" show-word-limit /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="流程分类" prop="categoryCode"> | ||||
|           <el-tree-select | ||||
|             v-model="form.categoryCode" | ||||
|             :data="categoryOptions" | ||||
|             :props="{ value: 'categoryCode', label: 'categoryName', children: 'children' }" | ||||
|             value-key="categoryCode" | ||||
|             placeholder="请选择流程分类" | ||||
|             check-strictly | ||||
|           /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="备注:" prop="description"> | ||||
|           <el-input v-model="form.description" type="textarea" maxlength="200" show-word-limit></el-input> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <span class="dialog-footer"> | ||||
|           <el-button type="primary" @click="submitForm">确 定</el-button> | ||||
|           <el-button @click="cancel">取 消</el-button> | ||||
|         </span> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup name="Model"> | ||||
| import Design from './design.vue'; | ||||
| import { listModel, addModel, delModel, modelDeploy, getInfo, update } from '@/api/workflow/model'; | ||||
| import { ModelQuery, ModelForm, ModelVO } from '@/api/workflow/model/types'; | ||||
| import { listCategory } from '@/api/workflow/category'; | ||||
|  | ||||
| const { proxy } = getCurrentInstance() as ComponentInternalInstance; | ||||
|  | ||||
| const formRef = ref<ElFormInstance>(); | ||||
| const queryFormRef = ref<ElFormInstance>(); | ||||
| const categoryTreeRef = ref<ElTreeInstance>(); | ||||
| const designRef = ref<InstanceType<typeof Design>>(); | ||||
|  | ||||
| type CategoryOption = { | ||||
|   categoryCode: string; | ||||
|   categoryName: string; | ||||
|   children?: CategoryOption[]; | ||||
| }; | ||||
|  | ||||
| const buttonLoading = ref(false); | ||||
| const loading = ref(true); | ||||
| const ids = ref<string[]>([]); | ||||
| const single = ref(true); | ||||
| const multiple = ref(true); | ||||
| const showSearch = ref(true); | ||||
| const total = ref(0); | ||||
| const modelList = ref<ModelVO[]>([]); | ||||
| const categoryOptions = ref<CategoryOption[]>([]); | ||||
| const categoryName = ref(''); | ||||
| const modelId = ref<string>(''); | ||||
|  | ||||
| const dialog = reactive<DialogOption>({ | ||||
|   visible: false, | ||||
|   title: '' | ||||
| }); | ||||
|  | ||||
| const initFormData: ModelForm = { | ||||
|   id: '', | ||||
|   name: '', | ||||
|   key: '', | ||||
|   categoryCode: '', | ||||
|   xml: '', | ||||
|   svg: '', | ||||
|   description: '' | ||||
| }; | ||||
| const data = reactive<PageData<ModelForm, ModelQuery>>({ | ||||
|   form: { ...initFormData }, | ||||
|   queryParams: { | ||||
|     pageNum: 1, | ||||
|     pageSize: 10, | ||||
|     name: '', | ||||
|     key: '', | ||||
|     categoryCode: '' | ||||
|   }, | ||||
|   rules: { | ||||
|     name: [{ required: true, message: '模型不能为空', trigger: 'blur' }], | ||||
|     key: [{ required: true, message: '模型KEY不能为空', trigger: 'blur' }], | ||||
|     categoryCode: [{ required: true, message: '流程分类不能为空', trigger: 'blur' }] | ||||
|   } | ||||
| }); | ||||
| const { queryParams, form, rules } = toRefs(data); | ||||
|  | ||||
| onMounted(() => { | ||||
|   getList(); | ||||
|   getTreeselect(); | ||||
| }); | ||||
|  | ||||
| /** 节点单击事件 */ | ||||
| const handleNodeClick = (data: ModelForm) => { | ||||
|   queryParams.value.categoryCode = data.categoryCode; | ||||
|   if (data.categoryCode === 'ALL') { | ||||
|     queryParams.value.categoryCode = ''; | ||||
|   } | ||||
|   handleQuery(); | ||||
| }; | ||||
| /** 通过条件过滤节点  */ | ||||
| const filterNode = (value: string, data: any) => { | ||||
|   if (!value) return true; | ||||
|   return data.categoryName.indexOf(value) !== -1; | ||||
| }; | ||||
| /** 根据名称筛选部门树 */ | ||||
| watchEffect( | ||||
|   () => { | ||||
|     categoryTreeRef.value?.filter(categoryName.value); | ||||
|   }, | ||||
|   { | ||||
|     flush: 'post' // watchEffect会在DOM挂载或者更新之前就会触发,此属性控制在DOM元素更新后运行 | ||||
|   } | ||||
| ); | ||||
|  | ||||
| /** 搜索按钮操作 */ | ||||
| const handleQuery = () => { | ||||
|   queryParams.value.pageNum = 1; | ||||
|   getList(); | ||||
| }; | ||||
| /** 重置按钮操作 */ | ||||
| const resetQuery = () => { | ||||
|   queryFormRef.value?.resetFields(); | ||||
|   queryParams.value.categoryCode = ''; | ||||
|   queryParams.value.pageNum = 1; | ||||
|   queryParams.value.pageSize = 10; | ||||
|   handleQuery(); | ||||
| }; | ||||
| // 多选框选中数据 | ||||
| const handleSelectionChange = (selection: ModelVO[]) => { | ||||
|   ids.value = selection.map((item: ModelVO) => item.id); | ||||
|   single.value = selection.length !== 1; | ||||
|   multiple.value = !selection.length; | ||||
| }; | ||||
| //分页 | ||||
| const getList = async () => { | ||||
|   loading.value = true; | ||||
|   const resp = await listModel(queryParams.value); | ||||
|   modelList.value = resp.rows; | ||||
|   total.value = resp.total; | ||||
|   loading.value = false; | ||||
| }; | ||||
| /** 删除按钮操作 */ | ||||
| const handleDelete = async (row?: ModelVO) => { | ||||
|   const id = row?.id || ids.value; | ||||
|   await proxy?.$modal.confirm('是否确认删除模型id为【' + id + '】的数据项?'); | ||||
|   loading.value = true; | ||||
|   await delModel(id).finally(() => (loading.value = false)); | ||||
|   await getList(); | ||||
|   proxy?.$modal.msgSuccess('删除成功'); | ||||
| }; | ||||
| // 流程部署 | ||||
| const clickDeploy = async (id: string, key: string) => { | ||||
|   await proxy?.$modal.confirm('是否部署模型key为【' + key + '】流程?'); | ||||
|   loading.value = true; | ||||
|   await modelDeploy(id).finally(() => (loading.value = false)); | ||||
|   await getList(); | ||||
|   proxy?.$modal.msgSuccess('部署成功'); | ||||
| }; | ||||
| const handleAdd = () => { | ||||
|   ids.value = []; | ||||
|   getTreeselect(); | ||||
|   form.value = { ...initFormData }; | ||||
|   dialog.visible = true; | ||||
|   dialog.title = '新增模型'; | ||||
| }; | ||||
| const handleUpdate = () => { | ||||
|   dialog.title = '修改模型'; | ||||
|   nextTick(async () => { | ||||
|     await getTreeselect(); | ||||
|     const _id = ids.value[0]; | ||||
|     const res = await getInfo(_id); | ||||
|     Object.assign(form.value, res.data); | ||||
|     dialog.visible = true; | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| /** 提交按钮 */ | ||||
| const submitForm = () => { | ||||
|   formRef.value.validate(async (valid: boolean) => { | ||||
|     if (valid) { | ||||
|       buttonLoading.value = true; | ||||
|       if (ids.value && ids.value.length > 0) { | ||||
|         form.value.id = ids.value[0]; | ||||
|         await update(form.value); | ||||
|         proxy?.$modal.msgSuccess('新增成功'); | ||||
|       } else { | ||||
|         initXml(form.value.key, form.value.name); | ||||
|         form.value.xml = xml.value; | ||||
|         await addModel(form.value); | ||||
|         proxy?.$modal.msgSuccess('新增成功'); | ||||
|       } | ||||
|       dialog.visible = false; | ||||
|       await getList(); | ||||
|     } | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| /** 取消按钮 */ | ||||
| const cancel = () => { | ||||
|   reset(); | ||||
|   dialog.visible = false; | ||||
| }; | ||||
|  | ||||
| /** 表单重置 */ | ||||
| const reset = () => { | ||||
|   form.value = { ...initFormData }; | ||||
|   formRef.value.resetFields(); | ||||
| }; | ||||
|  | ||||
| // 打开设计流程 | ||||
| const clickDesign = async (id: string) => { | ||||
|   await designRef.value.open(id); | ||||
| }; | ||||
| // 导出流程模型 | ||||
| const clickExportZip = (data: any) => { | ||||
|   proxy?.$download.zip('/workflow/model/export/zip/' + data.id, data.name + '-' + data.key); | ||||
| }; | ||||
| /** 查询流程分类下拉树结构 */ | ||||
| const getTreeselect = async () => { | ||||
|   const res = await listCategory(); | ||||
|   categoryOptions.value = []; | ||||
|   const data: CategoryOption = { categoryCode: 'ALL', categoryName: '顶级节点', children: [] }; | ||||
|   data.children = proxy?.handleTree<CategoryOption>(res.data, 'id', 'parentId'); | ||||
|   categoryOptions.value.push(data); | ||||
| }; | ||||
|  | ||||
| const xml = ref<string>(''); | ||||
|  | ||||
| const initXml = async (key: string, name: string) => { | ||||
|   xml.value = `<?xml version="1.0" encoding="UTF-8"?> | ||||
| <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:bioc="http://bpmn.io/schema/bpmn/biocolor/1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" targetNamespace="http://www.flowable.org/processdef"> | ||||
|   <process id="${key}" name="${name}"> | ||||
|     <startEvent id="startNode1" name="开始" /> | ||||
|   </process> | ||||
|   <bpmndi:BPMNDiagram id="BPMNDiagram_flow"> | ||||
|     <bpmndi:BPMNPlane id="BPMNPlane_flow" bpmnElement="T-2d89e7a3-ba79-4abd-9f64-ea59621c258c"> | ||||
|       <bpmndi:BPMNShape id="BPMNShape_startNode1" bpmnElement="startNode1" bioc:stroke=""> | ||||
|         <omgdc:Bounds x="240" y="200" width="30" height="30" /> | ||||
|         <bpmndi:BPMNLabel> | ||||
|           <omgdc:Bounds x="242" y="237" width="23" height="14" /> | ||||
|         </bpmndi:BPMNLabel> | ||||
|       </bpmndi:BPMNShape> | ||||
|     </bpmndi:BPMNPlane> | ||||
|   </bpmndi:BPMNDiagram> | ||||
| </definitions>`; | ||||
|   return xml; | ||||
| }; | ||||
| </script> | ||||
| @ -0,0 +1,57 @@ | ||||
| <template> | ||||
|   <el-dialog v-model="data.visible" title="预览" width="70%" append-to-body> | ||||
|     <div v-if="data.type === 'png'" style="align: center"> | ||||
|       <el-image v-if="data.type === 'png'" :src="data.url[0]"> | ||||
|         <div>流程图加载中 <i class="el-icon-loading"></i></div> | ||||
|       </el-image> | ||||
|     </div> | ||||
|     <div v-if="data.type === 'xml'" class="xml-data"> | ||||
|       <div v-for="(xml, index) in data.url" :key="index"> | ||||
|         <pre class="font">{{ xml }}</pre> | ||||
|       </div> | ||||
|     </div> | ||||
|     <template #footer> | ||||
|       <span v-if="data.type === 'xml'" class="dialog-footer"> </span> | ||||
|     </template> | ||||
|   </el-dialog> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| const data = reactive({ | ||||
|   visible: false, | ||||
|   url: new Array<string>(), | ||||
|   type: '' | ||||
| }); | ||||
| //打开 | ||||
| const openDialog = (url: string[], type: string) => { | ||||
|   data.visible = true; | ||||
|   data.url = url; | ||||
|   data.type = type; | ||||
| }; | ||||
| /** | ||||
|  * 对外暴露子组件方法 | ||||
|  */ | ||||
| defineExpose({ | ||||
|   openDialog | ||||
| }); | ||||
| </script> | ||||
| <style> | ||||
| .xml-data { | ||||
|   background-color: #2b2b2b; | ||||
|   border-radius: 5px; | ||||
|   color: #c6c6c6; | ||||
|   word-break: break-all; | ||||
|   overflow-y: scroll; | ||||
|   overflow-x: hidden; | ||||
|   box-sizing: border-box; | ||||
|   padding: 8px 0px; | ||||
|   height: 500px; | ||||
|   width: inherit; | ||||
|   line-height: 1px; | ||||
|   overflow: auto; | ||||
| } | ||||
| .font { | ||||
|   font-family: '幼圆'; | ||||
|   font-weight: 500; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										403
									
								
								src/views/workflow/processDefinition/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										403
									
								
								src/views/workflow/processDefinition/index.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,403 @@ | ||||
| <template> | ||||
|   <div class="p-2"> | ||||
|     <el-row :gutter="20"> | ||||
|       <!-- 流程分类树 --> | ||||
|       <el-col :lg="4" :xs="24" style=""> | ||||
|         <el-card shadow="hover"> | ||||
|           <el-input v-model="categoryName" placeholder="请输入流程分类名" prefix-icon="Search" clearable /> | ||||
|           <el-tree | ||||
|             ref="categoryTreeRef" | ||||
|             class="mt-2" | ||||
|             node-key="id" | ||||
|             :data="categoryOptions" | ||||
|             :props="{ label: 'categoryName', children: 'children' }" | ||||
|             :expand-on-click-node="false" | ||||
|             :filter-node-method="filterNode" | ||||
|             highlight-current | ||||
|             default-expand-all | ||||
|             @node-click="handleNodeClick" | ||||
|           ></el-tree> | ||||
|         </el-card> | ||||
|       </el-col> | ||||
|       <el-col :lg="20" :xs="24"> | ||||
|         <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> | ||||
|           <div v-show="showSearch" class="mb-[10px]"> | ||||
|             <el-card shadow="hover"> | ||||
|               <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true" label-width="120px"> | ||||
|                 <el-form-item label="流程定义名称" prop="name"> | ||||
|                   <el-input v-model="queryParams.name" placeholder="请输入流程定义名称" clearable @keyup.enter="handleQuery" /> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="流程定义KEY" prop="key"> | ||||
|                   <el-input v-model="queryParams.key" placeholder="请输入流程定义KEY" clearable @keyup.enter="handleQuery" /> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item> | ||||
|                   <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> | ||||
|                   <el-button icon="Refresh" @click="resetQuery">重置</el-button> | ||||
|                 </el-form-item> | ||||
|               </el-form> | ||||
|             </el-card> | ||||
|           </div> | ||||
|         </transition> | ||||
|         <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> | ||||
|           <div v-show="showSearch" class="mb-[10px]"> | ||||
|             <el-card shadow="hover"> | ||||
|               <el-button type="primary" icon="UploadFilled" @click="uploadDialog.visible = true">部署流程文件</el-button> | ||||
|             </el-card> | ||||
|           </div> | ||||
|         </transition> | ||||
|         <el-card shadow="hover"> | ||||
|           <template #header> | ||||
|             <el-row :gutter="10" class="mb8"> | ||||
|               <el-col :span="1.5"> </el-col> | ||||
|               <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> | ||||
|             </el-row> | ||||
|           </template> | ||||
|  | ||||
|           <el-table v-loading="loading" :data="processDefinitionList" @selection-change="handleSelectionChange"> | ||||
|             <el-table-column type="selection" width="55" align="center" /> | ||||
|             <el-table-column fixed align="center" type="index" label="序号" width="50"></el-table-column> | ||||
|             <el-table-column fixed align="center" prop="name" label="流程定义名称"></el-table-column> | ||||
|             <el-table-column align="center" prop="key" label="标识Key"></el-table-column> | ||||
|             <el-table-column align="center" prop="version" label="版本号" width="90"> | ||||
|               <template #default="scope"> v{{ scope.row.version }}.0</template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="center" prop="resourceName" label="流程XML" min-width="80" :show-overflow-tooltip="true"> | ||||
|               <template #default="scope"> | ||||
|                 <el-link type="primary" @click="clickPreviewXML(scope.row.id)">{{ scope.row.resourceName }}</el-link> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="center" prop="diagramResourceName" label="流程图片" min-width="80" :show-overflow-tooltip="true"> | ||||
|               <template #default="scope"> | ||||
|                 <el-link type="primary" @click="clickPreviewImg(scope.row.id)">{{ scope.row.diagramResourceName }}</el-link> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="center" prop="suspensionState" label="状态" min-width="70"> | ||||
|               <template #default="scope"> | ||||
|                 <el-tag v-if="scope.row.suspensionState == 1" type="success">激活</el-tag> | ||||
|                 <el-tag v-else type="danger">挂起</el-tag> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="center" prop="deploymentTime" label="部署时间" :show-overflow-tooltip="true"></el-table-column> | ||||
|             <el-table-column fixed="right" label="操作" align="center" width="200" class-name="small-padding fixed-width"> | ||||
|               <template #default="scope"> | ||||
|                 <el-row :gutter="10" class="mb8"> | ||||
|                   <el-col :span="1.5"> | ||||
|                     <el-button | ||||
|                       link | ||||
|                       type="primary" | ||||
|                       size="small" | ||||
|                       :icon="scope.row.suspensionState === 1 ? 'Lock' : 'Unlock'" | ||||
|                       @click="handleProcessDefState(scope.row)" | ||||
|                     > | ||||
|                       {{ scope.row.suspensionState === 1 ? '挂起流程' : '激活流程' }} | ||||
|                     </el-button> | ||||
|                   </el-col> | ||||
|                   <el-col :span="1.5"> | ||||
|                     <el-button link type="primary" size="small" icon="Delete" @click="handleDelete(scope.row)">删除</el-button> | ||||
|                   </el-col> | ||||
|                 </el-row> | ||||
|                 <el-row :gutter="10" class="mb8"> | ||||
|                   <el-col :span="1.5"> | ||||
|                     <el-button link type="primary" size="small" icon="Sort" @click="handleConvertToModel(scope.row)"> 转换模型 </el-button> | ||||
|                   </el-col> | ||||
|                   <el-col :span="1.5"> | ||||
|                     <el-button link type="primary" size="small" icon="Document" @click="getProcessDefinitionHitoryList(scope.row.id, scope.row.key)"> | ||||
|                       历史版本 | ||||
|                     </el-button> | ||||
|                   </el-col> | ||||
|                 </el-row> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|           </el-table> | ||||
|           <pagination | ||||
|             v-show="total > 0" | ||||
|             v-model:page="queryParams.pageNum" | ||||
|             v-model:limit="queryParams.pageSize" | ||||
|             :total="total" | ||||
|             @pagination="getList" | ||||
|           /> | ||||
|         </el-card> | ||||
|       </el-col> | ||||
|     </el-row> | ||||
|     <!-- 预览图片或xml --> | ||||
|     <process-preview ref="previewRef" /> | ||||
|  | ||||
|     <!-- 部署文件 --> | ||||
|     <el-dialog v-if="uploadDialog.visible" v-model="uploadDialog.visible" :title="uploadDialog.title" width="30%"> | ||||
|       <div v-loading="uploadDialogLoading"> | ||||
|         <el-upload class="upload-demo" drag accept="application/zip,application/xml,.bpmn" :http-request="handerDeployProcessFile"> | ||||
|           <el-icon class="UploadFilled"><upload-filled /></el-icon> | ||||
|           <div class="el-upload__text"><em>点击上传,选择BPMN流程文件</em></div> | ||||
|           <div class="el-upload__text">仅支持 .zip、.bpmn20.xml、bpmn 格式文件</div> | ||||
|           <div class="el-upload__text">PS:如若部署请部署从本项目模型管理导出的数据</div> | ||||
|       </el-upload> | ||||
|       </div> | ||||
|     </el-dialog> | ||||
|  | ||||
|     <!-- 历史版本 --> | ||||
|     <el-dialog v-if="processDefinitionDialog.visible" v-model="processDefinitionDialog.visible" :title="processDefinitionDialog.title" width="70%"> | ||||
|       <el-table v-loading="loading" :data="processDefinitionHistoryList" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column type="selection" width="55" align="center" /> | ||||
|         <el-table-column fixed align="center" type="index" label="序号" width="50"></el-table-column> | ||||
|         <el-table-column fixed align="center" prop="name" label="流程定义名称"></el-table-column> | ||||
|         <el-table-column align="center" prop="key" label="标识Key"></el-table-column> | ||||
|         <el-table-column align="center" prop="version" label="版本号" width="90"> | ||||
|           <template #default="scope"> v{{ scope.row.version }}.0</template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" prop="resourceName" label="流程XML" min-width="80" :show-overflow-tooltip="true"> | ||||
|           <template #default="scope"> | ||||
|             <el-link type="primary" @click="clickPreviewXML(scope.row.id)">{{ scope.row.resourceName }}</el-link> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" prop="diagramResourceName" label="流程图片" min-width="80" :show-overflow-tooltip="true"> | ||||
|           <template #default="scope"> | ||||
|             <el-link type="primary" @click="clickPreviewImg(scope.row.id)">{{ scope.row.diagramResourceName }}</el-link> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" prop="suspensionState" label="状态" min-width="70"> | ||||
|           <template #default="scope"> | ||||
|             <el-tag v-if="scope.row.suspensionState == 1" type="success">激活</el-tag> | ||||
|             <el-tag v-else type="danger">挂起</el-tag> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" prop="deploymentTime" label="部署时间" :show-overflow-tooltip="true"></el-table-column> | ||||
|         <el-table-column fixed="right" label="操作" align="center" width="200" class-name="small-padding fixed-width"> | ||||
|           <template #default="scope"> | ||||
|             <el-row :gutter="10" class="mb8"> | ||||
|               <el-col :span="1.5"> | ||||
|                 <el-button | ||||
|                   link | ||||
|                   type="primary" | ||||
|                   size="small" | ||||
|                   :icon="scope.row.suspensionState === 1 ? 'Lock' : 'Unlock'" | ||||
|                   @click="handleProcessDefState(scope.row)" | ||||
|                 > | ||||
|                   {{ scope.row.suspensionState === 1 ? '挂起流程' : '激活流程' }} | ||||
|                 </el-button> | ||||
|               </el-col> | ||||
|               <el-col :span="1.5"> | ||||
|                 <el-button link type="primary" icon="Delete" size="small" @click="handleDelete(scope.row)">删除</el-button> | ||||
|               </el-col> | ||||
|             </el-row> | ||||
|             <el-row :gutter="10" class="mb8"> | ||||
|               <el-col :span="1.5"> | ||||
|                 <el-button link type="primary" icon="Sort" size="small" @click="handleConvertToModel(scope.row)"> 转换模型 </el-button> | ||||
|               </el-col> | ||||
|             </el-row> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup name="processDefinition"> | ||||
| import { | ||||
|   listProcessDefinition, | ||||
|   processDefinitionImage, | ||||
|   processDefinitionXml, | ||||
|   deleteProcessDefinition, | ||||
|   updateProcessDefState, | ||||
|   convertToModel, | ||||
|   deployProcessFile, | ||||
|   getProcessDefinitionListByKey | ||||
| } from '@/api/workflow/processDefinition'; | ||||
| import ProcessPreview from './components/processPreview.vue'; | ||||
| import { listCategory } from '@/api/workflow/category'; | ||||
| import { CategoryVO } from '@/api/workflow/category/types'; | ||||
| import { ProcessDefinitionQuery, ProcessDefinitionVO } from '@/api/workflow/processDefinition/types'; | ||||
| import { UploadRequestOptions } from 'element-plus'; | ||||
|  | ||||
| const { proxy } = getCurrentInstance() as ComponentInternalInstance; | ||||
|  | ||||
| const previewRef = ref<InstanceType<typeof ProcessPreview>>(); | ||||
| const queryFormRef = ref<ElFormInstance>(); | ||||
| const categoryTreeRef = ref<ElTreeInstance>(); | ||||
|  | ||||
| type CategoryOption = { | ||||
|   categoryCode: string; | ||||
|   categoryName: string; | ||||
|   children?: CategoryOption[]; | ||||
| }; | ||||
|  | ||||
| const loading = ref(true); | ||||
| const ids = ref<Array<string | number>>([]); | ||||
| const single = ref(true); | ||||
| const multiple = ref(true); | ||||
| const showSearch = ref(true); | ||||
| const total = ref(0); | ||||
| const uploadDialogLoading = ref(false); | ||||
| const processDefinitionList = ref<ProcessDefinitionVO[]>([]); | ||||
| const processDefinitionHistoryList = ref<ProcessDefinitionVO[]>([]); | ||||
| const url = ref<string[]>([]); | ||||
| const categoryOptions = ref<CategoryOption[]>([]); | ||||
| const categoryName = ref(''); | ||||
|  | ||||
| const uploadDialog = reactive<DialogOption>({ | ||||
|   visible: false, | ||||
|   title: '部署流程文件' | ||||
| }); | ||||
|  | ||||
| const processDefinitionDialog = reactive<DialogOption>({ | ||||
|   visible: false, | ||||
|   title: '历史版本' | ||||
| }); | ||||
|  | ||||
| // 查询参数 | ||||
| const queryParams = ref<ProcessDefinitionQuery>({ | ||||
|   pageNum: 1, | ||||
|   pageSize: 10, | ||||
|   name: undefined, | ||||
|   key: undefined, | ||||
|   categoryCode: undefined | ||||
| }); | ||||
|  | ||||
| onMounted(() => { | ||||
|   getList(); | ||||
|   getTreeselect(); | ||||
| }); | ||||
|  | ||||
| /** 节点单击事件 */ | ||||
| const handleNodeClick = (data: CategoryVO) => { | ||||
|   queryParams.value.categoryCode = data.categoryCode; | ||||
|   if (data.categoryCode === 'ALL') { | ||||
|     queryParams.value.categoryCode = ''; | ||||
|   } | ||||
|   handleQuery(); | ||||
| }; | ||||
| /** 通过条件过滤节点  */ | ||||
| const filterNode = (value: string, data: any) => { | ||||
|   if (!value) return true; | ||||
|   return data.categoryName.indexOf(value) !== -1; | ||||
| }; | ||||
| /** 根据名称筛选部门树 */ | ||||
| watchEffect( | ||||
|   () => { | ||||
|     categoryTreeRef.value.filter(categoryName.value); | ||||
|   }, | ||||
|   { | ||||
|     flush: 'post' // watchEffect会在DOM挂载或者更新之前就会触发,此属性控制在DOM元素更新后运行 | ||||
|   } | ||||
| ); | ||||
|  | ||||
| /** 查询流程分类下拉树结构 */ | ||||
| const getTreeselect = async () => { | ||||
|   const res = await listCategory(); | ||||
|   categoryOptions.value = []; | ||||
|   const data: CategoryOption = { categoryCode: 'ALL', categoryName: '顶级节点', children: [] }; | ||||
|   data.children = proxy?.handleTree<CategoryOption>(res.data, 'id', 'parentId'); | ||||
|   categoryOptions.value.push(data); | ||||
| }; | ||||
|  | ||||
| /** 搜索按钮操作 */ | ||||
| const handleQuery = () => { | ||||
|   queryParams.value.pageNum = 1; | ||||
|   getList(); | ||||
| }; | ||||
| /** 重置按钮操作 */ | ||||
| const resetQuery = () => { | ||||
|   queryFormRef.value?.resetFields(); | ||||
|   queryParams.value.categoryCode = ''; | ||||
|   queryParams.value.pageNum = 1; | ||||
|   queryParams.value.pageSize = 10; | ||||
|   handleQuery(); | ||||
| }; | ||||
| // 多选框选中数据 | ||||
| const handleSelectionChange = (selection: any) => { | ||||
|   ids.value = selection.map((item: any) => item.id); | ||||
|   single.value = selection.length !== 1; | ||||
|   multiple.value = !selection.length; | ||||
| }; | ||||
| //分页 | ||||
| const getList = async () => { | ||||
|   loading.value = true; | ||||
|   const resp = await listProcessDefinition(queryParams.value); | ||||
|   processDefinitionList.value = resp.rows; | ||||
|   total.value = resp.total; | ||||
|   loading.value = false; | ||||
| }; | ||||
| //获取历史流程定义 | ||||
| const getProcessDefinitionHitoryList = async (id: string, key: string) => { | ||||
|   processDefinitionDialog.visible = true; | ||||
|   loading.value = true; | ||||
|   const resp = await getProcessDefinitionListByKey(key); | ||||
|   if (resp.data && resp.data.length > 0) { | ||||
|     processDefinitionHistoryList.value = resp.data.filter((item: any) => item.id !== id); | ||||
|   } | ||||
|   loading.value = false; | ||||
| }; | ||||
|  | ||||
| //预览图片 | ||||
| const clickPreviewImg = async (id: string) => { | ||||
|   loading.value = true; | ||||
|   const resp = await processDefinitionImage(id); | ||||
|   if (previewRef.value) { | ||||
|     url.value = []; | ||||
|     url.value.push('data:image/png;base64,' + resp.data); | ||||
|     loading.value = false; | ||||
|     previewRef.value.openDialog(url.value, 'png'); | ||||
|   } | ||||
| }; | ||||
| //预览xml | ||||
| const clickPreviewXML = async (id: string) => { | ||||
|   loading.value = true; | ||||
|   const resp = await processDefinitionXml(id); | ||||
|   if (previewRef.value) { | ||||
|     url.value = []; | ||||
|     url.value = resp.data.xml; | ||||
|     loading.value = false; | ||||
|     previewRef.value.openDialog(url.value, 'xml'); | ||||
|   } | ||||
| }; | ||||
| /** 删除按钮操作 */ | ||||
| const handleDelete = async (row: ProcessDefinitionVO) => { | ||||
|   await proxy?.$modal.confirm('是否确认删除流程定义key为【' + row.key + '】的数据项?'); | ||||
|   loading.value = true; | ||||
|   await deleteProcessDefinition(row.deploymentId, row.id).finally(() => (loading.value = false)); | ||||
|   await getList(); | ||||
|   proxy?.$modal.msgSuccess('删除成功'); | ||||
| }; | ||||
| /** 挂起/激活 */ | ||||
| const handleProcessDefState = async (row: ProcessDefinitionVO) => { | ||||
|   let msg: string; | ||||
|   if (row.suspensionState === 1) { | ||||
|     msg = `暂停后,此流程下的所有任务都不允许往后流转,您确定挂起【${row.name || row.key}】吗?`; | ||||
|   } else { | ||||
|     msg = `启动后,此流程下的所有任务都允许往后流转,您确定激活【${row.name || row.key}】吗?`; | ||||
|   } | ||||
|   await proxy?.$modal.confirm(msg); | ||||
|   loading.value = true; | ||||
|   await updateProcessDefState(row.id).finally(() => (loading.value = false)); | ||||
|   await getList(); | ||||
|   proxy?.$modal.msgSuccess('操作成功'); | ||||
| }; | ||||
| /** 流程定义转换为模型 */ | ||||
| const handleConvertToModel = async (row: ProcessDefinitionVO) => { | ||||
|   await proxy?.$modal.confirm('是否确认转换流程定义key为【' + row.key + '】的数据项?'); | ||||
|   await convertToModel(row.id).finally(() => (loading.value = false)); | ||||
|   getList(); | ||||
|   proxy?.$modal.msgSuccess('操作成功'); | ||||
| }; | ||||
|  | ||||
| //部署文件 | ||||
| const handerDeployProcessFile = (data: UploadRequestOptions): XMLHttpRequest => { | ||||
|   let formData = new FormData(); | ||||
|   if (queryParams.value.categoryCode === 'ALL') { | ||||
|     proxy?.$modal.msgError('顶级节点不可作为分类!'); | ||||
|     return; | ||||
|   } | ||||
|   if (!queryParams.value.categoryCode) { | ||||
|     proxy?.$modal.msgError('请选择左侧要上传的分类!'); | ||||
|     return; | ||||
|   } | ||||
|   uploadDialogLoading.value = true | ||||
|   formData.append('file', data.file); | ||||
|   formData.append('categoryCode', queryParams.value.categoryCode); | ||||
|   deployProcessFile(formData).then(() => { | ||||
|     uploadDialog.visible = false; | ||||
|     proxy?.$modal.msgSuccess('部署成功'); | ||||
|     uploadDialogLoading.value = false | ||||
|     handleQuery(); | ||||
|   }); | ||||
| }; | ||||
| </script> | ||||
							
								
								
									
										363
									
								
								src/views/workflow/processInstance/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										363
									
								
								src/views/workflow/processInstance/index.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,363 @@ | ||||
| <template> | ||||
|   <div class="p-2"> | ||||
|     <el-row :gutter="20"> | ||||
|       <!-- 流程分类树 --> | ||||
|       <el-col :lg="4" :xs="24" style=""> | ||||
|         <el-card shadow="hover"> | ||||
|           <el-input v-model="categoryName" placeholder="请输入流程分类名" prefix-icon="Search" clearable /> | ||||
|           <el-tree | ||||
|             ref="categoryTreeRef" | ||||
|             class="mt-2" | ||||
|             node-key="id" | ||||
|             :data="categoryOptions" | ||||
|             :props="{ label: 'categoryName', children: 'children' }" | ||||
|             :expand-on-click-node="false" | ||||
|             :filter-node-method="filterNode" | ||||
|             highlight-current | ||||
|             default-expand-all | ||||
|             @node-click="handleNodeClick" | ||||
|           ></el-tree> | ||||
|         </el-card> | ||||
|       </el-col> | ||||
|       <el-col :lg="20" :xs="24"> | ||||
|         <div class="mb-[10px]"> | ||||
|           <el-card shadow="hover" class="text-center"> | ||||
|             <el-radio-group v-model="tab" @change="changeTab(tab)"> | ||||
|               <el-radio-button label="running">运行中</el-radio-button> | ||||
|               <el-radio-button label="finish">已完成</el-radio-button> | ||||
|             </el-radio-group> | ||||
|           </el-card> | ||||
|         </div> | ||||
|         <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> | ||||
|           <div v-show="showSearch" class="mb-[10px]"> | ||||
|             <el-card shadow="hover"> | ||||
|               <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true" label-width="120px"> | ||||
|                 <el-form-item label="流程定义名称" prop="name"> | ||||
|                   <el-input v-model="queryParams.name" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" /> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="流程定义KEY" prop="key"> | ||||
|                   <el-input v-model="queryParams.key" placeholder="请输入流程定义KEY" @keyup.enter="handleQuery" /> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item> | ||||
|                   <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> | ||||
|                   <el-button icon="Refresh" @click="resetQuery">重置</el-button> | ||||
|                 </el-form-item> | ||||
|               </el-form> | ||||
|             </el-card> | ||||
|           </div> | ||||
|         </transition> | ||||
|         <el-card shadow="hover"> | ||||
|           <template #header> | ||||
|             <el-row :gutter="10" class="mb8"> | ||||
|               <el-col :span="1.5"> | ||||
|                 <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button> | ||||
|               </el-col> | ||||
|               <right-toolbar v-model:showSearch="showSearch" @query-table="handleQuery"></right-toolbar> | ||||
|             </el-row> | ||||
|           </template> | ||||
|  | ||||
|           <el-table v-loading="loading" :data="processInstanceList" @selection-change="handleSelectionChange"> | ||||
|             <el-table-column type="selection" width="55" align="center" /> | ||||
|             <el-table-column fixed align="center" type="index" label="序号" width="50"></el-table-column> | ||||
|             <el-table-column v-if="false" fixed align="center" prop="id" label="id"></el-table-column> | ||||
|             <el-table-column fixed align="center" prop="processDefinitionName" label="流程定义名称"></el-table-column> | ||||
|             <el-table-column fixed align="center" prop="processDefinitionKey" label="流程定义KEY"></el-table-column> | ||||
|             <el-table-column align="center" prop="processDefinitionVersion" label="版本号" width="90"> | ||||
|               <template #default="scope"> v{{ scope.row.processDefinitionVersion }}.0</template> | ||||
|             </el-table-column> | ||||
|             <el-table-column v-if="tab === 'running'" align="center" prop="isSuspended" label="状态" min-width="70"> | ||||
|               <template #default="scope"> | ||||
|                 <el-tag v-if="!scope.row.isSuspended" type="success">激活</el-tag> | ||||
|                 <el-tag v-else type="danger">挂起</el-tag> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="center" prop="businessStatusName" label="流程状态" min-width="70"> | ||||
|               <template #default="scope"> | ||||
|                 <el-tag type="success">{{ scope.row.businessStatusName }}</el-tag> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="center" prop="startTime" label="启动时间" width="160"></el-table-column> | ||||
|             <el-table-column v-if="tab === 'finish'" align="center" prop="endTime" label="结束时间" width="160"></el-table-column> | ||||
|             <el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width"> | ||||
|               <template #default="scope"> | ||||
|                 <el-row :gutter="10" class="mb8"> | ||||
|                   <el-col :span="1.5"> | ||||
|                     <el-button link type="primary" size="small" icon="Document" @click="handleApprovalRecord(scope.row)">审批记录</el-button> | ||||
|                   </el-col> | ||||
|                   <el-col :span="1.5"> | ||||
|                     <el-button link type="primary" size="small" icon="Delete" @click="handleDelete(scope.row)">删除</el-button> | ||||
|                   </el-col> | ||||
|                 </el-row> | ||||
|                 <el-row v-if="tab === 'running'" :gutter="10" class="mb8"> | ||||
|                   <el-col :span="1.5"> | ||||
|                     <el-button | ||||
|                       link | ||||
|                       type="primary" | ||||
|                       size="small" | ||||
|                       icon="Sort" | ||||
|                       @click="getProcessDefinitionHitoryList(scope.row.processDefinitionId, scope.row.processDefinitionKey)" | ||||
|                       >切换版本</el-button | ||||
|                     > | ||||
|                   </el-col> | ||||
|                   <el-col :span="1.5"> | ||||
|                     <el-popover :ref="`popoverRef${scope.$index}`" trigger="click" placement="left" :width="300"> | ||||
|                       <el-input v-model="deleteReason" resize="none" :rows="3" type="textarea" placeholder="请输入作废原因" /> | ||||
|                       <div style="text-align: right; margin: 5px 0px 0px 0px"> | ||||
|                         <el-button size="small" text @click="cancelPopover(scope.$index)">取消</el-button> | ||||
|                         <el-button size="small" type="primary" @click="handleInvalid(scope.row)">确认</el-button> | ||||
|                       </div> | ||||
|                       <template #reference> | ||||
|                         <el-button link type="primary" size="small" icon="CircleClose">作废</el-button> | ||||
|                       </template> | ||||
|                     </el-popover> | ||||
|                   </el-col> | ||||
|                 </el-row> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|           </el-table> | ||||
|           <pagination | ||||
|             v-show="total > 0" | ||||
|             v-model:page="queryParams.pageNum" | ||||
|             v-model:limit="queryParams.pageSize" | ||||
|             :total="total" | ||||
|             @pagination="handleQuery" | ||||
|           /> | ||||
|         </el-card> | ||||
|       </el-col> | ||||
|     </el-row> | ||||
|     <el-dialog v-if="processDefinitionDialog.visible" v-model="processDefinitionDialog.visible" :title="processDefinitionDialog.title" width="70%"> | ||||
|       <el-table v-loading="loading" :data="processDefinitionHistoryList"> | ||||
|         <el-table-column fixed align="center" type="index" label="序号" width="50"></el-table-column> | ||||
|         <el-table-column fixed align="center" prop="name" label="流程定义名称"></el-table-column> | ||||
|         <el-table-column align="center" prop="key" label="标识Key"></el-table-column> | ||||
|         <el-table-column align="center" prop="version" label="版本号" width="90"> | ||||
|           <template #default="scope"> v{{ scope.row.version }}.0</template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" prop="suspensionState" label="状态" min-width="70"> | ||||
|           <template #default="scope"> | ||||
|             <el-tag v-if="scope.row.suspensionState == 1" type="success">激活</el-tag> | ||||
|             <el-tag v-else type="danger">挂起</el-tag> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" prop="deploymentTime" label="部署时间" :show-overflow-tooltip="true"></el-table-column> | ||||
|         <el-table-column fixed="right" label="操作" align="center" width="200" class-name="small-padding fixed-width"> | ||||
|           <template #default="scope"> | ||||
|             <el-button link type="primary" size="small" icon="Sort" @click="handleChange(scope.row.id)">切换</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|     </el-dialog> | ||||
|     <!-- 审批记录 --> | ||||
|     <approvalRecord ref="approvalRecordRef" /> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| import { | ||||
|   getProcessInstanceRunningByPage, | ||||
|   getProcessInstanceFinishByPage, | ||||
|   deleteRuntimeProcessAndHisInst, | ||||
|   deleteFinishProcessAndHisInst, | ||||
|   deleteRuntimeProcessInst | ||||
| } from '@/api/workflow/processInstance'; | ||||
| import { getProcessDefinitionListByKey, migrationProcessDefinition } from '@/api/workflow/processDefinition'; | ||||
| import ApprovalRecord from '@/components/Process/approvalRecord.vue'; | ||||
| import { listCategory } from '@/api/workflow/category'; | ||||
| import { CategoryVO } from '@/api/workflow/category/types'; | ||||
| import { ProcessInstanceQuery, ProcessInstanceVO } from '@/api/workflow/processInstance/types'; | ||||
| //审批记录组件 | ||||
| const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>(); | ||||
| const { proxy } = getCurrentInstance() as ComponentInternalInstance; | ||||
| const queryFormRef = ref<ElFormInstance>(); | ||||
| const categoryTreeRef = ref<ElTreeInstance>(); | ||||
|  | ||||
| // 遮罩层 | ||||
| const loading = ref(true); | ||||
| // 选中数组 | ||||
| const ids = ref<Array<any>>([]); | ||||
| // 非单个禁用 | ||||
| const single = ref(true); | ||||
| // 非多个禁用 | ||||
| const multiple = ref(true); | ||||
| // 显示搜索条件 | ||||
| const showSearch = ref(true); | ||||
| // 总条数 | ||||
| const total = ref(0); | ||||
| // 流程定义id | ||||
| const processDefinitionId = ref<string>(''); | ||||
| // 模型定义表格数据 | ||||
| const processInstanceList = ref<ProcessInstanceVO[]>([]); | ||||
| const processDefinitionHistoryList = ref<Array<any>>([]); | ||||
| const categoryOptions = ref<CategoryOption[]>([]); | ||||
| const categoryName = ref(''); | ||||
|  | ||||
| const processDefinitionDialog = reactive<DialogOption>({ | ||||
|   visible: false, | ||||
|   title: '流程定义' | ||||
| }); | ||||
|  | ||||
| type CategoryOption = { | ||||
|   categoryCode: string; | ||||
|   categoryName: string; | ||||
|   children?: CategoryOption[]; | ||||
| }; | ||||
|  | ||||
| const tab = ref('running'); | ||||
| // 作废原因 | ||||
| const deleteReason = ref(''); | ||||
| // 查询参数 | ||||
| const queryParams = ref<ProcessInstanceQuery>({ | ||||
|   pageNum: 1, | ||||
|   pageSize: 10, | ||||
|   name: undefined, | ||||
|   key: undefined, | ||||
|   categoryCode: undefined | ||||
| }); | ||||
|  | ||||
| onMounted(() => { | ||||
|   getProcessInstanceRunningList(); | ||||
|   getTreeselect(); | ||||
| }); | ||||
|  | ||||
| /** 节点单击事件 */ | ||||
| const handleNodeClick = (data: CategoryVO) => { | ||||
|   queryParams.value.categoryCode = data.categoryCode; | ||||
|   if (data.categoryCode === 'ALL') { | ||||
|     queryParams.value.categoryCode = ''; | ||||
|   } | ||||
|   handleQuery(); | ||||
| }; | ||||
| /** 通过条件过滤节点  */ | ||||
| const filterNode = (value: string, data: any) => { | ||||
|   if (!value) return true; | ||||
|   return data.categoryName.indexOf(value) !== -1; | ||||
| }; | ||||
| /** 根据名称筛选部门树 */ | ||||
| watchEffect( | ||||
|   () => { | ||||
|     categoryTreeRef.value.filter(categoryName.value); | ||||
|   }, | ||||
|   { | ||||
|     flush: 'post' // watchEffect会在DOM挂载或者更新之前就会触发,此属性控制在DOM元素更新后运行 | ||||
|   } | ||||
| ); | ||||
|  | ||||
| /** 查询流程分类下拉树结构 */ | ||||
| const getTreeselect = async () => { | ||||
|   const res = await listCategory(); | ||||
|   categoryOptions.value = []; | ||||
|   const data: CategoryOption = { categoryCode: 'ALL', categoryName: '顶级节点', children: [] }; | ||||
|   data.children = proxy?.handleTree<CategoryOption>(res.data, 'id', 'parentId'); | ||||
|   categoryOptions.value.push(data); | ||||
| }; | ||||
|  | ||||
| //审批记录 | ||||
| const handleApprovalRecord = (row: any) => { | ||||
|   if (approvalRecordRef.value) { | ||||
|     approvalRecordRef.value.init(row.id); | ||||
|   } | ||||
| }; | ||||
| /** 搜索按钮操作 */ | ||||
| const handleQuery = () => { | ||||
|   if ('running' === tab.value) { | ||||
|     getProcessInstanceRunningList(); | ||||
|   } else { | ||||
|     getProcessInstanceFinishList(); | ||||
|   } | ||||
| }; | ||||
| /** 重置按钮操作 */ | ||||
| const resetQuery = () => { | ||||
|   queryFormRef.value?.resetFields(); | ||||
|   queryParams.value.categoryCode = ''; | ||||
|   queryParams.value.pageNum = 1; | ||||
|   queryParams.value.pageSize = 10; | ||||
|   handleQuery(); | ||||
| }; | ||||
| // 多选框选中数据 | ||||
| const handleSelectionChange = (selection: ProcessInstanceVO[]) => { | ||||
|   ids.value = selection.map((item: any) => item.id); | ||||
|   single.value = selection.length !== 1; | ||||
|   multiple.value = !selection.length; | ||||
| }; | ||||
| //分页 | ||||
| const getProcessInstanceRunningList = () => { | ||||
|   loading.value = true; | ||||
|   getProcessInstanceRunningByPage(queryParams.value).then((resp) => { | ||||
|     processInstanceList.value = resp.rows; | ||||
|     total.value = resp.total; | ||||
|     loading.value = false; | ||||
|   }); | ||||
| }; | ||||
| //分页 | ||||
| const getProcessInstanceFinishList = () => { | ||||
|   loading.value = true; | ||||
|   getProcessInstanceFinishByPage(queryParams.value).then((resp) => { | ||||
|     processInstanceList.value = resp.rows; | ||||
|     total.value = resp.total; | ||||
|     loading.value = false; | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| /** 删除按钮操作 */ | ||||
| const handleDelete = async (row: any) => { | ||||
|   const id = row.id || ids.value; | ||||
|   await proxy?.$modal.confirm('是否确认删除id为【' + id + '】的数据项?'); | ||||
|   loading.value = true; | ||||
|   if ('running' === tab.value) { | ||||
|     await deleteRuntimeProcessAndHisInst(id).finally(() => (loading.value = false)); | ||||
|     getProcessInstanceRunningList(); | ||||
|   } else { | ||||
|     await deleteFinishProcessAndHisInst(id).finally(() => (loading.value = false)); | ||||
|     getProcessInstanceFinishList(); | ||||
|   } | ||||
|   proxy?.$modal.msgSuccess('删除成功'); | ||||
| }; | ||||
| const changeTab = async (data: string) => { | ||||
|   queryParams.value.pageNum = 1; | ||||
|   if ('running' === data) { | ||||
|     getProcessInstanceRunningList(); | ||||
|   } else { | ||||
|     getProcessInstanceFinishList(); | ||||
|   } | ||||
| }; | ||||
| /** 作废按钮操作 */ | ||||
| const handleInvalid = async (row: ProcessInstanceVO) => { | ||||
|   await proxy?.$modal.confirm('是否确认作废业务id为【' + row.businessKey + '】的数据项?'); | ||||
|   loading.value = true; | ||||
|   if ('running' === tab.value) { | ||||
|     let param = { | ||||
|       processInstanceId: row.id, | ||||
|       deleteReason: deleteReason.value | ||||
|     }; | ||||
|     await deleteRuntimeProcessInst(param).finally(() => (loading.value = false)); | ||||
|     getProcessInstanceRunningList(); | ||||
|     proxy?.$modal.msgSuccess('操作成功'); | ||||
|   } | ||||
| }; | ||||
| const cancelPopover = async (index: any) => { | ||||
|   (proxy?.$refs[`popoverRef${index}`] as any).hide(); //关闭弹窗 | ||||
| }; | ||||
| //获取流程定义 | ||||
| const getProcessDefinitionHitoryList = (id: string, key: string) => { | ||||
|   processDefinitionDialog.visible = true; | ||||
|   processDefinitionId.value = id; | ||||
|   loading.value = true; | ||||
|   getProcessDefinitionListByKey(key).then((resp) => { | ||||
|     if (resp.data && resp.data.length > 0) { | ||||
|       processDefinitionHistoryList.value = resp.data.filter((item: any) => item.id !== id); | ||||
|     } | ||||
|     loading.value = false; | ||||
|   }); | ||||
| }; | ||||
| //切换流程版本 | ||||
| const handleChange = async (id: string) => { | ||||
|   await proxy?.$modal.confirm('是否确认切换?'); | ||||
|   loading.value = true; | ||||
|   migrationProcessDefinition(processDefinitionId.value, id).then((resp) => { | ||||
|     proxy?.$modal.msgSuccess('操作成功'); | ||||
|     getProcessInstanceRunningList(); | ||||
|     processDefinitionDialog.visible = false; | ||||
|     loading.value = false; | ||||
|   }); | ||||
| }; | ||||
| </script> | ||||
							
								
								
									
										237
									
								
								src/views/workflow/task/allTaskWaiting.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										237
									
								
								src/views/workflow/task/allTaskWaiting.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,237 @@ | ||||
| <template> | ||||
|   <div class="p-2"> | ||||
|     <div class="mb-[10px]"> | ||||
|       <el-card shadow="hover" class="text-center"> | ||||
|         <el-radio-group v-model="tab" @change="changeTab(tab)"> | ||||
|           <el-radio-button label="waiting">待办任务</el-radio-button> | ||||
|           <el-radio-button label="finish">已办任务</el-radio-button> | ||||
|         </el-radio-group> | ||||
|       </el-card> | ||||
|     </div> | ||||
|     <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> | ||||
|       <div v-show="showSearch" class="mb-[10px]"> | ||||
|         <el-card shadow="hover"> | ||||
|           <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> | ||||
|             <el-form-item label="任务名称" prop="name"> | ||||
|               <el-input v-model="queryParams.name" placeholder="请输入任务名称" @keyup.enter="handleQuery" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="流程定义名称" label-width="100" prop="processDefinitionName"> | ||||
|               <el-input v-model="queryParams.processDefinitionName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="流程定义KEY" label-width="100" prop="processDefinitionKey"> | ||||
|               <el-input v-model="queryParams.processDefinitionKey" placeholder="请输入流程定义KEY" @keyup.enter="handleQuery" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item> | ||||
|               <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> | ||||
|               <el-button icon="Refresh" @click="resetQuery">重置</el-button> | ||||
|             </el-form-item> | ||||
|           </el-form> | ||||
|         </el-card> | ||||
|       </div> | ||||
|     </transition> | ||||
|     <el-card shadow="hover"> | ||||
|       <template #header> | ||||
|         <el-row :gutter="10" class="mb8"> | ||||
|           <el-col :span="1.5"> | ||||
|             <el-button type="primary" plain icon="Edit" @click="handleUpdate">修改办理人</el-button> | ||||
|           </el-col> | ||||
|           <right-toolbar v-model:showSearch="showSearch" @query-table="handleQuery"></right-toolbar> | ||||
|         </el-row> | ||||
|       </template> | ||||
|  | ||||
|       <el-table v-loading="loading" :data="taskList" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column type="selection" width="55" align="center" /> | ||||
|         <el-table-column fixed align="center" type="index" label="序号" width="50"></el-table-column> | ||||
|         <el-table-column fixed align="center" prop="processDefinitionName" label="流程定义名称"></el-table-column> | ||||
|         <el-table-column fixed align="center" prop="processDefinitionKey" label="流程定义KEY"></el-table-column> | ||||
|         <el-table-column fixed align="center" prop="name" label="任务名称"></el-table-column> | ||||
|         <el-table-column fixed align="center" prop="assigneeName" label="办理人"> | ||||
|           <template v-if="tab === 'waiting'" #default="scope"> | ||||
|             <template v-if="scope.row.participantVo && scope.row.assignee === null"> | ||||
|               <el-tag v-for="(item, index) in scope.row.participantVo.candidateName" :key="index" type="success"> | ||||
|                 {{ item }} | ||||
|               </el-tag> | ||||
|             </template> | ||||
|             <template v-else> | ||||
|               <el-tag type="success"> | ||||
|                 {{ scope.row.assigneeName }} | ||||
|               </el-tag> | ||||
|             </template> | ||||
|           </template> | ||||
|           <template v-else-if="tab === 'finish'" #default="scope"> | ||||
|             <el-tag type="success"> | ||||
|               {{ scope.row.assigneeName }} | ||||
|             </el-tag> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" prop="businessStatusName" label="流程状态" min-width="70"> | ||||
|           <template #default="scope"> | ||||
|             <el-tag v-if="tab === 'waiting'" type="success">{{ scope.row.businessStatusName }}</el-tag> | ||||
|             <el-tag v-else type="success">已完成</el-tag> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" prop="createTime" label="创建时间" width="160"></el-table-column> | ||||
|         <el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width"> | ||||
|           <template #default="scope"> | ||||
|             <el-row :gutter="10" class="mb8"> | ||||
|               <el-col :span="1.5"> | ||||
|                 <el-button link type="primary" size="small" icon="Document" @click="handleApprovalRecord(scope.row)">审批记录</el-button> | ||||
|               </el-col> | ||||
|               <el-col v-if="scope.row.multiInstance" :span="1.5"> | ||||
|                 <el-button link type="primary" size="small" icon="CirclePlus" @click="addMultiInstanceUser(scope.row)">加签</el-button> | ||||
|               </el-col> | ||||
|               <el-col v-if="scope.row.multiInstance" :span="1.5"> | ||||
|                 <el-button link type="primary" size="small" icon="Remove" @click="deleteMultiInstanceUser(scope.row)">减签</el-button> | ||||
|               </el-col> | ||||
|             </el-row> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <pagination | ||||
|         v-show="total > 0" | ||||
|         v-model:page="queryParams.pageNum" | ||||
|         v-model:limit="queryParams.pageSize" | ||||
|         :total="total" | ||||
|         @pagination="handleQuery" | ||||
|       /> | ||||
|     </el-card> | ||||
|     <!-- 审批记录 --> | ||||
|     <approvalRecord ref="approvalRecordRef" /> | ||||
|     <!-- 提交组件 --> | ||||
|     <submitVerify ref="submitVerifyRef" :task-id="taskId" @submit-callback="handleQuery" /> | ||||
|     <!-- 加签组件 --> | ||||
|     <multiInstanceUser ref="multiInstanceUserRef" :title="title" @submit-callback="handleQuery" /> | ||||
|     <!-- 加签组件 --> | ||||
|     <SysUser ref="sysUserRef" :multiple="true" @submit-callback="submitCallback" /> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| import { getAllTaskWaitByPage, getAllTaskFinishByPage, updateAssignee } from '@/api/workflow/task'; | ||||
| import ApprovalRecord from '@/components/Process/approvalRecord.vue'; | ||||
| import SubmitVerify from '@/components/Process/submitVerify.vue'; | ||||
| import MultiInstanceUser from '@/components/Process/multiInstance-user.vue'; | ||||
| import SysUser from '@/components/Process/sys-user.vue'; | ||||
| import { TaskQuery, TaskVO } from '@/api/workflow/task/types'; | ||||
| //提交组件 | ||||
| const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>(); | ||||
| //审批记录组件 | ||||
| const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>(); | ||||
| //加签组件 | ||||
| const multiInstanceUserRef = ref<InstanceType<typeof MultiInstanceUser>>(); | ||||
| //选人组件 | ||||
| const sysUserRef = ref<InstanceType<typeof SysUser>>(); | ||||
|  | ||||
| const queryFormRef = ref<ElFormInstance>(); | ||||
| const { proxy } = getCurrentInstance() as ComponentInternalInstance; | ||||
| // 遮罩层 | ||||
| const loading = ref(true); | ||||
| // 选中数组 | ||||
| const ids = ref<Array<any>>([]); | ||||
| // 非单个禁用 | ||||
| const single = ref(true); | ||||
| // 非多个禁用 | ||||
| const multiple = ref(true); | ||||
| // 显示搜索条件 | ||||
| const showSearch = ref(true); | ||||
| // 总条数 | ||||
| const total = ref(0); | ||||
| // 模型定义表格数据 | ||||
| const taskList = ref([]); | ||||
| // 任务id | ||||
| const taskId = ref(''); | ||||
| const title = ref(''); | ||||
| // 查询参数 | ||||
| const queryParams = ref<TaskQuery>({ | ||||
|   pageNum: 1, | ||||
|   pageSize: 10, | ||||
|   name: undefined, | ||||
|   processDefinitionName: undefined, | ||||
|   processDefinitionKey: undefined | ||||
| }); | ||||
| const tab = ref('waiting'); | ||||
| onMounted(() => { | ||||
|   getWaitingList(); | ||||
| }); | ||||
| //审批记录 | ||||
| const handleApprovalRecord = (row: TaskVO) => { | ||||
|   if (approvalRecordRef.value) { | ||||
|     approvalRecordRef.value.init(row.processInstanceId); | ||||
|   } | ||||
| }; | ||||
| //加签 | ||||
| const addMultiInstanceUser = (row: TaskVO) => { | ||||
|   if (multiInstanceUserRef.value) { | ||||
|     title.value = '加签人员'; | ||||
|     multiInstanceUserRef.value.getAddMultiInstanceList(row.id, []); | ||||
|   } | ||||
| }; | ||||
| //减签 | ||||
| const deleteMultiInstanceUser = (row: TaskVO) => { | ||||
|   if (multiInstanceUserRef.value) { | ||||
|     title.value = '减签人员'; | ||||
|     multiInstanceUserRef.value.getDeleteMultiInstanceList(row.id); | ||||
|   } | ||||
| }; | ||||
| /** 搜索按钮操作 */ | ||||
| const handleQuery = () => { | ||||
|   if ('waiting' === tab.value) { | ||||
|     getWaitingList(); | ||||
|   } else { | ||||
|     getFinishList(); | ||||
|   } | ||||
| }; | ||||
| /** 重置按钮操作 */ | ||||
| const resetQuery = () => { | ||||
|   queryFormRef.value?.resetFields(); | ||||
|   queryParams.value.pageNum = 1; | ||||
|   queryParams.value.pageSize = 10; | ||||
|   handleQuery(); | ||||
| }; | ||||
| // 多选框选中数据 | ||||
| const handleSelectionChange = (selection: any) => { | ||||
|   ids.value = selection.map((item: any) => item.id); | ||||
|   single.value = selection.length !== 1; | ||||
|   multiple.value = !selection.length; | ||||
| }; | ||||
| const changeTab = async (data: string) => { | ||||
|   queryParams.value.pageNum = 1; | ||||
|   if ('waiting' === data) { | ||||
|     getWaitingList(); | ||||
|   } else { | ||||
|     getFinishList(); | ||||
|   } | ||||
| }; | ||||
| //分页 | ||||
| const getWaitingList = () => { | ||||
|   loading.value = true; | ||||
|   getAllTaskWaitByPage(queryParams.value).then((resp) => { | ||||
|     taskList.value = resp.rows; | ||||
|     total.value = resp.total; | ||||
|     loading.value = false; | ||||
|   }); | ||||
| }; | ||||
| const getFinishList = () => { | ||||
|   loading.value = true; | ||||
|   getAllTaskFinishByPage(queryParams.value).then((resp) => { | ||||
|     taskList.value = resp.rows; | ||||
|     total.value = resp.total; | ||||
|     loading.value = false; | ||||
|   }); | ||||
| }; | ||||
| const handleUpdate = () => { | ||||
|   if (sysUserRef.value) { | ||||
|     sysUserRef.value.getUserList([]); | ||||
|   } | ||||
| }; | ||||
| //修改办理人 | ||||
| const submitCallback = (data) => { | ||||
|   if (data && data.value.length > 0) { | ||||
|     updateAssignee(ids.value, data.value[0].userId).then((resp) => { | ||||
|       sysUserRef.value.close(); | ||||
|       proxy?.$modal.msgSuccess('操作成功'); | ||||
|       handleQuery(); | ||||
|     }); | ||||
|   } | ||||
| }; | ||||
| </script> | ||||
							
								
								
									
										256
									
								
								src/views/workflow/task/myDocument.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										256
									
								
								src/views/workflow/task/myDocument.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,256 @@ | ||||
| <template> | ||||
|   <div class="p-2"> | ||||
|     <el-row :gutter="20"> | ||||
|       <!-- 流程分类树 --> | ||||
|       <el-col :lg="4" :xs="24" style=""> | ||||
|         <el-card shadow="hover"> | ||||
|           <el-input v-model="categoryName" placeholder="请输入流程分类名" prefix-icon="Search" clearable /> | ||||
|           <el-tree | ||||
|             ref="categoryTreeRef" | ||||
|             class="mt-2" | ||||
|             node-key="id" | ||||
|             :data="categoryOptions" | ||||
|             :props="{ label: 'categoryName', children: 'children' }" | ||||
|             :expand-on-click-node="false" | ||||
|             :filter-node-method="filterNode" | ||||
|             highlight-current | ||||
|             default-expand-all | ||||
|             @node-click="handleNodeClick" | ||||
|           ></el-tree> | ||||
|         </el-card> | ||||
|       </el-col> | ||||
|       <el-col :lg="20" :xs="24"> | ||||
|         <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> | ||||
|           <div v-show="showSearch" class="mb-[10px]"> | ||||
|             <el-card shadow="hover"> | ||||
|               <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true" label-width="120px"> | ||||
|                 <el-form-item label="流程定义名称" prop="name"> | ||||
|                   <el-input v-model="queryParams.name" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" /> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item> | ||||
|                   <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> | ||||
|                   <el-button icon="Refresh" @click="resetQuery">重置</el-button> | ||||
|                 </el-form-item> | ||||
|               </el-form> | ||||
|             </el-card> | ||||
|           </div> | ||||
|         </transition> | ||||
|         <el-card shadow="hover"> | ||||
|           <template #header> | ||||
|             <el-row :gutter="10" class="mb8"> | ||||
|               <right-toolbar v-model:showSearch="showSearch" @query-table="handleQuery"></right-toolbar> | ||||
|             </el-row> | ||||
|           </template> | ||||
|  | ||||
|           <el-table v-loading="loading" :data="processInstanceList" @selection-change="handleSelectionChange"> | ||||
|             <el-table-column type="selection" width="55" align="center" /> | ||||
|             <el-table-column fixed align="center" type="index" label="序号" width="50"></el-table-column> | ||||
|             <el-table-column v-if="false" fixed align="center" prop="id" label="id"></el-table-column> | ||||
|             <el-table-column fixed align="center" prop="processDefinitionName" label="流程定义名称"></el-table-column> | ||||
|             <el-table-column fixed align="center" prop="processDefinitionKey" label="流程定义KEY"></el-table-column> | ||||
|             <el-table-column align="center" prop="processDefinitionVersion" label="版本号" width="90"> | ||||
|               <template #default="scope"> v{{ scope.row.processDefinitionVersion }}.0</template> | ||||
|             </el-table-column> | ||||
|             <el-table-column v-if="tab === 'running'" align="center" prop="isSuspended" label="状态" min-width="70"> | ||||
|               <template #default="scope"> | ||||
|                 <el-tag v-if="!scope.row.isSuspended" type="success">激活</el-tag> | ||||
|                 <el-tag v-else type="danger">挂起</el-tag> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="center" prop="businessStatusName" label="流程状态" min-width="70"> | ||||
|               <template #default="scope"> | ||||
|                 <el-tag type="success">{{ scope.row.businessStatusName }}</el-tag> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="center" prop="startTime" label="启动时间" width="160"></el-table-column> | ||||
|             <el-table-column v-if="tab === 'finish'" align="center" prop="endTime" label="结束时间" width="160"></el-table-column> | ||||
|             <el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width"> | ||||
|               <template #default="scope"> | ||||
|                 <el-row :gutter="10" class="mb8"> | ||||
|                   <el-col :span="1.5"> | ||||
|                     <el-button link type="primary" size="small" icon="Document" @click="handleApprovalRecord(scope.row.id)">审批记录</el-button> | ||||
|                   </el-col> | ||||
|                   <el-col | ||||
|                     v-if="scope.row.businessStatus === 'draft' || scope.row.businessStatus === 'cancel' || scope.row.businessStatus === 'back'" | ||||
|                     :span="1.5" | ||||
|                   > | ||||
|                     <el-button link type="primary" size="small" icon="Delete" @click="handleDelete(scope.row)">删除</el-button> | ||||
|                   </el-col> | ||||
|                   <el-col v-if="scope.row.businessStatus === 'waiting'" :span="1.5"> | ||||
|                     <el-button link type="primary" size="small" icon="Notification" @click="handleCancelProcessApply(scope.row.id)">撤销</el-button> | ||||
|                   </el-col> | ||||
|                   <el-col | ||||
|                     v-if="scope.row.businessStatus === 'draft' || scope.row.businessStatus === 'cancel' || scope.row.businessStatus === 'back'" | ||||
|                     :span="1.5" | ||||
|                   > | ||||
|                     <el-button link type="primary" size="small" icon="Edit" @click="submitVerifyOpen(scope.row.taskVoList[0].id)">提交</el-button> | ||||
|                   </el-col> | ||||
|                 </el-row> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|           </el-table> | ||||
|           <pagination | ||||
|             v-show="total > 0" | ||||
|             v-model:page="queryParams.pageNum" | ||||
|             v-model:limit="queryParams.pageSize" | ||||
|             :total="total" | ||||
|             @pagination="getList" | ||||
|           /> | ||||
|         </el-card> | ||||
|       </el-col> | ||||
|     </el-row> | ||||
|     <!-- 审批记录 --> | ||||
|     <approvalRecord ref="approvalRecordRef" /> | ||||
|     <!-- 提交组件 --> | ||||
|     <submitVerify ref="submitVerifyRef" @submit-callback="getList" /> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| import { getCurrentSubmitByPage, deleteRuntimeProcessAndHisInst, cancelProcessApply } from '@/api/workflow/processInstance'; | ||||
| import ApprovalRecord from '@/components/Process/approvalRecord.vue'; | ||||
| import SubmitVerify from '@/components/Process/submitVerify.vue'; | ||||
| import { listCategory } from '@/api/workflow/category'; | ||||
| import { CategoryVO } from '@/api/workflow/category/types'; | ||||
| import { ProcessInstanceQuery, ProcessInstanceVO } from '@/api/workflow/processInstance/types'; | ||||
| //提交组件 | ||||
| const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>(); | ||||
| //审批记录组件 | ||||
| const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>(); | ||||
| const { proxy } = getCurrentInstance() as ComponentInternalInstance; | ||||
| const queryFormRef = ref<ElFormInstance>(); | ||||
| const categoryTreeRef = ref<ElTreeInstance>(); | ||||
|  | ||||
| // 遮罩层 | ||||
| const loading = ref(true); | ||||
| // 选中数组 | ||||
| const ids = ref<Array<any>>([]); | ||||
| // 非单个禁用 | ||||
| const single = ref(true); | ||||
| // 非多个禁用 | ||||
| const multiple = ref(true); | ||||
| // 显示搜索条件 | ||||
| const showSearch = ref(true); | ||||
| // 总条数 | ||||
| const total = ref(0); | ||||
| // 模型定义表格数据 | ||||
| const processInstanceList = ref<ProcessInstanceVO[]>([]); | ||||
|  | ||||
| const categoryOptions = ref<CategoryOption[]>([]); | ||||
| const categoryName = ref(''); | ||||
|  | ||||
| interface CategoryOption { | ||||
|   categoryCode: string; | ||||
|   categoryName: string; | ||||
|   children?: CategoryOption[]; | ||||
| } | ||||
|  | ||||
| const tab = ref('running'); | ||||
| // 查询参数 | ||||
| const queryParams = ref<ProcessInstanceQuery>({ | ||||
|   pageNum: 1, | ||||
|   pageSize: 10, | ||||
|   name: undefined, | ||||
|   categoryCode: undefined | ||||
| }); | ||||
|  | ||||
| onMounted(() => { | ||||
|   getList(); | ||||
|   getTreeselect(); | ||||
| }); | ||||
|  | ||||
| /** 节点单击事件 */ | ||||
| const handleNodeClick = (data: CategoryVO) => { | ||||
|   queryParams.value.categoryCode = data.categoryCode; | ||||
|   if (data.categoryCode === 'ALL') { | ||||
|     queryParams.value.categoryCode = ''; | ||||
|   } | ||||
|   handleQuery(); | ||||
| }; | ||||
| /** 通过条件过滤节点  */ | ||||
| const filterNode = (value: string, data: any) => { | ||||
|   if (!value) return true; | ||||
|   return data.categoryName.indexOf(value) !== -1; | ||||
| }; | ||||
| /** 根据名称筛选部门树 */ | ||||
| watchEffect( | ||||
|   () => { | ||||
|     categoryTreeRef.value.filter(categoryName.value); | ||||
|   }, | ||||
|   { | ||||
|     flush: 'post' // watchEffect会在DOM挂载或者更新之前就会触发,此属性控制在DOM元素更新后运行 | ||||
|   } | ||||
| ); | ||||
|  | ||||
| /** 查询流程分类下拉树结构 */ | ||||
| const getTreeselect = async () => { | ||||
|   const res = await listCategory(); | ||||
|   categoryOptions.value = []; | ||||
|   const data: CategoryOption = { categoryCode: 'ALL', categoryName: '顶级节点', children: [] }; | ||||
|   data.children = proxy?.handleTree<CategoryOption>(res.data, 'id', 'parentId'); | ||||
|   categoryOptions.value.push(data); | ||||
| }; | ||||
|  | ||||
| //审批记录 | ||||
| const handleApprovalRecord = (processInstanceId: string) => { | ||||
|   if (approvalRecordRef.value) { | ||||
|     approvalRecordRef.value.init(processInstanceId); | ||||
|   } | ||||
| }; | ||||
| /** 搜索按钮操作 */ | ||||
| const handleQuery = () => { | ||||
|   getList(); | ||||
| }; | ||||
| /** 重置按钮操作 */ | ||||
| const resetQuery = () => { | ||||
|   queryFormRef.value?.resetFields(); | ||||
|   queryParams.value.categoryCode = ''; | ||||
|   queryParams.value.pageNum = 1; | ||||
|   queryParams.value.pageSize = 10; | ||||
|   handleQuery(); | ||||
| }; | ||||
| // 多选框选中数据 | ||||
| const handleSelectionChange = (selection: ProcessInstanceVO[]) => { | ||||
|   ids.value = selection.map((item: any) => item.id); | ||||
|   single.value = selection.length !== 1; | ||||
|   multiple.value = !selection.length; | ||||
| }; | ||||
| //分页 | ||||
| const getList = () => { | ||||
|   loading.value = true; | ||||
|   getCurrentSubmitByPage(queryParams.value).then((resp) => { | ||||
|     processInstanceList.value = resp.rows; | ||||
|     total.value = resp.total; | ||||
|     loading.value = false; | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| /** 删除按钮操作 */ | ||||
| const handleDelete = async (row: ProcessInstanceVO) => { | ||||
|   const id = row.id || ids.value; | ||||
|   await proxy?.$modal.confirm('是否确认删除id为【' + id + '】的数据项?'); | ||||
|   loading.value = true; | ||||
|   if ('running' === tab.value) { | ||||
|     await deleteRuntimeProcessAndHisInst(id).finally(() => (loading.value = false)); | ||||
|     getList(); | ||||
|   } | ||||
|   proxy?.$modal.msgSuccess('删除成功'); | ||||
| }; | ||||
|  | ||||
| /** 撤销按钮操作 */ | ||||
| const handleCancelProcessApply = async (processInstanceId: string) => { | ||||
|   await proxy?.$modal.confirm('是否确认撤销当前单据?'); | ||||
|   loading.value = true; | ||||
|   if ('running' === tab.value) { | ||||
|     await cancelProcessApply(processInstanceId).finally(() => (loading.value = false)); | ||||
|     getList(); | ||||
|   } | ||||
|   proxy?.$modal.msgSuccess('撤销成功'); | ||||
| }; | ||||
| //提交 | ||||
| const submitVerifyOpen = async (id: string) => { | ||||
|   if (submitVerifyRef.value) { | ||||
|     submitVerifyRef.value.openDialog(id); | ||||
|   } | ||||
| }; | ||||
| </script> | ||||
							
								
								
									
										141
									
								
								src/views/workflow/task/taskCopyList.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								src/views/workflow/task/taskCopyList.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,141 @@ | ||||
| <template> | ||||
|   <div class="p-2"> | ||||
|     <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> | ||||
|       <div v-show="showSearch" class="mb-[10px]"> | ||||
|         <el-card shadow="hover"> | ||||
|           <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> | ||||
|             <el-form-item label="任务名称" prop="name"> | ||||
|               <el-input v-model="queryParams.name" placeholder="请输入任务名称" @keyup.enter="handleQuery" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="流程定义名称" label-width="100" prop="processDefinitionName"> | ||||
|               <el-input v-model="queryParams.processDefinitionName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="流程定义KEY" label-width="100" prop="processDefinitionKey"> | ||||
|               <el-input v-model="queryParams.processDefinitionKey" placeholder="请输入流程定义KEY" @keyup.enter="handleQuery" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item> | ||||
|               <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> | ||||
|               <el-button icon="Refresh" @click="resetQuery">重置</el-button> | ||||
|             </el-form-item> | ||||
|           </el-form> | ||||
|         </el-card> | ||||
|       </div> | ||||
|     </transition> | ||||
|     <el-card shadow="hover"> | ||||
|       <template #header> | ||||
|         <el-row :gutter="10" class="mb8"> | ||||
|           <right-toolbar v-model:showSearch="showSearch" @query-table="handleQuery"></right-toolbar> | ||||
|         </el-row> | ||||
|       </template> | ||||
|  | ||||
|       <el-table v-loading="loading" :data="taskList" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column type="selection" width="55" align="center" /> | ||||
|         <el-table-column fixed align="center" type="index" label="序号" width="50"></el-table-column> | ||||
|         <el-table-column fixed align="center" prop="processDefinitionName" label="流程定义名称"></el-table-column> | ||||
|         <el-table-column fixed align="center" prop="processDefinitionKey" label="流程定义KEY"></el-table-column> | ||||
|         <el-table-column fixed align="center" prop="name" label="任务名称"></el-table-column> | ||||
|         <el-table-column fixed align="center" prop="assigneeName" label="办理人"> | ||||
|           <template #default="scope"> | ||||
|             <template v-if="scope.row.participantVo && scope.row.assignee === null"> | ||||
|               <el-tag v-for="(item, index) in scope.row.participantVo.candidateName" :key="index" type="success"> | ||||
|                 {{ item }} | ||||
|               </el-tag> | ||||
|             </template> | ||||
|             <template v-else> | ||||
|               <el-tag type="success"> | ||||
|                 {{ scope.row.assigneeName }} | ||||
|               </el-tag> | ||||
|             </template> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" prop="businessStatusName" label="流程状态" min-width="70"> | ||||
|           <template #default="scope"> | ||||
|             <el-tag type="success">{{ scope.row.businessStatusName }}</el-tag> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width"> | ||||
|           <template #default="scope"> | ||||
|             <el-button link type="primary" size="small" icon="Document" @click="handleApprovalRecord(scope.row)">审批记录</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <pagination | ||||
|         v-show="total > 0" | ||||
|         v-model:page="queryParams.pageNum" | ||||
|         v-model:limit="queryParams.pageSize" | ||||
|         :total="total" | ||||
|         @pagination="handleQuery" | ||||
|       /> | ||||
|     </el-card> | ||||
|     <!-- 审批记录 --> | ||||
|     <approvalRecord ref="approvalRecordRef" /> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| import { getTaskCopyByPage} from '@/api/workflow/task'; | ||||
| import ApprovalRecord from '@/components/Process/approvalRecord.vue'; | ||||
| import { TaskQuery, TaskVO } from '@/api/workflow/task/types'; | ||||
| //审批记录组件 | ||||
| const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>(); | ||||
| const queryFormRef = ref<ElFormInstance>(); | ||||
| const { proxy } = getCurrentInstance() as ComponentInternalInstance; | ||||
| // 遮罩层 | ||||
| const loading = ref(true); | ||||
| // 选中数组 | ||||
| const ids = ref<Array<any>>([]); | ||||
| // 非单个禁用 | ||||
| const single = ref(true); | ||||
| // 非多个禁用 | ||||
| const multiple = ref(true); | ||||
| // 显示搜索条件 | ||||
| const showSearch = ref(true); | ||||
| // 总条数 | ||||
| const total = ref(0); | ||||
| // 模型定义表格数据 | ||||
| const taskList = ref([]); | ||||
| // 查询参数 | ||||
| const queryParams = ref<TaskQuery>({ | ||||
|   pageNum: 1, | ||||
|   pageSize: 10, | ||||
|   name: undefined, | ||||
|   processDefinitionName: undefined, | ||||
|   processDefinitionKey: undefined | ||||
| }); | ||||
| onMounted(() => { | ||||
|   getTaskCopyList(); | ||||
| }); | ||||
| //审批记录 | ||||
| const handleApprovalRecord = (row: TaskVO) => { | ||||
|   if (approvalRecordRef.value) { | ||||
|     approvalRecordRef.value.init(row.processInstanceId); | ||||
|   } | ||||
| }; | ||||
| /** 搜索按钮操作 */ | ||||
| const handleQuery = () => { | ||||
|   getTaskCopyList(); | ||||
| }; | ||||
| /** 重置按钮操作 */ | ||||
| const resetQuery = () => { | ||||
|   queryFormRef.value?.resetFields(); | ||||
|   queryParams.value.pageNum = 1; | ||||
|   queryParams.value.pageSize = 10; | ||||
|   handleQuery(); | ||||
| }; | ||||
| // 多选框选中数据 | ||||
| const handleSelectionChange = (selection: any) => { | ||||
|   ids.value = selection.map((item: any) => item.id); | ||||
|   single.value = selection.length !== 1; | ||||
|   multiple.value = !selection.length; | ||||
| }; | ||||
| //分页 | ||||
| const getTaskCopyList = () => { | ||||
|   loading.value = true; | ||||
|   getTaskCopyByPage(queryParams.value).then((resp) => { | ||||
|     taskList.value = resp.rows; | ||||
|     total.value = resp.total; | ||||
|     loading.value = false; | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| </script> | ||||
							
								
								
									
										128
									
								
								src/views/workflow/task/taskFinish.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								src/views/workflow/task/taskFinish.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,128 @@ | ||||
| <template> | ||||
|   <div class="p-2"> | ||||
|     <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> | ||||
|       <div v-show="showSearch" class="mb-[10px]"> | ||||
|         <el-card shadow="hover"> | ||||
|           <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> | ||||
|             <el-form-item label="任务名称" prop="name"> | ||||
|               <el-input v-model="queryParams.name" placeholder="请输入任务名称" @keyup.enter="handleQuery" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="流程定义名称" label-width="100" prop="processDefinitionName"> | ||||
|               <el-input v-model="queryParams.processDefinitionName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="流程定义KEY" label-width="100" prop="processDefinitionKey"> | ||||
|               <el-input v-model="queryParams.processDefinitionKey" placeholder="请输入流程定义KEY" @keyup.enter="handleQuery" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item> | ||||
|               <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> | ||||
|               <el-button icon="Refresh" @click="resetQuery">重置</el-button> | ||||
|             </el-form-item> | ||||
|           </el-form> | ||||
|         </el-card> | ||||
|       </div> | ||||
|     </transition> | ||||
|     <el-card shadow="hover"> | ||||
|       <template #header> | ||||
|         <el-row :gutter="10" class="mb8"> | ||||
|           <right-toolbar v-model:showSearch="showSearch" @query-table="handleQuery"></right-toolbar> | ||||
|         </el-row> | ||||
|       </template> | ||||
|  | ||||
|       <el-table v-loading="loading" :data="taskList" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column type="selection" width="55" align="center" /> | ||||
|         <el-table-column fixed align="center" type="index" label="序号" width="50"></el-table-column> | ||||
|         <el-table-column fixed align="center" prop="processDefinitionName" label="流程定义名称"></el-table-column> | ||||
|         <el-table-column fixed align="center" prop="processDefinitionKey" label="流程定义KEY"></el-table-column> | ||||
|         <el-table-column fixed align="center" prop="name" label="任务名称"></el-table-column> | ||||
|         <el-table-column fixed align="center" prop="assigneeName" label="办理人"> | ||||
|           <template #default="scope"> | ||||
|             <el-tag type="success"> | ||||
|               {{ scope.row.assigneeName }} | ||||
|             </el-tag> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" prop="createTime" label="创建时间" width="160"></el-table-column> | ||||
|         <el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width"> | ||||
|           <template #default="scope"> | ||||
|             <el-button link type="primary" size="small" icon="Document" @click="handleApprovalRecord(scope.row)">审批记录</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <pagination | ||||
|         v-show="total > 0" | ||||
|         v-model:page="queryParams.pageNum" | ||||
|         v-model:limit="queryParams.pageSize" | ||||
|         :total="total" | ||||
|         @pagination="handleQuery" | ||||
|       /> | ||||
|     </el-card> | ||||
|     <!-- 审批记录 --> | ||||
|     <approvalRecord ref="approvalRecordRef" /> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| import { getTaskFinishByPage } from '@/api/workflow/task'; | ||||
| import ApprovalRecord from '@/components/Process/approvalRecord.vue'; | ||||
| import { TaskQuery, TaskVO } from '@/api/workflow/task/types'; | ||||
| //审批记录组件 | ||||
| const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>(); | ||||
| const queryFormRef = ref<ElFormInstance>(); | ||||
| const { proxy } = getCurrentInstance() as ComponentInternalInstance; | ||||
| // 遮罩层 | ||||
| const loading = ref(true); | ||||
| // 选中数组 | ||||
| const ids = ref<Array<any>>([]); | ||||
| // 非单个禁用 | ||||
| const single = ref(true); | ||||
| // 非多个禁用 | ||||
| const multiple = ref(true); | ||||
| // 显示搜索条件 | ||||
| const showSearch = ref(true); | ||||
| // 总条数 | ||||
| const total = ref(0); | ||||
| // 模型定义表格数据 | ||||
| const taskList = ref([]); | ||||
| // 查询参数 | ||||
| const queryParams = ref<TaskQuery>({ | ||||
|   pageNum: 1, | ||||
|   pageSize: 10, | ||||
|   name: undefined, | ||||
|   processDefinitionName: undefined, | ||||
|   processDefinitionKey: undefined | ||||
| }); | ||||
| onMounted(() => { | ||||
|   getFinishList(); | ||||
| }); | ||||
| //审批记录 | ||||
| const handleApprovalRecord = (row: TaskVO) => { | ||||
|   if (approvalRecordRef.value) { | ||||
|     approvalRecordRef.value.init(row.processInstanceId); | ||||
|   } | ||||
| }; | ||||
| /** 搜索按钮操作 */ | ||||
| const handleQuery = () => { | ||||
|   getFinishList(); | ||||
| }; | ||||
| /** 重置按钮操作 */ | ||||
| const resetQuery = () => { | ||||
|   queryFormRef.value?.resetFields(); | ||||
|   queryParams.value.pageNum = 1; | ||||
|   queryParams.value.pageSize = 10; | ||||
|   handleQuery(); | ||||
| }; | ||||
| // 多选框选中数据 | ||||
| const handleSelectionChange = (selection: any) => { | ||||
|   ids.value = selection.map((item: any) => item.id); | ||||
|   single.value = selection.length !== 1; | ||||
|   multiple.value = !selection.length; | ||||
| }; | ||||
| const getFinishList = () => { | ||||
|   loading.value = true; | ||||
|   getTaskFinishByPage(queryParams.value).then((resp) => { | ||||
|     taskList.value = resp.rows; | ||||
|     total.value = resp.total; | ||||
|     loading.value = false; | ||||
|   }); | ||||
| }; | ||||
| </script> | ||||
							
								
								
									
										181
									
								
								src/views/workflow/task/taskWaiting.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										181
									
								
								src/views/workflow/task/taskWaiting.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,181 @@ | ||||
| <template> | ||||
|   <div class="p-2"> | ||||
|     <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> | ||||
|       <div v-show="showSearch" class="mb-[10px]"> | ||||
|         <el-card shadow="hover"> | ||||
|           <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> | ||||
|             <el-form-item label="任务名称" prop="name"> | ||||
|               <el-input v-model="queryParams.name" placeholder="请输入任务名称" @keyup.enter="handleQuery" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="流程定义名称" label-width="100" prop="processDefinitionName"> | ||||
|               <el-input v-model="queryParams.processDefinitionName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="流程定义KEY" label-width="100" prop="processDefinitionKey"> | ||||
|               <el-input v-model="queryParams.processDefinitionKey" placeholder="请输入流程定义KEY" @keyup.enter="handleQuery" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item> | ||||
|               <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> | ||||
|               <el-button icon="Refresh" @click="resetQuery">重置</el-button> | ||||
|             </el-form-item> | ||||
|           </el-form> | ||||
|         </el-card> | ||||
|       </div> | ||||
|     </transition> | ||||
|     <el-card shadow="hover"> | ||||
|       <template #header> | ||||
|         <el-row :gutter="10" class="mb8"> | ||||
|           <right-toolbar v-model:showSearch="showSearch" @query-table="handleQuery"></right-toolbar> | ||||
|         </el-row> | ||||
|       </template> | ||||
|  | ||||
|       <el-table v-loading="loading" :data="taskList" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column type="selection" width="55" align="center" /> | ||||
|         <el-table-column fixed align="center" type="index" label="序号" width="50"></el-table-column> | ||||
|         <el-table-column fixed align="center" prop="processDefinitionName" label="流程定义名称"></el-table-column> | ||||
|         <el-table-column fixed align="center" prop="processDefinitionKey" label="流程定义KEY"></el-table-column> | ||||
|         <el-table-column fixed align="center" prop="name" label="任务名称"></el-table-column> | ||||
|         <el-table-column fixed align="center" prop="assigneeName" label="办理人"> | ||||
|           <template #default="scope"> | ||||
|             <template v-if="scope.row.participantVo && scope.row.assignee === null"> | ||||
|               <el-tag v-for="(item, index) in scope.row.participantVo.candidateName" :key="index" type="success"> | ||||
|                 {{ item }} | ||||
|               </el-tag> | ||||
|             </template> | ||||
|             <template v-else> | ||||
|               <el-tag type="success"> | ||||
|                 {{ scope.row.assigneeName }} | ||||
|               </el-tag> | ||||
|             </template> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" prop="businessStatusName" label="流程状态" min-width="70"> | ||||
|           <template #default="scope"> | ||||
|             <el-tag type="success">{{ scope.row.businessStatusName }}</el-tag> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" prop="createTime" label="创建时间" width="160"></el-table-column> | ||||
|         <el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width"> | ||||
|           <template #default="scope"> | ||||
|             <el-row :gutter="10" class="mb8"> | ||||
|               <el-col :span="1.5"> | ||||
|                 <el-button link type="primary" size="small" icon="Document" @click="handleApprovalRecord(scope.row)">审批记录</el-button> | ||||
|               </el-col> | ||||
|               <el-col v-if="scope.row.participantVo && (scope.row.participantVo.claim === null || scope.row.participantVo.claim === true)" :span="1.5"> | ||||
|                 <el-button link type="primary" size="small" icon="Edit" @click="submitVerifyOpen(scope.row.id)">办理</el-button> | ||||
|               </el-col> | ||||
|               <el-col v-if="scope.row.participantVo && scope.row.participantVo.claim === true" :span="1.5"> | ||||
|                 <el-button link type="primary" size="small" icon="Document" @click="handleReturnTask(scope.row.id)">归还</el-button> | ||||
|               </el-col> | ||||
|               <el-col v-if="scope.row.participantVo && scope.row.participantVo.claim === false" :span="1.5"> | ||||
|                 <el-button link type="primary" size="small" icon="Document" @click="handleClaimTask(scope.row.id)">认领</el-button> | ||||
|               </el-col> | ||||
|             </el-row> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <pagination | ||||
|         v-show="total > 0" | ||||
|         v-model:page="queryParams.pageNum" | ||||
|         v-model:limit="queryParams.pageSize" | ||||
|         :total="total" | ||||
|         @pagination="handleQuery" | ||||
|       /> | ||||
|     </el-card> | ||||
|     <!-- 审批记录 --> | ||||
|     <approvalRecord ref="approvalRecordRef" /> | ||||
|     <!-- 提交组件 --> | ||||
|     <submitVerify ref="submitVerifyRef" @submit-callback="handleQuery" /> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| import { getTaskWaitByPage, claim, returnTask } from '@/api/workflow/task'; | ||||
| import ApprovalRecord from '@/components/Process/approvalRecord.vue'; | ||||
| import SubmitVerify from '@/components/Process/submitVerify.vue'; | ||||
| import { TaskQuery, TaskVO } from '@/api/workflow/task/types'; | ||||
| //提交组件 | ||||
| const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>(); | ||||
| //审批记录组件 | ||||
| const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>(); | ||||
| const queryFormRef = ref<ElFormInstance>(); | ||||
| const { proxy } = getCurrentInstance() as ComponentInternalInstance; | ||||
| // 遮罩层 | ||||
| const loading = ref(true); | ||||
| // 选中数组 | ||||
| const ids = ref<Array<any>>([]); | ||||
| // 非单个禁用 | ||||
| const single = ref(true); | ||||
| // 非多个禁用 | ||||
| const multiple = ref(true); | ||||
| // 显示搜索条件 | ||||
| const showSearch = ref(true); | ||||
| // 总条数 | ||||
| const total = ref(0); | ||||
| // 模型定义表格数据 | ||||
| const taskList = ref([]); | ||||
| // 查询参数 | ||||
| const queryParams = ref<TaskQuery>({ | ||||
|   pageNum: 1, | ||||
|   pageSize: 10, | ||||
|   name: undefined, | ||||
|   processDefinitionName: undefined, | ||||
|   processDefinitionKey: undefined | ||||
| }); | ||||
| onMounted(() => { | ||||
|   getWaitingList(); | ||||
| }); | ||||
| //审批记录 | ||||
| const handleApprovalRecord = (row: TaskVO) => { | ||||
|   if (approvalRecordRef.value) { | ||||
|     approvalRecordRef.value.init(row.processInstanceId); | ||||
|   } | ||||
| }; | ||||
| /** 搜索按钮操作 */ | ||||
| const handleQuery = () => { | ||||
|   getWaitingList(); | ||||
| }; | ||||
| /** 重置按钮操作 */ | ||||
| const resetQuery = () => { | ||||
|   queryFormRef.value?.resetFields(); | ||||
|   queryParams.value.pageNum = 1; | ||||
|   queryParams.value.pageSize = 10; | ||||
|   handleQuery(); | ||||
| }; | ||||
| // 多选框选中数据 | ||||
| const handleSelectionChange = (selection: any) => { | ||||
|   ids.value = selection.map((item: any) => item.id); | ||||
|   single.value = selection.length !== 1; | ||||
|   multiple.value = !selection.length; | ||||
| }; | ||||
| //分页 | ||||
| const getWaitingList = () => { | ||||
|   loading.value = true; | ||||
|   getTaskWaitByPage(queryParams.value).then((resp) => { | ||||
|     taskList.value = resp.rows; | ||||
|     total.value = resp.total; | ||||
|     loading.value = false; | ||||
|   }); | ||||
| }; | ||||
| //提交 | ||||
| const submitVerifyOpen = async (id: string) => { | ||||
|   if (submitVerifyRef.value) { | ||||
|     submitVerifyRef.value.openDialog(id); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| /** 认领任务 */ | ||||
| const handleClaimTask = async (taskId: string) => { | ||||
|   loading.value = true; | ||||
|   await claim(taskId).finally(() => (loading.value = false)); | ||||
|   getWaitingList(); | ||||
|   proxy?.$modal.msgSuccess('操作成功'); | ||||
| }; | ||||
|  | ||||
| /** 归还任务 */ | ||||
| const handleReturnTask = async (taskId: string) => { | ||||
|   loading.value = true; | ||||
|   await returnTask(taskId).finally(() => (loading.value = false)); | ||||
|   getWaitingList(); | ||||
|   proxy?.$modal.msgSuccess('操作成功'); | ||||
| }; | ||||
| </script> | ||||
		Reference in New Issue
	
	Block a user
	 疯狂的狮子Li
					疯狂的狮子Li