吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2857|回复: 24
收起左侧

[Python 原创] Python 自研审批流引擎,可根据封装的审批引擎接口对接各类表单!!

  [复制链接]
Summer000 发表于 2024-1-10 21:16
本帖最后由 Summer000 于 2024-1-10 21:29 编辑

         这两个月给部门使用Django框架开发了一套内部人员使用的工作平台,想着可能很快就结束了,临到结束,领导要求增加两个调整申请审批单,需要有审批流,并且附带会签。可以自定义审批节点,本来想着找个开源的审批流引擎,发现市场上都是Activiti、Airflow、Zope之类的审批流引擎,引用起来还比较麻烦,不能很好的通过接口直接调用,比较烦人,索性自己开发了一套审批流引擎,暂且叫它MapFlow吧,为啥是Map呢,主要是配置很灵活,开箱即用。
      好了,言归正传,开始讲思路与功能点:
      首先,我需要使用一个类似于绘制前端动态图的方式绘制一张审批流程图,我需要保存当前绘制审批流程图的相关点位,对当前节点进行分类,是属于开始结束类还是步骤类,以及使用不同代码区分当前步骤节点,便于后期封装接口,这个后期再讲,上图:
f7ea199c07ac6ecf496e551fdada7be.png 2.png 3.png 4.png 5.png
  
