var express = require('express'); var router = express.Router(); var doSQL = require('../mysql/index').doSQL; const axios = require('axios'); const { createProxyMiddleware, responseInterceptor } = require('http-proxy-middleware'); const fs = require("fs"); var path = require("path"); var config = require('../config'); const baseURL = config.camunda.base; //1.获取最新流程定义列表 router.get('/engine-rest/process-definition', function(request, response) { //查询流程总数量 axios.get(baseURL + '/engine-rest/process-definition/count?latestVersion=true').then(res=>{ let count = res.data.count; doRequest(request).then(data=>{ response.send({ code: 200, data: { list: data, total: count } }); }).catch(err=>{ response.send(JSON.stringify({ code: 600, message: err })); }) }) }); //2.获取流程实例列表 router.get('/engine-rest/history/process-instance', function(request, response) { let processDefinitionKey = request.query.processDefinitionKey; let finished = request.query.finished; //查询实例总数量 axios.get(baseURL + `/engine-rest/history/process-instance/count`,{ params: { processDefinitionKey, finished } }).then(res=>{ let count = res.data.count; doRequest(request).then(data=>{ response.send({ code: 200, data: { list: data, total: count } }); }).catch(err=>{ response.send(JSON.stringify({ code: 600, message: err })); }) }) }); //3.获取流程实例任务列表 router.get('/engine-rest/history/task', function(request, response) { let processInstanceId = request.query.processInstanceId; //查询实例任务总数量 axios.get(baseURL + `/engine-rest/history/task/count?processInstanceId=${processInstanceId}`).then(res=>{ let count = res.data.count; doRequest(request).then(data=>{ //如果任务已完成,获取任务评论 let promiseArr = []; data.forEach(item=> { promiseArr.push(axios.get(baseURL + `/engine-rest/task/${item.id}/comment`)) }) Promise.all(promiseArr).then(res=>{ res.forEach((item,index)=> { data[index].comment = item.data; }) response.send({ code: 200, data: { list: data, total: count } }); }) }).catch(err=>{ response.send(JSON.stringify({ code: 600, message: err })); }) }) }); //4.添加候选人 router.post('/engine-rest/task/:taskId/identity-links', function(request, response) { doRequest(request).then(data=>{ response.send({ code: 200 }); }).catch(err=>{ response.send(JSON.stringify({ code: 600, message: err })); }) }); //5.移除候选人 router.post('/engine-rest/task/:taskId/identity-links/delete', function(request, response) { doRequest(request).then(data=>{ response.send({ code: 200 }); }).catch(err=>{ response.send(JSON.stringify({ code: 600, message: err })); }) }); function getProcessInstanceDetail(taskInfo,id) { return new Promise((resolve, reject) => { const query = ` SELECT wi.form_id, wi.process_key, wi.form_values, wi.process_instance_id, wi.status, wf.form_name, wf.form_desc, wf.form_path FROM workflow_instance wi LEFT JOIN workflow_form wf ON wf.id = wi.form_id WHERE process_instance_id = ? `; const params = [id]; doSQL(query, params).then(res=>{ let data = res.data[0]; axios.get(baseURL + `/engine-rest/process-definition/${taskInfo.processDefinitionId}`) .then(res=>{ let processInfo = res.data; if(data){ try { let form = require(path.join(__dirname, '../' + data.form_path)); resolve({ processName: processInfo.name, ...taskInfo, ...data, form: form.formFields }) } catch (error) { resolve({ processName: processInfo.name, ...taskInfo, ...data }) } // fs.readFile(path.join(__dirname, '../' + data.form_path), 'utf-8', function(err, form) { // if (err) { // resolve({ // processName: processInfo.name, // ...taskInfo, // ...data // }) // } else { // resolve({ // processName: processInfo.name, // ...taskInfo, // ...data, // form: JSON.parse(form) // }) // } // }); } else { resolve({ processName: processInfo.name, ...taskInfo }) } }) .catch(error => { // 处理 axios 错误 resolve({ ...taskInfo }) }); }).catch(error => { // 处理 doSQL 错误 reject(error); }); }); } //6.查询候选任务 router.get('/engine-rest/task', async function(request, response) { let candidateUser = request.query.candidateUser; let assignee = request.query.assignee; let candidateGroup = request.query.candidateGroup; try { let count = 0; let primiseArr = []; if(!candidateUser && !assignee && !candidateGroup){ res = await axios.get(baseURL + '/engine-rest/task/count'); count = res.data.count; const data = await doRequest(request); // 按照 created 字段倒序排序 data.sort((a, b) => new Date(b.created) - new Date(a.created)); data.forEach(item => { primiseArr.push(getProcessInstanceDetail(item, item.processInstanceId)); }); }else{ // 如果传入了参数,分别查询 let requests = []; if (candidateUser) { requests.push(axios.get(baseURL + '/engine-rest/task', { params: { candidateUser: candidateUser } })); } if (assignee) { requests.push(axios.get(baseURL + '/engine-rest/task', { params: { assignee: assignee } })); } if (candidateGroup) { requests.push(axios.get(baseURL + '/engine-rest/task', { params: { candidateGroup: candidateGroup } })); } // 等待所有请求完成 const responses = await Promise.all(requests); // 合并所有请求的结果 let tasks = []; responses.forEach(response => { tasks = tasks.concat(response.data); }); // 去重 const uniqueTasks = tasks.filter((task, index, self) => index === self.findIndex((t) => ( t.id === task.id )) ); // 按照 created 字段倒序排序 uniqueTasks.sort((a, b) => new Date(b.created) - new Date(a.created)); // 分页处理 let firstResult = request.query.firstResult || 0; let maxResults = request.query.maxResults || 10; const paginatedTasks = uniqueTasks.slice(firstResult, firstResult + maxResults); // 获取任务总数 count = uniqueTasks.length; // 获取任务详情 paginatedTasks.forEach(item => { primiseArr.push(getProcessInstanceDetail(item, item.processInstanceId)); }); } const results = await Promise.all(primiseArr); response.send({ code: 200, data: { list: results, total: count } }); } catch (err) { console.error('Error:', err); response.send({ code: 600, message: err.message || '处理请求时发生错误' }); } }); //7.领取任务 router.post('/engine-rest/task/:taskId/claim', function(request, response) { doRequest(request).then(data=>{ response.send({ code: 200 }); }).catch(err=>{ response.send(JSON.stringify({ code: 600, message: err })); }) }); //8.取消执行人 router.post('/engine-rest/task/:taskId/unclaim', function(request, response) { doRequest(request).then(data=>{ response.send({ code: 200 }); }).catch(err=>{ response.send(JSON.stringify({ code: 600, message: err })); }) }); //9.执行任务 router.post('/engine-rest/task/:taskId/complete', function(request, response) { doRequest(request).then(data=>{ response.send({ code: 200 }); }).catch(err=>{ response.send(JSON.stringify({ code: 600, message: err })); }) }); //10.设置任务评论 router.post('/engine-rest/task/:taskId/comment/create', function(request, response) { doRequest(request).then(data=>{ response.send({ code: 200 }); }).catch(err=>{ response.send(JSON.stringify({ code: 600, message: err })); }) }); /** * 创建自定义流程实例 * @description 本系统内生成流程实例,并启动camunda流程--------标准需要开事务 * @ */ router.post('/start', function(request, response) { //1. 启动camunda流程 let processKey = request.body.processKey; let createUser = request.body.createUser; //1.本系统内生成流程实例 let formId = request.body.formId; let formValues = request.body.formValues; const query = ` INSERT INTO workflow_instance (form_id, process_key, process_instance_id, form_values, status, create_user) VALUES (?, ?, NULL, ?, 1, ?) `; const params = [formId, processKey, formValues, createUser]; doSQL(query,params).then(res=>{ if(!res.error){ //获取刚刚插入的id const insertId = res.data.insertId; axios.post(baseURL + `/engine-rest/process-definition/key/${processKey}/start`, { businessKey: insertId }).then(res=>{ let processInstanceId = res.data.id; if( processInstanceId ){ //2. 创建本系统内的流程实例包含form_id,process_instance_id,status const query = `UPDATE workflow_instance SET process_instance_id = ? WHERE id = ?`; const params = [processInstanceId, insertId]; doSQL(query, params).then(res=>{ if(!res.error){ response.send({ code: 200, message: '启动流程成功' }); }else{ const query = `delete from workflow_instance where id = ?`; const params = [insertId]; doSQL(query, params).then(res=>{ response.send({ code: 600, message: '启动流程失败' }); }) } }) }else { response.send({ code: 600, message: '启动流程失败' }); } }) }else{ response.send({ code: 600, message: '启动流程失败' }); } }) }); router.use('/', createProxyMiddleware({ target: baseURL, changeOrigin: true, // 确保请求头正确 pathRewrite: { '^/process': '', // 去掉路径前缀 }, timeout: 60000, // 设置超时为60秒 selfHandleResponse: true, on: { // proxyReq: (proxyReq, req, res) => { // console.log('代理请求发送到目标服务器:', proxyReq.path); // console.log('请求头:', proxyReq.getHeaders()); // }, proxyRes: responseInterceptor(async (responseBuffer, proxyRes, req, res) => { const response = responseBuffer.toString('utf8'); // convert buffer to string let originalData; try { originalData = response ? JSON.parse(response) : {}; // parse JSON } catch (error) { originalData = { code: 500, message: 'Error parsing response', data: response }; } //异常特殊处理 if(originalData?.message?.includes('ENGINE-03076')){ return JSON.stringify({ code: 503, msg: '流程存在启用的实例,无法删除!' }); }else{ let statusCode = proxyRes.statusCode == 204 ? 200 : proxyRes.statusCode; const wrappedData = { code: originalData.code || statusCode, // 包含 HTTP 状态码 data: originalData.data || originalData, // 返回的实际数据 timestamp: new Date().toISOString(), // 添加时间戳 }; return JSON.stringify(wrappedData); } }), error: (err, req, res) => { console.error('Proxy error:', err); res.status(500).json({ code: 500, message: 'Proxy request failed', error: err.message }); } }, })); // function proxyDataResolver(fn) { // return proxy(baseURL + '', { // proxyReqPathResolver: function (req) { // // 移除请求路径中的开头 /process // return req.url.replace(/^\/process/, ''); // }, // proxyReqOptDecorator: function(proxyReqOpts, req) { // // 确保请求头中包含正确的 Content-Type // if (req.headers['content-type']) { // proxyReqOpts.headers['Content-Type'] = req.headers['content-type']; // } // return proxyReqOpts; // }, // userResDecorator: function (proxyRes, proxyResData, req, res) { // try { // // 处理返回的结果 // const originalData = JSON.parse(proxyResData.toString('utf8')); // 解析 JSON // const wrappedData = { // code: originalData.code || proxyRes.statusCode, // 包含 HTTP 状态码 // data: fn ? fn(originalData) : (originalData.data || originalData), // 返回的实际数据 // timestamp: new Date().toISOString(), // 添加时间戳 // }; // return JSON.stringify(wrappedData); // 转换为字符串返回 // } catch (error) { // console.error('Error processing response:', error); // return proxyResData; // 如果解析失败,直接返回原始数据 // } // }, // }) // } function doRequest(req) { return new Promise((resolve, reject) => { // 构建请求选项 const url = baseURL + `${req.url.replace(/^\/process/, '')}`; axios({ url: url, method: req.method, data: req.body, }) .then(response => { resolve(response.data,response) }) .catch(error => { reject(error) }); }); } module.exports = router;