Compare commits

..

208 Commits

Author SHA1 Message Date
奔跑的面条
f15e0cd15f build: 升级版本到2.1.3 2022-12-16 14:02:09 +08:00
奔跑的面条
aa17e93966 Merge branch 'master-fetch-dev' into master-fetch 2022-12-16 13:55:55 +08:00
奔跑的面条
feb9796449 feat: 全局接口保存之后调接口存储 2022-12-16 13:01:15 +08:00
奔跑的面条
e4b641a9c9 Merge branch 'dev' into master-fetch-dev 2022-12-16 12:56:28 +08:00
奔跑的面条
0cd31f48c1 style: 修改注释 2022-12-16 12:11:16 +08:00
奔跑的面条
e35e98c023 feat: 拉取图片路径处理的PR代码 2022-12-16 12:04:42 +08:00
奔跑的面条
352a1742cf !104 fix:图片hash会出现404问题
Merge pull request !104 from lastbee1204/master-fetch
2022-12-16 04:03:40 +00:00
奔跑的面条
11cd4d0da1 perf: 优化数字翻牌组件说明 2022-12-16 11:12:16 +08:00
奔跑的面条
8987dd1682 perf: 优化饼图展示 2022-12-16 11:01:02 +08:00
奔跑的面条
ff1384c825 !108 饼状图新增功能 显示标签,标签显示内容,引导线显示,饼状图圆角设置
Merge pull request !108 from 李少白/master-fetch
2022-12-16 10:44:32 +08:00
奔跑的面条
1af7ae865d !108 饼状图新增功能 显示标签,标签显示内容,引导线显示,饼状图圆角设置
Merge pull request !108 from 李少白/master-fetch
2022-12-16 02:44:00 +00:00
奔跑的面条
0e42f4ff35 fix: 解决预览时没有overflow-hidden 的问题 2022-12-16 10:31:04 +08:00
奔跑的面条
cfcc262fd6 fix: 禁用个别弹窗使用esc 2022-12-16 10:15:25 +08:00
奔跑的面条
36ca877d49 style: 优化代码格式 2022-12-16 09:19:56 +08:00
奔跑的面条
3bad7ec758 !107 修复过滤器编辑器未更新问题
Merge pull request !107 from Furoe/dev
2022-12-16 01:18:57 +00:00
奔跑的面条
e1e26cafcf fix: 新增编辑接口同步修改所有组件功能 2022-12-15 21:04:00 +08:00
奔跑的面条
99cd66c835 feat: 新增全局请求定时功能 2022-12-15 20:53:28 +08:00
奔跑的面条
e4aac1597f feat: 处理全局接口编辑请求 2022-12-15 20:22:05 +08:00
奔跑的面条
2dc7bc3b61 perf: 优化全局接口功能 2022-12-15 19:49:58 +08:00
奔跑的面条
07b7eec457 perf: 优化全局接口功能 2022-12-15 19:48:16 +08:00
奔跑的面条
eaab8d1d49 feat: 新增数据池配置页面 2022-12-15 19:37:43 +08:00
slxb
7bc6ff7619 饼状图新增功能 显示标签,标签显示内容,引导线显示,饼状图圆角设置 2022-12-13 19:07:47 +08:00
yangwq7
9903e73a69 fix: 修复过滤器编辑器未更新问题 2022-12-12 11:33:43 +08:00
奔跑的面条
7f1c001c99 fix: 解决颜色列表卡顿的问题 2022-12-10 17:04:24 +08:00
刘彪
67f6dcd1fe fix:图片hash会出现404问题 2022-11-29 11:56:37 +08:00
刘彪
de60c7cde5 fix:图片hash会出现404问题 2022-11-29 11:47:54 +08:00
奔跑的面条
889e5075ba style: 去除全局多余代码 2022-11-28 11:02:52 +08:00
奔跑的面条
2bba1dcae0 style: 修改代码格式,修改错误单词 2022-11-28 10:54:54 +08:00
奔跑的面条
9d81159141 !103 优化Axios相关类型推断和语法
Merge pull request !103 from 石头web/master-fetch-dev
2022-11-28 01:46:22 +00:00
a876691666
f8ebaa60b1 feat: 接口增加泛型支持 2022-11-27 12:16:32 +08:00
a876691666
02ec3c78d6 feat: 更新Type类型 2022-11-27 11:40:00 +08:00
奔跑的面条
21ba5c02b0 perf: 优化缩放动画 2022-11-24 11:48:13 +08:00
奔跑的面条
500795b7e5 feat: 新增数据池代码 2022-11-22 21:25:52 +08:00
奔跑的面条
8230757bd1 !102 fix:修复状态变更时(如切换语言等),useSync.hook.ts 中 dataSyncFetch 反复执行导致 chartEditStore.componentList 重复
Merge pull request !102 from fankeke007/N/A
2022-11-22 11:18:28 +00:00
奔跑的面条
c1de1f9db6 Merge remote-tracking branch 'origin/master-fetch-dev' into master-fetch 2022-11-22 12:44:37 +08:00
奔跑的面条
1b0591ee62 Merge remote-tracking branch 'origin/dev' into master-fetch-dev 2022-11-22 12:43:27 +08:00
奔跑的面条
3ee5faa248 Merge branch 'master-fetch-dev' into master-fetch 2022-11-21 10:50:33 +08:00
奔跑的面条
ab9b79e8a8 Merge branch 'dev' into master-fetch-dev 2022-11-21 10:50:10 +08:00
奔跑的面条
b6a78c64ed build: 升级版本到 2.1.2 2022-11-19 21:05:32 +08:00
奔跑的面条
9855d28e33 Merge branch 'master-fetch-dev' into master-fetch 2022-11-19 21:05:15 +08:00
奔跑的面条
16fb258908 Merge branch 'dev' into master-fetch-dev 2022-11-19 20:37:29 +08:00
奔跑的面条
52ed72e502 Merge branch 'dev' into master-fetch-dev 2022-11-19 20:27:10 +08:00
奔跑的面条
6f9993e9e8 perf: 解决登录按钮 loading 不会关闭的问题 2022-11-19 20:23:20 +08:00
奔跑的面条
3347e3b12a !94 使右上方正确显示登录账号名
Merge pull request !94 from 吴医生/master0fetch-dev-my
2022-11-19 09:47:01 +00:00
奔跑的面条
b4a5ff7935 fix: 预览页接口错误不处理,默认正确 2022-11-19 15:07:54 +08:00
fankeke007
e75e2ccfe6 fix:修复状态变更时(如切换语言等),useSync.hook.ts 中 dataSyncFetch 反复执行导致 chartEditStore.componentList 重复
Signed-off-by: fankeke007 <610047449@qq.com>
2022-11-18 08:03:35 +00:00
奔跑的面条
3d568f08de !95 feat: JSON编辑优化以及兼容后端接口保存
Merge pull request !95 from 潘潘/master-fetch-dev
2022-11-15 13:39:49 +00:00
潘潘
5cc20e9b19 perf: 编辑JSON兼容后端优化 2022-11-15 16:26:52 +08:00
潘潘
dec1130ace perf: 编辑JSON优化 2022-11-15 16:21:35 +08:00
潘潘
e3a294eb00 perf: 注释定时同步 2022-11-14 21:07:12 +08:00
吴医生
104551b600 fix: 使正确显示右上方登录账号名
Signed-off-by: 吴医生 <draculakkk@hotmail.com>
2022-11-14 09:26:21 +00:00
奔跑的面条
5c6bf57de1 docs: 优化说明文档 2022-11-14 10:00:30 +08:00
奔跑的面条
b0cb3addbd Merge branch 'dev' into master-fetch-dev 2022-11-13 21:45:16 +08:00
奔跑的面条
77ff4cdffd Merge branch 'dev' into master-fetch-dev 2022-11-13 02:39:13 +08:00
奔跑的面条
dde92bfe60 Merge branch 'dev' into master-fetch-dev 2022-11-12 17:42:39 +08:00
奔跑的面条
a8bcc93aed fix: 修改500展示文案 2022-11-05 21:45:48 +08:00
奔跑的面条
b6903a777a Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch-dev 2022-11-05 21:34:39 +08:00
奔跑的面条
f7cbc75e22 fix: 修改地址 2022-11-02 21:33:20 +08:00
奔跑的面条
0e1ae71b78 fix: 修改类型错误的问题 2022-11-02 19:30:47 +08:00
奔跑的面条
7fcfb953bd build: 修改版本到2.1.1 2022-11-02 19:07:18 +08:00
奔跑的面条
a76ad93600 Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch-dev 2022-11-02 19:06:49 +08:00
奔跑的面条
f9ed391c81 chore: 修改上传地址的接口和图片的展示地址拼接 2022-11-01 21:17:24 +08:00
奔跑的面条
8ab64846d4 fix: 处理更换背景图内容不会更新的问题 2022-10-31 10:40:58 +08:00
奔跑的面条
a82cc840b5 fix: 修改发布API错误调用 2022-10-26 10:51:10 +08:00
奔跑的面条
2171843c61 build: 修改版本号为2.1.0 2022-10-15 17:28:23 +08:00
奔跑的面条
934bac7201 fix: 修改版本号到2.0.10 2022-10-15 17:22:06 +08:00
奔跑的面条
ed2a46a3ef Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch-dev 2022-10-15 17:20:05 +08:00
奔跑的面条
766a3a8ede fix: 修复导入组件数据会错乱的问题 2022-10-09 16:39:10 +08:00
奔跑的面条
f3ec85050e Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch-dev 2022-10-09 09:29:40 +08:00
奔跑的面条
ba54d934a2 build: 修改正确版本到 2.0.8 2022-10-08 21:27:21 +08:00
奔跑的面条
d6ecad6467 build: 升级版本到 2.0.9 2022-10-08 21:09:47 +08:00
奔跑的面条
74cab1e9af Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch-dev 2022-10-08 21:06:06 +08:00
奔跑的面条
a823851541 feat: 合并1.1.1 2022-10-08 21:04:41 +08:00
奔跑的面条
618d1d77cb feat: 合并1.1.1,升级版本到2.0.8 2022-09-27 20:28:47 +08:00
奔跑的面条
17c48608ec style: 去除无用代码,设置默认值 2022-09-27 19:53:55 +08:00
奔跑的面条
6d5dfbced0 perf: 优化用户体验,完成接口配置后调用保存接口 2022-09-27 10:33:30 +08:00
奔跑的面条
c773bd8010 Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch-dev 2022-09-22 14:15:18 +08:00
奔跑的面条
5746da73dd Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch-dev 2022-09-21 19:56:56 +08:00
奔跑的面条
60bbfd9c92 Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch-dev 2022-09-19 20:46:53 +08:00
奔跑的面条
12d92f3aa4 Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch-dev 2022-09-19 20:14:40 +08:00
奔跑的面条
2edb1caf18 perf: 优化滤镜模糊问题,默认不开启 2022-09-19 17:51:12 +08:00
奔跑的面条
75067221da fix: 修改请求接口 token 名称 2022-09-18 17:45:59 +08:00
奔跑的面条
3358e164a1 build: 升级版本到2.0.7 2022-09-18 17:23:16 +08:00
奔跑的面条
94cde3f517 !47 修复在编辑项目之前加载数据异常,自动保存导致项目数据清空问题。
Merge pull request !47 from 秋名山路霸/master-fetch
2022-09-18 07:53:47 +00:00
秋名山路霸
a2c8827a35 fix: 修复在编辑项目之前加载数据异常,自动保存导致项目数据清空问题。 2022-09-18 11:56:26 +08:00
奔跑的面条
172a3163aa build: 升级依赖,锁定TS 版本 2022-09-12 01:20:27 +08:00
奔跑的面条
4d189e954c feat: 升级版本到 2.0.6 2022-09-12 00:49:22 +08:00
奔跑的面条
8a1f3ac2ef fix: 合并1.0.9 2022-09-12 00:31:52 +08:00
奔跑的面条
68dbf3e9ef feat: 新增移动撤回 2022-08-30 19:14:52 +08:00
奔跑的面条
0aece46d91 build: 升级版本到 2.0.5 2022-08-30 15:04:29 +08:00
奔跑的面条
094c7ed392 perf: 完善首页预览功能 2022-08-30 15:03:25 +08:00
奔跑的面条
c48517a89b Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch 2022-08-30 12:19:57 +08:00
奔跑的面条
68c68e96b1 fix: 尝试解决背景图片无法截图的问题 2022-08-29 21:35:51 +08:00
奔跑的面条
36b1f37f3f update LICENSE.
Signed-off-by: 奔跑的面条 <1262327911@qq.com>
2022-08-29 10:13:37 +00:00
奔跑的面条
51e5c756a7 perf: 优化参考线的展示方式 2022-08-21 14:52:30 +08:00
奔跑的面条
8df951992e Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch 2022-08-21 14:49:32 +08:00
奔跑的面条
1a00993ee8 Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch 2022-08-19 14:46:49 +08:00
奔跑的面条
cb7e887c36 fix: 补充代码合并丢失的枚举 2022-08-19 11:43:23 +08:00
奔跑的面条
255b14a597 perf: 优化500错误页重定向 2022-08-19 11:34:38 +08:00
奔跑的面条
3f462c1bee feat: 合并多选功能,解决冲突,升级版本到2.0.4 2022-08-19 10:44:44 +08:00
奔跑的面条
cacc99683d Merge branch 'dev' into master-fetch 2022-08-05 08:42:22 +08:00
奔跑的面条
d3a9f7d60f Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch 2022-07-26 16:12:31 +08:00
奔跑的面条
8d4dd3160d Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch 2022-07-21 11:46:54 +08:00
奔跑的面条
6847f7d966 feat: 合并 1.0.6 版本代码 2022-07-21 11:03:04 +08:00
奔跑的面条
35204898fc Merge branch 'dev' into master-fetch 2022-07-08 18:12:33 +08:00
奔跑的面条
7fe743d624 fix: 合并编辑功能的修改 2022-07-07 19:54:53 +08:00
奔跑的面条
6a285f610c Merge branch 'dev' into master-fetch 2022-07-07 13:14:53 +08:00
奔跑的面条
a4c0450f7a fix: 补充合并代码丢失的icon图标 2022-07-06 22:12:24 +08:00
奔跑的面条
a81f016e3f build: 合并dev 1.0.5 版本, 修改fetch分支为2.0.2 2022-07-06 21:58:28 +08:00
奔跑的面条
ee5fed4cd0 Merge branch 'dev' into master-fetch 2022-06-27 21:42:24 +08:00
奔跑的面条
3fb0fe43bb Merge branch 'dev' into master-fetch 2022-06-27 21:38:27 +08:00
奔跑的面条
f1f5f9cca9 fix: 修改合并冲突错误的代码 2022-06-27 20:42:17 +08:00
奔跑的面条
2ce17c3974 perf: 合并dev分支,解决组件无法更新数据的问题 2022-06-27 20:37:26 +08:00
奔跑的面条
1d7e40950f style: 去除多余代码 2022-06-24 11:44:26 +08:00
奔跑的面条
91bda457e7 docs: 修改文档 2022-06-23 09:53:01 +08:00
奔跑的面条
68aeea70cf feat: 新增保存按钮 2022-06-22 18:50:15 +08:00
奔跑的面条
7a19346700 build: 升级依赖 2022-06-20 15:13:50 +08:00
奔跑的面条
8d2269df78 build: 合并dev分支 2022-06-20 15:11:13 +08:00
奔跑的面条
b133cbdfea feat: 新增排名列表字体大小控制功能 2022-06-17 14:13:14 +08:00
奔跑的面条
f45d4ca5af build: 修改版本到 2.0.1 2022-06-16 10:48:42 +08:00
奔跑的面条
d96e7f71d7 fix: 解决打包之后无法加载页面的问题 2022-06-15 17:54:49 +08:00
奔跑的面条
24fee76237 feat: 新增 preview 模式,修改打包后路径指向 2022-06-15 17:48:16 +08:00
奔跑的面条
d59193bc33 feat: 新增commitlint 2022-06-15 17:18:39 +08:00
奔跑的面条
6928a70d9f docs: 更新文档 2022-06-15 17:15:29 +08:00
奔跑的面条
e0796280f5 doc: 文档更新 2022-06-15 17:14:27 +08:00
奔跑的面条
5d803e3fa6 feat: 新增渐变文本组件 2022-06-15 16:20:25 +08:00
奔跑的面条
749c0a2f39 build:升级依赖 2022-06-15 16:11:58 +08:00
奔跑的面条
737504cef5 fix: 解决npm,yarn 安装依赖报错的问题 2022-06-15 16:08:59 +08:00
奔跑的面条
8115950893 fix: 补充丢失的图片 2022-06-14 12:46:07 +08:00
奔跑的面条
f458a21a2f feat:新增数字滚动组件动态获取数据功能 2022-06-14 12:31:46 +08:00
奔跑的面条
13a9675894 feat: 新增表格滚动组件 2022-06-14 12:31:20 +08:00
奔跑的面条
77b5a41af9 fix:解决边框04展示不全的bug 2022-06-14 12:30:29 +08:00
奔跑的面条
2bf895ad3d feat:新增水球图设置项 2022-06-13 17:29:39 +08:00
奔跑的面条
6a5abd6762 fix: 修改列表页展示问题 2022-06-13 14:28:58 +08:00
奔跑的面条
5cb458c45b feat: 新增环形图,新增NaiveUI-进度组件 2022-06-13 13:18:30 +08:00
奔跑的面条
f828c48ab6 feat: 新增进度条组件 2022-06-12 18:47:47 +08:00
奔跑的面条
2626bc794f fix: 解决缩放比例展示不全的问题 2022-06-12 18:45:31 +08:00
奔跑的面条
734dd68607 chore: 优化拖拽锚点 2022-06-11 15:15:38 +08:00
奔跑的面条
19f53f705c fix:修改请求地址为null时引起的异常bug 2022-06-11 14:37:22 +08:00
奔跑的面条
b93caf1386 chore: 优化发布弹窗 2022-06-11 14:23:16 +08:00
奔跑的面条
aa613e2805 build: 依赖基本升级 2022-06-11 14:15:28 +08:00
奔跑的面条
616584fc19 fix: 修改双折线图X轴无法变更的问题 2022-06-11 14:13:32 +08:00
奔跑的面条
a5e83bfe9f fix: 解决项目列表信息栏会换行的问题 2022-06-09 08:49:07 +08:00
奔跑的面条
1252d266dd fix:解决截图有白边的问题 2022-06-09 08:48:28 +08:00
奔跑的面条
3c820d53a6 fix: 修改复制失败的提示类型错误的问题 2022-06-06 10:43:14 +08:00
奔跑的面条
f0525c7522 chore: 新增路由白名单 2022-06-06 10:42:55 +08:00
奔跑的面条
600f1b2dd2 chore:优化搜索结果列表UI 2022-06-05 11:41:57 +08:00
奔跑的面条
757b79514a chore:优化 dialog 的全局封装代码 2022-06-04 16:25:37 +08:00
奔跑的面条
cf8121eb00 build:修改 fetch 版本号 2022-06-04 15:44:26 +08:00
奔跑的面条
faf2d44fbb chore: 优化页面 UI 2022-06-03 20:21:35 +08:00
奔跑的面条
88516d9491 fix: 修改自动复制粘贴的问题 2022-06-03 18:53:37 +08:00
奔跑的面条
88dbbe03ea fix: 新增发布页面处理 2022-06-03 14:48:58 +08:00
奔跑的面条
ae1fd2e7cf chore: 优化了标题展示和大小样式 2022-06-03 11:19:29 +08:00
奔跑的面条
d3931f47bc type: 修改类型错误 2022-06-01 23:00:28 +08:00
奔跑的面条
bf9bd59b63 fix:处理列表页标题过长的展示问题 2022-06-01 22:58:22 +08:00
奔跑的面条
fb0ff50837 type: 定义全局返回值类型 2022-06-01 22:41:11 +08:00
奔跑的面条
93727a0ac7 build: 修改版本号 0.0.9 2022-06-01 22:28:46 +08:00
奔跑的面条
2641e70c78 chore:优化了路由写法,修改了错误页面的展示,新增未发布提示页面 2022-06-01 22:20:05 +08:00
奔跑的面条
bc44584698 feat: 新增动态预览功能 2022-06-01 22:19:03 +08:00
奔跑的面条
82394dd7a3 fix: 修改组件注册会报错的问题 2022-06-01 22:14:33 +08:00
奔跑的面条
2e688ad686 build:升级依赖包 2022-06-01 22:13:49 +08:00
奔跑的面条
9b998e0c6d fix: 解决列表图片展示缓存问题 2022-06-01 20:16:38 +08:00
奔跑的面条
1045588301 fix: 解决获取数据,但是配置模块不完整的问题 2022-06-01 19:01:05 +08:00
奔跑的面条
ba86399fd3 build: 修改请求地址 2022-05-31 11:19:17 +08:00
奔跑的面条
a89164f885 fix: 修改oss接口不会动态更改的问题 2022-05-31 11:18:34 +08:00
奔跑的面条
7f2344c82c chore:修改请求地址 2022-05-29 16:04:07 +08:00
奔跑的面条
3c8e430533 docs: 修改文档说明 2022-05-29 15:23:04 +08:00
奔跑的面条
f7209fba53 feat: 新增背景图文件上传保存 2022-05-29 14:54:35 +08:00
奔跑的面条
9fae683d8b chore: 去除生成预览图时的标尺 2022-05-28 17:58:07 +08:00
奔跑的面条
79a2b98a1a feat: 新增首页预览图展示 2022-05-28 16:39:27 +08:00
奔跑的面条
98b28a631a Merge branch 'dev' into master-fetch 2022-05-28 15:58:06 +08:00
奔跑的面条
6fec64f515 fix: 修改自动保存预览图无法存储的问题 2022-05-28 15:46:07 +08:00
奔跑的面条
01d5890b35 branch: 合并锚点样式修改 2022-05-28 12:46:32 +08:00
奔跑的面条
fea583eb5b feat: 保存预览图 2022-05-28 11:50:17 +08:00
奔跑的面条
bfe5039a1c fix: 解决打包后无法发送请求的bug 2022-05-28 00:32:32 +08:00
奔跑的面条
7a57d944c8 feat: 新增上传文件接口 2022-05-27 20:09:48 +08:00
奔跑的面条
ca27e87241 chore: 修改项目信息结构 2022-05-27 11:49:25 +08:00
奔跑的面条
e674a1ece4 feat: 新增项目信息修改功能 2022-05-26 01:01:59 +08:00
奔跑的面条
dfb63346d3 fix: 修改导入组件id会重复的问题 2022-05-25 23:00:36 +08:00
奔跑的面条
4d899d48dc feat: 新增快捷键展示 2022-05-24 18:17:41 +08:00
奔跑的面条
fa3a3dfcb0 faet: 新增保存快捷键 2022-05-24 18:16:33 +08:00
奔跑的面条
e36210aa27 feat: 新增自动同步功能 2022-05-24 17:42:49 +08:00
奔跑的面条
20a599594c feat: 新增数据保存接口 2022-05-24 15:05:51 +08:00
奔跑的面条
70f8dbae53 Merge branch 'dev' into master-fetch 2022-05-24 12:28:14 +08:00
奔跑的面条
d8022b2682 feat: 新增获取项目数据功能,新增同步数据功能 2022-05-23 23:50:35 +08:00
奔跑的面条
0d7c5b8ace Merge branch 'dev' into master-fetch 2022-05-23 16:06:13 +08:00
奔跑的面条
88c9850c44 Merge branch 'dev' into master-fetch 2022-05-22 23:27:39 +08:00
奔跑的面条
f1ed62cdca feat: 新增获取项目数据接口 2022-05-22 22:11:56 +08:00
奔跑的面条
bfac86d5dd feat:新增发布和取消发布接口 2022-05-22 16:38:22 +08:00
奔跑的面条
341015c584 style: 调整代码格式,去除多余代码 2022-05-22 15:39:30 +08:00
奔跑的面条
7c5a66978e feat: 新增删除接口 2022-05-22 15:25:07 +08:00
奔跑的面条
b21fc3f5e7 feat: 新增首页列表接口 2022-05-22 15:06:45 +08:00
奔跑的面条
0e52628842 Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch 2022-05-22 14:09:38 +08:00
奔跑的面条
f7922cafa5 feat: 新增项目列表接口 2022-05-22 14:05:57 +08:00
奔跑的面条
8c5496829e Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch 2022-05-22 13:36:30 +08:00
奔跑的面条
8514f051a7 fix: 修改新建项目id错误问题 2022-05-21 21:04:10 +08:00
奔跑的面条
61feb29fe2 fix: 修改i18n错误提示 2022-05-21 19:46:44 +08:00
奔跑的面条
fa29881f04 chore: 修改提示内容 2022-05-21 18:04:52 +08:00
奔跑的面条
46cb8e7d0b feat: 新增创建接口,修改i8n部分内容 2022-05-21 18:03:15 +08:00
奔跑的面条
b6143bc75e feat: 新增退出登录接口,新增全局接口封装,修改登录接口内容 2022-05-21 17:31:01 +08:00
奔跑的面条
92e1ec05d2 Merge branch 'master' of https://gitee.com/MTrun/go-view into master-fetch 2022-05-21 14:01:53 +08:00
奔跑的面条
75f23bb1bf Merge branch 'dev' into master-fetch 2022-05-21 13:44:25 +08:00
奔跑的面条
5f5731f813 feat: 新增登录接口请求 2022-05-20 16:12:27 +08:00
奔跑的面条
55159be0dc fix: 修改plop的问题 2022-05-20 16:12:09 +08:00
奔跑的面条
0c4e1dc7ae Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch 2022-05-20 10:25:46 +08:00
奔跑的面条
b4abdeb246 update README.md. 2022-05-19 01:56:30 +00:00
奔跑的面条
7e61dda4aa update README.md. 2022-05-16 10:38:39 +00:00
奔跑的面条
283aafb27d update README.md. 2022-05-16 04:23:10 +00:00
132 changed files with 3163 additions and 6150 deletions

