jsPlumb的学习使用(三):常规流程图完成

这篇具有很好参考价值的文章主要介绍了jsPlumb的学习使用(三):常规流程图完成。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

这篇文章就给大家展示个人的一个jsplumb成品,也是放在自己的项目之中.注释我基本上也都写好了,但是目前代码还没有进行整理,还有很多的测试痕迹以及备注打印.

先说包含的功能:

1.将节点拖拽到画布,精准放置画布内

2.画布中的节点可以自己主动去连线

3.画布节点和连线点击可以查看详情,并且可以删除节点和连线,并且重新绘制画布.

效果图如下:

jsplumb,jsplumb,流程图,js,vue.js

全部代码:

父组件(左侧和画布组件)

<template>
  <ul class="box">
    <li class="leftMenu">
      <h3>选择节点</h3>
      <el-collapse>
        <el-collapse-item
          :title="item1.name"
          v-for="(item1, index) in leftMenuData"
          :key="index"
        >
          <draggable
            @start="moveStart"
            @end="moveEnd"
            v-model="item1.children"
            :options="options"
          >
            <div
              v-for="(item2, n) in item1.children"
              class="content"
              :divOption="JSON.stringify(item2)"
              @mousedown="mouseDownFun"
              :key="n"
            >
              {{ item2.config[0].value }}
            </div>
          </draggable>
        </el-collapse-item>
      </el-collapse>
    </li>
    <li class="plumbBox" id="plumbBox">
      <div
        v-for="(item, index) in info"
        :key="index"
        :id="item.id"
        :style="getStyle(item)"
        :class="item.id === activeNode.id ? 'activeNode' : 'normalNode'"
        @click="sendActive(item)"
      >
        <div class="plumbNode" :id="item.id + 'plumbNode'">
          <el-icon :size="20">
            <CirclePlusFilled />
          </el-icon>
        </div>
        {{ item.config[0].value }}
        <el-icon
          class="is-loading"
          v-if="item.status === 'loading'"
          color="blue"
        >
          <Loading />
        </el-icon>
        <el-icon v-else-if="item.status === 'success'" color="green">
          <CircleCheckFilled />
        </el-icon>
        <el-icon v-else-if="item.status === 'error'" color="red">
          <CircleCloseFilled />
        </el-icon>
      </div>
    </li>

    <li class="rightContent">
      <h3>节点操作</h3>
      <div style="padding-left: 10px">
        <RightForm
          ref="rightForm"
          @changeActiveNodeInfo="changeActiveNodeInfo"
          @deleteLine="deleteLine"
          @deleteNode="deleteNode"
        ></RightForm>
      </div>
    </li>
  </ul>
</template>
<script setup>
//引入jsPlumb
import { jsPlumb } from "jsplumb";
import { VueDraggableNext } from "vue-draggable-next";
import { ElMessage } from "element-plus";
import lodash from "lodash";
import { v4 as uuidv4 } from "uuid";
import { reactive } from "vue";
import RightForm from "./rightForm";
const draggable = VueDraggableNext;
let plumbBox = null;
let plumbBoxPositionInfo = reactive({});
//鼠标和节点的内部差距,为了让节点更精准的判断区域
let nodePositionDiff = reactive({});
//后面需要回传给父组件的值
let plumbList = ref([]);
//绘制标识
let renderFlag = ref(undefined);
//动态节点
let activeNode = ref({});
let inputVal = ref("名称1");
let rightForm = ref(null);
/*
----------------------------------------------
//连线基础配置
let jsPlumbConnectOptions = {
        isSource: true,
        isTarget: true,
        // 动态锚点、提供了4个方向 Continuous、AutoDefault
        anchor: ["Continuous",{shape:"Circle"}],
        overlays: [['Arrow', { width: 8, length: 8, location: 1 }]] // overlay
      }
//画布节点的拖拽连线配置
const jsplumbSourceOptions = {
  filter:'.plumbNode',
  filterExclude:false,
  anchor:'Continuous',
  allowLoopback:true,
  maxConnections: -1,
  onMaxConnections:function (info,e){
    console.log(`超过了最大值连线:${info.maxConnections}`)
  }
}
----------------------------------------------
*/

