index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. <template>
  2. <ContentWrap>
  3. <!-- 搜索工作栏 -->
  4. <el-form
  5. class="-mb-15px"
  6. :model="queryParams"
  7. ref="queryFormRef"
  8. :inline="true"
  9. label-width="68px"
  10. >
  11. <el-form-item label="流程标识" prop="key">
  12. <el-input
  13. v-model="queryParams.key"
  14. placeholder="请输入流程标识"
  15. clearable
  16. @keyup.enter="handleQuery"
  17. class="!w-240px"
  18. />
  19. </el-form-item>
  20. <el-form-item label="流程名称" prop="name">
  21. <el-input
  22. v-model="queryParams.name"
  23. placeholder="请输入流程名称"
  24. clearable
  25. @keyup.enter="handleQuery"
  26. class="!w-240px"
  27. />
  28. </el-form-item>
  29. <el-form-item label="流程分类" prop="category">
  30. <el-select
  31. v-model="queryParams.category"
  32. placeholder="请选择流程分类"
  33. clearable
  34. class="!w-240px"
  35. >
  36. <el-option
  37. v-for="dict in getIntDictOptions(DICT_TYPE.BPM_MODEL_CATEGORY)"
  38. :key="dict.value"
  39. :label="dict.label"
  40. :value="dict.value"
  41. />
  42. </el-select>
  43. </el-form-item>
  44. <el-form-item>
  45. <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
  46. <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
  47. <el-button
  48. type="primary"
  49. plain
  50. @click="openForm('create')"
  51. v-hasPermi="['bpm:model:create']"
  52. >
  53. <Icon icon="ep:plus" class="mr-5px" /> 新建流程
  54. </el-button>
  55. <el-button type="success" plain @click="openImportForm" v-hasPermi="['bpm:model:import']">
  56. <Icon icon="ep:upload" class="mr-5px" /> 导入流程
  57. </el-button>
  58. </el-form-item>
  59. </el-form>
  60. </ContentWrap>
  61. <!-- 列表 -->
  62. <ContentWrap>
  63. <el-table v-loading="loading" :data="list">
  64. <el-table-column label="流程标识" align="center" prop="key" width="200" />
  65. <el-table-column label="流程名称" align="center" prop="name" width="200">
  66. <template #default="scope">
  67. <el-button type="text" @click="handleBpmnDetail(scope.row)">
  68. <span>{{ scope.row.name }}</span>
  69. </el-button>
  70. </template>
  71. </el-table-column>
  72. <el-table-column label="流程分类" align="center" prop="category" width="100">
  73. <template #default="scope">
  74. <dict-tag :type="DICT_TYPE.BPM_MODEL_CATEGORY" :value="scope.row.category" />
  75. </template>
  76. </el-table-column>
  77. <el-table-column label="表单信息" align="center" prop="formType" width="200">
  78. <template #default="scope">
  79. <el-button
  80. v-if="scope.row.formType === 10"
  81. type="text"
  82. @click="handleFormDetail(scope.row)"
  83. >
  84. <span>{{ scope.row.formName }}</span>
  85. </el-button>
  86. <el-button
  87. v-else-if="scope.row.formType === 20"
  88. type="text"
  89. @click="handleFormDetail(scope.row)"
  90. >
  91. <span>{{ scope.row.formCustomCreatePath }}</span>
  92. </el-button>
  93. <label v-else>暂无表单</label>
  94. </template>
  95. </el-table-column>
  96. <el-table-column
  97. label="创建时间"
  98. align="center"
  99. prop="createTime"
  100. width="180"
  101. :formatter="dateFormatter"
  102. />
  103. <el-table-column label="最新部署的流程定义" align="center">
  104. <el-table-column
  105. label="流程版本"
  106. align="center"
  107. prop="processDefinition.version"
  108. width="100"
  109. >
  110. <template #default="scope">
  111. <el-tag v-if="scope.row.processDefinition">
  112. v{{ scope.row.processDefinition.version }}
  113. </el-tag>
  114. <el-tag v-else type="warning">未部署</el-tag>
  115. </template>
  116. </el-table-column>
  117. <el-table-column
  118. label="激活状态"
  119. align="center"
  120. prop="processDefinition.version"
  121. width="85"
  122. >
  123. <template #default="scope">
  124. <el-switch
  125. v-if="scope.row.processDefinition"
  126. v-model="scope.row.processDefinition.suspensionState"
  127. :active-value="1"
  128. :inactive-value="2"
  129. @change="handleChangeState(scope.row)"
  130. />
  131. </template>
  132. </el-table-column>
  133. <el-table-column label="部署时间" align="center" prop="deploymentTime" width="180">
  134. <template #default="scope">
  135. <span v-if="scope.row.processDefinition">
  136. {{ formatDate(scope.row.processDefinition.deploymentTime) }}
  137. </span>
  138. </template>
  139. </el-table-column>
  140. </el-table-column>
  141. <el-table-column label="操作" align="center" width="240" fixed="right">
  142. <template #default="scope">
  143. <el-button
  144. link
  145. type="primary"
  146. @click="openForm('update', scope.row.id)"
  147. v-hasPermi="['bpm:model:update']"
  148. >
  149. 修改流程
  150. </el-button>
  151. <el-button
  152. link
  153. type="primary"
  154. @click="handleDesign(scope.row)"
  155. v-hasPermi="['bpm:model:update']"
  156. >
  157. 设计流程
  158. </el-button>
  159. <el-button
  160. link
  161. type="primary"
  162. @click="handleAssignRule(scope.row)"
  163. v-hasPermi="['bpm:task-assign-rule:query']"
  164. >
  165. 分配规则
  166. </el-button>
  167. <el-button
  168. link
  169. type="primary"
  170. @click="handleDeploy(scope.row)"
  171. v-hasPermi="['bpm:model:deploy']"
  172. >
  173. 发布流程
  174. </el-button>
  175. <el-button
  176. link
  177. type="primary"
  178. v-hasPermi="['bpm:process-definition:query']"
  179. @click="handleDefinitionList(scope.row)"
  180. >
  181. 流程定义
  182. </el-button>
  183. <el-button
  184. link
  185. type="danger"
  186. @click="handleDelete(scope.row.id)"
  187. v-hasPermi="['bpm:model:delete']"
  188. >
  189. 删除
  190. </el-button>
  191. </template>
  192. </el-table-column>
  193. </el-table>
  194. <!-- 分页 -->
  195. <Pagination
  196. :total="total"
  197. v-model:page="queryParams.pageNo"
  198. v-model:limit="queryParams.pageSize"
  199. @pagination="getList"
  200. />
  201. </ContentWrap>
  202. <!-- 表单弹窗:添加/修改流程 -->
  203. <ModelForm ref="formRef" @success="getList" />
  204. <!-- 表单弹窗:导入流程 -->
  205. <ModelImportForm ref="importFormRef" @success="getList" />
  206. <!-- 弹窗:表单详情 -->
  207. <Dialog title="表单详情" v-model="formDetailVisible" width="800">
  208. <form-create :rule="formDetailPreview.rule" :option="formDetailPreview.option" />
  209. </Dialog>
  210. <!-- 弹窗:流程模型图的预览 -->
  211. <Dialog title="流程图" v-model="bpmnDetailVisible" width="800">
  212. <my-process-viewer
  213. key="designer"
  214. v-model="bpmnXML"
  215. :value="bpmnXML"
  216. v-bind="bpmnControlForm"
  217. :prefix="bpmnControlForm.prefix"
  218. />
  219. </Dialog>
  220. </template>
  221. <script setup lang="ts" name="Form">
  222. import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
  223. import { dateFormatter, formatDate } from '@/utils/formatTime'
  224. import * as ModelApi from '@/api/bpm/model'
  225. import * as FormApi from '@/api/bpm/form'
  226. import ModelForm from './ModelForm.vue'
  227. import ModelImportForm from '@/views/bpm/model/ModelImportForm.vue'
  228. import { setConfAndFields2 } from '@/utils/formCreate'
  229. const message = useMessage() // 消息弹窗
  230. const { t } = useI18n() // 国际化
  231. const { push } = useRouter() // 路由
  232. const loading = ref(true) // 列表的加载中
  233. const total = ref(0) // 列表的总页数
  234. const list = ref([]) // 列表的数据
  235. const queryParams = reactive({
  236. pageNo: 1,
  237. pageSize: 10,
  238. key: undefined,
  239. name: undefined,
  240. category: undefined
  241. })
  242. const queryFormRef = ref() // 搜索的表单
  243. /** 查询列表 */
  244. const getList = async () => {
  245. loading.value = true
  246. try {
  247. const data = await ModelApi.getModelPage(queryParams)
  248. list.value = data.list
  249. total.value = data.total
  250. } finally {
  251. loading.value = false
  252. }
  253. }
  254. /** 搜索按钮操作 */
  255. const handleQuery = () => {
  256. queryParams.pageNo = 1
  257. getList()
  258. }
  259. /** 重置按钮操作 */
  260. const resetQuery = () => {
  261. queryFormRef.value.resetFields()
  262. handleQuery()
  263. }
  264. /** 添加/修改操作 */
  265. const formRef = ref()
  266. const openForm = (type: string, id?: number) => {
  267. formRef.value.open(type, id)
  268. }
  269. /** 添加/修改操作 */
  270. const importFormRef = ref()
  271. const openImportForm = () => {
  272. importFormRef.value.open()
  273. }
  274. /** 删除按钮操作 */
  275. const handleDelete = async (id: number) => {
  276. try {
  277. // 删除的二次确认
  278. await message.delConfirm()
  279. // 发起删除
  280. await ModelApi.deleteModel(id)
  281. message.success(t('common.delSuccess'))
  282. // 刷新列表
  283. await getList()
  284. } catch {}
  285. }
  286. /** 更新状态操作 */
  287. const handleChangeState = async (row) => {
  288. const state = row.processDefinition.suspensionState
  289. try {
  290. // 修改状态的二次确认
  291. const id = row.id
  292. const statusState = state === 1 ? '激活' : '挂起'
  293. const content = '是否确认' + statusState + '流程名字为"' + row.name + '"的数据项?'
  294. await message.confirm(content)
  295. // 发起修改状态
  296. await ModelApi.updateModelState(id, state)
  297. // 刷新列表
  298. await getList()
  299. } catch {
  300. // 取消后,进行恢复按钮
  301. row.processDefinition.suspensionState = state === 1 ? 2 : 1
  302. }
  303. }
  304. /** 设计流程 */
  305. const handleDesign = (row) => {
  306. push({
  307. name: 'modelEditor',
  308. query: {
  309. modelId: row.id
  310. }
  311. })
  312. }
  313. /** 发布流程 */
  314. const handleDeploy = async (row) => {
  315. try {
  316. // 删除的二次确认
  317. await message.confirm('是否部署该流程!!')
  318. // 发起部署
  319. await ModelApi.deployModel(row.id)
  320. message.success(t('部署成功'))
  321. // 刷新列表
  322. await getList()
  323. } catch {}
  324. }
  325. /** 点击任务分配按钮 */
  326. const handleAssignRule = (row) => {
  327. push({
  328. name: 'BpmTaskAssignRuleList',
  329. query: {
  330. modelId: row.id
  331. }
  332. })
  333. }
  334. /** 跳转到指定流程定义列表 */
  335. const handleDefinitionList = (row) => {
  336. push({
  337. name: 'BpmProcessDefinitionList',
  338. query: {
  339. key: row.key
  340. }
  341. })
  342. }
  343. /** 流程表单的详情按钮操作 */
  344. const formDetailVisible = ref(false)
  345. const formDetailPreview = ref({
  346. rule: [],
  347. option: {}
  348. })
  349. const handleFormDetail = async (row) => {
  350. if (row.formType == 10) {
  351. // 设置表单
  352. const data = await FormApi.getForm(row.formId)
  353. setConfAndFields2(formDetailPreview, data.conf, data.fields)
  354. // 弹窗打开
  355. formDetailVisible.value = true
  356. } else {
  357. await push({
  358. path: row.formCustomCreatePath
  359. })
  360. }
  361. }
  362. /** 流程图的详情按钮操作 */
  363. const bpmnDetailVisible = ref(false)
  364. const bpmnXML = ref(null)
  365. const bpmnControlForm = ref({
  366. prefix: 'flowable'
  367. })
  368. const handleBpmnDetail = async (row) => {
  369. const data = await ModelApi.getModel(row.id)
  370. bpmnXML.value = data.bpmnXml || ''
  371. bpmnDetailVisible.value = true
  372. }
  373. /** 初始化 **/
  374. onMounted(() => {
  375. getList()
  376. })
  377. </script>