Compare commits

...

221 Commits

Author SHA1 Message Date
奔跑的面条
796c844df7 build: 处理解决冲突产生的错误代码 2024-03-15 09:19:22 +08:00
奔跑的面条
85aa2d8283 fix: 解决视频组件动态数据源的问题 2024-03-14 17:15:02 +08:00
奔跑的面条
a4cd1f31b5 feat: 合并1.3.1的内容 2024-03-14 12:07:41 +08:00
奔跑的面条
5588205d8d feat: 合并PR,解决冲突 2024-03-06 11:25:49 +08:00
奔跑的面条
def75f0948 feat: 补充 GC 失去的视频资源 2023-12-18 22:22:16 +08:00
奔跑的面条
a93fd3c036 feat: 补充gitGC丢失的图片,升级版本号到 1.3.0 2023-12-18 22:04:15 +08:00
奔跑的面条
1f856d3631 Merge branch 'dev' 2023-12-17 20:45:50 +08:00
奔跑的面条
6a83cfa7b0 Merge branch 'dev' of https://gitee.com/dromara/go-view into dev 2023-12-17 14:27:16 +08:00
奔跑的面条
eedd2ecf9d test: 测试提交 2023-12-17 06:26:58 +00:00
奔跑的面条
eba9489077 Merge branch 'dev' 2023-12-17 00:20:30 +08:00
奔跑的面条
2e5601f0ba feat: iconify图标新增离线功能 2023-12-17 00:12:50 +08:00
奔跑的面条
da8e0bb6f2 style: 增强代码健壮性 2023-12-16 22:04:04 +08:00
奔跑的面条
78e1d3ffe4 fix: 解决文本组件内边距预览的时候会撑开的问题 2023-12-16 21:50:51 +08:00
奔跑的面条
02b423e620 fix: 解决饼图会自动轮播的问题 2023-12-16 21:44:12 +08:00
奔跑的面条
78c63298d7 perf: 优化公共接口更新数据的逻辑 2023-12-16 21:43:45 +08:00
奔跑的面条
3e641e4bab fix: 解决高版本TS错误问题 2023-12-16 21:26:16 +08:00
奔跑的面条
6ef2bd6b93 docs: update 2023-12-11 10:36:26 +08:00
奔跑的面条
c408cf8e1d docs: update 2023-11-24 21:44:37 +08:00
奔跑的面条
b50326e3c2 docs: add 2023-11-22 17:10:34 +08:00
奔跑的面条
624de4fdb5 docs: update 2023-11-22 15:49:37 +08:00
奔跑的面条
856d7d1de3 Merge branch 'dev' 2023-10-08 15:58:23 +08:00
奔跑的面条
77a129788f docs: update readme 2023-09-27 11:31:29 +08:00
奔跑的面条
4f21020d24 !211 解决发布后访问页面空白报错: Cannot reading 'addEventListener' of null
Merge pull request !211 from Denny/N/A
2023-09-26 04:09:24 +00:00
Denny
31636964ad 解决发布后访问页面空白报错: Cannot reading 'addEventListener' of null
解决问题: 发布后访问页面空白报错:ncaught (in promise) TypeError: Cannot read properties of null (reading 'addEventListener')

Signed-off-by: Denny <kingxi@163.com>
2023-09-26 03:00:36 +00:00
奔跑的面条
fdc39e18dc Merge branch 'dev' 2023-09-18 11:43:20 +08:00
奔跑的面条
d170d94186 fix: 解决分组在预览下的滤镜变换问题 2023-09-18 11:43:04 +08:00
奔跑的面条
5214c27331 fix: 解决window.opener 错误判断 2023-09-18 11:30:08 +08:00
奔跑的面条
af691af61f build: 升级版本到1.2.9 2023-09-18 11:07:39 +08:00
奔跑的面条
ab7ffcddac Merge branch 'dev' 2023-09-18 10:49:12 +08:00
奔跑的面条
19165c76d5 feat: 抽取PR地图下钻代码 2023-09-16 16:52:55 +08:00
ea179f9897 第三方应用open预览地址的时候,发现window.opener并不是一个window对象会报addEventListener不存在。
第三方应用open预览地址的时候,发现window.opener并不是一个window对象会报addEventListener不存在。

Signed-off-by: 空 <jinj@hxcfsoft.com>
2023-09-16 16:10:49 +08:00
奔跑的面条
65d3ee424a docs: update readme 2023-09-14 10:20:50 +08:00
奔跑的面条
55c84f2e39 fix: 解决保存时候可能数据获取不完整的bug 2023-09-13 10:43:11 +08:00
奔跑的面条
f348038ff7 fix: 解决依赖安装会报错的问题 2023-09-06 16:58:42 +08:00
奔跑的面条
dd71c311e0 feat: 解决分组在预览会失效的问题 2023-09-03 23:09:54 +08:00
奔跑的面条
0ab42027c4 style: 优化 pr_200 代码 2023-09-03 18:02:01 +08:00
奔跑的面条
a492ed2440 !200 性能提升, 未知key时处理逻辑调整
Merge pull request !200 from ly-chn/ly-chn
2023-09-03 09:59:15 +00:00
奔跑的面条
4444645dfd fix: 修改关系图的问题 2023-09-03 17:42:11 +08:00
奔跑的面条
c32a9f7d1b !203 feat: 增加关系图力引导布局逻辑
Merge pull request !203 from QuietlyChan/feat-graph
2023-09-03 09:41:19 +00:00
奔跑的面条
8472efd210 fix: 解决预览不会隐藏超出内容的问题 2023-09-03 16:52:31 +08:00
QuietlyChan
4a409393fb 增加关系图力引导布局逻辑 2023-08-30 15:23:41 +08:00
奔跑的面条
0f9e837508 docs: update 2023-08-25 10:40:23 +08:00
奔跑的面条
66a04660fe docs: update 2023-08-24 11:15:57 +08:00
奔跑的面条
a53a6678b7 docs: update 2023-08-24 11:13:59 +08:00
奔跑的面条
310b27f634 docs: add banner 2023-08-18 16:35:10 +08:00
奔跑的面条
552313df12 Merge branch 'dev' 2023-08-17 09:55:45 +08:00
ly-chn
51ba52ae45 fix: 同步时出现特殊key时, 加载进度始终显示, 且无法继续解析后续内容
perf: 大量使用相同组件时, 提升createComponent性能
2023-08-17 09:38:30 +08:00
奔跑的面条
95b50c7d76 fix: 解决TS打包报错 2023-08-15 09:29:06 +08:00
奔跑的面条
d76ddf1126 !197 新增输入框联动组件
Merge pull request !197 from 阿飞/dev1
2023-08-15 01:11:45 +00:00
luoyp
c5788f79b3 新增输入框组件 2023-08-14 11:01:04 +08:00
奔跑的面条
704a7bd8f8 feat: 新增基础分页表格 2023-08-11 23:56:30 +08:00
奔跑的面条
db73346c71 feat: 处理基础表格图片和文案提示 2023-08-11 23:47:05 +08:00
奔跑的面条
ab5ade9be1 perf: 格式化表格组件代码 2023-08-11 22:35:44 +08:00
奔跑的面条
0d3418259c !192 新增分页表格组件
Merge pull request !192 from 阿飞/dev2
2023-08-11 14:22:14 +00:00
奔跑的面条
541ce8a083 feat: 修改柱状图 & 折线图文件位置和名称,格式化内容 2023-08-11 22:20:32 +08:00
奔跑的面条
6b9e993599 !193 新增组合图
Merge pull request !193 from 阿飞/dev3
2023-08-11 14:08:47 +00:00
奔跑的面条
1ad0658a5f !194 新增分页联动组件
Merge pull request !194 from 阿飞/dev4
2023-08-11 14:03:20 +00:00
奔跑的面条
b89e5d702b !190 feat: 增加全屏按钮组件
Merge pull request !190 from QuietlyChan/feat-fullScreen
2023-08-11 13:55:15 +00:00
奔跑的面条
fed515f844 !191 修复单折线渐变图鼠标移入报错
Merge pull request !191 from 阿飞/dev1
2023-08-11 13:50:54 +00:00
奔跑的面条
9f9df3566f !196 修复naive-ui进度图预览显示bug
Merge pull request !196 from 阿飞/dev6
2023-08-11 13:49:47 +00:00
奔跑的面条
39e735b29c fix: 解决了三维地球不能被截图的bug 2023-08-11 21:43:43 +08:00
奔跑的面条
d2ad32e08e fix: 解决地图point的值展示错误的问题 2023-08-09 09:28:48 +08:00
retire
b75cbea6cc feat: 基础事件增加components参数 2023-08-03 21:05:06 +08:00
luoyp
3c1ea60f21 修复Naive-UI进度图预览显示bug 2023-08-03 15:38:47 +08:00
奔跑的面条
fb8034c915 docs: update 2023-08-03 10:47:59 +08:00
奔跑的面条
39f0a136b7 docs: update 2023-08-03 10:38:37 +08:00
奔跑的面条
f83db8a31d docs: update 2023-08-03 10:37:27 +08:00
奔跑的面条
fbf453b9fa docs: update 2023-08-03 10:36:37 +08:00
奔跑的面条
7fd9d339c4 docs: update readme 2023-08-03 10:33:35 +08:00
luoyp
32c5b216f2 修复组合图不显示 2023-08-01 16:44:30 +08:00
luoyp
a08e27da2d 新增分页联动组件 2023-08-01 09:32:55 +08:00
luoyp
4c13dc3184 新增组合图 2023-08-01 09:16:54 +08:00
luoyp
d91c86f01c 新增分页表格组件 2023-08-01 08:48:59 +08:00
luoyp
5479a26832 修复单折线渐变图鼠标移入报错 2023-08-01 08:44:27 +08:00
奔跑的面条
1250829da6 fix: 处理一开始不会请求的问题 2023-07-31 17:09:20 +08:00
奔跑的面条
ac2fd67688 fix: 修复创建分组排序会错误的bug 2023-07-31 15:45:43 +08:00
QuietlyChan
dbc44bf419 fix: 修复初始化不能拖拽 2023-07-28 14:34:40 +08:00
QuietlyChan
1401a091eb feat: 增加全屏按钮组件 2023-07-28 10:11:34 +08:00
奔跑的面条
5bef16665a docs: update readme 2023-07-24 10:06:31 +08:00
奔跑的面条
f528eb29bc fix: 处理加上链接内容就会消失的bug 2023-07-21 16:43:05 +08:00
奔跑的面条
06921ea3f5 !180 修复旋转组件预览错位问题
Merge pull request !180 from 张江胜/dev_fix
2023-07-21 08:29:05 +00:00
奔跑的面条
f2d9f14ea5 !179 修复右下角白点 通过修改样式修改 不需要元素
Merge pull request !179 from cherubic_c/dev
2023-07-21 08:06:37 +00:00
奔跑的面条
9477bceefc !182 基础事件增加components参数
Merge pull request !182 from Retire/pr
2023-07-21 07:06:42 +00:00
奔跑的面条
d76107e2b0 !183 调整过滤编辑界面大小,方便编写过滤
Merge pull request !183 from Retire/pr0713
2023-07-21 07:01:30 +00:00
奔跑的面条
97e5d985bd !184 fix: 左侧刻度尺错位问题
Merge pull request !184 from daidai/dev
2023-07-21 06:59:15 +00:00
刘嘉威
bb1828b478 fix: 左侧刻度尺错位问题 2023-07-20 14:28:31 +08:00
Ming
91c4cca62e fix: 粘贴坐标 2023-07-17 18:53:33 +08:00
奔跑的面条
c604b41fb2 Merge branch 'dev' 2023-07-15 14:14:19 +08:00
奔跑的面条
c3140d3746 build: 升级 axios lock错误 2023-07-15 14:13:40 +08:00
retire
c19080e75b style: 调整过滤编辑界面大小,方便编写过滤 2023-07-13 17:38:49 +08:00
retire
7519247f93 feat: 基础事件增加components参数 2023-07-13 11:23:51 +08:00
奔跑的面条
34fe89c168 docs: update readme 2023-07-12 18:26:57 +08:00
张江胜
307cdd9e9a fix: 修复单个组件旋转后,进行分组再次旋转预览错位的问题 2023-07-10 11:06:19 +08:00
IMyself
7bc8c16581 修复右下角白点 2023-07-10 08:21:10 +08:00
奔跑的面条
4cba991e9f Merge branch 'dev' 2023-07-09 17:07:14 +08:00
奔跑的面条
8caa588d3f perf: 优化预览拖拽交互 2023-07-09 17:06:35 +08:00
奔跑的面条
9cf023fcc8 Merge branch 'dev' 2023-07-09 15:54:38 +08:00
奔跑的面条
7076c4deb7 feat: 新增预览拖拽 2023-07-09 15:54:01 +08:00
奔跑的面条
28f0585a5c Merge branch 'dev' 2023-07-08 22:00:35 +08:00
奔跑的面条
e979149cfb feat: 不符合接口格式时添加拦截 2023-07-08 21:59:41 +08:00
奔跑的面条
5fc43d1d02 build: 升级版本到1.2.7 2023-07-08 21:52:07 +08:00
奔跑的面条
084441d365 Merge branch 'dev' 2023-07-08 21:48:53 +08:00
奔跑的面条
d0d031d1bb feat: 还原修改成组旋转的问题,优化预览放大的交互 2023-07-08 21:33:50 +08:00
奔跑的面条
9127e6f44c feat: 新增预览放大功能 2023-07-08 21:18:37 +08:00
xlys999
bb610ff7ae update src/views/chart/ContentEdit/components/EditRule/index.vue.
坐标尺刻度错位问题

Signed-off-by: xlys999 <xlys998@163.com>
2023-07-08 18:45:03 +08:00
奔跑的面条
2dc12b1f0b !177 update src/views/chart/ContentEdit/components/EditRule/index.vue.
Merge pull request !177 from xlys999/N/A
2023-07-08 10:42:13 +00:00
奔跑的面条
c575cff727 perf: 优化滤镜预设展示 2023-07-08 18:36:36 +08:00
奔跑的面条
5443c9647b !176 新增预设滤镜功能
Merge pull request !176 from 张江胜/dev_feat
2023-07-08 10:35:31 +00:00
xlys999
ace6b0f0d2 update src/views/chart/ContentEdit/components/EditRule/index.vue.
坐标尺刻度错位问题