//左侧菜单节点的拖拽配置
const options = {
  preventOnFilter: false,
  sort: false,
  disabled: false,
  ghostClass: "tt",
  // 不使用H5原生的配置
  forceFallback: true,
};
//默认配置
let globalConfig = {
  Container: "plumbBox",
  anchor: ["Bottom", "Top", "Left", "Right"],
  connector: "Bezier",
  endpoint: "Blank",
  paintStyle: {
    stroke: "#364249",
    strokeWidth: 1,
    outlineStroke: "transparent",
    outlineWidth: 10,
  },
  hoverPaintStyle: { stroke: "#000", strokeWidth: 1.3 },
  overlays: [["Arrow", { width: 5, length: 5, location: 1 }]],
  endpointStyle: {
    fill: "lightgray",
    outlineStroke: "darkgray",
    outlineWidth: 2,
  },
};
//左侧
let leftMenuData = ref([
  {
    name: "起始列表",
    children: [
      {
        to: [],
        top: 0,
        left: 0,
        status: "loading",
        isSource: true,
        isTarget: false,
        config: [
          {
            label: "名称",
            name: "label",
            type: "text",
            value: "起始节点1",
            require: true,
          },
          {
            label: "描述",
            name: "description",
            type: "textarea",
            value: "",
            require: false,
          },
          {
            label: "归属",
            name: "affiliation",
            type: "select",
            value: "check",
            require: true,
            options: [
              { label: "审核信息", value: "check" },
              { label: "生产经营", value: "manage" },
              { label: "结算报销", value: "account" },
            ],
          },
        ],
      },
      {
        to: [],
        top: 0,
        left: 0,
        status: "loading",
        isSource: true,
        isTarget: true,
        config: [
          {
            label: "名称",
            name: "label",
            type: "text",
            value: "起始节点2",
            require: true,
          },
          {
            label: "描述",
            name: "description",
            type: "textarea",
            value: "",
            require: false,
          },
          {
            label: "归属",
            name: "affiliation",
            type: "select",
            value: "check",
            require: true,
            options: [
              { label: "审核信息", value: "check" },
              { label: "生产经营", value: "manage" },
              { label: "结算报销", value: "account" },
            ],
          },
        ],
      },
    ],
  },
  {
    name: "完结列表",
    children: [
      {
        to: [],
        top: 0,
        left: 0,
        status: "loading",
        type: "target",
        isSource: false,
        isTarget: false,
        config: [
          {
            label: "名称",
            name: "label",
            type: "text",
            value: "完结节点1",
            require: true,
          },
          {
            label: "描述",
            name: "description",
            type: "textarea",
            value: "check",
            require: false,
          },
          {
            label: "归属",
            name: "affiliation",
            type: "select",
            value: "",
            require: true,
            options: [
              { label: "审核信息", value: "check" },
              { label: "生产经营", value: "manage" },
              { label: "结算报销", value: "account" },
            ],
          },
        ],
      },
      {
        to: [],
        top: 0,
        left: 0,
        status: "loading",
        isSource: false,
        isTarget: false,
        config: [
          {
            label: "名称",
            name: "label",
            type: "text",
            value: "完结节点2",
            require: true,
          },
          {
            label: "描述",
            name: "description",
            type: "textarea",
            value: "",
            require: false,
          },
          {
            label: "归属",
            name: "affiliation",
            type: "select",
            value: "check",
            require: true,
            options: [
              { label: "审核信息", value: "check" },
              { label: "生产经营", value: "manage" },
              { label: "结算报销", value: "account" },
            ],
          },
        ],
      },
    ],
  },
]);
//渲染节点信息(默认是后台传过来的)
let info = ref([]);
//新增一个节点
const addNode = (newInfo) => {
  newInfo.id = uuidv4();
  newInfo = Object.assign(newInfo, globalConfig);
  info.value.push(newInfo);
  console.log(newInfo, "???新增节点的信息");
  // makeFun(newInfo)
  nextTick(() => {
    renderFlag.value = "new";
    makeFun(newInfo);
  });
};