12
.env
View File

@@ -1,14 +1,8 @@
# port
VITE_DEV_PORT = '8001'
VITE_DEV_PORT = '8080'
# development path
VITE_DEV_PATH = '/'
VITE_DEV_PATH = 'https://demo.mtruning.club'
# production path
VITE_PRO_PATH = '/'
# spa-title
VITE_GLOB_APP_TITLE = GoView
# spa shortname
VITE_GLOB_APP_SHORT_NAME = GoView
VITE_PRO_PATH = 'https://demo.mtruning.club'

View File

@@ -1,51 +0,0 @@
version: '1.0'
name: branch-pipeline
displayName: BranchPipeline
stages:
- stage:
name: compile
displayName: 编译
steps:
- step: build@nodejs
name: build_nodejs
displayName: Nodejs 构建
# 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
nodeVersion: 14.16.0
# 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
commands:
- npm install && rm -rf ./dist && npm run build
# 非必填字段开启后表示将构建产物暂存但不会上传到制品库中7天后自动清除
artifacts:
# 构建产物名字作为产物的唯一标识可向下传递支持自定义默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
- name: BUILD_ARTIFACT
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
path:
- ./dist
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
# 上游构建任务定义的产物名默认BUILD_ARTIFACT
dependArtifact: BUILD_ARTIFACT
# 上传到制品库时的制品命名默认output
artifactName: output
dependsOn: build_nodejs
- stage:
name: release
displayName: 发布
steps:
- step: publish@release_artifacts
name: publish_release_artifacts
displayName: '发布'
# 上游上传制品任务的产出
dependArtifact: output
# 发布制品版本号
version: '1.0.0.0'
# 是否开启版本号自增,默认开启
autoIncrement: true
triggers:
push:
branches:
exclude:
- master
include:
- .*

View File

@@ -1,49 +0,0 @@
version: '1.0'
name: master-pipeline
displayName: MasterPipeline
stages:
- stage:
name: compile
displayName: 编译
steps:
- step: build@nodejs
name: build_nodejs
displayName: Nodejs 构建
# 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
nodeVersion: 14.16.0
# 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
commands:
- npm install && rm -rf ./dist && npm run build
# 非必填字段开启后表示将构建产物暂存但不会上传到制品库中7天后自动清除
artifacts:
# 构建产物名字作为产物的唯一标识可向下传递支持自定义默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
- name: BUILD_ARTIFACT
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
path:
- ./dist
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
# 上游构建任务定义的产物名默认BUILD_ARTIFACT
dependArtifact: BUILD_ARTIFACT
# 上传到制品库时的制品命名默认output
artifactName: output
dependsOn: build_nodejs
- stage:
name: release
displayName: 发布
steps:
- step: publish@release_artifacts
name: publish_release_artifacts
displayName: '发布'
# 上游上传制品任务的产出
dependArtifact: output
# 发布制品版本号
version: '1.0.0.0'
# 是否开启版本号自增,默认开启
autoIncrement: true
triggers:
push:
branches:
include:
- master

View File

@@ -1,36 +0,0 @@
version: '1.0'
name: pr-pipeline
displayName: PRPipeline
stages:
- stage:
name: compile
displayName: 编译
steps:
- step: build@nodejs
name: build_nodejs
displayName: Nodejs 构建
# 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
nodeVersion: 14.16.0
# 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
commands:
- npm install && rm -rf ./dist && npm run build
# 非必填字段开启后表示将构建产物暂存但不会上传到制品库中7天后自动清除
artifacts:
# 构建产物名字作为产物的唯一标识可向下传递支持自定义默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
- name: BUILD_ARTIFACT
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
path:
- ./dist
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
# 上游构建任务定义的产物名默认BUILD_ARTIFACT
dependArtifact: BUILD_ARTIFACT
# 上传到制品库时的制品命名默认output
artifactName: output
dependsOn: build_nodejs
triggers:
pr:
branches:
include:
- master

221
README.md
View File

