写点什么

可视化搭建数据大屏系统的前端实现

  • 2021-03-17
  • 本文字数:5190 字

    阅读完需:约 17 分钟

可视化搭建数据大屏系统的前端实现

背景


随着公司业务的发展,经常会收到一些数据大屏的需求。目前我司有两种实现方案,一是人肉搭建,二是用阿里云 DataV 搭建。


人肉搭建,在本地脚手架开发环境中进行编码,有大量的重复劳动,能力复用性差,占用前端宝贵的开发时间。


DataV 功能强大,但需要付费使用,且好用的组件还要额外收费,不支持本地化部署,还需要维护两套数仓。


综上,如果此类大屏的需求较多,业务的重要性明显,就需要考虑是不是需要自己开发一套搭建大屏的系统,用以降低开发复杂度,提升研发效率,降低成本。本文尝试基于政采云前端团队的数据大屏搭建系统 Big 的拆解说明,为大家提供一种此类系统的设计和实施方案。


Big 是什么


Big 是基于政采云前端搭建系统 鲁班,和数据大屏组件库,进行快速搭建数据大屏的可视化系统。

为什么叫 Big 呢? 打开百度翻译,输入大屏,英文翻译是 Big screen,四舍五入叫 Big


自己做一套系统的优势


  • 可定制性:内部产品,组件和展示形式私人订制

  • 支持本地化部署:业务需要决定部分业务只能在内网访问,无法访问外网(包括阿里云)

  • 解决 DataV 需要维护两套数仓的问题

  • 节约公司成本,增强公司数据产品能力,助力营收


总览


数据大屏是用可视化的方式展示庞杂数据的产品,经常会用在会议展览、业务监控、风险预警、地理信息分析等多种业务场景。下图是阿里云 DataV 的一个模板:



从前端实现来看,大屏是由线图、柱状图、饼图、标题、背景、边框等基本元素组成。实现思路是以这些基本元素为组件,通过选择组件、拖拽方式布局,配置样式、数据来源,将这些数据保存在数据库中。展示页面获取依赖的组件、样式和数据信息,呈现给用户。


大屏按场景划分,可分为编辑和查看。

编辑:指的是大屏制作者制作大屏。

查看:包含两种情况,大屏制作者预览和实际用户查看大屏。


编辑


编辑大屏是数据可视化系统核心,页面布局参考 DataV:

拆解为 4 个部分:顶部、组件区、画布、数据配置区。先讲下设计思路,再依次分解各区。