//新增一条连线
const addLine = () => {
  info.value[3].to = ["div6"];
  renderNode();
};
const mouseDownFun = (event) => {
  //具体位置鼠标信息
  let mousedownPositionInfo = { x: event.clientX, y: event.clientY };
  //被拖拽节点初始的位置信息
  let moveBoxBeforePosition = {
    x: event.target.getBoundingClientRect().x,
    y: event.target.getBoundingClientRect().y,
  };
  nodePositionDiff = {
    leftDiff: mousedownPositionInfo.x - moveBoxBeforePosition.x,
    topDiff: mousedownPositionInfo.y - moveBoxBeforePosition.y,
  };
};
//开始拖动
const moveStart = (el) => {
  console.log(el, "开始拖动");
};
//停止拖动
const moveEnd = (el) => {
  refreshPlumbPostionInfo();
  let dragNodeInfo = JSON.parse(el.item.attributes.divOption.nodeValue);
  judgePosition(
    dragNodeInfo,
    plumbBoxPositionInfo,
    el.originalEvent.x,
    el.originalEvent.y
  );
};
//判断拖动区域
const judgePosition = (dragNodeInfo, plumbBoxPositionInfo, x, y) => {
  //拖拽至画布外部
  if (
    x - nodePositionDiff.leftDiff < plumbBoxPositionInfo.left ||
    x + 180 - nodePositionDiff.leftDiff > plumbBoxPositionInfo.right ||
    y - nodePositionDiff.topDiff < plumbBoxPositionInfo.top ||
    y + 40 - nodePositionDiff.topDiff > plumbBoxPositionInfo.bottom
  ) {
    ElMessage({
      message: "节点不能拖拽至画布之外",
      type: "error",
    });
  } else {
    dragNodeInfo.left =
      x - plumbBoxPositionInfo.left - nodePositionDiff.leftDiff;
    dragNodeInfo.top = y - plumbBoxPositionInfo.top - nodePositionDiff.topDiff;
    addNode(dragNodeInfo);
  }
};
//刷新画布区域信息
const refreshPlumbPostionInfo = () => {
  plumbBox = document.querySelector(".plumbBox");
  let positionInfo = plumbBox.getBoundingClientRect();
  plumbBoxPositionInfo = positionInfo;
};
//渲染节点
const renderNode = (flag) => {
  //合并节点信息和配置
  info.value.map((item) => (item = Object.assign(item, globalConfig)));
  //这里需要等所依赖的DOM节点全部渲染完毕,才能进行图形渲染
  nextTick(() => {
    if (flag === "new") {
      renderFlag.value = "once";
    }
    plumbInit.deleteEveryConnection();
    plumbInit.deleteEveryEndpoint();
    refreshPlumbPostionInfo();
    //渲染画布中的信息节点
    let renderList = [];
    // if(info.value.length<1){return}
    info.value.forEach((item) => {
      if (item.to.length > 0) {
        item.to.forEach((v) => {
          renderList.push({
            source: item.id,
            target: v,
            anchor: item.anchor,
            connector: item.connector,
            endpoint: item.endpoint,
            overlays: item.overlays,
            paintStyle: item.paintStyle,
            hoverPaintStyle: item.hoverPaintStyle,
            endpointStyle: item.endpointStyle,
          });
        });
      }
    });
    plumbList.value = renderList;
    //渲染函数
    plumbInit.ready(() => {
      renderList.forEach((item) => {
        // plumbInit.connect(item,jsPlumbConnectOptions);
        plumbInit.connect(item);
      });
      info.value.forEach((item) => {
        makeFun(item);
        plumbInit.draggable(item.id, {
          containment: "parent",
          stop: function (el) {
            item.left = el.pos[0];
            item.top = el.pos[1];
          },
        });
      });
    });
  });
};
//设置节点可连接属性
const makeFun = (item) => {
  plumbInit.setSourceEnabled(item.id, item.isSource);
  plumbInit.setTargetEnabled(item.id, item.isTarget);
  plumbInit.setDraggable(item.id, true);
  plumbInit.makeSource(item.id, {
    filter: ".plumbNode",
    filterExclude: false,
    allowLoopback: true,
    maxConnections: -1,
    Container: "plumbBox",
    anchor: item.anchor,
    connector: item.connector,
    endpoint: item.endpoint,
    overlays: item.overlays,
    paintStyle: item.paintStyle,
    hoverPaintStyle: item.hoverPaintStyle,
    endpointStyle: item.endpointStyle,
  });
  plumbInit.makeTarget(item.id, {
    filter: ".plumbNode",
    filterExclude: false,
    allowLoopback: true,
    maxConnections: 1,
    Container: "plumbBox",
    anchor: item.anchor,
    connector: item.connector,
    endpoint: item.endpoint,
    overlays: item.overlays,
    paintStyle: item.paintStyle,
    hoverPaintStyle: item.hoverPaintStyle,
    endpointStyle: item.endpointStyle,
  });
  plumbInit.draggable(item.id, {
    containment: "parent",
    stop: function (el) {
      item.left = el.pos[0];
      item.top = el.pos[1];
    },
  });
};

