Compare commits

..

255 Commits

Author SHA1 Message Date
奔跑的面条
3ac9ffc73c Merge branch 'dev' 2022-11-22 12:44:51 +08:00
奔跑的面条
5ea963fb93 fix: 处理旧数据基础事件报错的问题 2022-11-22 12:42:23 +08:00
奔跑的面条
c420ae467f Merge branch 'dev' 2022-11-21 10:49:25 +08:00
奔跑的面条
be014225c1 fix: 去除页面错误静态数据 2022-11-21 10:49:04 +08:00
奔跑的面条
8334fe5bcc build: 升级版本到 1.1.5 2022-11-19 21:04:53 +08:00
奔跑的面条
f99edce6f4 Merge branch 'dev' 2022-11-19 21:04:32 +08:00
奔跑的面条
936d78975e fix: 解决点击图表分列没反应的bug 2022-11-19 20:37:06 +08:00
奔跑的面条
a25f9bc5a1 !100 胶囊柱图问题 ,滚动排名列表问题
Merge pull request !100 from daidai/dev
2022-11-19 06:03:47 +00:00
刘嘉威
5454f19f3d fix: 滚动排名列表问题当数据量小于等于列表数时,第一条数据会直接不显示 2022-11-18 11:25:41 +08:00
刘嘉威
b95cf946a8 perf: 胶囊图增加cloneDeep防止多个互相影响 2022-11-18 10:16:41 +08:00
刘嘉威
1b9a3f6f5b fix: 胶囊柱图source数量变化页面展示效果数量不变问题 2022-11-18 09:23:37 +08:00
奔跑的面条
d91cd00310 fix: 补充误删的代码 2022-11-17 22:35:49 +08:00
奔跑的面条
e4f821f46d perf: 去除多余代码,优化全局配置页面 2022-11-17 21:39:51 +08:00
奔跑的面条
ed5a452e2f perf: 优化配置页面结构 2022-11-17 00:41:11 +08:00
奔跑的面条
907a0afb77 chore: 优化地址输入框的长度 2022-11-17 00:18:39 +08:00
奔跑的面条
b32c718780 style: 新增注释 2022-11-16 22:55:03 +08:00
潘潘
adbdad1e88 perf: 注释定时同步 2022-11-15 21:42:22 +08:00
潘潘
f8229a0518 perf: 编辑JSON优化 2022-11-15 21:42:09 +08:00
奔跑的面条
48f00e44f6 feat: 新增数据池 hook 2022-11-15 21:25:35 +08:00
奔跑的面条
8c089b800a perf: 修改列表的样式wenti 2022-11-13 21:38:46 +08:00
奔跑的面条
44199fa4c4 feat: 新增图表展示模式切换 2022-11-13 21:28:38 +08:00
奔跑的面条
5e20689356 feat: 新增基础事件功能 2022-11-13 02:36:04 +08:00
奔跑的面条
9a9b752a96 feat: 新增基础事件 2022-11-12 23:03:13 +08:00
奔跑的面条
1ddf056ca6 fix: 修改事件类型错误 2022-11-12 22:03:51 +08:00
奔跑的面条
572ab73c92 perf: 优化事件代码结构 2022-11-12 21:49:04 +08:00
奔跑的面条
afc8f907ce perf: 优化修改json的代码 2022-11-12 17:20:11 +08:00
奔跑的面条
f6bad1513b perf: 优化获取id 的旧代码 2022-11-12 16:16:03 +08:00
奔跑的面条
fce514c490 chore: 转移master-fetch分支获取id函数到dev分支 2022-11-12 16:10:14 +08:00
奔跑的面条
30a9deaee7 fix: 解决部分组件的配置缺失深拷贝的问题 2022-11-12 15:37:41 +08:00
奔跑的面条
f47acca703 update README.md.
Signed-off-by: 奔跑的面条 <1262327911@qq.com>
2022-11-10 10:13:19 +00:00
奔跑的面条
73a6c6b920 update README.md.
Signed-off-by: 奔跑的面条 <1262327911@qq.com>
2022-11-10 10:10:58 +00:00
奔跑的面条
672f7a0a7c Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-11-05 21:46:26 +08:00
奔跑的面条
32762aa8a7 fix: 修改预览页面的报错问题 2022-11-05 21:31:42 +08:00
奔跑的面条
c35dd6fad9 fix: 解决锁定时,修改模块隐藏展示,标尺不会自适应的问题 2022-11-05 21:16:34 +08:00
奔跑的面条
de78fb2149 docs: 新增文档截图 2022-11-05 18:19:33 +08:00
奔跑的面条
8d05953b8b chore: 修改路径地址 2022-11-05 15:45:29 +08:00
奔跑的面条
afed1cb6b3 fix: 处理切换语言,UI框架不会变的问题 2022-11-05 15:23:01 +08:00
奔跑的面条
f6a4e87e05 style: 优化提示文案 2022-11-03 09:27:09 +08:00
奔跑的面条
e36265a2f4 style: 修改 iframe默认地址 2022-11-02 20:03:32 +08:00
奔跑的面条
4a59e69bbe docs: 修改首页地址 2022-11-02 19:46:19 +08:00
奔跑的面条
a442e13a7b feat: 升级版本到1.1.4 2022-11-02 19:05:16 +08:00
奔跑的面条
4d093a4a80 Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-11-02 19:02:38 +08:00
奔跑的面条
3dd94fb408 feat: 新增点击事件案例 2022-11-02 16:35:08 +08:00
奔跑的面条
7e59d8d36c docs: 修改链接地址 2022-11-02 09:57:28 +08:00
奔跑的面条
bb46050bb3 style: 优化代码结构 2022-10-31 09:52:02 +08:00
奔跑的面条
b50620ec2c style: 优化代码结构 2022-10-31 09:30:35 +08:00
奔跑的面条
7bef69af92 style: 修改翻牌器全局引用的目录 2022-10-31 09:29:22 +08:00
奔跑的面条
8241077495 update README.md.
Signed-off-by: 奔跑的面条 <1262327911@qq.com>
2022-10-29 12:09:36 +00:00
奔跑的面条
82b29a2f8b docs: 优化说明文档 2022-10-29 19:57:02 +08:00
奔跑的面条
b789d80f98 fix: 修改主页说明 2022-10-29 19:51:33 +08:00
奔跑的面条
a8c80e2366 docs: 修改主页说明 2022-10-29 19:50:30 +08:00
奔跑的面条
ae8fcd640b perf: 优化 iframe 组件 2022-10-29 19:10:47 +08:00
奔跑的面条
455f3ff09a perf: 优化iframe 2022-10-29 17:55:14 +08:00
奔跑的面条
e4afaded36 !92 新增Iframe组件
Merge pull request !92 from 自由/dev-wu-20221027
2022-10-29 09:27:15 +00:00
奔跑的面条
a10409f829 perf: 优化 mock 列表的快捷写法 2022-10-29 17:15:14 +08:00
奔跑的面条
112138fdc5 perf: 优化高德地图 2022-10-29 17:14:47 +08:00
wuyuting1
73e5ca59df feat: 增加iframe组件 2022-10-28 11:38:39 +08:00
奔跑的面条
38f92febb7 feat: 优化胶囊图,新增配置 2022-10-28 11:13:52 +08:00
奔跑的面条
cd6f1e0438 perf: 优化版权声明的UI 2022-10-28 09:49:35 +08:00
奔跑的面条
1d73f71aaf fix: 优化在线编辑JSON的代码和交互 2022-10-27 21:10:58 +08:00
奔跑的面条
e4e77cd141 !91 增加胶囊柱图
Merge pull request !91 from daidai/dev
2022-10-27 12:30:58 +00:00
奔跑的面条
e0e7270623 !87 feat:新增高德地图
Merge pull request !87 from jiangcheng/dev
2022-10-27 12:27:22 +00:00
奔跑的面条
885c376e2a !85 feat: 新增JSON编辑页面 以及 保存跨窗口同步视图更新
Merge pull request !85 from 潘潘/dev
2022-10-27 12:27:01 +00:00
奔跑的面条
2845e9829d fix: 修改工作台不去除监听的问题 2022-10-27 19:38:58 +08:00
刘嘉威
36b82de301 style: remove console.log 2022-10-27 11:41:53 +08:00
刘嘉威
a2ac99e7cb feat: 胶囊柱图增加mock数据源 2022-10-27 11:40:53 +08:00
刘嘉威
d037e1ff36 feat: 增加胶囊柱图 2022-10-27 11:01:41 +08:00
潘潘
9d4424356d feat: 定时、失焦、保存同步 2022-10-26 12:10:19 +08:00
奔跑的面条
f087a0766b !89 解决编译混淆的警告和i18n的控制台警告
Merge pull request !89 from unidmr/dev
2022-10-25 04:50:31 +00:00
xushihao
0bb7400755 chore:解决控制台关于vue-i18n的告警 2022-10-25 09:55:18 +08:00
xushihao
6460c475b6 build:用terser混淆时会出现警告,需要配置minify为terser,或者用esbuild 2022-10-25 09:52:12 +08:00
蒋承
f8b645f867 feat: 添加点标记 2022-10-24 10:20:06 +08:00
panjianhua
834b330bc8 style: 修改UI 2022-10-22 21:16:37 +08:00
潘潘
a4b4ce57bd feat: 预览页\JSON编辑页\图表页保存同步更新 2022-10-20 15:38:15 +08:00
蒋承
ff7a0830d0 feat: 高德地图新增属性 2022-10-19 10:21:48 +08:00
蒋承
ff43d0c2d8 feat: 新增高德地图 2022-10-19 09:29:50 +08:00
奔跑的面条
bad4b5d7b3 fix: 去除单独颜色设置 2022-10-18 21:23:18 +08:00
奔跑的面条
adaf30dd3b perf: 优化弹幕图片 2022-10-18 21:00:41 +08:00
奔跑的面条
c0fc84061e !81 feat:新增弹幕文字组件
Merge pull request !81 from jiangcheng/dev
2022-10-18 12:58:35 +00:00
蒋承
b84ad0f598 feat: 弹幕文字 2022-10-18 11:24:57 +08:00
奔跑的面条
aa0569ef4b fix: 修改列表图偏移的问题 2022-10-17 09:42:56 +08:00
奔跑的面条
b88d90cb80 perf: 优化文案描述 2022-10-17 09:26:19 +08:00
奔跑的面条
c055129309 perf: 优化标题 2022-10-16 20:49:48 +08:00
奔跑的面条
30351cecb5 feat: 新增案例说明 2022-10-16 20:46:01 +08:00
奔跑的面条
4f6757fff2 perf: 优化事件编辑页面 2022-10-16 16:27:15 +08:00
奔跑的面条
284fdb8e05 perf: 修改事件文件位置,修改图标 2022-10-16 10:41:12 +08:00
奔跑的面条
738bcae563 fix: 去除 setPosition 2022-10-16 10:29:01 +08:00
奔跑的面条
987a68a6d1 !76 新增组件生命周期事件
Merge pull request !76 from 潘潘/dev
2022-10-16 02:28:09 +00:00
奔跑的面条
bdbdd37789 build: 升级版本到1.1.3 2022-10-15 17:17:34 +08:00
奔跑的面条
c8fb5b9152 Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-10-15 17:12:13 +08:00
奔跑的面条
59cb5d609d perf: 去除grid多余配置,添加散点图、热力图的grid 2022-10-15 16:51:16 +08:00
奔跑的面条
4add9ce4c6 !80 feat: 折线图和柱状图添加网格配置,xy轴标签偏移量
Merge pull request !80 from jiangcheng/dev
2022-10-15 02:09:47 +00:00
蒋承
c75d9f7a59 feat: x,y轴标签偏移量 2022-10-14 17:09:26 +08:00
蒋承
2d94085c54 feat: 网格容器配置 2022-10-14 16:50:06 +08:00
蒋承
2a6e5915f5 feat: 柱状图折线图添加网格配置 2022-10-14 16:46:41 +08:00
潘潘
656532e43d Merge branch 'dev' of gitee.com:dromara/go-view into dev
Signed-off-by: 潘潘 <97274247@qq.com>
2022-10-14 07:01:47 +00:00
奔跑的面条
d835a904c9 fix: 解决导入时顺序不对的问题 2022-10-14 14:33:14 +08:00
奔跑的面条
a5bf0e9f6a perf: 优化导入失败提示 2022-10-14 09:37:31 +08:00
奔跑的面条
7e3efa46ee perf: 优化亮色模式图层提示 2022-10-14 09:37:12 +08:00
奔跑的面条
ce68910e48 fix: 解决 分组复制 id 会重复的问题 2022-10-13 21:10:32 +08:00
奔跑的面条
6dce639a0e perf: 优化按下文案tishi 2022-10-13 20:48:12 +08:00
奔跑的面条
c738103fec perf: 优化键盘按下的提示 2022-10-13 20:45:51 +08:00
奔跑的面条
801f298448 perf: 优化报错信息捕获,去除setPosition自带函数 2022-10-13 20:21:33 +08:00
奔跑的面条
e08a7723b6 perf: 优化格式 2022-10-13 19:52:41 +08:00
奔跑的面条
166b5b98e8 !78 feat: 过滤方法增加api返回顶级对象作为参数,增强过滤器兼容性
Merge pull request !78 from dodu/dev-api-filter
2022-10-13 10:05:39 +00:00
奔跑的面条
07e56631da perf: 优化异常处理 2022-10-12 21:57:30 +08:00
奔跑的面条
1435789a6c !77 feat: 折线图和柱状图配置label选项
Merge pull request !77 from jiangcheng/dev
2022-10-12 13:35:36 +00:00
奔跑的面条
7c5fa7610d fix: 新增三维组件限制 2022-10-12 21:30:08 +08:00
奔跑的面条
084e680e12 perf: 优化三维地球内存泄漏 2022-10-12 21:15:08 +08:00
奔跑的面条
380a6b95b7 feat: 新增三维地球 2022-10-12 21:08:24 +08:00
tnt group
9467feff23 fix: 移除开发标记 2022-10-12 16:50:25 +08:00
tnt group
a6f4267915 feat: 过滤方法增加api返回顶级对象作为参数,增强过滤器兼容性 2022-10-12 16:41:49 +08:00
jiangcheng
cfe9efd4dd Merge branch 'dev' of https://gitee.com/jiang_cheng_1/go-view into dev 2022-10-12 11:31:05 +08:00
jiangcheng
971b03620a fix: 格式问题 2022-10-12 11:30:54 +08:00
潘潘
92339dae28 feat: 组件生命周期事件 2022-10-11 18:31:29 +08:00
奔跑的面条
c84f6d9c33 perf: 优化补丁的判单方式 2022-10-11 16:02:43 +08:00
奔跑的面条
e187c012cc perf: 修改ctrl默认值 2022-10-11 15:15:03 +08:00
奔跑的面条
af1c280f28 perf: 优化 ctrl 监听 2022-10-10 18:47:07 +08:00
奔跑的面条
aef155e039 fix: 修复组件导入数据错乱的问题 2022-10-09 16:37:30 +08:00
蒋承
016e48cc69 feat: 折线图和柱状图配置label 2022-10-09 16:04:29 +08:00
蒋承
6dcd39983f feat: 更新 2022-10-09 15:50:46 +08:00
蒋承
b055b6c511 Merge branch 'dev' of https://gitee.com/jiang_cheng_1/go-view into dev 2022-10-09 15:36:00 +08:00
奔跑的面条
293259a97d !72 在框选结束时,勿操作鼠标往选框内移动,选框不消失
Merge pull request !72 from 关宏荣/dev
2022-10-09 07:33:45 +00:00
奔跑的面条
7584c79519 build: 新增小版本1.1.11 2022-10-09 15:25:40 +08:00
奔跑的面条
d9bb0bf61d build: 修改版本1.1.1 2022-10-09 15:24:34 +08:00
奔跑的面条
cbb401840c fix: 修复导入组件数据会错乱的问题 2022-10-09 15:23:51 +08:00
蒋承
1d18c86dc7 feat: 动态数据维度不同,导致整合维度bug 2022-10-09 13:58:29 +08:00
hguan
f8b8624244 fix: 🐛 修复框选选框不消失问题
鼠标抬起的时候,结束节流函数
2022-10-09 10:34:09 +08:00
奔跑的面条
443573455b Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-10-09 09:28:38 +08:00
奔跑的面条
785a4d97f7 build: 升级naive-ui到2.33.4 2022-10-09 09:27:51 +08:00
奔跑的面条
d811ab7dfa build: 撤回错误版本号 2022-10-08 21:12:58 +08:00
奔跑的面条
5f79ab6e6d build: 升级版本到1.1.2 2022-10-08 21:12:27 +08:00
奔跑的面条
502edbca5d Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-10-08 21:05:48 +08:00
奔跑的面条
9da073e838 style: 修改错误注释 2022-10-08 21:05:32 +08:00
奔跑的面条
1a04267cb7 build: 升级版本到1.1.1 2022-10-08 20:59:55 +08:00
奔跑的面条
9c2c1bdfa1 Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-10-08 20:59:25 +08:00
奔跑的面条
1764c0de08 perf: 优化混合提示的展示方式 2022-10-08 20:58:48 +08:00
奔跑的面条
79fd809993 style: 优化代码 2022-10-08 20:49:08 +08:00
奔跑的面条
d3a0d36c92 fix: 解决右键解锁无法使用的问题 2022-10-08 20:48:52 +08:00
奔跑的面条
0841e632c2 perf: 优化首页样式 2022-10-08 20:32:36 +08:00
奔跑的面条
d8f8ef032d !68 feat: 组件公共属性滤镜中增添混合模式设置
Merge pull request !68 from dodu/dev-commet
2022-10-08 11:38:12 +00:00
奔跑的面条
b7f84dbb0d !71 地图南海群岛bug
Merge pull request !71 from daidai/dev
2022-10-08 09:46:13 +00:00
刘嘉威
17f1a7ce9d fix: 解决地图编辑不显示南海群岛 预览时仍显示 2022-10-08 14:52:56 +08:00
tnt group
ca69331286 fix: 修复分组未应用混合模式 2022-10-08 12:56:07 +08:00
tnt group
8258ad21d7 fix: 修复画布不使用旋转属性配置 2022-10-08 11:54:54 +08:00
tnt group
2a129d0ee3 fix: 修复因画布未默认设置背景色或背景图片导致预览时的混合状态未生效问题 2022-10-08 11:44:56 +08:00
tnt group
e391520ce3 fix: 替换 BLEND_MODE 2022-10-08 11:43:38 +08:00
奔跑的面条
3e8329c31f perf: 优化超时时间 2022-10-08 09:17:42 +08:00
奔跑的面条
19d7b1be77 fix: 优化Naive编译之后页面不对的bug 2022-10-07 18:56:31 +08:00
tnt group
ee8a05b6e6 feat: 组件公共属性滤镜中增添混合模式设置 2022-10-05 21:56:43 +08:00
奔跑的面条
111f5bdcfb fix: 修改切换轮播表格配置不会变的问题 2022-10-05 17:08:52 +08:00
奔跑的面条
4c1b955bd5 !67 feat: 新增 数字翻牌 和 倒计时(翻牌效果) 组件
Merge pull request !67 from dodu/dev-countdown
2022-10-03 08:40:10 +00:00
tnt group
ad6614e338 fix: 修复倒计时组件 Extraneous non-props attributes 问题 2022-10-02 23:06:23 +08:00
奔跑的面条
57c730a7eb perf: 修改图层类型图标 2022-10-02 20:28:21 +08:00
tnt group
e1ec5d15ee fix: 移除多余注释 2022-10-01 22:50:17 +08:00
tnt group
4496e17d45 fix: 修复 naive-ui 引用版本造成倒计时异常 2022-10-01 22:49:27 +08:00
奔跑的面条
28668f2acb feat: 新增图层展示类型持久化存储 2022-10-01 21:10:06 +08:00
奔跑的面条
87440362ac perf: 修改颜色默认展示,格式化代码 2022-10-01 20:34:24 +08:00
奔跑的面条
f470817c01 fix: 解决前进撤回中锁定/隐藏无法正常实现的问题 2022-10-01 19:59:57 +08:00
奔跑的面条
4d9330983a style: 去除多余代码 2022-10-01 17:27:06 +08:00
奔跑的面条
edecfc7116 perf: 去除屏幕大小处理 2022-10-01 17:26:52 +08:00
tnt group
d4f3b97b3d style: 调整缩略图和默认颜色配置 2022-10-01 10:27:11 +08:00
tnt group
48d17f9244 style: 调整翻牌默认大小 2022-09-30 22:25:08 +08:00
奔跑的面条
a96fa8f4b7 perf: 无数据时候的禁止下载和导入 2022-09-30 16:21:52 +08:00
奔跑的面条
a81c6e1756 perf: 优化部分组件接口返回错误数据,页面会卡死的问题 2022-09-30 16:03:35 +08:00
奔跑的面条
b3255ab28b fix: 修改饼图环形数值不出现的问题 2022-09-30 15:43:58 +08:00
tnt group
75b5103637 style: 优化调整属性分类 2022-09-30 12:18:46 +08:00
tnt group
ddee71fc0d feat: 加入缩略图,完成倒计时功能 2022-09-30 11:39:41 +08:00
tnt group
18ea1a575c feat: 完成数字翻牌组件 2022-09-30 09:22:56 +08:00
tnt group
3e4cc376f9 chore: 基本完成翻牌器 2022-09-30 01:29:48 +08:00
tnt group
f17c22793b fix: 修复中 2022-09-29 19:25:29 +08:00
tnt group
965f734618 perf: 优化翻牌组件 2022-09-29 19:11:54 +08:00
奔跑的面条
fc1258319e !66 fix: 丰富地图配置
Merge pull request !66 from jiangcheng/dev
2022-09-29 09:19:32 +00:00
蒋承
7d17e2b332 feat: 丰富地图配置 2022-09-29 15:23:32 +08:00
tnt group
5a79fc4f2d chore: 调整倒计时组件 2022-09-29 15:21:22 +08:00
tnt group
db8fd7582b fix: 引入 naiveui NCountdown 组件 2022-09-29 15:21:04 +08:00
tnt group
daa6458a26 fix: 调整翻牌器样式控制 2022-09-29 15:20:23 +08:00
奔跑的面条
b6ac93ae63 !64 fix: 修复隐藏组件预览状态下的异常
Merge pull request !64 from dodu/dev-commet
2022-09-29 06:59:34 +00:00
蒋承
87e7c4bee2 feat: 丰富地图配置 2022-09-29 12:37:19 +08:00
tnt group
4adc46dd79 fix: 调整预览状态下控制状态样式 2022-09-29 11:35:35 +08:00
奔跑的面条
73f6d6a622 feat: 新增锁定/隐藏快捷键处理 2022-09-29 10:47:07 +08:00
tnt group
b98c3166f2 feat: 增加倒计时组件(测试中) 2022-09-29 10:34:29 +08:00
tnt group
b7503a841a feat: 增加通用翻牌器组件 2022-09-29 10:32:17 +08:00
奔跑的面条
0eb3123848 style: 优化代码 2022-09-29 10:10:54 +08:00
奔跑的面条
a637cd783c perf: 优化层级展示, 优化失焦隐藏代码 2022-09-29 09:55:11 +08:00
奔跑的面条
8530e9bc5e perf: 优化层级UI展示 2022-09-29 09:12:05 +08:00
tnt group
f18c05519d fix: 修复隐藏组件预览状态下的异常 2022-09-28 22:16:08 +08:00
奔跑的面条
cbeddb2460 feat: 新增锁定和隐藏失焦 2022-09-28 21:39:31 +08:00
奔跑的面条
be84e64f00 perf: 优化层级的 UI 样式,支持点击图标完成功能 2022-09-28 21:31:41 +08:00
奔跑的面条
34210104d4 !63 feat: 增加图层隐藏锁定功能,图层列表模式控制
Merge pull request !63 from dodu/dev-layers
2022-09-28 13:30:35 +00:00
tnt group
035586c9ef feat: 隐藏锁定操作,支持历史记录回退和前进 2022-09-28 18:43:55 +08:00
tnt group
7f52ef9843 feat: 锁定组件不能选中和拖动 2022-09-28 17:51:59 +08:00
tnt group
ca9b33da88 feat: 锁定和隐藏组件不能被框选 2022-09-28 17:38:15 +08:00
tnt group
c7f64ceb00 feat: 增加 锁定组件 hover 和 select 样式控制 2022-09-28 17:37:09 +08:00
tnt group
11d4f86551 fix: 隐藏后,立即取消选中组件 2022-09-28 17:34:11 +08:00
tnt group
00aaf3427a feat: 增加右键菜单功能及处理逻辑 2022-09-28 16:47:12 +08:00
tnt group
3e72a0e440 chore: 完成锁定及隐藏,列表方式功能占位 2022-09-28 11:21:29 +08:00
奔跑的面条
72e93f3768 Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-09-27 20:16:07 +08:00
tnt group
0a1023f795 feat: 添加图层模式控制选项 2022-09-27 20:14:00 +08:00
奔跑的面条
71471bac27 perf: 去除不生效的配置代码 2022-09-27 20:08:43 +08:00
奔跑的面条
972c92519c perf: 优化性能,去除组件中多余注册内容 2022-09-27 20:02:35 +08:00
奔跑的面条
617b940d64 !62 fix: 文本组件新增字体加粗选项
Merge pull request !62 from jiangcheng/dev
2022-09-27 03:32:12 +00:00
蒋承
8d36a857eb feat: 新增文本字体加粗 2022-09-27 10:56:26 +08:00
奔跑的面条
59ff14aec4 perf: 打印错误ri'zrizhi 2022-09-27 10:18:20 +08:00
奔跑的面条
3c39d5db9d Merge branch 'dev' of https://gitee.com/MTrun/go-view into dev 2022-09-27 10:03:32 +08:00
奔跑的面条
3980cc584f fix: 处理文字预览不更新的问题 2022-09-27 10:01:43 +08:00
奔跑的面条
2167525312 !61 fix: 修复文本设置链接时,字体样式丢失问题,并增加水平对齐配置
Merge pull request !61 from dodu/dev-commet
2022-09-27 01:46:33 +00:00
tnt group
e724822198 fix: 修复文本设置链接时,字体样式丢失问题,并增加水平对齐配置 2022-09-27 08:56:49 +08:00
奔跑的面条
0d1abd00a1 feat: 新增基础树图 2022-09-26 21:18:01 +08:00
奔跑的面条
62aec195ea !60 饼图新增类型可修改
Merge pull request !60 from jiangcheng/dev
2022-09-26 12:38:22 +00:00
奔跑的面条
9692945716 perf: 优化 lock 2022-09-26 20:32:27 +08:00
奔跑的面条
b8dab8c87d !59 feat: 新增 标题装饰 和 时钟 组件
Merge pull request !59 from dodu/dev-clock
2022-09-26 12:25:09 +00:00
奔跑的面条
a6646be66b perf: 词云优化 2022-09-26 20:00:39 +08:00
奔跑的面条
8cfb54aab1 !57 feat: 添加词云组件
Merge pull request !57 from dodu/dev-commet
2022-09-26 11:59:53 +00:00
奔跑的面条
960f3aa3cf perf: 去除组件默认滤镜和变换,避免模糊问题 2022-09-26 19:40:46 +08:00
蒋承
43f35de27a feat: 饼图新增类型 2022-09-26 17:34:33 +08:00
tnt group
d39ce294b8 perf: 强化chartConfig类型 2022-09-26 17:12:16 +08:00
tnt group
e7349bfae9 perf: 优化时钟,移除无用元素 2022-09-26 17:07:12 +08:00
tnt group
ad1ff249aa perf: 调整装饰3的默认大小 2022-09-26 16:44:19 +08:00
tnt group
3fed2bb5e0 feat: 新增装饰6组件 2022-09-26 16:44:02 +08:00
tnt group
67995ac461 feat: 新增 clock 小组件 2022-09-26 15:00:47 +08:00
蒋承
39d9aa1896 feat: 饼图类型新增可选 2022-09-26 11:17:00 +08:00
tnt group
895fd25627 perf: 移除文件内eslint注释 2022-09-25 22:18:42 +08:00
tnt group
7582cac69a fix: 修复合并时遗漏的冲突 2022-09-25 22:10:42 +08:00
tnt group
790917eaf2 Merge branch 'dev-wordcloud' into dev-commet 2022-09-25 22:06:29 +08:00
奔跑的面条
18d83f161e !54 fix: 添加lint规则运行脚本,修复lint错误
Merge pull request !54 from dodu/dev-lint-commet
2022-09-25 10:47:34 +00:00
奔跑的面条
42e9e5edce perf: 优化新地图组件 2022-09-25 17:48:51 +08:00
奔跑的面条
31450e0eac !56 新增可选省份地图组件
Merge pull request !56 from daidai/dev
2022-09-25 09:40:37 +00:00
daidai
34d799049d perf: 可选省份地图组件异步加载geojson 2022-09-24 18:54:05 +08:00
奔跑的面条
92bf26ced5 !51 1、接口请求参数js动态获取
Merge pull request !51 from 潘潘/dev
2022-09-22 11:47:00 +00:00
奔跑的面条
6214c17903 perf: 优化视频组件 2022-09-22 19:38:35 +08:00
奔跑的面条
f1e801340f !50 feat: 新增视频组件
Merge pull request !50 from dodu/dev-video
2022-09-22 11:30:40 +00:00
奔跑的面条
4105883ab6 feat: 新增文本跳转功能 2022-09-22 19:17:26 +08:00
奔跑的面条
feb39bde44 !52 文本组件添加链接功能
Merge pull request !52 from 自由/wu
2022-09-22 11:16:25 +00:00
刘嘉威
ae4ae074d8 feat: 增加可选省份地图(异步会有问题) 2022-09-22 17:16:54 +08:00
刘嘉威
2ed1b4bf23 feat: 增加可选省份地图 2022-09-22 17:09:26 +08:00
奔跑的面条
e6f2066d42 Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-09-22 14:15:00 +08:00
奔跑的面条
e4ed2392bb build: 修改依赖 2022-09-22 14:13:14 +08:00
tnt group
ae32b9838b Merge branch 'dev-lint' into dev-lint-commet 2022-09-22 10:08:25 +08:00
tnt group
f126fc3d04 fix: 修复默认值冲突,导致旋转属性不生效的问题 2022-09-22 09:27:06 +08:00
tnt group
3ac03973fb fix: 修复自定义属性异常 2022-09-22 09:20:36 +08:00
tnt group
96384d7b39 fix: 增加 mock api,修复预览模式下动态数据更新问题 2022-09-22 09:01:19 +08:00
tnt group
20f720bf27 feat: 初步添加词云组件 2022-09-22 01:01:54 +08:00
奔跑的面条
2812c39524 Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-09-21 19:54:29 +08:00
奔跑的面条
642de9a78c perf: 去除多余图片,修改展示图 2022-09-21 19:46:02 +08:00
wuyuting1
b8a1fd904b feat: 文字组件添加链接功能 2022-09-21 17:27:50 +08:00
wuyuting1
31c63130d6 feat: text组件增加点击链接弹框 2022-09-20 17:51:41 +08:00
panjianhua
6a7c2bca9a feat: 请求参数动态配置 2022-09-19 23:26:14 +08:00
tnt group
9bdf42a057 fix: 去掉示例资源,默认使用本地资源,增加属性 2022-09-19 17:43:15 +08:00
tnt group
58033530c1 fix: 修复使用视频组件时保存画板缩略图的异常 2022-09-19 16:12:35 +08:00
tnt group
fa0c570f90 fix: 修复预览模式下组件的混合模式 2022-09-19 12:33:14 +08:00
tnt group
73bb93f166 fix: 完成视频组件,并支持属性实时控制video状态 2022-09-19 12:32:27 +08:00
tnt group
25077b91ca feat: 新增视频组件(支持混合模式视频背景透明) 2022-09-18 13:07:44 +08:00
tnt group
d37034cb52 Merge branch 'dev-commet' into dev-lint 2022-09-16 12:55:07 +08:00
tnt group
810f4d8e6d fix: 添加lint规则运行脚本,修复lint错误 2022-09-16 12:26:12 +08:00
350 changed files with 10747 additions and 35770 deletions

