npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

tf-flow-diagram

v0.1.3

Published

流程图组件

Downloads

2

Readme

流程图组件

本组件基于yarn构建

1. 安装

import TfFlowDiagram from 'tf-flow-diagram'

2. API文档

data = [ ...nodes, ...data ]

opts = { isTipEmptyShow: false, // 如果提示内容为空, 是否显示提示, 默认false

// 如果当前没有设置status状态, 是否依据其它的进行推导
// 例如:          -> 3 ->  
//      1 -> 2 ->        -> 5  // 如果设置了3的状态, 那么2和1的状态能推导出来; 如果设置了5的状态, 那么4,3,2,1的状态都能推导出来
//               -> 4 ->   
statusTrace: true, 
...opts

};

let temp = { /* // 格式如下: '5': { pre: ['3', '4'], // 上一级节点 status: 'xx', // 当前节点的状态 to: [] // 下一级节点 } */ }

let result = data.reduce((pre, cur) => { let name = cur.nodeName; let preName = cur.preNodeName

if (preName) { // 开始和结束节点的preNodeName为空
  if (!temp[preName]) {
    temp[preName] = { pre: [], status: '', to: [] }
  }
  temp[preName].to.push(name)

  pre.linkDataArray.push({
    from: preName,
    to: name,
    // color: 'xx'
    // ...
  })
}

if (!temp[name]) {
  temp[name] = { pre: [preName], status: cur.status || '', to: [] }
} else {
  temp[name].pre.push(preName);
}

// 只push到nodeDataArray一次
if (temp[name].pre.length > 1) return pre;

let isTipEmpty = !cur.approvalPerson

pre.nodeDataArray.push({
  key: cur.nodeName,
  text: cur.nodeName,
  tooltip: '审批人/' + {1: '且', 2: '或'}[cur.approvalRelation] + '\n' + (cur.approvalPerson || '').split(';').join('\n'),
  category: cur.category || (opts.isTipEmptyShow ? '' : (isTipEmpty ?  'notip' : '' )),
  status: cur.status,
  // bgColor: 'xx',
  // textColor: 'xx',
  // ...
})

return pre;

}, { nodeDataArray: [], linkDataArray: [] })

// 递归, 推导状态 function trace(obj, temp) { obj.pre.forEach(v => { if (temp[v] && !temp[v].status) { temp[v].status = '1' trace(temp[v], temp) } }) }

if (opts.statusTrace) { for(var i in temp) { if (temp[i].status === '1' || temp[i].status === '2') { trace(temp[i], temp); } } } // 最后的流程节点 let lastNodes = { names: [], // 最后的流程节点可能有多个 passed: [], // 状态为已通过的, 一般只有一个, 但是我程序里面不限制 lines: [], // 最后的流程节点指向结束节点的线条 passedToEndLine: [] // 最后的流程节点(状态为已通过)指向结束节点的线条 }; let endNodeIndex = -1; // 结束节点在nodeDataArray的位置

for (let i in temp) { // 配置 temp[i].config = this.props.statusMatchConfig(temp[i].status)

if(endNode && temp[i].to.length === 0 
  && temp[i].status !== endNode.status) {
  
  let line = {
    from: i,
    to: endNode.nodeName
  }

  lastNodes.names.push(i);
  lastNodes.lines.push(line);
  result.linkDataArray.push(line)

  if (temp[i].status == '1') {
    lastNodes.passed.push(i)
    lastNodes.passedToEndLine.push(line)
  }
}

}

// 设置颜色, 文本等配置信息 result.nodeDataArray.map((v, index) => { let { config } = temp[v.key]

v.bgColor = config.bgColor
v.textColor = config.textColor
v.borderColor = config.borderColor
v.borderWidth = config.borderWidth
v.margin = config.margin
v.font = config.font
v.textAlign = config.textAlign

if (v.status === '100') {
  endNodeIndex = index;
}

})

result.linkDataArray.map(v => { if (temp[v.to]) { v.color = temp[v.to].config.lineColor } })

// 指向结束节点的线条 let notPassed = this.props.statusMatchConfig('3') lastNodes.lines.forEach(v => { v.color = notPassed.lineColor }) // 设置结束节点 if (lastNodes.passed.length > 0) { let config = this.props.statusMatchConfig('1') let endConfig = this.props.statusMatchConfig('100').passed || {}; config = { ...config, ...endConfig }