// 给元素设置渲染样式
const getStyle = function (item) {
  return {
    position: "absolute",
    left: item.left + "px",
    top: item.top + "px",
    // color:item.color,
    // border:'1px solid #',
    width: "180px",
    height: "36px",
    lineHeight: "36px",
    textAlign: "center",
    borderLeft: "5px solid blue",
    borderRadius: "4%",
    boxShadow: "#eee 3px 3px 3px 3px",
    cursor: "pointer",
  };
};
//初始化jsplumb实例
let plumbInit = jsPlumb.getInstance();
//
plumbInit.bind("click", (conn, originalEvent) => {
  console.log(conn, "点击连线");
  let lineInfo = {};
  console.log(info.value, "整体信息");
  let sourceInfo = info.value.find((v) => v.id === conn.sourceId);
  let targetInfo = info.value.find((v) => v.id === conn.targetId);
  lineInfo = {
    sourceInfo,
    targetInfo,
  };
  rightForm.value.getLineInfo(lineInfo);
  // console.log("点击了", coon, originalEvent);
  // plumbInit.deleteConnection(conn);
});
//连线触发事件
plumbInit.bind("connection", (event) => {
  // console.log(event, "新的连线事件触发");
  // forceUpdate();
  let sourceNode = info.value.find((item) => item.id === event.sourceId);
  console.log(sourceNode.to, event.targetId, "???");
  if (sourceNode.to.findIndex((v) => v === event.targetId) === -1) {
    sourceNode.to.push(event.targetId);
  }
  plumbInit.repaint();
  nextTick(() => {
    renderFlag.value = "new";
  });
  if (renderFlag.value === "new") {
    console.log("新的页面刷新");
    renderFlag.value = "once";
    renderNode("new");
  }
  // console.log(info.value,'所有节点')
  // renderNode()
});

//切换动态节点
function sendActive(node) {
  activeNode.value = node;
  console.log(activeNode.value, "动态节点");
  rightForm.value.changeFormData(activeNode.value.config);
}