设计思路


  • 页面数据和依赖的组件由 SSR (https://juejin.im/post/5b063962f265da0ddb63dac3) 注入到 HTML 文件中

  • App 数据保存在 App state 中,未使用 Vuex(后续会考虑使用 Vuex)

  • 数据用 props 传递给子组件

  • 数据从子组件采用事件中心传递给祖父级组件

顶部


顶部区域包含三部分:左侧开关区、控制图层、组件列表、数据配置区的显示隐藏;中间是大屏的标题;右侧是保存和预览。

组件区


组件区分为左侧图层(已添加的组件)和右侧组件列表,具备添加组件、选择操作图层、分组对齐的功能。

图层

  • 图层支持上移、下移、置顶、删除的操作,支持右键显示操作菜单(暂不支持多选和分组)。实现原理是使用数组的基本方法改变数组

  • 单击组件选择该组件,画布区选中组件,数据配置区显示配置项

组件列表

  • 所有组件展示所有大屏组件,点击或拖动添加组件

  • 添加组件采用异步获取组件的 JS、CSS 、配置 Schema,将 CSS、JS 插入 DOM 中,配置传入属性配置区

  • 支持按组件类型分组,便于用户使用。


画布


画布用于实时展示大屏组件的位置、尺寸、属性和数据修改后的效果。


位置和尺寸改变通过注册组件 vue-draggable-resizable 的 drag 和 resize 方法,改变对应组件的属性。组件采用绝对定位,拖动时修改 top 和 left 的值。


属性改变通过修改对应组件的 props.models 的值修改。


数据分为静态数据和接口数据。启用静态数据时,数据从用户填写的数据获取。否则组件 watch 接口 id ,每次改变时重新发送请求获取数据。


画布上边和左边是标尺,画布缩放时标尺要跟随变动。在标尺上移动时显示一条移动的参考线。点击时增加一条参考线。双击参考线删除。标尺用 Canvas 画出,旋转 90 度可获得 Y 轴。


右下是缩放滑块,方便用户缩放查看。进入页面默认缩放到可查看全屏大小。缩放实现使用 CSS3 的transform: scale(${this.scale})


画布上未选择组件时,显示页面的基本配置,包括大屏的宽高、背景图。


选择组件后,高亮显示当前组件,标识位置,右侧数据配置区显示组件 Schema 定义的配置项。


核心代码


<div  v-for="item in preCompList"  :class="[    'data-com',    item.info.previewId === activePreviewId ? 'data-com-active' : ''  ]"  :key="item.info.activePreviewId">  <vue-draggable-resizable    :w="item.models.width || 100"    :h="item.models.height || 100"    :x="item.models.x || 0"    :y="item.models.y || 0"    :active="item.info.previewId === activePreviewId"    @dragging="onDrag"    @resizing="onResize"    @activated="      () => {        onCompActivated(item.info.previewId);      }"      :prevent-deactivation="true">    <navigator-line      :x="item.models.x"      :y="item.models.y"      :scale="scale"    />    <div       :is="item.info.name"       :models="item.models"       :extraProps="extraProps">    </div>    </vue-draggable-resizable></div>
复制代码

vue-draggable-resizable (https://npm.taobao.org/package/vue-draggable-resizable) 用于选择组件、缩放组件大小,可参考官方文档。这个组件不支持分组和多选对齐场景,需要定制开发。


navigator-line 显示组件当前的标尺位置。这里要注意避免因为画布缩小导致坐标看不清,除以缩放比例即可。

使用 Vue 动态组件 is (https://cn.vuejs.org/v2/api/#is) 控制组件显示。


数据配置区


数据配置区有 2 种情况:


  • 未选中组件展示页面级配置:大屏宽高、背景色、背景图等

  • 选中组件:展示组件配置信息


实现逻辑:根据当前用户的选择来动态渲染出组件的属性编辑域,并回填属性的初始值,从而达到良好的编辑交互效果。用户拖拽组件时同步更新编辑域中的属性值,在属性编辑域修改属性时通知大屏触发组件的刷新动作,达到实时编辑的效果。


数据配置区界面由组件 Schema 定义,props 定义展示,models 表示默认数据,详细介绍见下面 Schema。


编辑类型由 fileds 里的 type 决定,实现 Input、Select、Image、Border 等各种类型组件,再利用 Vue 的动态组件 is 属性来展示。


数据回传:每个子组件值的修改会通知父组件 <Setting /> 更新回传给父组件 App,这里采用全量回传,避免 App 对 models 查找更新数据。


查看


查看是将数据库里保存的数据,配合组件渲染出来。实现原理是通过页面 id 获取组件、数据渲染。代码如下:


<div class="preview">  <div class="layout">    <div      :class="[        'preview-line',        preComp.info.name + '-' + preComp.info.previewId      ]"      v-for="(preComp, index) in preCompList"      :key="preComp.info.previewId"      :style="formatCompStyle(preComp, index)"    >      <div        :is="preComp.info.name"        :models="preComp.models"        :isPreview="isPreview"        :extraProps="extraProps"></div>    </div>  </div></div>
复制代码

全屏展示


需要注意大屏是全屏展示,根据大屏配置的屏幕宽高、背景图、背景色设置 body 样式,设置 <meta name="viewport" content="width=' + window.screen.width + '"/> viewport 的 width 让屏幕占满全屏,再监听屏幕的变化设置压缩比例。自适应关键代码如下:


// 获取设置的大屏宽高、背景图、背景色if (window.__INITIAL_STATE__) {  const { width, height, backgroundImage, backgroundColor } =        __INITIAL_STATE__.preview.pageConfig.models;  window.scr = {    width: width,    height: height,    backgroundImage: `url(${backgroundImage})`,    backgroundColor: backgroundColor,  };} else {  window.scr = {    width: window.screen.width,    height: window.screen.height,  };}
// 全屏展示function resizeFull() { if (!window.scr.height || !window.scr.width) return resizeFullBak(); var ratioX = $(window).width() / window.scr.width; var ratioY = $(window).height() / window.scr.height; $('body').css({ transform: "scale(" + ratioX + ", " + ratioY + ")", transformOrigin: "left top", backgroundSize: "100% 100%", });}function resizeFullBak() { var ratioX = $(window).width() / $('body').width(); var ratioY = $(window).height() / $('body').height(); $('body').css({ transform: "scale(" + ratioX + ", " + ratioY + ")", transformOrigin: "left top", backgroundSize: "100% " + ratioY * 100 + "%", });}
复制代码

组件设计


组件是整个大屏设计的基础。组件由组件模板来初始化,模板提供了两个主要功能,一是实现一个可开发的简单 Demo,二是提供打包发布功能。


模板代码很简单,通过传入的 props 控制组件的展示和业务逻辑。组件自动安装,这样在异步加载组件的时候页面可以识别组件。重点讲下组件的 Schema 设计。


schema.json


schema.json 是用来定义组件的可编辑项和默认配置。决定组件哪些东西可以配置,配置的形式是什么样子的(Input、Select 等有默认值)。所以 Schema 包含 props 和 models 两个属性。


props: 数组,每个元素是 tab 的一项。info 是 tab 头部信息,fields 是配置项。fields 的 name 对应 models 的属性名,type 决定了配置的类型,title 是中文名。还可以定义其他属性,比如下拉框选择项、数字输入框最大最小值等。


models: 默认数据,props.fileds 里每个 name 的默认值。

下面是一个简单 Schema 的定义:


{  "props": [    {      "info": {        "title": "配置",        "icon": "icon-setting"      },      "fields": [        {          "title": "组件宽度",          "name": "width",          "description": "组件宽度",          "type": "number"        },        {          "title": "组件高度",          "name": "height",          "description": "组件高度",          "type": "number"        },        {          "title": "x轴坐标",          "name": "x",          "description": "组件x轴坐标",          "type": "number"        },        {          "title": "y轴坐标",          "name": "y",          "description": "组件y轴坐标",          "type": "number"        }      ]    }  ],  "models": {    "width": 300,    "height": 200,    "x": 0,    "y": 0  }}
复制代码


碰到的问题

通信

大屏组件之间如何通信?要确保大屏组件可以通信。

采用事件中心来处理组件间的通信。核心代码如下:

// 全局事件中心Vue.prototype.$eventBus = new Vue();// 触发, 在组件内部this.$eventBus.$emit('eventName', '这里传值');// 监听, 获取值this.$eventBus.on('eventName', v => {  console.log(v);})
// 组件通知父组件区划变动或其他变动this.$eventBus.$emit('component__update-extraProps', { dist: '选择的区划' });
复制代码

App 统一管理通信对象 extraProps,以 props 形式注入到每个组件。组件可以监听 extraProps 的属性变化。

// 组件代码{  ...,  props: {    extraProps: {      type: Object,      default: () => {}    }  },  computed: {    dist() {      return (this.extraProps && this.extraProps.dist) || '';    }  },  watch: {    dist(val, oldVal){      // 添加区划改变时获取新数据的逻辑    }  }}
复制代码


权限


大屏数据需要做权限控制,有权限的人才能查看大屏,而鲁班原来页面访问逻辑是没有权限的。实现方案是编辑、预览页面调用的免登接口访问中间 Server,中间 Server 实现登录,去 Server 请求数据。用户的查看页面内嵌鲁班 iframe,该地址由实际服务器提供并带上权限 token。访问该鲁班地址时先去 Server 鉴权,有权限返回大屏页面,否则返回 401。



待优化


Big 处于初级阶段,还有好多地方需要完善:


  • 分组:像 PS、Sketch 里一样分组,方便归类和操作

  • 多选:多选后选择对齐方式。也是方便用户操作

  • 代码优化

  • 体验优化


总结


DT 时代,数据可视化将会越来越重要。相信有越来越多的同学会遇到大屏的场景。通过可视化搭建大屏系统,可以赋能相关的业务方,让非专业人士做出专业的大屏效果,同时满足公司的一些定制化需求。这里做了一个比较浅的大屏构建方案,目前还在开发阶段,希望抛砖引玉,有更多的可视化数据搭建方案分享出来,谢谢阅读。



头图:Unsplash

作者:明明

原文:https://mp.weixin.qq.com/s/j2dx5S2TWXpznfh3zPthYA

原文:可视化搭建数据大屏系统的前端实现

来源:政采云前端团队 - 微信公众号 [ID:Zoo-Team]

转载:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2021-03-17 00:445945

评论 1 条评论

发布
用户头像
感谢分享,推荐一个好用的接口管理工具apipost,支持mac,windows,linux,多个平台。特别方便
2021-09-01 18:02
回复
没有更多了
发现更多内容

使用 Postman 批量发送请求实用教程

Liam

Java 后端 开发 Postman API

java面试题-多线程

程序员小张

语音聊天app源码中,技术性和功能性并存,技术和功能层面的细节考虑有哪些?

山东布谷科技胡月

语音聊天APP源码 语音直播app开发 国际多语言设计app开发 语音社交平台搭建

模块八 消息队列mysql存储表结构设计

家有两宝

#架构训练营

用友BIP助力企业升级数智化底座,实现数智转型

用友BIP

国产替代

【参考设计】100 W USB PD 3.0电源

元器件秋姐

设计 电路 方案 usb 电源

软件测试/测试开发丨Python 面向对象编程思想

测试人

Python 编程 面向对象 软件测试

什么是低代码开发平台?浅谈它的价值

高端章鱼哥

低代码 aPaaS JNPF

【网易云信】直播场景播放侧常见问题分析与实践经验

网易智企

直播 实时音视频 直播推流 音视频技术

9个值得推荐的前端低代码项目!

这我可不懂

前端 低代码 低代码平台 JNPF

简化办公,云上助力!

知者如C

【MySQL技术专题】「问题实战系列」深入探索和分析MySQL数据库的数据备份和恢复实战开发指南(数据恢复补充篇)

洛神灬殇

MySQL 数据库 Binlog 数据库备份和恢复

成都站|阿里云 Serverless 技术实战营邀你来玩!

Serverless Devs

云计算 负载均衡 Serverless 云原生 弹性计算

携手生态共筑数智底座,加速企业数智化转型

用友BIP

数智底座

“数智化供应链“赋能有色企业原料供应链管理优化

用友BIP

冶金

兴业银行携手用友,为企业打造新一代财资管理服务

用友BIP

银行 司库

Python案例实现|爬取租房网站信息

TiAmo

Python 数据分析

五种高级 NodeJS 技术

互联网工科生

node.js nodejs

如何使用 NFTScan SDK 工具构建 NFT Explorer Dapp

NFT Research

NFT\ SDK 教程

OpenMLDB 发布线上到线下数据自动同步工具

第四范式开发者社区

人工智能 机器学习 数据库 开源 特征

得物 Android 包体积资源优化实践

得物技术

前端 用户体验 SEO

如何成为网络安全大牛(黑客)?

网络安全学海

黑客 网络安全 信息安全 计算机 渗透测试

Spring 容器介绍

EquatorCoco

spring spring ioc

点云标注在自动驾驶中有着广泛的应用案例

来自四九城儿

汽车软件的模糊测试

DevOps和数字孪生

软件定义汽车

智能制造之路—从0开始打造一套轻量级MOM平台

EquatorCoco

数字化 智能制造

软件测试/测试开发丨Linux 三剑客与管道使用

测试人

Linux 程序员 软件测试

MQTT 订阅选项的使用

EMQ映云科技

mqtt 订阅选项

【网易云信】直播场景播放侧常见问题分析与实践经验

网易云信

直播 实时音视频 音视频开发 直播推流

打造工业互联网平台,强化“腰部”支撑,助力实现国产替代

用友BIP

国产替代

覆盖全球4亿+用户的大型企业如何构建财务共享中心?

用友BIP

财务共享

可视化搭建数据大屏系统的前端实现_语言 & 开发_政采云前端团队_InfoQ精选文章