antd/x6-graph——实现流程图绘制功能——技能提升

news2024/11/19 22:38:39

效果图:
在这里插入图片描述

解决步骤1:安装"@antv/x6": "^1.35.0"

npm install @antv/x6@1.35.0

安装指定版本的antv/x6插件

解决步骤2:配置tools文件

assets/js中新增一个graphTools.js文件
内容如下:

/* 
antv x6图谱相关工具函数
*/
export default {
  /* 
  初始化初始节点(开始,结束节点)
  x:x轴坐标
  y:y轴坐标
  id:开始节点id
  name:节点内容,默认为空
  type:节点类型,默认为空
  */
  gongxuNode(x, y, id, name, type) {
    let node = {
      shape: 'rect',
      type: type,
      id: id, // String,可选,节点的唯一标识
      x: x, // Number,必选,节点位置的 x 值
      y: y, // Number,必选,节点位置的 y 值
      width: 130, // Number,可选,节点大小的 width 值
      height: 30, // Number,可选,节点大小的 height 值
      label: "功能模块",
      attrs: {
        // 这里给生成的节点的body加上透明的边框,一定要给边框宽度加上>0的值,否则节点将不能连线
        body: {
          strokeWidth: 3, // 边框的粗细
          magnet: true, // 节点是否可以连线
        }
      },
      extraProperties: {
        IsOutSend: false,
        IsSkip: false,
        TimeSpan: 0
      },
      // html: `
      //       <div class="custom_node_initial">
      //         <div>
      //           <p title=${name}>${name||''}</p>
      //         </div>
      //       </div>
      //       `,
      // attrs: {
      //   // 这里给生成的节点的body加上透明的边框,一定要给边框宽度加上>0的值,否则节点将不能连线
      //   body: {
      //     stroke: 'transparent',
      //     strokeWidth: 3, // 边框的粗细
      //     magnet: true, // 节点是否可以连线
      //   }
      // },
    }
    return node
  },

  /* 
  初始化逻辑节点
  x:x轴坐标
  y:y轴坐标
  id:开始节点id
  name:节点内容,默认为空
  type:节点类型,默认为空
  */
  tiaojianNode(x, y, id, name, type) {
    let node = {
      shape: 'rect',
      type: type, // 动作所属类型
      id: id, // String,可选,节点的唯一标识
      x: x, // Number,必选,节点位置的 x 值
      y: y, // Number,必选,节点位置的 y 值
      width: 190, // Number,可选,节点大小的 width 值
      height: 30, // Number,可选,节点大小的 height 值
      label: "条件模块",
      attrs: {
        // 这里给生成的节点的body加上透明的边框,一定要给边框宽度加上>0的值,否则节点将不能连线
        body: {
          stroke: '#f90',
          fill: 'rgba(255, 172, 50, 0.2)',
          strokeWidth: 3, // 边框的粗细
          magnet: true, // 节点是否可以连线
        }
      },
      extraProperties: {
        IsOutSend: false,
        IsSkip: false,
        TimeSpan: 0
      },
      // html: `
      //         <div class="custom_node_logic">
      //           <div>
      //             <p title=${name}>${name||''}</p>
      //           </div>
      //         </div>
      //       `,
      // attrs: {
      //   body: {
      //     stroke: 'transparent',
      //     strokeWidth: 3,
      //     magnet: true,
      //   }
      // },
    }
    return node
  }
}

解决步骤3:页面引入及dom节点

import { Graph } from "@antv/x6";
import Tools from "@/assets/js/graphTools.js";

页面初始化:

 <!-- 画布部分 -->
<div class="canvas-card">
  <div id="container" @dragover="dragoverDiv"></div>
</div>

解决步骤4:data配置字段