onMounted(() => {
  setTimeout(() => {
    //     info.value = [
    //   {
    //     name: "div1",
    //     to: ["div2", "div3"],
    //     top: 300,
    //     left: 100,
    //     color: "red",
    //     context: "开始运行",
    //     status: "success",
    //     isSource: true,
    //     isTarget: false,
    //   },
    //   {
    //     name: "div2",
    //     to: ["div4"],
    //     top: 200,
    //     left: 500,
    //     color: "green",
    //     context: "构建任务1",
    //     status: "success",
    //     isSource: true,
    //     isTarget: true,
    //   },
    //   {
    //     name: "div3",
    //     to: ["div5"],
    //     top: 400,
    //     left: 500,
    //     color: "green",
    //     context: "构建任务2",
    //     status: "error",
    //     isSource: true,
    //     isTarget: true,
    //   },
    //   {
    //     name: "div4",
    //     to: [],
    //     top: 200,
    //     left: 900,
    //     color: "blue",
    //     context: "完成部署1",
    //     status: "success",
    //     isSource: false,
    //     isTarget: true,
    //   },
    //   {
    //     name: "div5",
    //     to: [],
    //     top: 400,
    //     left: 900,
    //     color: "blue",
    //     context: "完成部署2",
    //     status: "loading",
    //     isSource: false,
    //     isTarget: true,
    //   },
    // ]
    renderNode();
    nextTick(() => {
      console.log("页面初次渲染完毕");
      renderFlag.value = "render";
    });
  }, 2000);
});
//右侧保存值
const changeActiveNodeInfo = (info) => {
  console.log(info, "保存后的新值");
  activeNode.value.config = info;
  nextTick(() => {
    renderFlag.value = "new";
    makeFun(activeNode.value);
  });
};
//删除线
const deleteLine = (deleteLineInfo) => {
  console.log(deleteLineInfo, "要删除的连线信息");
  console.log(info.value, "全量信息");
  let sourceIndex = info.value.findIndex(
    (item) => item.id === deleteLineInfo.sourceInfo.id
  );
  let deleteTargetId = deleteLineInfo.targetInfo.id;
  let deleteTargetIndex = info.value[sourceIndex].to.findIndex(
    (v) => v === deleteTargetId
  );
  info.value[sourceIndex].to.splice(deleteTargetIndex, 1);
  renderNode();
};
//删除节点
const deleteNode = (nodeInfo) => {
  console.log(activeNode.value);
  let nodeIndex = info.value.findIndex(
    (item) => item.id === activeNode.value.id
  );
  info.value.splice(nodeIndex, 1);
  info.value.forEach((item) => {
    let flagIndex = item.to.findIndex((v) => v === activeNode.value.id);
    if (flagIndex !== -1) {
      item.to.splice(flagIndex, 1);
    }
  });
  console.log(info.value, "节点列表");
  renderNode();
  activeNode.value = {};
  rightForm.value.changeFormData([]);
};
//暴露给父组件的值,需要父组件发送请求
defineExpose({
  plumbList,
  info,
});
</script>
<style lang="less" scoped>
.box {
  width: 100%;
  height: 100%;
  display: flex;
}

.leftMenu {
  width: 240px;
  border-right: 1px solid #d3d3d3;
  border-bottom: 1px solid #d3d3d3;
  h3 {
    width: 100%;
    height: 30px;
    line-height: 30px;
    background: #eee;
    text-align: center;
  }
  .content {
    width: 180px;
    height: 40px;
    border: dashed 1px #030303;
    text-align: center;
    line-height: 40px;
    margin-bottom: 10px;
    margin-right: 10px;
    cursor: pointer;
  }
}

.plumbBox {
  overflow: scroll;
  position: relative;
  // margin: 0 20px;
  width: 100%;
  border-right: 1px solid #d3d3d3;
}

.rightContent {
  width: 240px;
  border-bottom: 1px solid #d3d3d3;
  h3 {
    width: 200px;
    height: 30px;
    line-height: 30px;
    text-align: center;
  }
}

.plumbNode {
  float: left;
  line-height: 45px;
}
.activePlumbNode {
  float: left;
  line-height: 45px;
  background: #0bcfe9;
}
.normalNode {
  background-color: #fff;
}
.activeNode {
  background-color: #80eaf8;
}
</style>







 



    

子组件(右侧信息栏)

<template>
  <el-form
    v-if="infoType === 'node'"
    ref="ruleFormRef"
    :model="ruleForm"
    :rules="rules"
    label-width="120px"
    class="demo-ruleForm"
    :size="formSize"
    status-icon
    label-position="left"
  >
    <el-form-item
      :label="item.label"
      :prop="item.name"
      v-for="(item, index) in formData"
      :key="index"
    >
      <el-input v-model="ruleForm[item.name]" v-if="item.type === 'text'" />
      <el-input
        v-model="ruleForm[item.name]"
        type="textarea"
        v-else-if="item.type === 'textarea'"
      />
      <el-select
        v-model="ruleForm[item.name]"
        v-else-if="item.type === 'select'"
      >
        <el-option
          :label="m.label"
          :value="m.value"
          v-for="(m, n) in item.options"
          :key="n"
        />
      </el-select>
    </el-form-item>
  </el-form>
  <div v-if="infoType === 'line'">
    <h6>起始节点:</h6>
    <p>{{ lineData.sourceInfo.config[0].value }}</p>
    <h6>目标节点:</h6>
    <p>{{ lineData.targetInfo.config[0].value }}</p>
  </div>
  <div class="btnBox" v-show="listShow">
    <el-button
      type="primary"
      @click="submitForm(ruleFormRef)"
      v-show="infoType === 'node' && formData.length > 0"
    >
      保存节点
    </el-button>
    <el-button
      type="primary"
      v-show="infoType === 'node' && formData.length > 0"
      @click="delteNodeFun"
    >
      删除节点
    </el-button>
    <el-button
      type="primary"
      v-show="infoType === 'line'"
      @click="deleteLineFun"
    >
      删除连线
    </el-button>
  </div>
