ElementMultiInstance.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. <template>
  2. <div class="panel-tab__content">
  3. <el-radio-group v-model="approveMethod" @change="onApproveMethodChange">
  4. <div class="flex-col">
  5. <div v-for="(item, index) in APPROVE_METHODS" :key="index">
  6. <el-radio :value="item.value" :label="item.value">
  7. {{ item.label }}
  8. </el-radio>
  9. <el-form-item prop="approveRatio">
  10. <el-input-number
  11. v-model="approveRatio"
  12. :min="10"
  13. :max="100"
  14. :step="10"
  15. size="small"
  16. v-if="
  17. item.value === ApproveMethodType.APPROVE_BY_RATIO &&
  18. approveMethod === ApproveMethodType.APPROVE_BY_RATIO
  19. "
  20. @change="onApproveRatioChange"
  21. />
  22. </el-form-item>
  23. </div>
  24. </div>
  25. </el-radio-group>
  26. <!-- 与Simple设计器配置合并,保留以前的代码 -->
  27. <el-form label-width="90px" style="display: none">
  28. <el-form-item label="快捷配置">
  29. <el-button size="small" @click="changeConfig('依次审批')">依次审批</el-button>
  30. <el-button size="small" @click="changeConfig('会签')">会签</el-button>
  31. <el-button size="small" @click="changeConfig('或签')">或签</el-button>
  32. </el-form-item>
  33. <el-form-item label="会签类型">
  34. <el-select v-model="loopCharacteristics" @change="changeLoopCharacteristicsType">
  35. <el-option label="并行多重事件" value="ParallelMultiInstance" />
  36. <el-option label="时序多重事件" value="SequentialMultiInstance" />
  37. <el-option label="无" value="Null" />
  38. </el-select>
  39. </el-form-item>
  40. <template
  41. v-if="
  42. loopCharacteristics === 'ParallelMultiInstance' ||
  43. loopCharacteristics === 'SequentialMultiInstance'
  44. "
  45. >
  46. <el-form-item label="循环数量" key="loopCardinality">
  47. <el-input
  48. v-model="loopInstanceForm.loopCardinality"
  49. clearable
  50. @change="updateLoopCardinality"
  51. />
  52. </el-form-item>
  53. <el-form-item label="集合" key="collection" v-show="false">
  54. <el-input v-model="loopInstanceForm.collection" clearable @change="updateLoopBase" />
  55. </el-form-item>
  56. <!-- add by 芋艿:由于「元素变量」暂时用不到,所以这里 display 为 none -->
  57. <el-form-item label="元素变量" key="elementVariable" style="display: none">
  58. <el-input v-model="loopInstanceForm.elementVariable" clearable @change="updateLoopBase" />
  59. </el-form-item>
  60. <el-form-item label="完成条件" key="completionCondition">
  61. <el-input
  62. v-model="loopInstanceForm.completionCondition"
  63. clearable
  64. @change="updateLoopCondition"
  65. />
  66. </el-form-item>
  67. <!-- add by 芋艿:由于「异步状态」暂时用不到,所以这里 display 为 none -->
  68. <el-form-item label="异步状态" key="async" style="display: none">
  69. <el-checkbox
  70. v-model="loopInstanceForm.asyncBefore"
  71. label="异步前"
  72. value="异步前"
  73. @change="updateLoopAsync('asyncBefore')"
  74. />
  75. <el-checkbox
  76. v-model="loopInstanceForm.asyncAfter"
  77. label="异步后"
  78. value="异步后"
  79. @change="updateLoopAsync('asyncAfter')"
  80. />
  81. <el-checkbox
  82. v-model="loopInstanceForm.exclusive"
  83. v-if="loopInstanceForm.asyncAfter || loopInstanceForm.asyncBefore"
  84. label="排除"
  85. value="排除"
  86. @change="updateLoopAsync('exclusive')"
  87. />
  88. </el-form-item>
  89. <el-form-item
  90. label="重试周期"
  91. prop="timeCycle"
  92. v-if="loopInstanceForm.asyncAfter || loopInstanceForm.asyncBefore"
  93. key="timeCycle"
  94. >
  95. <el-input v-model="loopInstanceForm.timeCycle" clearable @change="updateLoopTimeCycle" />
  96. </el-form-item>
  97. </template>
  98. </el-form>
  99. </div>
  100. </template>
  101. <script lang="ts" setup>
  102. import { ApproveMethodType, APPROVE_METHODS } from '@/components/SimpleProcessDesignerV2/src/consts'
  103. defineOptions({ name: 'ElementMultiInstance' })
  104. const props = defineProps({
  105. businessObject: Object,
  106. type: String,
  107. id: String
  108. })
  109. const prefix = inject('prefix')
  110. const loopCharacteristics = ref('')
  111. //默认配置,用来覆盖原始不存在的选项,避免报错
  112. const defaultLoopInstanceForm = ref({
  113. completionCondition: '',
  114. loopCardinality: '',
  115. extensionElements: [],
  116. asyncAfter: false,
  117. asyncBefore: false,
  118. exclusive: false
  119. })
  120. const loopInstanceForm = ref<any>({})
  121. const bpmnElement = ref(null)
  122. const multiLoopInstance = ref(null)
  123. const bpmnInstances = () => (window as any)?.bpmnInstances
  124. const getElementLoop = (businessObject) => {
  125. if (!businessObject.loopCharacteristics) {
  126. loopCharacteristics.value = 'Null'
  127. loopInstanceForm.value = {}
  128. return
  129. }
  130. if (businessObject.loopCharacteristics.$type === 'bpmn:StandardLoopCharacteristics') {
  131. loopCharacteristics.value = 'StandardLoop'
  132. loopInstanceForm.value = {}
  133. return
  134. }
  135. if (businessObject.loopCharacteristics.isSequential) {
  136. loopCharacteristics.value = 'SequentialMultiInstance'
  137. } else {
  138. loopCharacteristics.value = 'ParallelMultiInstance'
  139. }
  140. // 合并配置
  141. loopInstanceForm.value = {
  142. ...defaultLoopInstanceForm.value,
  143. ...businessObject.loopCharacteristics,
  144. completionCondition: businessObject.loopCharacteristics?.completionCondition?.body ?? '',
  145. loopCardinality: businessObject.loopCharacteristics?.loopCardinality?.body ?? ''
  146. }
  147. // 保留当前元素 businessObject 上的 loopCharacteristics 实例
  148. multiLoopInstance.value = bpmnInstances().bpmnElement.businessObject.loopCharacteristics
  149. // 更新表单
  150. if (
  151. businessObject.loopCharacteristics.extensionElements &&
  152. businessObject.loopCharacteristics.extensionElements.values &&
  153. businessObject.loopCharacteristics.extensionElements.values.length
  154. ) {
  155. loopInstanceForm.value['timeCycle'] =
  156. businessObject.loopCharacteristics.extensionElements.values[0].body
  157. }
  158. }
  159. const changeLoopCharacteristicsType = (type) => {
  160. // this.loopInstanceForm = { ...this.defaultLoopInstanceForm }; // 切换类型取消原表单配置
  161. // 取消多实例配置
  162. if (type === 'Null') {
  163. bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
  164. loopCharacteristics: null
  165. })
  166. return
  167. }
  168. // 配置循环
  169. if (type === 'StandardLoop') {
  170. const loopCharacteristicsObject = bpmnInstances().moddle.create(
  171. 'bpmn:StandardLoopCharacteristics'
  172. )
  173. bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
  174. loopCharacteristics: loopCharacteristicsObject
  175. })
  176. multiLoopInstance.value = null
  177. return
  178. }
  179. // 时序
  180. if (type === 'SequentialMultiInstance') {
  181. multiLoopInstance.value = bpmnInstances().moddle.create(
  182. 'bpmn:MultiInstanceLoopCharacteristics',
  183. { isSequential: true }
  184. )
  185. } else {
  186. multiLoopInstance.value = bpmnInstances().moddle.create(
  187. 'bpmn:MultiInstanceLoopCharacteristics',
  188. { collection: '${coll_userList}' }
  189. )
  190. }
  191. bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
  192. loopCharacteristics: toRaw(multiLoopInstance.value)
  193. })
  194. }
  195. // 循环基数
  196. const updateLoopCardinality = (cardinality) => {
  197. let loopCardinality = null
  198. if (cardinality && cardinality.length) {
  199. loopCardinality = bpmnInstances().moddle.create('bpmn:FormalExpression', {
  200. body: cardinality
  201. })
  202. }
  203. bpmnInstances().modeling.updateModdleProperties(
  204. toRaw(bpmnElement.value),
  205. multiLoopInstance.value,
  206. {
  207. loopCardinality
  208. }
  209. )
  210. }
  211. // 完成条件
  212. const updateLoopCondition = (condition) => {
  213. let completionCondition = null
  214. if (condition && condition.length) {
  215. completionCondition = bpmnInstances().moddle.create('bpmn:FormalExpression', {
  216. body: condition
  217. })
  218. }
  219. bpmnInstances().modeling.updateModdleProperties(
  220. toRaw(bpmnElement.value),
  221. multiLoopInstance.value,
  222. {
  223. completionCondition
  224. }
  225. )
  226. }
  227. // 重试周期
  228. const updateLoopTimeCycle = (timeCycle) => {
  229. const extensionElements = bpmnInstances().moddle.create('bpmn:ExtensionElements', {
  230. values: [
  231. bpmnInstances().moddle.create(`${prefix}:FailedJobRetryTimeCycle`, {
  232. body: timeCycle
  233. })
  234. ]
  235. })
  236. bpmnInstances().modeling.updateModdleProperties(
  237. toRaw(bpmnElement.value),
  238. multiLoopInstance.value,
  239. {
  240. extensionElements
  241. }
  242. )
  243. }
  244. // 直接更新的基础信息
  245. const updateLoopBase = () => {
  246. bpmnInstances().modeling.updateModdleProperties(
  247. toRaw(bpmnElement.value),
  248. multiLoopInstance.value,
  249. {
  250. collection: loopInstanceForm.value.collection || null,
  251. elementVariable: loopInstanceForm.value.elementVariable || null
  252. }
  253. )
  254. }
  255. // 各异步状态
  256. const updateLoopAsync = (key) => {
  257. const { asyncBefore, asyncAfter } = loopInstanceForm.value
  258. let asyncAttr = Object.create(null)
  259. if (!asyncBefore && !asyncAfter) {
  260. // this.$set(this.loopInstanceForm, "exclusive", false);
  261. loopInstanceForm.value['exclusive'] = false
  262. asyncAttr = { asyncBefore: false, asyncAfter: false, exclusive: false, extensionElements: null }
  263. } else {
  264. asyncAttr[key] = loopInstanceForm.value[key]
  265. }
  266. bpmnInstances().modeling.updateModdleProperties(
  267. toRaw(bpmnElement.value),
  268. multiLoopInstance.value,
  269. asyncAttr
  270. )
  271. }
  272. const changeConfig = (config) => {
  273. if (config === '依次审批') {
  274. changeLoopCharacteristicsType('SequentialMultiInstance')
  275. updateLoopCardinality('1')
  276. updateLoopCondition('${ nrOfCompletedInstances >= nrOfInstances }')
  277. } else if (config === '会签') {
  278. changeLoopCharacteristicsType('ParallelMultiInstance')
  279. updateLoopCondition('${ nrOfCompletedInstances >= nrOfInstances }')
  280. } else if (config === '或签') {
  281. changeLoopCharacteristicsType('ParallelMultiInstance')
  282. updateLoopCondition('${ nrOfCompletedInstances > 0 }')
  283. }
  284. }
  285. /**
  286. * -----新版本多实例-----
  287. */
  288. const approveMethod = ref()
  289. const approveRatio = ref(100)
  290. const otherExtensions = ref()
  291. const getElementLoopNew = () => {
  292. const extensionElements =
  293. bpmnElement.value.businessObject?.extensionElements ??
  294. bpmnInstances().moddle.create('bpmn:ExtensionElements', { values: [] })
  295. approveMethod.value = extensionElements.values.filter(
  296. (ex) => ex.$type === `${prefix}:ApproveMethod`
  297. )?.[0]?.value
  298. otherExtensions.value =
  299. extensionElements.values.filter((ex) => ex.$type !== `${prefix}:ApproveMethod`) ?? []
  300. if (!approveMethod.value) {
  301. approveMethod.value = ApproveMethodType.SEQUENTIAL_APPROVE
  302. updateLoopCharacteristics()
  303. }
  304. }
  305. const onApproveMethodChange = () => {
  306. approveRatio.value = 100
  307. updateLoopCharacteristics()
  308. }
  309. const onApproveRatioChange = () => {
  310. updateLoopCharacteristics()
  311. }
  312. const updateLoopCharacteristics = () => {
  313. // 根据ApproveMethod生成multiInstanceLoopCharacteristics节点
  314. if (approveMethod.value === ApproveMethodType.RANDOM_SELECT_ONE_APPROVE) {
  315. bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
  316. loopCharacteristics: null
  317. })
  318. } else {
  319. if (approveMethod.value === ApproveMethodType.APPROVE_BY_RATIO) {
  320. multiLoopInstance.value = bpmnInstances().moddle.create(
  321. 'bpmn:MultiInstanceLoopCharacteristics',
  322. { isSequential: false, collection: '${coll_userList}' }
  323. )
  324. multiLoopInstance.value.completionCondition = bpmnInstances().moddle.create(
  325. 'bpmn:FormalExpression',
  326. {
  327. body: '${ nrOfCompletedInstances/nrOfInstances >= ' + approveRatio.value / 100 + '}'
  328. }
  329. )
  330. }
  331. if (approveMethod.value === ApproveMethodType.ANY_APPROVE) {
  332. multiLoopInstance.value = bpmnInstances().moddle.create(
  333. 'bpmn:MultiInstanceLoopCharacteristics',
  334. { isSequential: false, collection: '${coll_userList}' }
  335. )
  336. multiLoopInstance.value.completionCondition = bpmnInstances().moddle.create(
  337. 'bpmn:FormalExpression',
  338. {
  339. body: '${ nrOfCompletedInstances > 0 }'
  340. }
  341. )
  342. }
  343. if (approveMethod.value === ApproveMethodType.SEQUENTIAL_APPROVE) {
  344. multiLoopInstance.value = bpmnInstances().moddle.create(
  345. 'bpmn:MultiInstanceLoopCharacteristics',
  346. { isSequential: true, collection: '${coll_userList}' }
  347. )
  348. multiLoopInstance.value.loopCardinality = bpmnInstances().moddle.create(
  349. 'bpmn:FormalExpression',
  350. {
  351. body: '1'
  352. }
  353. )
  354. multiLoopInstance.value.completionCondition = bpmnInstances().moddle.create(
  355. 'bpmn:FormalExpression',
  356. {
  357. body: '${ nrOfCompletedInstances >= nrOfInstances }'
  358. }
  359. )
  360. }
  361. bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
  362. loopCharacteristics: toRaw(multiLoopInstance.value)
  363. })
  364. }
  365. // 添加ApproveMethod到ExtensionElements
  366. const extensions = bpmnInstances().moddle.create('bpmn:ExtensionElements', {
  367. values: [
  368. ...otherExtensions.value,
  369. bpmnInstances().moddle.create(`${prefix}:ApproveMethod`, {
  370. value: approveMethod.value
  371. })
  372. ]
  373. })
  374. bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
  375. extensionElements: extensions
  376. })
  377. }
  378. onBeforeUnmount(() => {
  379. multiLoopInstance.value = null
  380. bpmnElement.value = null
  381. })
  382. watch(
  383. () => props.id,
  384. (val) => {
  385. if (val) {
  386. nextTick(() => {
  387. bpmnElement.value = bpmnInstances().bpmnElement
  388. // getElementLoop(val)
  389. getElementLoopNew()
  390. })
  391. }
  392. },
  393. { immediate: true }
  394. )
  395. </script>