model: {
        // 节点
        nodes: [
          {
            id: "start", // String,可选,节点的唯一标识
            x: 10, // Number,必选,节点位置的 x 值
            y: 10, // Number,必选,节点位置的 y 值
            width: 130, // Number,可选,节点大小的 width 值
            height: 30, // Number,可选,节点大小的 height 值
            label: "开始",
            type: "0", // 开始类型
            extraProperties: {
              IsOutSend: false,
              IsSkip: false,
              TimeSpan: 0
            },
            attrs: {
              // 这里给生成的节点的body加上透明的边框,一定要给边框宽度加上>0的值,否则节点将不能连线
              body: {
                strokeWidth: 3, // 边框的粗细
                magnet: true // 节点是否可以连线
              }
            }
          },

          {
            id: "end", // String,可选,节点的唯一标识
            x: 1220, // Number,必选,节点位置的 x 值
            y: 600, // Number,必选,节点位置的 y 值
            width: 130, // Number,可选,节点大小的 width 值
            height: 30, // Number,可选,节点大小的 height 值
            label: "结束",
            type: "100", // 动作所属类型
            extraProperties: {
              IsOutSend: false
            },
            attrs: {
              // 这里给生成的节点的body加上透明的边框,一定要给边框宽度加上>0的值,否则节点将不能连线
              body: {
                strokeWidth: 3, // 边框的粗细
                magnet: true // 节点是否可以连线
              }
            }
          }
        ],
        // 边
        edges: [
          // {
          //   source: "node1", // String,必须,起始节点 id
          //   target: "node2", // String,必须,目标节点 id
          //   extraProperties: {
          //     IsOutSend: 11
          //   }
          // },
          // {
          //   source: "node1", // String,必须,起始节点 id
          //   target: "node3", // String,必须,目标节点 id
          //   extraProperties: {
          //     IsOutSend: 2222222222222222222
          //   } // String,必须,目标节点 id
          // }
        ]
      },

解决步骤5:初始化画布

// 初始化流程图画布
    initGraph() {
      let container = document.getElementById("container");
      this.graph = new Graph({
        container: container, // 画布容器
        width: container.offsetWidth, // 画布宽
        height: container.offsetHeight, // 画布高
        background: false, // 背景(透明)
        snapline: true, // 对齐线
        // 配置连线规则
        connecting: {
          snap: true, // 自动吸附
          allowBlank: false, //是否允许连接到画布空白位置的点
          allowMulti: false, //是否允许在相同的起始节点和终止之间创建多条边
          allowLoop: false, //是否允许创建循环连线,即边的起始节点和终止节点为同一节点
          highlight: true, //拖动边时,是否高亮显示所有可用的节点
          validateEdge({ edge, type, previous }) {
            // 连线时设置折线
            edge.setRouter({
              name: "er"
            });
            // 设置连线样式
            // edge.setAttrs({
            //   line: {
            //     stroke: "#275da3",
            //     strokeWidth: 4
            //   }
            // });
            return true;
          }
        },
        panning: {
          enabled: true
        },
        mousewheel: {
          enabled: true // 支持滚动放大缩小
        },
        grid: {
          type: "mesh",
          size: 10, // 网格大小 10px
          visible: true, // 渲染网格背景
          args: {
            color: "#eeeeee", // 网格线/点颜色
            thickness: 2 // 网格线宽度/网格点大小
          }
        }
      });
      //有ID说明是编辑
      if (this.$route.query.id) {
        plantflowSet_get(this.$route.query.id).then(res => {
          this.name = res.data.name;
          this.remark = res.data.remark;
          var nodesArr = []; //点
          var edgesArr = []; //线
          res.data.elements.map(item => {
            nodesArr.push({
              id: item.code, // String,节点的唯一标识
              x: item.xCoordinate, // Number,必选,节点位置的 x 值
              y: item.yCoordinate, // Number,必选,节点位置的 y 值
              width: item.width, // Number,可选,节点大小的 width 值
              height: item.height, // Number,可选,节点大小的 height 值
              label: item.name,
              extraProperties: {
                ...item.extraProperties
              },
              type: item.type, // 条件类型
              attrs: {
                // 这里给生成的节点的body加上透明的边框,一定要给边框宽度加上>0的值,否则节点将不能连线
                body: {
                  fill:
                    item.type == 20
                      ? "rgba(255, 172, 50, 0.2)"
                      : "rgba(255, 172, 50, 0)",
                  stroke: item.type == 20 ? "#f90" : "#000",
                  strokeWidth: 3, // 边框的粗细
                  magnet: true // 节点是否可以连线
                }
              }
            });
          });

          res.data.connections.map(item => {
            edgesArr.push({
              source: item.startElementCode, // String,必须,起始节点 id
              target: item.endElementCode, // String,必须,目标节点 id
              ...item
              // extraProperties: {
              //   IsOutSend: 11
              // }
            });
          });
          this.model.nodes = nodesArr;
          this.model.edges = edgesArr;
          this.graph.fromJSON(this.model);
          this.nodeAddEvent();
        });
      } else {
        this.graph.fromJSON(this.model);
        this.nodeAddEvent();
      }
    },

解决步骤6:生成节点