</template>
<script setup>
let formData = ref([]);
let lineData = ref({});
const formSize = ref("default");
const ruleFormRef = ref();
const listShow = ref(false);
let ruleForm = reactive({});
const infoType = ref("node");
const emit = defineEmits(["changeActiveNodeInfo", "deleteLine", "deleteNode"]);
const rules = reactive({
  label: [
    { required: true, message: "节点名称为必输项", trigger: "blur" },
    { min: 4, max: 8, message: "请输入4至8之间的字符", trigger: "blur" },
  ],
  affiliation: [
    {
      required: true,
      message: "请选择归属项",
      trigger: "change",
    },
  ],
});
const submitForm = async (formEl) => {
  if (!formEl) return;
  await formEl.validate((valid, fields) => {
    if (valid) {
      console.log(valid, ruleForm);
      formData.value.forEach((item) => {
        item.value = ruleForm[item.name];
      });
      emit("changeActiveNodeInfo", formData.value);
    } else {
      console.log("error submit!", fields);
    }
  });
};

const resetForm = (formEl) => {
  if (!formEl) return;
  formEl.resetFields();
};

const options = Array.from({ length: 10000 }).map((_, idx) => ({
  value: `${idx + 1}`,
  label: `${idx + 1}`,
}));
const getFormData = () => {
  console.log(formData, "信息");
};
//父节点传递信息函数
const changeFormData = (val) => {
  infoType.value = "node";
  listShow.value = true;
  console.log(val);
  formData.value = val;
  formData.value.forEach((item) => {
    console.log(item, "遍历");
    ruleForm[item.name] = item.value;
  });
  console.log(ruleForm, "???");
};
//父节点传递连线信息
const getLineInfo = (lineInfo) => {
  listShow.value = true;
  console.log(lineInfo, "连线信息");
  infoType.value = "line";
  lineData.value = lineInfo;
};
//删除连线信息
const deleteLineFun = () => {
  emit("deleteLine", lineData.value);
  infoType.value = null;
};
//删除节点
const delteNodeFun = () => {
  emit("deleteNode");
};
onMounted(() => {});
defineExpose({
  changeFormData,
  getLineInfo,
  formData,
});
</script>
<style lang="less" scoped>
/deep/ .el-form-item {
  display: flex;
  flex-direction: column !important;
}
h6 {
  font-size: 14px;
  font-weight: 500;
  margin: 5px;
  overflow: hidden;
}
p {
  margin: 20px;
  border-bottom: 1px solid #eee;
  overflow: hidden;
}
</style>

vue3的项目可以直接引用如上的代码,下载相关依赖就可以运行了.文章来源地址https://www.toymoban.com/news/detail-759913.html

