简介
"时序图"-->先简单解释一下,突然接到任务要求做一个时序图(后面会附上参考图片),由于需求不是很完善,设计也还没给出图纸,暂时就先做一个满足基本功能的demo。
需求整理:
- 默认显示主任务,主任务下有N个子任务,需要查看子任务的运行状态时再加载子任务。
- 只有所有的子任务都结束了,主任务才显示完成状态,主任务的运行时间是变化的(开始时间可以确定)。
- 如何显示子任务并行、串行的运行状态?
- 以不同的颜色区分子任务所占主任务的比例,以及子任务本身的状态。
- 每个主任务的运行时间是不同的(有可能是一天、也有可能是一周),所以table head的时间的刻度是变化的。(不太理解的话,可以观看下面的参考图)。
- 思考如何搜索子任务(因为默认只显示主任务,需要点击时才加载子任务,这样做是为了考虑性能、加载速度),搜索功能应该可以按照名字、id、时间段,来进行搜索。
暂时的需求整理结束,下面来看看实现上遇到的一些问题,及解决方法。 注:
- 本文使用的是React + ts,UI组件库使用的是,本文中将简称antd。
- 本文中的'任务结束时间'表示任务正在运行的当前时间或者任务真正的完成时间。
先看参考图,了解一下大概是要做一个怎样的效果。
对示例图进行分析:
- 从上面这张图片可以看出,左侧是一个树形结构,比较开心,因为antd里有类似的组件,我们可以从组件上着手。
- table head 是延迟时间,对应我们需求里的任务运行时间。(对应我们需求整理的第5点的时间刻度)。
- 右侧是一个用进度条的形式显示对应的延时时间。细心的话会发现进度条的颜色是有区分的。(里面的文字数据就不多做介绍了,这个比较简单)
时序图的table head运行时刻计算,刻度为4
判断一个主任务的时刻步长:
step = (主任务结束时间 - 主任务开始时间)/3// 这里为什么是除以3呢?比如从12:00 - 15:00(12:00为刻度1,12 + step,12 + 2step, 15:00)复制代码
使用Tree做我们时序图
注: 实现的代码有点长,全部贴出来的话阅读会比较困难,所以我会贴出一些重要的部分,以及遇到问题的部分。
按照antd给出的示例去引入Tree组件,然后给参数添加类型。
public renderTree = () => { return ( // (JSX attribute) loadData?: ((node: AntTreeNode) => PromiseLike) | undefined {this.renderTreeNodes(this.state.treeData)} );}复制代码
使用TreeNodes加载数据的话,ts里会遇到一个这样的报错提示:
AntTreeNode上不存在dataRef,这时我选择去Tree.d.ts里面的AntTreeNodeProps接口里自己定义一个
dataRef: Partial<{children?: React.ReactNode}>;复制代码
在我们的组件里还需要这样去定义:
interface IRef extends AntTreeNodeProps{ dataRef: Partial<{children?: React.ReactNode}>;}// 因为我们的TreedNode是一个组件类型,我们需要在组件上注入dataRef这样在使用TreeNode时就不会有错误提示了const TreeNode = Tree.TreeNode as React.ComponentClass;复制代码
这里算是antd对ts写作支持的一个遗漏。好了ts的问题就到这里。
使用TreeNode时我们发现他的Title属性支持ReactNode,那么我们的进度条可以利用这个属性去显示。进度条的位置可以利用子任务的开始时间去判断。
我们的tree是为了实现任务的层级关系,那么我们如何控制左侧任务名字所占空间像上图一样呢?
antd Tree组件的子组件都是块级元素,并且为了表示层级,antd里treeNode都有一个固定的padding:0,0,0,18px,我们设置左侧任务名字的最大长度为400px.那么我们可以计算一下treeNode的长度:
400 - (index - 1) * 18 // 第一层的tree Node 的index为1,第一层的tree Node 的index为2,第一层的tree Node 的index为3以此类推。复制代码
子任务并行、串行的开始位置计算及定义
解释: 子任务不管是串行还是并行,我们这里先不做考虑,因为子任务开始时会记录它开始的时间段,我们只需要用它结束的时间段,和开始的时间段就可以知道任务的运行时长,以及子任务所占主任务的比例,通过比例我们可以设定它不同的颜色及状态。
- 子任务进度条的长度:
(子任务结束时间 - 子任务开始时间) / (主任务结束时间 - 主任务开始时间) * (屏幕宽度 - 400)// 400任务名所占的最大宽度复制代码
- 子任务进度条的颜色通过子任务所占主任务长度的多少来判断子任务的颜色变化。
// color 设置子任务的颜色。public color = { done: '#52c41a', failed: '#f5222d', running: '#1890ff'};public running_color = (max: number, min: number, item_width: number, color: string) => { if (min < item_width && item_width <= max) { this.color.running = color; }}// 通过运行状态取判断子任务的颜色if (item.status === 'running') { this.running_color(total_width, 0, item_width, '#b0afcc'); this.running_color((total_width * 2), total_width, item_width, '#7e7bc9'); this.running_color((total_width * 3), (total_width * 2), item_width, '#3a34c9'); this.running_color((total_width * 4), (total_width * 3), item_width, '#1427e1');}else this.progress_color = this.color[item.status];复制代码
展示一下只实现基础功能的时序图
原文链接:
作者信息:宁文飞,人和未来大数据前端工程师