View File

@@ -20,6 +20,11 @@ module.exports = {
extends: ['plugin:vue/vue3-essential', 'eslint:recommended'],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-unused-vars': 'off',
'vue/no-unused-vars': 'off',
'vue/multi-word-component-names': 'off',
'vue/valid-template-root': 'off',
'vue/no-mutating-props': 'off'
}
}

View File

@@ -1,30 +1,34 @@
## 总览
![logo](readme/logo-t-y.png)
<p align="center">
<img src="readme/logo-t-y.png" alt="go-view" />
</p>
GoView 是一个高效的拖拽式低代码数据可视化开发平台,将图表或页面元素封装为基础组件,无需编写代码即可制作数据大屏,减少心智负担。
<h4 align="center">开源、精美、便捷的「数据可视化」低代码开发平台</h4>
### 😶 **前端** 分支: **`master`**
#### 😶 **前端** 分支: **`master`**
### 👻 携带 **后端** 请求分支: **`master-fetch`**
#### 👻 携带 **后端** 请求分支: **`master-fetch`**
### 📚 GoView **文档** 地址:[http://www.mtruning.club:81/](http://www.mtruning.club:81/)
#### 📚 GoView **文档** 地址:[https://www.mtruning.club/](https://www.mtruning.club/)
项目纯前端-Demo 地址:[https://www.mtruning.club](https://www.mtruning.club)
项目纯前端-Demo 地址:[https://vue.mtruning.club/](https://vue.mtruning.club/)
项目带后端-Demo 地址:[后端 Demo 地址](http://1.117.240.165:8080/goview/#/login)
文档-在线地址:[http://www.mtruning.club:81/](http://www.mtruning.club:81/)
项目带后端-Demo 地址:[https://demo.mtruning.club/](https://demo.mtruning.club/)
文档-源码地址:[https://gitee.com/MTrun/go-view-doc](https://gitee.com/MTrun/go-view-doc)
### 🤯 后端项目
#### 🤯 后端项目看这里!
后端项目gitee地址[https://gitee.com/MTrun/go-view-serve](https://gitee.com/MTrun/go-view-serve)
后端项目 gitee 地址:[https://gitee.com/MTrun/go-view-serve](https://gitee.com/MTrun/go-view-serve)
接口说明地址:[https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb](https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb)
技术点
其它后端方案地址
- 【.NET】[https://gitee.com/sun_xiang_yu/go-view-dotnet](https://gitee.com/sun_xiang_yu/go-view-dotnet)
#### 整体介绍
- 框架:基于 `Vue3` 框架编写,使用 `hooks` 写法抽离部分逻辑,使代码结构更加清晰;
@@ -36,17 +40,29 @@ GoView 是一个高效的拖拽式低代码数据可视化开发平台,将图
- 封装:项目进行了详细的工具类封装如:路由、存储、加/解密、文件处理、主题、NaiveUI 全局方法、组件等
说明文档:
![说明文档](readme/go-view-doc.png)
工作台:
![项目截图](readme/go-view-canvas.png)
![工作台](readme/go-view-canvas.png)
请求配置:
![项目截图](readme/go-view-fetch.png)
![请求配置](readme/go-view-fetch.png)
数据过滤:
![项目截图](readme/go-view-filter.png)
![数据过滤](readme/go-view-filter.png)
高级事件编辑:
![高级事件编辑](readme/go-view-event.png)
快捷主页:
![快捷主页](readme/go-view-indexpage.png)
主题色:
![项目截图](readme/go-view-color.png)
![主题色](readme/go-view-color.png)
亮白主题:
![亮白主题](readme/go-view-theme.png)
主要技术栈为:
@@ -71,10 +87,12 @@ GoView 是一个高效的拖拽式低代码数据可视化开发平台,将图
| 图表 | 柱状图 | 横向柱状图 | 折线图 | 单/多 折线面积图(渐变色) |
| \* | 饼图 | 环形图 | 水球图 | 雷达图 |
| \* | NaiveUI 多种进度 | 散点图 | 对数回归散点图 | 热力图 |
| \* | 漏斗图 | 中国地图 | 🤪 | 🤖 |
| 信息 | 文字 | 渐变文字 | 图片 | 😶 |
| 列表 | 滚动排名列表 | 滚动表格 | 🤓 | 👻 |
| \* | 漏斗图 | 中国地图 | 高德地图 | 🦊 |
| 信息 | 文字 | 渐变文字 | 词云 | 嵌套网页 |
| \* | 图片 | 视频 | 😺 | 🐯 |
| 列表 | 滚动排名列表 | 滚动表格 | 🐮 | 🐐 |
| 小组件 | 边框-01~13 | 装饰-01~05 | 数字翻牌 | 通用时间 |
| \* | 数字计数 | 倒计时 | 时钟 | 🦁 |
## 浏览器支持

View File

@@ -82,25 +82,4 @@
to {
opacity: 1;
}
}
/* 小屏处理 0~1000*/
.mobile-terminal {
display: none;
}
@media (max-width: 1000px) {
#app {
display: none;
}
.mobile-terminal {
display: flex;
align-items: center;
justify-content: center;
width: 100vw;
height: 100vh;
text-align: center;
font-size: 24px;
font-weight: 200;
background-image: linear-gradient(to top, #fff1eb 0%, #ace0f9 100%);
}
}

View File

@@ -24,9 +24,6 @@
</div>
</div>
</div>
<div class="mobile-terminal">
<p>请使用 Web 端进行查看</p>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@@ -1,14 +1,18 @@
{
"name": "go-view",
"version": "1.1.0",
"version": "1.1.5",
"scripts": {
"dev": "vite --host",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview",
"new": "plop --plopfile ./plop/plopfile.js",
"postinstall": "husky install"
"postinstall": "husky install",
"lint": "eslint --ext .js,.jsx,.ts,.tsx,.vue src",
"lint:fix": "eslint --ext .js,.jsx,.ts,.tsx,.vue src --fix"
},
"dependencies": {
"@amap/amap-jsapi-loader": "^1.0.1",
"@amap/amap-jsapi-types": "^0.0.8",
"@types/color": "^3.0.3",
"@types/crypto-js": "^4.1.1",
"@types/keymaster": "^1.6.30",
@@ -19,13 +23,16 @@
"crypto-js": "^4.1.1",
"echarts-liquidfill": "^3.1.0",
"echarts-stat": "^1.2.0",
"echarts-wordcloud": "^2.0.0",
"gsap": "^3.11.3",
"highlight.js": "^11.5.0",
"html2canvas": "^1.4.1",
"keymaster": "^1.6.2",
"monaco-editor": "^0.33.0",
"naive-ui": "2.30.3",
"naive-ui": "2.33.4",
"pinia": "^2.0.13",
"screenfull": "^6.0.1",
"three": "^0.145.0",
"vue": "^3.2.31",
"vue-demi": "^0.13.1",
"vue-i18n": "9.1.9",
@@ -38,6 +45,7 @@
"@commitlint/cli": "^17.0.2",
"@commitlint/config-conventional": "^17.0.2",
"@types/node": "^16.11.26",
"@types/three": "^0.144.0",
"@typescript-eslint/eslint-plugin": "^5.18.0",
"@typescript-eslint/parser": "^5.18.0",
"@vicons/carbon": "^0.12.0",

692
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

BIN
readme/go-view-doc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

BIN
readme/go-view-theme.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 KiB

View File

@@ -1,9 +1,9 @@
<template>
<n-config-provider
:locale="zhCN"
:theme="darkTheme"
:hljs="hljsTheme"
:date-locale="dateZhCN"
:locale="locale"
:date-locale="dateLocale"
:theme-overrides="overridesTheme"
>
<go-app-provider>
@@ -14,11 +14,10 @@
</template>
<script lang="ts" setup>
import { zhCN, dateZhCN, NConfigProvider } from 'naive-ui'
import { NConfigProvider } from 'naive-ui'
import { GoAppProvider } from '@/components/GoAppProvider'
import { I18n } from '@/components/I18n'
import { useDarkThemeHook, useThemeOverridesHook, useCode } from '@/hooks'
import { useDarkThemeHook, useThemeOverridesHook, useCode, useLang } from '@/hooks'
// 暗黑主题
const darkTheme = useDarkThemeHook()
@@ -28,4 +27,8 @@ const overridesTheme = useThemeOverridesHook()
// 代码主题
const hljsTheme = useCode()
// 全局语言
const { locale, dateLocale } = useLang()
</script>

View File

@@ -27,7 +27,6 @@ axiosInstance.interceptors.response.use(
return Promise.resolve(res.data)
},
(err: AxiosResponse) => {
window['$message'].error('接口异常,请检查!')
Promise.reject(err)
}
)

View File

@@ -80,6 +80,32 @@ export const http = (type?: RequestHttpEnum) => {
return get
}
}
const prefix = 'javascript:'
// 对输入字符进行转义处理
export const translateStr = (target: string | object) => {
if (typeof target === 'string') {
if (target.startsWith(prefix)) {
const funcStr = target.split(prefix)[1]
let result;
try {
result = new Function(`${funcStr}`)()
} catch (error) {
console.log(error)
window['$message'].error('js内容解析有误')
}
return result
} else {
return target
}
}
for (const key in target) {
if (Object.prototype.hasOwnProperty.call(target, key)) {
const subTarget = (target as any)[key];
(target as any)[key] = translateStr(subTarget)
}
}
return target
}
/**
* * 自定义请求
@@ -87,7 +113,7 @@ export const http = (type?: RequestHttpEnum) => {
* @param globalParams 全局参数
*/
export const customizeHttp = (targetParams: RequestConfigType, globalParams: RequestGlobalConfigType) => {
if(!targetParams || !globalParams) {
if (!targetParams || !globalParams) {
return
}
@@ -125,15 +151,17 @@ export const customizeHttp = (targetParams: RequestConfigType, globalParams: Req
}
// 处理头部
const headers: RequestParamsObjType = {
let headers: RequestParamsObjType = {
...globalRequestParams.Header,
...targetRequestParams.Header,
...targetRequestParams.Header
}
headers = translateStr(headers)
// data 参数
let data: RequestParamsObjType | FormData | string = {}
// params 参数
let params: RequestParamsObjType = targetRequestParams.Params
let params: RequestParamsObjType = { ...targetRequestParams.Params }
params = translateStr(params)
// form 类型处理
let formData: FormData = new FormData()
formData.set('default', 'defaultData')
@@ -145,33 +173,35 @@ export const customizeHttp = (targetParams: RequestConfigType, globalParams: Req
case RequestBodyEnum.JSON:
headers['Content-Type'] = ContentTypeEnum.JSON
data = JSON.parse(targetRequestParams.Body['json'])
data = translateStr(JSON.parse(targetRequestParams.Body['json']))
// json 赋值给 data
break
case RequestBodyEnum.XML:
headers['Content-Type'] = ContentTypeEnum.XML
// xml 字符串赋值给 data
data = targetRequestParams.Body['xml']
data = translateStr(targetRequestParams.Body['xml'])
break
case RequestBodyEnum.X_WWW_FORM_URLENCODED:
case RequestBodyEnum.X_WWW_FORM_URLENCODED: {
headers['Content-Type'] = ContentTypeEnum.FORM_URLENCODED
const bodyFormData = targetRequestParams.Body['x-www-form-urlencoded']
for (const i in bodyFormData) formData.set(i, bodyFormData[i])
for (const i in bodyFormData) formData.set(i, translateStr(bodyFormData[i]))
// FormData 赋值给 data
data = formData
break
}
case RequestBodyEnum.FORM_DATA:
case RequestBodyEnum.FORM_DATA: {
headers['Content-Type'] = ContentTypeEnum.FORM_DATA
const bodyFormUrlencoded = targetRequestParams.Body['form-data']
for (const i in bodyFormUrlencoded) {
formData.set(i, bodyFormUrlencoded[i])
formData.set(i, translateStr(bodyFormUrlencoded[i]))
}
// FormData 赋值给 data
data = formData
break
}
}
// sql 处理
@@ -180,11 +210,17 @@ export const customizeHttp = (targetParams: RequestConfigType, globalParams: Req
data = requestSQLContent
}
return axiosInstance({
url: `${requestOriginUrl}${requestUrl}`,
method: requestHttpType,
data,
params,
headers
})
try {
const url = (new Function("return `" + `${requestOriginUrl}${requestUrl}`.trim() + "`"))();
return axiosInstance({
url,
method: requestHttpType,
data,
params,
headers
})
} catch (error) {
console.log(error)
window['$message'].error('URL地址格式有误')
}
}

View File

@@ -14,6 +14,11 @@ export const scrollBoardUrl = '/mock/scrollBoard'
export const radarUrl = '/mock/radarData'
export const heatMapUrl = '/mock/heatMapData'
export const scatterBasicUrl = '/mock/scatterBasic'
export const mapUrl = '/mock/map'
export const capsuleUrl = '/mock/capsule'
export const wordCloudUrl = '/mock/wordCloud'
export const treemapUrl = '/mock/treemap'
export const threeEarth01Url = '/mock/threeEarth01Data'
const mockObject: MockMethod[] = [
{
@@ -73,6 +78,31 @@ const mockObject: MockMethod[] = [
method: RequestHttpEnum.GET,
response: () => test.fetchScatterBasic
},
{
url: mapUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchMap
},
{
url: capsuleUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchCapsule
},
{
url: wordCloudUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchWordCloud
},
{
url: treemapUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchTreemap
},
{
url: threeEarth01Url,
method: RequestHttpEnum.GET,
response: () => test.threeEarth01Data
},
]
export default mockObject

9
src/api/mock/map.json Normal file
View File

@@ -0,0 +1,9 @@
{
"markers|50": [
{
"name": "某某地市",
"value": "@integer(2, 20)",
"position": ["@float(115, 117, 1, 6)", "@float(38, 40, 1, 6)"]
}
]
}

View File

@@ -1,5 +1,7 @@
import heatmapJson from './heatMapData.json'
import scatterJson from './scatter.json'
import mapJson from './map.json'
import tTreemapJson from './treemap.json'
export default {
// 单图表
@@ -9,27 +11,7 @@ export default {
msg: '请求成功',
data: {
dimensions: ['product', 'dataOne'],
source: [
{
product: '@name',
'dataOne|0-900': 3
},
{
product: '@name',
'dataOne|0-900': 3
},
{
product: '@name',
'dataOne|0-900': 3
},
{
product: '@name',
'dataOne|0-900': 3
},
{
product: '@name',
'dataOne|0-900': 3
},
'source|50': [
{
product: '@name',
'dataOne|0-900': 3
@@ -37,6 +19,22 @@ export default {
]
}
},
// 胶囊图
fetchCapsule: {
code: 0,
status: 200,
msg: '请求成功',
data: {
dimensions: ['name', 'value'],
source: [
{ name: '厦门', 'value|0-40': 20 },
{ name: '南阳', 'value|20-60': 40 },
{ name: '北京', 'value|40-80': 60 },
{ name: '上海', 'value|60-100': 80 },
{ name: '新疆', value: 100 }
]
}
},
// 图表
fetchMockData: {
code: 0,
@@ -44,32 +42,7 @@ export default {
msg: '请求成功',
data: {
dimensions: ['product', 'dataOne', 'dataTwo'],
source: [
{
product: '@name',
'dataOne|100-900': 3,
'dataTwo|100-900': 3
},
{
product: '@name',
'dataOne|100-900': 3,
'dataTwo|100-900': 3
},
{
product: '@name',
'dataOne|100-900': 3,
'dataTwo|100-900': 3
},
{
product: '@name',
'dataOne|100-900': 3,
'dataTwo|100-900': 3
},
{
product: '@name',
'dataOne|100-900': 3,
'dataTwo|100-900': 3
},
'source|50': [
{
product: '@name',
'dataOne|100-900': 3,
@@ -83,21 +56,7 @@ export default {
code: 0,
status: 200,
msg: '请求成功',
data: [
{ name: '@name', 'value|100-900': 5 },
{ name: '@name', 'value|100-900': 5 },
{ name: '@name', 'value|100-900': 5 },
{ name: '@name', 'value|100-900': 5 },
{ name: '@name', 'value|100-900': 5 },
{ name: '@name', 'value|100-900': 5 },
{ name: '@name', 'value|100-900': 5 },
{ name: '@name', 'value|100-900': 5 },
{ name: '@name', 'value|100-900': 5 },
{ name: '@name', 'value|100-900': 5 },
{ name: '@name', 'value|100-900': 5 },
{ name: '@name', 'value|100-900': 5 },
{ name: '@name', 'value|100-900': 5 }
]
'data|50': [{ name: '@name', 'value|100-900': 5 }]
},
// 轮播表格
fetchScrollBoard: {
@@ -198,5 +157,70 @@ export default {
status: 200,
msg: '请求成功',
data: scatterJson
},
// 中国地图
fetchMap: {
code: 0,
status: 200,
msg: '请求成功',
data: mapJson
},
// 词云
fetchWordCloud: {
code: 0,
status: 200,
msg: '请求成功',
data: [
{
name: '@name',
value: 8000,
textStyle: {
color: '#78fbb2'
},
emphasis: {
textStyle: {
color: 'red'
}
}
},
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' }
]
},
// 树图
fetchTreemap: {
code: 0,
status: 200,
msg: '请求成功',
data: tTreemapJson
},
// 三维地球
threeEarth01Data: {
code: 0,
status: 200,
msg: '请求成功',
data: [
{
startArray: { name: '@name', N: '@integer(10, 100)', E: '@integer(10, 100)' },
'endArray|10': [{ name: '@name', N: '@integer(10, 100)', E: '@integer(10, 100)' }]
}
]
}
}

50
src/api/mock/treemap.json Normal file
View File

@@ -0,0 +1,50 @@
[
{
"name": "@name",
"value": "@integer(0, 1000)",
"children": [
{
"name": "@name",
"value": "@integer(0, 500)"
},
{
"name": "@name",
"value": "@integer(0, 500)"
}
]
},
{
"name": "@name",
"value": "@integer(0, 1000)",
"children": [
{
"name": "@name",
"value": "@integer(0, 00)"
},
{
"name": "@name",
"value": "@integer(0, 500)"
}
]
},
{
"name": "@name",
"value": "@integer(0, 1000)",
"children": [
{
"name": "@name",
"value": "@integer(0, 1000)"
}
]
},
{
"name": "@name",
"value": "@integer(0, 1000)",
"children": [
{
"name": "@name",
"value": "@integer(0, 1000)"
}
]
}
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

View File

@@ -11,7 +11,7 @@
</template>
<n-list-item>
<n-space :size="20">
<n-space class="go-my-2" :size="20">
<n-text class="item-left">版权声明</n-text>
<n-text>
GoView 版权属于
@@ -21,8 +21,7 @@
</n-list-item>
<n-list-item>
<n-divider style="margin-top: 0" />
<n-space :size="20">
<n-space class="go-my-2" :size="20">
<n-text class="item-left">协议备注</n-text>
<n-text>
请遵守开源 MIT 协议以上声明 <n-text type="error">不可删除</n-text>否则视作侵权行为后果自负
@@ -31,8 +30,7 @@
</n-list-item>
<n-list-item>
<n-divider style="margin-top: 0" />
<n-space :size="20">
<n-space class="go-mt-2" :size="20">
<n-text class="item-left">商业授权</n-text>
<n-text>
若不想保留版权声明请通过仓库/交流群 联系项目作者进行授权

View File

@@ -190,11 +190,14 @@ const handleChange = (e: MouseEvent, item: ListType) => {
width: 100px;
}
.select-min-width {
width: 110px;
width: 115px;
}
@include deep() {
.n-list-item:not(:last-child) {
border-bottom: 0;
.n-list-item {
border-bottom: 0!important;
}
.n-list-item__divider {
display: none!important;
}
}
}

View File

@@ -1,3 +1,4 @@
<!-- eslint-disable vue/valid-template-root -->
<template></template>
<script lang="ts" setup>

View File

@@ -21,6 +21,23 @@
</setting-item-box>
</collapse-item>
<collapse-item v-if="grid" name="容器">
<setting-item-box name="距离">
<setting-item name="左侧距离">
<n-input v-model:value="grid.left" size="small"></n-input>
</setting-item>
<setting-item name="右侧距离">
<n-input v-model:value="grid.right" size="small"></n-input>
</setting-item>
<setting-item name="上侧距离">
<n-input v-model:value="grid.top" size="small"></n-input>
</setting-item>
<setting-item name="下侧距离">
<n-input v-model:value="grid.bottom" size="small"></n-input>
</setting-item>
</setting-item-box>
</collapse-item>
<collapse-item v-if="xAxis" name="X轴">
<template #header>
<n-switch v-model:value="xAxis.show" size="small"></n-switch>
@@ -51,6 +68,9 @@
<setting-item name="大小">
<n-input-number v-model:value="xAxis.axisLabel.fontSize" :min="8" size="small"></n-input-number>
</setting-item>
<setting-item name="偏移量">
<n-input-number v-model:value="xAxis.axisLabel.rotate" :min="-90" :max="90" size="small"></n-input-number>
</setting-item>
</setting-item-box>
<setting-item-box name="轴线">
<setting-item name="展示">
@@ -140,6 +160,9 @@
<setting-item name="大小">
<n-input-number v-model:value="yAxis.axisLabel.fontSize" :min="8" size="small"></n-input-number>
</setting-item>
<setting-item name="偏移量">
<n-input-number v-model:value="yAxis.axisLabel.rotate" :min="-90" :max="90" size="small"></n-input-number>
</setting-item>
</setting-item-box>
<setting-item-box name="轴线">
<setting-item name="展示">
@@ -230,15 +253,15 @@
</setting-item>
</setting-item-box>
<setting-item-box name="视觉映射">
<setting-item-box name="控制块">
<setting-item name="放置方向">
<n-select v-model:value="visualMap.orient" size="small" :options="axisConfig.visualMap.orient"></n-select>
</setting-item>
<setting-item name="宽度">
<n-input-number v-model:value="visualMap.temWidth" size="small"></n-input-number>
<n-input-number v-model:value="visualMap.itemWidth" :min="5" size="small"></n-input-number>
</setting-item>
<setting-item name="高度">
<n-input-number v-model:value="visualMap.itemHeight" size="small"></n-input-number>
<n-input-number v-model:value="visualMap.itemHeight" :min="5" size="small"></n-input-number>
</setting-item>
<setting-item name="反转">
<n-space>
@@ -252,14 +275,6 @@
</setting-item>
</setting-item-box>
<global-setting-position :targetData="visualMap"></global-setting-position>
<!-- <setting-item-box name="位置">
<setting-item name="距离底部">
<n-input-number v-model:value="visualMap.bottom" size="small"></n-input-number>
</setting-item>
<setting-item name="距离左侧">
<n-input-number v-model:value="visualMap.left" size="small"></n-input-number>
</setting-item>
</setting-item-box> -->
</collapse-item>
</template>
@@ -297,6 +312,10 @@ const legend = computed(() => {
return props.optionData.legend
})
const grid = computed(() => {
return props.optionData.grid
})
const visualMap = computed(() => {
return props.optionData.visualMap
})

View File

@@ -1,5 +1,5 @@
<template>
<setting-item-box name="位置">
<setting-item-box v-if="targetData" name="位置">
<setting-item :name="`偏移 X${targetData.left || 0}px`">
<n-input-number v-model:value="targetData.left" size="small" step="10"></n-input-number>
</setting-item>

View File

@@ -1,12 +1,12 @@
<template>
<div v-show="isGroup">
<n-divider n-divider style="margin: 10px 0"></n-divider>
<n-tag type="warning"> 解散分组 {{ isCanvas ? '滤镜' : '滤镜 / 变换' }} 也将消失!</n-tag>
<n-tag type="warning"> 解散分组 {{ isCanvas ? '滤镜' : '滤镜 / 变换' }} 也将消失!</n-tag>
</div>
<collapse-item :name="isCanvas ? '滤镜' : '滤镜 / 变换'">
<template #header>
<n-switch v-if="isCanvas" v-model:value="chartStyles.filterShow" size="small"></n-switch>
<n-switch v-model:value="chartStyles.filterShow" size="small"></n-switch>
</template>
<setting-item-box name="色相" :alone="true">
<setting-item :name="`值:${chartStyles.hueRotate}deg`">
@@ -69,6 +69,24 @@
</setting-item>
</setting-item-box>
<!-- 混合模式 -->
<setting-item-box v-if="!isCanvas" :alone="true">
<template #name>
<n-text>混合</n-text>
<n-tooltip trigger="hover">
<template #trigger>
<n-icon size="21" :depth="3">
<help-outline-icon></help-outline-icon>
</n-icon>
</template>
<n-text>视频组件需要底色透明一般选中滤色</n-text>
</n-tooltip>
</template>
<setting-item>
<n-select v-model:value="chartStyles.blendMode" size="small" filterable :options="BlendModeEnumList"></n-select>
</setting-item>
</setting-item-box>
<!-- 变换 -->
<setting-item-box v-if="!isCanvas" name="旋转°">
<setting-item name="Z轴(平面) - 旋转">
@@ -126,14 +144,15 @@
</setting-item-box>
<!-- 提示 -->
<n-tag v-show="isCanvas" type="warning"> 若预览时大屏模糊可以尝试关闭滤镜进行修复 </n-tag>
<n-tag type="warning"> 若预览时大屏模糊可以尝试关闭滤镜进行修复 </n-tag>
</collapse-item>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { PickCreateComponentType } from '@/packages/index.d'
import { PickCreateComponentType, BlendModeEnumList } from '@/packages/index.d'
import { SettingItemBox, SettingItem, CollapseItem } from '@/components/Pages/ChartItemSetting'
import { icon } from '@/plugins'
const props = defineProps({
isGroup: {
@@ -150,14 +169,14 @@ const props = defineProps({
}
})
// 百分比格式化persen
const { HelpOutlineIcon } = icon.ionicons5
// 百分比格式化 person
const sliderFormatTooltip = (v: string) => {
// @ts-ignore
return `${(parseFloat(v) * 100).toFixed(0)}%`
}
// 角度格式化
const degFormatTooltip = (v: string) => {
// @ts-ignore
return `${v}deg`
}
</script>

View File

@@ -0,0 +1,5 @@
import Flipper from './index.vue'
type FlipType = 'up' | 'down'
export { Flipper, FlipType }

View File

@@ -0,0 +1,218 @@
<template>
<div class="go-Flipper" :class="[flipType, { go: isFlipping }]">
<div class="digital front" :data-front="frontTextFromData"></div>
<div class="digital back" :data-back="backTextFromData"></div>
</div>
</template>
<script lang="ts" setup>
import { ref, PropType, watch } from 'vue'
import { FlipType } from './index'
const props = defineProps({
flipType: {
type: String as PropType<FlipType>,
default: () => {
return 'down'
}
},
count: {
type: [Number, String],
default: 0
},
duration: {
type: Number,
default: 600
},
width: {
type: Number,
default: 60
},
height: {
type: Number,
default: 100
},
radius: {
type: Number,
default: 10
},
frontColor: {
type: String,
default: '#ffffff'
},
backColor: {
type: String,
default: '#000000'
}
})
const isFlipping = ref(false)
const frontTextFromData = ref(props.count || 0)
const backTextFromData = ref(props.count || 0)
// 翻牌
const flip = (front: string | number, back: string | number) => {
// 如果处于翻转中,则不执行
if (isFlipping.value) return
// 设置翻盘前后数据
backTextFromData.value = back
frontTextFromData.value = front
// 设置翻转状态为true
isFlipping.value = true
// 翻牌结束的行为
setTimeout(() => {
isFlipping.value = false // 设置翻转状态为false
frontTextFromData.value = back
}, props.duration)
}
watch(
() => props.count,
(newVal, oldVal) => {
flip(oldVal as string | number, newVal as string | number)
},
{
immediate: true
}
)
</script>
<style lang="scss" scoped>
$frontColor: v-bind('props.frontColor');
$backColor: v-bind('props.backColor');
$radius: v-bind('`${props.radius}px`');
$width: v-bind('`${props.width}px`');
$height: v-bind('`${props.height}px`');
$perspective: v-bind('`${props.height * 2}px`');
$speed: v-bind('`${props.duration / 1000}s`');
$shadowColor: #000000;
$lineColor: #4a9ef8;
// #region 动画效果
@keyframes frontFlipDown {
0% {
transform: perspective($perspective) rotateX(0deg);
}
100% {
transform: perspective($perspective) rotateX(-180deg);
}
}
@keyframes backFlipDown {
0% {
transform: perspective($perspective) rotateX(180deg);
}
100% {
transform: perspective($perspective) rotateX(0deg);
}
}
@keyframes frontFlipUp {
0% {
transform: perspective($perspective) rotateX(0deg);
}
100% {
transform: perspective($perspective) rotateX(180deg);
}
}
@keyframes backFlipUp {
0% {
transform: perspective($perspective) rotateX(-180deg);
}
100% {
transform: perspective($perspective) rotateX(0deg);
}
}
// #endregion
.go-Flipper {
display: inline-block;
position: relative;
width: $width;
height: $height;
line-height: $height;
border: solid 1px $backColor;
border-radius: $radius;
background: $frontColor;
font-size: $width;
color: $frontColor;
box-shadow: 0 0 6px rgba($color: $shadowColor, $alpha: 0.5); // 阴影部分
text-align: center;
// font-family: 'Helvetica Neue';
.digital:before,
.digital:after {
content: '';
position: absolute;
left: 0;
right: 0;
background: $backColor;
overflow: hidden;
box-sizing: border-box;
}
.digital.front:before,
.digital.front:after {
content: attr(data-front) !important;
}
.digital.back:before,
.digital.back:after {
content: attr(data-back) !important;
}
.digital:before {
top: 0;
bottom: 50%;
border-radius: $radius $radius 0 0;
border-bottom: solid 1px rgba($color: $lineColor, $alpha: 0.3); // 中间线颜色
}
.digital:after {
top: 50%;
bottom: 0;
border-radius: 0 0 $radius $radius;
line-height: 0;
}
/*向下翻*/
&.down .front:before {
z-index: 3;
}
&.down .back:after {
z-index: 2;
transform-origin: 50% 0%;
transform: perspective($perspective) rotateX(180deg);
}
&.down .front:after,
&.down .back:before {
z-index: 1;
}
&.down.go .front:before {
transform-origin: 50% 100%;
animation: frontFlipDown $speed ease-in-out both;
box-shadow: 0 -2px 6px rgba($color: $lineColor, $alpha: 0.3);
backface-visibility: hidden;
}
&.down.go .back:after {
animation: backFlipDown $speed ease-in-out both;
}
/*向上翻*/
&.up .front:after {
z-index: 3;
}
&.up .back:before {
z-index: 2;
transform-origin: 50% 100%;
transform: perspective($perspective) rotateX(-180deg);
}
&.up .front:before,
&.up .back:after {
z-index: 1;
}
&.up.go .front:after {
transform-origin: 50% 0;
animation: frontFlipUp $speed ease-in-out both;
box-shadow: 0 2px 6px rgba($color: $lineColor, $alpha: 0.3);
backface-visibility: hidden;
}
&.up.go .back:before {
animation: backFlipUp $speed ease-in-out both;
}
}
</style>

View File

@@ -1,6 +1,7 @@
<!-- eslint-disable vue/valid-template-root -->
<template></template>
<script lang="ts" setup>
import { useDialog } from 'naive-ui';
import { useDialog } from 'naive-ui'
//挂载在 window 方便与在js中使用
window['$dialog'] = useDialog();
window['$dialog'] = useDialog()
</script>

View File

@@ -1,3 +1,4 @@
<!-- eslint-disable vue/valid-template-root -->
<template></template>
<script lang="ts" setup>

View File

@@ -1,7 +1,8 @@
<!-- eslint-disable vue/valid-template-root -->
<template></template>
<script lang="ts" setup>
import { useMessage } from 'naive-ui';
import { useMessage } from 'naive-ui'
//挂载在 window 方便与在js中使用
window['$message'] = useMessage();
window['$message'] = useMessage()
</script>

View File

@@ -1,7 +1,7 @@
// 鼠标点击左右键
export enum MouseEventButton {
LEFT = 1,
RIGHT = 2,
RIGHT = 2
}
// 页面拖拽键名
@@ -9,6 +9,12 @@ export enum DragKeyEnum {
DRAG_KEY = 'ChartData'
}
// 不同页面保存操作
export enum SavePageEnum {
CHART = 'SaveChart',
JSON = 'SaveJSON'
}
// 操作枚举
export enum MenuEnum {
// 移动
@@ -41,7 +47,17 @@ export enum MenuEnum {
// 后退
BACK = 'back',
// 前进
FORWORD = 'forward'
FORWORD = 'forward',
// 保存
SAVE = 'save',
// 锁定
LOCK = 'lock',
// 解除锁定
UNLOCK = 'unLock',
// 隐藏
HIDE = 'hide',
// 显示
SHOW = 'show'
}
// Win 键盘枚举
@@ -49,9 +65,9 @@ export enum WinKeyboard {
CTRL = 'ctrl',
SHIFT = 'shift',
ALT = ' alt',
CTRL_SOURCE_KEY = "control",
SHIFT_SOURCE_KEY = "shift",
ALT_SOURCE_KEY = "alt"
CTRL_SOURCE_KEY = 'control',
SHIFT_SOURCE_KEY = 'shift',
ALT_SOURCE_KEY = 'alt'
}
// Mac 键盘枚举
@@ -60,7 +76,7 @@ export enum MacKeyboard {
CTRL = '⌘',
SHIFT = '⇧',
ALT = '⌥',
CTRL_SOURCE_KEY = "⌘",
SHIFT_SOURCE_KEY = "⇧",
ALT_SOURCE_KEY = "⌥"
CTRL_SOURCE_KEY = '⌘',
SHIFT_SOURCE_KEY = '⇧',
ALT_SOURCE_KEY = '⌥'
}

View File

@@ -7,7 +7,7 @@ export enum ResultEnum {
SERVER_ERROR = 500,
SERVER_FORBIDDEN = 403,
NOT_FOUND = 404,
TIMEOUT = 10042
TIMEOUT = 60000
}
// 数据相关

View File

@@ -12,6 +12,12 @@ export enum PreviewEnum {
CHART_PREVIEW_NAME = 'ChartPreview',
}
export enum EditEnum {
// 图表JSON编辑
CHART_EDIT = '/chart/edit/:id(.*)*',
CHART_EDIT_NAME = 'ChartEdit',
}
export enum PageEnum {
// 登录
BASE_LOGIN = '/login',

View File

@@ -1,4 +1,7 @@
export * from '@/hooks/useTheme.hook'
export * from '@/hooks/usePreviewScale.hook'
export * from '@/hooks/useCode.hook'
export * from '@/hooks/useChartDataFetch.hook'
export * from '@/hooks/useChartDataFetch.hook'
export * from '@/hooks/useChartDataPondFetch.hook'
export * from '@/hooks/useLifeHandler.hook'
export * from '@/hooks/useLang.hook'

View File

@@ -1,6 +1,7 @@
import { ref, toRefs, toRaw } from 'vue'
import type VChart from 'vue-echarts'
import { customizeHttp } from '@/api/http'
import { useChartDataPondFetch } from '@/hooks/'
import { CreateComponentType, ChartFrameEnum } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { RequestDataTypeEnum } from '@/enums/httpEnum'
@@ -23,9 +24,25 @@ export const useChartDataFetch = (
const vChartRef = ref<typeof VChart | null>(null)
let fetchInterval: any = 0
// 数据池
const { addGlobalDataInterface } = useChartDataPondFetch()
const { requestDataPondId } = toRefs(targetComponent.request)
// 组件类型
const { chartFrame } = targetComponent.chartConfig
// eCharts 组件配合 vChart 库更新方式
const echartsUpdateHandle = (dataset: any) => {
if (chartFrame === ChartFrameEnum.ECHARTS) {
if (vChartRef.value) {
vChartRef.value.setOption({ dataset: dataset })
}
}
}
const requestIntervalFn = () => {
const chartEditStore = useChartEditStore()
// 全局数据
const {
requestOriginUrl,
@@ -41,9 +58,6 @@ export const useChartDataFetch = (
requestInterval: targetInterval
} = toRefs(targetComponent.request)
// 组件类型
const { chartFrame } = targetComponent.chartConfig
// 非请求类型
if (requestDataType.value !== RequestDataTypeEnum.AJAX) return
@@ -58,19 +72,14 @@ export const useChartDataFetch = (
clearInterval(fetchInterval)
const fetchFn = async () => {
const res = await customizeHttp(toRaw(targetComponent.request), toRaw(chartEditStore.requestGlobalConfig))
if (res && res.data) {
const res = await customizeHttp(toRaw(targetComponent.request), toRaw(chartEditStore.getRequestGlobalConfig))
if (res) {
try {
const filter = targetComponent.filter
// eCharts 组件配合 vChart 库更新方式
if (chartFrame === ChartFrameEnum.ECHARTS) {
if (vChartRef.value) {
vChartRef.value.setOption({ dataset: newFunctionHandle(res.data, filter) })
}
}
echartsUpdateHandle(newFunctionHandle(res?.data, res, filter))
// 更新回调函数
if (updateCallback) {
updateCallback(newFunctionHandle(res.data, filter))
updateCallback(newFunctionHandle(res?.data, res, filter))
}
} catch (error) {
console.error(error)
@@ -88,9 +97,17 @@ export const useChartDataFetch = (
// 开启轮询
if (time) fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit))
}
} catch (error) {}
// eslint-disable-next-line no-empty
} catch (error) {
console.log(error)
}
}
isPreview() && requestIntervalFn()
if (isPreview()) {
// 判断是否有数据池对应 id
requestDataPondId
? addGlobalDataInterface(targetComponent, useChartEditStore, updateCallback || echartsUpdateHandle)
: requestIntervalFn()
}
return { vChartRef }
}

View File

@@ -0,0 +1,93 @@
import { toRaw } from 'vue'
import { customizeHttp } from '@/api/http'
import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { RequestGlobalConfigType, RequestDataPondItemType } from '@/store/modules/chartEditStore/chartEditStore.d'
import { newFunctionHandle } from '@/utils'
// 获取类型
type ChartEditStoreType = typeof useChartEditStore
// 数据池存储的数据类型
type DataPondMapType = {
updateCallback: (...args: any) => any
filter?: string | undefined
}
// 数据池 Map 中请求对应 callback
const mittDataPondMap = new Map<string, DataPondMapType[]>()
// 创建单个数据项轮询接口
const newPondItemInterval = (
requestGlobalConfig: RequestGlobalConfigType,
requestDataPondItem: RequestDataPondItemType,
dataPondMapItem?: DataPondMapType[]
) => {
if (!dataPondMapItem) return
// 请求
const fetchFn = async () => {
try {
const res = await customizeHttp(toRaw(requestDataPondItem.dataPondRequestConfig), toRaw(requestGlobalConfig))
if (res) {
try {
// 遍历更新回调函数
dataPondMapItem.forEach(item => {
item.updateCallback(newFunctionHandle(res?.data, res, item.filter))
})
} catch (error) {
console.error(error)
return error
}
}
} catch (error) {
return error
}
}
// 立即调用
fetchFn()
}
/**
* 数据池接口处理
*/
export const useChartDataPondFetch = () => {
// 新增全局接口
const addGlobalDataInterface = (
targetComponent: CreateComponentType,
useChartEditStore: ChartEditStoreType,
updateCallback: (...args: any) => any
) => {
const chartEditStore = useChartEditStore()
const { requestDataPond } = chartEditStore.getRequestGlobalConfig
// 组件对应的数据池 Id
const requestDataPondId = '111' || (targetComponent.request.requestDataPondId as string)
// 新增数据项
const mittPondIdArr = mittDataPondMap.get(requestDataPondId) || []
mittPondIdArr.push({
updateCallback: updateCallback,
filter: targetComponent.filter
})
mittDataPondMap.set(requestDataPondId, mittPondIdArr)
}
// 初始化数据池
const initDataPond = (requestGlobalConfig: RequestGlobalConfigType) => {
const { requestDataPond } = requestGlobalConfig
// 根据 mapId 查找对应的数据池配置
for (let pondKey of mittDataPondMap.keys()) {
const requestDataPondItem = requestDataPond.find(item => item.dataPondId === pondKey)
if (requestDataPondItem) {
newPondItemInterval(requestGlobalConfig, requestDataPondItem, mittDataPondMap.get(pondKey))
}
}
}
return {
addGlobalDataInterface,
initDataPond
}
}

24
src/hooks/useLang.hook.ts Normal file
View File

@@ -0,0 +1,24 @@
import { computed } from 'vue'
import { LangEnum } from '@/enums/styleEnum'
import { useLangStore } from '@/store/modules/langStore/langStore'
import { zhCN, enUS, dateEnUS, dateZhCN } from 'naive-ui'
type LangStoreType = typeof useLangStore
// 语言切换
export const useLang = () => {
const lang = useLangStore()
const locale = computed(() => {
return lang.getLang === LangEnum.ZH ? zhCN : enUS
})
const dateLocale = computed(() => {
return lang.getLang === LangEnum.ZH ? dateZhCN : dateEnUS
})
return {
locale,
dateLocale
}
}

View File

@@ -0,0 +1,78 @@
import { CreateComponentType, CreateComponentGroupType, EventLife, BaseEvent } from '@/packages/index.d'
import * as echarts from 'echarts'
// 所有图表组件集合对象
const components: { [K in string]?: any } = {}
// 项目提供的npm 包变量
export const npmPkgs = { echarts }
// 组件事件处理 hook
export const useLifeHandler = (chartConfig: CreateComponentType | CreateComponentGroupType) => {
if (!chartConfig.events) return {}
// 处理基础事件
const baseEvent: { [key: string]: any } = {}
for (const key in chartConfig.events.baseEvent) {
const fnStr: string | undefined = (chartConfig.events.baseEvent as any)[key]
// 动态绑定基础事件
if (fnStr) {
baseEvent[key] = generateBaseFunc(fnStr)
}
}
// 生成生命周期事件
const events = chartConfig.events.advancedEvents || {}
const lifeEvents = {
[EventLife.VNODE_BEFORE_MOUNT](e: any) {
// 存储组件
components[chartConfig.id] = e.component
const fnStr = (events[EventLife.VNODE_BEFORE_MOUNT] || '').trim()
generateFunc(fnStr, e)
},
[EventLife.VNODE_MOUNTED](e: any) {
const fnStr = (events[EventLife.VNODE_MOUNTED] || '').trim()
generateFunc(fnStr, e)
}
}
return { ...baseEvent, ...lifeEvents }
}
/**
* 生成基础函数
* @param fnStr 用户方法体代码
* @param event 鼠标事件
*/
export function generateBaseFunc(fnStr: string) {
try {
return new Function(`
return (
async function(mouseEvent){
${fnStr}
}
)`)()
} catch (error) {
console.error(error)
}
}
/**
* 生成高级函数
* @param fnStr 用户方法体代码
* @param e 执行生命周期的动态组件实例
*/
function generateFunc(fnStr: string, e: any) {
try {
// npmPkgs 便于拷贝 echarts 示例时设置option 的formatter等相关内容
Function(`
"use strict";
return (
async function(e, components, node_modules){
const {${Object.keys(npmPkgs).join()}} = node_modules;
${fnStr}
}
)`)().bind(e?.component)(e, components, npmPkgs)
} catch (error) {
console.error(error)
}
}

View File

@@ -4,17 +4,21 @@ import { CreateComponentType } from '@/packages/index.d'
import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json'
export const includes = ['legend', 'xAxis', 'yAxis']
export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
export const seriesItem = {
type: 'bar',
barWidth: null,
barWidth: 15,
label: {
show: true,
position: 'top',
color: '#fff',
fontSize: 12
},
itemStyle: {
color: null,
borderRadius: 0
borderRadius: 2
}
}
export const option = {
tooltip: {
show: true,
@@ -24,10 +28,7 @@ export const option = {
type: 'shadow'
}
},
legend: {
show: true
},
xAxis: {
xAxis: {
show: true,
type: 'category'
},

View File

@@ -1,25 +1,8 @@
<template>
<!-- Echarts 全局设置 -->
<!-- Echarts 全局设置 -->
<global-setting :optionData="optionData"></global-setting>
<CollapseItem
v-for="(item, index) in seriesList"
:key="index"
:name="`柱状图-${index + 1}`"
:expanded="true"
>
<CollapseItem v-for="(item, index) in seriesList" :key="index" :name="`柱状图-${index + 1}`" :expanded="true">
<SettingItemBox name="图形">
<SettingItem name="颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="item.itemStyle.color"
></n-color-picker>
</SettingItem>
<SettingItem>
<n-button size="small" @click="item.itemStyle.color = null">
恢复默认
</n-button>
</SettingItem>
<SettingItem name="宽度">
<n-input-number
v-model:value="item.barWidth"
@@ -30,24 +13,40 @@
></n-input-number>
</SettingItem>
<SettingItem name="圆角">
<n-input-number
v-model:value="item.itemStyle.borderRadius"
:min="0"
size="small"
></n-input-number>
<n-input-number v-model:value="item.itemStyle.borderRadius" :min="0" size="small"></n-input-number>
</SettingItem>
</SettingItemBox>
<setting-item-box name="标签">
<setting-item>
<n-space>
<n-switch v-model:value="item.label.show" size="small" />
<n-text>展示标签</n-text>
</n-space>
</setting-item>
<setting-item name="大小">
<n-input-number v-model:value="item.label.fontSize" size="small" :min="1"></n-input-number>
</setting-item>
<setting-item name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="item.label.color"></n-color-picker>
</setting-item>
<setting-item name="位置">
<n-select
v-model:value="item.label.position"
:options="[
{ label: 'top', value: 'top' },
{ label: 'left', value: 'left' },
{ label: 'right', value: 'right' },
{ label: 'bottom', value: 'bottom' }
]"
/>
</setting-item>
</setting-item-box>
</CollapseItem>
</template>
<script setup lang="ts">
import { PropType, computed } from 'vue'
import {
GlobalSetting,
CollapseItem,
SettingItemBox,
SettingItem
} from '@/components/Pages/ChartItemSetting'
import { GlobalSetting, CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
const props = defineProps({

View File

@@ -24,6 +24,7 @@ import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { isPreview } from '@/utils'
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import isObject from 'lodash/isObject'
const props = defineProps({
themeSetting: {
@@ -51,17 +52,22 @@ const option = computed(() => {
// dataset 无法变更条数的补丁
watch(
() => props.chartConfig.option.dataset,
(newData, oldData) => {
if (newData.dimensions.length !== oldData.dimensions.length) {
const seriesArr = []
for (let i = 0; i < newData.dimensions.length - 1; i++) {
seriesArr.push(seriesItem)
(newData: { dimensions: any }, oldData) => {
try {
if (!isObject(newData) || !('dimensions' in newData)) return
if (Array.isArray(newData?.dimensions)) {
const seriesArr = []
for (let i = 0; i < newData.dimensions.length - 1; i++) {
seriesArr.push(seriesItem)
}
replaceMergeArr.value = ['series']
props.chartConfig.option.series = seriesArr
nextTick(() => {
replaceMergeArr.value = []
})
}
replaceMergeArr.value = ['series']
props.chartConfig.option.series = seriesArr
nextTick(() => {
replaceMergeArr.value = []
})
} catch (error) {
console.log(error)
}
},
{

View File

@@ -4,17 +4,21 @@ import { CreateComponentType } from '@/packages/index.d'
import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json'
export const includes = ['legend', 'xAxis', 'yAxis']
export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
export const seriesItem = {
type: 'bar',
barWidth: null,
label: {
show: true,
position: 'right',
color: '#fff',
fontSize: 12
},
itemStyle: {
color: null,
borderRadius: 0
}
}
export const option = {
tooltip: {
show: true,
@@ -24,12 +28,9 @@ export const option = {
type: 'shadow'
}
},
legend: {
show: true
},
xAxis: {
show: true,
type: 'value',
type: 'value'
},
yAxis: {
show: true,

View File

@@ -3,12 +3,6 @@
<global-setting :optionData="optionData"></global-setting>
<CollapseItem v-for="(item, index) in seriesList" :key="index" :name="`柱状图-${index+1}`" :expanded="true">
<SettingItemBox name="图形">
<SettingItem name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="item.itemStyle.color"></n-color-picker>
</SettingItem>
<SettingItem>
<n-button size="small" @click="item.itemStyle.color = null">恢复默认</n-button>
</SettingItem>
<SettingItem name="宽度">
<n-input-number
v-model:value="item.barWidth"
@@ -26,6 +20,39 @@
></n-input-number>
</SettingItem>
</SettingItemBox>
<setting-item-box name="标签">
<setting-item>
<n-space>
<n-switch v-model:value="item.label.show" size="small" />
<n-text>展示标签</n-text>
</n-space>
</setting-item>
<setting-item name="大小">
<n-input-number
v-model:value="item.label.fontSize"
size="small"
:min="1"
></n-input-number>
</setting-item>
<setting-item name="颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="item.label.color"
></n-color-picker>
</setting-item>
<setting-item name="位置">
<n-select
v-model:value="item.label.position"
:options="[
{ label: 'top', value: 'top' },
{ label: 'left', value: 'left' },
{ label: 'right', value: 'right' },
{ label: 'bottom', value: 'bottom' },
]"
/>
</setting-item>
</setting-item-box>
</CollapseItem>
</template>

View File

@@ -23,6 +23,7 @@ import { useChartDataFetch } from '@/hooks'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { isPreview } from '@/utils'
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import isObject from 'lodash/isObject'
const props = defineProps({
themeSetting: {
@@ -50,17 +51,22 @@ const option = computed(() => {
// dataset 无法变更条数的补丁
watch(
() => props.chartConfig.option.dataset,
(newData, oldData) => {
if (newData?.dimensions.length !== oldData?.dimensions.length) {
const seriesArr = []
for (let i = 0; i < newData.dimensions.length - 1; i++) {
seriesArr.push(seriesItem)
(newData: { dimensions: any }, oldData) => {
try {
if (!isObject(newData) || !('dimensions' in newData)) return
if (Array.isArray(newData?.dimensions)) {
const seriesArr = []
for (let i = 0; i < newData.dimensions.length - 1; i++) {
seriesArr.push(seriesItem)
}
replaceMergeArr.value = ['series']
props.chartConfig.option.series = seriesArr
nextTick(() => {
replaceMergeArr.value = []
})
}
replaceMergeArr.value = ['series']
props.chartConfig.option.series = seriesArr
nextTick(() => {
replaceMergeArr.value = []
})
} catch (error) {
console.log(error)
}
},
{

View File

@@ -0,0 +1,25 @@
import { PublicConfigClass } from '@/packages/public'
import { CapsuleChartConfig } from './index'
import { CreateComponentType } from '@/packages/index.d'
import { chartInitConfig } from '@/settings/designSetting'
import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json'
export const option = {
dataset: dataJson,
colors: ['#c4ebad', '#6be6c1', '#a0a7e6', '#96dee8', '#3fb1e3' ],
unit: '',
itemHeight: 10,
valueFontSize: 16,
paddingRight: 50,
paddingLeft: 50,
showValue: true
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key: string = CapsuleChartConfig.key
public attr = { ...chartInitConfig, zIndex: -1 }
public chartConfig = cloneDeep(CapsuleChartConfig)
public option = cloneDeep(option)
}

View File

@@ -0,0 +1,53 @@
<template>
<!-- Echarts 全局设置 -->
<global-setting :optionData="optionData"> </global-setting>
<!-- 胶囊柱图 -->
<collapse-item name="胶囊柱图" expanded>
<SettingItemBox name="布局">
<setting-item name="左侧边距">
<n-input-number v-model:value="optionData.paddingLeft" :min="10" :step="1" size="small"></n-input-number>
</setting-item>
<setting-item name="右侧边距">
<n-input-number v-model:value="optionData.paddingRight" :min="10" :step="1" size="small"></n-input-number>
</setting-item>
<setting-item name="每块高度(px)">
<n-input-number v-model:value="optionData.itemHeight" :min="0" :step="1" size="small"></n-input-number>
</setting-item>
</SettingItemBox>
<SettingItemBox name="文本">
<setting-item name="所有文字大小">
<n-input-number v-model:value="optionData.valueFontSize" :min="0" :step="1" size="small"></n-input-number>
</setting-item>
<setting-item name="单位">
<n-input v-model:value="optionData.unit" size="small"></n-input>
</setting-item>
<SettingItem>
<n-space>
<n-switch v-model:value="optionData.showValue" size="small"></n-switch>
<n-text>显示数值</n-text>
</n-space>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="颜色">
<setting-item v-for="(item, index) in optionData.colors" :key="index" :name="`颜色${index}`">
<n-color-picker v-model:value="optionData.colors[index]" size="small" :modes="['hex']"></n-color-picker>
</setting-item>
</SettingItemBox>
</collapse-item>
</template>
<script setup lang="ts">
import { PropType, computed } from 'vue'
import { GlobalSetting, CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
import { option } from './config'
const props = defineProps({
optionData: {
type: Object as PropType<typeof option & GlobalThemeJsonType>,
required: true
}
})
</script>

View File

@@ -0,0 +1,10 @@
{
"dimensions": ["name", "value"],
"source": [
{ "name": "厦门", "value": 20 },
{ "name": "南阳", "value": 40 },
{ "name": "北京", "value": 60 },
{ "name": "上海", "value": 80 },
{ "name": "新疆", "value": 100 }
]
}

View File

@@ -0,0 +1,15 @@
import image from '@/assets/images/chart/charts/capsule.png'
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
export const CapsuleChartConfig: ConfigType = {
key: 'CapsuleChart',
chartKey: 'VCapsuleChart',
conKey: 'VCCapsuleChart',
title: '胶囊柱图',
category: ChatCategoryEnum.BAR,
categoryName: ChatCategoryEnumName.BAR,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.COMMON,
image
}

View File

@@ -0,0 +1,226 @@
<template>
<div
v-if="state.mergedConfig"
class="go-dv-capsule-chart"
:style="{
fontSize: numberSizeHandle(state.mergedConfig.valueFontSize),
paddingLeft: numberSizeHandle(state.mergedConfig.paddingLeft),
paddingRight: numberSizeHandle(state.mergedConfig.paddingRight)
}"
>
<div class="label-column">
<div
v-for="item in state.mergedConfig.dataset.source"
:key="item[state.mergedConfig.dataset.dimensions[0]]"
:style="{ height: state.capsuleItemHeight, lineHeight: state.capsuleItemHeight }"
>
{{ item[state.mergedConfig.dataset.dimensions[0]] }}
</div>
<div class="laset">&nbsp;</div>
</div>
<div class="capsule-container">
<div
v-for="(capsule, index) in state.capsuleLength"
:key="index"
class="capsule-item"
:style="{ height: state.capsuleItemHeight }"
>
<div
class="capsule-item-column"
:style="`width: ${capsule * 100}%; background-color: ${
state.mergedConfig.colors[index % state.mergedConfig.colors.length]
};height:calc(100% - ${2}px);`"
>
<div v-if="state.mergedConfig.showValue" class="capsule-item-value">
{{ state.capsuleValue[index] }}
</div>
</div>
</div>
<div class="unit-label">
<div v-for="(label, index) in state.labelData" :key="label + index">
{{ label }}
</div>
</div>
</div>
<div v-if="state.mergedConfig.unit" class="unit-text">
{{ state.mergedConfig.unit }}
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted, watch, reactive, PropType } from 'vue'
import { useChartDataFetch } from '@/hooks'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import config, { option } from './config'
import cloneDeep from 'lodash/cloneDeep'
type DataProps = {
name: string | number
value: string | number
[key: string]: string | number
}
interface StateProps {
defaultConfig: {
dataset: {
dimensions: Array<string>
source: Array<DataProps>
}
colors: Array<string>
unit: string
showValue: boolean
itemHeight: number
valueFontSize: number
paddingLeft: number
paddingRight: number
}
mergedConfig: any
capsuleLength: Array<number>
capsuleValue: Array<string | Object>
labelData: Array<number>
capsuleItemHeight: string
}
const props = defineProps({
chartConfig: {
type: Object as PropType<config>,
default: () => ({})
}
})
const state = reactive<StateProps>({
defaultConfig: option,
mergedConfig: null,
capsuleLength: [],
capsuleValue: [],
labelData: [],
capsuleItemHeight: ''
})
watch(
() => props.chartConfig.option,
newVal => {
calcData(newVal)
},
{
deep: true
}
)
const calcData = (data: any) => {
mergeConfig(props.chartConfig.option)
calcCapsuleLengthAndLabelData()
}
const mergeConfig = (data: any) => {
state.mergedConfig = cloneDeep(data || {})
}
// 数据解析
const calcCapsuleLengthAndLabelData = () => {
const { source } = state.mergedConfig.dataset
if (!source.length) return
state.capsuleItemHeight = numberSizeHandle(state.mergedConfig.itemHeight)
const capsuleValue = source.map((item: DataProps) => item[state.mergedConfig.dataset.dimensions[1]])
const maxValue = Math.max(...capsuleValue)
state.capsuleValue = capsuleValue
state.capsuleLength = capsuleValue.map((v: any) => (maxValue ? v / maxValue : 0))
const oneFifth = maxValue / 5
const labelData = Array.from(new Set(new Array(6).fill(0).map((v, i) => Math.ceil(i * oneFifth))))
state.labelData = labelData
}
const numberSizeHandle = (val: string | number) => {
return val + 'px'
}
onMounted(() => {
calcData(props.chartConfig.option)
})
// 预览
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
calcData(newData)
})
</script>
<style lang="scss" scoped>
@include go('dv-capsule-chart') {
position: relative;
display: flex;
flex-direction: row;
box-sizing: border-box;
padding: 20px;
padding-right: 50px;
color: #b9b8cc;
.label-column {
display: flex;
flex-direction: column;
justify-content: space-between;
box-sizing: border-box;
padding-right: 10px;
text-align: right;
> div:not(:last-child) {
margin: 5px 0;
}
}
.capsule-container {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.capsule-item {
box-shadow: 0 0 3px #999;
height: 10px;
margin: 5px 0px;
border-radius: 5px;
.capsule-item-column {
position: relative;
height: 8px;
margin-top: 1px;
border-radius: 5px;
transition: all 0.3s;
display: flex;
justify-content: flex-end;
align-items: center;
.capsule-item-value {
padding-left: 10px;
transform: translateX(100%);
}
}
}
.unit-label {
height: 20px;
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
}
.unit-text {
text-align: right;
display: flex;
align-items: flex-end;
line-height: 20px;
margin-left: 10px;
}
}
</style>

View File

@@ -1,4 +1,5 @@
import { BarCommonConfig } from './BarCommon/index'
import { BarCrossrangeConfig } from './BarCrossrange/index'
import { CapsuleChartConfig } from './CapsuleChart/index'
export default [BarCommonConfig, BarCrossrangeConfig]
export default [BarCommonConfig, BarCrossrangeConfig, CapsuleChartConfig]

View File

@@ -2,19 +2,27 @@ import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
import { LineCommonConfig } from './index'
import { CreateComponentType } from '@/packages/index.d'
import { defaultTheme, chartColorsSearch } from '@/settings/chartThemes/index'
import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json'
export const includes = ['legend', 'xAxis', 'yAxis']
export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
export const seriesItem = {
type: 'line',
label: {
show: true,
position: 'top',
color: '#fff',
fontSize: 12
},
symbolSize: 5, //设定实心点的大小
itemStyle: {
color: null,
borderRadius: 0
},
lineStyle: {
type: 'solid',
width: 3,
itemStyle: {
color: null,
borderRadius: 0
}
color: null
}
}
@@ -26,9 +34,6 @@ export const option = {
type: 'line'
}
},
legend: {
show: true
},
xAxis: {
show: true,
type: 'category'
@@ -43,7 +48,7 @@ export const option = {
export default class Config extends PublicConfigClass implements CreateComponentType {
public key: string = LineCommonConfig.key
public chartConfig = LineCommonConfig
public chartConfig = cloneDeep(LineCommonConfig)
// 图表配置项
public option = echartOptionProfixHandle(option, includes)
}

View File

@@ -1,12 +1,7 @@
<template>
<!-- Echarts 全局设置 -->
<global-setting :optionData="optionData"></global-setting>
<CollapseItem
v-for="(item, index) in seriesList"
:key="index"
:name="`折线图-${index + 1}`"
:expanded="true"
>
<CollapseItem v-for="(item, index) in seriesList" :key="index" :name="`折线图-${index + 1}`" :expanded="true">
<SettingItemBox name="线条">
<SettingItem name="宽度">
<n-input-number
@@ -15,16 +10,48 @@
:max="100"
size="small"
placeholder="自动计算"
></n-input-number>
></n-input-number>
</SettingItem>
<SettingItem name="类型">
<n-select
v-model:value="item.lineStyle.type"
size="small"
:options="lineConf.lineStyle.type"
></n-select>
<n-select v-model:value="item.lineStyle.type" size="small" :options="lineConf.lineStyle.type"></n-select>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="实心点">
<SettingItem name="大小">
<n-input-number
v-model:value="item.symbolSize"
:min="1"
:max="100"
size="small"
placeholder="自动计算"
></n-input-number>
</SettingItem>
</SettingItemBox>
<setting-item-box name="标签">
<setting-item>
<n-space>
<n-switch v-model:value="item.label.show" size="small" />
<n-text>展示标签</n-text>
</n-space>
</setting-item>
<setting-item name="大小">
<n-input-number v-model:value="item.label.fontSize" size="small" :min="1"></n-input-number>
</setting-item>
<setting-item name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="item.label.color"></n-color-picker>
</setting-item>
<setting-item name="位置">
<n-select
v-model:value="item.label.position"
:options="[
{ label: 'top', value: 'top' },
{ label: 'left', value: 'left' },
{ label: 'right', value: 'right' },
{ label: 'bottom', value: 'bottom' }
]"
/>
</setting-item>
</setting-item-box>
</CollapseItem>
</template>
@@ -32,12 +59,7 @@
import { PropType, computed } from 'vue'
import { lineConf } from '@/packages/chartConfiguration/echarts/index'
import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
import {
GlobalSetting,
CollapseItem,
SettingItemBox,
SettingItem
} from '@/components/Pages/ChartItemSetting'
import { GlobalSetting, CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
const props = defineProps({
optionData: {

View File

@@ -24,6 +24,7 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore
import { useChartDataFetch } from '@/hooks'
import { isPreview } from '@/utils'
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import isObject from 'lodash/isObject'
const props = defineProps({
themeSetting: {
@@ -51,17 +52,22 @@ const option = computed(() => {
// dataset 无法变更条数的补丁
watch(
() => props.chartConfig.option.dataset,
(newData, oldData) => {
if (newData?.dimensions.length !== oldData?.dimensions.length) {
const seriesArr = []
for (let i = 0; i < newData.dimensions.length - 1; i++) {
seriesArr.push(seriesItem)
(newData: { dimensions: any }, oldData) => {
try {
if (!isObject(newData) || !('dimensions' in newData)) return
if (Array.isArray(newData?.dimensions)) {
const seriesArr = []
for (let i = 0; i < newData.dimensions.length - 1; i++) {
seriesArr.push(seriesItem)
}
replaceMergeArr.value = ['series']
props.chartConfig.option.series = seriesArr
nextTick(() => {
replaceMergeArr.value = []
})
}
replaceMergeArr.value = ['series']
props.chartConfig.option.series = seriesArr
nextTick(() => {
replaceMergeArr.value = []
})
} catch (error) {
console.log(error)
}
},
{

View File

@@ -3,9 +3,10 @@ import { LineGradientSingleConfig } from './index'
import { CreateComponentType } from '@/packages/index.d'
import { graphic } from 'echarts/core'
import { defaultTheme, chartColorsSearch } from '@/settings/chartThemes/index'
import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json'
export const includes = ['legend', 'xAxis', 'yAxis']
export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
const options = {
tooltip: {
@@ -15,9 +16,6 @@ const options = {
type: 'line'
}
},
legend: {
show: true
},
xAxis: {
show: true,
type: 'category'
@@ -31,6 +29,13 @@ const options = {
{
type: 'line',
smooth: false,
symbolSize: 5, //设定实心点的大小
label: {
show: true,
position: 'top',
color: '#fff',
fontSize: 12
},
lineStyle: {
type: 'solid',
width: 3
@@ -54,7 +59,7 @@ const options = {
export default class Config extends PublicConfigClass implements CreateComponentType {
public key: string = LineGradientSingleConfig.key
public chartConfig = LineGradientSingleConfig
public chartConfig = cloneDeep(LineGradientSingleConfig)
// 图表配置项
public option = echartOptionProfixHandle(options, includes)
}

View File

@@ -1,12 +1,7 @@
<template>
<!-- Echarts 全局设置 -->
<global-setting :optionData="optionData"></global-setting>
<CollapseItem
v-for="(item, index) in seriesList"
:key="index"
name="单折线面积图"
:expanded="true"
>
<CollapseItem v-for="(item, index) in seriesList" :key="index" name="单折线面积图" :expanded="true">
<SettingItemBox name="线条">
<SettingItem name="宽度">
<n-input-number
@@ -18,13 +13,45 @@
></n-input-number>
</SettingItem>
<SettingItem name="类型">
<n-select
v-model:value="item.lineStyle.type"
size="small"
:options="lineConf.lineStyle.type"
></n-select>
<n-select v-model:value="item.lineStyle.type" size="small" :options="lineConf.lineStyle.type"></n-select>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="实心点">
<SettingItem name="大小">
<n-input-number
v-model:value="item.symbolSize"
:min="1"
:max="100"
size="small"
placeholder="自动计算"
></n-input-number>
</SettingItem>
</SettingItemBox>
<setting-item-box name="标签">
<setting-item>
<n-space>
<n-switch v-model:value="item.label.show" size="small" />
<n-text>展示标签</n-text>
</n-space>
</setting-item>
<setting-item name="大小">
<n-input-number v-model:value="item.label.fontSize" size="small" :min="1"></n-input-number>
</setting-item>
<setting-item name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="item.label.color"></n-color-picker>
</setting-item>
<setting-item name="位置">
<n-select
v-model:value="item.label.position"
:options="[
{ label: 'top', value: 'top' },
{ label: 'left', value: 'left' },
{ label: 'right', value: 'right' },
{ label: 'bottom', value: 'bottom' }
]"
/>
</setting-item>
</setting-item-box>
</CollapseItem>
</template>
@@ -32,18 +59,13 @@
import { PropType, computed } from 'vue'
import { lineConf } from '@/packages/chartConfiguration/echarts/index'
import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
import {
GlobalSetting,
CollapseItem,
SettingItemBox,
SettingItem
} from '@/components/Pages/ChartItemSetting'
import { GlobalSetting, CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
const props = defineProps({
optionData: {
type: Object as PropType<GlobalThemeJsonType>,
required: true
},
}
})
const seriesList = computed(() => {

View File

@@ -43,23 +43,27 @@ const option = reactive({
watch(
() => chartEditStore.getEditCanvasConfig.chartThemeColor,
(newColor: keyof typeof chartColorsSearch) => {
if (!isPreview()) {
const themeColor = chartColorsSearch[newColor] || chartColorsSearch[defaultTheme]
props.chartConfig.option.series.forEach((value: any, index: number) => {
value.areaStyle.color = new graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: themeColor[3]
},
{
offset: 1,
color: 'rgba(0,0,0, 0)'
}
])
})
try {
if (!isPreview()) {
const themeColor = chartColorsSearch[newColor] || chartColorsSearch[defaultTheme]
props.chartConfig.option.series.forEach((value: any, index: number) => {
value.areaStyle.color = new graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: themeColor[3]
},
{
offset: 1,
color: 'rgba(0,0,0, 0)'
}
])
})
}
option.value = mergeTheme(props.chartConfig.option, props.themeSetting, includes)
props.chartConfig.option = option.value
} catch (error) {
console.log(error)
}
option.value = mergeTheme(props.chartConfig.option, props.themeSetting, includes)
props.chartConfig.option = option.value
},
{
immediate: true
@@ -70,9 +74,6 @@ watch(
() => props.chartConfig.option.dataset,
() => {
option.value = props.chartConfig.option
},
{
deep: false
}
)

View File

@@ -3,14 +3,12 @@ import { LineGradientsConfig } from './index'
import { CreateComponentType } from '@/packages/index.d'
import { graphic } from 'echarts/core'
import { defaultTheme, chartColorsSearch } from '@/settings/chartThemes/index'
import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json'
export const includes = ['legend', 'xAxis', 'yAxis']
export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
const option = {
legend: {
show: true
},
tooltip: {
show: true,
trigger: 'axis',
@@ -31,6 +29,13 @@ const option = {
{
type: 'line',
smooth: false,
symbolSize: 5, //设定实心点的大小
label: {
show: true,
position: 'top',
color: '#fff',
fontSize: 12
},
lineStyle: {
width: 3,
type: 'solid'
@@ -52,6 +57,12 @@ const option = {
{
type: 'line',
smooth: false,
label: {
show: true,
position: 'top',
color: '#fff',
fontSize: 12
},
lineStyle: {
width: 3,
type: 'solid'
@@ -75,7 +86,7 @@ const option = {
export default class Config extends PublicConfigClass implements CreateComponentType {
public key: string = LineGradientsConfig.key
public chartConfig = LineGradientsConfig
public chartConfig = cloneDeep(LineGradientsConfig)
// 图表配置项
public option = echartOptionProfixHandle(option, includes)
}

View File

@@ -12,7 +12,6 @@
<n-input-number
v-model:value="item.lineStyle.width"
:min="1"
:max="100"
size="small"
placeholder="自动计算"
></n-input-number>
@@ -25,6 +24,50 @@
></n-select>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="实心点">
<SettingItem name="大小">
<n-input-number
v-model:value="item.symbolSize"
:min="1"
:max="100"
size="small"
placeholder="自动计算"
></n-input-number>
</SettingItem>
</SettingItemBox>
<setting-item-box name="标签">
<setting-item>
<n-space>
<n-switch v-model:value="item.label.show" size="small" />
<n-text>展示标签</n-text>
</n-space>
</setting-item>
<setting-item name="大小">
<n-input-number
v-model:value="item.label.fontSize"
size="small"
:min="1"
></n-input-number>
</setting-item>
<setting-item name="颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="item.label.color"
></n-color-picker>
</setting-item>
<setting-item name="位置">
<n-select
v-model:value="item.label.position"
:options="[
{ label: 'top', value: 'top' },
{ label: 'left', value: 'left' },
{ label: 'right', value: 'right' },
{ label: 'bottom', value: 'bottom' },
]"
/>
</setting-item>
</setting-item-box>
</CollapseItem>
</template>

View File

@@ -42,23 +42,27 @@ const option = reactive({
watch(
() => chartEditStore.getEditCanvasConfig.chartThemeColor,
(newColor: keyof typeof chartColorsSearch) => {
if (!isPreview()) {
const themeColor = chartColorsSearch[newColor] || chartColorsSearch[defaultTheme]
props.chartConfig.option.series.forEach((value: any, index: number) => {
value.areaStyle.color = new graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: themeColor[3 + index]
},
{
offset: 1,
color: 'rgba(0,0,0, 0)'
}
])
})
try {
if (!isPreview()) {
const themeColor = chartColorsSearch[newColor] || chartColorsSearch[defaultTheme]
props.chartConfig.option.series.forEach((value: any, index: number) => {
value.areaStyle.color = new graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: themeColor[3 + index]
},
{
offset: 1,
color: 'rgba(0,0,0, 0)'
}
])
})
}
option.value = mergeTheme(props.chartConfig.option, props.themeSetting, includes)
props.chartConfig.option = option.value
} catch (error) {
console.log(error)
}
option.value = mergeTheme(props.chartConfig.option, props.themeSetting, includes)
props.chartConfig.option = option.value
},
{
immediate: true
@@ -71,6 +75,5 @@ watch(
option.value = props.chartConfig.option
}
)
const { vChartRef } = useChartDataFetch(props.chartConfig, useChartEditStore)
</script>

View File

@@ -2,9 +2,10 @@ import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
import { LineLinearSingleConfig } from './index'
import { CreateComponentType } from '@/packages/index.d'
import { defaultTheme, chartColorsSearch } from '@/settings/chartThemes/index'
import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json'
export const includes = ['legend', 'xAxis', 'yAxis']
export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
export const option = {
tooltip: {
@@ -14,9 +15,6 @@ export const option = {
type: 'line'
}
},
legend: {
show: true
},
xAxis: {
show: true,
type: 'category'
@@ -29,6 +27,7 @@ export const option = {
series: [
{
type: 'line',
symbolSize: 5, //设定实心点的大小
lineStyle: {
type: 'solid',
width: 3,
@@ -56,7 +55,7 @@ export const option = {
export default class Config extends PublicConfigClass implements CreateComponentType {
public key: string = LineLinearSingleConfig.key
public chartConfig = LineLinearSingleConfig
public chartConfig = cloneDeep(LineLinearSingleConfig)
// 图表配置项
public option = echartOptionProfixHandle(option, includes)
}

View File

@@ -39,6 +39,17 @@
></n-select>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="实心点">
<SettingItem name="大小">
<n-input-number
v-model:value="item.symbolSize"
:min="1"
:max="100"
size="small"
placeholder="自动计算"
></n-input-number>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="阴影" :alone="true">
<SettingItem name="颜色">
<n-color-picker

View File

@@ -43,17 +43,21 @@ const option = reactive({
watch(
() => chartEditStore.getEditCanvasConfig.chartThemeColor,
(newColor: keyof typeof chartColorsSearch) => {
if (!isPreview()) {
const themeColor = chartColorsSearch[newColor] || chartColorsSearch[defaultTheme]
props.chartConfig.option.series.forEach((value: any) => {
value.lineStyle.shadowColor = themeColor[2]
value.lineStyle.color.colorStops.forEach((v: { color: string }, i: number) => {
v.color = themeColor[i]
try {
if (!isPreview()) {
const themeColor = chartColorsSearch[newColor] || chartColorsSearch[defaultTheme]
props.chartConfig.option.series.forEach((value: any) => {
value.lineStyle.shadowColor = themeColor[2]
value.lineStyle.color.colorStops.forEach((v: { color: string }, i: number) => {
v.color = themeColor[i]
})
})
})
}
option.value = mergeTheme(props.chartConfig.option, props.themeSetting, includes)
props.chartConfig.option = option.value
} catch (error) {
console.log(error)
}
option.value = mergeTheme(props.chartConfig.option, props.themeSetting, includes)
props.chartConfig.option = option.value
},
{
immediate: true

View File

@@ -0,0 +1,83 @@
import { PublicConfigClass } from '@/packages/public'
import { CreateComponentType } from '@/packages/index.d'
import { MapAmapConfig } from './index'
import { chartInitConfig } from '@/settings/designSetting'
import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json'
export enum ThemeEnum {
NORMAL = 'normal',
DARK = 'dark',
LIGHT = 'light',
WHITES_MOKE = 'whitesmoke',
FRESH = 'fresh',
GREY = 'grey',
GRAFFITI = 'graffiti',
MACARON = 'macaron',
BLUE = 'blue',
DARKBLUE = 'darkblue',
WINE = 'wine'
}
export enum LangEnum {
ZH_CN = 'zh_cn',
EN = 'en',
ZH_EN = 'zh_en'
}
export enum ViewModeEnum {
PLANE = '2D',
STEREOSCOPIC = '3D'
}
export enum FeaturesEnum {
BG = 'bg',
POINT = 'point',
ROAD = 'road',
BUILDING = 'building'
}
export enum MarkerEnum {
// 圆圈
CIRCLE_MARKER = 'CircleMarker',
// 定位标点
MARKER = 'Marker',
// 暂无
NONE = 'none'
}
export const option = {
dataset: dataJson,
mapOptions: {
pitch: 60,
skyColor: '#53A9DE',
amapKey: 'd5f3e16589dbecae64d05fe90e2ba4f2',
amapStyleKey: ThemeEnum.DARK,
amapStyleKeyCustom: '',
amapLon: 116.397428,
amapLat: 39.90923,
amapZindex: 11,
marker: {
fillColor: '#E98984FF',
fillOpacity: 0.5,
strokeColor: 'white',
strokeWeight: 2,
strokeOpacity: 0.5,
zIndex: 10,
bubble: true,
cursor: 'pointer',
clickable: true
},
mapMarkerType: MarkerEnum.CIRCLE_MARKER,
viewMode: ViewModeEnum.PLANE,
lang: LangEnum.ZH_CN,
features: [FeaturesEnum.BG, FeaturesEnum.POINT, FeaturesEnum.ROAD, FeaturesEnum.BUILDING]
}
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key = MapAmapConfig.key
public attr = { ...chartInitConfig, w: 1000, h: 800, zIndex: -1 }
public chartConfig = cloneDeep(MapAmapConfig)
public option = cloneDeep(option)
}

View File

@@ -0,0 +1,199 @@
<template>
<collapse-item name="基础" :expanded="true">
<setting-item-box name="语言类型" :alone="true">
<setting-item>
<n-select size="small" v-model:value="optionData.mapOptions.lang" :options="langOptions" />
</setting-item>
</setting-item-box>
<setting-item-box name="Key" :alone="true">
<setting-item name="请务必使用自己的高德应用 key">
<n-input v-model:value="optionData.mapOptions.amapKey" size="small"></n-input>
</setting-item>
</setting-item-box>
<setting-item-box name="自定义地图样式ID" :alone="true">
<setting-item>
<n-input size="small" v-model:value="optionData.mapOptions.amapStyleKeyCustom" />
</setting-item>
</setting-item-box>
</collapse-item>
<collapse-item name="地图" :expanded="true">
<setting-item-box name="主题">
<setting-item>
<n-select size="small" v-model:value="optionData.mapOptions.amapStyleKey" :options="themeOptions" />
</setting-item>
</setting-item-box>
<setting-item-box name="内容" :alone="true">
<n-checkbox-group v-model:value="optionData.mapOptions.features">
<n-space item-style="display: flex;">
<n-checkbox :value="item.value" :label="item.label" v-for="(item, index) in featuresOptions" :key="index" />
</n-space>
</n-checkbox-group>
</setting-item-box>
<setting-item-box name="位置">
<setting-item name="经度">
<n-input-number v-model:value="optionData.mapOptions.amapLon" :show-button="false" size="small">
<template #suffix>°</template>
</n-input-number>
</setting-item>
<setting-item name="纬度">
<n-input-number v-model:value="optionData.mapOptions.amapLat" :show-button="false" size="small">
<template #suffix>°</template>
</n-input-number>
</setting-item>
<setting-item name="初始缩放">
<n-input-number v-model:value="optionData.mapOptions.amapZindex" :min="0" size="small"></n-input-number>
</setting-item>
</setting-item-box>
<setting-item-box name="模式" :alone="true">
<setting-item>
<n-radio-group v-model:value="optionData.mapOptions.viewMode" name="radiogroup">
<n-space>
<n-radio v-for="song in viewModeOptions" :key="song.value" :value="song.value">
{{ song.label }}
</n-radio>
</n-space>
</n-radio-group>
</setting-item>
</setting-item-box>
<template v-if="optionData.mapOptions.viewMode === '3D'">
<setting-item-box>
<setting-item name="天空色">
<n-color-picker size="small" :modes="['hex']" v-model:value="optionData.mapOptions.skyColor"></n-color-picker>
</setting-item>
<setting-item name="俯仰角">
<n-input-number v-model:value="optionData.mapOptions.pitch" :min="0" :max="83" size="small"></n-input-number>
</setting-item>
</setting-item-box>
</template>
</collapse-item>
<collapse-item name="标记" :expanded="true">
<setting-item-box name="样式">
<setting-item name="类型">
<n-select size="small" v-model:value="optionData.mapOptions.mapMarkerType" :options="MarkerOptions" />
</setting-item>
<setting-item name="颜色">
<n-color-picker v-model:value="optionData.mapOptions.marker.fillColor" size="small"></n-color-picker>
</setting-item>
</setting-item-box>
</collapse-item>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { option, MarkerEnum, ThemeEnum, LangEnum, ViewModeEnum, FeaturesEnum } from './config'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
defineProps({
optionData: {
type: Object as PropType<typeof option>,
required: true
}
})
const themeOptions = [
{
value: ThemeEnum.NORMAL,
label: '标准'
},
{
value: ThemeEnum.DARK,
label: '幻影黑'
},
{
value: ThemeEnum.LIGHT,
label: '月光银'
},
{
value: ThemeEnum.WHITES_MOKE,
label: '远山黛'
},
{
value: ThemeEnum.FRESH,
label: '草色青'
},
{
value: ThemeEnum.GREY,
label: '雅士灰'
},
{
value: ThemeEnum.GRAFFITI,
label: '涂鸦'
},
{
value: ThemeEnum.MACARON,
label: '马卡龙'
},
{
value: ThemeEnum.BLUE,
label: '靛青蓝'
},
{
value: ThemeEnum.DARKBLUE,
label: '极夜蓝'
},
{
value: ThemeEnum.WINE,
label: '酱籽'
}
]
const langOptions = [
{
value: LangEnum.ZH_CN,
label: '中文简体'
},
{
value: LangEnum.EN,
label: '英文'
},
{
value: LangEnum.ZH_EN,
label: '中英文对照'
}
]
const viewModeOptions = [
{
value: ViewModeEnum.PLANE,
label: '2D'
},
{
value: ViewModeEnum.STEREOSCOPIC,
label: '3D'
}
]
const featuresOptions = [
{
value: FeaturesEnum.BG,
label: '显示地图背景'
},
{
value: FeaturesEnum.POINT,
label: '显示标识'
},
{
value: FeaturesEnum.ROAD,
label: '显示道路'
},
{
value: FeaturesEnum.BUILDING,
label: '显示建筑'
}
]
const MarkerOptions = [
{
value: MarkerEnum.CIRCLE_MARKER,
label: '圆形标点'
},
{
value: MarkerEnum.MARKER,
label: '定位标点'
},
{
value: MarkerEnum.NONE,
label: '隐藏标点'
}
]
</script>

View File

@@ -0,0 +1,19 @@
{
"markers": [
{
"name": "某某地市",
"value": 10,
"position": [116.300467, 39.907761]
},
{
"name": "某某地市",
"value": 15,
"position": [116.400567, 39.908761]
},
{
"name": "某某地市",
"value": 20,
"position": [116.200467, 39.937761]
}
]
}

View File

@@ -1,12 +1,12 @@
import image from '@/assets/images/chart/charts/map.png'
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import image from '@/assets/images/chart/charts/map_amap.png'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
export const MapChinaConfig: ConfigType = {
key: 'MapChina',
chartKey: 'VMapChina',
conKey: 'VCMapChina',
title: '地图',
export const MapAmapConfig: ConfigType = {
key: 'MapAmap',
chartKey: 'VMapAmap',
conKey: 'VCMapAmap',
title: '高德地图',
category: ChatCategoryEnum.MAP,
categoryName: ChatCategoryEnumName.MAP,
package: PackagesCategoryEnum.CHARTS,

View File

@@ -0,0 +1,130 @@
<template>
<div ref="vChartRef"></div>
</template>
<script setup lang="ts">
import { ref, PropType, toRefs, watch } from 'vue'
import AMapLoader from '@amap/amap-jsapi-loader'
import { CreateComponentType } from '@/packages/index.d'
import { useChartDataFetch } from '@/hooks'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { MarkerEnum } from './config'
import { isArray } from '@/utils'
const props = defineProps({
chartConfig: {
type: Object as PropType<CreateComponentType>,
required: true
}
})
let {
amapKey,
amapStyleKey,
amapLon,
amapLat,
amapZindex,
mapMarkerType,
lang,
amapStyleKeyCustom,
features,
viewMode,
pitch,
skyColor,
marker
} = toRefs(props.chartConfig.option.mapOptions)
let mapIns: any = null
let markers: any = []
let AMapIns: any = null
const vChartRef = ref<HTMLElement>()
const initMap = (newData: any) => {
// 初始化
AMapLoader.load({
key: amapKey.value, //api服务key--另外需要在public中使用安全密钥
version: '1.4.8', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: ['AMap.PlaceSearch', 'AMap.AutoComplete'] // 需要使用的的插件列表
})
.then(AMap => {
AMapIns = AMap
mapIns = new AMap.Map(vChartRef.value, {
resizeEnable: true,
zoom: amapZindex.value, // 地图显示的缩放级别
center: [amapLon.value, amapLat.value],
mapStyle: `amap://styles/${amapStyleKeyCustom.value !== '' ? amapStyleKeyCustom.value : amapStyleKey.value}`, //自定义地图的显示样式
lang: lang.value,
features: features.value,
pitch: pitch.value, // 地图俯仰角度,有效范围 0 度- 83 度
skyColor: skyColor.value,
viewMode: viewMode.value, // 地图模式
willReadFrequently: true
})
dataHandle(props.chartConfig.option.dataset)
})
.catch(e => {})
}
const dataHandle = (newData: any) => {
if (!mapIns && !AMapIns) {
initMap(props.chartConfig.option)
return
}
if (isArray(newData.markers)) {
// 先清除旧标记
mapIns.remove(markers)
markers = []
// 记录新标记
if (mapMarkerType.value === MarkerEnum.MARKER) {
newData.markers.forEach((markerItem: any) => {
const markerInstance = new AMapIns.Marker({
position: [markerItem.position[0], markerItem.position[1]],
offset: new AMapIns.Pixel(-13, -30)
})
markers.push(markerInstance)
markerInstance.setMap(mapIns)
})
} else if (mapMarkerType.value === MarkerEnum.CIRCLE_MARKER) {
newData.markers.forEach((markerItem: any) => {
const markerInstance = new AMapIns.CircleMarker({
center: [markerItem.position[0], markerItem.position[1]],
radius: markerItem.value,
...marker.value
})
markers.push(markerInstance)
markerInstance.setMap(mapIns)
})
}
}
}
const stopWatch = watch(
() => props.chartConfig.option.mapOptions,
option => {
initMap(option)
},
{
immediate: true,
deep: true
}
)
watch(
() => props.chartConfig.option.dataset,
newData => {
try {
dataHandle(newData)
} catch (error) {
console.log(error)
}
},
{
deep: false
}
)
// 预览
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
stopWatch()
dataHandle(newData)
})
</script>

View File

@@ -0,0 +1,157 @@
import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
import { MapBaseConfig } from './index'
import { chartInitConfig } from '@/settings/designSetting'
import { CreateComponentType } from '@/packages/index.d'
import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json'
export const includes = []
export const option = {
dataset: dataJson,
mapRegion: {
adcode: 'china',
showHainanIsLands: true
},
tooltip: {
show: true,
trigger: 'item'
},
visualMap: {
show: true,
orient: 'vertical',
pieces: [
{ gte: 1000, label: '>1000' }, // 不指定 max表示 max 为无限大Infinity
{ gte: 600, lte: 999, label: '600-999' },
{ gte: 200, lte: 599, label: '200-599' },
{ gte: 50, lte: 199, label: '49-199' },
{ gte: 10, lte: 49, label: '10-49' },
{ lte: 9, label: '<9' } // 不指定 min表示 min 为无限大(-Infinity
],
inRange: {
// 渐变颜色,从小到大
color: ['#c3d7df', '#5cb3cc', '#8abcd1', '#66a9c9', '#2f90b9', '#1781b5']
},
textStyle: {
color: '#fff'
}
},
geo: {
show: false,
type: 'map',
roam: false,
map: 'china',
selectedMode: false, //是否允许选中多个区域
zoom: 1
},
series: [
{
name: '',
type: 'effectScatter',
coordinateSystem: 'geo',
symbolSize: 4,
legendHoverLink: true,
showEffectOn: 'render',
rippleEffect: {
scale: 6,
color: '#FFFFFF',
brushType: 'fill'
},
tooltip: {
show: true,
backgroundColor: 'rgba(0,0,0,.6)',
borderColor: 'rgba(147, 235, 248, .8)',
textStyle: {
color: '#FFF'
}
},
label: {
formatter: '{b}',
fontSize: 11,
offset: [0, 2],
position: 'bottom',
textBorderColor: '#fff',
textShadowColor: '#000',
textShadowBlur: 10,
textBorderWidth: 0,
color: '#FFFFFF',
show: true
},
itemStyle: {
color: '#FFFFFF',
borderColor: 'rgba(225,255,255,2)',
borderWidth: 4,
shadowColor: '#E1FFFF',
shadowBlur: 10
},
data: []
},
{
name: '区域',
type: 'map',
map: 'china',
data: [],
selectedMode: false,
zoom: 1,
geoIndex: 1,
tooltip: {
show: true,
backgroundColor: '#00000060',
borderColor: 'rgba(147, 235, 248, 0.8)',
textStyle: {
color: '#FFFFFF',
fontSize: 12,
}
},
label: {
show: false,
color: '#FFFFFF',
fontSize: 12,
},
emphasis: {
disabled: false,
label: {
color: '#FFFFFF',
fontSize: 12,
},
itemStyle: {
areaColor: '#389BB7',
shadowColor: '#389BB7',
borderWidth: 1
}
},
itemStyle: {
borderColor: '#93EBF8',
borderWidth: 1,
areaColor: {
type: 'radial',
x: 0.5,
y: 0.5,
r: 0.8,
colorStops: [
{
offset: 0,
color: '#93ebf800' // 0% 处的颜色
},
{
offset: 1,
color: '#93ebf820' // 100% 处的颜色
}
],
globalCoord: false
},
shadowColor: '#80D9F842',
shadowOffsetX: -2,
shadowOffsetY: 2,
shadowBlur: 10
}
}
]
}
export const MapDefaultConfig = { ...option }
export default class Config extends PublicConfigClass implements CreateComponentType {
public key: string = MapBaseConfig.key
public attr = { ...chartInitConfig, w: 750, h: 800, zIndex: -1 }
public chartConfig = cloneDeep(MapBaseConfig)
public option = echartOptionProfixHandle(option, includes)
}

View File

@@ -0,0 +1,277 @@
<template>
<!-- Echarts 全局设置 -->
<global-setting :optionData="optionData"></global-setting>
<CollapseItem name="地图" :expanded="true">
<SettingItemBox name="地图区域">
<SettingItem name="默认中国">
<n-select
size="small"
v-model:value="mapRegion.adcode"
:options="mapRegionOptions"
value-field="adcode"
label-field="name"
/>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="区域颜色">
<SettingItem name="0%处颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].itemStyle.areaColor.colorStops[0].color"
></n-color-picker>
</SettingItem>
<SettingItem name="100%处颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].itemStyle.areaColor.colorStops[1].color"
></n-color-picker>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="阴影">
<SettingItem name="颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].itemStyle.shadowColor"
></n-color-picker>
</SettingItem>
<SettingItem name="模糊程度">
<n-input-number
v-model:value="seriesList[1].itemStyle.shadowBlur"
:min="0"
size="small"
placeholder="请输入模糊程度"
></n-input-number>
</SettingItem>
<SettingItem name="水平偏移">
<n-input-number
v-model:value="seriesList[1].itemStyle.shadowOffsetX"
size="small"
placeholder="请输入水平偏移大小"
></n-input-number>
</SettingItem>
<SettingItem name="垂直偏移">
<n-input-number
v-model:value="seriesList[1].itemStyle.shadowOffsetY"
size="small"
placeholder="请输入垂直偏移大小"
></n-input-number>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="地理信息名称">
<SettingItem name="显示">
<n-space>
<n-switch v-model:value="seriesList[1].label.show" size="small"></n-switch>
</n-space>
</SettingItem>
<SettingItem name="字体颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].label.color"
></n-color-picker>
</SettingItem>
<SettingItem name="字体大小">
<n-input-number
v-model:value="seriesList[1].label.fontSize"
:min="1"
size="small"
placeholder="请输入字体大小"
></n-input-number>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="悬浮 (预览可见)">
<SettingItem name="禁用">
<n-space>
<n-switch v-model:value="seriesList[1].emphasis.disabled" size="small"></n-switch>
</n-space>
</SettingItem>
<SettingItem name="颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].emphasis.itemStyle.areaColor"
></n-color-picker>
</SettingItem>
<SettingItem name="字体大小">
<n-input-number
v-model:value="seriesList[1].emphasis.label.fontSize"
:min="1"
size="small"
placeholder="请输入字体大小"
></n-input-number>
</SettingItem>
<SettingItem name="阴影">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].emphasis.itemStyle.shadowColor"
></n-color-picker>
</SettingItem>
<SettingItem name="边框大小">
<n-input-number
v-model:value="seriesList[1].emphasis.itemStyle.borderWidth"
:min="1"
size="small"
placeholder="请输入边框大小"
></n-input-number>
</SettingItem>
<SettingItem name="文字颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].emphasis.label.color"
></n-color-picker>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="悬浮弹窗">
<SettingItem name="显示">
<n-space>
<n-switch v-model:value="seriesList[1].tooltip.show" size="small"></n-switch>
</n-space>
</SettingItem>
<SettingItem name="字体大小">
<n-input-number
v-model:value="seriesList[1].tooltip.textStyle.fontSize"
:min="1"
size="small"
placeholder="请输入字体大小"
></n-input-number>
</SettingItem>
<SettingItem name="字体颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].tooltip.textStyle.color"
></n-color-picker>
</SettingItem>
<SettingItem name="背景颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].tooltip.backgroundColor"
></n-color-picker>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="区域边框">
<SettingItem name="颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].itemStyle.borderColor"
></n-color-picker>
</SettingItem>
<SettingItem name="宽度大小">
<n-input-number
v-model:value="seriesList[1].itemStyle.borderWidth"
:min="1"
size="small"
placeholder="请输入边框大小"
></n-input-number>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="其他" v-if="mapRegion.adcode === 'china'">
<SettingItem>
<n-checkbox v-model:checked="mapRegion.showHainanIsLands" size="small">显示南海群岛</n-checkbox>
</SettingItem>
</SettingItemBox>
</CollapseItem>
<CollapseItem name="标记" :expanded="true">
<SettingItemBox name="样式">
<SettingItem name="大小">
<n-input-number v-model:value="seriesList[0].symbolSize" size="small" :min="0"></n-input-number>
</SettingItem>
<SettingItem name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="seriesList[0].itemStyle.color"></n-color-picker>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="文本">
<SettingItem name="显示">
<n-space>
<n-switch v-model:value="seriesList[0].label.show" size="small"></n-switch>
</n-space>
</SettingItem>
<SettingItem name="字体大小">
<n-input-number v-model:value="seriesList[0].label.fontSize" size="small" :min="0"></n-input-number>
</SettingItem>
<SettingItem name="字体颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="seriesList[0].label.color"></n-color-picker>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="涟漪">
<SettingItem name="涟漪大小">
<n-input-number
v-model:value="seriesList[0].rippleEffect.scale"
:min="1"
size="small"
placeholder="请输入涟漪大小"
></n-input-number>
</SettingItem>
<SettingItem name="涟漪颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="seriesList[0].rippleEffect.color"></n-color-picker>
</SettingItem>
<SettingItem name="涟漪的绘制方式">
<n-select size="small" v-model:value="seriesList[0].rippleEffect.brushType" :options="rippleEffectOptions" />
</SettingItem>
</SettingItemBox>
</CollapseItem>
</template>
<script setup lang="ts">
import { PropType, computed } from 'vue'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
import { GlobalSetting } from '@/components/Pages/ChartItemSetting'
import { ref } from 'vue'
import mapChinaJson from './mapGeojson/china.json'
const mapRegionOptions = ref([
{
adcode: 'china',
name: '中国'
}
])
const rippleEffectOptions = ref([
{
value: 'fill',
label: '实心'
},
{
value: 'stroke',
label: '空心'
}
])
const props = defineProps({
optionData: {
type: Object as PropType<GlobalThemeJsonType>,
required: true
}
})
const initMapRegionOptions = () => {
mapChinaJson.features.forEach((element: any) => {
if (element.properties.name) {
mapRegionOptions.value.push({ ...element.properties })
}
})
}
initMapRegionOptions()
const seriesList = computed(() => {
return props.optionData.series
})
const mapRegion = computed(() => {
return props.optionData.mapRegion
})
</script>

View File

@@ -0,0 +1,79 @@
{
"point": [
{
"name": "北京",
"value": [116.405285, 39.904989, 200]
},
{
"name": "郑州",
"value": [113.665412, 34.757975, 888]
},
{
"name": "青海",
"value": [101.778916, 36.623178, 666]
},
{
"name": "宁夏回族自治区",
"value": [106.278179, 38.46637, 66]
},
{
"name": "哈尔滨市",
"value": [126.642464, 45.756967, 101]
}
],
"map": [
{
"name": "北京市",
"value": 666
},
{
"name": "河北省",
"value": 98
},
{
"name": "江苏省",
"value": 300
},
{
"name": "福建省",
"value": 1199
},
{
"name": "山东省",
"value": 86
},
{
"name": "河南省",
"value": 850
},
{
"name": "湖北省",
"value": 84
},
{
"name": "广西壮族自治区",
"value": 81
},
{
"name": "海南省",
"value": 900
},
{
"name": "青海省",
"value": 800
},
{
"name": "新疆维吾尔自治区",
"value": 7
}
],
"pieces": [
{ "gte": 1000, "label": ">1000" },
{ "gte": 600, "lte": 999, "label": "600-999" },
{ "gte": 200, "lte": 599, "label": "200-599" },
{ "gte": 50, "lte": 199, "label": "49-199" },
{ "gte": 10, "lte": 49, "label": "10-49" },
{ "lte": 9, "label": "<9" }
]
}

View File

@@ -0,0 +1,15 @@
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import image from '@/assets/images/chart/charts/map.png'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
export const MapBaseConfig: ConfigType = {
key: 'MapBase',
chartKey: 'VMapBase',
conKey: 'VCMapBase',
title: '地图(可选省份)',
category: ChatCategoryEnum.MAP,
categoryName: ChatCategoryEnumName.MAP,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.COMMON,
image
}

View File

@@ -0,0 +1,152 @@
<template>
<v-chart ref="vChartRef" :theme="themeColor" :option="option.value" :manual-update="isPreview()" autoresize>
</v-chart>
</template>
<script setup lang="ts">
import { PropType, reactive, watch, ref, nextTick } from 'vue'
import config, { includes } from './config'
import VChart from 'vue-echarts'
import { use, registerMap } from 'echarts/core'
import { EffectScatterChart, MapChart } from 'echarts/charts'
import { CanvasRenderer } from 'echarts/renderers'
import { useChartDataFetch } from '@/hooks'
import { mergeTheme } from '@/packages/public/chart'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { isPreview } from '@/utils'
import mapJsonWithoutHainanIsLands from './mapWithoutHainanIsLands.json'
import { DatasetComponent, GridComponent, TooltipComponent, GeoComponent, VisualMapComponent } from 'echarts/components'
const props = defineProps({
themeSetting: {
type: Object,
required: true
},
themeColor: {
type: Object,
required: true
},
chartConfig: {
type: Object as PropType<config>,
required: true
}
})
use([
MapChart,
DatasetComponent,
CanvasRenderer,
GridComponent,
TooltipComponent,
GeoComponent,
EffectScatterChart,
VisualMapComponent
])
const option = reactive({
value: mergeTheme(props.chartConfig.option, props.themeSetting, includes)
})
const vChartRef = ref<typeof VChart>()
//动态获取json注册地图
const getGeojson = (regionId: string) => {
return new Promise<boolean>(resolve => {
import(`./mapGeojson/${regionId}.json`).then(data => {
registerMap(regionId, { geoJSON: data.default as any, specialAreas: {} })
resolve(true)
})
})
}
//异步时先注册空的 保证初始化不报错
registerMap(props.chartConfig.option.mapRegion.adcode, { geoJSON: {} as any, specialAreas: {} })
// 进行更换初始化地图 如果为china 单独处理
const registerMapInitAsync = async () => {
await nextTick()
if (props.chartConfig.option.mapRegion.adcode != 'china') {
await getGeojson(props.chartConfig.option.mapRegion.adcode)
} else {
await hainanLandsHandle(props.chartConfig.option.mapRegion.showHainanIsLands)
}
vEchartsSetOption()
}
registerMapInitAsync()
// 手动触发渲染
const vEchartsSetOption = () => {
option.value = props.chartConfig.option
vChartRef.value?.setOption(props.chartConfig.option)
}
// 更新数据处理
const dataSetHandle = async (dataset: any) => {
props.chartConfig.option.series.forEach((item: any) => {
if (item.type === 'effectScatter' && dataset.point) item.data = dataset.point
else if (item.type === 'map' && dataset.map) item.data = dataset.map
})
if (dataset.pieces) props.chartConfig.option.visualMap.pieces = dataset.pieces
isPreview() && vEchartsSetOption()
}
// 处理海南群岛
const hainanLandsHandle = async (newData: boolean) => {
if (newData) {
await getGeojson('china')
} else {
registerMap('china', { geoJSON: mapJsonWithoutHainanIsLands as any, specialAreas: {} })
}
}
//监听 dataset 数据发生变化
watch(
() => props.chartConfig.option.dataset,
newData => {
dataSetHandle(newData)
},
{
immediate: true,
deep: false
}
)
//监听是否显示南海群岛
watch(
() => props.chartConfig.option.mapRegion.showHainanIsLands,
async newData => {
try {
await hainanLandsHandle(newData)
vEchartsSetOption()
} catch (error) {
console.log(error)
}
},
{
deep: false
}
)
//监听地图展示区域发生变化
watch(
() => props.chartConfig.option.mapRegion.adcode,
async newData => {
try {
await getGeojson(newData)
props.chartConfig.option.geo.map = newData
props.chartConfig.option.series.forEach((item: any) => {
if (item.type === 'map') item.map = newData
})
vEchartsSetOption()
} catch (error) {
console.log(error)
}
},
{
deep: false
}
)
// 预览
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
dataSetHandle(newData)
})
</script>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More