procinst-diagram.html 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. <!doctype html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  5. <title>流程图</title>
  6. <!--#include file="common/_header.html"-->
  7. <link rel="stylesheet" type="text/css" href="scripts/workflow/tipsy.css" />
  8. <link rel="stylesheet" type="text/css" href="lib/select2/select2.min.css" />
  9. <style>
  10. body {
  11. position: fixed;
  12. top: 0;
  13. bottom: 0;
  14. left: 0;
  15. right: 0;
  16. margin: 0;
  17. padding: 0;
  18. font-family:tahoma "microsoft yahei";
  19. }
  20. .live.map {
  21. width: 100%;
  22. height: 100%;
  23. }
  24. .live.map text {
  25. font-weight: 300;
  26. font-size: 14px;
  27. }
  28. .live.map .node rect {
  29. stroke-width: 1.5px;
  30. stroke: #bbb;
  31. fill: #666;
  32. }
  33. svg {
  34. width: 100%;
  35. height: 100%;
  36. overflow: hidden;
  37. }
  38. .live.map .status {
  39. height: 100%;
  40. width: 15px;
  41. display: block;
  42. float: left;
  43. border-top-left-radius: 5px;
  44. border-bottom-left-radius: 5px;
  45. margin-right: 4px;
  46. color:cornsilk;
  47. }
  48. .live.map .start .status {
  49. background-color: green;
  50. }
  51. .live.map .finish .status {
  52. background-color: green;
  53. }
  54. .live.map .running .status {
  55. background-color:blue;
  56. }
  57. .live.map .blank .status {
  58. background-color: white;
  59. }
  60. .live.map .ignore .status {
  61. background-color: #aaaaaa;
  62. }
  63. .live.map .end .status {
  64. background-color: red;
  65. }
  66. .live.map .node g div {
  67. width: 200px;
  68. height: 40px;
  69. color: #fff;
  70. }
  71. .live.map .userTask{
  72. cursor:pointer;
  73. }
  74. .live.map .taskName {
  75. display: inline-block;
  76. width: 200px;
  77. padding:2px;
  78. }
  79. .live.map .remark {
  80. display: block;
  81. float: left;
  82. width: 130px;
  83. height: 20px;
  84. font-size: 12px;
  85. margin-top: 2px;
  86. color:cornsilk;
  87. }
  88. .live.map .edgeLabel text {
  89. width: 50px;
  90. fill: #fff;
  91. }
  92. .live.map .edgePath path {
  93. stroke: #999;
  94. stroke-width: 1.5px;
  95. fill: #999;
  96. }
  97. .live.map .node g .gateway{
  98. width : 50px;
  99. height : 50px;
  100. border-radius: 100%;
  101. }
  102. .flex-container{
  103. display: flex;
  104. flex-direction: row;
  105. height:100%;
  106. width:100%;
  107. }
  108. #diagram{
  109. flex:1;
  110. }
  111. #propertyPanel{
  112. width:400px;
  113. border-left:1px dotted black;
  114. padding:5px;
  115. overflow:scroll;
  116. }
  117. .input-text{
  118. height:30px;
  119. border-radius: 4px;
  120. border: 1px solid #aaa;
  121. width:100%;
  122. }
  123. dt{
  124. font-weight: bold;
  125. height:30px;
  126. line-height:30px;
  127. }
  128. dd {
  129. margin-inline-start:0px;
  130. }
  131. </style>
  132. </head>
  133. <body>
  134. <div class="flex-container">
  135. <h5 id="tmplName" style="position:absolute;left:10px;top:10px;"></h5>
  136. <div id="diagram" class="live map">
  137. <svg style="width:100%;height:100%;"></svg>
  138. </div>
  139. </div>
  140. <script id="taskTmpl" type="text/html">
  141. <div id="task_{{id}}" class="userTask {{className}}">
  142. <span class="status"></span>
  143. <span class="taskName" id="{{id}}">{{name}}</span>
  144. <span class="remark">{{remark}}</span>
  145. </div>
  146. </script>
  147. <script id="gatewayTmpl" type="text/html">
  148. <p class="gateway"></p>
  149. </script>
  150. <!--#include file="common/_footer.html"-->
  151. <script type="text/javascript" src="scripts/workflow/d3.v3.min.js" charset="utf-8"></script>
  152. <script type="text/javascript" src="scripts/workflow/dagre-d3.min.js" ></script>
  153. <script type="text/javascript" src="scripts/workflow/tipsy.js" ></script>
  154. <script type="text/javascript" src="scripts/global.js"></script>
  155. <script type="text/javascript">
  156. var procInstId = getQueryString("procInstId");
  157. var procDefKey = getQueryString("procDefKey");
  158. </script>
  159. <script type="text/javascript">
  160. $(document).ready(function(){
  161. var loadingIndex = layer.load(0, {shade: false});
  162. $.get(
  163. global_backend_url + "/procDef/loadDiagram",
  164. {
  165. procDefKey : procDefKey
  166. }, function(rs){
  167. var data = rs.data;
  168. createDiagram(data);
  169. }, "json").then(function(){
  170. console.log("读取流程进度:" + procInstId);
  171. if(procInstId==null ||procInstId.length==0){
  172. layer.close(loadingIndex);
  173. layer.msg("流程未开启!");
  174. return;
  175. }
  176. $.get(
  177. global_backend_url + "/procInst/processProgress",
  178. {
  179. procInstId : procInstId
  180. }, function(resp){
  181. if(resp.result) {
  182. var data = resp.data;
  183. $("#tmplName").html("采用模板:" + data.template.title);
  184. //将已完成任务节点添加样式
  185. data.finishedTasks.forEach(function(task){
  186. $("#task_" + task.key).removeClass("blank");
  187. $("#task_" + task.key).addClass("finish");
  188. $(".remark","#task_" + task.key).html("已完成");
  189. var remark = [];
  190. remark.push("经办人:" + task.assignee);
  191. remark.push("完成时间:" + task.endTime);
  192. $("#task_" + task.key).attr("title", remark.join("\n"));
  193. });
  194. //将已忽略任务节点添加样式
  195. if(data.ignoreTasks!=null){
  196. data.ignoreTasks.forEach(function(task){
  197. $("#task_" + task.key).removeClass("blank");
  198. $("#task_" + task.key).removeClass("finish");
  199. $("#task_" + task.key).addClass("ignore");
  200. $(".remark","#task_" + task.key).html("自动忽略");
  201. });
  202. }
  203. //将正在进行的节点添加样式
  204. data.pendingTasks.forEach(function(task){
  205. $("#task_" + task.key).removeClass("blank");
  206. $("#task_" + task.key).addClass("running");
  207. $(".remark","#task_" + task.key).html("进行中");
  208. var remark = [];
  209. if(task.assignee!=null){
  210. remark.push("经办人:" + task.assignee);
  211. }
  212. else{
  213. remark.push("候选人:" + task.candidates);
  214. }
  215. $("#task_" + task.key).attr("title", remark.join("\n"));
  216. });
  217. layer.close(loadingIndex);
  218. }
  219. else{
  220. layer.close(loadingIndex);
  221. layer.msg("获取流程进度失败!" + resp.message);
  222. }
  223. }, "json");
  224. });
  225. });
  226. function createDiagram(data){
  227. // Create a new directed graph
  228. var g = new dagreD3.graphlib.Graph();
  229. g.setGraph({
  230. nodesep: 70,
  231. ranksep: 50,
  232. rankdir: "TB",
  233. marginx: 20,
  234. marginy: 20
  235. });
  236. //start
  237. for(var i=0;i<data.startNodeList.length;i++){
  238. var node = data.startNodeList[i];
  239. g.setNode(node.id, {
  240. labelType: "html",
  241. label:template("taskTmpl",{
  242. id:node.id,
  243. name:node.name,
  244. className:"start"
  245. }),
  246. rx: 5,
  247. ry: 5,
  248. padding: 0
  249. });
  250. }
  251. //end
  252. for(var i=0;i<data.endNodeList.length;i++){
  253. var node = data.endNodeList[i];
  254. g.setNode(node.id, {
  255. labelType: "html",
  256. label:template("taskTmpl",{
  257. id:node.id,
  258. name:node.name,
  259. className:"end"
  260. }),
  261. rx: 5,
  262. ry: 5,
  263. padding: 0
  264. });
  265. }
  266. //用户任务
  267. for(var i=0;i<data.taskList.length;i++){
  268. var task = data.taskList[i];
  269. g.setNode(task.id, {
  270. labelType: "html",
  271. label:template("taskTmpl",{
  272. id:task.id,
  273. name:task.name,
  274. className:"blank"
  275. }),
  276. rx: 5,
  277. ry: 5,
  278. padding: 1
  279. });
  280. }
  281. //独占网关
  282. for(var i=0;i<data.exclusiveGatewayList.length;i++){
  283. var gateway = data.exclusiveGatewayList[i];
  284. g.setNode(gateway.id, {
  285. shape: 'diamond',
  286. style: "fill: #fff; stroke: #000"
  287. });
  288. }
  289. //并行网关
  290. for(var i=0;i<data.parallelGatewayList.length;i++){
  291. var gateway = data.parallelGatewayList[i];
  292. g.setNode(gateway.id, {
  293. label:'',
  294. shape: 'diamond',
  295. style: "fill: #fff; stroke: #000"
  296. });
  297. }
  298. //连接线
  299. for(var i=0;i<data.seqFlowList.length;i++){
  300. var seqFlow = data.seqFlowList[i];
  301. g.setEdge(seqFlow.sourceRef, seqFlow.targetRef,{
  302. label: seqFlow.name
  303. });
  304. }
  305. // Create the renderer
  306. var render = new dagreD3.render();
  307. // Set up an SVG group so that we can translate the final graph.
  308. var svg = d3.select("svg"),
  309. inner = svg.append("g");
  310. // Set up zoom support
  311. var zoom = d3.behavior.zoom().on("zoom", function() {
  312. inner.attr("transform", "translate(" + d3.event.translate + ")" + "scale(" + d3.event.scale + ")");
  313. });
  314. svg.call(zoom);
  315. // Run the renderer. This is what draws the final graph.
  316. render(inner, g);
  317. // Zoom and scale to fit
  318. // Zoom and scale to fit
  319. var graphWidth = g.graph().width + 80;
  320. var graphHeight = g.graph().height + 40;
  321. var width = parseInt(svg.style("width").replace(/px/, ""));
  322. var height = parseInt(svg.style("height").replace(/px/, ""));
  323. var zoomScale = Math.min(width / graphWidth, height / graphHeight);
  324. // var zoomScale = 1;
  325. // var translate = [(width/2) - ((graphWidth*zoomScale)/2), (height/2) - ((graphHeight*zoomScale)/2)];
  326. var translate = [(width/2) - ((graphWidth*zoomScale)/2), 0];
  327. zoom.translate(translate);
  328. zoom.scale(zoomScale);
  329. zoom.event(svg);
  330. }
  331. </script>
  332. </body>
  333. </html>