fireFlowTask.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /**
  2. * 动火作业票流程环节的运行时辅助
  3. *
  4. * 职责:
  5. * 1) 取流程实例当前待办任务的信息(任务定义 key + 任务名称)
  6. * —— 任务定义 key 由流程设计器决定,与源系统(HO_PERMIT_FIRE_*)不同,
  7. * 环节识别需要同时参考任务名称。
  8. * 2) 按节点 schema 从数据源取值(回显)
  9. * 3) 环节内容写入流程实例表单变量(合并写入,保留作业票原有字段)
  10. * 4) 生成随审批提交的流程变量(字符串化,兼容流程变量类型限制)
  11. */
  12. import { getTaskListByProcessInstanceId } from '@/api/bpm/task';
  13. import { getProcessInstance } from '@/api/bpm/processInstance';
  14. import { getFieldKeys } from './fireFlowNodes';
  15. /**
  16. * 取流程实例当前待办任务的信息
  17. * @param {string} processInstanceId 流程实例 id
  18. * @param {string} taskDefinitionKey 当前任务定义 key(用于精确匹配)
  19. * @returns {Promise<{name: string, taskDefinitionKey: string, result: number}>}
  20. */
  21. export async function getCurrentTaskInfo(processInstanceId, taskDefinitionKey) {
  22. const empty = { name: '', taskDefinitionKey: '', result: 0 };
  23. if (!processInstanceId) {
  24. return empty;
  25. }
  26. try {
  27. const list = await getTaskListByProcessInstanceId(processInstanceId);
  28. const tasks = Array.isArray(list) ? list : [];
  29. if (!tasks.length) {
  30. return empty;
  31. }
  32. const matched = taskDefinitionKey
  33. ? tasks.find((task) => task.taskDefinitionKey === taskDefinitionKey)
  34. : null;
  35. // 待处理中的任务:result 1-待处理、6-处理中
  36. const pending = tasks.find((task) => task.result == 1 || task.result == 6);
  37. const task = matched || pending || tasks[0];
  38. return {
  39. name: task.name || '',
  40. taskDefinitionKey: task.taskDefinitionKey || '',
  41. result: task.result
  42. };
  43. } catch (e) {
  44. return empty;
  45. }
  46. }
  47. /**
  48. * 读流程实例表单变量
  49. * @returns {Promise<{loaded: boolean, vars: object}>} loaded=false 表示读取失败(不可合并写入)
  50. */
  51. export async function loadProcessFormVariables(processInstanceId) {
  52. if (!processInstanceId) {
  53. return { loaded: false, vars: {} };
  54. }
  55. try {
  56. const instance = await getProcessInstance(processInstanceId);
  57. return {
  58. loaded: true,
  59. vars: parseJsonObject(instance && instance.formVariables)
  60. };
  61. } catch (e) {
  62. return { loaded: false, vars: {} };
  63. }
  64. }
  65. /**
  66. * 合并作业票内容(extensionJson)与环节数据
  67. * @param {object} extension 作业票现有内容
  68. * @param {object} payload 环节字段值
  69. * @returns {object} 合并后的作业票内容
  70. */
  71. export function mergeExtension(extension, payload) {
  72. return { ...(extension || {}), ...(payload || {}) };
  73. }
  74. /**
  75. * 组装作业票修改参数(后端「危险作业票修改请求」契约)
  76. * - 扩展数据字段名是 extensionJson,且要求 JSON 字符串
  77. * - 不接收 workId(所属危险作业不可变更)
  78. * - status 不传则不修改
  79. * - 取不到的字段直接剔除,避免后端把未取到的值置空
  80. * @param {object} ticket 作业票详情
  81. * @param {object} extension 合并后的作业票内容
  82. * @param {string|number} fallbackId 作业票 id(详情未返回时兜底)
  83. * @returns {object} 修改参数
  84. */
  85. export function buildTicketUpdateParams(ticket, extension, fallbackId) {
  86. const t = ticket || {};
  87. const params = {
  88. id: t.id !== undefined && t.id !== null ? t.id : fallbackId,
  89. workType:
  90. t.workType === undefined || t.workType === null || t.workType === ''
  91. ? undefined
  92. : String(t.workType),
  93. applyDeptId: t.applyDeptId,
  94. applyDeptName: t.applyDeptName,
  95. applicantId: t.applicantId,
  96. applicantName: t.applicantName,
  97. workLocation: t.workLocation,
  98. startTime: t.startTime,
  99. endTime: t.endTime,
  100. extensionJson: JSON.stringify(extension || {})
  101. };
  102. Object.keys(params).forEach((key) => {
  103. if (params[key] === undefined) {
  104. delete params[key];
  105. }
  106. });
  107. return params;
  108. }
  109. /**
  110. * 按节点 schema 从数据源中取值(回显)
  111. * @param {object} node 节点定义
  112. * @param {Array<object>} sources 数据源,按优先级从高到低
  113. * @returns {object} { [field.key]: value }
  114. */
  115. export function loadNodeValues(node, sources) {
  116. const values = {};
  117. (node?.fields || []).forEach((field) => {
  118. let value;
  119. const keys = getFieldKeys(field);
  120. for (const source of sources || []) {
  121. for (const key of keys) {
  122. const item = source && source[key];
  123. if (item !== undefined && item !== null && item !== '') {
  124. value = item;
  125. break;
  126. }
  127. }
  128. if (value !== undefined) {
  129. break;
  130. }
  131. }
  132. values[field.key] = value;
  133. });
  134. return values;
  135. }
  136. /**
  137. * 环节内容转成流程变量(字符串化,兼容流程变量的类型限制)
  138. * @param {object} node 节点定义
  139. * @param {object} values 环节字段值
  140. * @returns {object} 流程变量
  141. */
  142. export function buildNodeVariables(node, values) {
  143. const vars = {};
  144. (node?.fields || []).forEach((field) => {
  145. const value = values ? values[field.key] : undefined;
  146. if (value === undefined || value === null || value === '') {
  147. return;
  148. }
  149. if (field.type === 'table') {
  150. if (!Array.isArray(value) || !value.length) {
  151. return;
  152. }
  153. vars[field.key] = JSON.stringify(value);
  154. return;
  155. }
  156. if (Array.isArray(value)) {
  157. if (!value.length) {
  158. return;
  159. }
  160. vars[field.key] = value.join(',');
  161. return;
  162. }
  163. vars[field.key] = String(value);
  164. });
  165. return vars;
  166. }
  167. /**
  168. * 环节内容(保留原始类型,便于详情页按数组/对象回显)
  169. * @param {object} node 节点定义
  170. * @param {object} values 环节字段值
  171. * @returns {object}
  172. */
  173. export function buildNodePayload(node, values) {
  174. const payload = {};
  175. (node?.fields || []).forEach((field) => {
  176. const value = values ? values[field.key] : undefined;
  177. if (value === undefined || value === null || value === '') {
  178. return;
  179. }
  180. if (Array.isArray(value) && !value.length) {
  181. return;
  182. }
  183. payload[field.key] = value;
  184. });
  185. return payload;
  186. }
  187. /**
  188. * 解析 JSON 对象(字符串或对象)
  189. */
  190. export function parseJsonObject(raw) {
  191. if (!raw) {
  192. return {};
  193. }
  194. if (typeof raw === 'object') {
  195. return Array.isArray(raw) ? {} : { ...raw };
  196. }
  197. try {
  198. const data = JSON.parse(raw);
  199. return data && typeof data === 'object' && !Array.isArray(data) ? data : {};
  200. } catch (e) {
  201. return {};
  202. }
  203. }