// 重置结束节点的配置
if (endNodeIndex > -1) {
  let node = result.nodeDataArray[endNodeIndex];
  result.nodeDataArray[endNodeIndex] = { ...node, ...config }
}
// 指向结束节点的线条颜色
lastNodes.passedToEndLine.forEach(v => v.color = config.lineColor);

}

// 将一些数据挂载到上面去 result.__ = {temp, lastNodes, endNodeIndex };console.log(result) return result; } statusMatchConfig

  <td>
  </td>
  </tr>
  <tr>
  <td>customNodes</td>
  <td>定义额外的节点, 如: 开始和结束节点</td>
  <td>
  </td>
  </tr>
  <tr>
    <td>onBuiltInNodeTemplateClick</td>
    <td>自定义节点模板: 点击</td>
    <td><pre>(opts, ...rest) => {}</pre></td>
  </tr>
   <tr>
    <td>onBuiltInShapeClick</td>
    <td>自定义节点模板: 形状点击</td>
    <td><pre>(opts, ...rest) => {}</pre></td>
  </tr>
   <tr>
    <td>onBuiltInTextClick</td>
    <td>自定义节点模板: 文本点击</td>
    <td><pre>(opts, ...rest) => {}</pre></td>
  </tr>

3. 使用示例

import React, { useRef } from "react";

import TfFlowDiagram from 'tf-flow-diagram'

var responseData = [
  {
    "nodeName": "1", // 节点名称
    "preNodeName": "开始", // 上一级节点名称
    "approvalRelation": 1, // 审批人关系 1且 2或
    "approvalPerson":"19380_代办;14231_已办", // 审批人, 分号分隔
    //"status" : '3' // 状态, '1': 已通过, '2': 当前节点, '3': 未执行(默认), '0': 开始节点, '100': 结束节点
  },
  {
    "nodeName": "2", // 节点名称
    "preNodeName": "1", // 上一级节点名称
    "approvalRelation": 1,// 审批人关系 1且 2或
    "approvalPerson":"19380_代办;14231_已办", // 审批人, 分号分隔
    "status" : '1' // 状态, '1': 已通过, '2': 当前节点, '3': 未执行(默认), '0': 开始节点, '100': 结束节点
  },
  {
    "nodeName": "3", // 节点名称
    "preNodeName": "2", // 上一级节点名称
    "approvalRelation": 1,// 审批人关系 1且 2或
    "approvalPerson":"19380_代办;14231_已办", // 审批人, 分号分隔
    "status" : '2' // 状态, '1': 已通过, '2': 当前节点, '3': 未执行(默认), '0': 开始节点, '100': 结束节点
  },
  {
    "nodeName": "4", // 节点名称
    "preNodeName": "2", // 上一级节点名称
    "approvalRelation": 1,// 审批人关系 1且 2或
    "approvalPerson":"19380_代办;14231_已办", // 审批人, 分号分隔
    "status" : '1' // 状态, '1': 已通过, '2': 当前节点, '3': 未执行(默认), '0': 开始节点, '100': 结束节点
  },
  {
    "nodeName": "5", // 节点名称
    "preNodeName": "3", // 上一级节点名称
    "approvalRelation": 1,// 审批人关系 1且 2或
    "approvalPerson":"19380_代办;14231_已办", // 审批人, 分号分隔
    "status" : '' // 状态, '1': 已通过, '2': 当前节点, '3': 未执行(默认), '0': 开始节点, '100': 结束节点
  },
  {
    "nodeName": "5", // 节点名称
    "preNodeName": "4", // 上一级节点名称
    "approvalRelation": 1,// 审批人关系 1且 2或
    "approvalPerson":"19380_代办;14231_已办", // 审批人, 分号分隔
    "status" : '' // 状态, '1': 已通过, '2': 当前节点, '3': 未执行(默认), '0': 开始节点, '100': 结束节点
  }
]

export default function App() {
  let flowDiagram = useRef(null)

  function handleClick() {
    flowDiagram.current.setModel(responseData)
  }

  return (
    <div>
      <button onClick={handleClick}>更改数据</button>

      <TfFlowDiagram 
        ref={ flowDiagram }

        builtInTooltipTextConverter = {
          (opts) => (data, textNode) => {
            return data.tooltip || '暂无提示数据'
          }
        }

        onBuiltInTextClick = {
          (opts, ...rest) => {
            console.log('文字点击:', rest)
          }
        }
      />
    </div>
  )

}

4. 命令

npm start // 运行测试
npm run build // 构建生产
npm run pub // 发布

5. 版本更新说明


  0.0.1:
    初始版本