// 生成节点函数  0--开始节点, 10--工序节点, 20--条件节点, 100--结束节点
addHandleNode(x, y, id, name, type) {
  type == "20"
    ? this.graph.addNode(Tools.tiaojianNode(x, y, id, name, type))
    : this.graph.addNode(Tools.gongxuNode(x, y, id, name, type));
},

解决步骤7:节点点击

//节点事件
    nodeAddEvent() {
      // 节点绑定点击事件
      this.graph.on("node:click", ({ e, x, y, node, view }) => {
        if(node.label === '开始'||node.label === '结束'){
          return false
        }
        // 判断是否有选中过节点
        if (this.curSelectNode) {
          // 移除选中状态
          this.curSelectNode.removeTools();
          // 判断两次选中节点是否相同
          if (this.curSelectNode !== node) {
            node.addTools([
              {
                name: "boundary",
                args: {
                  attrs: {
                    fill: "#16B8AA",
                    stroke: "#2F80EB",
                    strokeWidth: 1,
                    fillOpacity: 0.1
                  }
                }
              },
              {
                name: "button-remove",
                args: {
                  x: "100%",
                  y: 0,
                  offset: {
                    x: 0,
                    y: 0
                  }
                }
              }
            ]);
            this.curSelectNode = node;
          } else {
            this.curSelectNode = null;
          }
        } else {
          this.curSelectNode = node;
          node.addTools([
            {
              name: "boundary",
              args: {
                attrs: {
                  fill: "#16B8AA",
                  stroke: "#2F80EB",
                  strokeWidth: 1,
                  fillOpacity: 0.1
                }
              }
            },
            {
              name: "button-remove",
              args: {
                x: "100%",
                y: 0,
                offset: {
                  x: 0,
                  y: 0
                }
              }
            }
          ]);
        }

        let isNewNode = true;
        if (this.curSelectNode && this.curSelectNode.id) {
          this.graph.toJSON().cells.map(item => {
            if (item.id == this.curSelectNode.id) {
              this.editNode = item.label;
              this.nodeDataForm = item.extraProperties;
              this.formData1 = {
                ...this.nodeDataForm
              };

              this.formData1.StepKey = item.label;
              isNewNode = false;
              //点击的节点类型
              this.clickType = item.type;
              //点击条件
              if (item.type == "20") {
                this.$refs.tiaojianModalRef.openModules(item);
              }
            }
          });
          this.editNodeId = this.curSelectNode.id;
          // 如果点击是新节点
          if (isNewNode) {
            this.editNode = node.label;
            this.formData1.StepKey = node.label;
            this.nodeDataForm = node.extraProperties;
            //点击的节点类型
            this.clickType = node.type;
          }
        }
      });
      // 连线绑定悬浮事件
      this.graph.on("cell:mouseenter", ({ cell }) => {
        if (cell.shape == "edge") {
          cell.addTools([
            {
              name: "button-remove",
              label: "999999",
              args: {
                x: "100%",
                y: 0,
                offset: {
                  x: 0,
                  y: 0
                }
              }
            }
          ]);
          cell.setAttrs({
            line: {
              stroke: "#409EFF"
            }
          });
          cell.zIndex = 99;
        }
      });
      //点击连接线
      this.graph.on("cell:click", ({ cell }) => {
        var newArredge = [];

        this.graph.toJSON().cells.map(item => {
          if (item.shape == "edge") {
            newArredge.push(item);
          }
        });
        if (cell.shape == "edge") {
          this.xianVisible = true;
          //遍历获取点击的线
          newArredge.map(item => {
            if (
              (item.source == cell.source.cell &&
                item.target == cell.target.cell) ||
              (item.source.cell == this.itemSource &&
                item.target.cell == this.itemTarget) ||
              (item.source.cell == cell.source.cell &&
                item.target.cell == cell.target.cell)
            ) {
              this.itemSource = cell.source.cell; //点击线的起止
              this.itemTarget = cell.target.cell; //点击线的起止
              if (item.conditionExpression!=undefined && item.conditionExpression == "false"){
                this.clickTypeCheck = false;
              } else {
                this.clickTypeCheck = true;
              }
            }
          });

          // this.clickTypeCheck=true;
        }
      });
      this.graph.on("cell:mouseleave", ({ cell }) => {
        if (cell.shape === "edge") {
          cell.removeTools();
          cell.setAttrs({
            line: {
              stroke: "#275da3"
            }
          });
          cell.zIndex = 1;
        }
      });
    },

