普通视图

发现新文章,点击刷新页面。
昨天以前diss带码

datart系列04:基于threejs自定义插件3D-MAP

作者 dumplingbao
2023年1月11日 13:01

概述

datart自定义插件的方式,基于threejs自定义插件3D-MAP。

应用场景

根据经纬度进行的城市数据展示场景,适用数据大屏,3D地图等

验证数据

见插件文件:air_quality.sqlair_quality_sd.sql

前置条件

  1. 三个纬度、一个指标
  2. 三个纬度有顺序要求(1、需要显示的名称,2、经度,3、纬度)

备注:三个维度有顺序要求是为了保证不改动源码扩展插件,动源码有两种解决方式如下:

第一种:增加经度、纬度的维度类型,根据类型判断

第二种:扩展经度、纬度的维度拖入框,类似双Y轴方式

规则设定

  • 地图:地图json文件url地址

  • 基准值:适配不同数据级别展示,推荐设置样本数据最大值

  • 缩放级别:地图缩放等级,适配不同区域展示情况

  • 效果:水波、气泡、热力图

  • 中心坐标:设置中心坐标的经度、纬度,控制地图显示区域

使用说明

插件地址:https://github.com/dumplingbao/datar-plug

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<div id="container"></div>
<script>
let f1 = new dumplingbaoThree.Map(
document.getElementById('container'),
{
data: {
// 城市数据
cityData:
[
{
city: "青岛",
value: 100,
EN: [120.3844, 36.1052],//经纬度
},
{
city: "济南",
value: 89,
EN: [117.00, 36.40],
}
]
}
},
{
// config: {
// mapJson: 'https://geo.datav.aliyun.com/areas_v3/bound/370000_full.json',
// valueMax: 100,
// level: 3,
// longitude: 118.77,
// latitude: 36.40
// },
config: {
// 地图json地址
mapJson: 'https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json',
// 基准值,推进样本数据最大值
valueMax: 100,
// 缩放级别
level: 16,
// 中心坐标经度
longitude: 105.11,
// 中心坐标纬度
latitude: 35.98
},
}
);
</script>

备注:

  1. 根据datart插件使用说明进行操作
  2. 根据需要优化后提交官方自定义插件库,部分规则依据当前使用的版本,命名规则等未按官方提供插件库的方式
  3. 地图json文件推荐,阿里云datav:http://datav.aliyun.com/portal/school/atlas/area_selector
  4. 私有化部署,只需把文件放到私有化文件服务器或者可访问的地址即可
  5. 省份地图,推荐缩放级别在3或4即可,省份中心坐标自行百度
  6. 插件存在已知bug,后续修复,正常使用满足

效果展示

3d-01

3d-02

3d-sd

datart系列03:图表插件开发

作者 dumplingbao
2022年4月15日 08:00

概述

开篇写过,datart借助自定义插件的方式,实现自定义扩展插件,就有了无限的可能。

通过最近一段时间的使用,datart自定义插件的方式同时把原来的不可能或很麻烦的二次开发变成了可能。

本身一些复杂的定制化的需求就需要独立于BI之外去做,借助自定义插件既保留的原来的灵活性,又可以抽离形成标准化,本身BI系统就是希望通过标准化来进行数据的分析展示

示例:库存01

数据结构

1m-1

展示效果

1-01

1-02

示例:库存02

2-01

2-02

示例:库存03

数据结构

3m-1

展示效果

3-01

3-02

datart系列02:图表插件开发作品

作者 dumplingbao
2022年4月5日 11:00

概述

今天整理了两个为未能参赛的作品,个人感觉还是比较好的两个点,就索性整理发出来。

作品:手绘风格(D3)

这个上一篇中说到了,也是时间的问题,未能找到原因,本以为是iframe嵌套导致的,后来官方给了去掉iframe的配置的方法进行了尝试,发现不是这个原因。

其实到现在也没有完全定位不能正常的渲染的原因,今天就换了种实现方式,放弃直接用开源的轮子,直接写源代码到插件里面,发现能够正常展示了,后续在把其它图表的补充完整。效果如下:

xkcd01

xkcd01

xkcd01

作品:3D地图(CesiumJs)

关于Threejs、WebGL、CesiumJs这里不做赘述,虽然CesiumJs受众相对较小,而且偏重GIS,但是利用cesiumjs做数字孪生应该也有很多了,所以就集成到datar插件试一下,而且CesiumJs号称永久开源免费,但是这个完全不在参赛作品计划内,原因很简单,用到了付费插件,虽然费用很低,做项目没有任何问题,但是参赛开源就不好了。但是CesiumJs作为datart插件集成还是很简单的,单纯的3D地球,肯定满足不了实际场景,但是花点实际研究研究API搞点特效出来,还是不难的,而且CesiumJs好用,效果出众,下面就看一下效果:

xkcd01

xkcd01

我的2021年新Mac设置

作者 dumplingbao
2021年11月27日 23:48

看到SHAWN @SWYX WANGMy 2021 New Mac Setup的文章,相同的是都是用Mac作为程序开发,因此借着我的新Mac,我也进行了整理,写下这一份整理笔记。

系统设置

这个根据个人不同的喜好

  • 修复触控板方向:触控板 -> 滚动和缩放 - 自然关闭
  • 禁用 Spotlight 搜索除应用程序和系统首选项之外的所有杂项
  • 禁用询问 Siri
  • 禁用字典查找:触控板 -> 指向和点击 -> 查找和数据检测器关闭
  • 首选项 → 显示文件扩展名
  • 从 程序坞(Dock) 中删除所有内容,除了:Finder、系统偏好设置和垃圾箱
  • 启用三指拖移:辅助功能 -> 指针控制 -> 启用拖移。(备注:启用后原三指操作变为四指)

浏览器设置

Chrome自然必不可少,下载安装即可,设置为默认

扩展程序

终端设置

命令行真的是程序员必备的了,这个终端就很重要了,Mac的终端默认是bash,这个可真是太bash了,连ll命令都不行,当然可以配置。还是不推荐bash(就像window下的cmd,宁愿选择git下的bash),这个确实没法让我们起飞。

备注:bash就是shell一种增强版本,就是经常在sh文件里看到的#! /bin/bash

shell有很多种,常用的基本上就是bashzshfish了,他们的区别无外乎就是命令、格式(包括高亮、特殊格式显示)、提示信息等方面上的区分。

可以先看一下Mac提供了哪些shell(可以直接到bin目录下看),可以通过偏好设置就像修改,也可以直接通过下面的命令设置,设置完成需要重新进入终端