Signed-off-by: xlys999 <xlys998@163.com>
2023-07-03 14:10:00 +00:00
张江胜
271a02ff12 feat: 增加预设滤镜功能
1.滤镜变换:新增了快捷预设滤镜
2023-06-29 18:45:59 +08:00
张江胜
f747fd3506 fix: 解决单个组件旋转后,再组合分组渲染预览会错位的问题
1.解决单个组件旋转后,和其他组件组合分组后再次旋转,进行预览后该分组会错位的问题
2.解决TS类型报错
2023-06-29 17:39:17 +08:00
奔跑的面条
b59c28b8ae fix: 解决 TS 类型错误问题 2023-06-27 18:11:37 +08:00
奔跑的面条
b1a0e7b5e2 fix: 修改 axios 类型错误 2023-06-27 17:54:17 +08:00
奔跑的面条
0d762f7d30 style: 优化 pr_173 的问题 2023-06-27 17:48:08 +08:00
奔跑的面条
cc156a0a6b !173 1.时间选择器增加默认值类型选项
Merge pull request !173 from dingxs/dingxs
2023-06-27 09:47:39 +00:00
奔跑的面条
a77f4d6bf4 !174 feat: 为 naive-ui 组件配置感知、属性提示、自动完成功能
Merge pull request !174 from dodu/dev-commet
2023-06-25 01:32:43 +00:00
tnt group
9e5676e5ed feat: 为 naive-ui 组件提供感知能力 2023-06-23 11:54:52 +08:00
dingxs
bc79e2f01f fix:用in判断对象是否具有某个特定的key,而不是value,解决当value为null时永远得不到修改 2023-06-19 14:39:00 +08:00
dingxs
80f06afa02 feat:时间选择器增加默认值类型选项 2023-06-19 14:35:17 +08:00
奔跑的面条
58ab3dee6d !172 环形饼图增加轨道宽度设置,并优化数字显示(如无小数位,则不强制显示小数位)
Merge pull request !172 from dodu/dev-commet
2023-06-15 11:52:47 +00:00
奔跑的面条
d7a3bb7ba0 !169 feat:标签选择器增加默认值选项
Merge pull request !169 from h5coder/dev-h5coder
2023-06-15 19:50:27 +08:00
奔跑的面条
5387a7ad90 !171 fix: 修复旧版本没有legend配置导致报settting color错误
Merge pull request !171 from h5coder/h5coder-fix
2023-06-15 19:46:13 +08:00
tnt group
fe37435f79 chore: 设置选择框size 2023-06-14 07:54:36 +08:00
tnt group
1ef6d9797a feat: 环形饼图增加轨道宽度设置,并优化数字显示 2023-06-13 10:27:08 +08:00
奔跑的面条
c70d54c622 style: 删除冗余代码 2023-06-08 16:39:18 +08:00
Ming
d74645d7b0 feat: 组件交互对公共api支持配置页 2023-06-07 15:13:48 +08:00
Ming
86910de3b2 fix: 数据初始化 2023-06-07 15:08:52 +08:00
Ming
47636ee680 feat: 支持对公共api进行交互 2023-06-07 15:06:51 +08:00
Ming
9485931f5d feat: 更新公共api对组件动态绑定交互 2023-06-07 15:03:59 +08:00
Ming
20fa9e4afe fix: declare module '@iconify/vue' 2023-06-07 15:00:28 +08:00
Ming
cbd629d7f8 feat: 更新交互组件更新方式 2023-06-07 15:00:06 +08:00
Ming
1551aa9ded fix: 语言转换为英文后,创建按钮的英文拼写错误 2023-05-29 10:29:44 +08:00
奔跑的面条
471610963b build: 升级版本到1.2.6 2023-05-28 17:29:19 +08:00
奔跑的面条
f6424245fd Merge branch 'dev' 2023-05-28 17:28:34 +08:00
奔跑的面条
d9834482f3 !166 fix: 调整组件列表下图片的展现方式,保持图片不被变形
Merge pull request !166 from dodu/dev-commet
2023-05-28 09:27:17 +00:00
tnt group
6fe20c4655 fix: 调整组件列表下图片的展现方式,保持图片不被变形 2023-05-28 17:23:59 +08:00
奔跑的面条
6afbe59828 Merge branch 'dev' 2023-05-28 17:20:36 +08:00
奔跑的面条
52389fa6fc !162 ecahrts全局公共图例新增详细配置参数
Merge pull request !162 from tanhao/feat-echarts-legend
2023-05-28 09:09:26 +00:00
奔跑的面条
bcb2ca1cb5 !159 地图组件新增卫星地图主题
Merge pull request !159 from tanhao/feat-map-theme
2023-05-28 16:15:58 +08:00
奔跑的面条
346c8d439a !164 feat: 增加管道组件
Merge pull request !164 from wsc/dev
2023-05-28 07:50:00 +00:00
奔跑的面条
c7f7c6a731 !163 fix: 修复原来动态导入的问题,保留 redirectComponent 配置的灵活性
Merge pull request !163 from dodu/dev-commet
2023-05-27 07:00:44 +00:00
tnt group
6063408d94 fix: 上次遗漏的修复 #e463b2cd 2023-05-27 13:21:17 +08:00
tnt group
ff4140cbfb chore: 使用模板字符串方式表示 redirectComponent 规则,更为精准,避免手误 2023-05-27 12:06:43 +08:00
tnt group
d8bcb4ab4f fix: 修复图标组件持久化(或导出再导入)时保存的分类不正确导致无法载入的问题 2023-05-27 00:02:40 +08:00
Wang sc
3d4e05b514 feat: 增加管道组件 2023-05-26 18:07:35 +08:00
tnt group
bb48745484 fix: 修复动态导入的问题,保留 redirectComponent 配置的灵活性 2023-05-26 16:51:05 +08:00
tanhao
f9adeac742 feat: echarts公共图例新增详细配置信息 2023-05-25 11:52:10 +08:00
奔跑的面条
8867a489a2 fix: 处理编译之后无法生成新数据的bug 2023-05-24 22:49:25 +08:00
奔跑的面条
adfd8c63e2 !159 地图组件新增卫星地图主题
Merge pull request !159 from tanhao/feat-map-theme
2023-05-24 12:58:20 +00:00
奔跑的面条
d8c55b6325 perf: 优化提示文案 2023-05-24 20:53:26 +08:00
奔跑的面条
44ace74ca9 fix: 新增删除功能 2023-05-24 17:59:27 +08:00
奔跑的面条
2e84b3d196 feat: 修改代码结构,新增删除按钮 2023-05-24 16:56:39 +08:00
奔跑的面条
8f82c1fa59 !157 fix:修复[时间选择器无法获取实际所选时间范围]Bug并且设置默认值
Merge pull request !157 from dingxs/dev-fix
2023-05-24 07:54:08 +00:00
奔跑的面条
7098e2e5e7 !158 chore: 图标和图片虚拟组件设置成static静态资源
Merge pull request !158 from dodu/dev-commet
2023-05-24 07:40:14 +00:00
tanhao
11af941590 feat: 在地图组件基础上新增卫星地图主题 2023-05-24 14:44:46 +08:00
tnt group
051ddcc2d4 chore: 图标和图片动态组件设置成static静态资源 2023-05-24 11:49:24 +08:00
奔跑的面条
773ae65085 perf: 处理提示词 2023-05-23 21:13:54 +08:00
奔跑的面条
e4db7cb8ff feat: 新增图片和图标 2023-05-23 20:55:24 +08:00
dingxs
8bb0f5e3a5 fix:修复[时间选择器无法获取实际所选时间范围]Bug并且设置默认值 2023-05-23 11:50:47 +08:00
Ming
93ed31f093 feat: 防止前端编译工具安全警告报错 2023-05-22 11:43:54 +08:00
Ming
76e511daa0 feat: 动态日期,初始化日期 2023-05-22 11:38:38 +08:00
Ming
a2184b19b3 feat: 动态日期config面板 2023-05-22 11:36:43 +08:00
Ming
ec9210d7e7 feat: 动态日期config 2023-05-22 11:34:59 +08:00
奔跑的面条
e0fe8f673c !155 增加图片、图标侧边栏功能
Merge pull request !155 from dodu/dev-commet
2023-05-22 03:06:22 +00:00
tnt group
95466aa076 feat: 添加天气分组图标 2023-05-20 13:53:15 +08:00
tnt group
6e8e38e737 fix: 修复搜索列表不显示图标的问题 2023-05-19 17:19:34 +08:00
tnt group
3008073829 fix: 修复图标无法拖拽的问题 2023-05-19 17:15:24 +08:00
tnt group
0e0794338a fix: 修复合并丢掉的虚拟组件配置,导致photos my 下的虚拟组件异常 2023-05-18 20:20:58 +08:00
tnt group
5059c9ea65 chore: 移除 pnpm-lock,避免冲突 2023-05-18 19:59:25 +08:00
tnt group
50a8342c49 Merge branch 'dev-photos' into dev-commet 2023-05-18 19:56:31 +08:00
tnt group
afad8e49b1 feat: 增加图标边栏选项卡 2023-05-18 19:44:27 +08:00
tnt group
a3d97e56ab feat: 增加两种图标类别及虚拟组件 2023-05-18 19:43:36 +08:00
tnt group
816c11a877 feat: 扩展 ConfigType,以支持虚拟图标组件 2023-05-18 19:41:30 +08:00
tnt group
6fee63600b feat: 创建通用图标组件 2023-05-18 19:39:21 +08:00
tnt group
1dd055294c feat: 添加 iconify 库及图标素材 2023-05-18 19:36:58 +08:00
tnt group
4aa41bbe36 chore: 忽略vite警告 2023-05-18 12:00:31 +08:00
tnt group
9585bd07a3 feat: 扩展 ConfigType 添加 clickHandle 属性,为上传图片组件增加点击事件,完善点击上传(暂时不走网络,读取其base64) 2023-05-18 09:46:18 +08:00
tnt group
aecba9c95e feat: 扩展 ConfigType,添加禁用属性,并添加一个上传按钮组件,在拖拽、双击、搜索模式让配置了禁用项的组件不可用 2023-05-18 09:45:41 +08:00
奔跑的面条
57ad9a2c7a build: 升级依赖 2023-05-18 09:21:54 +08:00
奔跑的面条
e71fb22b22 build: 升级依赖 2023-05-18 09:19:02 +08:00
tnt group
d177ebc900 feat: 侧边栏中加入图片类型选项卡 2023-05-17 20:30:50 +08:00
tnt group
e18cf847cd feat: 组件 Image 支持延迟加载 2023-05-17 20:23:55 +08:00
tnt group
31ed863d53 feat: 在通过拖拽、双击、搜索不同方式动态创建组件时,支持创建虚拟组件,并根据预设值和预设标题,初始化组件 2023-05-17 20:23:05 +08:00
tnt group
c7b2daa0b8 feat: 创建Photos虚拟组件(设置 virtualComponent 组件路径),预设我的|共享类别 2023-05-17 20:16:36 +08:00
tnt group
3a6990f124 feat: 扩展 ConfigType 组件配置类型,支持虚拟组件路径和预设组件 dataset 值 2023-05-17 20:12:48 +08:00
tnt group
9f41ad1811 feat: 列表组件的image渲染支持url模式 2023-05-17 20:09:03 +08:00
奔跑的面条
0ec0a12b0f feat: 升级 vite 版本到4.3.6 2023-05-16 19:48:23 +08:00
奔跑的面条
c18bc019d3 feat: 新增饼图轮播功能 2023-05-16 19:48:06 +08:00
奔跑的面条
6bbe489162 !154 修复数字翻牌因未等待ui更新导致显示错误的异常,并能实时响应更新
Merge pull request !154 from dodu/dev-commet
2023-05-14 09:09:48 +00:00
tnt group
54cdada560 style: 加重翻牌动画效果 2023-05-14 13:03:25 +08:00
tnt group
048f3426fe fix: 修复因变化快无法显示反动动画效果 2023-05-14 12:34:21 +08:00
tnt group
c508aaa400 feat: 翻牌数字增加内阴影边框属性及配置,默认为 0 2023-05-14 12:12:59 +08:00
tnt group
606cb753c4 fix: 修复因翻牌值变化太快,导致显示错误的异常 2023-05-14 12:09:38 +08:00
奔跑的面条
66e376a87d docs: update 2023-05-13 14:21:49 +08:00
奔跑的面条
318821680a docs: update 2023-05-13 14:19:52 +08:00
奔跑的面条
114fe5626a update README.md.
Signed-off-by: 奔跑的面条 <1262327911@qq.com>
2023-05-13 05:55:38 +00:00
奔跑的面条
afb364b362 docs: add sponsors 2023-05-13 13:52:52 +08:00
tnt group
01be79ee9a Merge branch 'dev' into dev-commet 2023-05-10 11:33:48 +08:00
Ming
3137109c6d fix: 支持分组 2023-05-09 10:13:48 +08:00
Ming
1d876418fe feat: 交互绑定组件,可以绑定分组内组件 2023-05-09 10:09:26 +08:00
Ming
fd37ce6ede fix: 补充枚举字段 2023-05-09 10:08:47 +08:00
Ming
9693c0dedf docs: md 2023-05-09 09:50:13 +08:00
Ming
dc8d7c86d7 perf: 优化颜色 2023-05-09 09:46:00 +08:00
Ming
8499d574dc fix: 小组件外层盒子宽度不一致 2023-05-09 09:44:14 +08:00
tntgroup
09a21f44c5 Merge branch 'dev' into dev-commet 2023-04-22 08:05:21 +08:00
tnt group
98b38640d1 Merge branch 'dev' into dev-commet 2023-01-09 23:24:58 +08:00
tntgroup
89194848de Merge branch 'dev' into dev-commet 2022-12-19 13:25:57 +08:00
tnt group
7c1bcd0605 Merge branch 'dev' into dev-commet 2022-12-12 07:55:10 +08:00
tnt group
c1d98b03a9 Merge branch 'dev' into dev-commet 2022-11-29 17:03:05 +08:00
tnt group
66f4768285 Merge branch 'dev' into dev-commet 2022-11-24 11:04:20 +08:00
tnt group
ec6d8dedec Merge branch 'dev' into dev-commet 2022-11-18 13:21:38 +08:00
tnt group
99d20d99f9 Merge branch 'dev' into dev-commet 2022-11-13 16:21:11 +08:00
tnt group
0106d43467 Merge branch 'dev' into dev-commet 2022-11-07 08:25:07 +08:00
tnt group
231fb9dd29 Merge branch 'dev' into dev-commet 2022-11-03 11:06:18 +08:00
tnt group
f2ae08e62a Merge branch 'dev' into dev-commet 2022-11-01 08:28:43 +08:00
tnt group
e930ca1587 Merge branch 'dev' into dev-commet 2022-10-15 18:37:12 +08:00
tnt group
ddb125656a Merge branch 'dev' into dev-commet 2022-10-14 14:18:18 +08:00
tnt group
35cda43d95 Merge branch 'dev' into dev-commet 2022-10-13 22:19:28 +08:00
tnt group
e3faaad5e0 fix: 修复 eslint 报错(移除多余eslint注释) 2022-10-13 18:41:00 +08:00
tnt group
24ef446fd6 Merge branch 'dev' into dev-commet 2022-10-13 18:09:55 +08:00
tnt group
53b9e03e69 fix: 修复编辑动态请求modal,esc关闭后无法再次打开的问题,并增加取消关闭 2022-10-13 16:33:51 +08:00
174 changed files with 6362 additions and 2411 deletions

1
.gitignore vendored
View File

@@ -4,3 +4,4 @@ dist
dist-ssr
*.local
.vscode
.idea

114
README.md
View File