解决步骤8:线条编辑

//线条件编辑
    xianhandleOk() {
      var newArr = [];
      var newArredge = [];

      this.graph.toJSON().cells.map(item => {
        if (item.shape == "edge") {
          newArredge.push(item);
        }
      });

      newArredge.map(item => {
        if (
          (item.source == this.itemSource && item.target == this.itemTarget) ||
          (item.source.cell == this.itemSource &&
            item.target.cell == this.itemTarget)
        ) {
          item.conditionExpression = this.clickTypeCheck+"";

        }
        newArr.push(item);
      });

      this.setData();
      this.model.edges = newArr;

      this.xianVisible = false;
      this.graph.fromJSON(this.model);
    },

解决步骤9:新增模块

//新增工序模块
addGXMokuai() {
  this.addHandleNode(500, 200, new Date().getTime(), "工序模块", "10");
},
//新增条件模块
addTJMokuai() {
  this.addHandleNode(500, 100, new Date().getTime(), "条件模块", "20");
},

解决步骤10:拖动节点+保存等

// 拖动节点到画布中鼠标样式变为可拖动状态
    dragoverDiv(ev) {
      ev.preventDefault();
    },
    //单节点保存 不掉接口
    setData() {
      let mapArr = this.graph.toJSON().cells;
      const newNodesModel = [];
      const newEdgesModel = [];
      mapArr.map(item => {
        if (item.shape == "rect") {
          newNodesModel.push({
            id: item.id,
            x: item.position.x,
            y: item.position.y,
            type: item.type,
            width: item.size.width,
            height: item.size.height,
            label:
              item.id == this.editNodeId
                ? this.formData1.StepKey
                : item.attrs.text.text,
            extraProperties:
              this.editNodeId == item.id
                ? { ...this.formData1 }
                : { ...item.extraProperties },
            attrs: item.attrs
          });
        } else {
          newEdgesModel.push({
            source: item.source,
            target: item.target,
            ...item
          });
        }
      });
      this.model.nodes = newNodesModel;
      this.model.edges = newEdgesModel;
      this.graph.fromJSON(this.model);
    },
    //条件保存
    user_success(data) {
      let mapArr = this.graph.toJSON().cells;
      const newNodesModel = [];
      const newEdgesModel = [];
      mapArr.map(item => {
        if (item.shape == "rect") {
          if (item.id != data.id) {
            newNodesModel.push({
              id: item.id,
              x: item.position.x,
              y: item.position.y,
              type: item.type,
              width: item.size.width,
              height: item.size.height,
              label:
                item.id == this.editNodeId
                  ? this.formData1.StepKey
                  : item.attrs.text.text,
              extraProperties:
                this.editNodeId == item.id
                  ? { ...this.formData1 }
                  : { ...item.extraProperties },
              attrs: item.attrs
            });
          } else {
            newNodesModel.push(data);
          }
        } else {
          newEdgesModel.push({
            source: item.source,
            target: item.target,
            ...item
          });
        }
      });
      this.model.nodes = newNodesModel;
      this.model.edges = newEdgesModel;
      this.graph.fromJSON(this.model);
    },
    //整体提交调用接口
    setDataOk() {
      if (this.name == "" || this.remark == "") {
        return this.$message.error("请先填写名称/备注");
      }

      const params = {
        factoryid: "d4882b18-47b0-ca1f-4ad3-3a10cc22976a",
        name: this.name,
        expression: "string",
        sort: 0,
        remark: this.remark,
        elements: [
          // {
          //   code: "string",
          //   type: "BeginNode",
          //   name: "string",
          //   xCoordinate: 0,
          //   yCoordinate: 0,
          //   width: 0,
          //   height: 0,
          //   textContent: "string",
          //   expression: "string",
          //   parameters: [
          //     {
          //       name: "string",
          //       expressionType: "Constant",
          //       expression: "string",
          //       enabled: true,
          //       sort: 0
          //     }
          //   ]
          // }
        ],
        connections: [
          // {
          //   startElementCode: "string",
          //   endElementCode: "string",
          //   connectionType: 0,
          //   conditionExpression: "string"
          // }
        ]
      };

      this.graph.toJSON().cells.map(item => {
        //节点
        if (item.shape == "rect") {
          params.elements.push({
            code: item.id.toString(),
            type: item.type,
            name: item.attrs.text.text,
            xCoordinate: item.position.x,
            yCoordinate: item.position.y,
            width: item.size.width,
            height: item.size.height,
            textContent: "string",
            expression: item.expression,
            extraProperties: item.extraProperties,
            parameters: [
              {
                name: "string",
                expressionType: "Constant",
                expression: "string",
                enabled: true,
                sort: 0
              }
            ]
          });
        } else {
          //连线
          params.connections.push({
            startElementCode: item.source.cell.toString(),
            endElementCode: item.target.cell.toString(),
            extraProperties: item.extraProperties,
            // connectionType: 0,
            conditionExpression: item.conditionExpression?item.conditionExpression:"true",
            ...item
          });
        }
      });

      if (this.$route.query.id) {
        params.id = this.$route.query.id;
        plantflowSet_edit(params).then(res => {
          if (res.success == true) {
            this.$message.success(res.message);
          } else {
            this.$message.error(res.message);
          }
        });
      } else {
        plantflowSet_add(params).then(res => {
          if (res.success == true) {
            this.$message.success(res.message);
          } else {
            this.$message.error(res.message);
          }
        });
      }
    },
    UpdateData() {
      this.$forceUpdate();
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1567008.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

启动mysql

删除C:\Program Files (x86)\MySQL\MySQL Server 5.7这个路径下的data文件夹&#xff0c;这个很难删除&#xff0c;因为一开机&#xff0c;mysql的某些服务就启动了&#xff0c;每次重新启动mysql之前&#xff0c;都要删除这个文件夹 因为这个文件夹在后端执行一些我们看不到的…

从零开始:Flutter应用上架iOS的完整流程解析

引言 &#x1f680; Flutter作为一种跨平台的移动应用程序开发框架&#xff0c;为开发者提供了便利&#xff0c;使他们能够通过单一的代码库构建出高性能、高保真度的应用程序&#xff0c;同时支持Android和iOS两个平台。然而&#xff0c;完成Flutter应用程序的开发只是第一步…

Java基于微信小程序的电子竞技信息交流系统,附源码(V2.0)

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…

前视声呐目标识别定位(八)-代码解析之各模块通信

前视声呐目标识别定位&#xff08;一&#xff09;-基础知识 前视声呐目标识别定位&#xff08;二&#xff09;-目标识别定位模块 前视声呐目标识别定位&#xff08;三&#xff09;-部署至机器人 前视声呐目标识别定位&#xff08;四&#xff09;-代码解析之启动识别模块 …

51单片机入门_江协科技_20.1_Proteus串口仿真

1.为了解决51单片机学习过程中在Proteus中的串口仿真的问题&#xff0c;需要在Proteus中建立串口仿真的环境&#xff08;目前Proteus安装在Win7x64虚拟机环境中&#xff1b; 2. 在CSDN中找到VSPD下载地址&#xff0c;在虚拟机中进行VSPD的安装&#xff0c;具体链接地址如下&am…

MySQL 学习心得和知识总结(五)|MySQL的一般查询日志(general log)

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《PostgreSQL数据库内核分析》 2、参考书籍&#xff1a;《数据库事务处理的艺术&#xff1a;事务管理与并发控制》 3、PostgreSQL数据库仓库…

计算机视觉——图像金字塔理解与代码示例

图像金字塔 有时为了在图像中检测一个物体&#xff08;例如人脸、汽车或其他类似的物体&#xff09;&#xff0c;需要调整图像的大小或对图像进行子采样&#xff0c;并进行进一步的分析。在这种情况下&#xff0c;会保持一组具有不同分辨率的同一图像。称这种集合为图像金字塔…

耐腐蚀耐高温实验室塑料烧杯进口高纯PFA材质反应器特氟龙烧杯

PFA烧杯在实验过程中可作为储酸容器或涉及强酸强碱类实验的反应容器&#xff0c;用于盛放样品、试剂&#xff0c;可搭配电热板加热、蒸煮、赶酸用。 外壁均有凸起刻度&#xff0c;直筒设计&#xff0c;带翻边&#xff0c;便于夹持和移动&#xff0c;边沿有嘴&#xff0c;便于倾…

【前端面试3+1】10 npm run dev 发生了什么、vue的自定义指令如何实现、js的数据类型有哪些及其不同、【最长公共前缀】

一、npm run dev发生了什么 运行npm run dev时&#xff0c;通常是在一个基于Node.js的项目中&#xff0c;用来启动开发服务器或者执行一些开发环境相关的任务。下面是一般情况下npm run dev会执行的步骤&#xff1a; 1. 查找package.json中的scripts字段&#xff1a; npm会在项…

Unity自定义icon

Unity自定义icon 1. 新建文件夹 OfficeFabricIconSet2. 新建Iconset3. 新建子文件夹Textures并添加icon图片4. 向iconset添加Quad Icons5. 最终效果 教程来源处&#xff1a; https://365xr.blog/build-your-own-button-icon-set-for-microsoft-hololens-2-apps-with-mrtk-using…

园区管理(源码+文档)

园区管理系统&#xff08;小程序、ios、安卓都可部署&#xff09; 文件包含内容程序简要说明含有功能项目截图客户端登录页我的退出登录发布详细注意事项公告列表入园记录主页我的资料电梯报修意见反馈客服入园申请注册招商列表 后台管理签到管理公告管理招商管理入园管理反馈报…

玩机进阶教程-----高通9008线刷XML脚本修改备份 檫除的操作步骤解析

在高通9008官方固件中我们可以看到刷写需要的脚本rawprogram0.xml和辅助脚本patch0.xml&#xff0c;脚本的作用在于将固件内各个分区对应写入手机内。根据分区地址段。然后判断脚本中那些分区不写入。以下步骤将分析emmc字库为例来讲解如何将默认刷入脚本修改为备份 檫除脚本。…

从汇编看函数调用

文章目录 函数调用流程栈相关寄存器及的作用简介寄存器功能指令功能 函数的括号{}正括号反括号 栈函数调用函数内部处理 参数传递传值&#xff0c;变量不可改传指针&#xff0c;变量可改C 传引用 函数调用流程 目标&#xff1a;函数调用前后栈保持不变 保存main函数的寄存器…

爬虫实战三、PyCharm搭建Scrapy开发调试环境

#一、环境准备 Python开发环境以及Scrapy框架安装&#xff0c;参考&#xff1a;爬虫实战一、Scrapy开发环境&#xff08;Win10Anaconda&#xff09;搭建 PyCharm安装和破解&#xff0c;参考&#xff1a;爬虫实战二、2019年PyCharm安装&#xff08;激活到2100年&#xff09; …

【机器学习】“强化机器学习模型:Bagging与Boosting详解“

1. 引言 在当今数据驱动的世界里&#xff0c;机器学习技术已成为解决复杂问题和提升决策制定效率的关键工具。随着数据的增长和计算能力的提升&#xff0c;传统的单一模型方法已逐渐无法满足高精度和泛化能力的双重要求。集成学习&#xff0c;作为一种结合多个学习算法以获得比…

WPS二次开发专题:如何获取应用签名SHA256值

作者持续关注WPS二次开发专题系列&#xff0c;持续为大家带来更多有价值的WPS开发技术细节&#xff0c;如果能够帮助到您&#xff0c;请帮忙来个一键三连&#xff0c;更多问题请联系我&#xff08;QQ:250325397&#xff09; 在申请WPS SDK授权版时候需要开发者提供应用包名和签…

如何处理Jenkins打包npm install没有拉取到最新依赖的问题

问题背景&#xff1a; 我们项目中有私有依赖包 frame&#xff0c;是私有服务器上通过 npm 去管理。frame包 publish 之后&#xff0c;通过Jenkins打包时&#xff0c;npm install 一直没有拉取最新的代码。 思考&#xff1a;通过在本地直接替换 node_modules 里的 frame 包&…

推理端框架简介 高通SNPE 神经网络处理引擎 阿里巴巴 MNN 腾讯 FeatherCNN 端侧推理引擎 卷积计算优化 卷积计算优化

高性能计算(High performance computing, 缩写HPC) 指通常使用很多处理器(作为单个机器的一部分) 或者某一集群中组织的几台计算机(作为单个计 算资源操作)的计算系统和环境。 有许多类型的HPC 系统,其范围从标准计算机的大型集群,到高度专用的硬件。 大多数基于集群的H…

复现带积分柱状图+多个分类注释

Original research: Tumor microenvironment evaluation promotes precise checkpoint immunotherapy of advanced gastric cancer - PMC (nih.gov) 补充文件位置&#xff1a;https://www.ncbi.nlm.nih.gov/pmc/articles/PMC8356190/bin/jitc-2021-002467supp001.xlsx 原图 该…

【JavaSE】类和对象详解(下)

前言 面向对象程序的三大特性&#xff1a;封装、继承、多态~ 书接上回 类和对象&#xff08;上&#xff09;~ 欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 前言 封装 private public 快速生成可访问封装的方法 包…