@@ -1,165 +1,114 @@
## 总览
<p align="center">
<img src="readme/logo-t-y.png" alt="go-view" />
</p>
**`master-fetch` 分支是带有后端接口请求的分支**
<h4 align="center">开源、精美、便捷的「数据可视化」低代码开发平台</h4>
**后端项目地址:[https://gitee.com/MTrun/go-view-serve](https://gitee.com/MTrun/go-view-serve)**
#### 😶 **纯前端** 分支: **`master`**
**接口说明地址:[https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb](https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb)**
#### 👻 携带 **后端** 请求分支: **`master-fetch`**
## 使用
#### 📚 GoView **文档** 地址:[https://www.mtruning.club/](https://www.mtruning.club/)
所有的接口地址位置:`src\api\path\*`
项目纯前端-Demo 地址:[https://vue.mtruning.club/](https://vue.mtruning.club/)
项目带后端-Demo 地址:[https://demo.mtruning.club/](https://demo.mtruning.club/)
文档-源码地址:[https://gitee.com/MTrun/go-view-doc](https://gitee.com/MTrun/go-view-doc)
#### 🤯 后端项目看这里!
后端项目 gitee 地址:[https://gitee.com/MTrun/go-view-serve](https://gitee.com/MTrun/go-view-serve)
接口说明地址:[https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb](https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb)
其它后端方案地址:
- 【.NET】[https://gitee.com/sun_xiang_yu/go-view-dotnet](https://gitee.com/sun_xiang_yu/go-view-dotnet)
#### 整体介绍
- 框架:基于 `Vue3` 框架编写,使用 `hooks` 写法抽离部分逻辑,使代码结构更加清晰;
- 类型:使用 `TypeScript` 进行类型约束,减少未知错误发生概率,可以大胆修改逻辑内容;
- 性能:多处性能优化,使用页面懒加载、组件动态注册、数据滚动加载等方式,提升页面渲染速度;
- 存储:拥有本地记忆,部分配置项采用 `storage` 存储本地,提升使用体验;
- 封装:项目进行了详细的工具类封装如:路由、存储、加/解密、文件处理、主题、NaiveUI 全局方法、组件等
说明文档:
![说明文档](readme/go-view-doc.png)
工作台:
![工作台](readme/go-view-canvas.png)
请求配置:
![请求配置](readme/go-view-fetch.png)
数据过滤:
![数据过滤](readme/go-view-filter.png)
高级事件编辑:
![高级事件编辑](readme/go-view-event.png)
快捷主页:
![快捷主页](readme/go-view-indexpage.png)
主题色:
![主题色](readme/go-view-color.png)
亮白主题:
![亮白主题](readme/go-view-theme.png)
主要技术栈为:
| 名称 | 版本 | 名称 | 版本 |
| ------------------- | ----- | ----------- | ------ |
| Vue | 3.2.x | TypeScript4 | 4.6.x |
| Vite | 2.9.x | NaiveUI | 2.27.x |
| ECharts | 5.3.x | Pinia | 2.0.x |
| 详见 `package.json` | 😁 | 🥰 | 🤗 |
开发环境:
| 名称 | 版本 | 名称 | 版本 |
| ---- | ------- | ------- | ----- |
| node | 16.14.x | npm | 8.5.x |
| pnpm | 7.1.x | windows | 11 |
已完成图表:
| 分类 | 名称 | 名称 | 名称 | 名称 |
| ------ | ---------------- | ---------- | -------------- | ------------------------ |
| 图表 | 柱状图 | 横向柱状图 | 折线图 | 单/多 折线面积图(渐变色) |
| \* | 饼图 | 环形图 | 水球图 | 雷达图 |
| \* | NaiveUI 多种进度 | 散点图 | 对数回归散点图 | 热力图 |
| \* | 漏斗图 | 中国地图 | 高德地图 | 🦊 |
| 信息 | 文字 | 渐变文字 | 词云 | 嵌套网页 |
| \* | 图片 | 视频 | 😺 | 🐯 |
| 列表 | 滚动排名列表 | 滚动表格 | 🐮 | 🐐 |
| 小组件 | 边框-01~13 | 装饰-01~05 | 数字翻牌 | 通用时间 |
| \* | 数字计数 | 倒计时 | 时钟 | 🦁 |
## 浏览器支持
开发和测试平台均在 `Google` 和最新版 `EDGE` 上完成,暂未测试 `IE11` 等其它浏览器,如有需求请自行测试与兼容。
## 安装
本项目采用` pnpm` 进行包管理
接口地址修改:`.env`
```shell
#建议使用 nrm 切换到淘宝源 https://registry.npmmirror.com/
#pnpm
pnpm install
# port
VITE_DEV_PORT = '8080'
#yarn
yarn install
# development path
VITE_DEV_PATH = 'http://127.0.0.1:8080'
#npm
npm install
# production path
VITE_PRO_PATH = 'http://127.0.0.1:8080'
```
## 启动
公共前缀修改:`src\settings\httpSetting.ts`
```shell
#pnpm
pnpm dev
# npm
npm run dev
#yarn
yarn dev
#Makefile
make dev
// 请求前缀
export const axiosPre = '/api/goview'
```
## 编译
接口封装:`src\api\http.ts`
```shell
#pnpm
pnpm run build
```ts
import axiosInstance from './axios'
import { RequestHttpEnum, ContentTypeEnum } from '@/enums/httpEnum'
# npm
npm run build
export const get = (url: string, params?: object) => {
return axiosInstance({
url: url,
method: RequestHttpEnum.GET,
params: params,
})
}
#yarn
yarn run build
export const post = (url: string, data?: object, headersType?: string) => {
return axiosInstance({
url: url,
method: RequestHttpEnum.POST,
data: data,
headers: {
'Content-Type': headersType || ContentTypeEnum.JSON
}
})
}
#Makefile
make dist
export const put = (url: string, data?: object, headersType?: string) => {
return axiosInstance({
url: url,
method: RequestHttpEnum.PUT,
data: data,
headers: {
'Content-Type': headersType || ContentTypeEnum.JSON
}
})
}
export const del = (url: string, params?: object) => {
return axiosInstance({
url: url,
method: RequestHttpEnum.DELETE,
params
})
}
// 获取请求函数默认get
export const http = (type?: RequestHttpEnum) => {
switch (type) {
case RequestHttpEnum.GET:
return get
case RequestHttpEnum.POST:
return post
case RequestHttpEnum.PUT:
return put
case RequestHttpEnum.DELETE:
return del
default:
return get
}
}
```
## 代码提交
- feat: 新功能
- fix: 修复 Bug
- docs: 文档修改
- perf: 性能优化
- revert: 版本回退
- ci: CICD 集成相关
- test: 添加测试代码
- refactor: 代码重构
- build: 影响项目构建或依赖修改
- style: 不影响程序逻辑的代码修改
- chore: 不属于以上类型的其他类型(日常事务)
* feat: 新功能
* fix: 修复 Bug
* docs: 文档修改
* perf: 性能优化
* revert: 版本回退
* ci: CICD集成相关
* test: 添加测试代码
* refactor: 代码重构
* build: 影响项目构建或依赖修改
* style: 不影响程序逻辑的代码修改
* chore: 不属于以上类型的其他类型(日常事务)
## 交流

View File

@@ -1,3 +1,4 @@
import path from 'path'
export const OUTPUT_DIR = 'dist'
// monaco-editor 路径
@@ -6,7 +7,7 @@ export const prefix = `monaco-editor/esm/vs`
// chunk 警告大小
export const chunkSizeWarningLimit = 2000
// 禁用 brotli 压缩大小报告
// 禁用 brotliSize 压缩大小报告
export const brotliSize = false
// 分包
@@ -14,7 +15,12 @@ export const rollupOptions = {
output: {
chunkFileNames: 'static/js/[name]-[hash].js',
entryFileNames: 'static/js/[name]-[hash].js',
assetFileNames: 'static/[ext]/[name]-[hash].[ext]',
assetFileNames: (chunkInfo) => {
if(['.png', '.jpg', '.jpeg'].includes(path.extname(chunkInfo.name))) {
return `static/[ext]/[name].[ext]`
}
return `static/[ext]/[name]-[hash].[ext]`
},
manualChunks: {
jsonWorker: [`${prefix}/language/json/json.worker`],
cssWorker: [`${prefix}/language/css/css.worker`],

View File

@@ -1,9 +0,0 @@
/**
* Get the configuration file variable name
* @param env
*/
export const getConfigFileName = (env: Record<string, any>) => {
return `__PRODUCTION__${env.VITE_GLOB_APP_SHORT_NAME || '__APP'}__CONF__`
.toUpperCase()
.replace(/\s/g, '');
};

View File

@@ -1,6 +1,6 @@
{
"name": "go-view",
"version": "1.1.5",
"version": "2.1.3",
"scripts": {
"dev": "vite --host",
"build": "vue-tsc --noEmit && vite build",
@@ -35,7 +35,7 @@
"three": "^0.145.0",
"vue": "^3.2.31",
"vue-demi": "^0.13.1",
"vue-i18n": "9.1.9",
"vue-i18n": "9.1.10",
"vue-router": "4.0.12",
"vue3-lazyload": "^0.2.5-beta",
"vue3-sketch-ruler": "^1.3.3",

78
pnpm-lock.yaml generated
View File

@@ -59,7 +59,7 @@ specifiers:
vue: ^3.2.31
vue-demi: ^0.13.1
vue-echarts: ^6.0.2
vue-i18n: 9.1.9
vue-i18n: 9.1.10
vue-router: 4.0.12
vue-tsc: ^0.28.10
vue3-lazyload: ^0.2.5-beta
@@ -91,7 +91,7 @@ dependencies:
three: 0.145.0
vue: 3.2.37
vue-demi: 0.13.1_vue@3.2.37
vue-i18n: 9.1.9_vue@3.2.37
vue-i18n: 9.1.10_vue@3.2.37
vue-router: 4.0.12_vue@3.2.37
vue3-lazyload: 0.2.5-beta_2yymnzrok6eda47acnj2yjm3ae
vue3-sketch-ruler: 1.3.4_vue@3.2.37
@@ -671,60 +671,60 @@ packages:
resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==}
dev: true
/@intlify/core-base/9.1.9:
resolution: {integrity: sha512-x5T0p/Ja0S8hs5xs+ImKyYckVkL4CzcEXykVYYV6rcbXxJTe2o58IquSqX9bdncVKbRZP7GlBU1EcRaQEEJ+vw==}
/@intlify/core-base/9.1.10:
resolution: {integrity: sha512-So9CNUavB/IsZ+zBmk2Cv6McQp6vc2wbGi1S0XQmJ8Vz+UFcNn9MFXAe9gY67PreIHrbLsLxDD0cwo1qsxM1Nw==}
engines: {node: '>= 10'}
dependencies:
'@intlify/devtools-if': 9.1.9
'@intlify/message-compiler': 9.1.9
'@intlify/message-resolver': 9.1.9
'@intlify/runtime': 9.1.9
'@intlify/shared': 9.1.9
'@intlify/vue-devtools': 9.1.9
'@intlify/devtools-if': 9.1.10
'@intlify/message-compiler': 9.1.10
'@intlify/message-resolver': 9.1.10
'@intlify/runtime': 9.1.10
'@intlify/shared': 9.1.10
'@intlify/vue-devtools': 9.1.10
dev: false
/@intlify/devtools-if/9.1.9:
resolution: {integrity: sha512-oKSMKjttG3Ut/1UGEZjSdghuP3fwA15zpDPcjkf/1FjlOIm6uIBGMNS5jXzsZy593u+P/YcnrZD6cD3IVFz9vQ==}
/@intlify/devtools-if/9.1.10:
resolution: {integrity: sha512-SHaKoYu6sog3+Q8js1y3oXLywuogbH1sKuc7NSYkN3GElvXSBaMoCzW+we0ZSFqj/6c7vTNLg9nQ6rxhKqYwnQ==}
engines: {node: '>= 10'}
dependencies:
'@intlify/shared': 9.1.9
'@intlify/shared': 9.1.10
dev: false
/@intlify/message-compiler/9.1.9:
resolution: {integrity: sha512-6YgCMF46Xd0IH2hMRLCssZI3gFG4aywidoWQ3QP4RGYQXQYYfFC54DxhSgfIPpVoPLQ+4AD29eoYmhiHZ+qLFQ==}
/@intlify/message-compiler/9.1.10:
resolution: {integrity: sha512-+JiJpXff/XTb0EadYwdxOyRTB0hXNd4n1HaJ/a4yuV960uRmPXaklJsedW0LNdcptd/hYUZtCkI7Lc9J5C1gxg==}
engines: {node: '>= 10'}
dependencies:
'@intlify/message-resolver': 9.1.9
'@intlify/shared': 9.1.9
'@intlify/message-resolver': 9.1.10
'@intlify/shared': 9.1.10
source-map: 0.6.1
dev: false
/@intlify/message-resolver/9.1.9:
resolution: {integrity: sha512-Lx/DBpigeK0sz2BBbzv5mu9/dAlt98HxwbG7xLawC3O2xMF9MNWU5FtOziwYG6TDIjNq0O/3ZbOJAxwITIWXEA==}
/@intlify/message-resolver/9.1.10:
resolution: {integrity: sha512-5YixMG/M05m0cn9+gOzd4EZQTFRUu8RGhzxJbR1DWN21x/Z3bJ8QpDYj6hC4FwBj5uKsRfKpJQ3Xqg98KWoA+w==}
engines: {node: '>= 10'}
dev: false
/@intlify/runtime/9.1.9:
resolution: {integrity: sha512-XgPw8+UlHCiie3fI41HPVa/VDJb3/aSH7bLhY1hJvlvNV713PFtb4p4Jo+rlE0gAoMsMCGcsiT982fImolSltg==}
/@intlify/runtime/9.1.10:
resolution: {integrity: sha512-7QsuByNzpe3Gfmhwq6hzgXcMPpxz8Zxb/XFI6s9lQdPLPe5Lgw4U1ovRPZTOs6Y2hwitR3j/HD8BJNGWpJnOFA==}
engines: {node: '>= 10'}
dependencies:
'@intlify/message-compiler': 9.1.9
'@intlify/message-resolver': 9.1.9
'@intlify/shared': 9.1.9
'@intlify/message-compiler': 9.1.10
'@intlify/message-resolver': 9.1.10
'@intlify/shared': 9.1.10
dev: false
/@intlify/shared/9.1.9:
resolution: {integrity: sha512-xKGM1d0EAxdDFCWedcYXOm6V5Pfw/TMudd6/qCdEb4tv0hk9EKeg7lwQF1azE0dP2phvx0yXxrt7UQK+IZjNdw==}
/@intlify/shared/9.1.10:
resolution: {integrity: sha512-Om54xJeo1Vw+K1+wHYyXngE8cAbrxZHpWjYzMR9wCkqbhGtRV5VLhVc214Ze2YatPrWlS2WSMOWXR8JktX/IgA==}
engines: {node: '>= 10'}
dev: false
/@intlify/vue-devtools/9.1.9:
resolution: {integrity: sha512-YPehH9uL4vZcGXky4Ev5qQIITnHKIvsD2GKGXgqf+05osMUI6WSEQHaN9USRa318Rs8RyyPCiDfmA0hRu3k7og==}
/@intlify/vue-devtools/9.1.10:
resolution: {integrity: sha512-5l3qYARVbkWAkagLu1XbDUWRJSL8br1Dj60wgMaKB0+HswVsrR6LloYZTg7ozyvM621V6+zsmwzbQxbVQyrytQ==}
engines: {node: '>= 10'}
dependencies:
'@intlify/message-resolver': 9.1.9
'@intlify/runtime': 9.1.9
'@intlify/shared': 9.1.9
'@intlify/message-resolver': 9.1.10
'@intlify/runtime': 9.1.10
'@intlify/shared': 9.1.10
dev: false
/@jridgewell/gen-mapping/0.1.1:
@@ -3074,7 +3074,7 @@ packages:
source-map: 0.6.1
wordwrap: 1.0.0
optionalDependencies:
uglify-js: 3.16.0
uglify-js: 3.17.4
dev: true
/hard-rejection/2.1.0:
@@ -5014,8 +5014,8 @@ packages:
hasBin: true
dev: true
/uglify-js/3.16.0:
resolution: {integrity: sha512-FEikl6bR30n0T3amyBh3LoiBdqHRy/f4H80+My34HOesOKyHfOsxAPAxOoqC0JUnC1amnO0IwkYC3sko51caSw==}
/uglify-js/3.17.4:
resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==}
engines: {node: '>=0.8.0'}
hasBin: true
requiresBuild: true
@@ -5385,15 +5385,15 @@ packages:
- supports-color
dev: true
/vue-i18n/9.1.9_vue@3.2.37:
resolution: {integrity: sha512-JeRdNVxS2OGp1E+pye5XB6+M6BBkHwAv9C80Q7+kzoMdUDGRna06tjC0vCB/jDX9aWrl5swxOMFcyAr7or8XTA==}
/vue-i18n/9.1.10_vue@3.2.37:
resolution: {integrity: sha512-jpr7gV5KPk4n+sSPdpZT8Qx3XzTcNDWffRlHV/cT2NUyEf+sEgTTmLvnBAibjOFJ0zsUyZlVTAWH5DDnYep+1g==}
engines: {node: '>= 10'}
peerDependencies:
vue: ^3.0.0
dependencies:
'@intlify/core-base': 9.1.9
'@intlify/shared': 9.1.9
'@intlify/vue-devtools': 9.1.9
'@intlify/core-base': 9.1.10
'@intlify/shared': 9.1.10
'@intlify/vue-devtools': 9.1.10
'@vue/devtools-api': 6.1.4
vue: 3.2.37
dev: false

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 404 KiB

View File

@@ -17,7 +17,7 @@
import { NConfigProvider } from 'naive-ui'
import { GoAppProvider } from '@/components/GoAppProvider'
import { I18n } from '@/components/I18n'
import { useDarkThemeHook, useThemeOverridesHook, useCode, useLang } from '@/hooks'
import { useSystemInit, useDarkThemeHook, useThemeOverridesHook, useCode, useLang } from '@/hooks'
// 暗黑主题
const darkTheme = useDarkThemeHook()
@@ -28,6 +28,9 @@ const overridesTheme = useThemeOverridesHook()
// 代码主题
const hljsTheme = useCode()
// 系统全局数据初始化
useSystemInit()
// 全局语言
const { locale, dateLocale } = useLang()

14
src/api/axios.config.ts Normal file
View File

@@ -0,0 +1,14 @@
import { ModuleTypeEnum } from '@/enums/httpEnum'
// 接口白名单(免登录)
export const fetchAllowList = [
// 登录
`${ModuleTypeEnum.SYSTEM}/login`,
// 获取 OSS 接口
`${ModuleTypeEnum.SYSTEM}/getOssInfo`,
// 预览获取数据
`${ModuleTypeEnum.PROJECT}/getData`,
]
// 接口黑名单
export const fetchBlockList = []

View File

@@ -1,29 +1,80 @@
import axios, { AxiosResponse, AxiosRequestConfig } from 'axios'
import { ResultEnum } from "@/enums/httpEnum"
import { ErrorPageNameMap } from "@/enums/pageEnum"
import { redirectErrorPage } from '@/utils'
import axios, { AxiosResponse, AxiosRequestConfig, Axios } from 'axios'
import { ResultEnum, ModuleTypeEnum } from "@/enums/httpEnum"
import { PageEnum, ErrorPageNameMap } from "@/enums/pageEnum"
import { StorageEnum } from '@/enums/storageEnum'
import { axiosPre } from '@/settings/httpSetting'
import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'
import { redirectErrorPage, getLocalStorage, routerTurnByName, isPreview } from '@/utils'
import { fetchAllowList } from './axios.config'
import includes from 'lodash/includes'
export interface MyResponseType<T> {
code: ResultEnum
data: T
message: string
}
export interface MyRequestInstance extends Axios {
<T = any>(config: AxiosRequestConfig): Promise<MyResponseType<T>>
}
const axiosInstance = axios.create({
baseURL: import.meta.env.DEV ? import.meta.env.VITE_DEV_PATH : import.meta.env.VITE_PRO_PATH,
baseURL: `${import.meta.env.PROD ? import.meta.env.VITE_PRO_PATH : ''}${axiosPre}`,
timeout: ResultEnum.TIMEOUT,
})
}) as unknown as MyRequestInstance
axiosInstance.interceptors.request.use(
(config: AxiosRequestConfig) => {
// 白名单校验
if (includes(fetchAllowList, config.url)) return config
// 获取 token
const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
// 重新登录
if (!info) {
routerTurnByName(PageEnum.BASE_LOGIN_NAME)
return config
}
const userInfo = info[SystemStoreEnum.USER_INFO]
config.headers = {
...config.headers,
[userInfo[SystemStoreUserInfoEnum.TOKEN_NAME] || 'token']: userInfo[SystemStoreUserInfoEnum.USER_TOKEN] || ''
}
return config
},
(error: AxiosRequestConfig) => {
Promise.reject(error)
(err: AxiosRequestConfig) => {
Promise.reject(err)
}
)
// 响应拦截器
axiosInstance.interceptors.response.use(
(res: AxiosResponse) => {
// 预览页面错误不进行处理
if (isPreview()) {
return Promise.resolve(res.data)
}
const { code } = res.data as { code: number }
if (code === ResultEnum.DATA_SUCCESS) return Promise.resolve(res.data)
// 重定向
if (ErrorPageNameMap.get(code)) redirectErrorPage(code)
// 成功
if (code === ResultEnum.SUCCESS) {
return Promise.resolve(res.data)
}
// 登录过期
if (code === ResultEnum.TOKEN_OVERDUE) {
window['$message'].error(window['$t']('http.token_overdue_message'))
routerTurnByName(PageEnum.BASE_LOGIN_NAME)
return Promise.resolve(res.data)
}
// 固定错误码重定向
if (ErrorPageNameMap.get(code)) {
redirectErrorPage(code)
return Promise.resolve(res.data)
}
// 提示错误
window['$message'].error(window['$t']((res.data as any).msg))
return Promise.resolve(res.data)
},
(err: AxiosResponse) => {

View File

@@ -9,16 +9,16 @@ import {
} from '@/enums/httpEnum'
import type { RequestGlobalConfigType, RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
export const get = (url: string, params?: object) => {
return axiosInstance({
export const get = <T = any>(url: string, params?: object) => {
return axiosInstance<T>({
url: url,
method: RequestHttpEnum.GET,
params: params
params: params,
})
}
export const post = (url: string, data?: object, headersType?: string) => {
return axiosInstance({
export const post = <T = any>(url: string, data?: object, headersType?: string) => {
return axiosInstance<T>({
url: url,
method: RequestHttpEnum.POST,
data: data,
@@ -28,8 +28,8 @@ export const post = (url: string, data?: object, headersType?: string) => {
})
}
export const patch = (url: string, data?: object, headersType?: string) => {
return axiosInstance({
export const patch = <T = any>(url: string, data?: object, headersType?: string) => {
return axiosInstance<T>({
url: url,
method: RequestHttpEnum.PATCH,
data: data,
@@ -39,8 +39,8 @@ export const patch = (url: string, data?: object, headersType?: string) => {
})
}
export const put = (url: string, data?: object, headersType?: ContentTypeEnum) => {
return axiosInstance({
export const put = <T = any>(url: string, data?: object, headersType?: ContentTypeEnum) => {
return axiosInstance<T>({
url: url,
method: RequestHttpEnum.PUT,
data: data,
@@ -50,8 +50,8 @@ export const put = (url: string, data?: object, headersType?: ContentTypeEnum) =
})
}
export const del = (url: string, params?: object) => {
return axiosInstance({
export const del = <T = any>(url: string, params?: object) => {
return axiosInstance<T>({
url: url,
method: RequestHttpEnum.DELETE,
params
@@ -82,11 +82,11 @@ export const http = (type?: RequestHttpEnum) => {
}
const prefix = 'javascript:'
// 对输入字符进行转义处理
export const translateStr = (target: string | object) => {
export const translateStr = (target: string | Record<any, any>) => {
if (typeof target === 'string') {
if (target.startsWith(prefix)) {
const funcStr = target.split(prefix)[1]
let result;
let result
try {
result = new Function(`${funcStr}`)()
} catch (error) {
@@ -100,8 +100,8 @@ export const translateStr = (target: string | object) => {
}
for (const key in target) {
if (Object.prototype.hasOwnProperty.call(target, key)) {
const subTarget = (target as any)[key];
(target as any)[key] = translateStr(subTarget)
const subTarget = target[key]
target[key] = translateStr(subTarget)
}
}
return target
@@ -116,7 +116,6 @@ export const customizeHttp = (targetParams: RequestConfigType, globalParams: Req
if (!targetParams || !globalParams) {
return
}
// 全局
const {
// 全局请求源地址

2
src/api/path/index.ts Normal file
View File

@@ -0,0 +1,2 @@
export * from '@/api/path/project.api'
export * from '@/api/path/system.api'

View File

@@ -0,0 +1,98 @@
import { http } from '@/api/http'
import { httpErrorHandle } from '@/utils'
import { ContentTypeEnum, RequestHttpEnum, ModuleTypeEnum } from '@/enums/httpEnum'
import { ProjectItem, ProjectDetail } from './project'
// * 项目列表
export const projectListApi = async (data: object) => {
try {
const res = await http(RequestHttpEnum.GET)<ProjectItem[]>(`${ModuleTypeEnum.PROJECT}/list`, data)
return res
} catch {
httpErrorHandle()
}
}
// * 新增项目
export const createProjectApi = async (data: object) => {
try {
const res = await http(RequestHttpEnum.POST)<{
/**
* 项目id
*/
id: number
}>(`${ModuleTypeEnum.PROJECT}/create`, data)
return res
} catch {
httpErrorHandle()
}
}
// * 获取项目
export const fetchProjectApi = async (data: object) => {
try {
const res = await http(RequestHttpEnum.GET)<ProjectDetail>(`${ModuleTypeEnum.PROJECT}/getData`, data)
return res
} catch {
httpErrorHandle()
}
}
// * 保存项目
export const saveProjectApi = async (data: object) => {
try {
const res = await http(RequestHttpEnum.POST)(
`${ModuleTypeEnum.PROJECT}/save/data`,
data,
ContentTypeEnum.FORM_URLENCODED
)
return res
} catch {
httpErrorHandle()
}
}
// * 修改项目基础信息
export const updateProjectApi = async (data: object) => {
try {
const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.PROJECT}/edit`, data)
return res
} catch {
httpErrorHandle()
}
}
// * 删除项目
export const deleteProjectApi = async (data: object) => {
try {
const res = await http(RequestHttpEnum.DELETE)(`${ModuleTypeEnum.PROJECT}/delete`, data)
return res
} catch {
httpErrorHandle()
}
}
// * 修改发布状态 [-1未发布,1发布]
export const changeProjectReleaseApi = async (data: object) => {
try {
const res = await http(RequestHttpEnum.PUT)(`${ModuleTypeEnum.PROJECT}/publish`, data)
return res
} catch {
httpErrorHandle()
}
}
// * 上传文件
export const uploadFile = async (data: object) => {
try {
const res = await http(RequestHttpEnum.POST)<{
/**
* 文件地址
*/
fileName: string
}>(`${ModuleTypeEnum.PROJECT}/upload`, data, ContentTypeEnum.FORM_DATA)
return res
} catch {
httpErrorHandle()
}
}

39
src/api/path/project.d.ts vendored Normal file
View File

@@ -0,0 +1,39 @@
export type ProjectItem = {
/**
* 项目 id
*/
id: string
/**
* 项目名称
*/
projectName: string
/**
* 项目状态:\
* -1: 未发布\
* 1: 已发布
*/
state: number
/**
* 创建时间
*/
createTime: string
/**
* 预览图片url
*/
indexImage: string
/**
* 创建者 id
*/
createUserId: string
/**
* 项目备注
*/
remarks: string
}
export interface ProjectDetail extends ProjectItem {
/**
* 项目参数
*/
content: string
}

View File

@@ -0,0 +1,39 @@
import { http } from '@/api/http'
import { httpErrorHandle } from '@/utils'
import { RequestHttpEnum, ModuleTypeEnum } from '@/enums/httpEnum'
import { LoginResult } from './system'
// * 登录
export const loginApi = async (data: object) => {
try {
const res = await http(RequestHttpEnum.POST)<LoginResult>(`${ModuleTypeEnum.SYSTEM}/login`, data)
return res
} catch (err) {
httpErrorHandle()
}
}
// * 登出
export const logoutApi = async () => {
try {
const res = await http(RequestHttpEnum.GET)(`${ModuleTypeEnum.SYSTEM}/logout`)
return res
} catch (err) {
httpErrorHandle()
}
}
// * 获取 oss 上传接口
export const ossUrlApi = async (data: object) => {
try {
const res = await http(RequestHttpEnum.GET)<{
/**
* bucket 地址
*/
bucketURL?: string
}>(`${ModuleTypeEnum.SYSTEM}/getOssInfo`, data)
return res
} catch (err) {
httpErrorHandle()
}
}

26
src/api/path/system.d.ts vendored Normal file
View File

@@ -0,0 +1,26 @@
export interface LoginResult {
token: {
/**
* token 值
*/
tokenValue: string
/**
* token key
*/
tokenName: string
}
userinfo: {
/**
* 昵称
*/
nickname: string
/**
* 用户名
*/
username: string
/**
* 用户 id
*/
id: string
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

@@ -42,15 +42,21 @@
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue'
import { icon } from '@/plugins'
const { HelpOutlineIcon, CloseIcon } = icon.ionicons5
const emit = defineEmits(['update:modelShow'])
defineProps({
const props = defineProps({
modelShow: Boolean
})
const emit = defineEmits(['update:modelShow'])
const { HelpOutlineIcon, CloseIcon } = icon.ionicons5
const modelShow = ref(false)
watch(() => props.modelShow, (newValue) => {
modelShow.value = newValue
})
const closeHandle = () => {
emit('update:modelShow', false)
}

View File

@@ -69,21 +69,20 @@
</template>
<script script lang="ts" setup>
import { reactive } from 'vue'
import { reactive, ref, watch } from 'vue'
import { ListType } from './index.d'
import { useSettingStore } from '@/store/modules/settingStore/settingStore'
import { SettingStoreEnums, ToolsStatusEnum } from '@/store/modules/settingStore/settingStore.d'
import { icon } from '@/plugins'
const { HelpOutlineIcon, CloseIcon } = icon.ionicons5
const emit = defineEmits(['update:modelShow'])
defineProps({
const props = defineProps({
modelShow: Boolean
})
const emit = defineEmits(['update:modelShow'])
const { HelpOutlineIcon, CloseIcon } = icon.ionicons5
const settingStore = useSettingStore()
const modelShow = ref(false)
const list = reactive<ListType[]>([
{
@@ -168,6 +167,10 @@ const list = reactive<ListType[]>([
}
])
watch(() => props.modelShow, (newValue) => {
modelShow.value = newValue
})
const closeHandle = () => {
emit('update:modelShow', false)
}

View File

@@ -27,7 +27,9 @@
<script lang="ts" setup>
import { h, ref } from 'vue'
import { NAvatar, NText } from 'naive-ui'
import { renderIcon } from '@/utils'
import { renderIcon, getLocalStorage } from '@/utils'
import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'
import { StorageEnum } from '@/enums/storageEnum'
import { logout, renderLang } from '@/utils'
import { GoSystemSet } from '@/components/GoSystemSet/index'
import { GoSystemInfo } from '@/components/GoSystemInfo/index'
@@ -64,7 +66,17 @@ const renderUserInfo = () => {
}),
h('div', null, [
h('div', null, [
h(NText, { depth: 2 }, { default: () => '奔跑的面条' })
h(NText, { depth: 2 }, {
default: () => {
const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
if (info) {
return info[SystemStoreEnum.USER_INFO][SystemStoreUserInfoEnum.USER_NAME];
}
else {
return 'admin';
}
}
})
])
])
]
@@ -137,4 +149,4 @@ const handleSelect = (key: string) => {
cursor: pointer;
transform: scale(0.7);
}
</style>
</style>

View File

@@ -99,6 +99,7 @@ const colorSelectHandle = (color: AppThemeColorType) => {
overflow: hidden;
border-radius: 5px;
@extend .go-background-filter-shallow;
backdrop-filter: none;
}
&-color {
width: 8px;

View File

@@ -46,7 +46,6 @@ export enum MenuEnum {
UN_GROUP = 'unGroup',
// 后退
BACK = 'back',
// 前进
FORWORD = 'forward',
// 保存
SAVE = 'save',
@@ -80,3 +79,15 @@ export enum MacKeyboard {
SHIFT_SOURCE_KEY = '⇧',
ALT_SOURCE_KEY = '⌥'
}
// 同步状态枚举
export enum SyncEnum {
// 等待
PENDING,
// 开始
START,
// 成功
SUCCESS,
// 失败
FAILURE
}

View File

@@ -1,13 +1,18 @@
/**
* @description: 请求结果集
*/
// 模块 Path 前缀分类
export enum ModuleTypeEnum {
SYSTEM = 'sys',
PROJECT = 'project',
}
// 请求结果集
export enum ResultEnum {
DATA_SUCCESS = 0,
SUCCESS = 200,
SERVER_ERROR = 500,
SERVER_FORBIDDEN = 403,
NOT_FOUND = 404,
TIMEOUT = 60000
TOKEN_OVERDUE = 886,
TIMEOUT = 60000,
}
// 数据相关
@@ -15,7 +20,9 @@ export enum RequestDataTypeEnum {
// 静态数据
STATIC = 0,
// 请求数据
AJAX = 1
AJAX = 1,
// 数据池
Pond = 2
}
// 请求主体类型
@@ -26,9 +33,13 @@ export enum RequestContentTypeEnum {
SQL = 1
}
/**
* @description: 请求方法
*/
// 头部
export enum RequestHttpHeaderEnum {
TOKEN = 'Token',
COOKIE = 'Cookie'
}
// 请求方法
export enum RequestHttpEnum {
GET = 'get',
POST = 'post',
@@ -109,9 +120,7 @@ export type RequestParams = {
}
}
/**
* @description: 常用的contentTyp类型
*/
// 常用的contentTyp类型
export enum ContentTypeEnum {
// json
JSON = 'application/json;charset=UTF-8',

View File

@@ -26,10 +26,15 @@ export enum PageEnum {
//重定向
REDIRECT = '/redirect',
REDIRECT_NAME = 'Redirect',
// 未发布
REDIRECT_UN_PUBLISH = '/redirect/unPublish',
REDIRECT_UN_PUBLISH_NAME = 'redirect-un-publish',
// 重载
RELOAD = '/reload',
RELOAD_NAME = 'Reload',
// 首页
BASE_HOME = '/project',
BASE_HOME_NAME = 'Project',

View File

@@ -1,10 +1,8 @@
export enum StorageEnum {
// 全局设置
GO_SYSTEM_SETTING_STORE = 'GO_SYSTEM_SETTING',
// token 等信息
GO_ACCESS_TOKEN_STORE = 'GO_ACCESS_TOKEN',
GO_SETTING_STORE = 'GO_SETTING',
// 登录信息
GO_LOGIN_INFO_STORE = 'GO_LOGIN_INFO',
GO_SYSTEM_STORE = 'GO_SYSTEM',
// 语言
GO_LANG_STORE = 'GO_LANG',
// 当前选择的主题

View File

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

View File

@@ -26,11 +26,10 @@ export const useChartDataFetch = (
// 数据池
const { addGlobalDataInterface } = useChartDataPondFetch()
const { requestDataPondId } = toRefs(targetComponent.request)
// 组件类型
const { chartFrame } = targetComponent.chartConfig
// eCharts 组件配合 vChart 库更新方式
const echartsUpdateHandle = (dataset: any) => {
if (chartFrame === ChartFrameEnum.ECHARTS) {
@@ -89,7 +88,6 @@ export const useChartDataFetch = (
// 立即调用
fetchFn()
// 定时时间
const time = targetInterval && targetInterval.value ? targetInterval.value : globalRequestInterval.value
// 单位
@@ -104,8 +102,8 @@ export const useChartDataFetch = (
}
if (isPreview()) {
// 判断是否数据池对应 id
requestDataPondId
// 判断是否数据池类型
targetComponent.request.requestDataType === RequestDataTypeEnum.Pond
? addGlobalDataInterface(targetComponent, useChartEditStore, updateCallback || echartsUpdateHandle)
: requestIntervalFn()
}

View File

@@ -3,7 +3,7 @@ import { customizeHttp } from '@/api/http'
import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { RequestGlobalConfigType, RequestDataPondItemType } from '@/store/modules/chartEditStore/chartEditStore.d'
import { newFunctionHandle } from '@/utils'
import { newFunctionHandle, intervalUnitHandle } from '@/utils'
// 获取类型
type ChartEditStoreType = typeof useChartEditStore
@@ -24,6 +24,9 @@ const newPondItemInterval = (
dataPondMapItem?: DataPondMapType[]
) => {
if (!dataPondMapItem) return
let fetchInterval: any = 0
clearInterval(fetchInterval)
// 请求
const fetchFn = async () => {
@@ -48,6 +51,19 @@ const newPondItemInterval = (
// 立即调用
fetchFn()
const targetInterval = requestDataPondItem.dataPondRequestConfig.requestInterval
const targetUnit = requestDataPondItem.dataPondRequestConfig.requestIntervalUnit
const globalRequestInterval = requestGlobalConfig.requestInterval
const globalUnit = requestGlobalConfig.requestIntervalUnit
// 定时时间
const time = targetInterval ? targetInterval : globalRequestInterval
// 单位
const unit = targetInterval ? targetUnit : globalUnit
// 开启轮询
if (time) fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit))
}
/**
@@ -64,7 +80,7 @@ export const useChartDataPondFetch = () => {
const { requestDataPond } = chartEditStore.getRequestGlobalConfig
// 组件对应的数据池 Id
const requestDataPondId = '111' || (targetComponent.request.requestDataPondId as string)
const requestDataPondId = targetComponent.request.requestDataPondId as string
// 新增数据项
const mittPondIdArr = mittDataPondMap.get(requestDataPondId) || []
mittPondIdArr.push({
@@ -74,6 +90,11 @@ export const useChartDataPondFetch = () => {
mittDataPondMap.set(requestDataPondId, mittPondIdArr)
}
// 清除旧数据
const clearMittDataPondMap = () => {
mittDataPondMap.clear()
}
// 初始化数据池
const initDataPond = (requestGlobalConfig: RequestGlobalConfigType) => {
const { requestDataPond } = requestGlobalConfig
@@ -88,6 +109,7 @@ export const useChartDataPondFetch = () => {
return {
addGlobalDataInterface,
clearMittDataPondMap,
initDataPond
}
}

View File

@@ -0,0 +1,23 @@
import { useSystemStore } from '@/store/modules/systemStore/systemStore'
import { SystemStoreEnum } from '@/store/modules/systemStore/systemStore.d'
import { ResultEnum } from '@/enums/httpEnum'
import { ossUrlApi } from '@/api/path'
// * 初始化
export const useSystemInit = async () => {
const systemStore = useSystemStore()
// 获取 OSS 信息的 url 地址,用来拼接展示图片的地址
const getOssUrl = async () => {
const res = await ossUrlApi({})
if (res && res.code === ResultEnum.SUCCESS) {
systemStore.setItem(SystemStoreEnum.FETCH_INFO, {
OSSUrl: res.data?.bucketURL
})
}
}
// 执行
getOssUrl()
}

View File

@@ -11,6 +11,8 @@ const global = {
help: 'Help',
contact: 'About Software',
logout: 'Logout',
logout_success: 'Logout success',
logout_failure: 'Logout Failed',
// system setting
sys_set: 'System Setting',
lang_set: 'Language Setting',
@@ -26,8 +28,14 @@ const global = {
r_more: 'More',
}
const http = {
error_message: 'The interface is abnormal, please check the interface!',
token_overdue_message: 'Login expired, please log in again!'
}
export default {
global,
http,
login,
project
}

View File

@@ -2,6 +2,6 @@ export default {
desc: "Login",
form_auto: "Sign in automatically",
form_button: "Login",
login_success: "Login success",
login_message: "Please complete the letter",
login_success: "Login success!",
login_message: "Please complete the letter!",
}

View File

@@ -1,6 +1,8 @@
export default {
create_btn: 'Creat',
create_tip: 'Please select a content for development',
create_success: 'Creat Success!',
create_failure: 'Failed to create, please try again later',
create_tip: 'Please select a content for development!',
project: 'Project',
my: 'My',
new_project: 'New Project',

View File

@@ -11,6 +11,8 @@ const global = {
help: '帮助中心',
contact: '关于软件',
logout: '退出登录',
logout_success: '退出成功!',
logout_failure: '退出失败!',
// 系统设置
sys_set: '系统设置',
lang_set: '语言设置',
@@ -18,16 +20,27 @@ const global = {
r_edit: '编辑',
r_preview: '预览',
r_copy: '克隆',
r_copy_success: '克隆成功!',
r_rename: '重命名',
r_rename_success: '重命名成功!',
r_publish: '发布',
r_publish_success: '成功发布!',
r_unpublish: '取消发布',
r_unpublish_success: '取消成功!',
r_download: '下载',
r_delete: '删除',
r_delete_success: '删除成功!',
r_more: '更多',
}
const http = {
error_message: '获取数据失败,请稍后重试!',
token_overdue_message: '登录过期,请重新登录!'
}
export default {
global,
http,
login,
project
}

View File

@@ -2,6 +2,6 @@ export default {
desc: "登录",
form_auto: "自动登录",
form_button: "登录",
login_success: "登录成功",
login_message: "请填写完整信息",
login_success: "登录成功!",
}

View File

@@ -1,6 +1,8 @@
export default {
// aside
create_btn: '新建',
create_success: '新建成功!',
create_failure: '新建失败,请稍后重试!',
create_tip: '从哪里出发好呢?',
project: '项目',
my: '我的',

View File

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

View File

@@ -0,0 +1,7 @@
export const labelConfig = {
position: [
{ label: '外侧', value: 'outside' },
{ label: '内部', value: 'inside' },
{ label: '中心', value: 'center' }
]
}

View File

@@ -43,7 +43,9 @@ const option = {
},
label: {
show: false,
position: 'center'
position: 'center',
formatter: '{b}',
fontSize:12
},
emphasis: {
label: {

View File

@@ -7,6 +7,48 @@
<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>
@@ -15,6 +57,7 @@ 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: {
@@ -36,4 +79,10 @@ const fontWeightOptions = [
value: PieTypeObject[PieTypeEnum.ROSE]
}
]
const labelFormatterOptions = [
{ label: '数据名', value: '{b}' },
{ label: '百分比', value: '{d}' },
{ label: '列名:百分比', value: '{b}:{d}%' }
]
</script>

View File

@@ -6,7 +6,7 @@ export const FlipperNumberConfig: ConfigType = {
key: 'FlipperNumber',
chartKey: 'VFlipperNumber',
conKey: 'VCFlipperNumber',
title: '数字翻牌',
title: '数字翻牌-需动态触发',
category: ChatCategoryEnum.MORE,
categoryName: ChatCategoryEnumName.MORE,
package: PackagesCategoryEnum.DECORATES,

View File

@@ -20,7 +20,7 @@ import { chartInitConfig } from '@/settings/designSetting'
import cloneDeep from 'lodash/cloneDeep'
// 请求基础属性
const requestConfig: RequestConfigType = {
export const requestConfig: RequestConfigType = {
requestDataType: RequestDataTypeEnum.STATIC,
requestHttpType: RequestHttpEnum.GET,
requestUrl: '',

View File

@@ -8,7 +8,10 @@ import { SketchRule } from 'vue3-sketch-ruler'
* @param app
*/
export function setupCustomComponents(app: App) {
// 骨架屏
app.component('GoSkeleton', GoSkeleton)
// 加载
app.component('GoLoading', GoLoading)
// 标尺
app.component('SketchRule', SketchRule)
}

View File

@@ -54,6 +54,7 @@ import {
ArrowForward as ArrowForwardIcon,
Planet as PawIcon,
Search as SearchIcon,
Reload as ReloadIcon,
ChevronUpOutline as ChevronUpOutlineIcon,
ChevronDownOutline as ChevronDownOutlineIcon,
Pulse as PulseIcon,
@@ -93,6 +94,7 @@ import {
FitToScreen as FitToScreenIcon,
FitToHeight as FitToHeightIcon,
FitToWidth as FitToWidthIcon,
Save as SaveIcon,
Carbon3DCursor as Carbon3DCursorIcon,
Carbon3DSoftware as Carbon3DSoftwareIcon,
Filter as FilterIcon,
@@ -210,6 +212,8 @@ const ionicons5 = {
PawIcon,
// 搜索(放大镜)
SearchIcon,
// 加载
ReloadIcon,
// 过滤器
FilterIcon,
// 向上
@@ -277,6 +281,8 @@ const carbon = {
FitToScreenIcon,
FitToHeightIcon,
FitToWidthIcon,
// 保存
SaveIcon,
// 成组
Carbon3DCursorIcon,
// 解组

View File

@@ -7,6 +7,7 @@ import {
NH2,
NH3,
NH4,
NH5,
NCode,
NCountdown,
NText,
@@ -109,6 +110,7 @@ const naive = create({
NH2,
NH3,
NH4,
NH5,
NCode,
NCountdown,
NText,

View File

@@ -1,13 +1,13 @@
import { RouteRecordRaw } from 'vue-router'
import type { AppRouteRecordRaw } from '@/router/types';
import { ErrorPage404, ErrorPage403, ErrorPage500, Layout } from '@/router/constant';
import { ErrorPage404, ErrorPage403, ErrorPage500, Layout, RedirectHome, RedirectUnPublish } from '@/router/constant';
import { PageEnum } from '@/enums/pageEnum'
import { GoReload } from '@/components/GoReload'
export const LoginRoute: RouteRecordRaw = {
path: '/login',
name: 'Login',
path: PageEnum.BASE_LOGIN,
name: PageEnum.BASE_LOGIN_NAME,
component: () => import('@/views/login/index.vue'),
meta: {
title: '登录',
@@ -60,22 +60,21 @@ export const ReloadRoute: AppRouteRecordRaw = {
},
}
export const RedirectRoute: AppRouteRecordRaw = {
path: PageEnum.REDIRECT,
name: PageEnum.REDIRECT_NAME,
component: Layout,
meta: {
title: PageEnum.REDIRECT_NAME,
},
children: [
{
path: '/redirect/:path(.*)',
name: PageEnum.REDIRECT_NAME,
component: () => import('@/views/redirect/index.vue'),
meta: {
title: PageEnum.REDIRECT_NAME,
hideBreadcrumb: true,
},
export const RedirectRoute: RouteRecordRaw[] = [
{
path: PageEnum.REDIRECT,
name: PageEnum.REDIRECT_NAME,
component: RedirectHome,
meta: {
title: PageEnum.REDIRECT_NAME,
},
],
};
},
{
path: PageEnum.REDIRECT_UN_PUBLISH,
name: PageEnum.REDIRECT_UN_PUBLISH_NAME,
component: RedirectUnPublish,
meta: {
title: PageEnum.REDIRECT_UN_PUBLISH_NAME,
},
},
]

View File

@@ -4,6 +4,10 @@ export const ErrorPage403 = () => import('@/views/exception/403.vue');
export const ErrorPage500 = () => import('@/views/exception/500.vue');
export const RedirectHome = () => import('@/views/redirect/index.vue');
export const RedirectUnPublish = () => import('@/views/redirect/UnPublish.vue');
export const Layout = () => import('@/layout/index.vue');
export const ParentLayout = () => import('@/layout/parentLayout.vue');

View File

@@ -1,9 +1,8 @@
import type { App } from 'vue'
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
import { RedirectRoute } from '@/router/base'
import { createRouterGuards } from './router-guards'
import { PageEnum } from '@/enums/pageEnum'
import { HttpErrorPage, LoginRoute, ReloadRoute } from '@/router/base'
import { HttpErrorPage, LoginRoute, ReloadRoute, RedirectRoute } from '@/router/base'
import { Layout } from '@/router/constant'
import modules from '@/router/modules'
@@ -19,6 +18,7 @@ const RootRoute: Array<RouteRecordRaw> = [
},
children: [
...HttpErrorPage,
...RedirectRoute,
modules.projectRoutes,
modules.chartRoutes,
modules.previewRoutes,
@@ -28,7 +28,7 @@ const RootRoute: Array<RouteRecordRaw> = [
]
export const constantRouter: any[] = [LoginRoute, ...RootRoute, RedirectRoute, ReloadRoute];
export const constantRouter: any[] = [LoginRoute, ...RootRoute, ReloadRoute];
const router = createRouter({
history: createWebHashHistory(''),

View File

@@ -1,7 +1,15 @@
import { Router } from 'vue-router';
import { PageEnum } from '@/enums/pageEnum'
import { PageEnum, PreviewEnum } from '@/enums/pageEnum'
import { loginCheck } from '@/utils'
// 路由白名单
const routerAllowList = [
// 登录
PageEnum.BASE_LOGIN_NAME,
// 预览
PreviewEnum.CHART_PREVIEW_NAME
]
export function createRouterGuards(router: Router) {
// 前置
router.beforeEach(async (to, from, next) => {
@@ -12,10 +20,8 @@ export function createRouterGuards(router: Router) {
next({ name: PageEnum.ERROR_PAGE_NAME_404 })
}
if (!loginCheck()) {
if (to.name === PageEnum.BASE_LOGIN_NAME) {
next()
}
// @ts-ignore
if (!routerAllowList.includes(to.name) && !loginCheck()) {
next({ name: PageEnum.BASE_LOGIN_NAME })
}
next()

View File

@@ -61,6 +61,9 @@ export const editToJsonInterval = 5000
// 数据请求间隔
export const requestInterval = 30
// 工作台自动保存间隔s
export const saveInterval = 30
// 数据请求间隔单位
export const requestIntervalUnit = RequestHttpIntervalEnum.SECOND

View File

@@ -0,0 +1,2 @@
// 请求前缀
export const axiosPre = '/api/goview'

View File

@@ -1,5 +1,6 @@
import { CreateComponentType, CreateComponentGroupType, FilterEnum } from '@/packages/index.d'
import { HistoryActionTypeEnum } from '@/store/modules/chartHistoryStore/chartHistoryStore.d'
import { SyncEnum } from '@/enums/editPageEnum'
import {
RequestHttpEnum,
RequestContentTypeEnum,
@@ -12,6 +13,29 @@ import {
import { PreviewScaleEnum } from '@/enums/styleEnum'
import type { ChartColorsNameType, GlobalThemeJsonType } from '@/settings/chartThemes/index'
// 项目数据枚举
export enum ProjectInfoEnum {
// ID
PROJECT_ID = "projectId",
// 名称
PROJECT_NAME = 'projectName',
// 描述
REMARKS = 'remarks',
// 缩略图
THUMBNAIL= 'thumbnail',
// 是否公开发布
RELEASE = 'release'
}
// 项目数据
export type ProjectInfoType = {
[ProjectInfoEnum.PROJECT_ID]: string,
[ProjectInfoEnum.PROJECT_NAME]: string,
[ProjectInfoEnum.REMARKS]: string,
[ProjectInfoEnum.THUMBNAIL]: string,
[ProjectInfoEnum.RELEASE]: boolean
}
// 编辑画布属性
export enum EditCanvasTypeEnum {
EDIT_LAYOUT_DOM = 'editLayoutDom',
@@ -20,12 +44,13 @@ export enum EditCanvasTypeEnum {
SCALE = 'scale',
USER_SCALE = 'userScale',
LOCK_SCALE = 'lockScale',
SAVE_STATUS = 'saveStatus',
IS_CREATE = 'isCreate',
IS_DRAG = 'isDrag',
IS_SELECT = 'isSelect'
}
// 编辑区域
// 编辑区域(临时)
export type EditCanvasType = {
// 编辑区域 DOM
[EditCanvasTypeEnum.EDIT_LAYOUT_DOM]: HTMLElement | null
@@ -42,11 +67,13 @@ export type EditCanvasType = {
[EditCanvasTypeEnum.IS_CREATE]: boolean
// 拖拽中
[EditCanvasTypeEnum.IS_DRAG]: boolean
// 保存状态
[EditCanvasTypeEnum.SAVE_STATUS]: SyncEnum
// 框选中
[EditCanvasTypeEnum.IS_SELECT]: boolean
}
// 滤镜/背景色/宽高主题等
// 画布数据/滤镜/背景色/宽高主题等
export enum EditCanvasConfigEnum {
WIDTH = 'width',
HEIGHT = 'height',
@@ -58,7 +85,14 @@ export enum EditCanvasConfigEnum {
PREVIEW_SCALE_TYPE = 'previewScaleType'
}
export interface EditCanvasConfigType {
// 画布属性(需保存)
export type EditCanvasConfigType = {
// ID
[EditCanvasConfigEnum.PROJECT_ID]: string,
// 项目名称
[EditCanvasConfigEnum.PROJECT_NAME]: string,
// 项目描述
[EditCanvasConfigEnum.REMARKS]: string,
// 滤镜-启用
[FilterEnum.FILTERS_SHOW]: boolean
// 滤镜-色相
@@ -130,6 +164,7 @@ export type RecordChartType = {
// Store 枚举
export enum ChartEditStoreEnum {
PROJECT_INFO = 'projectInfo',
EDIT_RANGE = 'editRange',
EDIT_CANVAS = 'editCanvas',
RIGHT_MENU_SHOW = 'rightMenuShow',
@@ -191,6 +226,7 @@ export interface RequestConfigType extends RequestPublicConfigType {
// Store 类型
export interface ChartEditStoreType {
[ChartEditStoreEnum.PROJECT_INFO]: ProjectInfoType
[ChartEditStoreEnum.EDIT_CANVAS]: EditCanvasType
[ChartEditStoreEnum.EDIT_CANVAS_CONFIG]: EditCanvasConfigType
[ChartEditStoreEnum.RIGHT_MENU_SHOW]: boolean

View File

@@ -10,14 +10,22 @@ import { requestInterval, previewScaleType, requestIntervalUnit } from '@/settin
import { useChartHistoryStore } from '@/store/modules/chartHistoryStore/chartHistoryStore'
// 全局设置
import { useSettingStore } from '@/store/modules/settingStore/settingStore'
// 历史类型
import { HistoryActionTypeEnum, HistoryItemType, HistoryTargetTypeEnum } from '@/store/modules/chartHistoryStore/chartHistoryStore.d'
// 画布枚举
import { MenuEnum, SyncEnum } from '@/enums/editPageEnum'
import {
HistoryActionTypeEnum,
HistoryItemType,
HistoryTargetTypeEnum
} from '@/store/modules/chartHistoryStore/chartHistoryStore.d'
import { MenuEnum } from '@/enums/editPageEnum'
import { getUUID, loadingStart, loadingFinish, loadingError, isString, isArray } from '@/utils'
getUUID,
loadingStart,
loadingFinish,
loadingError,
isString,
isArray
} from '@/utils'
import {
ProjectInfoType,
ChartEditStoreEnum,
ChartEditStorage,
ChartEditStoreType,
@@ -36,6 +44,14 @@ const settingStore = useSettingStore()
export const useChartEditStore = defineStore({
id: 'useChartEditStore',
state: (): ChartEditStoreType => ({
// 项目数据
projectInfo: {
projectId: '',
projectName: '',
remarks: '',
thumbnail: '',
release: false
},
// 画布属性
editCanvas: {
// 编辑区域 Dom
@@ -54,7 +70,9 @@ export const useChartEditStore = defineStore({
// 拖拽中
isDrag: false,
// 框选中
isSelect: false
isSelect: false,
// 同步中
saveStatus: SyncEnum.PENDING
},
// 右键菜单
rightMenuShow: false,
@@ -132,6 +150,9 @@ export const useChartEditStore = defineStore({
componentList: []
}),
getters: {
getProjectInfo(): ProjectInfoType {
return this.projectInfo
},
getMousePosition(): MousePositionType {
return this.mousePosition
},
@@ -166,6 +187,10 @@ export const useChartEditStore = defineStore({
}
},
actions: {
// * 设置 peojectInfo 数据项
setProjectInfo<T extends keyof ProjectInfoType, K extends ProjectInfoType[T]>(key: T, value: K) {
this.projectInfo[key] = value
},
// * 设置 editCanvas 数据项
setEditCanvas<T extends keyof EditCanvasType, K extends EditCanvasType[T]>(key: T, value: K) {
this.editCanvas[key] = value

View File

@@ -4,10 +4,10 @@ import { asideCollapsedWidth } from '@/settings/designSetting'
import { SettingStoreType, ToolsStatusEnum } from './settingStore.d'
import { setLocalStorage, getLocalStorage } from '@/utils'
import { StorageEnum } from '@/enums/storageEnum'
const { GO_SYSTEM_SETTING_STORE } = StorageEnum
const { GO_SETTING_STORE } = StorageEnum
const storageSetting: SettingStoreType = getLocalStorage(
GO_SYSTEM_SETTING_STORE
GO_SETTING_STORE
)
// 全局设置
@@ -48,7 +48,7 @@ export const useSettingStore = defineStore({
this.$patch(state => {
state[key] = value
})
setLocalStorage(GO_SYSTEM_SETTING_STORE, this.$state)
setLocalStorage(GO_SETTING_STORE, this.$state)
}
}
})

View File

@@ -0,0 +1,31 @@
export enum SystemStoreUserInfoEnum {
USER_TOKEN = 'userToken',
TOKEN_NAME = 'tokenName',
USER_ID = 'userId',
USER_NAME = 'userName',
NICK_NAME = 'nickName',
}
export interface UserInfoType {
[SystemStoreUserInfoEnum.USER_TOKEN]?: string,
[SystemStoreUserInfoEnum.TOKEN_NAME]?: string,
[SystemStoreUserInfoEnum.USER_ID]?: string,
[SystemStoreUserInfoEnum.USER_NAME]?: string,
[SystemStoreUserInfoEnum.NICK_NAME]?: string,
}
export interface FetchInfoType {
OSSUrl?: string,
}
export enum SystemStoreEnum {
// 用户
USER_INFO = 'userInfo',
// 请求
FETCH_INFO = 'fetchInfo'
}
export interface SystemStoreType {
[SystemStoreEnum.USER_INFO]: UserInfoType
[SystemStoreEnum.FETCH_INFO]: FetchInfoType
}

View File

@@ -0,0 +1,40 @@
import { defineStore } from 'pinia'
import { SystemStoreType, UserInfoType, FetchInfoType } from './systemStore.d'
import { setLocalStorage, getLocalStorage } from '@/utils'
import { StorageEnum } from '@/enums/storageEnum'
const { GO_SYSTEM_STORE } = StorageEnum
const storageSystem: SystemStoreType = getLocalStorage(GO_SYSTEM_STORE)
// 系统数据记录
export const useSystemStore = defineStore({
id: 'useSystemStore',
state: (): SystemStoreType => storageSystem || {
userInfo: {
userId: undefined,
userName: undefined,
userToken: undefined,
nickName: undefined
},
fetchInfo: {
OSSUrl: undefined
}
},
getters: {
getUserInfo(): UserInfoType {
return this.userInfo
},
getFetchInfo(): FetchInfoType {
return this.fetchInfo
},
},
actions: {
setItem<T extends keyof SystemStoreType, K extends SystemStoreType[T]>(key: T, value: K): void {
this.$patch(state => {
state[key] = value
});
setLocalStorage(GO_SYSTEM_STORE, this.$state)
}
}
})

View File

@@ -1,3 +1,65 @@
/**
* * base64转file
* @param dataurl
* @param fileName
* @returns
*/
export const base64toFile = (dataurl: string, fileName: string) => {
let dataArr = dataurl.split(","),
mime = (dataArr as any[])[0].match(/:(.*?);/)[1],
bstr = atob(dataArr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], fileName, { type: mime });
}
/**
* * file转url
*/
export const fileToUrl = (file: File): string => {
const Url = URL || window.URL || window.webkitURL
const ImageUrl = Url.createObjectURL(file)
return ImageUrl
}
/**
* * url转file
*/
export const urlToFile = (fileUrl: string, fileName = `${new Date().getTime()}`): File => {
const dataArr = fileUrl.split(',')
const mime = (dataArr as any[])[0].match(/:(.*);/)[1]
const originStr = atob(dataArr[1])
return new File([originStr], `${fileName}`, { type: mime })
}
/**
* * file转base64
* @param file 文件数据
* @param callback 回调函数
*/
export const fileTobase64 = (file: File, callback: Function) => {
let reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = function (e: ProgressEvent<FileReader>) {
if (e.target) {
let base64 = e.target.result
callback(base64)
}
}
}
/**
* * canvas转file
* @param canvas
*/
export const canvastoFile = (canvas: HTMLCanvasElement, name?: string) => {
const dataurl = canvas.toDataURL('image/png')
return urlToFile(dataurl, name)
}
/**
* *获取上传的文件数据
* @param { File } file 文件对象
@@ -51,4 +113,4 @@ export const downloadTextFile = (
// 字符内容转变成blob地址
const blob = new Blob([content])
downloadByA(URL.createObjectURL(blob), filename, fileSuffix)
}
}

6
src/utils/http.ts Normal file
View File

@@ -0,0 +1,6 @@
/**
* * 请求失败统一处理
*/
export const httpErrorHandle = () => {
window['$message'].error(window['$t']('http.error_message'))
}

View File

@@ -7,3 +7,4 @@ export * from '@/utils/plugin'
export * from '@/utils/components'
export * from '@/utils/type'
export * from '@/utils/file'
export * from '@/utils/http'

View File

@@ -35,7 +35,7 @@ export const loadingError = () => {
* })
* ```
*/
export const goDialog = (
export const goDialog = (
params: {
// 基本
type?: DialogEnum

View File

@@ -1,11 +1,12 @@
import { useRoute } from 'vue-router'
import { ResultEnum } from '@/enums/httpEnum'
import { ErrorPageNameMap, PageEnum } from '@/enums/pageEnum'
import { ResultEnum, RequestHttpHeaderEnum } from '@/enums/httpEnum'
import { ErrorPageNameMap, PageEnum, PreviewEnum } from '@/enums/pageEnum'
import { docPath, giteeSourceCodePath } from '@/settings/pathConst'
import { cryptoDecode } from './crypto'
import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'
import { StorageEnum } from '@/enums/storageEnum'
import { clearLocalStorage, getLocalStorage } from './storage'
import { clearLocalStorage, getLocalStorage, clearCookie } from './storage'
import router from '@/router'
import { logoutApi } from '@/api/path'
/**
* * 根据名字跳转路由
@@ -101,11 +102,20 @@ export const reloadRoutePage = () => {
}
/**
* * 退出
* * 退出登录
*/
export const logout = () => {
clearLocalStorage(StorageEnum.GO_LOGIN_INFO_STORE)
routerTurnByName(PageEnum.BASE_LOGIN_NAME)
export const logout = async () => {
try {
const res = await logoutApi()
if(res && res.code === ResultEnum.SUCCESS) {
window['$message'].success(window['$t']('global.logout_success'))
clearCookie(RequestHttpHeaderEnum.COOKIE)
clearLocalStorage(StorageEnum.GO_SYSTEM_STORE)
routerTurnByName(PageEnum.BASE_LOGIN_NAME)
}
} catch (error) {
window['$message'].success(window['$t']('global.logout_failure'))
}
}
/**
@@ -157,7 +167,7 @@ export const fetchRouteParams = () => {
* * 通过硬解析获取当前路由下的参数
* @returns object
*/
export const fetchRouteParamsLocation = () => {
export const fetchRouteParamsLocation = () => {
try {
return document.location.hash.split('/').pop() || ''
} catch (error) {
@@ -175,19 +185,29 @@ export const goHome = () => {
}
/**
* * 判断是否登录(现阶段是有 login 数据即可)
* * 判断是否登录
* @return boolean
*/
export const loginCheck = () => {
try {
const info = getLocalStorage(StorageEnum.GO_LOGIN_INFO_STORE)
const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
if (!info) return false
const decodeInfo = cryptoDecode(info)
if (decodeInfo) {
if (info[SystemStoreEnum.USER_INFO][SystemStoreUserInfoEnum.USER_TOKEN]) {
return true
}
return false
} catch (error) {
return false
}
}
}
/**
* * 预览地址
* @returns
*/
export const previewPath = (id?: string | number) => {
const { origin, pathname } = document.location
const path = fetchPathByName(PreviewEnum.CHART_PREVIEW_NAME, 'href')
const previewPath = `${origin}${pathname}${path}/${id || fetchRouteParamsLocation()}`
return previewPath
}

View File

@@ -68,3 +68,41 @@ export const getSessionStorage: (k: string) => any = (k: string) => {
export const clearSessioStorage = (name: string) => {
window.sessionStorage.removeItem(name)
}
/**
* * 设置 cookie
* @param name 键名
* @param cvalue 键值
* @param exdays 过期时间
*/
export const setCookie = (name: string, cvalue: string, exdays: number) => {
const d = new Date();
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
const expires = "expires=" + d.toUTCString();
document.cookie = name + "=" + cvalue + "; " + expires;
}
/**
* * 获取 cookie
* @param cname 键名
* @returns string
*/
export const getCookie = (cname: string) => {
const name = cname + "=";
const ca = document.cookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1);
if (c.indexOf(name) != -1) return c.substring(name.length, c.length);
}
return "";
}
/**
* * 清除 cookie
* @param name 键名
* @returns string
*/
export const clearCookie = (name: string) => {
setCookie(name, "", -1);
}

View File

@@ -113,29 +113,6 @@ export const isMac = () => {
return /macintosh|mac os x/i.test(navigator.userAgent)
}
/**
* * file转url
*/
export const fileToUrl = (file: File): string => {
const Url = URL || window.URL || window.webkitURL
const ImageUrl = Url.createObjectURL(file)
return ImageUrl
}
/**
* * file转base64
*/
export const fileTobase64 = (file: File, callback: Function) => {
let reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = function (e: ProgressEvent<FileReader>) {
if (e.target) {
let base64 = e.target.result
callback(base64)
}
}
}
/**
* * 挂载监听
*/

View File

@@ -1,35 +1,41 @@
<template>
<div class="go-content-charts-item-box" :class="{ double: chartMode === ChartModeEnum.DOUBLE }">
<!-- 每一项组件的渲染 -->
<div class="go-content-charts-item-animation-patch">
<div
class="item-box"
v-for="(item, index) in menuOptions"
:key="index"
draggable
@dragstart="dragStartHandle($event, item)"
@dragend="dragendHandle"
@dblclick="dblclickHandle(item)"
ref="contentChartsItemBoxRef"
class="go-content-charts-item-box"
:class="[chartMode === ChartModeEnum.DOUBLE ? 'double' : 'single']"
>
<div class="list-header">
<mac-os-control-btn class="list-header-control-btn" :mini="true" :disabled="true"></mac-os-control-btn>
<n-text class="list-header-text" depth="3">
<n-ellipsis>{{ item.title }}</n-ellipsis>
</n-text>
</div>
<div class="list-center go-flex-center">
<img class="list-img" v-lazy="item.image" alt="图表图片" />
</div>
<div class="list-bottom">
<n-text class="list-bottom-text" depth="3">
<n-ellipsis style="max-width: 90%">{{ item.title }}</n-ellipsis>
</n-text>
<!-- 每一项组件的渲染 -->
<div
class="item-box"
v-for="(item, index) in menuOptions"
:key="index"
draggable
@dragstart="dragStartHandle($event, item)"
@dragend="dragendHandle"
@dblclick="dblclickHandle(item)"
>
<div class="list-header">
<mac-os-control-btn class="list-header-control-btn" :mini="true" :disabled="true"></mac-os-control-btn>
<n-text class="list-header-text" depth="3">
<n-ellipsis>{{ item.title }}</n-ellipsis>
</n-text>
</div>
<div class="list-center go-flex-center go-transition">
<img class="list-img" v-lazy="item.image" alt="图表图片" />
</div>
<div class="list-bottom">
<n-text class="list-bottom-text" depth="3">
<n-ellipsis style="max-width: 90%">{{ item.title }}</n-ellipsis>
</n-text>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { PropType, ref, Ref, computed } from 'vue'
import { PropType, watch, ref, Ref, computed, nextTick } from 'vue'
import { MacOsControlBtn } from '@/components/Tips/MacOsControlBtn/index'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
@@ -51,6 +57,7 @@ defineProps({
})
const chartLayoutStore = useChartLayoutStore()
const contentChartsItemBoxRef = ref()
// 组件展示状态
const chartMode: Ref<ChartModeEnum> = computed(() => {
@@ -92,21 +99,38 @@ const dblclickHandle = async (item: ConfigType) => {
window['$message'].warning(`图表正在研发中, 敬请期待...`)
}
}
watch(
() => chartMode.value,
(newValue: ChartModeEnum) => {
if (newValue === ChartModeEnum.DOUBLE) {
nextTick(() => {
contentChartsItemBoxRef.value.classList.add('miniAnimation')
})
}
}
)
</script>
<style lang="scss" scoped>
/* 列表项宽度 */
$itemWidth: 100%;
$maxItemWidth: 180px;
$halfItemWidth: 46%;
/* 内容高度 */
$centerHeight: 100px;
$halfCenterHeight: 50px;
@include go('content-charts-item-animation-patch') {
padding: 10px;
}
@include go('content-charts-item-box') {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: 9px;
padding: 10px;
transition: all 0.7s linear;
.item-box {
margin: 0;
width: $itemWidth;
@@ -115,7 +139,6 @@ $halfCenterHeight: 50px;
cursor: pointer;
border: 1px solid rgba(0, 0, 0, 0);
@include fetch-bg-color('background-color2');
@extend .go-transition;
&:hover {
@include hover-border-color('background-color4');
.list-img {
@@ -152,7 +175,11 @@ $halfCenterHeight: 50px;
}
}
}
/* 缩小展示 */
&.single {
.item-box {
@extend .go-transition;
}
}
&.double {
.list-header {
padding: 2px 5px;
@@ -165,6 +192,7 @@ $halfCenterHeight: 50px;
}
.item-box {
width: $halfItemWidth;
max-width: $maxItemWidth;
}
.list-center {
height: $halfCenterHeight;
@@ -172,11 +200,24 @@ $halfCenterHeight: 50px;
.list-img {
height: $halfCenterHeight;
width: auto;
transition: all 0.2s;
}
}
.list-bottom {
display: block;
}
}
/* 缩小展示 */
@keyframes miniAnimation {
from {
width: $itemWidth * 2;
}
to {
width: $itemWidth;
}
}
&.miniAnimation {
animation: miniAnimation 0.5s;
}
}
</style>

View File

@@ -131,16 +131,20 @@ import { backgroundImageSize } from '@/settings/designSetting'
import { FileTypeEnum } from '@/enums/fileTypeEnum'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
import { useSystemStore } from '@/store/modules/systemStore/systemStore'
import { StylesSetting } from '@/components/Pages/ChartItemSetting'
import { UploadCustomRequestOptions } from 'naive-ui'
import { fileToUrl, loadAsyncComponent } from '@/utils'
import { loadAsyncComponent, fetchRouteParamsLocation } from '@/utils'
import { PreviewScaleEnum } from '@/enums/styleEnum'
import { ResultEnum } from '@/enums/httpEnum'
import { icon } from '@/plugins'
import { uploadFile} from '@/api/path'
const { ColorPaletteIcon } = icon.ionicons5
const { ScaleIcon, FitToScreenIcon, FitToHeightIcon, FitToWidthIcon } = icon.carbon
const chartEditStore = useChartEditStore()
const systemStore = useSystemStore()
const canvasConfig = chartEditStore.getEditCanvasConfig
const editCanvas = chartEditStore.getEditCanvas
@@ -268,11 +272,30 @@ const clearColor = () => {
// 自定义上传操作
const customRequest = (options: UploadCustomRequestOptions) => {
const { file } = options
nextTick(() => {
nextTick(async () => {
if (file.file) {
const ImageUrl = fileToUrl(file.file)
chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.BACKGROUND_IMAGE, ImageUrl)
chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.SELECT_COLOR, false)
// 修改名称
const newNameFile = new File(
[file.file],
`${fetchRouteParamsLocation()}_index_background.png`,
{ type: file.file.type }
)
let uploadParams = new FormData()
uploadParams.append('object', newNameFile)
const uploadRes = await uploadFile(uploadParams)
if(uploadRes && uploadRes.code === ResultEnum.SUCCESS) {
chartEditStore.setEditCanvasConfig(
EditCanvasConfigEnum.BACKGROUND_IMAGE,
`${systemStore.getFetchInfo.OSSUrl}${uploadRes.data.fileName}?time=${new Date().getTime()}`
)
chartEditStore.setEditCanvasConfig(
EditCanvasConfigEnum.SELECT_COLOR,
false
)
return
}
window['$message'].error('添加图片失败,请稍后重试!')
} else {
window['$message'].error('添加图片失败,请稍后重试!')
}

View File

@@ -1,7 +1,7 @@
<template>
<div class="go-chart-configurations-animations" v-if="targetData">
<n-button
class="clear-btn"
class="clear-btn go-my-2"
:disabled="!targetData.styles.animations.length"
@click="clearAnimation"
>
@@ -72,7 +72,7 @@ const addAnimation = (item: { label: string; value: string }) => {
<style lang="scss" scoped>
@include go('chart-configurations-animations') {
padding: 20px 10px;
padding: 0;
.clear-btn {
width: 100%;
}

View File

@@ -12,7 +12,7 @@
<n-input size="small" :placeholder="targetData.request.requestHttpType || '暂无'" :disabled="true"></n-input>
</setting-item>
<setting-item name="组件间隔(高级)">
<setting-item name="组件间隔">
<n-input size="small" :placeholder="`${targetData.request.requestInterval || '暂无'}`" :disabled="true">
<template #suffix> {{ SelectHttpTimeNameObj[targetData.request.requestIntervalUnit] }} </template>
</n-input>
@@ -41,13 +41,9 @@
</n-input>
</setting-item-box>
<n-space justify="end">
<n-text depth="3" style="font-size: 12px">更新内容请点击展示区域</n-text>
</n-space>
<div class="edit-text" @click="requestModelHandle">
<div class="go-absolute-center">
<n-button type="primary" secondary>查看更多</n-button>
<n-button type="primary" secondary>编辑配置</n-button>
</div>
</div>
</n-card>
@@ -76,10 +72,16 @@
<!-- 底部数据展示 -->
<chart-data-matching-and-show :show="showMatching && !loading" :ajax="true"></chart-data-matching-and-show>
<!-- 骨架图 -->
<go-skeleton :load="loading" :repeat="3"></go-skeleton>
<!-- 请求配置model -->
<chart-data-request v-model:modelShow="requestShow" @sendHandle="sendHandle"></chart-data-request>
<chart-data-request
v-model:modelShow="requestShow"
:targetData="targetData"
@sendHandle="sendHandle"
></chart-data-request>
</div>
</template>
@@ -95,7 +97,7 @@ import { http, customizeHttp } from '@/api/http'
import { SelectHttpType } from '../../index.d'
import { ChartDataMatchingAndShow } from '../ChartDataMatchingAndShow'
import { useTargetData } from '../../../hooks/useTargetData.hook'
import { isDev, newFunctionHandle } from '@/utils'
import { newFunctionHandle } from '@/utils'
const { HelpOutlineIcon, FlashIcon, PulseIcon } = icon.ionicons5
const { targetData, chartEditStore } = useTargetData()
@@ -128,7 +130,7 @@ const sendHandle = async () => {
const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.getRequestGlobalConfig))
loading.value = false
if (res) {
if(!res?.data && !targetData.value.filter) window['$message'].warning('您的数据不符合默认格式,请配置过滤器!')
if (!res?.data && !targetData.value.filter) window['$message'].warning('您的数据不符合默认格式,请配置过滤器!')
targetData.value.option.dataset = newFunctionHandle(res?.data, res, targetData.value.filter)
showMatching.value = true
return
@@ -175,7 +177,7 @@ onBeforeUnmount(() => {
top: 0px;
left: 0px;
width: 325px;
height: 292px;
height: 270px;
cursor: pointer;
opacity: 0;
transition: all 0.3s;

View File

@@ -117,7 +117,7 @@ const { uploadFileListRef, customRequest, beforeUpload, download } = useFile(tar
// 是否展示过滤器
const filterShow = computed(() => {
return targetData.value.request.requestDataType === RequestDataTypeEnum.AJAX
return targetData.value.request.requestDataType !== RequestDataTypeEnum.STATIC
})
// 是支持 dataset 的图表类型

View File

@@ -34,7 +34,7 @@
</template>
<!-- 弹窗 -->
<n-modal class="go-chart-data-monaco-editor" v-model:show="showModal" :mask-closable="false">
<n-modal class="go-chart-data-monaco-editor" v-model:show="showModal" :mask-closable="false" :closeOnEsc="false">
<n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 1000px; height: 600px">
<template #header>
<n-space>
@@ -101,7 +101,7 @@
</template>
<script lang="ts" setup>
import { ref, computed, watch, toRefs, toRaw } from 'vue'
import { ref, computed, watch, toRef, toRefs, toRaw, reactive } from 'vue'
import { useTargetData } from '../../../hooks/useTargetData.hook'
import { MonacoEditor } from '@/components/Pages/MonacoEditor'
import { icon } from '@/plugins'
@@ -187,7 +187,10 @@ const saveFilter = () => {
watch(
() => showModal.value,
(newData: boolean) => {
if (newData) fetchTargetData()
if (newData) {
fetchTargetData()
filter.value = targetData.value.filter || `return data`
}
}
)
</script>

View File

@@ -0,0 +1,64 @@
<template>
<n-table
:bordered="false"
:single-line="false"
size="small"
style="border-bottom-right-radius: 7px; border-bottom-left-radius: 7px"
>
<thead>
<tr>
<th>key</th>
<th>value</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in tableArray.content" :key="index">
<td>
{{ item.key || '暂无'}}
</td>
<td>
{{ item.value || '暂无'}}
</td>
</tr>
</tbody>
</n-table>
</template>
<script setup lang="ts">
import { PropType, reactive, ref, toRefs, watch } from 'vue'
import { RequestParamsObjType } from '@/enums/httpEnum'
import noData from '@/assets/images/canvas/noData.png'
const props = defineProps({
target: Object as PropType<RequestParamsObjType>
})
// 默认表格
const defaultItem = {
key: '',
value: ''
}
const tableArray = reactive<{
content: typeof defaultItem[]
}>({ content: [] })
// 监听选项
watch(
() => props.target as RequestParamsObjType,
(target: RequestParamsObjType) => {
tableArray.content = []
for (const k in target) {
tableArray.content.push({
key: k,
value: target[k]
})
}
// 默认值
if (!tableArray.content.length) tableArray.content = [JSON.parse(JSON.stringify(defaultItem))]
},
{
immediate: true,
deep: true
}
)
</script>

View File

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

View File

@@ -0,0 +1,191 @@
<template>
<div class="go-chart-data-display">
<n-scrollbar style="max-height: 570px">
<div class="go-mr-3">
<div>
<setting-item-box name="主体信息">
<setting-item name="接口名称">
<n-input size="small" :placeholder="targetData?.dataPondName || '暂无'" :disabled="true"> </n-input>
</setting-item>
<setting-item name="接口类型">
<n-input size="small" :placeholder="requestHttpType || '暂无'" :disabled="true"></n-input>
</setting-item>
</setting-item-box>
<setting-item-box>
<setting-item name="组件间隔">
<n-input size="small" :placeholder="`${requestInterval || '暂无'}`" :disabled="true">
<template #suffix>
{{ targetData && SelectHttpTimeNameObj[requestIntervalUnit] }}
</template>
</n-input>
</setting-item>
<setting-item name="全局间隔(默认)">
<n-input size="small" :placeholder="`${globalData?.requestInterval || '暂无'}`" :disabled="true">
<template #suffix> {{ globalData && SelectHttpTimeNameObj[globalData.requestIntervalUnit] }} </template>
</n-input>
</setting-item>
</setting-item-box>
<setting-item-box name="源地址" :alone="true">
<n-input size="small" :placeholder="globalData?.requestOriginUrl || '暂无'" :disabled="true">
<template #prefix>
<n-icon :component="PulseIcon" />
</template>
</n-input>
</setting-item-box>
<setting-item-box name="接口地址" :alone="true">
<n-input
size="small"
:placeholder="requestUrl || '暂无'"
:disabled="true"
>
<template #prefix>
<n-icon :component="FlashIcon" />
</template>
</n-input>
</setting-item-box>
</div>
<n-divider />
<setting-item-box name="类型">
<setting-item name="配置类型">
<n-input
size="small"
:placeholder="targetData && requestContentTypeObj[requestContentType]"
:disabled="true"
></n-input>
</setting-item>
<setting-item name="body 类型" v-if="requestContentType === RequestContentTypeEnum.DEFAULT">
<n-input size="small" :placeholder="targetData && requestParamsBodyType" :disabled="true"></n-input>
</setting-item>
</setting-item-box>
<div v-if="requestContentType === RequestContentTypeEnum.DEFAULT">
<n-tabs type="line" animated v-model:value="tabValue">
<n-tab v-for="item in RequestParamsTypeEnum" :key="item" :name="item" :tab="item"> {{ item }} </n-tab>
</n-tabs>
<!-- 各个页面 -->
<div class="go-mt-3">
<div v-if="tabValue !== RequestParamsTypeEnum.BODY">
<display-table class="go-my-3" :target="requestParams[tabValue]"> </display-table>
</div>
<!-- 选择了 body -->
<div v-else>
<!-- none -->
<n-card class="go-mt-3 go-pb-3" v-if="requestParamsBodyType === RequestBodyEnum['NONE']">
<n-text depth="3">该接口没有 Body </n-text>
</n-card>
<!-- 具有对象属性时 -->
<template
v-else-if="
requestParamsBodyType === RequestBodyEnum['FORM_DATA'] ||
requestParamsBodyType === RequestBodyEnum['X_WWW_FORM_URLENCODED']
"
>
<display-table
class="go-my-3"
:target="requestParams[RequestParamsTypeEnum.BODY][requestParamsBodyType]"
></display-table>
</template>
<!-- json -->
<template v-else-if="requestParamsBodyType === RequestBodyEnum['JSON']">
<n-card size="small" style="padding-bottom: 7px">
<n-code
:code="requestParams[RequestParamsTypeEnum.BODY][requestParamsBodyType] || '暂无内容'"
language="json"
></n-code>
</n-card>
</template>
<!-- xml -->
<template v-else-if="requestParamsBodyType === RequestBodyEnum['XML']">
<n-code
:code="requestParams[RequestParamsTypeEnum.BODY][requestParamsBodyType] || ''"
language="html"
></n-code>
</template>
</div>
</div>
</div>
<!-- SQL 请求 -->
<div v-else>
<setting-item-box name="键名">
<n-text>sql</n-text>
</setting-item-box>
<setting-item-box name="键值">
<n-code :code="requestSQLContent.sql || ''" language="sql"></n-code>
</setting-item-box>
</div>
</div>
</n-scrollbar>
</div>
</template>
<script setup lang="ts">
import { PropType, ref, toRefs } from 'vue'
import { icon } from '@/plugins'
import { MonacoEditor } from '@/components/Pages/MonacoEditor'
import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { RequestDataPondItemType, RequestGlobalConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
import displayTable from './displayTable.vue'
import {
RequestBodyEnum,
RequestParamsTypeEnum,
SelectHttpTimeNameObj,
RequestContentTypeEnum,
RequestBodyEnumList,
RequestParamsObjType
} from '@/enums/httpEnum'
const props = defineProps({
globalData: Object as PropType<RequestGlobalConfigType>,
targetData: Object as PropType<RequestDataPondItemType>
})
const { HelpOutlineIcon, FlashIcon, PulseIcon } = icon.ionicons5
const {
requestUrl,
requestInterval,
requestHttpType,
requestContentType,
requestSQLContent,
requestParams,
requestParamsBodyType,
requestIntervalUnit
} = toRefs((props.targetData as RequestDataPondItemType).dataPondRequestConfig)
const tabs = [RequestParamsTypeEnum.HEADER]
const requestContentTypeObj = {
[RequestContentTypeEnum.DEFAULT]: '普通请求',
[RequestContentTypeEnum.SQL]: 'SQL 请求'
}
const tabValue = ref<RequestParamsTypeEnum>(RequestParamsTypeEnum.PARAMS)
// 更新参数表格数据
const updateRequestParams = (paramsObj: RequestParamsObjType) => {
if (tabValue.value !== RequestParamsTypeEnum.BODY) {
requestParams.value[tabValue.value] = paramsObj
}
}
// 更新参数表格数据
const updateRequestBodyTable = (paramsObj: RequestParamsObjType) => {
if (
tabValue.value === RequestParamsTypeEnum.BODY &&
// 仅有两种类型有 body
(requestParamsBodyType.value === RequestBodyEnum.FORM_DATA ||
requestParamsBodyType.value === RequestBodyEnum.X_WWW_FORM_URLENCODED)
) {
requestParams.value[RequestParamsTypeEnum.BODY][requestParamsBodyType.value] = paramsObj
}
}
</script>
<style lang="scss" scoped>
@include go('chart-data-display') {
flex: 1;
}
</style>

View File

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

View File

@@ -0,0 +1,230 @@
<template>
<n-modal class="go-chart-data-pond-control" v-model:show="modelShow" :mask-closable="false">
<n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 900px; height: 650px">
<template #header></template>
<template #header-extra> </template>
<div class="pond-content">
<!-- 展示区域 -->
<chart-data-display
v-if="pondData && !loading"
:targetData="pondData"
:globalData="chartEditStore.getRequestGlobalConfig"
></chart-data-display>
<!-- 无数据 -->
<div v-else class="no-data go-flex-center">
<img :src="noData" alt="暂无数据" />
<n-text :depth="3">暂未选择公共接口</n-text>
</div>
<!-- 左侧列表 -->
<chart-data-pond-list @createPond="createPond" @deletePond="deletePond"></chart-data-pond-list>
</div>
<!-- 底部 -->
<template #action>
<n-space justify="space-between">
<n-button type="info" secondary :disabled="!pondData" @click="openPond(true)">
编辑内容
<template #icon>
<n-icon>
<pencil-icon />
</n-icon>
</template>
</n-button>
<n-button type="primary" @click="closeHandle">保存 & 发送请求</n-button>
</n-space>
</template>
</n-card>
</n-modal>
<!-- 请求配置model -->
<pond-data-request
v-if="requestShow"
v-model:modelShow="requestShow"
:targetDataRequest="editData"
:isEdit="isEdit"
@editSaveHandle="saveHandle"
></pond-data-request>
</template>
<script setup lang="ts">
import { ref, toRefs, computed, nextTick, watch, toRaw } from 'vue'
import noData from '@/assets/images/canvas/noData.png'
import { ChartDataPondList } from '../ChartDataPondList'
import { PondDataRequest } from '../../../ChartDataRequest'
import { ChartDataDisplay } from '../ChartDataDisplay'
import { requestConfig } from '@/packages/public/publicConfig'
import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook'
import { RequestDataPondItemType } from '@/store/modules/chartEditStore/chartEditStore.d'
import { RequestDataTypeEnum } from '@/enums/httpEnum'
import { icon } from '@/plugins'
import { getUUID, goDialog } from '@/utils'
import { cloneDeep } from 'lodash'
defineProps({
modelShow: Boolean
})
const emit = defineEmits(['update:modelShow', 'sendHandle'])
const { PencilIcon } = icon.ionicons5
const { chartEditStore, targetData } = useTargetData()
const { requestDataPond } = toRefs(chartEditStore.getRequestGlobalConfig)
const requestShow = ref(false)
const loading = ref(false)
const isEdit = ref(false)
const editData = ref<RequestDataPondItemType>()
// 所选数据池
const pondData = computed(() => {
const selectId = targetData?.value?.request?.requestDataPondId
if (!selectId) return undefined
const data = requestDataPond.value.filter(item => {
return selectId === item.dataPondId
})
return data[0]
})
watch(
() => pondData.value,
newValue => {
loading.value = true
editData.value = newValue
nextTick(() => {
loading.value = false
})
},
{
immediate: true
}
)
// 打开/编辑
const openPond = (isEditFlag: boolean = false) => {
isEdit.value = !!isEditFlag
requestShow.value = true
}
// 创建
const createPond = () => {
const id = getUUID()
editData.value = {
dataPondId: id,
dataPondName: id,
dataPondRequestConfig: cloneDeep({ ...requestConfig, requestDataType: RequestDataTypeEnum.Pond })
}
openPond()
}
// 完成创建/编辑
const saveHandle = (newData: RequestDataPondItemType) => {
// 走创建
if (isEdit.value) {
editSaveHandle(newData)
} else {
createSaveHandle(newData)
}
isEdit.value = false
requestShow.value = false
}
// 编辑保存之后
const editSaveHandle = (newData: RequestDataPondItemType) => {
try {
const targetIndex = requestDataPond.value.findIndex(item => item.dataPondId === newData.dataPondId)
if (targetIndex !== -1) {
requestDataPond.value.splice(targetIndex, 1, newData)
// 修改数据池后, 修改所有关联的组件
chartEditStore.getComponentList.forEach(item => {
if (
item.request.requestDataType === RequestDataTypeEnum.Pond &&
item.request.requestDataPondId === newData.dataPondId
) {
item.request = {
...toRaw(newData.dataPondRequestConfig),
requestDataPondId: newData.dataPondId
}
}
})
window.$message.success('保存成功!')
} else {
window.$message.error('编辑失败,请稍后重试!')
}
} catch (error) {
window.$message.error('编辑失败,请稍后重试!')
}
}
// 创建保存成功之后
const createSaveHandle = (newData: RequestDataPondItemType) => {
try {
if (editData.value) {
requestDataPond.value.unshift(newData)
window.$message.success('创建成功!')
} else {
window.$message.error('创建失败,请稍后重试!')
}
} catch (error) {
window.$message.error('创建失败,请稍后重试!')
}
}
// 删除数据池
const deletePond = (targetData: RequestDataPondItemType) => {
goDialog({
message: '删除数据后,需手动处理使用改接口的组件,是否继续?',
isMaskClosable: true,
transformOrigin: 'center',
onPositiveCallback: () => {
const targetIndex = requestDataPond.value.findIndex(item => item.dataPondId === targetData.dataPondId)
if (targetIndex !== -1) {
requestDataPond.value.splice(targetIndex, 1)
window.$message.success('删除成功!')
} else {
window.$message.error('删除失败,请稍后重试!')
}
}
})
}
// 关闭
const closeHandle = () => {
// 将所选内容赋值给对象
if (pondData.value) {
targetData.value.request = {
...toRaw(pondData.value.dataPondRequestConfig),
requestDataPondId: pondData.value.dataPondId
}
}
emit('update:modelShow', false)
emit('sendHandle')
}
</script>
<style lang="scss" scoped>
@include go('chart-data-pond-control') {
/* 中间 */
.pond-content {
display: flex;
}
.no-data {
flex-direction: column;
width: 100%;
img {
width: 200px;
}
}
&.n-card.n-modal,
.n-card {
@extend .go-background-filter;
}
.n-card-shallow {
background-color: rgba(0, 0, 0, 0) !important;
}
@include deep() {
& > .n-card__content {
padding-right: 0;
}
.n-card__content {
padding-bottom: 5px;
}
}
}
</style>

View File

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

View File

@@ -0,0 +1,202 @@
<template>
<div class="go-chart-data-pond-list">
<n-timeline style="width: 20px">
<n-timeline-item type="info"> </n-timeline-item>
<n-timeline-item type="success"></n-timeline-item>
</n-timeline>
<div class="pond-item-box">
<!-- 新增 -->
<n-button class="create-btn go-py-4" ghost @click="createPond">
<span> 创建 </span>
<template #icon>
<n-icon>
<DuplicateOutlineIcon></DuplicateOutlineIcon>
</n-icon>
</template>
</n-button>
<n-divider style="margin: 10px 0"></n-divider>
<n-space v-if="!requestDataPond.length" justify="center">
<n-text class="not-layer-text" :depth="3">
暂无数据内容
<n-a @click="createPond">立即创建</n-a>
</n-text>
</n-space>
<n-scrollbar style="max-height: 490px">
<div
v-for="item in requestDataPond"
:key="item.dataPondId"
:class="{ select: item.dataPondId === selectPondId }"
class="pond-item"
@click="clickHandle(item)"
>
<div class="item-content">
<div class="item-content-body">
<div>
<n-tag class="go-mr-1" :type="item.dataPondId === selectPondId ? 'warning' : ''" :bordered="false">
名称
</n-tag>
<n-ellipsis style="max-width: 180px">
{{ item.dataPondName || '暂无' }}
</n-ellipsis>
</div>
<div>
<n-tag class="go-mr-1" :type="item.dataPondId === selectPondId ? 'warning' : ''" :bordered="false">
地址
</n-tag>
<n-ellipsis style="max-width: 180px">
{{ item.dataPondRequestConfig.requestUrl || '暂无' }}
</n-ellipsis>
</div>
</div>
<div class="item-content-icon go-transition-quick" @click="deletePond($event, item)">
<n-icon>
<trash-icon></trash-icon>
</n-icon>
</div>
</div>
<div :class="{ 'select-modal': item.dataPondId === selectPondId }"></div>
</div>
</n-scrollbar>
</div>
</div>
</template>
<script setup lang="ts">
import { toRefs, computed } from 'vue'
import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook'
import { useDesignStore } from '@/store/modules/designStore/designStore'
import { RequestDataPondItemType } from '@/store/modules/chartEditStore/chartEditStore.d'
import { icon } from '@/plugins'
const emit = defineEmits(['createPond', 'deletePond'])
const { DuplicateOutlineIcon, TrashIcon } = icon.ionicons5
const designStore = useDesignStore()
const { chartEditStore, targetData } = useTargetData()
const { requestDataPond } = toRefs(chartEditStore.getRequestGlobalConfig)
// 选中的全局数据
const selectPondId = computed(() => {
return targetData.value.request.requestDataPondId
})
// 颜色
const themeColor = computed(() => {
return designStore.getAppTheme
})
// 创建数据池
const createPond = () => {
emit('createPond', true)
}
// 删除数据池
const deletePond = (target: Event, targetData: RequestDataPondItemType) => {
target.stopPropagation()
target.preventDefault()
emit('deletePond', targetData)
}
// 选中
const clickHandle = (item: RequestDataPondItemType) => {
targetData.value.request.requestDataPondId = item.dataPondId
}
</script>
<style scoped lang="scss">
$height: 530px;
$listWidth: 280px;
$centerHeight: 60px;
$centerMiniHeight: 28px;
$textSize: 10px;
@include go('chart-data-pond-list') {
padding-top: 10px;
padding-bottom: 5px;
margin-right: 5px;
display: flex;
@include deep() {
.n-timeline > .n-timeline-item {
&:first-child {
height: $height;
}
}
}
.pond-item-box {
width: $listWidth;
position: relative;
.create-btn {
width: calc(#{$listWidth - 15px});
margin-right: 15px;
}
.pond-item {
position: relative;
height: $centerHeight;
padding: 5px;
margin-bottom: 10px;
margin-right: 15px;
border-radius: 5px;
cursor: pointer;
border: 1px solid rgba(0, 0, 0, 0);
@include fetch-bg-color('background-color3');
@extend .go-transition-quick;
&.hover,
&:hover {
@include fetch-bg-color('background-color4');
}
&:hover {
@include deep() {
.icon-item {
opacity: 1;
}
}
.item-content-icon {
opacity: 1 !important;
}
}
&.select {
border: 1px solid v-bind('themeColor');
background-color: rgba(0, 0, 0, 0);
.item-content-icon {
display: none;
}
}
.select-modal,
.item-content {
position: absolute;
top: 0;
left: 0;
}
.item-content {
z-index: 1;
display: flex;
justify-content: space-between;
align-items: center;
padding: 5px;
.item-content-body {
width: 230px;
display: flex;
flex-direction: column;
gap: 5px;
}
.item-content-icon {
opacity: 0;
height: $centerHeight;
line-height: $centerHeight;
padding-left: 5px;
}
}
.select-modal {
width: 100%;
height: 100%;
opacity: 0.3;
background-color: v-bind('themeColor');
}
}
}
}
</style>

View File

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

View File

@@ -0,0 +1,185 @@
<template>
<!-- 选中内容 -->
<div class="go-chart-data-pond">
<n-card class="n-card-shallow">
<setting-item-box name="请求名称" :alone="true">
<n-input size="small" :placeholder="pondData?.dataPondName || '暂无'" :disabled="true">
<template #prefix>
<n-icon :component="FishIcon" />
</template>
</n-input>
</setting-item-box>
<setting-item-box name="接口地址" :alone="true">
<n-input size="small" :placeholder="pondData?.dataPondRequestConfig.requestUrl || '暂无'" :disabled="true">
<template #prefix>
<n-icon :component="FlashIcon" />
</template>
</n-input>
</setting-item-box>
<div class="edit-text" @click="controlModelHandle">
<div class="go-absolute-center">
<n-button type="primary" secondary>编辑配置</n-button>
</div>
</div>
</n-card>
</div>
<setting-item-box :alone="true">
<template #name>
测试
<n-tooltip trigger="hover">
<template #trigger>
<n-icon size="21" :depth="3">
<help-outline-icon></help-outline-icon>
</n-icon>
</template>
默认赋值给 dataset 字段
</n-tooltip>
</template>
<n-button type="primary" ghost @click="sendHandle">
<template #icon>
<n-icon>
<flash-icon />
</n-icon>
</template>
发送请求
</n-button>
</setting-item-box>
<!-- 底部数据展示 -->
<chart-data-matching-and-show :show="showMatching && !loading" :ajax="true"></chart-data-matching-and-show>
<!-- 骨架图 -->
<go-skeleton :load="loading" :repeat="3"></go-skeleton>
<!-- 编辑 / 新增弹窗 -->
<chart-data-pond-control v-model:modelShow="controlModel" @sendHandle="sendHandle"></chart-data-pond-control>
</template>
<script setup lang="ts">
import { ref, toRefs, toRaw, onBeforeUnmount, computed, watchEffect } from 'vue'
import { icon } from '@/plugins'
import { http, customizeHttp } from '@/api/http'
import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { ChartDataPondControl } from './components/ChartDataPondControl'
import { useDesignStore } from '@/store/modules/designStore/designStore'
import { useTargetData } from '../../../hooks/useTargetData.hook'
import { ChartDataMatchingAndShow } from '../ChartDataMatchingAndShow'
import { newFunctionHandle } from '@/utils'
const designStore = useDesignStore()
const { HelpOutlineIcon, FlashIcon, PulseIcon, FishIcon } = icon.ionicons5
const { targetData, chartEditStore } = useTargetData()
const {
requestDataPond,
requestInterval: GlobalRequestInterval,
requestIntervalUnit: GlobalRequestIntervalUnit
} = toRefs(chartEditStore.getRequestGlobalConfig)
const loading = ref(false)
const controlModel = ref(false)
const showMatching = ref(false)
let firstFocus = 0
let lastFilter: any = undefined
// 所选数据池
const pondData = computed(() => {
const selectId = targetData.value.request.requestDataPondId
if (!selectId) return undefined
const data = requestDataPond.value.filter(item => {
return selectId === item.dataPondId
})
return data[0]
})
// 颜色
const themeColor = computed(() => {
return designStore.getAppTheme
})
// 请求配置 model
const controlModelHandle = () => {
controlModel.value = true
}
// 发送请求
const sendHandle = async () => {
if (!targetData.value?.request) {
window.$message.warning('请选择一个公共接口!')
return
}
loading.value = true
try {
// const res = await customizeHttp(
// toRaw(pondData.value?.dataPondRequestConfig),
// toRaw(chartEditStore.getRequestGlobalConfig)
// )
const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.getRequestGlobalConfig))
loading.value = false
if (res) {
if (!res?.data && !targetData.value.filter) window['$message'].warning('您的数据不符合默认格式,请配置过滤器!')
targetData.value.option.dataset = newFunctionHandle(res?.data, res, targetData.value.filter)
showMatching.value = true
return
}
window['$message'].warning('数据异常,请检查参数!')
} catch (error) {
loading.value = false
window['$message'].warning('数据异常,请检查参数!')
}
}
watchEffect(() => {
const filter = targetData.value?.filter
if (lastFilter !== filter && firstFocus) {
lastFilter = filter
sendHandle()
}
firstFocus++
})
onBeforeUnmount(() => {
lastFilter = null
})
</script>
<style scoped lang="scss">
@include go('chart-data-pond') {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
.n-card-shallow {
&.n-card {
@extend .go-background-filter;
@include deep() {
.n-card__content {
padding: 10px;
}
}
}
.edit-text {
position: absolute;
top: 0px;
left: 0px;
width: 325px;
height: 136px;
cursor: pointer;
opacity: 0;
transition: all 0.3s;
@extend .go-background-filter;
backdrop-filter: blur(2px) !important;
}
&:hover {
border-color: v-bind('themeColor');
.edit-text {
opacity: 1;
}
}
}
}
</style>

View File

@@ -1,7 +1,7 @@
<template>
<!-- 全局配置 -->
<n-card class="n-card-shallow">
<n-tag type="info" :bordered="false" style="border-radius: 5px"> 全局配置 </n-tag>
<n-tag type="info" :bordered="false" style="border-radius: 5px"> 全局公共配置 </n-tag>
<setting-item-box
name="服务"
:itemRightStyle="{

View File

@@ -29,7 +29,7 @@
<!-- none -->
<n-card class="go-mt-3 go-pb-3" v-if="requestParamsBodyType === RequestBodyEnum['NONE']">
<n-text depth="3">请求没有 Body </n-text>
<n-text depth="3">接口没有 Body </n-text>
</n-card>
<!-- 具有对象属性时 -->
@@ -86,13 +86,12 @@
</template>
<script setup lang="ts">
import { ref, toRefs } from 'vue'
import { ref, toRefs, PropType } from 'vue'
import { MonacoEditor } from '@/components/Pages/MonacoEditor'
import { RequestHeaderTable } from '../RequestHeaderTable/index'
import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook'
import { RequestHeaderTable } from '../RequestHeaderTable/index'
import { RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
import {
RequestParamsTypeEnum,
RequestContentTypeEnum,
@@ -102,9 +101,13 @@ import {
RequestHttpEnum
} from '@/enums/httpEnum'
const { targetData } = useTargetData()
const props = defineProps({
targetDataRequest: Object as PropType<RequestConfigType>
})
const { requestHttpType, requestContentType, requestSQLContent, requestParams, requestParamsBodyType } = toRefs(targetData.value.request)
const { requestHttpType, requestContentType, requestSQLContent, requestParams, requestParamsBodyType } = toRefs(
props.targetDataRequest as RequestConfigType
)
const tabValue = ref<RequestParamsTypeEnum>(RequestParamsTypeEnum.PARAMS)

View File

@@ -5,7 +5,7 @@
:itemRightStyle="{
gridTemplateColumns: '6fr 2fr'
}"
style="padding-right: 25px;"
style="padding-right: 25px"
>
<template #name>
地址
@@ -51,15 +51,16 @@
</setting-item>
</setting-item-box>
<setting-item-box name="选择方式" class="go-mt-0">
<request-header></request-header>
<request-header :targetDataRequest="targetDataRequest"></request-header>
</setting-item-box>
</template>
<script setup lang="ts">
import { ref, toRefs } from 'vue'
import { PropType, toRefs } from 'vue'
import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook'
import { selectTypeOptions, selectTimeOptions } from '@/views/chart/ContentConfigurations/components/ChartData/index.d'
import { RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
import { RequestHeader } from '../RequestHeader'
import { isDev } from '@/utils'
import { icon } from '@/plugins'
@@ -82,10 +83,16 @@ import {
threeEarth01Url
} from '@/api/mock'
const props = defineProps({
targetDataRequest: Object as PropType<RequestConfigType>
})
const { HelpOutlineIcon } = icon.ionicons5
const { targetData, chartEditStore } = useTargetData()
const { chartEditStore } = useTargetData()
const { requestOriginUrl } = toRefs(chartEditStore.getRequestGlobalConfig)
const { requestInterval, requestIntervalUnit, requestHttpType, requestUrl } = toRefs(targetData.value.request)
const { requestInterval, requestIntervalUnit, requestHttpType, requestUrl } = toRefs(
props.targetDataRequest as RequestConfigType
)
const apiList = [
{

View File

@@ -1,3 +1,4 @@
import ChartDataRequest from './index.vue'
import PondDataRequest from './pondIndex.vue'
export { ChartDataRequest }
export { ChartDataRequest, PondDataRequest }

View File

@@ -1,5 +1,5 @@
<template>
<n-modal class="go-chart-data-request" v-model:show="modelShow" :mask-closable="false">
<n-modal class="go-chart-data-request" v-model:show="modelShow" :mask-closable="false" :closeOnEsc="false">
<n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 1000px; height: 800px">
<template #header></template>
<template #header-extra> </template>
@@ -7,7 +7,7 @@
<div class="go-pr-3">
<n-space vertical>
<request-global-config></request-global-config>
<request-target-config></request-target-config>
<request-target-config :target-data-request="targetData?.request"></request-target-config>
</n-space>
</div>
</n-scrollbar>
@@ -17,9 +17,11 @@
<div>
<n-text> {{ chartConfig.categoryName }} </n-text>
<n-text> </n-text>
<n-tag type="primary" :bordered="false" style="border-radius: 5px"> {{ requestContentTypeObj[requestContentType] }} </n-tag>
<n-tag type="primary" :bordered="false" style="border-radius: 5px">
{{ requestContentTypeObj[requestContentType] }}
</n-tag>
</div>
<n-button type="primary" @click="closeHandle">保存 & 发送请求</n-button>
<n-button type="primary" @click="closeAndSendHandle"> {{ saveBtnText || '保存 & 发送请求' }}</n-button>
</n-space>
</template>
</n-card>
@@ -27,30 +29,40 @@
</template>
<script script lang="ts" setup>
import { toRefs } from 'vue'
import { toRefs, PropType } from 'vue'
import { RequestContentTypeEnum } from '@/enums/httpEnum'
import { useTargetData } from '../../../hooks/useTargetData.hook'
import { RequestGlobalConfig } from './components/RequestGlobalConfig'
import { RequestTargetConfig } from './components/RequestTargetConfig'
import { useSync } from '@/views/chart/hooks/useSync.hook'
import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
const props = defineProps({
modelShow: Boolean,
targetData: Object as PropType<CreateComponentType>,
saveBtnText: String || null
})
const emit = defineEmits(['update:modelShow', 'sendHandle'])
const { targetData } = useTargetData()
const { dataSyncUpdate } = useSync()
// 解构基础配置
const { chartConfig } = toRefs(targetData.value)
const { requestContentType } = toRefs(targetData.value.request)
const { chartConfig } = toRefs(props.targetData as CreateComponentType)
const { requestContentType } = toRefs((props.targetData as CreateComponentType).request)
const requestContentTypeObj = {
[RequestContentTypeEnum.DEFAULT]: '普通请求',
[RequestContentTypeEnum.SQL]: 'SQL 请求'
}
defineProps({
modelShow: Boolean
})
const closeHandle = () => {
emit('update:modelShow', false)
}
const closeAndSendHandle = () => {
emit('update:modelShow', false)
emit('sendHandle')
dataSyncUpdate()
}
</script>

View File

@@ -0,0 +1,105 @@
<template>
<n-modal class="go-chart-data-request" v-model:show="modelShow" :mask-closable="false" :closeOnEsc="false">
<n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 1000px; height: 800px">
<template #header></template>
<template #header-extra> </template>
<n-scrollbar style="max-height: 718px">
<div class="go-pr-3">
<n-space vertical>
<request-global-config></request-global-config>
<request-target-config
:target-data-request="targetDataRequest?.dataPondRequestConfig"
></request-target-config>
</n-space>
</div>
</n-scrollbar>
<!-- 底部 -->
<template #action>
<n-space justify="space-between">
<n-space v-if="targetDataRequest">
<n-tag :bordered="false" type="primary">名称</n-tag>
<n-input
v-model:value="targetDataRequest.dataPondName"
ref="inputInstRef"
type="text"
size="small"
:autofocus="true"
:clearable="true"
:minlength="1"
:maxlength="16"
placeholder="请输入名称"
></n-input>
</n-space>
<span v-else></span>
<n-space>
<n-button @click="closeHandle">取消</n-button>
<n-button type="primary" @click="closeAndSendHandle">保存</n-button>
</n-space>
</n-space>
</template>
</n-card>
</n-modal>
</template>
<script script lang="ts" setup>
import { PropType, ref, watchEffect } from 'vue'
import { RequestContentTypeEnum } from '@/enums/httpEnum'
import { useTargetData } from '../../../hooks/useTargetData.hook'
import { RequestGlobalConfig } from './components/RequestGlobalConfig'
import { RequestTargetConfig } from './components/RequestTargetConfig'
import { RequestDataPondItemType } from '@/store/modules/chartEditStore/chartEditStore.d'
import { useSync } from '@/views/chart/hooks/useSync.hook'
import { goDialog } from '@/utils'
const props = defineProps({
modelShow: Boolean,
targetDataRequest: Object as PropType<RequestDataPondItemType>
})
const emit = defineEmits(['update:modelShow', 'editSaveHandle'])
const { dataSyncUpdate } = useSync()
const pondName = ref()
const inputInstRef = ref()
const closeHandle = () => {
emit('update:modelShow', false)
}
const closeAndSendHandle = () => {
if (!props.targetDataRequest?.dataPondName) {
window.$message.warning('请在左下角输入名称!')
inputInstRef.value?.focus()
return
}
goDialog({
message: '保存内容将同步修改所有使用此接口的组件, 是否继续?',
isMaskClosable: true,
transformOrigin: 'center',
onPositiveCallback: () => {
emit('update:modelShow', false)
emit('editSaveHandle', props.targetDataRequest)
dataSyncUpdate()
}
})
}
</script>
<style lang="scss" scoped>
@include go('chart-data-request') {
&.n-card.n-modal,
.n-card {
@extend .go-background-filter;
}
.n-card-shallow {
background-color: rgba(0, 0, 0, 0) !important;
}
@include deep() {
& > .n-card__content {
padding-right: 0;
}
.n-card__content {
padding-bottom: 5px;
}
}
}
</style>

View File

@@ -16,6 +16,7 @@ export enum TimelineTitleEnum {
export enum SelectCreateDataEnum {
STATIC = '静态数据',
AJAX = '动态请求',
Pond = '公共接口',
}
export interface SelectCreateDataType {

View File

@@ -3,24 +3,27 @@
<setting-item-box name="请求方式" :alone="true">
<n-select v-model:value="targetData.request.requestDataType" :disabled="isNotData" :options="selectOptions" />
</setting-item-box>
<!-- 静态 -->
<chart-data-static v-if="targetData.request.requestDataType === RequestDataTypeEnum.STATIC"></chart-data-static>
<!-- 动态 -->
<chart-data-ajax v-else></chart-data-ajax>
<chart-data-ajax v-if="targetData.request.requestDataType === RequestDataTypeEnum.AJAX"></chart-data-ajax>
<!-- 数据池 -->
<chart-data-pond v-if="targetData.request.requestDataType === RequestDataTypeEnum.Pond"></chart-data-pond>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { loadAsyncComponent } from '@/utils'
import { SettingItemBox } from '@/components/Pages/ChartItemSetting'
import { useTargetData } from '../hooks/useTargetData.hook'
import { ChartDataStatic } from './components/ChartDataStatic/index'
import { ChartDataAjax } from './components/ChartDataAjax/index'
import { SelectCreateDataType, SelectCreateDataEnum } from './index.d'
import { RequestDataTypeEnum } from '@/enums/httpEnum'
const ChartDataStatic = loadAsyncComponent(() => import('./components/ChartDataStatic/index.vue'))
const ChartDataAjax = loadAsyncComponent(() => import('./components/ChartDataAjax/index.vue'))
const ChartDataPond = loadAsyncComponent(() => import('./components/ChartDataPond/index.vue'))
const { targetData } = useTargetData()
// 选项
@@ -32,6 +35,10 @@ const selectOptions: SelectCreateDataType[] = [
{
label: SelectCreateDataEnum.AJAX,
value: RequestDataTypeEnum.AJAX
},
{
label: SelectCreateDataEnum.Pond,
value: RequestDataTypeEnum.Pond
}
]

View File

@@ -5,6 +5,8 @@
<edit-history></edit-history>
<!-- CTRL按键触发展示 -->
<n-text id="keyboard-dress-show" depth="3"></n-text>
<n-divider vertical />
<edit-data-sync></edit-data-sync>
</n-space>
<n-space class="bottom-ri">
@@ -55,7 +57,8 @@
import { reactive, ref, toRefs, watchEffect } from 'vue'
import { icon } from '@/plugins'
import { EditHistory } from '../EditHistory/index'
import EditShortcutKey from '../EditShortcutKey/index.vue'
import { EditShortcutKey } from '../EditShortcutKey/index'
import { EditDataSync } from '../EditDataSync/index'
import { useDesignStore } from '@/store/modules/designStore/designStore'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
@@ -144,6 +147,10 @@ $max-width: 670px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 10px;
width: 100%;
min-width: $min-width;
height: 40px;
.bottom-ri {
position: relative;
top: 15px;

View File

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

View File

@@ -0,0 +1,97 @@
<template>
<div class="go-edit-data-sync go-flex-items-center">
<n-tooltip trigger="hover">
<template #trigger>
<n-text class="status-desc go-ml-2" :type="descType" depth="3">
{{ statusDesc }}
</n-text>
</template>
<span>{{saveInterval}}s 更新一次</span>
</n-tooltip>
<n-spin
v-show="statusDesc === statusDescObj[1]['text']"
class="go-ml-2"
size="small"
>
<template #icon>
<n-icon size="13">
<reload-icon />
</n-icon>
</template>
</n-spin>
</div>
</template>
<script lang="ts" setup>
import { ref, toRefs, watch } from 'vue'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { useDesignStore } from '@/store/modules/designStore/designStore'
import { SyncEnum } from '@/enums/editPageEnum'
import { icon } from '@/plugins'
import { saveInterval } from '@/settings/designSetting'
const { ReloadIcon } = icon.ionicons5
const chartEditStore = useChartEditStore()
const designStore = useDesignStore()
const { saveStatus } = toRefs(chartEditStore.getEditCanvas)
const themeColor = ref(designStore.getAppTheme)
const statusDesc = ref('')
const descType = ref('')
let setTimeoutIns: NodeJS.Timeout = setTimeout(() => {})
const statusDescObj = {
[SyncEnum.PENDING]: {
text: '等待自动同步',
type: '',
},
[SyncEnum.START]: {
text: '正在同步中',
type: 'success',
},
[SyncEnum.SUCCESS]: {
text: '同步成功!',
type: 'success',
},
[SyncEnum.FAILURE]: {
text: '同步失败!',
type: 'error',
},
}
watch(
() => saveStatus.value,
newData => {
clearTimeout(setTimeoutIns)
statusDesc.value = statusDescObj[newData]['text']
descType.value = statusDescObj[newData]['type']
// 3秒重置展示
setTimeoutIns = setTimeout(() => {
statusDesc.value = statusDescObj[SyncEnum.PENDING]['text']
descType.value = statusDescObj[SyncEnum.PENDING]['type']
}, 3000)
},
{
immediate: true,
}
)
</script>
<style lang="scss" scoped>
@include go('edit-data-sync') {
@include deep() {
.n-spin {
width: 13px;
height: 13px;
}
}
.status-desc {
cursor: default;
color: v-bind('themeColor');
font-size: 12px;
opacity: 0.8;
}
}
</style>

View File

@@ -133,9 +133,6 @@ const options = computed(() => {
</script>
<style lang="scss" scoped>
.mr-10 {
margin-right: 10px;
}
.edit-history-popover {
.btn-text {
font-size: 12px;

View File

@@ -113,20 +113,25 @@ const shortcutKeyOptions = [
win: `${WinKeyboard.CTRL.toUpperCase()} + ${WinKeyboard.SHIFT.toUpperCase()} + Z `,
mac: `${MacKeyboard.CTRL.toUpperCase()} + ${MacKeyboard.SHIFT.toUpperCase()} + Z `
},
{
label: '保存',
win: `${WinKeyboard.CTRL.toUpperCase()} + S `,
mac: `${MacKeyboard.CTRL.toUpperCase()} + S `,
},
{
label: '多选',
win: `${WinKeyboard.CTRL.toUpperCase()} + 🖱️ `,
mac: `${MacKeyboard.CTRL_SOURCE_KEY.toUpperCase()} + 🖱️ `
mac: `${MacKeyboard.CTRL.toUpperCase()} + 🖱️ `
},
{
label: '创建分组',
win: `${WinKeyboard.CTRL.toUpperCase()} + G / 🖱️ `,
mac: `${MacKeyboard.CTRL_SOURCE_KEY.toUpperCase()} + G / 🖱️`
mac: `${MacKeyboard.CTRL.toUpperCase()} + G / 🖱️`
},
{
label: '解除分组',
win: `${WinKeyboard.CTRL.toUpperCase()} + ${WinKeyboard.SHIFT.toUpperCase()} + G `,
mac: `${MacKeyboard.CTRL_SOURCE_KEY.toUpperCase()} + ${WinKeyboard.SHIFT.toUpperCase()} + G `
mac: `${MacKeyboard.CTRL.toUpperCase()} + ${WinKeyboard.SHIFT.toUpperCase()} + G `
}
]
const closeHandle = () => {

View File

@@ -1,2 +1,3 @@
import EditShortcutKey from './index.vue'
export { EditShortcutKey }

View File

@@ -7,7 +7,6 @@ import { useSync } from '@/views/chart/hooks/useSync.hook'
export const useFile = () => {
const importUploadFileListRef = ref()
const { updateComponent } = useSync()
// 上传-前置
//@ts-ignore
const importBeforeUpload = ({ file }) => {

View File

@@ -6,7 +6,7 @@ import { ChartEnum } from '@/enums/pageEnum'
import { SavePageEnum } from '@/enums/editPageEnum'
import { editToJsonInterval } from '@/settings/designSetting'
const { updateComponent } = useSync()
const { updateComponent, dataSyncUpdate } = useSync()
const chartEditStore = useChartEditStore()
// 侦听器更新
@@ -15,11 +15,17 @@ const useSyncUpdateHandle = () => {
let timer: any
const updateFn = (e: any) => updateComponent(e!.detail, true, false)
const syncData = async () => {
dataSyncUpdate && (await dataSyncUpdate())
dispatchEvent(new CustomEvent(SavePageEnum.CHART, { detail: chartEditStore.getStorageInfo }))
}
// 开启侦听
const use = () => {
// // 1、定时同步数据
// timer = setInterval(() => {
// // 窗口激活并且处于工作台
// document.hasFocus() && syncData()
// }, editToJsonInterval)
// // 1、定时同步数据
// timer = setInterval(() => {
// // 窗口激活并且处于工作台
@@ -34,6 +40,7 @@ const useSyncUpdateHandle = () => {
// 关闭侦听
const unUse = () => {
// clearInterval(timer)
// clearInterval(timer)
removeEventListener(SavePageEnum.JSON, updateFn)
removeEventListener('blur', syncData)

View File

@@ -9,7 +9,7 @@ export const exportHandle = () => {
// 导出数据
downloadTextFile(
JSON.stringify(chartEditStore.getStorageInfo || [], (k, v) => {
JSON.stringify(chartEditStore.getStorageInfo || {}, (k, v) => {
return v === undefined ? null : v
}),
undefined,

View File

@@ -91,6 +91,7 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore
import { useLayout } from './hooks/useLayout.hook'
import { useAddKeyboard } from '../hooks/useKeyboard.hook'
import { useSync } from '../hooks/useSync.hook'
import { dragHandle, dragoverHandle, mousedownHandleUnStop, useMouseHandle } from './hooks/useDrag.hook'
import { useComponentStyle, useSizeStyle } from './hooks/useStyle.hook'
@@ -104,6 +105,7 @@ import { EditTools } from './components/EditTools'
const chartEditStore = useChartEditStore()
const { handleContextMenu } = useContextMenu()
const { dataSyncFetch, intervalDataSyncUpdate } = useSync()
// 布局处理
useLayout()
@@ -172,9 +174,13 @@ const rangeStyle = computed(() => {
}
})
// 键盘事件
onMounted(() => {
// 键盘事件
useAddKeyboard()
// 获取数据
dataSyncFetch()
// 定时更新数据
intervalDataSyncUpdate()
})
</script>

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