@@ -1,4 +1,16 @@
#### 总览
<p align="center">
<a
href="https://ai.goviewlink.com/?channel=mayun"
target="_blank"
style="
padding: 10px 20px;
display: inline-block;
border-radius: 10px;
">
<img src="readme/GoViewPro.png" alt="go-view" />
</a>
</p>
<p align="center">
<img src="readme/logo-t-y.png" alt="go-view" />
</p>
@@ -6,6 +18,7 @@
<h4 align="center">开源、精美、便捷的「数据可视化」低代码开发平台</h4>
#### 长期赞助商
<div>
<div align="center" style="column-gap: 20px;">
<a
@@ -20,6 +33,19 @@
<img src="readme/sponsors/ccflow-banner.png" alt="go-view" style="width: 250px;" width="250px" />
</a>
<span> &nbsp;</span>
<a
href="https://fastbee.cn/"
target="_blank"
style="
padding: 10px 20px;
display: inline-block;
border-radius: 10px;
background: #f9f9f9;
">
<img src="readme/sponsors/fb-banner.gif" alt="go-view" style="width: 250px;" width="250px"/>
</a>
<br/>
<br/>
<a
href="https://www.qeasy.cloud/"
target="_blank"
@@ -31,6 +57,79 @@
">
<img src="readme/sponsors/qyy-banner.png" alt="go-view" style="width: 250px;" width="250px"/>
</a>
<span> &nbsp;</span>
<a
href="http://doc.zyplayer.com/#/integrate/zyplayer-doc?utm=goview"
target="_blank"
style="
padding: 10px 20px;
display: inline-block;
border-radius: 10px;
background: #f9f9f9;
">
<img src="readme/sponsors/zyplayer-banner.png" alt="go-view" style="width: 250px;" width="250px"/>
</a>
<br/>
<br/>
<a
href="https://gitee.com/dandiankeji/icampus"
target="_blank"
style="
padding: 10px 20px;
display: inline-block;
border-radius: 10px;
background: #f9f9f9;
">
<img src="readme/sponsors/dandian-banner.png" alt="go-view" style="width: 250px;" width="250px"/>
</a>
<a
href="https://www.mingdao.com?s=utm_88&utm_source=Goview&utm_medium=banner&utm_campaign=gitee&utm_content=IT%E8%B5%8B%E8%83%BD%E4%B8%9A%E5%8A%A1"
target="_blank"
style="
padding: 10px 20px;
display: inline-block;
border-radius: 10px;
background: #f9f9f9;
">
<img src="readme/sponsors/mdy-banner.png" alt="go-view" style="width: 270px;" width="270px"/>
</a>
<br/>
<br/>
<a
href="https://iotdoc.sagoo.cn/"
target="_blank"
style="
padding: 10px 20px;
display: inline-block;
border-radius: 10px;
background: #f9f9f9;
">
<img src="readme/sponsors/shaguo-banner.png" alt="go-view" style="width: 270px;" width="270px"/>
</a>
<a
href="http://www.yunchengxc.com/"
target="_blank"
style="
padding: 10px 20px;
display: inline-block;
border-radius: 10px;
background: #f9f9f9;
">
<img src="readme/sponsors/yuncheng-banner.png" alt="go-view" style="width: 270px;" width="270px"/>
</a>
<br/>
<br/>
<a
href="https://www.diboot.com?from=gv/"
target="_blank"
style="
padding: 10px 20px;
display: inline-block;
border-radius: 10px;
background: #f9f9f9;
">
<img src="readme/sponsors/diboot-banner.png" alt="go-view" style="width: 270px;" width="270px"/>
</a>
</div>
</div>
@@ -102,7 +201,7 @@ Cloud IDE 代码在线预览地址:[https://idegitee.com/dromara/go-view](http
| 名称 | 版本 | 名称 | 版本 |
| ------------------- | ----- | ----------- | ------ |
| Vue | 3.2.x | TypeScript4 | 4.6.x |
| Vite | 2.9.x | NaiveUI | 2.27.x |
| Vite | 4.2.x | NaiveUI | 2.34.x |
| ECharts | 5.3.x | Pinia | 2.0.x |
| 详见 `package.json` | 😁 | 🥰 | 🤗 |
@@ -110,7 +209,7 @@ Cloud IDE 代码在线预览地址:[https://idegitee.com/dromara/go-view](http
| 名称 | 版本 | 名称 | 版本 |
| ---- | ------- | ------- | ----- |
| node | 16.14.x | npm | 8.5.x |
| node | 16.16.x | npm | 8.5.x |
| pnpm | 7.1.x | windows | 11 |
已完成图表:
@@ -151,7 +250,12 @@ Cloud IDE 代码在线预览地址:[https://idegitee.com/dromara/go-view](http
## 交流群
QQ 群663629294
<img width="260px" src="readme/go-view-qq.png" alt="QQ群" style="border-radius: 20px" />
QQ 群647239611
<img width="260px" src="readme/go-view-qq.jpg" alt="QQ群" style="border-radius: 20px" />
## Pro 部分功能展示
体验地址: <a href="https://ai.goviewlink.com/" target="_blank">https://ai.goviewlink.com/</a>
![渲染海报](readme/logo-poster.png)

View File

@@ -1,6 +1,6 @@
{
"name": "go-view",
"version": "1.2.5",
"version": "1.3.1",
"engines": {
"node": ">=12.0"
},
@@ -16,12 +16,13 @@
"dependencies": {
"@amap/amap-jsapi-loader": "^1.0.1",
"@amap/amap-jsapi-types": "^0.0.8",
"@iconify/json": "^2.2.158",
"@types/color": "^3.0.3",
"@types/crypto-js": "^4.1.1",
"@types/keymaster": "^1.6.30",
"@types/lodash": "^4.14.184",
"animate.css": "^4.1.1",
"axios": "^0.27.2",
"axios": "^1.4.0",
"color": "^4.2.3",
"crypto-js": "^4.1.1",
"dayjs": "^1.11.7",
@@ -32,7 +33,9 @@
"gsap": "^3.11.3",
"highlight.js": "^11.5.0",
"html2canvas": "^1.4.1",
"iconify-icon": "^1.0.8",
"keymaster": "^1.6.2",
"mitt": "^3.0.0",
"monaco-editor": "^0.33.0",
"naive-ui": "2.34.3",
"pinia": "^2.0.13",
@@ -40,7 +43,7 @@
"three": "^0.145.0",
"vue": "^3.2.31",
"vue-demi": "^0.13.1",
"vue-i18n": "^9.2.2",
"vue-i18n": "9.2.2",
"vue-router": "4.0.12",
"vue3-lazyload": "^0.2.5-beta",
"vue3-sketch-ruler": "^1.3.3",
@@ -55,8 +58,8 @@
"@typescript-eslint/parser": "^5.18.0",
"@vicons/carbon": "^0.12.0",
"@vicons/ionicons5": "~0.11.0",
"@vitejs/plugin-vue": "^1.10.2",
"@vitejs/plugin-vue-jsx": "^1.3.9",
"@vitejs/plugin-vue": "^4.2.3",
"@vitejs/plugin-vue-jsx": "^3.0.1",
"@vue/compiler-sfc": "^3.2.31",
"@vueuse/core": "^7.7.1",
"commitlint": "^17.0.2",
@@ -75,7 +78,7 @@
"sass": "^1.49.11",
"sass-loader": "^12.6.0",
"typescript": "4.6.3",
"vite": "4.2.1",
"vite": "4.3.6",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-importer": "^0.2.5",
"vite-plugin-mock": "^2.9.6",

945
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

BIN
readme/GoViewPro.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

BIN
readme/go-view-qq.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -30,5 +30,5 @@ const hljsTheme = useCode()
// 全局语言
const { locale, dateLocale } = useLang()
//测试提交
</script>

View File

@@ -1,4 +1,4 @@
import axios, { AxiosResponse, AxiosRequestConfig } from 'axios'
import axios, { AxiosResponse, InternalAxiosRequestConfig, AxiosError } from 'axios'
import { ResultEnum } from "@/enums/httpEnum"
import { ErrorPageNameMap } from "@/enums/pageEnum"
import { redirectErrorPage } from '@/utils'
@@ -9,10 +9,10 @@ const axiosInstance = axios.create({
})
axiosInstance.interceptors.request.use(
(config: AxiosRequestConfig) => {
(config: InternalAxiosRequestConfig) => {
return config
},
(error: AxiosRequestConfig) => {
(error: AxiosError) => {
Promise.reject(error)
}
)

View File

@@ -163,7 +163,6 @@ export const customizeHttp = (targetParams: RequestConfigType, globalParams: Req
params = translateStr(params)
// form 类型处理
let formData: FormData = new FormData()
formData.set('default', 'defaultData')
// 类型处理
switch (requestParamsBodyType) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 999 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 983 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 KiB

BIN
src/assets/videos/earth.mp4 Normal file

Binary file not shown.

View File

@@ -0,0 +1,3 @@
import GoIconify from './index.vue';
export { GoIconify };

View File

@@ -0,0 +1,34 @@
<template>
<iconify-icon
:icon="icon"
:rotate="`${rotate}deg`"
:width="width"
:style="{
color: color
}"
></iconify-icon>
</template>
<script setup lang="ts">
defineProps({
icon: {
type: String,
required: true
},
color: {
type: String,
default: '#999999',
required: false
},
width: {
type: [String, Number],
default: '20',
required: false
},
rotate: {
type: [String, Number],
default: '0',
required: false
}
})
</script>

View File

@@ -257,9 +257,36 @@
<n-switch v-model:value="legend.show" size="small"></n-switch>
</template>
<setting-item-box name="图例文字">
<setting-item>
<setting-item name="颜色">
<n-color-picker size="small" v-model:value="legend.textStyle.color"></n-color-picker>
</setting-item>
<setting-item name="大小">
<n-input-number v-model:value="legend.textStyle.fontSize" :min="1" size="small"></n-input-number>
</setting-item>
</setting-item-box>
<setting-item-box name="图例位置">
<setting-item name="x轴">
<n-select v-model:value="legend.x" size="small" :options="legendConfig.lengendX" />
</setting-item>
<setting-item name="y轴">
<n-select v-model:value="legend.y" size="small" :options="legendConfig.lengendY" />
</setting-item>
</setting-item-box>
<setting-item-box name="图例信息">
<setting-item name="方向">
<n-select v-model:value="legend.orient" size="small" :options="legendConfig.orient" />
</setting-item>
<setting-item name="形状">
<n-select v-model:value="legend.icon" size="small" :options="legendConfig.shape" />
</setting-item>
</setting-item-box>
<setting-item-box name="图例大小">
<setting-item name="宽">
<n-input-number v-model:value="legend.itemWidth" :min="1" size="small"></n-input-number>
</setting-item>
<setting-item name="高">
<n-input-number v-model:value="legend.itemHeight" :min="1" size="small"></n-input-number>
</setting-item>
</setting-item-box>
</collapse-item>
@@ -309,9 +336,9 @@
</template>
<script setup lang="ts">
import { PropType, computed } from 'vue'
import { PropType, computed, watch } from 'vue'
import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
import { axisConfig } from '@/packages/chartConfiguration/echarts/index'
import { axisConfig, legendConfig } from '@/packages/chartConfiguration/echarts/index'
import { CollapseItem, SettingItemBox, SettingItem, GlobalSettingPosition } from '@/components/Pages/ChartItemSetting'
import { icon } from '@/plugins'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
@@ -360,4 +387,18 @@ const grid = computed(() => {
const visualMap = computed(() => {
return props.optionData.visualMap
})
// 监听legend color颜色改变type = scroll的颜色
watch(() => legend.value && legend.value.textStyle.color, (newVal) => {
if (legend.value && newVal) {
if (!legend.value.pageTextStyle) {
legend.value.pageTextStyle = { color: newVal }
} else {
legend.value.pageTextStyle.color = newVal
}
}
}, {
immediate: true,
deep: true,
})
</script>

View File

@@ -69,6 +69,22 @@
</setting-item>
</setting-item-box>
<!-- 预设滤镜 -->
<div v-if="presetImageList.length" class="preset-filter">
<n-image
class="preset-img"
width="46"
preview-disabled
object-fit="scale-down"
v-for="(item, index) in presetImageList"
:key="index"
:class="{ 'active-preset': item.hueRotate === chartStyles.hueRotate }"
:style="{ filter: `hue-rotate(${item.hueRotate}deg)` }"
:src="item.src"
@click="() => (chartStyles.hueRotate = item.hueRotate)"
></n-image>
</div>
<!-- 混合模式 -->
<setting-item-box v-if="!isCanvas" :alone="true">
<template #name>
@@ -149,10 +165,12 @@
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { ref, PropType } from 'vue'
import { PickCreateComponentType, BlendModeEnumList } from '@/packages/index.d'
import { SettingItemBox, SettingItem, CollapseItem } from '@/components/Pages/ChartItemSetting'
import { icon } from '@/plugins'
import logoImg from '@/assets/logo.png'
import { useDesignStore } from '@/store/modules/designStore/designStore'
const props = defineProps({
isGroup: {
@@ -175,10 +193,48 @@ const { HelpOutlineIcon } = icon.ionicons5
const sliderFormatTooltip = (v: string) => {
return `${(parseFloat(v) * 100).toFixed(0)}%`
}
// 角度格式化
const degFormatTooltip = (v: string) => {
return `${v}deg`
}
// 预设滤镜
interface presetImageData {
index: number
src: string
hueRotate: number
}
const presetImageList = ref([] as presetImageData[])
for (let i = 1; i <= 12; i++) {
presetImageList.value.push({
index: i,
src: logoImg,
hueRotate: i * 30
})
}
</script>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
// 预设滤镜
.preset-filter {
margin: 20px 0 10px 0;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.preset-img {
margin-bottom: 10px;
padding: 2px;
border-radius: 6px;
transition: 0.2s all;
cursor: pointer;
&:hover {
box-shadow: 0 0 0 2px #66a9c9;
}
}
.active-preset {
box-shadow: 0 0 0 2px #66a9c9;
}
}
</style>

View File

@@ -1,13 +1,13 @@
<template>
<div class="go-Flipper" :class="[flipType, { go: isFlipping }]">
<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'
import { ref, PropType, watch, nextTick } from 'vue'
import { FlipType } from './index'
const props = defineProps({
flipType: {
@@ -43,6 +43,10 @@ const props = defineProps({
backColor: {
type: String,
default: '#000000'
},
borderWidth: {
type: Number,
default: 2
}
})
@@ -50,19 +54,27 @@ const isFlipping = ref(false)
const frontTextFromData = ref(props.count || 0)
const backTextFromData = ref(props.count || 0)
let timeoutID: any = 0
// 翻牌
const flip = (front: string | number, back: string | number) => {
const flip = async (front: string | number, back: string | number) => {
// 如果处于翻转中,则不执行
if (isFlipping.value) return
if (isFlipping.value) {
isFlipping.value = false // 立即结束此次动画
clearTimeout(timeoutID) // 清除上一个计时器任务
await nextTick()
await flip(front, back) // 开始最后一次翻牌任务
return
}
// 设置翻盘前后数据
backTextFromData.value = back
frontTextFromData.value = front
// 设置翻转状态为true
isFlipping.value = true
// 翻牌结束的行为
setTimeout(() => {
timeoutID = setTimeout(() => {
isFlipping.value = false // 设置翻转状态为false
frontTextFromData.value = back
}, props.duration)
@@ -86,6 +98,7 @@ $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`');
$borderWidth: v-bind('`${props.borderWidth * 2}px`');
$speed: v-bind('`${props.duration / 1000}s`');
$shadowColor: #000000;
$lineColor: #4a9ef8;
@@ -125,13 +138,12 @@ $lineColor: #4a9ef8;
}
// #endregion
.go-Flipper {
.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;
@@ -139,6 +151,17 @@ $lineColor: #4a9ef8;
box-shadow: 0 0 6px rgba($color: $shadowColor, $alpha: 0.5); // 阴影部分
text-align: center;
// font-family: 'Helvetica Neue';
&::after {
content: '';
position: absolute;
z-index: 10;
left: 0;
top: 0;
right: 0;
bottom: 0;
box-shadow: inset 0 0 $borderWidth 0 $frontColor; // 内测阴影部分
border-radius: $radius;
}
.digital:before,
.digital:after {
@@ -186,11 +209,13 @@ $lineColor: #4a9ef8;
&.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);
box-shadow: 0 -2px $borderWidth 0 $frontColor;
backface-visibility: hidden;
}
&.down.go .back:after {
animation: backFlipDown $speed ease-in-out both;
box-shadow: 0 2px $borderWidth 0 $frontColor;
backface-visibility: hidden;
}
/*向上翻*/
&.up .front:after {
@@ -208,11 +233,13 @@ $lineColor: #4a9ef8;
&.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);
box-shadow: 0 2px $borderWidth 0 $frontColor;
backface-visibility: hidden;
}
&.up.go .back:before {
animation: backFlipUp $speed ease-in-out both;
box-shadow: 0 -2px $borderWidth 0 $frontColor;
backface-visibility: hidden;
}
}
</style>

View File

@@ -12,5 +12,7 @@ export enum StorageEnum {
// 工作台布局配置
GO_CHART_LAYOUT_STORE = 'GO_CHART_LAYOUT',
// 工作台需要保存的数据
GO_CHART_STORAGE_LIST = 'GO_CHART_STORAGE_LIST'
GO_CHART_STORAGE_LIST = 'GO_CHART_STORAGE_LIST',
// 用户存储的图片媒体
GO_USER_MEDIA_PHOTOS = 'GO_USER_MEDIA_PHOTOS'
}

View File

@@ -90,7 +90,7 @@ export const useChartDataFetch = (
// 普通初始化与组件交互处理监听
watch(
() => targetComponent.request,
() => targetComponent.request.requestParams,
() => {
fetchFn()
},
@@ -105,7 +105,11 @@ export const useChartDataFetch = (
// 单位
const unit = targetInterval && targetInterval.value ? targetUnit.value : globalUnit.value
// 开启轮询
if (time) fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit))
if (time) {
fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit))
} else {
fetchFn()
}
}
// eslint-disable-next-line no-empty
} catch (error) {
@@ -114,10 +118,14 @@ export const useChartDataFetch = (
}
if (isPreview()) {
// 判断是否是数据池类型
targetComponent.request.requestDataType === RequestDataTypeEnum.Pond
? addGlobalDataInterface(targetComponent, useChartEditStore, updateCallback || echartsUpdateHandle)
? addGlobalDataInterface(targetComponent, useChartEditStore, (newData: any) => {
echartsUpdateHandle(newData)
if (updateCallback) updateCallback(newData)
})
: requestIntervalFn()
} else {
requestIntervalFn()
}
return { vChartRef }
}

View File

@@ -1,4 +1,4 @@
import { toRaw } from 'vue'
import { toRaw, watch, computed, ComputedRef } from 'vue'
import { customizeHttp } from '@/api/http'
import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
@@ -20,7 +20,7 @@ const mittDataPondMap = new Map<string, DataPondMapType[]>()
// 创建单个数据项轮询接口
const newPondItemInterval = (
requestGlobalConfig: RequestGlobalConfigType,
requestDataPondItem: RequestDataPondItemType,
requestDataPondItem: ComputedRef<RequestDataPondItemType>,
dataPondMapItem?: DataPondMapType[]
) => {
if (!dataPondMapItem) return
@@ -31,8 +31,7 @@ const newPondItemInterval = (
// 请求
const fetchFn = async () => {
try {
const res = await customizeHttp(toRaw(requestDataPondItem.dataPondRequestConfig), toRaw(requestGlobalConfig))
const res = await customizeHttp(toRaw(requestDataPondItem.value.dataPondRequestConfig), toRaw(requestGlobalConfig))
if (res) {
try {
// 遍历更新回调函数
@@ -49,19 +48,32 @@ const newPondItemInterval = (
}
}
watch(
() => requestDataPondItem.value.dataPondRequestConfig.requestParams.Params,
() => {
fetchFn()
},
{
immediate: false,
deep: true
}
)
// 立即调用
fetchFn()
const targetInterval = requestDataPondItem.dataPondRequestConfig.requestInterval
const targetUnit = requestDataPondItem.dataPondRequestConfig.requestIntervalUnit
const targetInterval = requestDataPondItem.value.dataPondRequestConfig.requestInterval
const targetUnit = requestDataPondItem.value.dataPondRequestConfig.requestIntervalUnit
const globalRequestInterval = requestGlobalConfig.requestInterval
const globalUnit = requestGlobalConfig.requestIntervalUnit
// 定时时间
const time = targetInterval ? targetInterval : globalRequestInterval
const time = targetInterval ? targetInterval : globalRequestInterval
// 单位
const unit = targetInterval ? targetUnit : globalUnit
const unit = targetInterval ? targetUnit : globalUnit
// 开启轮询
if (time) fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit))
}
@@ -96,13 +108,16 @@ export const useChartDataPondFetch = () => {
}
// 初始化数据池
const initDataPond = (requestGlobalConfig: RequestGlobalConfigType) => {
const { requestDataPond } = requestGlobalConfig
const initDataPond = (useChartEditStore: ChartEditStoreType) => {
const { requestGlobalConfig } = useChartEditStore()
const chartEditStore = useChartEditStore()
// 根据 mapId 查找对应的数据池配置
for (let pondKey of mittDataPondMap.keys()) {
const requestDataPondItem = requestDataPond.find(item => item.dataPondId === pondKey)
const requestDataPondItem = computed(() => {
return requestGlobalConfig.requestDataPond.find(item => item.dataPondId === pondKey)
}) as ComputedRef<RequestDataPondItemType>
if (requestDataPondItem) {
newPondItemInterval(requestGlobalConfig, requestDataPondItem, mittDataPondMap.get(pondKey))
newPondItemInterval(chartEditStore.requestGlobalConfig, requestDataPondItem, mittDataPondMap.get(pondKey))
}
}
}

View File

@@ -1,4 +1,5 @@
import { toRefs } from 'vue'
import { isPreview } from '@/utils'
import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
@@ -12,6 +13,7 @@ export const useChartInteract = (
param: { [T: string]: any },
interactEventOn: string
) => {
if (!isPreview()) return
const chartEditStore = useChartEditStore()
const { interactEvents } = chartConfig.events
const fnOnEvent = interactEvents.filter(item => {
@@ -20,20 +22,37 @@ export const useChartInteract = (
if (fnOnEvent.length === 0) return
fnOnEvent.forEach(item => {
const index = chartEditStore.fetchTargetIndex(item.interactComponentId)
if (index === -1) return
const { Params, Header } = toRefs(chartEditStore.componentList[index].request.requestParams)
Object.keys(item.interactFn).forEach(key => {
if (Params.value[key]) {
Params.value[key] = param[item.interactFn[key]]
}
if (Header.value[key]) {
Header.value[key] = param[item.interactFn[key]]
}
})
const globalConfigPindAprndex = chartEditStore.requestGlobalConfig.requestDataPond.findIndex(cItem =>
cItem.dataPondId === item.interactComponentId
)
if (globalConfigPindAprndex !== -1) {
const { Params, Header } = toRefs(chartEditStore.requestGlobalConfig.requestDataPond[globalConfigPindAprndex].dataPondRequestConfig.requestParams)
Object.keys(item.interactFn).forEach(key => {
if (key in Params.value) {
Params.value[key] = param[item.interactFn[key]]
}
if (key in Header.value) {
Header.value[key] = param[item.interactFn[key]]
}
})
} else {
const index = chartEditStore.fetchTargetIndex(item.interactComponentId)
if (index === -1) return
const { Params, Header } = toRefs(chartEditStore.componentList[index].request.requestParams)
Object.keys(item.interactFn).forEach(key => {
if (key in Params.value) {
Params.value[key] = param[item.interactFn[key]]
}
if (key in Header.value) {
Header.value[key] = param[item.interactFn[key]]
}
})
}
})
}
// 联动事件触发的 type 变更时,清除当前绑定内容
export const clearInteractEvent = (chartConfig: CreateComponentType) => {

View File

@@ -48,10 +48,10 @@ export const useLifeHandler = (chartConfig: CreateComponentType | CreateComponen
try {
return new Function(`
return (
async function(mouseEvent){
async function(components,mouseEvent){
${fnStr}
}
)`)()
)`)().bind(undefined,components)
} catch (error) {
console.error(error)
}

View File

@@ -1,218 +1,218 @@
import throttle from 'lodash/throttle'
// 拆出来是为了更好的分离单独复用
// * 屏幕缩放适配(两边留白)
export const usePreviewFitScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 画布尺寸px
const baseWidth = width
const baseHeight = height
// * 默认缩放值
const scale = {
width: 1,
height: 1,
}
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
const calcRate = () => {
// 当前屏幕宽高比
const currentRate = parseFloat(
(window.innerWidth / window.innerHeight).toFixed(5)
)
if (scaleDom) {
if (currentRate > baseProportion) {
// 表示更宽
scale.width = parseFloat(((window.innerHeight * baseProportion) / baseWidth).toFixed(5))
scale.height = parseFloat((window.innerHeight / baseHeight).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
} else {
// 表示更高
scale.height = parseFloat(((window.innerWidth / baseProportion) / baseHeight).toFixed(5))
scale.width = parseFloat((window.innerWidth / baseWidth).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
}
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 改变窗口大小重新绘制
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}
// * X轴撑满Y轴滚动条
export const usePreviewScrollYScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 画布尺寸px
const baseWidth = width
const baseHeight = height
// * 默认缩放值
const scale = {
width: 1,
height: 1,
}
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
const calcRate = () => {
if (scaleDom) {
scale.height = parseFloat(((window.innerWidth / baseProportion) / baseHeight).toFixed(5))
scale.width = parseFloat((window.innerWidth / baseWidth).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 改变窗口大小重新绘制
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}
// * Y轴撑满X轴滚动条
export const usePreviewScrollXScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 画布尺寸px
const baseWidth = width
const baseHeight = height
// * 默认缩放值
const scale = {
height: 1,
width: 1,
}
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
const calcRate = () => {
if (scaleDom) {
scale.width = parseFloat(((window.innerHeight * baseProportion) / baseWidth).toFixed(5))
scale.height = parseFloat((window.innerHeight / baseHeight).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 改变窗口大小重新绘制
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}
// * 变形内容,宽高铺满
export const usePreviewFullScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 默认缩放值
const scale = {
width: 1,
height: 1,
}
const calcRate = () => {
if (scaleDom) {
scale.width = parseFloat((window.innerWidth / width).toFixed(5))
scale.height = parseFloat((window.innerHeight / height).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 改变窗口大小重新绘制
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
import throttle from 'lodash/throttle'
// 拆出来是为了更好的分离单独复用
// * 屏幕缩放适配(两边留白)
export const usePreviewFitScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 画布尺寸px
const baseWidth = width
const baseHeight = height
// * 默认缩放值
const scale = {
width: 1,
height: 1,
}
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
const calcRate = () => {
// 当前屏幕宽高比
const currentRate = parseFloat(
(window.innerWidth / window.innerHeight).toFixed(5)
)
if (scaleDom) {
if (currentRate > baseProportion) {
// 表示更宽
scale.width = parseFloat(((window.innerHeight * baseProportion) / baseWidth).toFixed(5))
scale.height = parseFloat((window.innerHeight / baseHeight).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
} else {
// 表示更高
scale.height = parseFloat(((window.innerWidth / baseProportion) / baseHeight).toFixed(5))
scale.width = parseFloat((window.innerWidth / baseWidth).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
}
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 卸载监听
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}
// * X轴撑满Y轴滚动条
export const usePreviewScrollYScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 画布尺寸px
const baseWidth = width
const baseHeight = height
// * 默认缩放值
const scale = {
width: 1,
height: 1,
}
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
const calcRate = () => {
if (scaleDom) {
scale.height = parseFloat(((window.innerWidth / baseProportion) / baseHeight).toFixed(5))
scale.width = parseFloat((window.innerWidth / baseWidth).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 卸载监听
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}
// * Y轴撑满X轴滚动条
export const usePreviewScrollXScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 画布尺寸px
const baseWidth = width
const baseHeight = height
// * 默认缩放值
const scale = {
height: 1,
width: 1,
}
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
const calcRate = () => {
if (scaleDom) {
scale.width = parseFloat(((window.innerHeight * baseProportion) / baseWidth).toFixed(5))
scale.height = parseFloat((window.innerHeight / baseHeight).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 卸载监听
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}
// * 变形内容,宽高铺满
export const usePreviewFullScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 默认缩放值
const scale = {
width: 1,
height: 1,
}
const calcRate = () => {
if (scaleDom) {
scale.width = parseFloat((window.innerWidth / width).toFixed(5))
scale.height = parseFloat((window.innerHeight / height).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 卸载监听
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}

View File

@@ -1,5 +1,5 @@
export default {
create_btn: 'Creat',
create_btn: 'Create',
create_tip: 'Please select a content for development',
project: 'Project',
my: 'My',

View File

@@ -1,59 +1,67 @@
import { createApp } from 'vue'
import App from './App.vue'
import router, { setupRouter } from '@/router'
import i18n from '@/i18n/index'
import { setupStore } from '@/store'
import { setupNaive, setupDirectives, setupCustomComponents, initFunction } from '@/plugins'
import { GoAppProvider } from '@/components/GoAppProvider/index'
import { setHtmlTheme } from '@/utils'
// 引入全局样式
import '@/styles/pages/index.scss'
// 引入动画
import 'animate.css/animate.min.css'
// 引入标尺
import 'vue3-sketch-ruler/lib/style.css'
async function appInit() {
const goAppProvider = createApp(GoAppProvider)
const app = createApp(App)
// 注册全局常用的 naive-ui 组件
setupNaive(app)
// 注册全局自定义指令
setupDirectives(app)
// 注册全局自定义组件
setupCustomComponents(app)
// 挂载状态管理
setupStore(app)
// 解决路由守卫Axios中可使用DialogMessage 等全局组件
goAppProvider.mount('#appProvider', true)
// 挂载路由
setupRouter(app)
// 路由准备就绪后挂载APP实例
await router.isReady()
// Store 准备就绪后处理主题色
setHtmlTheme()
// 语言注册
app.use(i18n)
// 挂载到页面
app.mount('#app', true)
// 挂载到 window
window['$vue'] = app
}
appInit().then(() => {
initFunction()
})
import { createApp } from 'vue'
import App from './App.vue'
import router, { setupRouter } from '@/router'
import i18n from '@/i18n/index'
import { setupStore } from '@/store'
import { setupNaive, setupDirectives, setupCustomComponents, initFunction } from '@/plugins'
import { GoAppProvider } from '@/components/GoAppProvider/index'
import { setHtmlTheme } from '@/utils'
import { addCollection } from 'iconify-icon'
import uimIcons from '@iconify/json/json/uim.json'
import lineMdIcons from '@iconify/json/json/line-md.json'
import wiIcons from '@iconify/json/json/wi.json'
// 引入全局样式
import '@/styles/pages/index.scss'
// 引入动画
import 'animate.css/animate.min.css'
// 引入标尺
import 'vue3-sketch-ruler/lib/style.css'
// 注册图标
addCollection(uimIcons)
addCollection(lineMdIcons)
addCollection(wiIcons)
async function appInit() {
const goAppProvider = createApp(GoAppProvider)
const app = createApp(App)
// 注册全局常用的 naive-ui 组件
setupNaive(app)
// 注册全局自定义指令
setupDirectives(app)
// 注册全局自定义组件
setupCustomComponents(app)
// 挂载状态管理
setupStore(app)
// 解决路由守卫Axios中可使用DialogMessage 等全局组件
goAppProvider.mount('#appProvider', true)
// 挂载路由
setupRouter(app)
// 路由准备就绪后挂载APP实例
await router.isReady()
// Store 准备就绪后处理主题色
setHtmlTheme()
// 语言注册
app.use(i18n)
// 挂载到页面
app.mount('#app', true)
// 挂载到 window
window['$vue'] = app
}
appInit().then(() => {
initFunction()
})

View File

@@ -1,3 +1,4 @@
export * from './axis'
export * from './line'
export * from './label'
export * from './label'
export * from './legend'

View File

@@ -0,0 +1,70 @@
export const legendConfig = {
// X轴位置
lengendX: [
{
label: '靠左',
value: 'left'
},
{
label: '居中',
value: 'center'
},
{
label: '靠右',
value: 'right'
}
],
// y轴位置
lengendY: [
{
label: '靠上',
value: 'top'
},
{
label: '居中',
value: 'center'
},
{
label: '靠下',
value: 'bottom'
}
],
// 排列方向
orient: [
{
label: '水平',
value: 'horizontal'
},
{
label: '垂直',
value: 'vertical'
}
],
// 形状
shape: [
{
label: '圆形',
value: 'circle'
},
{
label: '方形',
value: 'rect'
},
{
label: '圆角方形',
value: 'roundRect'
},
{
label: '三角形',
value: 'triangle'
},
{
label: '钢笔形',
value: 'pin'
},
{
label: '箭头形',
value: 'arrow'
}
]
}

View File

@@ -0,0 +1,75 @@
import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
import { BarLineConfig } from './index'
import { CreateComponentType } from '@/packages/index.d'
import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json'
export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
// 柱状折线组合图 分别定义series
// 写死name可以定义legend显示的名称
export const barSeriesItem = {
type: 'bar',
barWidth: 15,
label: {
show: true,
position: 'top',
color: '#fff',
fontSize: 12
},
itemStyle: {
color: null,
borderRadius: 2
}
}
export const lineSeriesItem = {
type: 'line',
symbol: 'circle',
label: {
show: true,
position: 'top',
color: '#fff',
fontSize: 12
},
symbolSize: 5, //设定实心点的大小
itemStyle: {
color: '#FFE47A',
borderWidth: 1
},
lineStyle: {
type: 'solid',
width: 3,
color: null
}
}
export const option = {
tooltip: {
show: true,
trigger: 'axis',
axisPointer: {
show: true,
type: 'shadow'
}
},
legend: {
data: null
},
xAxis: {
show: true,
type: 'category'
},
yAxis: {
show: true,
type: 'value'
},
dataset: { ...dataJson },
series: [barSeriesItem, lineSeriesItem]
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key = BarLineConfig.key
public chartConfig = cloneDeep(BarLineConfig)
// 图表配置项
public option = echartOptionProfixHandle(option, includes)
}

View File

@@ -0,0 +1,138 @@
<template>
<!-- Echarts 全局设置 -->
<global-setting :optionData="optionData"></global-setting>
<CollapseItem
v-for="(item, index) in seriesList"
:key="index"
:name="`系列${index + 1}`"
:expanded="true"
>
<template #header>
<n-text class="go-fs-13" depth="3">
{{ item.type == 'bar' ? '「柱状图」' : '「折线图」' }}
</n-text>
</template>
<SettingItemBox name="类型">
<SettingItem name="宽度">
<n-select
:value="item.type"
size="small"
:options="[
{ label: '柱状图', value: 'bar' },
{ label: '折线图', value: 'line' }
]"
@update:value="(value: any) => {
updateHandle(item, value)
}"
/>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="图形" v-if="item.type == 'bar'">
<SettingItem name="宽度">
<n-input-number
v-model:value="item.barWidth"
:min="1"
:max="100"
size="small"
placeholder="自动计算"
></n-input-number>
</SettingItem>
<SettingItem name="圆角">
<n-input-number v-model:value="item.itemStyle.borderRadius" :min="0" size="small"></n-input-number>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="线条" v-if="item.type == 'line'">
<SettingItem name="宽度">
<n-input-number
v-model:value="item.lineStyle.width"
:min="1"
:max="100"
size="small"
placeholder="自动计算"
></n-input-number>
</SettingItem>
<SettingItem name="类型">
<n-select v-model:value="item.lineStyle.type" size="small" :options="lineConf.lineStyle.type"></n-select>
</SettingItem>
<setting-item>
<n-space>
<n-switch v-model:value="item.smooth" size="small" />
<n-text>曲线</n-text>
</n-space>
</setting-item>
</SettingItemBox>
<SettingItemBox name="实心点" v-if="item.type == 'line'">
<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="tip颜色">
<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: '顶部', value: 'top' },
{ label: '左侧', value: 'left' },
{ label: '右侧', value: 'right' },
{ label: '底部', value: 'bottom' }
]"
/>
</setting-item>
</setting-item-box>
</CollapseItem>
</template>
<script setup lang="ts">
import { PropType, computed, toRaw } from 'vue'
import { merge, cloneDeep } from 'lodash';
import GlobalSetting from '@/components/Pages/ChartItemSetting/GlobalSetting.vue'
import CollapseItem from '@/components/Pages/ChartItemSetting/CollapseItem.vue'
import SettingItemBox from '@/components/Pages/ChartItemSetting/SettingItemBox.vue'
import SettingItem from '@/components/Pages/ChartItemSetting/SettingItem.vue'
import { lineConf } from '@/packages/chartConfiguration/echarts'
import { GlobalThemeJsonType } from '@/settings/chartThemes'
import { barSeriesItem, lineSeriesItem } from './config'
const props = defineProps({
optionData: {
type: Object as PropType<GlobalThemeJsonType>,
required: true
}
})
const seriesList = computed(() => {
return props.optionData.series
})
const updateHandle = (item:any, value:string) => {
const _label = cloneDeep(toRaw(item.label))
lineSeriesItem.label = _label
if (value === 'line') {
merge(item, lineSeriesItem)
} else {
merge(item, barSeriesItem)
}
}
</script>

View File

@@ -0,0 +1,40 @@
{
"dimensions": ["product", "data1", "data2"],
"source": [
{
"product": "1月",
"data1": 104,
"data2": 30
},
{
"product": "2月",
"data1": 56,
"data2": 56
},
{
"product": "3月",
"data1": 136,
"data2": 36
},
{
"product": "4月",
"data1": 86,
"data2": 6
},
{
"product": "5月",
"data1": 98,
"data2": 10
},
{
"product": "6月",
"data1": 86,
"data2": 70
},
{
"product": "7月",
"data1": 77,
"data2": 57
}
]
}

View File

@@ -0,0 +1,16 @@
// 公共类型声明
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
// 当前[信息模块]分类声明
import { ChatCategoryEnum,ChatCategoryEnumName } from '../../index.d'
export const BarLineConfig: ConfigType = {
key: 'BarLine',
chartKey: 'VBarLine',
conKey: 'VCBarLine',
title: '柱状图 & 折线图',
category: ChatCategoryEnum.BAR,
categoryName: ChatCategoryEnumName.BAR,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.ECHARTS,
image: 'bar_line.png'
}

View File

@@ -0,0 +1,92 @@
<template>
<v-chart
ref="vChartRef"
:init-options="initOptions"
:theme="themeColor"
:option="option"
:manual-update="isPreview()"
autoresize
></v-chart>
</template>
<script setup lang="ts">
import { ref, computed, watch, PropType, nextTick } from 'vue'
import VChart from 'vue-echarts'
import { isObject, cloneDeep } from 'lodash'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
//引入柱状图 折线图
import { BarChart, LineChart } from 'echarts/charts'
import config, { includes, barSeriesItem, lineSeriesItem } from './config'
import { mergeTheme } from '@/packages/public/chart'
import { useChartDataFetch } from '@/hooks'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { isPreview } from '@/utils'
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
const props = defineProps({
themeSetting: {
type: Object,
required: true
},
themeColor: {
type: Object,
required: true
},
chartConfig: {
type: Object as PropType<config>,
required: true
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
use([DatasetComponent, CanvasRenderer, BarChart, LineChart, GridComponent, TooltipComponent, LegendComponent])
const replaceMergeArr = ref<string[]>()
const option = computed(() => {
return mergeTheme(props.chartConfig.option, props.themeSetting, includes)
})
watch(
() => props.chartConfig.option.dataset,
(newData: any, oldData) => {
try {
if (!isObject(newData) || !('dimensions' in newData)) return
if (Array.isArray((newData as any)?.dimensions)) {
const seriesArr: typeof barSeriesItem[] = []
// 对oldData进行判断防止传入错误数据之后对旧维度判断产生干扰
// 此处计算的是dimensions的Y轴维度若是dimensions.length为0或1则默认为1排除X轴维度干扰
const oldDimensions =
Array.isArray(oldData?.dimensions) && oldData.dimensions.length >= 1 ? oldData.dimensions.length : 1
const newDimensions = (newData as any).dimensions.length >= 1 ? (newData as any).dimensions.length : 1
const dimensionsGap = newDimensions - oldDimensions
if (dimensionsGap < 0) {
props.chartConfig.option.series.splice(newDimensions - 1)
} else if (dimensionsGap > 0) {
if (!oldData || !oldData?.dimensions || !Array.isArray(oldData?.dimensions) || !oldData?.dimensions.length) {
props.chartConfig.option.series = []
}
for (let i = 0; i < dimensionsGap; i++) {
seriesArr.push(cloneDeep(barSeriesItem))
}
props.chartConfig.option.series.push(...seriesArr)
}
replaceMergeArr.value = ['series']
nextTick(() => {
replaceMergeArr.value = []
})
}
} catch (error) {
console.log(error)
}
},
{
deep: false
}
)
const { vChartRef } = useChartDataFetch(props.chartConfig, useChartEditStore)
</script>

View File

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

View File

@@ -33,6 +33,10 @@ export const option = {
width: 3,
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,

View File

@@ -30,6 +30,11 @@ export enum ViewModeEnum {
STEREOSCOPIC = '3D'
}
export const ShowHideEnum = {
SHOW: true,
HIDE: false
}
export enum FeaturesEnum {
BG = 'bg',
POINT = 'point',
@@ -70,6 +75,25 @@ export const option = {
},
mapMarkerType: MarkerEnum.CIRCLE_MARKER,
viewMode: ViewModeEnum.PLANE,
showLabel: ShowHideEnum.SHOW,
satelliteTileLayer: {
show: ShowHideEnum.HIDE,
zIndex: 1,
opacity: 1,
zooms: [3, 18]
},
roadNetTileLayer: {
show: ShowHideEnum.HIDE,
zIndex: 2,
opacity: 1,
zooms: [3, 18]
},
trafficTileLayer: {
show: ShowHideEnum.HIDE,
zIndex: 3,
opacity: 1,
zooms: [3, 18]
},
lang: LangEnum.ZH_CN,
features: [FeaturesEnum.BG, FeaturesEnum.POINT, FeaturesEnum.ROAD, FeaturesEnum.BUILDING]
}

View File

@@ -22,13 +22,21 @@
<n-select size="small" v-model:value="optionData.mapOptions.amapStyleKey" :options="themeOptions" />
</setting-item>
</setting-item-box>
<setting-item-box name="内容" :alone="true">
<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="文字标注" :alone="true">
<setting-item>
<n-space>
<n-switch v-model:value="optionData.mapOptions.showLabel" size="small" />
<n-text>是否显示</n-text>
</n-space>
</setting-item>
</setting-item-box>
<setting-item-box name="位置">
<setting-item name="经度">
<n-input-number v-model:value="optionData.mapOptions.amapLon" :show-button="false" size="small">
@@ -76,11 +84,94 @@
</setting-item>
</setting-item-box>
</collapse-item>
<collapse-item name="图层" :expanded="true">
<setting-item-box name="卫星图层">
<setting-item>
<n-space>
<n-switch v-model:value="optionData.mapOptions.satelliteTileLayer.show" size="small" />
<n-text>是否显示</n-text>
</n-space>
</setting-item>
<setting-item name="叠加顺序值">
<n-input-number
v-model:value="optionData.mapOptions.satelliteTileLayer.zIndex"
:min="0"
size="small"
></n-input-number>
</setting-item>
<setting-item name="透明度">
<n-input-number
v-model:value="optionData.mapOptions.satelliteTileLayer.opacity"
:min="0"
:max="1"
step="0.1"
size="small"
></n-input-number>
</setting-item>
<setting-item name="缩放级别范围">
<n-slider v-model:value="optionData.mapOptions.satelliteTileLayer.zooms" range :step="1" :max="18" :min="3" />
</setting-item>
</setting-item-box>
<setting-item-box name="路网图层">
<setting-item>
<n-space>
<n-switch v-model:value="optionData.mapOptions.roadNetTileLayer.show" size="small" />
<n-text>是否显示</n-text>
</n-space>
</setting-item>
<setting-item name="叠加顺序值">
<n-input-number
v-model:value="optionData.mapOptions.roadNetTileLayer.zIndex"
:min="0"
size="small"
></n-input-number>
</setting-item>
<setting-item name="透明度">
<n-input-number
v-model:value="optionData.mapOptions.roadNetTileLayer.opacity"
:min="0"
:max="1"
step="0.1"
size="small"
></n-input-number>
</setting-item>
<setting-item name="缩放级别范围">
<n-slider v-model:value="optionData.mapOptions.roadNetTileLayer.zooms" range :step="1" :max="18" :min="3" />
</setting-item>
</setting-item-box>
<setting-item-box name="实时交通">
<setting-item>
<n-space>
<n-switch v-model:value="optionData.mapOptions.trafficTileLayer.show" size="small" />
<n-text>是否显示</n-text>
</n-space>
</setting-item>
<setting-item name="叠加顺序值">
<n-input-number
v-model:value="optionData.mapOptions.trafficTileLayer.zIndex"
:min="0"
size="small"
></n-input-number>
</setting-item>
<setting-item name="透明度">
<n-input-number
v-model:value="optionData.mapOptions.trafficTileLayer.opacity"
:min="0"
:max="1"
step="0.1"
size="small"
></n-input-number>
</setting-item>
<setting-item name="缩放级别范围">
<n-slider v-model:value="optionData.mapOptions.trafficTileLayer.zooms" range :step="1" :max="18" :min="3" />
</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 { option, MarkerEnum, ThemeEnum, LangEnum, ViewModeEnum, ShowHideEnum, FeaturesEnum } from './config'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
defineProps({
@@ -166,19 +257,19 @@ const viewModeOptions = [
const featuresOptions = [
{
value: FeaturesEnum.BG,
label: '显示地图背景'
label: '区域面'
},
{
value: FeaturesEnum.POINT,
label: '显示标识'
label: '标注'
},
{
value: FeaturesEnum.ROAD,
label: '显示道路'
label: '道路'
},
{
value: FeaturesEnum.BUILDING,
label: '显示建筑'
label: '建筑'
}
]

View File

@@ -8,7 +8,7 @@ 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 { MarkerEnum, ThemeEnum } from './config'
import { isArray } from '@/utils'
const props = defineProps({
@@ -28,9 +28,13 @@ let {
amapStyleKeyCustom,
features,
viewMode,
showLabel,
pitch,
skyColor,
marker
marker,
satelliteTileLayer,
roadNetTileLayer,
trafficTileLayer
} = toRefs(props.chartConfig.option.mapOptions)
let mapIns: any = null
@@ -42,7 +46,7 @@ const initMap = (newData: any) => {
// 初始化
AMapLoader.load({
key: amapKey.value, //api服务key--另外需要在public中使用安全密钥
version: '1.4.8', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
version: '1.4.15', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: ['AMap.PlaceSearch', 'AMap.AutoComplete'] // 需要使用的的插件列表
})
.then(AMap => {
@@ -51,15 +55,45 @@ const initMap = (newData: any) => {
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, // 地图模式
showLabel: showLabel.value, // 是否显示地图文字标记
willReadFrequently: true
})
dataHandle(props.chartConfig.option.dataset)
let satelliteLayer = new AMap.TileLayer.Satellite({
zIndex: satelliteTileLayer.value.zIndex,
opacity: satelliteTileLayer.value.opacity,
zooms: satelliteTileLayer.value.zooms
})
let roadNetLayer = new AMap.TileLayer.RoadNet({
zIndex: roadNetTileLayer.value.zIndex,
opacity: roadNetTileLayer.value.opacity,
zooms: roadNetTileLayer.value.zooms
})
let trafficLayer = new AMap.TileLayer.Traffic({
zIndex: trafficTileLayer.value.zIndex,
opacity: trafficTileLayer.value.opacity,
zooms: trafficTileLayer.value.zooms
})
mapIns.remove([satelliteLayer, roadNetLayer, trafficLayer])
if (satelliteTileLayer.value.show) {
mapIns.add([satelliteLayer])
}
if (roadNetTileLayer.value.show) {
mapIns.add([roadNetLayer])
}
if (trafficTileLayer.value.show) {
mapIns.add([trafficLayer])
}
mapIns.setMapStyle(
`amap://styles/${amapStyleKeyCustom.value !== '' ? amapStyleKeyCustom.value : amapStyleKey.value}`
)
})
.catch(e => {})
}

View File

@@ -11,7 +11,10 @@ export const option = {
dataset: dataJson,
mapRegion: {
adcode: 'china',
showHainanIsLands: true
showHainanIsLands: true,
enter: false,
backSize: 20,
backColor: '#ffffff'
},
tooltip: {
show: true,
@@ -84,7 +87,10 @@ export const option = {
shadowColor: '#E1FFFF',
shadowBlur: 10
},
data: []
data: [],
encode: {
value: 2
}
},
{
name: '区域',
@@ -100,19 +106,19 @@ export const option = {
borderColor: 'rgba(147, 235, 248, 0.8)',
textStyle: {
color: '#FFFFFF',
fontSize: 12,
fontSize: 12
}
},
label: {
show: false,
color: '#FFFFFF',
fontSize: 12,
fontSize: 12
},
emphasis: {
disabled: false,
label: {
color: '#FFFFFF',
fontSize: 12,
fontSize: 12
},
itemStyle: {
areaColor: '#389BB7',
@@ -145,6 +151,26 @@ export const option = {
shadowOffsetY: 2,
shadowBlur: 10
}
},
{
type: 'lines',
zlevel: 2,
effect: {
show: true,
period: 4, //箭头指向速度,值越小速度越快
trailLength: 0.4, //特效尾迹长度[0,1]值越大,尾迹越长重
symbol: 'arrow', //箭头图标
symbolSize: 7 //图标大小
},
lineStyle: {
normal: {
color: '#4fb6d2',
width: 1, //线条宽度
opacity: 0.1, //尾迹线条透明度
curveness: 0.3 //尾迹线条曲直度
}
},
data: []
}
]
}

View File

@@ -69,11 +69,7 @@
</n-space>
</SettingItem>
<SettingItem name="字体颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].label.color"
></n-color-picker>
<n-color-picker size="small" :modes="['hex']" v-model:value="seriesList[1].label.color"></n-color-picker>
</SettingItem>
<SettingItem name="字体大小">
<n-input-number
@@ -129,7 +125,7 @@
></n-color-picker>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="悬浮弹窗">
<SettingItem name="显示">
<n-space>
@@ -180,6 +176,22 @@
<SettingItem>
<n-checkbox v-model:checked="mapRegion.showHainanIsLands" size="small">显示南海群岛</n-checkbox>
</SettingItem>
<SettingItem v-if="seriesList[2]">
<n-checkbox v-model:checked="mapRegion.enter" size="small">点击进入下级</n-checkbox>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="返回图标" v-if="mapRegion.enter">
<SettingItem name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="mapRegion.backColor"></n-color-picker>
</SettingItem>
<SettingItem name="大小">
<n-input-number
v-model:value="mapRegion.backSize"
:min="1"
size="small"
placeholder="请输入字体大小"
></n-input-number>
</SettingItem>
</SettingItemBox>
</CollapseItem>
<CollapseItem name="标记" :expanded="true">
@@ -191,7 +203,7 @@
<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>
@@ -223,6 +235,47 @@
</SettingItem>
</SettingItemBox>
</CollapseItem>
<CollapseItem v-if="seriesList[2]" name="飞线" :expanded="true">
<SettingItemBox name="箭头">
<SettingItem name="速度">
<n-tooltip trigger="hover">
<template #trigger>
<n-input-number v-model:value="seriesList[2].effect.period" size="small" :min="0"></n-input-number>
</template>
值越小速度越快
</n-tooltip>
</SettingItem>
<SettingItem name="尾迹">
<n-tooltip trigger="hover">
<template #trigger>
<n-input-number
v-model:value="seriesList[2].effect.trailLength"
size="small"
:min="0"
:max="1"
></n-input-number>
</template>
特效尾迹长度[0,1]值越大尾迹越长重
</n-tooltip>
</SettingItem>
<SettingItem name="大小">
<n-input-number v-model:value="seriesList[2].effect.symbolSize" size="small" :min="0"></n-input-number>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="配置">
<SettingItem name="颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[2].lineStyle.normal.color"
></n-color-picker>
</SettingItem>
<SettingItem name="宽度">
<n-input-number v-model:value="seriesList[2].lineStyle.normal.width" size="small" :min="1"></n-input-number>
</SettingItem>
</SettingItemBox>
</CollapseItem>
</template>
<script setup lang="ts">

View File

@@ -21,6 +21,32 @@
"value": [126.642464, 45.756967, 101]
}
],
"line": [
{
"coords": [
[113.665412, 34.757975],
[116.405285, 39.904989]
]
},
{
"coords": [
[101.778916, 36.623178],
[116.405285, 39.904989]
]
},
{
"coords": [
[106.278179, 38.46637],
[116.405285, 39.904989]
]
},
{
"coords": [
[126.642464, 45.756967],
[116.405285, 39.904989]
]
}
],
"map": [
{
"name": "北京市",

View File

@@ -1,156 +1,268 @@
<template>
<v-chart ref="vChartRef" :init-options="initOptions" :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 { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use, registerMap } from 'echarts/core'
import { EffectScatterChart, MapChart } from 'echarts/charts'
import { CanvasRenderer } from 'echarts/renderers'
import { useChartDataFetch } from '@/hooks'
import { mergeTheme, setOption } 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
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
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()
const adCode = `${props.chartConfig.option.mapRegion.adcode}`;
if (adCode !== 'china') {
await getGeojson(adCode)
} else {
await hainanLandsHandle(props.chartConfig.option.mapRegion.showHainanIsLands)
}
vEchartsSetOption()
}
registerMapInitAsync()
// 手动触发渲染
const vEchartsSetOption = () => {
option.value = props.chartConfig.option
setOption(vChartRef.value, 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>
<template>
<div>
<div class="back-icon" v-if="(enter && levelHistory.length !== 0) || (enter && !isPreview())" @click="backLevel">
<n-icon :color="backColor" :size="backSize * 1.1">
<ArrowBackIcon />
</n-icon>
<span
:style="{
'font-weight': 200,
color: backColor,
'font-size': `${backSize}px`
}"
>
返回上级
</span>
</div>
<v-chart
ref="vChartRef"
:init-options="initOptions"
:theme="themeColor"
:option="option.value"
:manual-update="isPreview()"
autoresize
@click="chartPEvents"
>
</v-chart>
</div>
</template>
<script setup lang="ts">
import { PropType, reactive, watch, ref, nextTick, toRefs } from 'vue'
import config, { includes } from './config'
import VChart from 'vue-echarts'
import { icon } from '@/plugins'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use, registerMap } from 'echarts/core'
import { EffectScatterChart, MapChart } from 'echarts/charts'
import { CanvasRenderer } from 'echarts/renderers'
import { useChartDataFetch } from '@/hooks'
import { mergeTheme, setOption } from '@/packages/public/chart'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { isPreview } from '@/utils'
import mapJsonWithoutHainanIsLands from './mapWithoutHainanIsLands.json'
import mapChinaJson from './mapGeojson/china.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
}
})
const { ArrowBackIcon } = icon.ionicons5
let levelHistory: any = ref([])
const { backColor, backSize, enter } = toRefs(props.chartConfig.option.mapRegion)
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
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()
const adCode = `${props.chartConfig.option.mapRegion.adcode}`
if (adCode !== 'china') {
await getGeojson(adCode)
} else {
await hainanLandsHandle(props.chartConfig.option.mapRegion.showHainanIsLands)
}
vEchartsSetOption()
}
registerMapInitAsync()
// 手动触发渲染
const vEchartsSetOption = () => {
option.value = props.chartConfig.option
setOption(vChartRef.value, 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 === 'lines' && dataset.line) {
item.data = dataset.line.map((it: any) => {
return {
...it,
lineStyle: {
color: props.chartConfig.option.series[2].lineStyle.normal.color
}
}
})
} 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: {} })
}
}
// 点击区域
const chartPEvents = (e: any) => {
if (e.seriesType !== 'map') return
if (!props.chartConfig.option.mapRegion.enter) {
return
}
mapChinaJson.features.forEach(item => {
var pattern = new RegExp(e.name)
if (pattern.test(item.properties.name)) {
let code = String(item.properties.adcode)
levelHistory.value.push(code)
checkOrMap(code)
}
})
}
// 返回上一级
const backLevel = () => {
levelHistory.value = []
if (levelHistory.value.length > 1) {
levelHistory.value.pop()
const code = levelHistory[levelHistory.value.length - 1]
checkOrMap(code)
} else {
checkOrMap('china')
}
}
// 切换地图
const checkOrMap = async (newData: string) => {
if (newData === 'china') {
if (props.chartConfig.option.mapRegion.showHainanIsLands) {
// 显示南海
hainanLandsHandle(true)
vEchartsSetOption()
} else {
// 隐藏南海
hainanLandsHandle(false)
vEchartsSetOption()
}
} else {
await getGeojson(newData)
}
props.chartConfig.option.geo.map = newData
props.chartConfig.option.series.forEach((item: any) => {
if (item.type === 'map') item.map = newData
})
vEchartsSetOption()
}
//监听 dataset 数据发生变化
watch(
() => props.chartConfig.option.dataset,
newData => {
dataSetHandle(newData)
},
{
immediate: true,
deep: false
}
)
// 监听线的颜色
if (props.chartConfig.option.series[2] && !isPreview()) {
watch(
() => props.chartConfig.option.series[2].lineStyle.normal.color,
() => {
dataSetHandle(props.chartConfig.option.dataset)
},
{
deep: false
}
)
}
//监听是否显示南海群岛
if (!isPreview()) {
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}`,
newData => {
try {
checkOrMap(newData)
} catch (error) {
console.log(error)
}
},
{
deep: false
}
)
// 预览
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
dataSetHandle(newData)
})
</script>
<style scope lang="scss">
.back-icon {
z-index: 50;
cursor: pointer;
position: absolute;
display: flex;
align-items: center;
top: 0;
left: 0;
gap: 2px;
}
</style>

View File

@@ -1,44 +1,52 @@
<template>
<v-chart ref="vChartRef" :init-options="initOptions" :theme="themeColor" :option="option" :manual-update="isPreview()" autoresize></v-chart>
</template>
<script setup lang="ts">
import { computed, PropType } from 'vue'
import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { FunnelChart } from 'echarts/charts'
import { includes } from './config'
import { mergeTheme } from '@/packages/public/chart'
import { useChartDataFetch } from '@/hooks'
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'
const props = defineProps({
themeSetting: {
type: Object,
required: true
},
themeColor: {
type: Object,
required: true
},
chartConfig: {
type: Object as PropType<CreateComponentType>,
required: true
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
use([DatasetComponent, CanvasRenderer, FunnelChart, GridComponent, TooltipComponent, LegendComponent])
const option = computed(() => {
return mergeTheme(props.chartConfig.option, props.themeSetting, includes)
})
const { vChartRef } = useChartDataFetch(props.chartConfig, useChartEditStore)
</script>
<template>
<v-chart
ref="vChartRef"
:init-options="initOptions"
:theme="themeColor"
:option="(option as EChartsOption)"
:manual-update="isPreview()"
autoresize
></v-chart>
</template>
<script setup lang="ts">
import { computed, PropType } from 'vue'
import VChart from 'vue-echarts'
import { EChartsOption } from 'echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { FunnelChart } from 'echarts/charts'
import { includes } from './config'
import { mergeTheme } from '@/packages/public/chart'
import { useChartDataFetch } from '@/hooks'
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'
const props = defineProps({
themeSetting: {
type: Object,
required: true
},
themeColor: {
type: Object,
required: true
},
chartConfig: {
type: Object as PropType<CreateComponentType>,
required: true
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
use([DatasetComponent, CanvasRenderer, FunnelChart, GridComponent, TooltipComponent, LegendComponent])
const option = computed(() => {
return mergeTheme(props.chartConfig.option, props.themeSetting, includes)
})
const { vChartRef } = useChartDataFetch(props.chartConfig, useChartEditStore)
</script>

View File

@@ -9,7 +9,8 @@ export const includes = []
// 关系图布局
export const GraphLayout = [
{ label: '无', value: 'none' },
{ label: '环形', value: 'circular' }
{ label: '环形', value: 'circular' },
{ label: '力引导', value: 'force' }
]
// 标签开关
@@ -24,44 +25,57 @@ export const LabelPosition = [
{ label: '右侧', value: 'right' },
{ label: '顶部', value: 'top' },
{ label: '底部', value: 'bottom' },
{ label: '内部', value: 'inside' },
{ label: '内部', value: 'inside' }
]
// 图-迭代动画
export const LayoutAnimation = [
{ label: '开启', value: 1 },
{ label: '关闭', value: 0 }
]
export const option = {
dataset: { ...dataJson },
tooltip: {},
legend:{
show:true,
textStyle:{
color:"#eee",
fontSize: 14 ,
},
data: dataJson.categories.map(function (a) {
return a.name;
})
dataset: { ...dataJson },
tooltip: {},
legend: {
show: true,
textStyle: {
color: '#eee',
fontSize: 14
},
series: [
{
type: 'graph',
layout: 'none', // none circular环形布局
data: dataJson.nodes,
links: dataJson.links,
categories: dataJson.categories,
label: { // 标签
show: 1,
position: 'right',
formatter: '{b}'
},
labelLayout: {
hideOverlap: true
},
lineStyle: {
color: 'source', // 线条颜色
curveness: 0.2 // 线条卷曲程度
}
data: dataJson.categories.map(function (a) {
return a.name
})
},
series: [
{
type: 'graph',
layout: 'none', // none circular环形布局
data: dataJson.nodes,
links: dataJson.links,
categories: dataJson.categories,
label: {
show: 1,
position: 'right',
formatter: '{b}'
},
labelLayout: {
hideOverlap: true
},
lineStyle: {
color: 'source', // 线条颜色
curveness: 0.2 // 线条卷曲程度
},
force: {
repulsion: 100,
gravity: 0.1,
edgeLength: 30,
layoutAnimation: 1,
friction: 0.6
}
]
};
}
]
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key = GraphConfig.key

View File

@@ -16,14 +16,14 @@
</SettingItemBox>
<SettingItemBox name="线条">
<SettingItem name="弧线">
<!-- 需要输入两位的小数才会变化 -->
<!-- 需要输入两位的小数才会变化 -->
<n-input-number
v-model:value="optionData.series[0].lineStyle.curveness"
:min="0"
:step="0.01"
placeholder="弯曲程度"
size="small"
></n-input-number>
v-model:value="optionData.series[0].lineStyle.curveness"
:min="0"
:step="0.01"
placeholder="弯曲程度"
size="small"
></n-input-number>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="图例">
@@ -32,10 +32,61 @@
size="small"
:modes="['hex']"
v-model:value="optionData.legend.textStyle.color"
></n-color-picker>
></n-color-picker>
</SettingItem>
<SettingItem name="文本">
<n-input-number v-model:value="optionData.legend.textStyle.fontSize" :min="0" :step="1" size="small" placeholder="文字大小">
<n-input-number
v-model:value="optionData.legend.textStyle.fontSize"
:min="0"
:step="1"
size="small"
placeholder="文字大小"
>
</n-input-number>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="力引导" v-if="optionData.series[0].force && graphConfig.layout == 'force'">
<SettingItem name="斥力因子" v-if="optionData.series[0].force.repulsion">
<n-input-number
v-model:value="optionData.series[0].force.repulsion"
:min="0"
:step="1"
size="small"
placeholder="斥力因子大小"
>
</n-input-number>
</SettingItem>
<SettingItem name="引力因子" v-if="optionData.series[0].force.gravity">
<n-input-number
v-model:value="optionData.series[0].force.gravity"
:min="0"
:step="0.1"
size="small"
placeholder="引力因子"
>
</n-input-number>
</SettingItem>
<SettingItem name="节点距离">
<n-input-number
v-model:value="optionData.series[0].force.edgeLength"
:min="0"
:step="1"
size="small"
placeholder="节点距离"
>
</n-input-number>
</SettingItem>
<SettingItem name="迭代动画">
<n-select v-model:value="graphConfig.force.layoutAnimation" :options="LayoutAnimation" size="small" />
</SettingItem>
<SettingItem name="节点速度">
<n-input-number
v-model:value="optionData.series[0].force.friction"
:min="0"
:step="0.1"
size="small"
placeholder="节点速度"
>
</n-input-number>
</SettingItem>
</SettingItemBox>
@@ -46,7 +97,7 @@
<script setup lang="ts">
import { PropType, computed } from 'vue'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { option, GraphLayout, LabelSwitch, LabelPosition } from './config'
import { option, GraphLayout, LabelSwitch, LabelPosition, LayoutAnimation } from './config'
import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
const props = defineProps({
@@ -56,7 +107,7 @@ const props = defineProps({
}
})
const graphConfig = computed<typeof option.series[0]>(() => {
const graphConfig = computed<(typeof option.series)[0]>(() => {
return props.optionData.series[0]
})
</script>

View File

@@ -1,10 +1,18 @@
<template>
<v-chart ref="vChartRef" :init-options="initOptions" :theme="themeColor" :option="option" :manual-update="isPreview()" autoresize></v-chart>
<v-chart
ref="vChartRef"
:init-options="initOptions"
:theme="themeColor"
:option="(option as EChartsOption)"
:manual-update="isPreview()"
autoresize
></v-chart>
</template>
<script setup lang="ts">
import { ref, computed, PropType, watch } from 'vue'
import VChart from 'vue-echarts'
import { EChartsOption } from 'echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import dataJson from './data.json'
import { use } from 'echarts/core'

View File

@@ -1,95 +1,103 @@
<template>
<v-chart ref="vChartRef" :init-options="initOptions" :theme="themeColor" :option="option" :manual-update="isPreview()" autoresize></v-chart>
</template>
<script setup lang="ts">
import { ref, watch, computed, PropType } from 'vue'
import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import dataJson from './data.json'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { HeatmapChart } from 'echarts/charts'
import { includes } from './config'
import { mergeTheme, setOption } from '@/packages/public/chart'
import { useChartDataFetch } from '@/hooks'
import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { isPreview } from '@/utils'
import {
DatasetComponent,
GridComponent,
TooltipComponent,
LegendComponent,
VisualMapComponent
} from 'echarts/components'
const props = defineProps({
themeSetting: {
type: Object,
required: true
},
themeColor: {
type: Object,
required: true
},
chartConfig: {
type: Object as PropType<CreateComponentType>,
required: true
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
use([
DatasetComponent,
CanvasRenderer,
HeatmapChart,
GridComponent,
TooltipComponent,
LegendComponent,
VisualMapComponent
])
const option = computed(() => {
return mergeTheme(props.chartConfig.option, props.themeSetting, includes)
})
const vChartRef = ref<typeof VChart>()
const dataSetHandle = (dataset: typeof dataJson) => {
const { seriesData, xAxis, yAxis } = dataset
if (xAxis) {
// @ts-ignore
props.chartConfig.option.xAxis.data = xAxis
}
if (yAxis) {
// @ts-ignore
props.chartConfig.option.yAxis.data = yAxis
}
if (seriesData) {
props.chartConfig.option.series[0].data = seriesData
}
if (vChartRef.value && isPreview()) {
setOption(vChartRef.value, props.chartConfig.option)
}
}
watch(
() => props.chartConfig.option.dataset,
newData => {
try {
dataSetHandle(newData)
} catch (error) {
console.log(error)
}
},
{
deep: false
}
)
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: typeof dataJson) => {
dataSetHandle(newData)
})
</script>
<template>
<v-chart
ref="vChartRef"
:init-options="initOptions"
:theme="themeColor"
:option="(option as EChartsOption)"
:manual-update="isPreview()"
autoresize
></v-chart>
</template>
<script setup lang="ts">
import { ref, watch, computed, PropType } from 'vue'
import VChart from 'vue-echarts'
import { EChartsOption } from 'echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import dataJson from './data.json'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { HeatmapChart } from 'echarts/charts'
import { includes } from './config'
import { mergeTheme, setOption } from '@/packages/public/chart'
import { useChartDataFetch } from '@/hooks'
import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { isPreview } from '@/utils'
import {
DatasetComponent,
GridComponent,
TooltipComponent,
LegendComponent,
VisualMapComponent
} from 'echarts/components'
const props = defineProps({
themeSetting: {
type: Object,
required: true
},
themeColor: {
type: Object,
required: true
},
chartConfig: {
type: Object as PropType<CreateComponentType>,
required: true
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
use([
DatasetComponent,
CanvasRenderer,
HeatmapChart,
GridComponent,
TooltipComponent,
LegendComponent,
VisualMapComponent
])
const option = computed(() => {
return mergeTheme(props.chartConfig.option, props.themeSetting, includes)
})
const vChartRef = ref<typeof VChart>()
const dataSetHandle = (dataset: typeof dataJson) => {
const { seriesData, xAxis, yAxis } = dataset
if (xAxis) {
// @ts-ignore
props.chartConfig.option.xAxis.data = xAxis
}
if (yAxis) {
// @ts-ignore
props.chartConfig.option.yAxis.data = yAxis
}
if (seriesData) {
props.chartConfig.option.series[0].data = seriesData
}
if (vChartRef.value && isPreview()) {
setOption(vChartRef.value, props.chartConfig.option)
}
}
watch(
() => props.chartConfig.option.dataset,
newData => {
try {
dataSetHandle(newData)
} catch (error) {
console.log(error)
}
},
{
deep: false
}
)
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: typeof dataJson) => {
dataSetHandle(newData)
})
</script>

View File

@@ -3,7 +3,7 @@
:type="type"
:height="h"
:processing="processing"
:percentage="option.dataset"
:percentage="dataset"
:indicator-placement="indicatorPlacement"
:color="color"
:rail-color="railColor"
@@ -15,7 +15,7 @@
fontSize: `${indicatorTextSize}px`
}"
>
{{ option.dataset }} {{ unit }}
{{ dataset }} {{ unit }}
</n-text>
</n-progress>
</template>

View File

@@ -8,4 +8,14 @@ import { DialConfig } from './Dial/index'
import { SankeyConfig } from './Sankey/index'
import { GraphConfig } from './Graph/index'
export default [ProcessConfig, RadarConfig, FunnelConfig, HeatmapConfig, WaterPoloConfig, TreeMapConfig, GraphConfig, SankeyConfig, DialConfig]
export default [
ProcessConfig,
RadarConfig,
FunnelConfig,
HeatmapConfig,
WaterPoloConfig,
TreeMapConfig,
GraphConfig,
SankeyConfig,
DialConfig
]

View File

@@ -7,6 +7,22 @@
</n-input-number>
</SettingItem>
</SettingItemBox>
<!-- 中心标题 -->
<SettingItemBox v-if="config.title" name="标题">
<SettingItem name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="config.title.textStyle.color"></n-color-picker>
</SettingItem>
<SettingItem name="字体大小">
<n-input-number
v-model:value="config.title.textStyle.fontSize"
:min="0"
:step="1"
size="small"
placeholder="字体大小"
>
</n-input-number>
</SettingItem>
</SettingItemBox>
<!-- Echarts 全局设置 -->
<SettingItemBox name="进度条">
<SettingItem name="颜色">
@@ -31,24 +47,8 @@
></n-color-picker>
</SettingItem>
</SettingItemBox>
<!-- 中心标题 -->
<SettingItemBox v-if="config.title" name="标题">
<SettingItem name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="config.title.textStyle.color"></n-color-picker>
</SettingItem>
<SettingItem name="字体大小">
<n-input-number
v-model:value="config.title.textStyle.fontSize"
:min="0"
:step="1"
size="small"
placeholder="字体大小"
>
</n-input-number>
</SettingItem>
</SettingItemBox>
<!-- 其他样式 -->
<SettingItemBox name="轨道样式">
<SettingItemBox name="轨道">
<SettingItem name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="item.data[1].itemStyle.color"></n-color-picker>
</SettingItem>
@@ -69,6 +69,18 @@
v-model:value="item.data[1].itemStyle.shadowColor"
></n-color-picker>
</SettingItem>
<SettingItem name="轨道宽度">
<n-select
v-model:value="item.radius[0]"
size="small"
:options="[
{ label: '窄', value: '75%' },
{ label: '中', value: '60%' },
{ label: '宽', value: '45%' },
{ label: '更宽', value: '30%' }
]"
/>
</SettingItem>
</SettingItemBox>
</CollapseItem>
</template>

View File

@@ -41,7 +41,7 @@ const option = reactive({
const dataHandle = (newData: any) => {
const d = parseFloat(`${newData}`) * 100
let config = props.chartConfig.option
config.title.text = d.toFixed(2) + '%'
config.title.text = `${+d.toFixed(2)}%`
config.series[0].data[0].value[0] = d
config.series[0].data[1].value[0] = 100 - d
option.value = mergeTheme(props.chartConfig.option, props.themeSetting, includes)
@@ -68,7 +68,7 @@ watch(
useChartDataFetch(props.chartConfig, useChartEditStore, (resData: number) => {
let d = parseFloat(`${resData}`) * 100
// @ts-ignore
option.value.title.text = d.toFixed(2) + '%'
option.value.title.text = `${+d.toFixed(2)}%`
// @ts-ignore
option.value.series[0].data[0].value[0] = d
// @ts-ignore

View File

@@ -18,7 +18,14 @@ export const PieTypeObject = {
[PieTypeEnum.ROSE]: 'rose'
}
// 其它配置
const otherConfig = {
// 轮播动画
isCarousel: false,
}
const option = {
...otherConfig,
type: 'ring',
tooltip: {
show: true,

View File

@@ -1,88 +1,99 @@
<template>
<!-- Echarts 全局设置 -->
<global-setting :optionData="optionData"></global-setting>
<CollapseItem name="饼图配置" :expanded="true">
<SettingItemBox name="类型">
<SettingItem>
<n-select v-model:value="optionData.type" size="small" :options="fontWeightOptions" />
</SettingItem>
</SettingItemBox>
<SettingItemBox name="标签">
<SettingItem>
<n-space>
<n-switch v-model:value="optionData.series[0].label.show" size="small"></n-switch>
<n-text>展示标签</n-text>
</n-space>
</SettingItem>
<setting-item>
<n-space>
<n-switch v-model:value="optionData.series[0].labelLine.show" size="small"></n-switch>
<n-text>引导线</n-text>
</n-space>
</setting-item>
<SettingItem name="位置">
<n-select v-model:value="optionData.series[0].label.position" size="small" :options="labelConfig.position" />
</SettingItem>
<setting-item name="展示类型">
<n-select v-model:value="optionData.series[0].label.formatter" size="small" :options="labelFormatterOptions" />
</setting-item>
</SettingItemBox>
<setting-item-box name="圆角">
<setting-item>
<n-space>
<n-input-number
v-model:value="optionData.series[0].itemStyle.borderRadius"
size="small"
:min="0"
></n-input-number>
<n-text>圆角大小</n-text>
</n-space>
</setting-item>
<setting-item>
<n-space>
<n-input-number
v-model:value="optionData.series[0].itemStyle.borderWidth"
size="small"
:min="0"
></n-input-number>
<n-text>线条宽度</n-text>
</n-space>
</setting-item>
</setting-item-box>
</CollapseItem>
</template>
<script setup lang="ts">
import { PropType, watch } from 'vue'
import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
import { GlobalSetting, CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { PieTypeObject, PieTypeEnum } from './config'
import { labelConfig } from '@/packages/chartConfiguration/echarts'
const props = defineProps({
optionData: {
type: Object as PropType<GlobalThemeJsonType>,
required: true
}
})
const fontWeightOptions = [
{
label: PieTypeEnum.NORMAL,
value: PieTypeObject[PieTypeEnum.NORMAL]
},
{
label: PieTypeEnum.RING,
value: PieTypeObject[PieTypeEnum.RING]
},
{
label: PieTypeEnum.ROSE,
value: PieTypeObject[PieTypeEnum.ROSE]
}
]
const labelFormatterOptions = [
{ label: '数据名', value: '{b}' },
{ label: '百分比', value: '{d}' },
{ label: '列名:百分比', value: '{b}:{d}%' }
]
</script>
<template>
<!-- Echarts 全局设置 -->
<global-setting :optionData="optionData"></global-setting>
<CollapseItem name="饼图配置" :expanded="true">
<SettingItemBox name="类型">
<SettingItem>
<n-select v-model:value="optionData.type" size="small" :options="fontWeightOptions" />
</SettingItem>
</SettingItemBox>
<SettingItemBox name="动画" :alone="true">
<SettingItem>
<n-space>
<n-switch v-model:value="optionData.isCarousel" size="small"></n-switch>
<n-text>开启<n-text :depth="3">将自动隐藏图例</n-text></n-text>
</n-space>
</SettingItem>
<SettingItem>
<n-text :depth="3">无鼠标点击图例场景时可强行打开图例</n-text>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="标签">
<SettingItem>
<n-space>
<n-switch v-model:value="optionData.series[0].label.show" size="small"></n-switch>
<n-text>展示标签</n-text>
</n-space>
</SettingItem>
<setting-item>
<n-space>
<n-switch v-model:value="optionData.series[0].labelLine.show" size="small"></n-switch>
<n-text>引导线</n-text>
</n-space>
</setting-item>
<SettingItem name="位置">
<n-select v-model:value="optionData.series[0].label.position" size="small" :options="labelConfig.position" />
</SettingItem>
<setting-item name="展示类型">
<n-select v-model:value="optionData.series[0].label.formatter" size="small" :options="labelFormatterOptions" />
</setting-item>
</SettingItemBox>
<setting-item-box name="圆角">
<setting-item>
<n-space>
<n-input-number
v-model:value="optionData.series[0].itemStyle.borderRadius"
size="small"
:min="0"
></n-input-number>
<n-text>圆角大小</n-text>
</n-space>
</setting-item>
<setting-item>
<n-space>
<n-input-number
v-model:value="optionData.series[0].itemStyle.borderWidth"
size="small"
:min="0"
></n-input-number>
<n-text>线条宽度</n-text>
</n-space>
</setting-item>
</setting-item-box>
</CollapseItem>
</template>
<script setup lang="ts">
import { PropType, watch } from 'vue'
import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
import { GlobalSetting, CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { PieTypeObject, PieTypeEnum } from './config'
import { labelConfig } from '@/packages/chartConfiguration/echarts'
const props = defineProps({
optionData: {
type: Object as PropType<GlobalThemeJsonType>,
required: true
}
})
const fontWeightOptions = [
{
label: PieTypeEnum.NORMAL,
value: PieTypeObject[PieTypeEnum.NORMAL]
},
{
label: PieTypeEnum.RING,
value: PieTypeObject[PieTypeEnum.RING]
},
{
label: PieTypeEnum.ROSE,
value: PieTypeObject[PieTypeEnum.ROSE]
}
]
const labelFormatterOptions = [
{ label: '数据名', value: '{b}' },
{ label: '百分比', value: '{d}' },
{ label: '列名:百分比', value: '{b}:{d}%' }
]
</script>

View File

@@ -1,64 +1,149 @@
<template>
<v-chart ref="vChartRef" :init-options="initOptions" :theme="themeColor" :option="option" :manual-update="isPreview()" autoresize></v-chart>
</template>
<script setup lang="ts">
import { computed, PropType, reactive, watch } from 'vue'
import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { PieChart } from 'echarts/charts'
import { mergeTheme } from '@/packages/public/chart'
import config, { includes } from './config'
import { useChartDataFetch } from '@/hooks'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { isPreview } from '@/utils'
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
const props = defineProps({
themeSetting: {
type: Object,
required: true
},
themeColor: {
type: Object,
required: true
},
chartConfig: {
type: Object as PropType<config>,
required: true
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
use([DatasetComponent, CanvasRenderer, PieChart, GridComponent, TooltipComponent, LegendComponent])
const option = computed(() => {
return mergeTheme(props.chartConfig.option, props.themeSetting, includes)
})
watch(
() => props.chartConfig.option.type,
newData => {
try {
if (newData === 'nomal') {
props.chartConfig.option.series[0].radius = '70%'
props.chartConfig.option.series[0].roseType = false
} else if (newData === 'ring') {
props.chartConfig.option.series[0].radius = ['40%', '65%']
props.chartConfig.option.series[0].roseType = false
} else {
props.chartConfig.option.series[0].radius = '70%'
props.chartConfig.option.series[0].roseType = true
}
} catch (error) {
console.log(error)
}
},
{ deep: false, immediate: true }
)
const { vChartRef } = useChartDataFetch(props.chartConfig, useChartEditStore)
</script>
<template>
<v-chart
ref="vChartRef"
autoresize
:init-options="initOptions"
:theme="themeColor"
:option="option"
:manual-update="isPreview()"
@mouseover="handleHighlight"
@mouseout="handleDownplay"
></v-chart>
</template>
<script setup lang="ts">
import { computed, PropType, onMounted, watch } from 'vue'
import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { PieChart } from 'echarts/charts'
import { mergeTheme } from '@/packages/public/chart'
import config, { includes } from './config'
import { useChartDataFetch } from '@/hooks'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { isPreview } from '@/utils'
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import dataJson from './data.json'
const props = defineProps({
themeSetting: {
type: Object,
required: true
},
themeColor: {
type: Object,
required: true
},
chartConfig: {
type: Object as PropType<config>,
required: true
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
let seriesDataNum = -1
let seriesDataMaxLength = 0
let intervalInstance: any = null
use([DatasetComponent, CanvasRenderer, PieChart, GridComponent, TooltipComponent, LegendComponent])
const option = computed(() => {
return mergeTheme(props.chartConfig.option, props.themeSetting, includes)
})
// 会重新选择需要选中和展示的数据
const handleSeriesData = () => {
if (seriesDataNum > -1) {
vChartRef.value?.dispatchAction({
type: 'downplay',
dataIndex: seriesDataNum
})
}
seriesDataNum = seriesDataNum >= seriesDataMaxLength - 1 ? 0 : seriesDataNum + 1
vChartRef.value?.dispatchAction({
type: 'highlight',
dataIndex: seriesDataNum
})
}
// 新增轮播
const addPieInterval = (newData?: typeof dataJson, skipPre = false) => {
if (!skipPre && !Array.isArray(newData?.source)) return
if (!skipPre) seriesDataMaxLength = newData?.source.length || 0
clearInterval(intervalInstance)
intervalInstance = setInterval(() => {
handleSeriesData()
}, 1000)
}
// 取消轮播
const clearPieInterval = () => {
vChartRef.value?.dispatchAction({
type: 'downplay',
dataIndex: seriesDataNum
})
clearInterval(intervalInstance)
intervalInstance = null
}
// 处理鼠标聚焦高亮内容
const handleHighlight = () => {
clearPieInterval()
}
// 处理鼠标取消悬浮
const handleDownplay = () => {
if (props.chartConfig.option.isCarousel && !intervalInstance) {
// 恢复轮播
addPieInterval(undefined, true)
}
}
watch(
() => props.chartConfig.option.type,
newData => {
try {
if (newData === 'nomal') {
props.chartConfig.option.series[0].radius = '70%'
props.chartConfig.option.series[0].roseType = false
} else if (newData === 'ring') {
props.chartConfig.option.series[0].radius = ['40%', '65%']
props.chartConfig.option.series[0].roseType = false
} else {
props.chartConfig.option.series[0].radius = '70%'
props.chartConfig.option.series[0].roseType = true
}
} catch (error) {
console.log(error)
}
},
{ deep: false, immediate: true }
)
watch(
() => props.chartConfig.option.isCarousel,
newData => {
if (newData) {
addPieInterval(undefined, true)
props.chartConfig.option.legend.show = false
} else {
props.chartConfig.option.legend.show = true
clearPieInterval()
}
}
)
const { vChartRef } = useChartDataFetch(props.chartConfig, useChartEditStore, (newData: typeof dataJson) => {
clearPieInterval()
if (props.chartConfig.option.isCarousel) {
addPieInterval(newData)
}
})
onMounted(() => {
seriesDataMaxLength = dataJson.source.length
if (props.chartConfig.option.isCarousel) {
addPieInterval(undefined, true)
}
})
</script>

View File

@@ -1,81 +1,80 @@
import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
import { ScatterCommonConfig } from './index'
import { CreateComponentType } from '@/packages/index.d'
import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json'
export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
export const seriesItem = {
type: 'scatter',
emphasis: {
focus: 'series'
},
symbolSize: 12,
markArea: {
silent: true,
itemStyle: {
color: 'transparent',
borderWidth: 1,
borderType: 'dashed'
},
data: [
[
{
xAxis: 'min',
yAxis: 'min'
},
{
xAxis: 'max',
yAxis: 'max'
}
]
]
},
markPoint: {
symbol: 'pin',
symbolSize: 50,
data: [
{ type: 'max', name: 'Max' },
{ type: 'min', name: 'Min' }
]
}
}
export const option = {
dataset: dataJson,
tooltip: {
showDelay: 0,
formatter: (params: { value: string | any[]; seriesName: string; name: string }) => {
// console.log(params)
return params.value.length > 1
? `${params.seriesName}<br />${params.value[0]} ${params.value[1]}`
: `${params.seriesName}<br />${params.name} ${params.value}`
},
axisPointer: {
show: true,
type: 'cross',
lineStyle: {
type: 'dashed',
width: 1
}
}
},
xAxis: {
scale: true
},
yAxis: {
scale: true
},
series: dataJson.map((item, index) => ({
...seriesItem,
datasetIndex: index
}))
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key = ScatterCommonConfig.key
public chartConfig = cloneDeep(ScatterCommonConfig)
// 图表配置项
public option = echartOptionProfixHandle(option, includes)
}
import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
import { ScatterCommonConfig } from './index'
import { CreateComponentType } from '@/packages/index.d'
import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json'
export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
export const seriesItem = {
type: 'scatter',
emphasis: {
focus: 'series'
},
symbolSize: 12,
markArea: {
silent: true,
itemStyle: {
color: 'transparent',
borderWidth: 1,
borderType: 'dashed'
},
data: [
[
{
xAxis: 'min',
yAxis: 'min'
},
{
xAxis: 'max',
yAxis: 'max'
}
]
]
},
markPoint: {
symbol: 'pin',
symbolSize: 50,
data: [
{ type: 'max', name: 'Max' },
{ type: 'min', name: 'Min' }
]
}
}
export const option = {
dataset: dataJson,
tooltip: {
showDelay: 0,
formatter: (params: { value: string | any[]; seriesName: string; name: string }) => {
return params.value.length > 1
? `${params.seriesName}<br />${params.value[0]} ${params.value[1]}`
: `${params.name} ${params.value}`
},
axisPointer: {
show: true,
type: 'cross',
lineStyle: {
type: 'dashed',
width: 1
}
}
},
xAxis: {
scale: true
},
yAxis: {
scale: true
},
series: dataJson.map((item, index) => ({
...seriesItem,
datasetIndex: index
}))
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key = ScatterCommonConfig.key
public chartConfig = cloneDeep(ScatterCommonConfig)
// 图表配置项
public option = echartOptionProfixHandle(option, includes)
}

View File

@@ -14,5 +14,6 @@ export enum ChatCategoryEnumName {
LINE = '折线图',
SCATTER = '散点图',
MAP = '地图',
COMBINATION = '组合图',
MORE = '更多'
}

View File

@@ -16,6 +16,7 @@ export interface OptionType {
flipperGap: number
flipperType: FlipType
flipperSpeed: number
flipperBorderWidth: number
}
export const option: OptionType = {
@@ -28,7 +29,8 @@ export const option: OptionType = {
flipperRadius: 5,
flipperGap: 10,
flipperType: 'down',
flipperSpeed: 450
flipperSpeed: 450,
flipperBorderWidth: 0,
}
export default class Config extends PublicConfigClass implements CreateComponentType {

View File

@@ -16,12 +16,16 @@
<setting-item name="高度">
<n-input-number v-model:value="optionData.flipperHeight" size="small" :min="1"></n-input-number>
</setting-item>
<setting-item name="间隔">
<n-input-number v-model:value="optionData.flipperGap" size="small" :min="0"></n-input-number>
<setting-item name="边框">
<n-input-number v-model:value="optionData.flipperBorderWidth" size="small" :min="0" :max="10"></n-input-number>
</setting-item>
<setting-item name="圆角">
<n-input-number v-model:value="optionData.flipperRadius" size="small" :min="0"></n-input-number>
</setting-item>
<setting-item name="翻牌间隔">
<n-input-number v-model:value="optionData.flipperGap" size="small" :min="0"></n-input-number>
</setting-item>
<setting-item />
<setting-item name="背景色">
<n-color-picker
size="small"

View File

@@ -9,6 +9,7 @@
:radius="flipperRadius"
:flip-type="flipperType"
:duration="flipperSpeed"
:border-width="flipperBorderWidth"
v-for="(item, index) in flipperData"
:key="index"
class="go-d-block"
@@ -42,7 +43,8 @@ const {
flipperRadius,
flipperGap,
flipperType,
flipperSpeed
flipperSpeed,
flipperBorderWidth
} = toRefs(props.chartConfig.option as OptionType)
const flipperData = ref<string[] | number[]>([])
@@ -61,7 +63,7 @@ watch(
() => props.chartConfig.option,
newVal => {
try {
updateDatasetHandler((newVal as OptionType).dataset)
updateDatasetHandler((newVal as any as OptionType).dataset)
} catch (error) {
console.log(error)
}

View File

@@ -0,0 +1,18 @@
import { PublicConfigClass } from '@/packages/public'
import { CreateComponentType } from '@/packages/index.d'
import { chartInitConfig } from '@/settings/designSetting'
import { FullScreenConfig } from './index'
import cloneDeep from 'lodash/cloneDeep'
export const option = {
border: 6,
bgColor: '#84a5e9',
borderColor: '#84a5e9'
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key = FullScreenConfig.key
public attr = { ...chartInitConfig, w: 150, h: 150, zIndex: -1 }
public chartConfig = cloneDeep(FullScreenConfig)
public option = cloneDeep(option)
}

View File

@@ -0,0 +1,28 @@
<template>
<CollapseItem name="全屏按钮" expanded>
<SettingItemBox name="按钮">
<SettingItem name="背景色">
<n-color-picker size="small" :modes="['hex']" v-model:value="optionData.bgColor"></n-color-picker>
</SettingItem>
<SettingItem name="边框色">
<n-color-picker size="small" :modes="['hex']" v-model:value="optionData.borderColor"></n-color-picker>
</SettingItem>
<SettingItem name="边框大小">
<n-input-number v-model:value="optionData.border" size="small" :step="0.5" :min="0"></n-input-number>
</SettingItem>
</SettingItemBox>
</CollapseItem>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { option } from './config'
const props = defineProps({
optionData: {
type: Object as PropType<typeof option>,
required: true
}
})
</script>

View File

@@ -0,0 +1,14 @@
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
export const FullScreenConfig: ConfigType = {
key: 'FullScreen',
chartKey: 'VFullScreen',
conKey: 'VCFullScreen',
title: '全屏按钮',
category: ChatCategoryEnum.MORE,
categoryName: ChatCategoryEnumName.MORE,
package: PackagesCategoryEnum.DECORATES,
chartFrame: ChartFrameEnum.STATIC,
image: 'fullScreen.png'
}

View File

@@ -0,0 +1,111 @@
<template>
<svg @click="toggleFullscreen" v-if="!isFullscreen" viewBox="0 0 1024 1024">
<path
d="M665.6 1017.6c-19.2 0-38.4-19.2-38.4-38.4s19.2-38.4 38.4-38.4h268.8l6.4-268.8c0-19.2 19.2-38.4 38.4-38.4s38.4 19.2 38.4 38.4v294.4c0 32-25.6 51.2-51.2 51.2h-300.8zM51.2 396.8c-19.2 0-38.4-19.2-38.4-38.4V64C12.8 32 38.4 12.8 64 12.8h294.4c19.2 0 38.4 19.2 38.4 38.4s-19.2 38.4-38.4 38.4H89.6v268.8c0 19.2-19.2 38.4-38.4 38.4zM64 1017.6c-32 0-51.2-25.6-51.2-51.2v-294.4c0-19.2 19.2-38.4 38.4-38.4s38.4 19.2 38.4 38.4v217.6l198.4-198.4c6.4-6.4 19.2-12.8 25.6-12.8s19.2 6.4 25.6 12.8c6.4 6.4 12.8 19.2 12.8 25.6 0 12.8-6.4 19.2-12.8 25.6l-198.4 198.4h217.6c19.2 0 38.4 19.2 38.4 38.4s-19.2 38.4-38.4 38.4H64z m915.2-620.8c-19.2 0-38.4-19.2-38.4-38.4V140.8l-198.4 198.4c-6.4 6.4-19.2 12.8-25.6 12.8-12.8 0-19.2-6.4-25.6-12.8-12.8-12.8-12.8-38.4 0-51.2l198.4-198.4h-217.6c-19.2 0-38.4-19.2-38.4-38.4s19.2-38.4 38.4-38.4h294.4c32 0 51.2 25.6 51.2 51.2v294.4c0 19.2-19.2 38.4-38.4 38.4z"
class="fullScreen-border"
></path>
</svg>
<svg @click="toggleFullscreen" v-else viewBox="0 0 1024 1024">
<path
d="M379.336 697.237L153.362 921.55c-14.11 14.007-36.905 13.922-50.912-0.188-14.007-14.11-13.922-36.905 0.188-50.912l227.6-225.927H138.645c-18.99 0-34.385-15.446-34.385-34.5 0-19.053 15.395-34.5 34.385-34.5H413.72c18.99 0 34.384 15.447 34.384 34.5v276c0 9.15-3.622 17.926-10.07 24.396a34.326 34.326 0 0 1-24.314 10.104 34.326 34.326 0 0 1-24.314-10.104 34.559 34.559 0 0 1-10.071-24.396V697.237z m263.395-366.88l227.813-227.813c14.059-14.059 36.853-14.059 50.912 0 14.059 14.059 14.059 36.853 0 50.912l-225.18 225.18h187.147c18.99 0 34.385 15.445 34.385 34.5 0 19.053-15.395 34.5-34.385 34.5H608.346c-18.99 0-34.384-15.447-34.384-34.5v-276c0-9.15 3.622-17.926 10.07-24.396a34.326 34.326 0 0 1 24.314-10.105c9.12 0 17.865 3.635 24.314 10.105a34.559 34.559 0 0 1 10.07 24.395v193.223zM99.385 410a34.326 34.326 0 0 1-24.314-10.105A34.559 34.559 0 0 1 65 375.5v-276C65 80.446 80.395 65 99.385 65h275.077c18.99 0 34.384 15.446 34.384 34.5 0 19.054-15.394 34.5-34.384 34.5H133.769v241.5c0 9.15-3.622 17.925-10.07 24.395A34.326 34.326 0 0 1 99.384 410z m825.23 552H649.538c-18.99 0-34.384-15.446-34.384-34.5 0-19.054 15.394-34.5 34.384-34.5h240.693V651.5c0-19.054 15.394-34.5 34.384-34.5 18.99 0 34.385 15.446 34.385 34.5v276c0 19.054-15.395 34.5-34.385 34.5z"
class="fullScreen-border"
></path>
</svg>
</template>
<script setup lang="ts">
import { PropType, toRefs, ref, onMounted, onUnmounted } from 'vue'
import { CreateComponentType } from '@/packages/index.d'
import { option } from './config'
const props = defineProps({
chartConfig: {
type: Object as PropType<CreateComponentType & typeof option>,
required: true
}
})
let { border, bgColor, borderColor } = toRefs(props.chartConfig.option)
const isFullscreen = ref(false)
const checkFullscreen = () => {
isFullscreen.value = !!(
document.fullscreenElement ||
(document as any).webkitFullscreenElement ||
(document as any).mozFullScreenElement ||
(document as any).msFullscreenElement
)
}
checkFullscreen()
const requestFullscreen = (element: Element) => {
if (element.requestFullscreen) {
element.requestFullscreen()
} else if ((document as any).mozRequestFullScreen) {
/* Firefox */
(document as any).mozRequestFullScreen()
} else if ((document as any).webkitRequestFullscreen) {
/* Chrome, Safari and Opera */
(document as any).webkitRequestFullscreen()
} else if ((document as any).msRequestFullscreen) {
/* IE/Edge */
(document as any).msRequestFullscreen()
}
}
const exitFullscreen = () => {
if (document.fullscreenElement && document.exitFullscreen) {
document.exitFullscreen()
} else if ((document as any).mozFullScreenElement && (document as any).mozCancelFullScreen) {
/* Firefox */
(document as any).mozCancelFullScreen()
} else if ((document as any).webkitFullscreenElement && (document as any).webkitExitFullscreen) {
/* Chrome, Safari and Opera */
(document as any).webkitExitFullscreen()
} else if ((document as any).msFullscreenElement && (document as any).msExitFullscreen) {
/* IE/Edge */
(document as any).msExitFullscreen()
}
}
const toggleFullscreen = () => {
if (!isFullscreen.value) {
requestFullscreen(document.documentElement)
} else {
exitFullscreen()
}
isFullscreen.value = !isFullscreen.value
// 由于全屏状态的改变不会立即生效,所以需要延迟一段时间再去获取全屏状态
setTimeout(() => {
checkFullscreen()
}, 1000)
}
// 监听全屏状态的改变,保证多个全屏组件的状态一致
onMounted(() => {
document.addEventListener('fullscreenchange', checkFullscreen)
document.addEventListener('webkitfullscreenchange', checkFullscreen)
document.addEventListener('mozfullscreenchange', checkFullscreen)
document.addEventListener('MSFullscreenChange', checkFullscreen)
})
onUnmounted(() => {
document.removeEventListener('fullscreenchange', checkFullscreen)
document.removeEventListener('webkitfullscreenchange', checkFullscreen)
document.removeEventListener('mozfullscreenchange', checkFullscreen)
document.removeEventListener('MSFullscreenChange', checkFullscreen)
})
</script>
<style lang="scss" scoped>
svg {
display: block;
width: 100%;
height: 100%;
cursor: pointer;
}
.fullScreen-border {
stroke: v-bind('borderColor');
stroke-width: v-bind('border+"px"');
fill: v-bind('bgColor');
}
</style>

View File

@@ -0,0 +1,19 @@
import { PublicConfigClass } from '@/packages/public'
import { CreateComponentType } from '@/packages/index.d'
import { chartInitConfig } from '@/settings/designSetting'
import { PipelineHConfig } from './index'
import cloneDeep from 'lodash/cloneDeep'
export const option = {
color_type: 1,
o_color: '#0a7ae2',
i_color: '#119bfa',
line_class: 'svg_ani_flow'
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key = PipelineHConfig.key
public attr = { ...chartInitConfig, w: 500, h: 15, zIndex: -1 }
public chartConfig = cloneDeep(PipelineHConfig)
public option = cloneDeep(option)
}

View File

@@ -0,0 +1,77 @@
<template>
<CollapseItem name="管道" :expanded="true">
<SettingItemBox name="默认颜色">
<SettingItem>
<n-select v-model:value="optionData.color_type" :options="colorOptions" @update:value="handleColorChange" />
</SettingItem>
</SettingItemBox>
<SettingItemBox name="管道颜色">
<SettingItem>
<n-color-picker size="small" :modes="['hex']" v-model:value="optionData.o_color"></n-color-picker>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="水流颜色">
<SettingItem>
<n-color-picker size="small" :modes="['hex']" v-model:value="optionData.i_color"></n-color-picker>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="流向">
<SettingItem>
<n-select v-model:value="optionData.line_class" :options="options" />
</SettingItem>
</SettingItemBox>
</CollapseItem>
</template>
<script setup lang="ts">
import { PropType, ref } from 'vue'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { option } from './config'
const props = defineProps({
optionData: {
type: Object as PropType<typeof option>,
required: true
}
})
const options = ref([
{
value: 'svg_ani_flow',
label: '正向'
},
{
value: 'svg_ani_flow_back',
label: '反向'
},
{
value: 'svg_ani_flow_stop',
label: '停止'
}
])
const colorOptions = ref([
{
value: 1,
label: '蓝'
},
{
value: 2,
label: '黄'
}
])
// 默认颜色
const handleColorChange = (e: number) => {
switch (e) {
case 1:
props.optionData.o_color = '#0a7ae2'
props.optionData.i_color = '#119bfa'
break
case 2:
props.optionData.o_color = '#ff9d00'
props.optionData.i_color = '#f7ea37'
break
}
}
</script>

View File

@@ -0,0 +1,13 @@
import { ConfigType, PackagesCategoryEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
export const PipelineHConfig: ConfigType = {
key: 'PipelineH',
chartKey: 'VPipelineH',
conKey: 'VCPipelineH',
title: '管道-横向',
category: ChatCategoryEnum.MORE,
categoryName: ChatCategoryEnumName.MORE,
package: PackagesCategoryEnum.DECORATES,
image: 'Pipeline_H.png'
}

View File

@@ -0,0 +1,141 @@
<template>
<div class="go-decorates-line">
<svg :width="w" :height="h">
<line :x1="0" :y1="h / 2" :x2="w" :y2="h / 2" :stroke="o_color" :stroke-width="h"></line>
<line :x1="0" :y1="h / 2" :x2="w" :y2="h / 2" :stroke="i_color" :stroke-width="h / 2" :class="line_class"></line>
</svg>
</div>
</template>
<script setup lang="ts">
import { PropType, toRefs } from 'vue'
import { CreateComponentType } from '@/packages/index.d'
const props = defineProps({
chartConfig: {
type: Object as PropType<CreateComponentType>,
required: true
}
})
const { w, h } = toRefs(props.chartConfig.attr)
const { o_color, i_color, line_class } = toRefs(props.chartConfig.option)
</script>
<style lang="scss" scoped>
.go-decorates-line {
font-size: 0;
}
/* 正向流动效果 */
.svg_ani_flow {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: ani_flow 10s linear infinite;
animation-fill-mode: forwards;
-webkit-animation: ani_flow 10s linear infinite;
-webkit-animation-fill-mode: forwards;
}
@keyframes ani_flow {
from {
stroke-dasharray: 10, 5;
}
to {
stroke-dasharray: 13, 5;
}
}
@-webkit-keyframes ani_flow {
from {
stroke-dasharray: 10, 5;
}
to {
stroke-dasharray: 13, 5;
}
}
/* 停止流动效果 */
.svg_ani_flow_stop {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: ani_flow_stop 10s linear infinite;
animation-fill-mode: forwards;
-webkit-animation: ani_flow_stop 10s linear infinite;
-webkit-animation-fill-mode: forwards;
}
@keyframes ani_flow_stop {
from {
stroke-dasharray: 10, 5;
}
to {
stroke-dasharray: 10, 5;
}
}
@-webkit-keyframes ani_flow_stop {
from {
stroke-dasharray: 10, 5;
}
to {
stroke-dasharray: 10, 5;
}
}
/* 反向流动效果 */
.svg_ani_flow_back {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: ani_flow_back 10s linear infinite;
animation-fill-mode: forwards;
-webkit-animation: ani_flow_back 10s linear infinite;
-webkit-animation-fill-mode: forwards;
}
@keyframes ani_flow_back {
from {
stroke-dasharray: 13, 5;
}
to {
stroke-dasharray: 10, 5;
}
}
@-webkit-keyframes ani_flow_stop {
from {
stroke-dasharray: 10, 5;
}
to {
stroke-dasharray: 10, 5;
}
}
/* 以最大40高度填充 */
.svg_ani_fill_h40 {
animation: ani_fill_h40 5s linear infinite;
animation-fill-mode: forwards;
-webkit-animation: ani_fill_h40 5s linear infinite;
-webkit-animation-fill-mode: forwards;
}
@keyframes ani_fill_h40 {
from {
height: 0px;
}
to {
height: 40px;
}
}
@-webkit-keyframes ani_flow_stop {
from {
stroke-dasharray: 10, 5;
}
to {
stroke-dasharray: 10, 5;
}
}
</style>

View File

@@ -0,0 +1,19 @@
import { PublicConfigClass } from '@/packages/public'
import { CreateComponentType } from '@/packages/index.d'
import { chartInitConfig } from '@/settings/designSetting'
import { PipelineVConfig } from './index'
import cloneDeep from 'lodash/cloneDeep'
export const option = {
color_type: 1,
o_color: '#0a7ae2',
i_color: '#119bfa',
line_class: 'svg_ani_flow'
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key = PipelineVConfig.key
public attr = { ...chartInitConfig, w: 15, h: 500, zIndex: -1 }
public chartConfig = cloneDeep(PipelineVConfig)
public option = cloneDeep(option)
}

View File

@@ -0,0 +1,77 @@
<template>
<CollapseItem name="管道" :expanded="true">
<SettingItemBox name="默认颜色">
<SettingItem>
<n-select v-model:value="optionData.color_type" :options="colorOptions" @update:value="handleColorChange" />
</SettingItem>
</SettingItemBox>
<SettingItemBox name="管道颜色">
<SettingItem>
<n-color-picker size="small" :modes="['hex']" v-model:value="optionData.o_color"></n-color-picker>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="水流颜色">
<SettingItem>
<n-color-picker size="small" :modes="['hex']" v-model:value="optionData.i_color"></n-color-picker>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="流向">
<SettingItem>
<n-select v-model:value="optionData.line_class" :options="options" />
</SettingItem>
</SettingItemBox>
</CollapseItem>
</template>
<script setup lang="ts">
import { PropType, ref } from 'vue'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { option } from './config'
const props = defineProps({
optionData: {
type: Object as PropType<typeof option>,
required: true
}
})
const options = ref([
{
value: 'svg_ani_flow',
label: '正向'
},
{
value: 'svg_ani_flow_back',
label: '反向'
},
{
value: 'svg_ani_flow_stop',
label: '停止'
}
])
const colorOptions = ref([
{
value: 1,
label: '蓝'
},
{
value: 2,
label: '黄'
}
])
// 默认颜色
const handleColorChange = (e: number) => {
switch (e) {
case 1:
props.optionData.o_color = '#0a7ae2'
props.optionData.i_color = '#119bfa'
break
case 2:
props.optionData.o_color = '#ff9d00'
props.optionData.i_color = '#f7ea37'
break
}
}
</script>

View File

@@ -0,0 +1,14 @@
import { ConfigType, PackagesCategoryEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
export const PipelineVConfig: ConfigType = {
key: 'PipelineV',
chartKey: 'VPipelineV',
conKey: 'VCPipelineV',
title: '管道-纵向',
category: ChatCategoryEnum.MORE,
categoryName: ChatCategoryEnumName.MORE,
package: PackagesCategoryEnum.DECORATES,
image: 'Pipeline_V.png'
}

View File

@@ -0,0 +1,115 @@
<template>
<div class="go-decorates-line">
<svg :width="w" :height="h">
<line :x1="w / 2" :y1="0" :x2="w / 2" :y2="h" :stroke="o_color" :stroke-width="w"></line>
<line :x1="w / 2" :y1="0" :x2="w / 2" :y2="h" :stroke="i_color" :stroke-width="w / 2" :class="line_class"></line>
</svg>
</div>
</template>
<script setup lang="ts">
import { PropType, toRefs } from 'vue'
import { CreateComponentType } from '@/packages/index.d'
const props = defineProps({
chartConfig: {
type: Object as PropType<CreateComponentType>,
required: true
}
})
const { w, h } = toRefs(props.chartConfig.attr)
const { o_color, i_color, line_class } = toRefs(props.chartConfig.option)
</script>
<style lang="scss" scoped>
.go-decorates-line {
font-size: 0;
}
/* 正向流动效果 */
.svg_ani_flow {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: ani_flow 10s linear infinite;
animation-fill-mode: forwards;
-webkit-animation: ani_flow 10s linear infinite;
-webkit-animation-fill-mode: forwards;
}
@keyframes ani_flow {
from {
stroke-dasharray: 10, 5;
}
to {
stroke-dasharray: 13, 5;
}
}
@-webkit-keyframes ani_flow {
from {
stroke-dasharray: 10, 5;
}
to {
stroke-dasharray: 13, 5;
}
}
/* 停止流动效果 */
.svg_ani_flow_stop {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: ani_flow_stop 10s linear infinite;
animation-fill-mode: forwards;
-webkit-animation: ani_flow_stop 10s linear infinite;
-webkit-animation-fill-mode: forwards;
}
@keyframes ani_flow_stop {
from {
stroke-dasharray: 10, 5;
}
to {
stroke-dasharray: 10, 5;
}
}
@-webkit-keyframes ani_flow_stop {
from {
stroke-dasharray: 10, 5;
}
to {
stroke-dasharray: 10, 5;
}
}
/* 反向流动效果 */
.svg_ani_flow_back {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: ani_flow_back 10s linear infinite;
animation-fill-mode: forwards;
-webkit-animation: ani_flow_back 10s linear infinite;
-webkit-animation-fill-mode: forwards;
}
@keyframes ani_flow_back {
from {
stroke-dasharray: 13, 5;
}
to {
stroke-dasharray: 10, 5;
}
}
@-webkit-keyframes ani_flow_back {
from {
stroke-dasharray: 13, 5;
}
to {
stroke-dasharray: 10, 5;
}
}
</style>

View File

@@ -1,7 +1,19 @@
import { NumberConfig } from './Number/index'
import { TimeCommonConfig } from './TimeCommon/index'
import { ClockConfig } from './Clock/index'
import { FullScreenConfig } from './FullScreen/index'
import { CountDownConfig } from './CountDown/index'
import { FlipperNumberConfig } from './FlipperNumber'
import { PipelineHConfig } from './PipelineH/index'
import { PipelineVConfig } from './PipelineV/index'
export default [NumberConfig, FlipperNumberConfig, TimeCommonConfig, CountDownConfig, ClockConfig]
export default [
NumberConfig,
FlipperNumberConfig,
TimeCommonConfig,
CountDownConfig,
ClockConfig,
FullScreenConfig,
PipelineHConfig,
PipelineVConfig
]

View File

@@ -1,4 +1,3 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
import {
ArcCurve,

View File

@@ -1,62 +1,63 @@
/**
* 创建 threejs 四大天王
* 场景、相机、渲染器、控制器
*/
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
export class Basic {
public scene!: THREE.Scene
public camera!: THREE.PerspectiveCamera
public renderer!: THREE.WebGLRenderer
public controls!: OrbitControls
public dom: HTMLElement
constructor(dom: HTMLElement) {
this.dom = dom
this.initScenes()
this.setControls()
}
/**
* 初始化场景
*/
initScenes() {
this.scene = new THREE.Scene()
this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 100000)
this.camera.position.set(0, 30, -250)
this.renderer = new THREE.WebGLRenderer({
// canvas: this.dom,
alpha: true, // 透明
antialias: true // 抗锯齿
})
this.renderer.setPixelRatio(window.devicePixelRatio) // 设置屏幕像素比
this.renderer.setSize(window.innerWidth, window.innerHeight) // 设置渲染器宽高
this.dom.appendChild(this.renderer.domElement) // 添加到dom中
}
/**
* 设置控制器
*/
setControls() {
// 鼠标控制 相机渲染dom
this.controls = new OrbitControls(this.camera, this.renderer.domElement)
this.controls.autoRotateSpeed = 3
// 使动画循环使用时阻尼或自转 意思是否有惯性
this.controls.enableDamping = true
// 动态阻尼系数 就是鼠标拖拽旋转灵敏度
this.controls.dampingFactor = 0.05
// 是否可以缩放
this.controls.enableZoom = true
// 设置相机距离原点的最远距离
this.controls.minDistance = 100
// 设置相机距离原点的最远距离
this.controls.maxDistance = 300
// 是否开启右键拖拽
this.controls.enablePan = false
}
}
/**
* 创建 threejs 四大天王
* 场景、相机、渲染器、控制器
*/
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
export class Basic {
public scene!: THREE.Scene
public camera!: THREE.PerspectiveCamera
public renderer!: THREE.WebGLRenderer
public controls!: OrbitControls
public dom: HTMLElement
constructor(dom: HTMLElement) {
this.dom = dom
this.initScenes()
this.setControls()
}
/**
* 初始化场景
*/
initScenes() {
this.scene = new THREE.Scene()
this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 100000)
this.camera.position.set(0, 30, -250)
this.renderer = new THREE.WebGLRenderer({
// canvas: this.dom,
alpha: true, // 透明
antialias: true, // 抗锯齿
preserveDrawingBuffer: true
})
this.renderer.setPixelRatio(window.devicePixelRatio) // 设置屏幕像素比
this.renderer.setSize(window.innerWidth, window.innerHeight) // 设置渲染器宽高
this.dom.appendChild(this.renderer.domElement) // 添加到dom中
}
/**
* 设置控制器
*/
setControls() {
// 鼠标控制 相机渲染dom
this.controls = new OrbitControls(this.camera, this.renderer.domElement)
this.controls.autoRotateSpeed = 3
// 使动画循环使用时阻尼或自转 意思是否有惯性
this.controls.enableDamping = true
// 动态阻尼系数 就是鼠标拖拽旋转灵敏度
this.controls.dampingFactor = 0.05
// 是否可以缩放
this.controls.enableZoom = true
// 设置相机距离原点的最远距离
this.controls.minDistance = 100
// 设置相机距离原点的最远距离
this.controls.maxDistance = 300
// 是否开启右键拖拽
this.controls.enablePan = false
}
}

View File

@@ -0,0 +1,84 @@
import { IconConfig } from '../Default/Icon/index'
import { PackagesCategoryEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../index.d'
const iconNames = [
'uim:adobe',
'uim:airplay',
'uim:align',
'uim:angle-double-down',
'uim:angle-double-left',
'uim:angle-double-right',
'uim:angle-double-up',
'uim:angle-down',
'uim:angle-left',
'uim:angle-right',
'uim:angle-up',
'uim:android-alt',
'uim:apple',
'uim:apps',
'uim:bag',
'uim:battery-bolt',
'uim:bing',
'uim:box',
'uim:briefcase',
'uim:calender',
'uim:chart',
'uim:chart-pie',
'uim:circle-layer',
'uim:clinic-medical',
'uim:clock',
'uim:comment-alt',
'uim:comment-alt-dots',
'uim:docker',
'uim:download-alt',
'uim:dribbble',
'uim:dropbox',
'uim:entry',
'uim:exclamation-circle',
'uim:exclamation-triangle',
'uim:exit',
'uim:facebook',
'uim:facebook-messenger',
'uim:facebook-messenger-alt',
'uim:google-drive',
'uim:google-play',
'uim:graph-bar',
'uim:head-side-mask',
'uim:horizontal-align-left',
'uim:hospital',
'uim:house-user',
'uim:image-v',
'uim:key-skeleton',
'uim:layer-group',
'uim:layers-alt',
'uim:link-h',
'uim:microscope',
'uim:microsoft',
'uim:object-group',
'uim:object-ungroup',
'uim:paypal',
'uim:refresh',
'uim:repeat',
'uim:right-indent-alt',
'uim:rocket',
'uim:shield-plus',
'uim:social-distancing',
'uim:telegram-alt',
'uim:user-md',
'uim:toilet-paper',
'uim:youtube'
]
const iconList = iconNames.map(name => ({
...IconConfig,
category: ChatCategoryEnum.COMMON,
categoryName: ChatCategoryEnumName.COMMON,
package: PackagesCategoryEnum.ICONS,
image: name,
icon: name,
dataset: name,
title: name.replace('uim:', ''),
redirectComponent: `${IconConfig.package}/${IconConfig.category}/${IconConfig.key}` // 跳转组件路径规则packageName/categoryName/componentKey
}))
export default iconList

View File

@@ -0,0 +1,20 @@
import { PublicConfigClass } from '@/packages/public'
import { CreateComponentType } from '@/packages/index.d'
import { chartInitConfig } from '@/settings/designSetting'
import { IconConfig } from './index'
import cloneDeep from 'lodash/cloneDeep'
export const option = {
// 图标名称
dataset: 'uim:apple',
color: '#03A9F4',
size: 64,
rotate: 0 // 旋转角度
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key = IconConfig.key
public attr = { ...chartInitConfig, w: 64, h: 64, zIndex: 1 }
public chartConfig = cloneDeep(IconConfig)
public option = cloneDeep(option)
}

View File

@@ -0,0 +1,50 @@
<template>
<collapse-item name="属性" :expanded="true">
<setting-item-box name="样式">
<setting-item name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="optionData.color"></n-color-picker>
</setting-item>
<setting-item name="尺寸">
<n-input-number v-model:value="optionData.size" size="small" :min="0" placeholder="尺寸"></n-input-number>
</setting-item>
</setting-item-box>
<setting-item-box name="旋转">
<setting-item name="旋转">
<n-select v-model:value="optionData.rotate" size="small" :options="rotateMode"></n-select>
</setting-item>
</setting-item-box>
</collapse-item>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { option } from './config'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
const props = defineProps({
optionData: {
type: Object as PropType<typeof option>,
required: true
}
})
// 旋转方式
const rotateMode = [
{
value: 0,
label: '0°'
},
{
value: 1,
label: '90°'
},
{
value: 2,
label: '180°'
},
{
value: 3,
label: '270°'
}
]
</script>

View File

@@ -0,0 +1,14 @@
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
export const IconConfig: ConfigType = {
key: 'Icon',
chartKey: 'VIcon',
conKey: 'VCIcon',
title: '图标',
category: ChatCategoryEnum.DEFAULT,
categoryName: ChatCategoryEnumName.DEFAULT,
package: PackagesCategoryEnum.ICONS,
chartFrame: ChartFrameEnum.STATIC,
image: 'icon.png'
}

View File

@@ -0,0 +1,31 @@
<template>
<div class="go-icon-box">
<GoIconify :icon="((dataset || '') as string)" :color="color" :width="size" :rotate="rotate" />
</div>
</template>
<script setup lang="ts">
import { PropType, toRefs } from 'vue'
import { CreateComponentType } from '@/packages/index.d'
import { GoIconify } from '@/components/GoIconify'
const props = defineProps({
chartConfig: {
type: Object as PropType<CreateComponentType>,
required: true
}
})
const { w, h } = toRefs(props.chartConfig.attr)
const { dataset, color, size, rotate } = toRefs(props.chartConfig.option)
</script>
<style lang="scss" scoped>
@include go('icon-box') {
display: flex;
align-items: center;
justify-content: center;
width: v-bind('`${w}px`');
height: v-bind('`${h}px`');
}
</style>

View File

@@ -0,0 +1,45 @@
import { IconConfig } from '../Default/Icon/index'
import { PackagesCategoryEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../index.d'
const iconNames = [
'line-md:beer-alt-filled-loop',
'line-md:beer-alt-twotone-loop',
'line-md:cloud-braces-loop',
'line-md:cloud-download-loop',
'line-md:cloud-download-outline-loop',
'line-md:cloud-upload-loop',
'line-md:cloud-upload-outline-loop',
'line-md:coffee-half-empty-twotone-loop',
'line-md:coffee-loop',
'line-md:coffee-twotone-loop',
'line-md:downloading-loop',
'line-md:github-loop',
'line-md:light-dark-loop',
'line-md:loading-alt-loop',
'line-md:loading-loop',
'line-md:loading-twotone-loop',
'line-md:moon-alt-loop',
'line-md:moon-alt-to-sunny-outline-loop-transition',
'line-md:moon-filled-loop',
'line-md:moon-filled-to-sunny-filled-loop-transition',
'line-md:star-pulsating-filled-loop',
'line-md:star-pulsating-loop',
'line-md:star-pulsating-twotone-loop',
'line-md:upload-loop',
'line-md:upload-outline-loop',
'line-md:uploading-loop'
]
const iconList = iconNames.map(name => ({
...IconConfig,
category: ChatCategoryEnum.ML,
categoryName: ChatCategoryEnumName.ML,
package: PackagesCategoryEnum.ICONS,
image: name,
icon: name,
dataset: name,
title: name.replace('line-md:', ''),
redirectComponent: `${IconConfig.package}/${IconConfig.category}/${IconConfig.key}` // 跳转组件路径规则packageName/categoryName/componentKey
}))
export default iconList

View File

@@ -0,0 +1,53 @@
import { IconConfig } from '../Default/Icon/index'
import { PackagesCategoryEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../index.d'
const iconNames = [
'wi:cloud',
'wi:cloudy',
'wi:cloudy-gusts',
'wi:cloudy-windy',
'wi:day-cloudy',
'wi:day-cloudy-high',
'wi:day-hail',
'wi:day-haze',
'wi:day-light-wind',
'wi:day-lightning',
'wi:day-rain',
'wi:day-rain-mix',
'wi:day-rain-wind',
'wi:day-showers',
'wi:day-sleet',
'wi:day-sleet-storm',
'wi:day-snow',
'wi:day-snow-thunderstorm',
'wi:day-snow-wind',
'wi:day-sprinkle',
'wi:day-storm-showers',
'wi:day-sunny',
'wi:day-sunny-overcast',
'wi:hail',
'wi:horizon',
'wi:horizon-alt',
'wi:hot',
'wi:lightning',
'wi:night-alt-cloudy',
'wi:night-alt-cloudy-gusts',
'wi:night-alt-cloudy-high',
'wi:night-alt-hail',
'wi:night-alt-lightning',
'wi:umbrella'
]
const iconList = iconNames.map(name => ({
...IconConfig,
category: ChatCategoryEnum.WEATHER,
categoryName: ChatCategoryEnumName.WEATHER,
package: PackagesCategoryEnum.ICONS,
image: name,
icon: name,
dataset: name,
title: name.replace('wi:', ''),
redirectComponent: `${IconConfig.package}/${IconConfig.category}/${IconConfig.key}` // 跳转组件路径规则packageName/categoryName/componentKey
}))
export default iconList

View File

@@ -0,0 +1,13 @@
export enum ChatCategoryEnum {
ML = 'MaterialLine',
COMMON = 'Common',
WEATHER = 'Weather',
DEFAULT = 'Default' // 这个仅用来表示组件分类目录,不要在 index.ts 中导入
}
export enum ChatCategoryEnumName {
ML = '动画',
COMMON = '通用',
WEATHER = '天气',
DEFAULT = '默认'
}

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