呃,图片咋贴出来这么chou,先将就着看吧。。。
整个审批流引擎一共使用了12张表,包括两个完全不同的申请单,两个审批流审核,审批节点记录表,审批记录表等;
这个代码粘贴的太丑了,为啥不能直接上小方块呢?
[m_shl_code=python,true]    function init() {
        var $ = go.GraphObject.make;  // for conciseness in defining template

myDiagram =
            $(go.Diagram, "myDiagramDiv",  // must name or refer to the DIV HTML element
                {
                    "LinkDrawn": showLinkLabel,  // this DiagramEvent listener is defined below
                    "LinkRelinked": showLinkLabel,
                    "undoManager.isEnabled": true  // enable undo & redo
                });

        myDiagram.addDiagramListener("Modified", function(e) {
            var button = document.getElementById("SaveButton");
            if (button) button.disabled = !myDiagram.isModified;
            var idx = document.title.indexOf("*");
            if (myDiagram.isModified) {
                if (idx < 0) document.title += "*";
            } else {
                if (idx >= 0) document.title = document.title.substr(0, idx);
            }
        });

        function nodeStyle() {
            return [
                new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
                {
                    locationSpot: go.Spot.Center
                }
            ];
        }

        function makePort(name, align, spot, output, input) {
            var horizontal = align.equals(go.Spot.Top) || align.equals(go.Spot.Bottom);
            return $(go.Shape,
                {
                    fill: "transparent",  // changed to a color in the mouseEnter event handler
                    strokeWidth: 0,  // no stroke
                    width: horizontal ? NaN : 8,  // if not stretching horizontally, just 8 wide
                    height: !horizontal ? NaN : 8,  // if not stretching vertically, just 8 tall
                    alignment: align,  // align the port on the main Shape
                    stretch: (horizontal ? go.GraphObject.Horizontal : go.GraphObject.Vertical),
                    portId: name,  // declare this object to be a "port"
                    fromSpot: spot,  // declare where links may connect at this port
                    fromLinkable: output,  // declare whether the user may draw links from here
                    toSpot: spot,  // declare where links may connect at this port
                    toLinkable: input,  // declare whether the user may draw links to here
                    cursor: "pointer",  // show a different cursor to indicate potential link point
                    mouseEnter: function(e, port) {  // the PORT argument will be this Shape
                        if (!e.diagram.isReadOnly) port.fill = "rgba(255,0,255,0.5)";
                    },
                    mouseLeave: function(e, port) {
                        port.fill = "transparent";
                    }
                });
        }

        function textStyle() {
            return {
                font: "bold 11pt Lato, Helvetica, Arial, sans-serif",
                stroke: "#F8F8F8"
            }
        }

        function makeButton(text, action, visiblePredicate) {
            return $("ContextMenuButton",
                $(go.TextBlock, text),
                { click: action },
                visiblePredicate ? new go.Binding("visible", "", function(o, e) { return o.diagram ? visiblePredicate(o, e) : false; }).ofObject() : {});
        }

        var myContextMenu =  $("ContextMenu",
            makeButton("&#10032;配置&#10032;",
                function(e, obj) {  // OBJ is this Button
                    var contextmenu = obj.part;  // the Button is in the context menu Adornment
                    var part = contextmenu.adornedPart;  // the adornedPart is the Part that the context menu adorns
                    if (part instanceof go.Link) alert(linkInfo(part.data));
                    else if (part instanceof go.Group) alert(groupInfo(contextmenu));
                    else nodeInfo(part.data);
                }),


function isInArray(arr,value){
            for(var i = 0; i < arr.length; i++){
                if(value === arr){
                    return true;
                }
            }
            return false;
        }

        function nodeInfo(d) {
            var re_url = "{{url_data|safe}}";
            var pro_id = "{{process_id|safe}}";
            var node_key = JSON.parse('{{chart_exist|safe}}');
            if (isInArray(node_key,d.key) == true){
                layui.use('layer', function(){
                    parent.layer.open({
                        type: 2 //Page层类型
                        ,area: ['40%', '70%']
                        ,title: '节点配置'
                        ,shade: 0.6 //遮罩透明度
                        ,anim: 4 //0-6的动画形式,-1不开启
                        ,offset: '8%'
                        ,content:['/Flow/flow_chart_setting.html/'] + "?node_key=" + d.key + "&node_name=" + d.text + "&type=" + re_url + "&process_id=" + pro_id
                    });
                })
            }
            else {
                layui.use('layer', function(){
                    parent.layer.msg('请先保存节点数据!', {icon: 2});
                })
            }
        }

        myDiagram.nodeTemplateMap.add("",  // the default category
            $(go.Node, "Table", nodeStyle(),
                { contextMenu: myContextMenu },
                $(go.Panel, "Auto",
                    $(go.Shape, "Rectangle",
                        { fill: "#282c34", stroke: "#00A9C9", strokeWidth: 3.5 },
                        new go.Binding("figure", "figure")),
                    $(go.TextBlock, textStyle(),
                        {
                            margin: 8,
                            maxSize: new go.Size(160, NaN),
                            wrap: go.TextBlock.WrapFit,
                            editable: true
                        },
                        new go.Binding("text").makeTwoWay())
                ),
                makePort("T", go.Spot.Top, go.Spot.TopSide, false, true),
                makePort("L", go.Spot.Left, go.Spot.LeftSide, true, true),
                makePort("R", go.Spot.Right, go.Spot.RightSide, true, true),
                makePort("B", go.Spot.Bottom, go.Spot.BottomSide, true, false)
            ));

        myDiagram.nodeTemplateMap.add("Conditional",
            $(go.Node, "Table", nodeStyle(),
                { contextMenu: myContextMenu },
                $(go.Panel, "Auto",
                    $(go.Shape, "Diamond",
                        { fill: "#282c34", stroke: "#00A9C9", strokeWidth: 3.5 },
                        new go.Binding("figure", "figure")),
                    $(go.TextBlock, textStyle(),
                        {
                            margin: 8,
                            maxSize: new go.Size(160, NaN),
                            wrap: go.TextBlock.WrapFit,
                            editable: true
                        },
                        new go.Binding("text").makeTwoWay())
                ),
                makePort("T", go.Spot.Top, go.Spot.Top, false, true),
                makePort("L", go.Spot.Left, go.Spot.Left, true, true),
                makePort("R", go.Spot.Right, go.Spot.Right, true, true),
                makePort("B", go.Spot.Bottom, go.Spot.Bottom, true, false)
            ));

        myDiagram.nodeTemplateMap.add("Start",
            $(go.Node, "Table", nodeStyle(),
                // { contextMenu: myContextMenu },
                $(go.Panel, "Spot",
                    $(go.Shape, "Circle",
                        { desiredSize: new go.Size(70, 70), fill: "#282c34", stroke: "#09d3ac", strokeWidth: 3.5 }),
                    $(go.TextBlock, "Start", textStyle(),
                        new go.Binding("text"))
                ),
                makePort("L", go.Spot.Left, go.Spot.Left, true, false),
                makePort("R", go.Spot.Right, go.Spot.Right, true, false),
                makePort("B", go.Spot.Bottom, go.Spot.Bottom, true, false)
            ));

        myDiagram.nodeTemplateMap.add("End",
            $(go.Node, "Table", nodeStyle(),
                // { contextMenu: myContextMenu },
                $(go.Panel, "Spot",
                    $(go.Shape, "Circle",
                        { desiredSize: new go.Size(60, 60), fill: "#282c34", stroke: "#DC3C00", strokeWidth: 3.5 }),
                    $(go.TextBlock, "End", textStyle(),
                        new go.Binding("text"))
                ),
                makePort("T", go.Spot.Top, go.Spot.Top, false, true),
                makePort("L", go.Spot.Left, go.Spot.Left, false, true),
                makePort("R", go.Spot.Right, go.Spot.Right, false, true)
            ));

        go.Shape.defineFigureGenerator("File", function(shape, w, h) {
            var geo = new go.Geometry();
            var fig = new go.PathFigure(0, 0, true); // starting point
            geo.add(fig);
            fig.add(new go.PathSegment(go.PathSegment.Line, .75 * w, 0));
            fig.add(new go.PathSegment(go.PathSegment.Line, w, .25 * h));
            fig.add(new go.PathSegment(go.PathSegment.Line, w, h));
            fig.add(new go.PathSegment(go.PathSegment.Line, 0, h).close());
            var fig2 = new go.PathFigure(.75 * w, 0, false);
            geo.add(fig2);
            // The Fold
            fig2.add(new go.PathSegment(go.PathSegment.Line, .75 * w, .25 * h));
            fig2.add(new go.PathSegment(go.PathSegment.Line, w, .25 * h));
            geo.spot1 = new go.Spot(0, .25);
            geo.spot2 = go.Spot.BottomRight;
            return geo;
        });

        myDiagram.nodeTemplateMap.add("Comment",
            $(go.Node, "Auto", nodeStyle(),
                { contextMenu: myContextMenu },
                $(go.Shape, "File",
                    { fill: "#282c34", stroke: "#DEE0A3", strokeWidth: 3 }),
                $(go.TextBlock, textStyle(),
                    {
                        margin: 8,
                        maxSize: new go.Size(200, NaN),
                        wrap: go.TextBlock.WrapFit,
                        textAlign: "center",
                        editable: true
                    },
                    new go.Binding("text").makeTwoWay())
            ));


        myDiagram.linkTemplate =
            $(go.Link,  // the whole link panel
                {
                    routing: go.Link.AvoidsNodes,
                    curve: go.Link.JumpOver,
                    corner: 5, toShortLength: 4,
                    relinkableFrom: true,
                    relinkableTo: true,
                    reshapable: true,
                    resegmentable: true,
                    mouseEnter: function(e, link) { link.findObject("HIGHLIGHT").stroke = "rgba(30,144,255,0.2)"; },
                    mouseLeave: function(e, link) { link.findObject("HIGHLIGHT").stroke = "transparent"; },
                    selectionAdorned: false
                },
                new go.Binding("points").makeTwoWay(),
                $(go.Shape,  // the highlight shape, normally transparent
                    { isPanelMain: true, strokeWidth: 8, stroke: "transparent", name: "HIGHLIGHT" }),
                $(go.Shape,  // the link path shape
                    { isPanelMain: true, stroke: "gray", strokeWidth: 2 },
                    new go.Binding("stroke", "isSelected", function(sel) { return sel ? "dodgerblue" : "gray"; }).ofObject()),
                $(go.Shape,  // the arrowhead
                    { toArrow: "standard", strokeWidth: 0, fill: "gray" }),
                $(go.Panel, "Auto",  // the link label, normally not visible
                    { visible: false, name: "LABEL", segmentIndex: 2, segmentFraction: 0.5 },
                    new go.Binding("visible", "visible").makeTwoWay(),
                    $(go.Shape, "RoundedRectangle",  // the label shape
                        { fill: "#F8F8F8", strokeWidth: 0 }),
                    $(go.TextBlock, "Yes",  // the label
                        {
                            textAlign: "center",
                            font: "10pt helvetica, arial, sans-serif",
                            stroke: "#333333",
                            editable: true
                        },
                        new go.Binding("text").makeTwoWay())
                )
            );

        function showLinkLabel(e) {
            var label = e.subject.findObject("LABEL");
            if (label !== null) label.visible = (e.subject.fromNode.data.category === "Conditional");
        }

        myDiagram.toolManager.linkingTool.temporaryLink.routing = go.Link.Orthogonal;
        myDiagram.toolManager.relinkingTool.temporaryLink.routing = go.Link.Orthogonal;

        load();  // load an initial diagram from some JSON text

        myPalette =
            $(go.Palette, "myPaletteDiv",  // must name or refer to the DIV HTML element
                {
                    "animationManager.initialAnimationStyle": go.AnimationManager.None,
                    "InitialAnimationStarting": animateFadeDown, // Instead, animate with this function

                    nodeTemplateMap: myDiagram.nodeTemplateMap,  // share the templates used by myDiagram
                    model: new go.GraphLinksModel([  // specify the contents of the Palette
                        { category: "Start", text: "开始" },
                        { text: "步骤" },
                        { category: "Conditional", text: "判断" },
                        { category: "End", text: "结束" },
                    ])
                });

        function animateFadeDown(e) {
            var diagram = e.diagram;
            var animation = new go.Animation();
            animation.isViewportUnconstrained = true;
            animation.easing = go.Animation.EaseOutExpo;
            animation.duration = 900;
            animation.add(diagram, 'position', diagram.position.copy().offset(0, 200), diagram.position);
            animation.add(diagram, 'opacity', 0, 1);
            animation.start();
        }
    }

免费评分

参与人数 2吾爱币 +2 热心值 +2 收起 理由
gusong125 + 1 + 1 我很赞同!
blindcat + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

知心 发表于 2024-1-11 00:37
Summer000 发表于 2024-1-10 21:24
咱论坛代码不好粘贴呀

[Python] 纯文本查看 复制代码
myDiagram =
    $(go.Diagram, "myDiagramDiv",  // must name or refer to the DIV HTML element
        {
            "LinkDrawn": showLinkLabel,  // this DiagramEvent listener is defined below
            "LinkRelinked": showLinkLabel,
            "undoManager.isEnabled": true  // enable undo & redo
        });

myDiagram.addDiagramListener("Modified", function(e) {
    var button = document.getElementById("SaveButton");
    if (button) button.disabled = !myDiagram.isModified;
    var idx = document.title.indexOf("*");
    if (myDiagram.isModified) {
        if (idx < 0) document.title += "*";
    } else {
        if (idx >= 0) document.title = document.title.substr(0, idx);
    }
});

这还可以吧
青蛙考拉 发表于 2024-1-10 21:43
  File "<frozen importlib._bootstrap_external>", line 936, in exec_module
  File "<frozen importlib._bootstrap_external>", line 1074, in get_code
  File "<frozen importlib._bootstrap_external>", line 1004, in source_to_code
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "C:\Users\1\PycharmProjects\djangoProject\djangoProject\urls.py", line 1
    [md]function init() {
IndentationError: unexpected indent
你确定你做的程序能跑?
 楼主| Summer000 发表于 2024-1-10 21:24
blindcat 发表于 2024-1-11 07:50
学习学习,感谢分享
milu1123 发表于 2024-1-11 08:47
老大。有成品嘛?
15126819695 发表于 2024-1-11 08:51
主要是学习你的项目数据结构的啦     这个东西那几家收费的目前比较有优势
 楼主| Summer000 发表于 2024-1-11 09:10
青蛙考拉 发表于 2024-1-10 21:43
File "", line 936, in exec_module
  File "", line 1074, in get_code
  File "", line 1004, in sou ...

必须能跑,代码贴的不全,抽空我会都放上去,
 楼主| Summer000 发表于 2024-1-11 09:11
milu1123 发表于 2024-1-11 08:47
老大。有成品嘛?

必须有!!一种是直接内部调用审批流的,一种是对接系统封装的外部接口。
weilai8023 发表于 2024-1-11 09:12
大佬,有应用程序成品吗
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 11:43

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表