1
2
3
4
5
6
7
8
9
10
# 查看所有的shell
cat /etc/shells
# 查看系统用户默认shell
cat /etc/passwd | grep sh
## 系统默认的终端为bash,切换该终端为zsh
chsh -s /bin/zsh
# 切回默认终端bash
chsh -s /bin/bash
# 切换终端fish
chsh -s /bin/fish

没有需要安装,这里我安装的zsh而且是Oh My Zsh,安装简单,直接看官网。

Oh My Zsh可以设置主题和插件,提示信息非常nice,详细配置不再赘述,我摘了一段和zsh的区别:

1
#  Zsh 是一个shell,就像bash或fish 一样,它解释命令并运行它们。Oh My Zsh 是一个构建在 zsh 之上的框架,其结构允许它拥有插件和主题,并从一开始就提供我们认为最好的设置。您可以在没有 Oh My Zsh 的情况下使用 zsh,但如果您没有 zsh,则无法使用 Oh My Zsh。

如果需要fish的,推荐阮一峰的文章:Fish shell 入门教程

terminal

超级终端(Hyper Terminal

Hyper Terminal,一个通用的串行交互软件,可以通过串口、调制解调器或以太网连接,使用该程序连接到其他计算机、Telnet 站点、公告板系统 (BBS)、联机服务和主机、嵌入式系统等。

超级终端还能对外观进行主题设置并可以安装插件,配置直接通过修改.hyper.js即可。

hyper

环境及应用程序安装

关闭SIP

关闭SIP(SIP 全称为「System Integrity Protection」即「系统完整性保护」)还是有必要的,关闭之后才能修改某些文件的权限,一般建议修改完再打开,长期关闭回更方便,即使有些软件sudo进行安装也可以,还是关闭了吧。

以前的快捷键Command+R进入到恢复模式,M1芯片直接按住电源按钮即可进入。

顶部菜单拉中打开终端,输入:

1
csrutil disable

然后重启,设置权限就可以了

1
2
3
sudo chmod -R 777 目标文件夹
或者
sudo chmod a+w 目标文件夹

Homebrew

安装:

1
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

如果443,修改host文件

1
2
3
sudo vi /etc/hosts
# 加入
199.232.4.133 raw.githubusercontent.com

或者使用国内源

使用国内源:

1
/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"

配置的中科大的资源

jdk

官网下载安装(1.8),默认不需要配置环境变量

maven

官网下载最新版,解压配置环境变量即可

1
2
3
4
 // vi ~/.bash_profile

export MAVEN_HOME=/Users/bao/software/apache-maven-3.8.4
export PATH=$PATH:$MAVEN_HOME/bin

git

1
2
3
4
brew install git
git --version
git config --global user.name "用户名"
git config --global user.email "邮箱"

nodejs

直接安装

1
2
 ~/ brew install node
 ~/ node -v

但是实际工作会涉及到多node版本的问题,建议还是用n或者mvn来管理,这里我们用n,个人感觉好用轻巧

1
2
3
4
5
6
7
8
9
 ~/ brew install n
 ~/ n stable // 安装最新稳定版
 ~/ n 14.17.0
// 历史版本地址:https://nodejs.org/zh-cn/download/releases/
 ~/ n ls // 列出所有版本
node/14.17.0
node/16.13.0
 ~/ n // 切换版本
 ~/ n rm <version> // 删除某个版本

如果已经安装了,node卸载方法

验证

1
2
 ~/ which node
/User/<your's-user-name>/.nvm/versions/node/<latest-node-lts-version>/bin/node

卸载

1
 ~/ rm -rf /usr/local/{bin/{node,npm},lib/node_modules/npm,lib/node,share/man/*/node.*}

IntelliJ IDEA (v2021.2.3)

官网下载,需破解

idea

VSCode

官网下载即可,简单

其它

  • Redis Desktop Manager(需破解)
  • Navicat Premium 15(需破解)
  • UltraEdit(需破解)
  • FinalShell

desk

其它应用

  • CleanMyMac X (电脑清理、破解版)
  • WPS Office
  • 超级右键
  • iShot(截图工具)
  • Typora(Markdown编辑工具)
  • AppDelete(软件卸载、破解版)
  • Photoshop
  • Parallels Desktop(Linux、win11、破解版)
  • MindNode(思维导图)

最后一游

Wonderbox

Wonderbox

小程序:Painter画布

作者 dumplingbao
2021年8月3日 23:37

Painter这个小程序画布组件应该很多人在用,github上超3K的star就已经说明这个组件的强大了。这里我们用这个组件实现短讯(如24小时动态)的分享和海报生成。

效果

p001

图二生成的图片,也是分享出去的效果,可以点击分享跳转到短讯的详情即可,分享到群如下:

p002

介绍

Painter组件地址:https://github.com/Kujiale-Mobile/Painter

可以通过源代码看一下组件的实现方式,其实Painter的readMe里面已经把组件的实现方式描述的很详细了,组件接收json格式,然后通过pen.js(画笔)画出json格式不同类型(文本、图片、矩形、qrcode )的view绘制,这种方式设计巧妙,对于很多复杂的情况需求都能满足。而且代码完善,优化调整也很方便。

Painter提供的工具能够将json数据直接转换效果,方便调试,链接地址:

链接1:https://painterjs.github.io/

链接2:https://lingxiaoyi.github.io/painter-custom-poster/

我们上面短讯的效果,只需利用Painter封装两个组件,一个用于分享,一个用于生成海报,控制两个组件显示隐藏即可。通过按钮传递标题、时间、标签、内容等信息,并通过组件接收,然后拼装json文件传递给Painter组件。

1
2
3
4
5
<!-- 分享绘图组件 -->
<share-box wx:if="{{isCanDraw}}" isCanDraw="{{isCanDraw}}" time="{{timeShare}}" source="{{sourceShare}}" id="{{idShare}}" title="{{titleShare}}" content="{{contentShare}}" bind:close="handleClose" bind:initData="initData" bind:createPoster="createPoster"/>

<!-- 海报组件 -->
<poster-box isPoster="{{isPoster}}" time="{{timeShare}}" source="{{sourceShare}}" id="{{idShare}}" title="{{titleShare}}" content="{{contentShare}}" bind:closePoster="handleClosePoster"/>

此外,我们利用lin-ui实现了日期的吸顶效果(备:lin-ui对于吸顶效果的封装很易用,可以尝试一下)、内容展示的卡片效果,不再赘述,详细实现可直接查看下面的代码地址。

代码

diss

已提交github,扫码关注公众号(diss带码),回复:webview,获得源码github地址

小程序:webview + PDF预览

作者 dumplingbao
2021年7月20日 23:58

一般文件预览除了图片基本主要指office的文件预览,不同文件(word、Excel、pdf)格式差异大,所以很难有共性。相对来说PDF的预览会相对简单一些,而且大都能转换成pdf,我们就已pdf为例。小程序官方未提供,目前能找到和想到的方式,如下:

第一:采用wx.openDocument

1
2
3
4
5
6
7
8
9
10
11
12
wx.downloadFile({
url: 'www.file.com/file.ppt',//可以是后台传过来的路径
success: function(res) {
const filePath = res.tempFilePath
wx.openDocument({
filePath: filePath,
success: function(res) {
//成功
}
})
}
})

效果:

说明:这种实际上是先下载了临时路径,好处是pdf、word、Excel都能预览,坏处是这种方式不一定能接受。

001

第二:webview+第三方pdf库

pdfjs是个很好的pdf预览的js库,可以不用改造直接使用,简单部署个服务,或者通过nginx配置一下即可,这里我们直接通过cdn阿里oss文件服务器来运行

pdfjs获取地址:https://github.com/mozilla/pdf.js

oss服务demo:

1
https://byfile.disscode.cn/pdfjs-2.8/web/viewer.html?file=https://byfile.disscode.cn/blog/2021/wx/pdf/01.pdf

小程序配置就很简单了,就是通过webview的方式调用pdfjs服务,只需传递pdf文件地址即可

1
<web-view src="https://byfile.disscode.cn/pdfjs-2.8/web/viewer.html?file={{url}}"></web-view>

002

备注:PDF.js访问远程服务器(非同域名下)报file origin does not match viewer’s

需要将pdfjs下面的viewer.js中注释掉代码

1
2
3
// if (origin !== viewerOrigin && protocol !== 'blob:') {
// throw new Error('file origin does not match viewer\'s');
// }

第三:延伸markdown文件渲染

markdown格式的内容渲染已有组件可以支持,尝试markdown的文件直接进行渲染,这里直接找到第三方库marked.js进行尝试

github地址:https://github.com/markedjs/marked

同样制作oss服务的demo

1
https://byfile.disscode.cn/marked/marked.html?file=https://byfile.disscode.cn/blog/2021/wx/mk/%E3%80%90BLOG%E3%80%91hexo%E6%90%AD%E5%BB%BAblog%E6%95%99%E7%A8%8B.md

小程序同样是webview的方式:

1
<web-view src="https://byfile.disscode.cn/marked/marked.html?file={{url}}"></web-view>

mk01

但是,markdown采用这种方式直接渲染文件,发现图片、换行等样式渲染还是有问题的,所以期待更多尝试。

备注:测试去掉域名的校验,要么就添加到小程序业务域名里面,否则不能正常访问

第四:代码

diss

已提交github,扫码关注公众号(diss带码),回复:webview,获得源码github地址

小程序:数十年Lite

作者 dumplingbao
2021年7月17日 12:00

概述

端午参加毕业十周年聚会,聚会之前花了几天时间撸了个小程序,聚会结束了,十年也真的过去了。

效果

0102030404060708

组件介绍

ColorUI

很棒的小程序UI,而且很大一个特点是特别的简洁,组件也很完善

github地址:https://github.com/weilanwl/ColorUI/

效果地址:http://demo.color-ui.com/

Painter

这个用来生成图片、海报确实好用

github地址:https://github.com/Kujiale-Mobile/Painter

菊码

ju

代码

diss

已提交github,扫码关注公众号(diss带码),回复:数十年,获得源码github地址

备注:后端采用springboot + MongoDB,源码已去除后端,可以直接运行,数据目前读取的json文件

温馨提示:发布动态(上传图片)功能涉及个人小程序审核就去掉了,但是可以当成后台工具,要么就单独做个后台管理的web端

验证码:五福临门

作者 dumplingbao
2021年3月5日 00:00

一看

验证码这个既熟悉又常用的功能,一提起来你就会想起各种各样的验证码,一个偶然的机会,就冒出来做个验证码,慢慢的就演变成现在的五福临门验证码。先看一下效果图:

bless

由来

  1. 春节前看到一篇关于验证码的文章,动态刷新、滑动验证,这里的动,总感觉没有“动”
  2. 加上之前做的游鱼,就想让它动起来,所以最初就是在滑块验证码的基础上,让滑块在外面游动起来
  3. 后来支付宝集五福,让我突然感觉可以考虑,五个福字随机掉下来一个在外面游动,然后滑动原位置,正好符合春节的气息
  4. 再后来参与了支付宝打印福字的活动,然后就手写了五福,这样不仅是随机五福,还可以随机不同主题的五福了
  5. 春节前开始的,前期做了技术验证,春节陆陆续续进行了实现
  6. 后来找资料做轨迹校验,断断续续,今天暂时把前端部分发出来,后端验证决定后续再补一篇

下面是个设计效果图:

wflm

认知

验证码虽然已经司空见惯了,但是还是想讲一下验证的一些接触,从中也能体会乐趣。

起初进入技术行业,还是一个验证码不流行的阶段,计算机识别技术更是起步,所以扭曲、污染的文字无法辨识,所以最初见到的就是4个字母数字,一条飞线。

01

慢慢的越来越流行,越来越多样,越来越看不懂

02

越来越烧脑,亦或是恶搞

03

新时代的验证码越来越多样,出现了两极分化,一种让你赏心悦目,一种让你抢不到票

yzm

验证码在技术里面或许是小场面,但却蕴藏着大智慧,而且是紧跟时代的产物,根据人们需求的变化而变化,当然破解和识别技术的提升也在嘶声呐喊和“催更”

技术

验证码可以防止:恶意破解密码、刷票、论坛灌水等

  • 软件包:成熟的插件和软件包,直接引入使用就可以了

  • 第三方:网易易盾等,购买按官方文档使用

    网易易盾:https://dun.163.com/

  • 无痕验证:阿里云-人机验证

    https://help.aliyun.com/product/28308.html

    用过阿里云的都知道,阿里云登录输入账号密码就可以了,点击登录也没有多余的操作,以为就没有验证,其实阿里做的是无痕验证,即使没有可视化的验证码出现,其实已经对你登录做了人机的校验了,所以不要以为没有可见的验证码就误以为没有验证。

实现

技术栈:前端nodejs+vue,后端java+redis

滑块验证:vue-drag-drop

游动:animateplus

目前的前端部分演示demo(目前只支持pc端):http://bless.disscode.cn/#/loginSlider

五福临门

一曰寿,二曰富,三曰康宁,四曰攸好德,五曰考终命

五福含意:第一福是“长寿”、第二福是“富贵”、第三福是“康宁”、第四福是“好德”、第五福是“善终”。有人简称为寿富康德善。

开源论坛:社区选择Discourse

作者 dumplingbao
2021年3月2日 23:00

回想以往逛论坛、贴吧的年代,似乎渐行渐远,现在人类追求的多样性超出想象,但论坛并未走下神坛,只是换了一种或者是以多种方式存在。社区、小组、圈子等都有更多的载体和工具,今天就说一下开源论坛discourse。

Discourse应该也已经20多年了,并不新鲜,也是因为平常经常浏览的技术社区用的就是discourse,所以就搭建一下,深入感受一下discourse,以备后用。

Discourse总体下来,觉得挺适合做社区,尤其是技术性比较聚集的论坛

  • 开源论坛
  • 创始人想要让改变十年未变的互联网论坛模样
  • 基于Ruby on Rails 和 Ember.js 开发,数据库使用 PostgreSQL 和 Redis
  • 最大的特点是简洁和专业性,以话题为关系聚集用户

dis

Discourse官网:

搭建步骤

安装git和Docker

1
2
apt-get install git
wget -qO- https://get.docker.io/ | sh

安装Discourse

1
2
3
4
mkdir /var/discourse
git clone https://github.com/discourse/discourse_docker.git /var/discourse
cd /var/discourse
cp samples/standalone.yml containers/app.yml(or ./discourse-setup 初始化)

修改配置文件

1
2
3
4
5
6
7
8
9
vim containers/app.yml

UNICORN_WORKERS(如果是1Gb内存就是2,2GB内存以上就是3-4)
DISCOURSE_DEVELOPER_EMAILS管理员邮箱
DISCOURSE_HOSTNAME 绑定的域名
DISCOURSE_SMTP_ADDRESS是邮局服务器
DISCOURSE_SMTP_PORT是SMTP的端口
DISCOURSE_SMTP_USER_NAME账号
DISCOURSE_SMTP_PASSWORD密码

特别注意的是:端口号465是没有效果的

1
DISCOURSE_SMTP_PORT: 587

以上配置完了,会收不到邮件有两种方式修改

第一种:用官方的工具launcher创建管理员账号

1
2
3
cd /var/discourse
./launcher enter app
rake admin:create
  • 创建管理员账号,按要求输入管理员邮箱和登录密码
  • 登录网站,用刚才创建的账号直接登录。
  • 在settings页面设置notification email为发件邮箱,就是之前配置文件里面写的那个邮箱。
  • 在邮件测试页面发一封测试邮件,应该测试成功了。

第二种:编辑发件邮箱

1
2
3
4
5
vim containers/app.yml
//定位文件底部,打开注释
- exec: rails r "SiteSetting.notification_email='xxx@qq.com'"
//重新build一下
./launcher rebuild app

修改完成后,重新构建

1
./launcher rebuild app

nginx与discourse

discourse配置修改:

1
2
cd /var/discourse
vim containers/app.yml

修改:(设置端口代理)

1
2
expose:
- "9090:80" # http

最后运行

1
./launcher rebuild app

nginx增加配置:

增加discourse.conf即可

添加Github第三方登录

打开Github application,进入Developer applications,新建应用程序

Homepage url为你的discourse地址,authorization callback url为你的discourse地址加上/auth/github/callback,然后复制Client ID和Client Secret,
最后打开discourse,进入管理-设置-登录,找到下图所示三个字段,勾选填入刚才复制的内容

然后确定、完成。

点击=>完成!

常见问题

计算技术论坛关于discourse的问题:https://www.ossez.com/search?q=discourse

其它

体验了一下Discourse的管理界面和可配置的操作,后台支持定制化的配置和插件化,而且确实很简洁,并能够提供对外API,有时间可以继续探究

我的discourse地址:https://lt.disscode.cn/

牛年开篇:网站拜年

作者 dumplingbao
2021年2月24日 23:48

牛年开篇:网站拜年

开启新年第一篇,本应该在春节假期完成,趁着马上元宵节,就以此开篇。

重新调整了一下个人网站,来个新年新气象,也希望牛年牛转乾坤,更上一层楼。

力求简单,做几点要求:

  • 个人网站,我们还是区分一下企业和产品网站
  • 前端展示,先不牵扯后端,当然也是为了快速部署
  • 新年元素、牛元素
  • 兼容手机端

达成几个目的:

  • 迎接新的一年
  • 宣传,似乎这个是必不可少,即使没有什么可宣传的内容
  • github网络的限制,导致博客受限,同时选择了简书,后期考虑通过网站,进而做调整
  • 服务器的充分利用

网站地址:https://disscode.cn

web01

web02

建站方式

  • 服务器:云服务器,扩展性、灵活性高(推荐)

  • 虚拟主机:这个的经济优势很明显

  • 第三方:快捷建站网站

域名

无论何种方式,有个自己的域名这个是最好的、也算是必须的,申请渠道很多,申请一个即可(备注:需要备案)

ssl证书

ssl证书其实是挺贵的,但是可以用免费的,ssl证书其实对于网站来说也是必不可少的,没有证书的网站就感觉别扭

推荐免费证书:

网站代码

技术栈:nodejs + react

找了一些网站,最好选了个开源的网站代码,推荐一下,记得点赞

github地址:https://github.com/ArthurYung/react-my-website

发布

如果是服务器,采用Nginx来部署就很简单了

Davinci-二次开发系列08:mongoDB(JDBC查询)四种解决方案

作者 dumplingbao
2020年8月24日 12:00

​ 关于Davinci使用mongoDB的问题,就一直没有断过。我们不管怎么评价mongoDB,似乎年轻的mongoDB俨然是主流数据库了。而且现在对于BI来说能不能支持主流的NoSQL数据库,已经成为一个很重要的衡量标准。目前BI通过JDBC的方式访问NoSQL数据库还是首选,但是mongo官方未提供JDBC驱动包,这里介绍四种mongo-JDBC查询数据的解决方案:(备注:mongo-JDBC问题不仅限于Davinci,也不限于BI,一些实际应用中也会碰到)

序号方案备注综述
1利用presto连接facebook开源SQL查询引擎优点:开源、免费、兼容性良好
缺点:需要单独部署服务
21、unityjdbc破解版
2、unityjdbc试用版
商业化产品优点:集成简单、不需要单独部署
缺点:收费、_id字段值不显示
试用版本地mongo支持需要解决
破解版只能简单的查询、子查询等有问题,存在问题比较多
3mongo-bi连接器mongo官方优点:官方出品、免费、兼容性极好
缺点:需要单独部署服务
推荐用此方式
4开源手写驱动包开源优点:灵活性可控
缺点:成本高、耗精力

利用presto连接

​ Presto是一个facebook开源的分布式SQL查询引擎,而且支持跨库查询,当然也支持mongoDB,Davinci通过presto做类似的桥接,然后也能实现mongoDB的jdbc查询,如果公司使用presto,采用这种方案也是不错的选择,兼容性可以。

​ 这里我们重点介绍后面两种,没有实际进行尝试,大家可以尝试一下,简单介绍一下步骤:

​ 第一:首先需要安装presto-server服务,看好版本,支持MongoDB的才可以

​ 第二:配置mongodb.properties

1
2
3
connector.name=mongodb
mongodb.seeds=ip:port
mongodb.schema-collection=admin

​ 第三:Davinci配置数据源

jdbc:presto://ip:port/mongodb/test

​ 第四:view实现JDBC查询

select * from mongodb.数据库名.集合

unityjdbc

​ 由于unityjdbc是收费的,这里我们用网上的破解版和试用版都试一下。

官方试用版

​ 第一:试用版,去官网unityjdbc下载JDBC Driver for MongoDB,这里我们用的是``这个版本下载地址:http://www.unityjdbc.com/download.php?type=mongodb

​ 第二:下载下来的UnityJDBC_Trial_Install.jar 需要java -jar安装,安装完获取unityJdbc.jar(或者mongodb_unityjdbc_full.jar这个jar包也可以)

mongo_uj00

​ 第三:mongodb-driver的依赖默认是注释掉的,将注释去掉,并将unityJdbc.jar引入到工程里面或者复制进去,在porm里面引入本地依赖

1
2
3
4
5
6
7
8
9
10
11
12
<!--mongodb -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver</artifactId>
<version>3.6.3</version>
</dependency>
<dependency>
<groupId>unityjdbc</groupId>
<artifactId>unityjdbc</artifactId>
<scope>system</scope>
<systemPath>${project.basedir}/lib/unityjdbc.jar</systemPath>
</dependency>

​ 第四:Davinci配置数据源(强调一下,我用官方的包,连接本地mongo报hostname的错误,就先用官方的测试库)

jdbc:mongo://localhost:27017/数据库

官方测试地址 jdbc:mongo://ds029847.mongolab.com:29847/tpch

mongo-uj01

创建view(_id不能正常显示)

mongo_uj07

创建widget

mongo_uj08

mongo_uj09

子查询

mongo_uj10

关联查询

mongo_uj11

网传破解版

试了一下分享出来的破解版,除去上面的安装步骤,直接引入即可

创建数据源,这个包比试用版好的是本地mongo能直接使用

jdbc:mongo://localhost:27017/数据库

创建view(_id不显示、集合列表不显示)

mongo_uj02

创建widget

mongo_uj03

从错误上来就不能很好的兼容,子查询关联查询更是不能正常使用

mongo-bi连接器

​ mongo官方没有提供mongo的JDBC驱动,但是提供了mongo-bi-connector,允许使用所选的BI工具通过标准SQL查询对MongoDB数据进行可视化。

​ 搜了一下资料,BI Connector 可以使用 SQL 或 ODBC 数据源方式直接访问 MongoDB,MongoDB 早期版本直接使用 Postgresql FDW 来实现 SQL 到 MQL 的转换,后来实现更加轻量级的 mongosqld 来支持 BI 工具的连接。这里我们就尝试一下mongosqld,来验证一下。

下载并安装mongo-bi-connector

​ 官方下载:https://www.mongodb.com/try/download/bi-connector,支持windows、linux版本

​ 默认安装即可

配置文件

​ 默认配置即可,如果有mongo做了限制,或者调整端口,修改mongosqld-config.yml,详细配置看官网

1
2
3
4
5
6
7
8
9
10
11
12
13
net:
bindIp: "127.0.0.1" # To bind to multiple IP addresses
port: 3307
mongodb:
net:
uri: "mongodb://127.0.0.1:27017"
ssl:
enabled: false
auth:
username: xxx
password: xxx
source: xxx
mechanism: SCRAM-SHA-1

启动mongosqld

​ 我使用的windows版本双击mongosqld.exe运行即可

maven引入依赖包

1
2
3
4
5
6
7
8
9
10
11
12
<!-- 这个包必须有 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency>
<!-- 非必须,这个是JDBC认证插件,如果你做测试或者你的mongo本身在裸奔,就没必要了 -->
<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>5.1.42</version>
</dependency>

创建数据源

备注:这里使用mysql即可

mongo-bi01

创建view(_id和集合列表均正常)

mongo-bi02

创建widget

mongo-bi03

mongo-bi04

子查询

mongo-bi05

关联查询

mongo-bi06

开源手写驱动包

​ 这个绝对是一个解决方案,其实工作中就会封装mongo的一些比如关联查询类似的组件,写这个驱动包也未必没有优势,我觉着如果上面的方案兼容sql的场景如果存在问题,那么自己写的驱动包改造就容易的多,第三方的包就没那么好改了。

​ 这里推荐一个mongo的JDBC开源驱动包,如果有自己想写的想法仅供参考。

​ 连接:https://gitee.com/f4haofeng/mongodb-jdbc/tree/master/src/main/java/com/mongodb

综上所述

​ 其实,表格里面已经比较了,根据个人需求选择即可,还是推荐使用mongo官方的BI连接器的方式,虽然我们没有对性能进行比较,但从使用性、兼容性、子查询、关联查询等方面比较,BI连接器的方式完全能够胜任。

交流学习

学习Metabase、Davinci等开源BI,群号:72569367,感兴趣的可以加一下。

Davinci-二次开发系列06:导出excel合并单元格

作者 dumplingbao
2020年5月14日 12:00

前言

​ 系统数据导出excel已经很具普遍性,不单单是BI有这需求,表单性质的数据大都希望直接导出excel,这个需求甚至比邮件接收更加突出。

​ Davinci导出excel有两种方式,都在dashboard页面

  1. 单个widget导出
  2. 整个dashboard导出,多个sheet页,一个sheet页对应一个widget数据

    表格数据

​ Davinci透视驱动和图表驱动下都有表格的功能,表格中维度指标是自动合并的,效果如下:

图表驱动

table-chart

透视驱动

table-pivot

表格导出excel

​ 这里先不考虑图形效果的数据导出,表格数据更希望导出excel是相同的样式,也就是自动合并单元格,现有的表格数据导出效果如下:

图表驱动

table-chart-old

透视驱动

table-pivot-old

图表驱动表格excel自动合并单元格

合并后效果图

图表驱动

table-chart-now

透视驱动

table-pivot-now

了解现有逻辑

1
2
3
4
5
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.9</version>
</dependency>

通过代码和依赖可以看出采用的poi处理导出excel

改造计划

​ 如果通过现有的方式加入合并单元格的逻辑改造有点麻烦,这里我们直接找较完善的poi合并单元格的方法来直接引用并调用,如果有更好的方式可以一起讨论交流,欢迎留言。

​ 参考poi合并单元格:https://www.cnblogs.com/mr-wuxiansheng/p/7930378.html

代码改造

​ 参考上面链接这里直接提供改造后端的代码

新增PoiInfo实体类,严格意义上这应该是DO这样我们放的DTO下面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package edp.davinci.dto.poiDto;
import lombok.Data;
import java.io.Serializable;
/**
* POI Excel报表导出,列合并实体<br>
*/
@Data
public class PoiInfo implements Serializable{
private static final long serialVersionUID = 1L;
private String content;
private String oldContent;
private int rowIndex;
private int cellIndex;
public PoiInfo() {
}
public PoiInfo(String content, String oldContent, int rowIndex,
int cellIndex) {
this.content = content;
this.oldContent = oldContent;
this.rowIndex = rowIndex;
this.cellIndex = cellIndex;
}
@Override
public String toString() {
return "PoiInfo [content=" + content + ", oldContent=" + oldContent
+ ", rowIndex=" + rowIndex + ", cellIndex=" + cellIndex + "]";
}
}

废弃writeLine方法,新增createSheet方法

1
\server\src\main\java\edp\davinci\service\excel\AbstractSheetWriter.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/**
* @param queryColumns 标题集合 queryColumns的长度应该与list中的model的属性个数一致
* @param maps 内容集合
* @param mergeIndex 合并单元格的列
*/
public Boolean createSheet(Sheet sheet,List<QueryColumn> queryColumns, Map<String, List<Map<String, Object>>> maps, int[] mergeIndex){
if (queryColumns.size()==0){
return false;
}
int n = 0;
for(Map.Entry<String, List<Map<String, Object>>> entry : maps.entrySet()){
/*初始化head,填值标题行(第一行)*/
Row row0 = sheet.createRow(0);
for(int i = 0; i<queryColumns.size(); i++){
/*创建单元格,指定类型*/
Cell cell_1 = row0.createCell(i, Cell.CELL_TYPE_STRING);
cell_1.setCellValue(queryColumns.get(i).getName());
}
/*得到当前sheet下的数据集合*/
List<Map<String, Object>> list = entry.getValue();
/*遍历该数据集合*/
List<PoiInfo> poiInfos = new ArrayList();
if(true){
Iterator iterator = list.iterator();
int index = 1;
while (iterator.hasNext()){
Row row = sheet.createRow(index);
/*取得当前这行的map,该map中以key,value的形式存着这一行值*/
Map<String, String> map = (Map<String, String>)iterator.next();
/*循环列数,给当前行塞值*/
for(int i = 0; i<queryColumns.size(); i++){
String old = "";
/*old存的是上一行统一位置的单元的值,第一行是最上一行了,所以从第二行开始记*/
if(index > 1){
old = poiInfos.get(i)==null?"": poiInfos.get(i).getContent();
}
/*循环需要合并的列*/
for(int j = 0; j < mergeIndex.length; j++){
if(index == 1){
/*记录第一行的开始行和开始列*/
PoiInfo poiInfo = new PoiInfo();
poiInfo.setOldContent(String.valueOf(map.get(queryColumns.get(i).getName())));
poiInfo.setContent(String.valueOf(map.get(queryColumns.get(i).getName())));
poiInfo.setRowIndex(1);
poiInfo.setCellIndex(i);
poiInfos.add(poiInfo);
break;
}else if(i > 0 && mergeIndex[j] == i){
/*这边i>0也是因为第一列已经是最前一列了,只能从第二列开始*/
/*当前同一列的内容与上一行同一列不同时,把那以上的合并, 或者在当前元素一样的情况下,前一列的元素并不一样,这种情况也合并*/
/*如果不需要考虑当前行与上一行内容相同,但是它们的前一列内容不一样则不合并的情况,把下面条件中
                  ||poiModels.get(i).getContent().equals(map.get(title[i])) && !poiModels.get(i - 1).getOldContent().equals(map.get(title[i-1]))去掉就行*/
if(!poiInfos.get(i).getContent().equals(String.valueOf(map.get(queryColumns.get(i).getName()))) || poiInfos.get(i).getContent().equals(String.valueOf(map.get(queryColumns.get(i).getName())))
&& !poiInfos.get(i - 1).getOldContent().equals(String.valueOf(map.get(queryColumns.get(i-1).getName())))){
/*当前行的当前列与上一行的当前列的内容不一致时,则把当前行以上的合并*/
CellRangeAddress cra=new CellRangeAddress(poiInfos.get(i).getRowIndex(), index - 1, poiInfos.get(i).getCellIndex(), poiInfos.get(i).getCellIndex());
//在sheet里增加合并单元格
sheet.addMergedRegion(cra);
/*重新记录该列的内容为当前内容,行标记改为当前行标记,列标记则为当前列*/
poiInfos.get(i).setContent(String.valueOf(map.get(queryColumns.get(i).getName())));
poiInfos.get(i).setRowIndex(index);
poiInfos.get(i).setCellIndex(i);
}
}
/*处理第一列的情况*/
if(mergeIndex[j] == i && i == 0 && !poiInfos.get(i).getContent().equals(String.valueOf(map.get(queryColumns.get(i).getName())))){
/*当前行的当前列与上一行的当前列的内容不一致时,则把当前行以上的合并*/
CellRangeAddress cra=new CellRangeAddress(poiInfos.get(i).getRowIndex(), index - 1, poiInfos.get(i).getCellIndex(), poiInfos.get(i).getCellIndex());
//在sheet里增加合并单元格
sheet.addMergedRegion(cra);
/*重新记录该列的内容为当前内容,行标记改为当前行标记*/
poiInfos.get(i).setContent(String.valueOf(map.get(queryColumns.get(i).getName())));
poiInfos.get(i).setRowIndex(index);
poiInfos.get(i).setCellIndex(i);
}

/*最后一行没有后续的行与之比较,所有当到最后一行时则直接合并对应列的相同内容*/
if(mergeIndex[j] == i && index == list.size()){
CellRangeAddress cra=new CellRangeAddress(poiInfos.get(i).getRowIndex(), index, poiInfos.get(i).getCellIndex(), poiInfos.get(i).getCellIndex());
//在sheet里增加合并单元格
sheet.addMergedRegion(cra);
}
}
Cell cell = row.createCell(i, Cell.CELL_TYPE_STRING);
cell.setCellValue(String.valueOf(map.get(queryColumns.get(i).getName())));
/*在每一个单元格处理完成后,把这个单元格内容设置为old内容*/
poiInfos.get(i).setOldContent(old);
}
index++;
}
}
n++;
}
return true;
}

放弃原来template.query 使用lambda表达式的调用方式(注释部分),修改如下

1
\server\src\main\java\edp\davinci\service\excel\SheetWorker.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//            template.query(sql, rs -> {
// Map<String, Object> dataMap = Maps.newHashMap();
// for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
// dataMap.put(SqlUtils.getColumnLabel(queryFromsAndJoins, rs.getMetaData().getColumnLabel(i)), rs.getObject(rs.getMetaData().getColumnLabel(i)));
// }
// writeLine(context, dataMap);
// count.incrementAndGet();
// });

List<Map<String, Object>> list = template.queryForList(sql);
// 获取合并列
List<Integer> listIt = new ArrayList<Integer>();
for (int j = 0; j < context.getQueryColumns().size(); j++) {
QueryColumn queryColumn = context.getQueryColumns().get(j);
if(!queryColumn.getType().equals("value")){
listIt.add(j);
}
}
int[] mergeIndex = new int[listIt.size()];
int i = 0;
for(Integer it: listIt){
mergeIndex[i++] = it.intValue();
}

Map<String, List<Map<String, Object>>> map = new HashMap();
map.put("合并单元格数据", list);
createSheet(context.getSheet(),context.getQueryColumns(),map,mergeIndex);

完成以上配置,效果就有了

存在问题

透视驱动表头样式

​ 目前无法做到透视驱动的表头样式,数据导出excel也仅仅和图表驱动类似的单元格数据的合并。

table-pivot2

表头样式进行分组合并影响导出

​ 表头样式进行分组合并设置,会影响导出,后续再进行处理。

table-merge

图表驱动表格合并存在不合理情形

数据第一层维度数据不同,第二次数据相同合并,似乎不合理,excel做了处理,这样就不一致,如下情况:

table-issue

交流学习

学习Metabase、Davinci等开源BI,群号:72569367,感兴趣的可以加一下。

Davinci-二次开发系列05:echarts-gl map3D扩展

作者 dumplingbao
2020年4月3日 23:00

echarts-gl

​ 介绍一下echarts-glcharts-gl专门为echarts补充了丰富三维可视化组件。这里的gl应该是global的意思,很多地方简写GL,不建议这样写,因为和真实的GL太冲突,更何况最近肖某的事情,和BL有着千丝万缕的关系,所以,就别和GL扯上关系,我们还是写全称echarts-gl

echarts-gl map3D

​ 这次介绍echarts-gl map3D,就是用echarts-gl实现的地图的3D模式,也是在系列03的基础上进行的改造,开启3D,切换地图,效果如下:

echarts-gl

echarts-gl安装

1
cnpm install echarts-gl --save

页面引入

1
import 'echarts/dist/echarts-gl'

特别注意一下:如果集成了百度地图,这个引入不要放入到app.tsx里面,会出现一直加载不完的情况,所以最好放到chart.tsx

控制参数

​ 在样式里面,添加控制参数,开启3D

is3D

render调整

​ 在render下面的map.ts调整图形,主要是series的属性

1
2
map:'' // 注意与echarts.registerMap第一个参数保持一致
type: 'map3D' // 通过type指定必须是map3D,还有一种方式geo3D,见echarts官方实例

完成以上配置,效果就有了

echarts-gl事件存在问题

echarts-gl图表事件一直存在问题,算是个坑,截止目前,我统计了一下官方issue关于事件目前一直open的最少四个,echarts-gl目前维护进度也较慢。

​ 试了几个版本的echarts-gl,发现对于不同的版本:

  • 有版本需要加getZr(),有的版本不需要
  • 有的事件需要加getZr(),有的事件不需要
  • 有的版本获取不到区域名称,只能获取到坐标,有的版本能
  • 有的版本区域域名加了getZr()能获取到,有的不加能获取到,有的都能,有的都不能

​ 我目前使用的版本1.1.1,单击事件不用加getZr(),右键事件需要加,但是右键事件获取不到区域名称,如果发现某个版本单击和右键事件都有,并能获取到取到区域名称,烦请留言告知,在此谢过。

​ 就拿我们用的单击和右键事件来说:

​ 单击事件实现方式:

1
2
3
4
5
6
7
8
// 方式一
myChart.on('click', function (params) {
console.log(params);
});
// 方式二
myChart.getZr().on('click', function (params) {
console.log(params);
});

​ 右键事件

1
2
3
4
5
6
7
8
// 方式一
myChart.on('contextmenu', function (params) {
console.log(params);
});
// 方式二
myChart.getZr().on('contextmenu', function (params) {
console.log(params);
});

几个推荐和注意

echarts-gl地图下钻

​ 如果echarts-gl 地图下钻,一些类似边框、颜色等属性,需要在下钻事件里面重新调整,否则下钻到新的地图属性不能匹配。

echarts-gl map3D组合图形

​ 如果仅仅echarts-gl map3D效果没那么出众,一般都是配合其它图形,在地图上放柱形、雨滴等会更突出3D效果,所以可以进一步扩展。

demo-3D

echarts-gl性能

​ 这里map3D较简单,性能未发现问题,echarts-gl有很多空间性很强的图形,这种图形渲染加载都会比2D慢,所以性能也是需要考虑的,其它3D图形用的维度指标较多,性能有待测试验证。

geo3D和map3d区别

geo3D不支持visualMap,显示3D地理,上面可以加柱状图,各省份数据无法展示。

map3d支持visualMap,可以显示区域数据,不能绘制柱状图,但是也有说可以隐藏一个geo3D来实现,所以待验证,大家可以尝试一下。

交流学习

刚建的群,学习Metabase、Davinci等开源BI,群号:72569367,感兴趣的可以加一下。

Davinci-二次开发系列04:自定义水印扩展

作者 dumplingbao
2020年4月3日 23:00

水印(watermark)

​ 目前来看,水印已经具有很高的附加价值了,钱币的水印能防伪,资料上的水印能宣传,甚至很多对外的产品软件都把去水印当成VIP的一项特殊功能,随着知识产权加强,知识付费的流行,水印也成了防止盗用的一种很重要的手段。

​ Davinci的水印我觉着官方迟早会出,但目前来看短时间出不来,出成什么样子也不确定,所以我们就先制瓜吃瓜。

​ 效果:

watermark

水印制作

自定义水印位置

​ 既然是自定义水印,自然也离不开用户和权限,为了先实现自定义,不考虑复杂因素,自定义水印根据项目划分,支持快捷显示项目名称等,不考虑用户自定义和项目自定义水印同时存在的情况。

​ 在用户界面》》组织》》项目》》设置》》水印设置

水印显示位置

目前来看有这么几个位置:

  • widget编辑区(编辑区理论不需要水印,观点不一)
  • dashboard看板
  • display大屏
  • widget分享面板(官方留了口子,但没有实现完善,暂不考虑)
  • dashboard分享面板
  • display分享面板

widget工作区:

water-edit

dashboard页面:

water-dashboard

display页面:

water-display

水印属性

  • 开启关闭

  • 项目名称

  • 用户名

  • 水印文本(比如“内部资料,严禁外传”这类)

  • 水印时间戳(支持多种日期格式)

  • 水印颜色

备注:未实现上传图片等格式的水印

data

水印编码实现

用户信息获取

​ 登录用户信息获取目前有两种

​ 方式一:

1
2
3
const mapStateToProps = createStructuredSelector({
loginUser: makeSelectLoginUser(),
})

​ 方式二:

1
const loginUser = localStorage.getItem('loginUser')

项目信息获取

1
2
3
const mapStateToProps = createStructuredSelector({
currentProject: makeSelectCurrentProject()
})

后台改造

后台改造比较简单:

第一:project表增加config字段,类型text,注意和json的转换

第二:分享功能增加project信息,用于展示项目名称,因为分享不登录状态即可访问,所以无法显示用户名

前端改造

前端改造难点除代码语法外,

第一:重点还是在用户名称和项目名称获取上

第二:自定义水印在组织里面,项目的获取和值传递

第三:分享功能,项目信息传递

第四:水印组件引入可以放在多个位置,放到widget下面会比较省劲,尤其是要求多个地方都呈现水印

几个推荐和注意

dashboard和display水印问题

​ 第一:看上面的效果图能明显看到水印是最终实在单个widget下面的,而不是在整个面板上的,整体效果就差一些

​ 第二:尤其是大屏这种,可以考虑每个大屏自定义水印,因为大屏有自身特有的组件

导出excel水印

数据导出excel同样需要水印,推荐实现

分享链接的水印

Davinci里面widget、dashboard、display都支持分享,widget不完善,分享不受权限控制,也不是我们正常进入到某个项目里面的操作,而我们的自定义水印是根据项目设定的,所以分享链接需要根据dashboard获取项目信息和水印的配置信息,并传递到widget组件里。

定时任务邮件接收水印

邮件接收报表带水印是非常合理的,根据水印时间戳更是能够准确判断当前报表的出具时间。

交流学习

刚建的群,学习Metabase、Davinci等开源BI,群号:72569367,感兴趣的可以加一下。

Davinci-二次开发系列03:区域地图下钻与选择

作者 dumplingbao
2020年3月28日 12:00

概述

系列02中讲到百度地图扩展,地图应用场景多样,对于BI数据的呈现区域地图(非经纬度坐标)似乎应用更加广泛,这次说一下对于区域地图的几点改造。一个是下钻,一个是指定自定义的区域地图。

地图下钻

层级下钻,没有具体的几级,可以一直下钻并返回,这里做了国家、省份、市、区县、街道的下钻。

drill

指定地图

指定需要展示的地图,并可以钻取和上卷。

switch

s&d

吐槽一下Davinci地图

Davinci 地图目前十分的不友好,不得不吐槽一下:

  • 不能很好的扩展地图

  • 地图数据逻辑,通过地理类型和对照js文件去汇总,这种十分的不灵活

  • 地图真实应用需求类似下钻不能满足

地图改造点

去掉原有的地图类型

​ 原有地图类型:地图、气泡图、热力图、飞行图,

​ 改造后:去掉地图类型

​ 这些需求在区域地图上是有的,官方就是考虑这些类型的实现导致区域地图显得复杂,尤其是飞行图这种实际BI应用场景中较少,而且飞行图是要有起点的,默认指定的第一个为起始点,非配置化,略显鸡肋。我们已经在百度地图扩展里做了一些实现,这里直接去掉原有的地图类型,简化代码,更突出区域地图的功能。

style

数据类型扩展

​ 原类型:地理国家、地理省份、地理城市

​ 扩展后:增加地理区县和地理街道

​ 备注:实际改造了数据组装逻辑之后,类型仅仅是体现特殊性的地理维度,并不是严格的层级区分了,就是说改造之后实际指定的类型不影响数据展示。

dimtype

数据组装逻辑改造

​ 原逻辑:根据配置的地理类型,根据层级对照的js文件进行汇总计算。

​ 改造后:根据实际数据进行自动汇总处理,与类型无关,即相同字段名称的汇总。

datastructure

增加单击下钻右键返回事件

​ 添加单击和右键事件实现下钻返回。

1
2
3
4
5
6
7
8
instance.off('click')
instance.on('click', (params) => {
// 添加单击事件
})

instance.on('contextmenu', (params) => {
// 添加右键事件
})

地图json文件扩展

​ 既然能够指定区域地图,就要有地图的json文件,这里推荐两个免费的json地图地址。

​ 阿里的:http://datav.aliyun.com/tools/atlas/#&lat=33.54139466898275&lng=104.2822265625&zoom=4

​ 个人的:https://gallery.echartsjs.com/editor.html?c=xr1IEt3r4Q 更新很及时,行政区划调整比较及时。

​ 中国闭源软件多,开源软件少,可能一个原因是付费的少,这些作者提供的json文件着实给力,所以建议大家使用之余,能力范围内打赏一下(非广告)。

json

几个推荐和注意

json文件改造自定义上传

​ 可以改造json文件自定义上传,这样用户可以自己上传json文件然后从地图样式里面指定。

json层级建立对照字典表

​ 对于自定义上传的json文件建立层级对照表,源码里面通过js文件对照的,不利于维护。

普通图表下钻功能的影响

​ Davinci dashboard有下钻的功能,并且图表的钻添加了右键事件,所以需要进一步验证是否存在冲突的问题。

交流学习

刚建的群,学习Metabase、Davinci等开源BI,群号:72569367,感兴趣的可以加一下。

❌
❌