到了这里,关于jsPlumb的学习使用(三):常规流程图完成的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用Jsmind实现前端流程图功能

    需求:实现流程图功能,根据状态不同显示不同的颜色,点击有对应的点击颜色 思想:根据jsmind构建思维导图,改变节点背景颜色,获取点击节点事件当点击节点是设置节点选中背景图片。 注意: 由于jsmind更新各版本api都有很大改动,所以我使用的都是官方文档注明的基于各

    2024年02月03日
    浏览(55)
  • 流程图软件Visio的使用笔记

    一、概述 Microsoft Visio 是Office软件系列中的负责绘制流程图和示意图的软件,是一款便于IT和商务人员就复杂信息、系统和流程进行可视化处理、分析和交流的软件。 也是工作中常用的软件之一,我们经常用它来画流程图和电源树等,下面就使用软件做的一些笔记,希望对初

    2024年02月09日
    浏览(44)
  • Selenium 学习(0.17)——软件测试之流程图绘制方法

            病假5天,出去野20天,成功错过了慕课网上的期末考试。         害,都怪玩乐太开心了……         反正咱又不指着全靠这个行当来吃饭,错过也就错过了,立的Flag能抢救一下还是要抢救一下吧。【这个其实早都会画了,而且基本也正确,既然是学习,还

    2024年02月03日
    浏览(58)
  • Python学习-流程图、分支与循环(branch and loop)

    1、流程图(Flowchart) 流程图是一种用于表示算法或代码流程的框图组合,它以不同类型的框框代表不同种类的程序步骤,每两个步骤之间以箭头连接起来。 好处: 1)代码的指导文档 2)有助于规划高效率的程序结构 3)便于与他人交流 流程图的思维是至上往下走的,线性逻

    2024年02月21日
    浏览(52)
  • 如何使用drawio画流程图以及导入导出

    你可以在线使用drawio, 或者drawon创建很多不同类型的图表。 如何使用编辑器,让我们以一个最基本的流程图开始。 流程图,就是让你可视化的描述一个过程或者系统。 图形和很少部分的文字表达就可以让读者很快的理解他们需要什么。 为了便于大家更直观的理解,我们在

    2024年02月07日
    浏览(45)
  • 使用 AntV X6 + vue 实现单线流程图

    X6 是 AntV 旗下的图编辑引擎,提供了一系列开箱即用的交互组件和简单易用的节点定制能力,方便我们快速搭建 DAG 图、ER 图、流程图等应用。 官方文档 Tips: 目前 X6 有 1.x 和 2.x 两个版本,因为官方文档的示例代码都是 1.x 版本的,所以本文档也是基于 1.x 版本的,如果你使

    2024年02月14日
    浏览(46)
  • Vue使用AntV X6绘制流程图(组态呈现)

    先上几个网址 AntV | 蚂蚁数据可视化 AntV X6 图编辑引擎 AntV X6文档 AntV X6 API AntV X6图表示例 上面是一些用到的网址,先说下我项目中的需求,就是要自己绘制出一个我们想要的图,组态化呈现出来,然后这个图中会有很多节点,每个节点都会有自己的状态 ,状态会实时改变,

    2024年02月06日
    浏览(64)
  • BPMNJS插件使用及汉化(Activiti绘制流程图插件)

    BPMNJS插件运行最重要的就是需要安装nodejs插件,这 一定要安装和测试好 。 主要是使用npm命令 1.1.1、下载nodejs 下载地址:https://nodejs.org/en  1.1.2、安装nodejs,傻瓜式安装 安装之后在安装目录下创建node_cache和node_global两个目录 如果目录已经存在可以不创建 node_cache:作为缓存路

    2024年02月14日
    浏览(39)
  • OD(8)之Mermaid流程图(flowcharts)使用详解

    OD(8)之Mermaid流程图(flowcharts)使用详解 Author: Once Day Date: 2024年2月20日 漫漫长路才刚刚开始… 全系列文章可参考专栏: Linux实践记录_Once_day的博客-CSDN博客 参考文章: 关于 Mermaid | Mermaid 中文网 (nodejs.cn) Mermaid | Diagramming and charting tool ‍‌⁡⁤‍‍⁢‌‬⁡⁤⁢‍‌⁣⁢⁢⁤⁣‌‌

    2024年02月22日
    浏览(47)
  • 在vue3中使用pinia完整流程图文

    使用vite创建好一个vue3项目,开发语言选择ts 使用 npm i pinia -s 安装最新版本的pinia 这里我的版本安装的是 2.1.4 1.在main中注册pinia 2.在store中创建index.ts和store-name.ts文件 index.ts内容如下: store-name.ts内容如下: app.vue文件的内容如下: 页面输出如下内容则一次简单的pinia的调用完

    2024年02月10日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包