In the previous work, we have built the workflow editing and viewing page, and now we add another function, which is to view the running results of the process after starting a workflow process.
First, we add a new page called processes.html, which is redirected from the definitions page. When clicking a certain workflow ID link on the definitions page, it will jump to this page to view the corresponding process of this workflow. The content of the page is as follows:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
<meta name="generator" content="Hugo 0.101.0">
<title>Workflow Processes</title>
<!-- Bootstrap core CSS -->
<link href="assets/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="vendor/datatables.net-bs4/assets/dataTables.bootstrap4.min.css">
<style>
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
@media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
</style>
<!-- Custom styles for this template -->
<link href="assets/workflow.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
<a class="navbar-brand col-md-3 col-lg-2 mr-0 px-3" href="#">工作流管理平台</a>
<button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-toggle="collapse" data-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<ul class="navbar-nav px-3">
<li class="nav-item text-nowrap">
<a class="nav-link" href="#">退出登录</a>
</li>
</ul>
</nav>
<div class="container-fluid d-flex h-75">
<div class="row flex-fill">
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
<div class="sidebar-sticky pt-3">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link active" href="workflow.html">
<i data-feather="home"></i>
编辑工作流
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="definitions.html">
<i data-feather="file"></i>
查看工作流
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<i data-feather="shopping-cart"></i>
编辑规则
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<i data-feather="users"></i>
查看规则
</a>
</li>
</ul>
</div>
</nav>
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">工作流进程列表</h1>
</div>
<div>
<img id="diagram", src="">
</div>
<div class="card shadow mb-4">
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>进程id</th>
<th>工作流名字</th>
<th>开始时间</th>
<th>结束时间</th>
<th>状态</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</main>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="instanceModal" tabindex="-1" data-backdrop="static" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">工作流进程变量</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="table-responsive">
<table class="table table-bordered" id="detailTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>参数名称</th>
<th>数值</th>
<th>创建时间</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<script src="assets/jquery/dist/jquery.slim.min.js"></script>
<script src="assets/bootstrap/dist/bootstrap.bundle.min.js"></script>
<script src="vendor/datatables.net-bs4/assets/jquery.dataTables.min.js"></script>
<script src="vendor/datatables.net-bs4/assets/dataTables.bootstrap4.min.js"></script>
<script src="processes.bundle.js"></script>
<script src="assets/feather-icons/dist/feather.min.js"></script>
<script>feather.replace()</script>
</body>
</html>
Lines 85-87 of this page define a container for placing the graphics of this workflow. Lines 88-105 define a container to place the datatable, which is used to display the list of processes related to this workflow. Lines 111-137 define a modal, which contains a datatable, which is used to display the detailed information of the variables of a certain process.
Then we define a processes.js file to query the relevant interface of camunda, and update the content to the corresponding container of processes.html, the content is as follows:
import axios from 'axios';
import Keycloak from 'keycloak-js';
import config from './config.json';
var token;
async function initKeycloak() {
const keycloak = new Keycloak();
console.log('set keycloak');
await keycloak.init({onLoad: 'login-required'});
return keycloak.token;
}
window.viewInstance = async function viewInstance(id) {
var res = await axios
.create({withCredentials: true})
.post(
config.baseurl+'/engine-rest/history/variable-instance',
{"processInstanceId": id},
{headers: {'Content-Type':'application/json', 'Authorization':'Bearer '+token}}
);
if (res.status==200) {
$('#detailTable').DataTable({
destroy: true,
searching: false,
paging: false,
data: res.data,
columns: [
{data: "name"},
{data: "value"},
{data: "createTime"}
]
});
$('#instanceModal').modal();
}
else {
alert("无法读取该进程的变量数据");
}
}
$(document).ready(async function () {
var str = window.location.search;
var definition_id = str.substring(4, str.length);
token = await initKeycloak();
axios.create({withCredentials: true}).get(
config.baseurl+'/engine-rest/process-definition/'+definition_id+'/diagram',
{headers: {'Authorization':'Bearer '+token}}
).then(
res=>{
var svgdata = 'data:image/svg+xml;base64,'+window.btoa(unescape(encodeURIComponent(res.data)));
$('#diagram').prop("src", svgdata);
}
);
axios.create({withCredentials: true}).get(
config.baseurl+'/engine-rest/history/process-instance?processDefinitionId='+definition_id,
{headers: {'Content-Type':'application/json', 'Authorization':'Bearer '+token}}
).then(
res=>{
console.log(res.data);
$('#dataTable').DataTable({
data: res.data,
columns: [
{
data: "id",
render: function(data) {
return '<a href="javascript:void(0);" onclick="viewInstance(\'' + data + '\')">' + data + '</a>';
}
},
{data: "processDefinitionName"},
{data: "startTime"},
{data: "endTime"},
{data: "state"}
]
});
}
);
});
Finally, run npm run build, and the effect is as follows:
view_process