Compare commits

...

303 Commits

Author SHA1 Message Date
奔跑的面条
4300472c93 Merge branch 'dev' into master-fetch-dev 2025-09-28 17:10:17 +08:00
奔跑的面条
4fd296cc3a Merge branch 'dev' into master-fetch-dev 2025-09-06 14:10:33 +08:00
奔跑的面条
36f5396305 !270 修复master-fetch-dev分支项目数据保存错误,导致获取项目数据时报错
Merge pull request !270 from 叶建新/N/A
2025-07-24 01:19:05 +00:00
叶建新
4ed9a5b50e update src/views/chart/hooks/useSync.hook.ts.
修复项目数据保存时,chartEditStore.getStorageInfo未执行调用,保存的是函数字符串,导致数据保存错误

Signed-off-by: 叶建新 <1170392673@qq.com>
2025-07-22 02:09:21 +00:00
奔跑的面条
3d4384a6f8 Merge branch 'dev' into master-fetch-dev 2025-06-14 22:57:06 +08:00
奔跑的面条
dd46701f6d build: 固定ruler版本 2025-04-28 16:18:44 +08:00
奔跑的面条
c47f729144 Merge branch 'dev' into master-fetch-dev 2025-04-28 16:11:51 +08:00
奔跑的面条
415b3d6f7d !265 fix: 修复已保存的饼图数据radius被watch修改为默认值bug
Merge pull request !265 from xihai777/master-fetch-dev
2025-04-28 07:31:24 +00:00
奔跑的面条
0869fd6c95 Merge branch 'dev' into master-fetch-dev 2025-04-28 15:12:54 +08:00
xihai777
e57ebb1fc1 fix: 修复已保存的饼图数据radius被watch修改为默认值bug https://gitee.com/dromara/go-view/issues/IBJ8QF 2025-04-21 18:16:57 +08:00
奔跑的面条
950344127f Merge branch 'dev' into master-fetch-dev 2025-04-15 13:47:50 +08:00
奔跑的面条
dafba45c64 build: 升级版本 2025-02-24 15:56:25 +08:00
奔跑的面条
aad77cf022 Merge branch 'dev' into master-fetch-dev 2025-02-24 15:55:43 +08:00
奔跑的面条
d504639b7d Merge branch 'dev' into master-fetch-dev 2024-12-22 13:05:20 +08:00
奔跑的面条
812141bf62 !251 update src/packages/components/Charts/Mores/Process/index.vue.
Merge pull request !251 from 初级开发人员/N/A
2024-12-22 04:57:34 +00:00
初级开发人员
4d62ea8b76 update src/packages/components/Charts/Mores/Process/index.vue.
之前那样UI值不会随着预览更新更新到UI上,接口数变了,UI不变。
前端小白不懂之前为啥要那么写,简单修改一下

Signed-off-by: 初级开发人员 <qinweiw@foxmail.com>
2024-12-17 08:35:04 +00:00
奔跑的面条
62d63c3f65 Merge branch 'dev' into master-fetch-dev 2024-12-03 08:59:52 +08:00
奔跑的面条
79a7bc0229 Merge branch 'dev' into master-fetch-dev 2024-11-26 09:58:00 +08:00
奔跑的面条
f9a8593e43 Merge branch 'dev' into master-fetch-dev 2024-11-21 20:47:58 +08:00
奔跑的面条
8a9b07ca45 Merge branch 'dev' into master-fetch-dev 2024-10-11 09:40:45 +08:00
奔跑的面条
8835d9b217 feat: change login 2024-09-24 12:21:11 +08:00
奔跑的面条
5dea9b5c5a Merge branch 'dev' into master-fetch-dev 2024-08-06 21:32:40 +08:00
奔跑的面条
c4a078cc34 Merge branch 'dev' into master-fetch-dev 2024-07-01 15:42:18 +08:00
奔跑的面条
d60a1fd979 Merge branch 'dev' into master-fetch-dev 2024-06-05 18:26:25 +08:00
奔跑的面条
9db1980f9b Merge branch 'dev' into master-fetch-dev 2024-05-27 21:14:22 +08:00
奔跑的面条
a6b3580a01 Merge branch 'dev' into master-fetch-dev 2024-05-14 12:00:14 +08:00
奔跑的面条
fbb137b3ad Merge branch 'dev' into master-fetch-dev 2024-04-26 17:00:41 +08:00
奔跑的面条
37a6ac35ff Merge branch 'dev' into master-fetch-dev 2024-04-26 10:42:45 +08:00
奔跑的面条
6447a1a3bf Merge branch 'dev' into master-fetch-dev 2024-04-26 10:11:44 +08:00
奔跑的面条
39dbc913d1 Merge branch 'dev' into master-fetch-dev 2024-04-24 14:47:27 +08:00
奔跑的面条
f69dc60e7b Merge branch 'dev' into master-fetch-dev 2024-04-19 09:42:28 +08:00
奔跑的面条
a420fc81d9 Merge branch 'dev' into master-fetch-dev 2024-04-17 10:35:47 +08:00
奔跑的面条
9c62c62820 Merge branch 'dev' into master-fetch-dev 2024-04-10 16:17:34 +08:00
奔跑的面条
a3119ff519 Merge branch 'dev' into master-fetch-dev 2024-04-10 16:13:01 +08:00
奔跑的面条
de06e42c5c Merge branch 'dev' into master-fetch-dev 2024-03-21 08:51:28 +08:00
奔跑的面条
bd5adfa922 Merge branch 'dev' into master-fetch-dev 2024-03-14 17:15:25 +08:00
奔跑的面条
f333be7f05 build: 修改版本号到2.2.8 2024-03-14 12:10:07 +08:00
奔跑的面条
ea9590441b Merge branch 'dev' into master-fetch-dev 2024-03-14 12:09:36 +08:00
奔跑的面条
1c43272719 Merge branch 'dev' into master-fetch-dev 2024-03-06 11:32:22 +08:00
奔跑的面条
2ae971d17a !222 build.brotliSize(改为了 build.reportCompressedSize)
Merge pull request !222 from uglyp/master-fetch-dev
2024-03-06 02:48:54 +00:00
qsk
272815578b fixed:build.brotliSize(改为了 build.reportCompressedSize)在 v2 当中已经标记为弃用选项,现在已经被移除 2024-01-26 09:24:52 +08:00
奔跑的面条
ff403c5e6a build: 升级版本到 2.2.7 2023-12-18 22:06:24 +08:00
奔跑的面条
d7f0986cec Merge branch 'dev' into master-fetch-dev 2023-12-17 20:46:33 +08:00
奔跑的面条
a54652c072 Merge branch 'dev' into master-fetch-dev 2023-10-08 16:00:06 +08:00
奔跑的面条
c228bc97fb fix: 补充误删的setProjectInfo代码 2023-09-18 17:15:22 +08:00
奔跑的面条
b825e41707 Merge branch 'dev' into master-fetch-dev 2023-09-18 11:45:29 +08:00
奔跑的面条
e07be55f65 build: 升级版本到2.2.6 2023-09-18 11:08:09 +08:00
奔跑的面条
b06b5f252b Merge branch 'dev' into master-fetch-dev 2023-09-18 10:51:44 +08:00
奔跑的面条
6e55c9951b !209 第三方应用open预览地址的时候,发现window.opener并不是一个window对象会报addEventListener不存在。
Merge pull request !209 from 空/N/A
2023-09-16 08:09:10 +00:00
52aeca9dd4 第三方应用open预览地址的时候,发现window.opener并不是一个window对象会报addEventListener不存在。
第三方应用open预览地址的时候,发现window.opener并不是一个window对象会报addEventListener不存在。

Signed-off-by: 空 <jinj@hxcfsoft.com>
2023-09-15 14:12:28 +00:00
奔跑的面条
87aa938e60 Merge branch 'dev' into master-fetch-dev 2023-09-13 10:44:28 +08:00
奔跑的面条
58a4a4ca17 build: 初始化依赖 2023-08-17 10:01:50 +08:00
奔跑的面条
97bb192696 Merge branch 'dev' into master-fetch-dev 2023-08-17 09:57:56 +08:00
奔跑的面条
d9fec13eae Merge branch 'dev' into master-fetch-dev 2023-07-09 17:08:50 +08:00
奔跑的面条
f4c9787807 Merge branch 'dev' into master-fetch-dev 2023-07-09 15:54:55 +08:00
奔跑的面条
6c968d9a24 build: 升级到版本 2.2.4 2023-07-08 22:03:27 +08:00
奔跑的面条
586db5aca1 Merge branch 'dev' into master-fetch-dev 2023-07-08 22:01:54 +08:00
奔跑的面条
491604527e Merge branch 'dev' into master-fetch-dev 2023-06-15 19:56:44 +08:00
奔跑的面条
70da85c1e9 !169 feat:标签选择器增加默认值选项
Merge pull request !169 from h5coder/dev-h5coder
2023-06-15 11:49:54 +00:00
奔跑的面条
9dce33ee01 !171 fix: 修复旧版本没有legend配置导致报settting color错误
Merge pull request !171 from h5coder/h5coder-fix
2023-06-15 11:45:41 +00:00
lyx
e903489a52 fix: 修复旧版本没有legend配置导致报settting color错误 2023-06-09 10:56:36 +08:00
lyx
5b932af6c8 fix:标签选择器去除多余的代码 2023-06-05 18:06:57 +08:00
lyx
84f6bfcb8a feat:标签选择器增加默认值选项 2023-06-02 17:29:18 +08:00
奔跑的面条
2f43ddd59b fix: 去除定时存储数据的逻辑 2023-05-30 09:34:54 +08:00
奔跑的面条
afc6cf04a1 fix: 处理ts报错 2023-05-28 18:00:07 +08:00
奔跑的面条
4d05697b1c fix: 修改ts 错误 2023-05-28 17:56:38 +08:00
奔跑的面条
307480ded2 build: 升级版本到 2.2.3 2023-05-28 17:35:21 +08:00
奔跑的面条
817b25f1a8 Merge branch 'dev' into master-fetch-dev 2023-05-28 17:34:43 +08:00
奔跑的面条
d457cc7135 Merge branch 'dev' into master-fetch-dev 2023-05-28 17:18:49 +08:00
奔跑的面条
8f996173b3 !165 更新 axios 到 1.4.0,并在axios响应拦截中处理 401 状态(跳转到登录)
Merge pull request !165 from dodu/fetch-401
2023-05-28 09:09:46 +00:00
tnt group
a06e8fb7a4 chore: 重新 install,更新 pnpm-lock 2023-05-28 17:01:29 +08:00
tnt group
276bcbe831 Merge branch 'fetch-feat-401' into fetch-401 2023-05-28 17:00:26 +08:00
tnt group
2c6086edca chore: 为避免冲突,删除 pnpm-lock 2023-05-28 16:59:11 +08:00
奔跑的面条
55a6bd93ad !159 地图组件新增卫星地图主题
Merge pull request !159 from tanhao/feat-map-theme
2023-05-28 16:03:10 +08:00
奔跑的面条
622fec4e73 Merge branch 'dev' into master-fetch-dev 2023-05-28 15:59:08 +08:00
tnt group
bdfad88357 chore: 变更 status 获取方式 2023-05-22 08:15:06 +08:00
tnt group
c8e0b6c474 feat: 更新 axios 到 1.4.0,在响应拦截中处理 401 状态(跳转到登录) 2023-05-22 07:39:33 +08:00
奔跑的面条
dfe97bf5d5 build: 升级版本到 2.2.2 2023-05-08 20:43:14 +08:00
奔跑的面条
fe87d0e433 fix: 修改上传的 httpurl 为 fileurl 2023-05-08 20:15:20 +08:00
奔跑的面条
f37264fdbb feat: 去除多余功能代码 2023-05-01 21:51:18 +08:00
奔跑的面条
092a252ac4 feat: 兼容新版本后端 2023-05-01 21:49:08 +08:00
奔跑的面条
f23439d31f Merge branch 'dev' into master-fetch-dev 2023-04-23 21:14:54 +08:00
奔跑的面条
c3b7711f0a Merge branch 'dev' into master-fetch-dev 2023-04-23 21:07:05 +08:00
奔跑的面条
0a775af9bb Merge branch 'dev' into master-fetch-dev 2023-04-23 20:07:03 +08:00
奔跑的面条
2e6611bf8b Merge branch 'dev' into master-fetch-dev 2023-04-05 16:39:39 +08:00
奔跑的面条
6038bc8e58 Merge branch 'dev' into master-fetch-dev 2023-04-03 20:11:20 +08:00
奔跑的面条
3be567ada8 build: 升级版本到 2.2.1 2023-04-02 18:20:40 +08:00
奔跑的面条
8edc2767f9 fix: 还原解决冲突不小心删掉的代码 2023-04-02 18:07:38 +08:00
奔跑的面条
29339c4c7c Merge branch 'dev' into master-fetch-dev 2023-04-02 17:54:57 +08:00
奔跑的面条
30f1f058c7 fix: 处理联动的合并问题 2023-03-16 20:25:31 +08:00
奔跑的面条
afe17efde9 Merge branch 'dev' into master-fetch-dev 2023-03-16 20:02:18 +08:00
奔跑的面条
bcbf53d08f Merge branch 'dev' into master-fetch-dev 2023-03-04 17:32:27 +08:00
奔跑的面条
b7fda10caf Merge branch 'dev' into master-fetch-dev 2023-03-04 17:06:51 +08:00
奔跑的面条
326ad82182 build: 升级版本到 2.1.9 2023-03-04 16:24:57 +08:00
奔跑的面条
02500aff30 !133 解决adcode类型不正确可能导致的问题
Merge pull request !133 from wallellen/master-fetch-dev
2023-03-04 08:01:54 +00:00
奔跑的面条
c31fa20b02 Merge branch 'dev' into master-fetch-dev 2023-03-04 14:42:56 +08:00
wallellen
31cdbe2a57 update src/packages/components/Charts/Maps/MapBase/index.vue.
解决https://gitee.com/dromara/go-view/issues/I6E0JS问题

Signed-off-by: wallellen <wallellen@hotmail.com>
2023-03-04 05:59:26 +00:00
奔跑的面条
5605e6a831 !132 fix: 动态请求中,body的json参数使用javasctipt
Merge pull request !132 from guo_ddt/master-fetch
2023-03-04 13:47:02 +08:00
奔跑的面条
7f9cde3c67 build: 升级版本到2.1.8 2023-02-27 19:04:05 +08:00
奔跑的面条
effd870897 Merge branch 'dev' into master-fetch-dev 2023-02-27 13:07:05 +08:00
奔跑的面条
dd7e1692d6 Merge branch 'dev' into master-fetch-dev 2023-02-27 12:53:44 +08:00
奔跑的面条
a3bbe95643 feat: 新增颜色自定义功能 2023-02-27 00:29:47 +08:00
奔跑的面条
85fe91705b Merge branch 'dev' into master-fetch-dev 2023-02-17 18:15:35 +08:00
奔跑的面条
b53dd405a5 build: 升级带后端版本到2.1.7 2023-02-17 14:33:53 +08:00
奔跑的面条
de6b2e8bf9 Merge branch 'dev' into master-fetch-dev 2023-02-15 14:26:56 +08:00
奔跑的面条
968edea932 Merge branch 'dev' into master-fetch-dev 2023-02-15 09:45:37 +08:00
奔跑的面条
682419d174 Merge branch 'dev' into master-fetch-dev 2023-02-09 16:24:19 +08:00
奔跑的面条
edaa9f7b99 feat: 合并修复序列化代码,解决冲突 2023-01-17 15:34:10 +08:00
奔跑的面条
0fdbde1cc1 feat: 合并dev 2023-01-17 14:49:49 +08:00
奔跑的面条
6e3302fed6 Merge branch 'dev' into master-fetch-dev 2023-01-16 17:58:29 +08:00
奔跑的面条
0d52a8bc5e Merge branch 'dev' into master-fetch-dev 2023-01-16 13:51:54 +08:00
奔跑的面条
09ac83a62b Merge remote-tracking branch 'origin/dev' into master-fetch-dev 2023-01-16 10:22:13 +08:00
奔跑的面条
0fd8d11107 Merge remote-tracking branch 'origin/dev' into master-fetch-dev 2023-01-13 16:52:28 +08:00
奔跑的面条
661b3570a5 Merge branch 'dev' into master-fetch-dev 2023-01-13 16:15:09 +08:00
奔跑的面条
4ffc6a608b fix: 处理 ts 报错 2023-01-09 20:20:19 +08:00
奔跑的面条
2308e1c22b feat: 合并标题名称功能, 解决冲突 2023-01-09 20:18:27 +08:00
奔跑的面条
2967a6c763 Merge branch 'dev' into master-fetch-dev 2023-01-09 19:32:54 +08:00
奔跑的面条
327d23ebac fix: 优化 JSON 序列化无法处理函数的问题 2023-01-09 11:37:57 +08:00
奔跑的面条
15c12ca367 feat: 合并dev 2023-01-09 11:31:54 +08:00
奔跑的面条
8186595d84 build: 升级版本到 2.1.5 2023-01-08 20:06:11 +08:00
奔跑的面条
16e58749a7 feat: 合并 dev 分支功能 2023-01-08 20:01:49 +08:00
奔跑的面条
7dfa156e30 build: 新增提醒 2022-12-31 21:26:18 +08:00
奔跑的面条
dff9ff2caf build: 修改版本号到2.1.3 2022-12-31 20:56:55 +08:00
奔跑的面条
9a4f436b27 build: 升级2.1.2 2022-12-31 20:55:12 +08:00
奔跑的面条
83e50d6e96 Merge branch 'dev' into master-fetch-dev 2022-12-20 17:05:32 +08:00
奔跑的面条
2d752f119d Merge branch 'dev' into master-fetch-dev 2022-12-20 16:59:55 +08:00
奔跑的面条
18784d4455 feat: 全局接口保存之后调接口存储 2022-12-16 13:01:15 +08:00
奔跑的面条
08b1c14a1c Merge branch 'dev' into master-fetch-dev 2022-12-16 12:56:28 +08:00
奔跑的面条
6f9b109022 style: 去除全局多余代码 2022-11-28 11:02:52 +08:00
奔跑的面条
2f6bdcc8c8 style: 修改代码格式,修改错误单词 2022-11-28 10:54:54 +08:00
奔跑的面条
4886af4bb5 !103 优化Axios相关类型推断和语法
Merge pull request !103 from 石头web/master-fetch-dev
2022-11-28 01:46:22 +00:00
a876691666
b57cf1bf59 feat: 接口增加泛型支持 2022-11-27 12:16:32 +08:00
a876691666
183349dce8 feat: 更新Type类型 2022-11-27 11:40:00 +08:00
奔跑的面条
1b9d220abd !102 fix:修复状态变更时(如切换语言等),useSync.hook.ts 中 dataSyncFetch 反复执行导致 chartEditStore.componentList 重复
Merge pull request !102 from fankeke007/N/A
2022-11-22 11:18:28 +00:00
奔跑的面条
ae7f1bcb3e Merge remote-tracking branch 'origin/dev' into master-fetch-dev 2022-11-22 12:43:27 +08:00
奔跑的面条
b270e0ad43 Merge branch 'dev' into master-fetch-dev 2022-11-21 10:50:10 +08:00
奔跑的面条
367d0a23ca Merge branch 'dev' into master-fetch-dev 2022-11-19 20:37:29 +08:00
奔跑的面条
4d6b68ee60 Merge branch 'dev' into master-fetch-dev 2022-11-19 20:27:10 +08:00
奔跑的面条
a34544296a perf: 解决登录按钮 loading 不会关闭的问题 2022-11-19 20:23:20 +08:00
奔跑的面条
e8399875e5 !94 使右上方正确显示登录账号名
Merge pull request !94 from 吴医生/master0fetch-dev-my
2022-11-19 09:47:01 +00:00
奔跑的面条
d78be0093e fix: 预览页接口错误不处理,默认正确 2022-11-19 15:07:54 +08:00
fankeke007
09fb1aff92 fix:修复状态变更时(如切换语言等),useSync.hook.ts 中 dataSyncFetch 反复执行导致 chartEditStore.componentList 重复
Signed-off-by: fankeke007 <610047449@qq.com>
2022-11-18 08:03:35 +00:00
奔跑的面条
b79c2b2fdb !95 feat: JSON编辑优化以及兼容后端接口保存
Merge pull request !95 from 潘潘/master-fetch-dev
2022-11-15 13:39:49 +00:00
潘潘
656adfcf56 perf: 编辑JSON兼容后端优化 2022-11-15 16:26:52 +08:00
潘潘
786458adfe perf: 编辑JSON优化 2022-11-15 16:21:35 +08:00
潘潘
31b5a6961b perf: 注释定时同步 2022-11-14 21:07:12 +08:00
吴医生
babab39710 fix: 使正确显示右上方登录账号名
Signed-off-by: 吴医生 <draculakkk@hotmail.com>
2022-11-14 09:26:21 +00:00
奔跑的面条
9e25e1866d Merge branch 'dev' into master-fetch-dev 2022-11-13 21:45:16 +08:00
奔跑的面条
781151319c Merge branch 'dev' into master-fetch-dev 2022-11-13 02:39:13 +08:00
奔跑的面条
d3c3cf86b2 Merge branch 'dev' into master-fetch-dev 2022-11-12 17:42:39 +08:00
奔跑的面条
5f7d505f20 fix: 修改500展示文案 2022-11-05 21:45:48 +08:00
奔跑的面条
cd8bdc5d1d Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch-dev 2022-11-05 21:34:39 +08:00
奔跑的面条
d8117b66ca fix: 修改地址 2022-11-02 21:33:20 +08:00
奔跑的面条
b26a45a7b6 fix: 修改类型错误的问题 2022-11-02 19:30:47 +08:00
奔跑的面条
37eb0ed357 build: 修改版本到2.1.1 2022-11-02 19:07:18 +08:00
奔跑的面条
858ee8515d Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch-dev 2022-11-02 19:06:49 +08:00
奔跑的面条
7313f8707e chore: 修改上传地址的接口和图片的展示地址拼接 2022-11-01 21:17:24 +08:00
奔跑的面条
564f8d0ae2 fix: 处理更换背景图内容不会更新的问题 2022-10-31 10:40:58 +08:00
奔跑的面条
37df8a7fa1 fix: 修改发布API错误调用 2022-10-26 10:51:10 +08:00
奔跑的面条
8039213380 build: 修改版本号为2.1.0 2022-10-15 17:28:23 +08:00
奔跑的面条
c5a704767d fix: 修改版本号到2.0.10 2022-10-15 17:22:06 +08:00
奔跑的面条
20be7f2e45 Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch-dev 2022-10-15 17:20:05 +08:00
奔跑的面条
d43823794d fix: 修复导入组件数据会错乱的问题 2022-10-09 16:39:10 +08:00
奔跑的面条
5e09105a70 Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch-dev 2022-10-09 09:29:40 +08:00
奔跑的面条
7d2a98ab85 build: 修改正确版本到 2.0.8 2022-10-08 21:27:21 +08:00
奔跑的面条
2d302bb468 build: 升级版本到 2.0.9 2022-10-08 21:09:47 +08:00
奔跑的面条
789328b02e Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch-dev 2022-10-08 21:06:06 +08:00
奔跑的面条
b93a2a516a feat: 合并1.1.1 2022-10-08 21:04:41 +08:00
奔跑的面条
c8662537ca feat: 合并1.1.1,升级版本到2.0.8 2022-09-27 20:28:47 +08:00
奔跑的面条
b083bd9724 style: 去除无用代码,设置默认值 2022-09-27 19:53:55 +08:00
奔跑的面条
5fd6870cfe perf: 优化用户体验,完成接口配置后调用保存接口 2022-09-27 10:33:30 +08:00
奔跑的面条
9004a55b8c Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch-dev 2022-09-22 14:15:18 +08:00
奔跑的面条
c349e6384e Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch-dev 2022-09-21 19:56:56 +08:00
奔跑的面条
4e298efaa0 Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch-dev 2022-09-19 20:46:53 +08:00
奔跑的面条
c7cbb9b72a Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch-dev 2022-09-19 20:14:40 +08:00
奔跑的面条
bd5e06350d perf: 优化滤镜模糊问题,默认不开启 2022-09-19 17:51:12 +08:00
奔跑的面条
c311dd08e3 fix: 修改请求接口 token 名称 2022-09-18 17:45:59 +08:00
奔跑的面条
504a1f4703 build: 升级版本到2.0.7 2022-09-18 17:23:16 +08:00
奔跑的面条
a67cc9f876 !47 修复在编辑项目之前加载数据异常,自动保存导致项目数据清空问题。
Merge pull request !47 from 秋名山路霸/master-fetch
2022-09-18 07:53:47 +00:00
秋名山路霸
e0d2e8031d fix: 修复在编辑项目之前加载数据异常,自动保存导致项目数据清空问题。 2022-09-18 11:56:26 +08:00
奔跑的面条
bcec26374f build: 升级依赖,锁定TS 版本 2022-09-12 01:20:27 +08:00
奔跑的面条
a5981a4387 feat: 升级版本到 2.0.6 2022-09-12 00:49:22 +08:00
奔跑的面条
0d26dce512 fix: 合并1.0.9 2022-09-12 00:31:52 +08:00
奔跑的面条
6359ec15b3 feat: 新增移动撤回 2022-08-30 19:14:52 +08:00
奔跑的面条
32ca138e6a build: 升级版本到 2.0.5 2022-08-30 15:04:29 +08:00
奔跑的面条
171e0aa408 perf: 完善首页预览功能 2022-08-30 15:03:25 +08:00
奔跑的面条
52009a415b Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch 2022-08-30 12:19:57 +08:00
奔跑的面条
da809f13b3 fix: 尝试解决背景图片无法截图的问题 2022-08-29 21:35:51 +08:00
奔跑的面条
801aa1f82f update LICENSE.
Signed-off-by: 奔跑的面条 <1262327911@qq.com>
2022-08-29 10:13:37 +00:00
奔跑的面条
72c26b71f3 perf: 优化参考线的展示方式 2022-08-21 14:52:30 +08:00
奔跑的面条
3b8181ae10 Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch 2022-08-21 14:49:32 +08:00
奔跑的面条
c2a9642393 Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch 2022-08-19 14:46:49 +08:00
奔跑的面条
3c04f81147 fix: 补充代码合并丢失的枚举 2022-08-19 11:43:23 +08:00
奔跑的面条
ec28ccf09c perf: 优化500错误页重定向 2022-08-19 11:34:38 +08:00
奔跑的面条
fa34300401 feat: 合并多选功能,解决冲突,升级版本到2.0.4 2022-08-19 10:44:44 +08:00
奔跑的面条
f506ccd2e4 Merge branch 'dev' into master-fetch 2022-08-05 08:42:22 +08:00
奔跑的面条
f379f7652c Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch 2022-07-26 16:12:31 +08:00
奔跑的面条
e8760c81ac Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch 2022-07-21 11:46:54 +08:00
奔跑的面条
a9bb294f60 feat: 合并 1.0.6 版本代码 2022-07-21 11:03:04 +08:00
奔跑的面条
0b5f35752b Merge branch 'dev' into master-fetch 2022-07-08 18:12:33 +08:00
奔跑的面条
7322817cb5 fix: 合并编辑功能的修改 2022-07-07 19:54:53 +08:00
奔跑的面条
437ad1bd9f Merge branch 'dev' into master-fetch 2022-07-07 13:14:53 +08:00
奔跑的面条
cd20e68480 fix: 补充合并代码丢失的icon图标 2022-07-06 22:12:24 +08:00
奔跑的面条
35968475b9 build: 合并dev 1.0.5 版本, 修改fetch分支为2.0.2 2022-07-06 21:58:28 +08:00
奔跑的面条
78eb3ccc3f Merge branch 'dev' into master-fetch 2022-06-27 21:42:24 +08:00
奔跑的面条
7cccbabca4 Merge branch 'dev' into master-fetch 2022-06-27 21:38:27 +08:00
奔跑的面条
cdccfa3e12 fix: 修改合并冲突错误的代码 2022-06-27 20:42:17 +08:00
奔跑的面条
e8c5455748 perf: 合并dev分支,解决组件无法更新数据的问题 2022-06-27 20:37:26 +08:00
奔跑的面条
8e40416e72 style: 去除多余代码 2022-06-24 11:44:26 +08:00
奔跑的面条
d058361e01 docs: 修改文档 2022-06-23 09:53:01 +08:00
奔跑的面条
2491f7ff57 feat: 新增保存按钮 2022-06-22 18:50:15 +08:00
奔跑的面条
c5908f6d92 build: 升级依赖 2022-06-20 15:13:50 +08:00
奔跑的面条
7e64d30258 build: 合并dev分支 2022-06-20 15:11:13 +08:00
奔跑的面条
437818abce feat: 新增排名列表字体大小控制功能 2022-06-17 14:13:14 +08:00
奔跑的面条
5197eb9292 build: 修改版本到 2.0.1 2022-06-16 10:48:42 +08:00
奔跑的面条
3cf01f0c51 fix: 解决打包之后无法加载页面的问题 2022-06-15 17:54:49 +08:00
奔跑的面条
db815661e8 feat: 新增 preview 模式,修改打包后路径指向 2022-06-15 17:48:16 +08:00
奔跑的面条
6edbb7c8a7 feat: 新增commitlint 2022-06-15 17:18:39 +08:00
奔跑的面条
799c445c4b docs: 更新文档 2022-06-15 17:15:29 +08:00
奔跑的面条
70fbf5de3e doc: 文档更新 2022-06-15 17:14:27 +08:00
奔跑的面条
73c7697443 feat: 新增渐变文本组件 2022-06-15 16:20:25 +08:00
奔跑的面条
8092edab81 build:升级依赖 2022-06-15 16:11:58 +08:00
奔跑的面条
ef4f45ddb0 fix: 解决npm,yarn 安装依赖报错的问题 2022-06-15 16:08:59 +08:00
奔跑的面条
3e969e4ae5 fix: 补充丢失的图片 2022-06-14 12:46:07 +08:00
奔跑的面条
bcd1dfd7bd feat:新增数字滚动组件动态获取数据功能 2022-06-14 12:31:46 +08:00
奔跑的面条
c1dfd78d18 feat: 新增表格滚动组件 2022-06-14 12:31:20 +08:00
奔跑的面条
39aa1645c9 fix:解决边框04展示不全的bug 2022-06-14 12:30:29 +08:00
奔跑的面条
d3afea8c5e feat:新增水球图设置项 2022-06-13 17:29:39 +08:00
奔跑的面条
2499cbdd44 fix: 修改列表页展示问题 2022-06-13 14:28:58 +08:00
奔跑的面条
3cc3714e94 feat: 新增环形图,新增NaiveUI-进度组件 2022-06-13 13:18:30 +08:00
奔跑的面条
be0aa6d099 feat: 新增进度条组件 2022-06-12 18:47:47 +08:00
奔跑的面条
34d27c1004 fix: 解决缩放比例展示不全的问题 2022-06-12 18:45:31 +08:00
奔跑的面条
85f3b4e9e3 chore: 优化拖拽锚点 2022-06-11 15:15:38 +08:00
奔跑的面条
0fb9a79df9 fix:修改请求地址为null时引起的异常bug 2022-06-11 14:37:22 +08:00
奔跑的面条
6b805fbdfb chore: 优化发布弹窗 2022-06-11 14:23:16 +08:00
奔跑的面条
abe76aeb59 build: 依赖基本升级 2022-06-11 14:15:28 +08:00
奔跑的面条
5f49bc1aa8 fix: 修改双折线图X轴无法变更的问题 2022-06-11 14:13:32 +08:00
奔跑的面条
71807be01d fix: 解决项目列表信息栏会换行的问题 2022-06-09 08:49:07 +08:00
奔跑的面条
e74f796203 fix:解决截图有白边的问题 2022-06-09 08:48:28 +08:00
奔跑的面条
041d7da9d8 fix: 修改复制失败的提示类型错误的问题 2022-06-06 10:43:14 +08:00
奔跑的面条
a99d949b29 chore: 新增路由白名单 2022-06-06 10:42:55 +08:00
奔跑的面条
c2a9e2a469 chore:优化搜索结果列表UI 2022-06-05 11:41:57 +08:00
奔跑的面条
80b05db764 chore:优化 dialog 的全局封装代码 2022-06-04 16:25:37 +08:00
奔跑的面条
340cab11b7 build:修改 fetch 版本号 2022-06-04 15:44:26 +08:00
奔跑的面条
712233c215 chore: 优化页面 UI 2022-06-03 20:21:35 +08:00
奔跑的面条
b9b915e913 fix: 修改自动复制粘贴的问题 2022-06-03 18:53:37 +08:00
奔跑的面条
044143571f fix: 新增发布页面处理 2022-06-03 14:48:58 +08:00
奔跑的面条
06fe805736 chore: 优化了标题展示和大小样式 2022-06-03 11:19:29 +08:00
奔跑的面条
077881e499 type: 修改类型错误 2022-06-01 23:00:28 +08:00
奔跑的面条
f655a57e61 fix:处理列表页标题过长的展示问题 2022-06-01 22:58:22 +08:00
奔跑的面条
0b04bf4929 type: 定义全局返回值类型 2022-06-01 22:41:11 +08:00
奔跑的面条
2fcd3b1132 build: 修改版本号 0.0.9 2022-06-01 22:28:46 +08:00
奔跑的面条
568fd6c105 chore:优化了路由写法,修改了错误页面的展示,新增未发布提示页面 2022-06-01 22:20:05 +08:00
奔跑的面条
221351ec11 feat: 新增动态预览功能 2022-06-01 22:19:03 +08:00
奔跑的面条
6ab34a0996 fix: 修改组件注册会报错的问题 2022-06-01 22:14:33 +08:00
奔跑的面条
6b551ae68b build:升级依赖包 2022-06-01 22:13:49 +08:00
奔跑的面条
2917cde2e5 fix: 解决列表图片展示缓存问题 2022-06-01 20:16:38 +08:00
奔跑的面条
294a4a6cdf fix: 解决获取数据,但是配置模块不完整的问题 2022-06-01 19:01:05 +08:00
奔跑的面条
1e678b7492 build: 修改请求地址 2022-05-31 11:19:17 +08:00
奔跑的面条
2ceca7287f fix: 修改oss接口不会动态更改的问题 2022-05-31 11:18:34 +08:00
奔跑的面条
7f4dd5295b chore:修改请求地址 2022-05-29 16:04:07 +08:00
奔跑的面条
ffd628fa82 docs: 修改文档说明 2022-05-29 15:23:04 +08:00
奔跑的面条
d639e445eb feat: 新增背景图文件上传保存 2022-05-29 14:54:35 +08:00
奔跑的面条
b263681dda chore: 去除生成预览图时的标尺 2022-05-28 17:58:07 +08:00
奔跑的面条
e16413b570 feat: 新增首页预览图展示 2022-05-28 16:39:27 +08:00
奔跑的面条
63b5186c3e Merge branch 'dev' into master-fetch 2022-05-28 15:58:06 +08:00
奔跑的面条
ba20316761 fix: 修改自动保存预览图无法存储的问题 2022-05-28 15:46:07 +08:00
奔跑的面条
437dd1c411 branch: 合并锚点样式修改 2022-05-28 12:46:32 +08:00
奔跑的面条
d0d5f5b77d feat: 保存预览图 2022-05-28 11:50:17 +08:00
奔跑的面条
efd9228cc9 fix: 解决打包后无法发送请求的bug 2022-05-28 00:32:32 +08:00
奔跑的面条
ebd6132385 feat: 新增上传文件接口 2022-05-27 20:09:48 +08:00
奔跑的面条
9098443c83 chore: 修改项目信息结构 2022-05-27 11:49:25 +08:00
奔跑的面条
423890a4df feat: 新增项目信息修改功能 2022-05-26 01:01:59 +08:00
奔跑的面条
fb2edeb7d2 fix: 修改导入组件id会重复的问题 2022-05-25 23:00:36 +08:00
奔跑的面条
b861587f01 feat: 新增快捷键展示 2022-05-24 18:17:41 +08:00
奔跑的面条
c3738fab45 faet: 新增保存快捷键 2022-05-24 18:16:33 +08:00
奔跑的面条
24fba75f28 feat: 新增自动同步功能 2022-05-24 17:42:49 +08:00
奔跑的面条
00b6b63e1e feat: 新增数据保存接口 2022-05-24 15:05:51 +08:00
奔跑的面条
5dab8fa7d9 Merge branch 'dev' into master-fetch 2022-05-24 12:28:14 +08:00
奔跑的面条
9a5d71fb5c feat: 新增获取项目数据功能,新增同步数据功能 2022-05-23 23:50:35 +08:00
奔跑的面条
c930efba0c Merge branch 'dev' into master-fetch 2022-05-23 16:06:13 +08:00
奔跑的面条
ff7c820b1f Merge branch 'dev' into master-fetch 2022-05-22 23:27:39 +08:00
奔跑的面条
4252725d9d feat: 新增获取项目数据接口 2022-05-22 22:11:56 +08:00
奔跑的面条
deeb3a472c feat:新增发布和取消发布接口 2022-05-22 16:38:22 +08:00
奔跑的面条
763173de44 style: 调整代码格式,去除多余代码 2022-05-22 15:39:30 +08:00
奔跑的面条
f46e6ad8c8 feat: 新增删除接口 2022-05-22 15:25:07 +08:00
奔跑的面条
09b31547e1 feat: 新增首页列表接口 2022-05-22 15:06:45 +08:00
奔跑的面条
dee2ff8dee Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch 2022-05-22 14:09:38 +08:00
奔跑的面条
7f315b95ce feat: 新增项目列表接口 2022-05-22 14:05:57 +08:00
奔跑的面条
093e7d1edb Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch 2022-05-22 13:36:30 +08:00
奔跑的面条
a4e18f8893 fix: 修改新建项目id错误问题 2022-05-21 21:04:10 +08:00
奔跑的面条
c754a36ee5 fix: 修改i18n错误提示 2022-05-21 19:46:44 +08:00
奔跑的面条
a07d4daed5 chore: 修改提示内容 2022-05-21 18:04:52 +08:00
奔跑的面条
39023832e3 feat: 新增创建接口,修改i8n部分内容 2022-05-21 18:03:15 +08:00
奔跑的面条
5b8dda60bd feat: 新增退出登录接口,新增全局接口封装,修改登录接口内容 2022-05-21 17:31:01 +08:00
奔跑的面条
f7ade54e93 Merge branch 'master' of https://gitee.com/MTrun/go-view into master-fetch 2022-05-21 14:01:53 +08:00
奔跑的面条
4ae7e9dd2e Merge branch 'dev' into master-fetch 2022-05-21 13:44:25 +08:00
奔跑的面条
7e237b508a feat: 新增登录接口请求 2022-05-20 16:12:27 +08:00
奔跑的面条
28bb82e579 fix: 修改plop的问题 2022-05-20 16:12:09 +08:00
奔跑的面条
bcabcb0831 Merge branch 'dev' of https://gitee.com/MTrun/go-view into master-fetch 2022-05-20 10:25:46 +08:00
奔跑的面条
c24b03f3da update README.md. 2022-05-19 01:56:30 +00:00
奔跑的面条
63dd03e755 update README.md. 2022-05-16 10:38:39 +00:00
奔跑的面条
f3f1f57b01 update README.md. 2022-05-16 04:23:10 +00:00
88 changed files with 1780 additions and 449 deletions

12
.env
View File

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

142
README.md
View File

@@ -2,21 +2,17 @@
![logo](readme/logo-t-y.png) ![logo](readme/logo-t-y.png)
GoView 是一个高效的拖拽式低代码数据可视化开发平台,将图表或页面元素封装为基础组件,无需编写代码即可制作数据大屏,减少心智负担。 **`master-fetch` 分支是带有后端接口请求的分支**
### 😶 纯 **前端** 分支: **`master`** **后端项目地址:[https://gitee.com/MTrun/go-view-serve](https://gitee.com/MTrun/go-view-serve)**
### 👻 携带 **后端** 请求分支: **`master-fetch`** **接口说明地址:[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)**
### 📚 GoView **文档** 地址:[http://www.mtruning.club:81/](http://www.mtruning.club:81/) ## 使用
项目纯前端-Demo 地址:[https://www.mtruning.club](https://www.mtruning.club) 所有的接口地址位置:`src\api\path\*`
项目带后端-Demo 地址:[后端 Demo 地址](http://1.117.240.165:8080/goview/#/login) 接口地址修改:`.env`
文档-在线地址:[http://www.mtruning.club:81/](http://www.mtruning.club:81/)
文档-源码地址:[https://gitee.com/MTrun/go-view-doc](https://gitee.com/MTrun/go-view-doc)
### 🤯 后端项目 ### 🤯 后端项目
@@ -36,13 +32,6 @@ GoView 是一个高效的拖拽式低代码数据可视化开发平台,将图
- 封装:项目进行了详细的工具类封装如:路由、存储、加/解密、文件处理、主题、NaiveUI 全局方法、组件等 - 封装:项目进行了详细的工具类封装如:路由、存储、加/解密、文件处理、主题、NaiveUI 全局方法、组件等
- 可视化:基于开源图表库[ECharts](https://echarts.apache.org/zh/index.html) 和 [VChart](https://www.visactor.io/vchart) 编写,具有丰富的图表类型和适配大屏的主题效果;
- 入选 NaiveUI 社区精选资源推荐:[查看 NaiveUI 推荐列表](https://www.naiveui.com/zh-CN/light/docs/community)
说明文档:
![说明文档](readme/go-view-doc.png)
工作台: 工作台:
![项目截图](readme/go-view-canvas.png) ![项目截图](readme/go-view-canvas.png)
@@ -91,63 +80,102 @@ GoView 是一个高效的拖拽式低代码数据可视化开发平台,将图
本项目采用` pnpm` 进行包管理 本项目采用` pnpm` 进行包管理
```shell ```shell
#建议使用 nrm 切换到淘宝源 https://registry.npmmirror.com/ # port
#pnpm VITE_DEV_PORT = '8080'
pnpm install
#yarn # development path
yarn install VITE_DEV_PATH = 'http://127.0.0.1:8080'
#npm # production path
npm install VITE_PRO_PATH = 'http://127.0.0.1:8080'
``` ```
## 启动 公共前缀修改:`src\settings\httpSetting.ts`
```shell ```shell
#pnpm // 请求前缀
pnpm dev export const axiosPre = '/api/goview'
# npm
npm run dev
#yarn
yarn dev
#Makefile
make dev
``` ```
## 编译 接口封装:`src\api\http.ts`
```shell ```ts
#pnpm import axiosInstance from './axios'
pnpm run build import { RequestHttpEnum, ContentTypeEnum } from '@/enums/httpEnum'
# npm export const get = (url: string, params?: object) => {
npm run build return axiosInstance({
url: url,
method: RequestHttpEnum.GET,
params: params,
})
}
#yarn export const post = (url: string, data?: object, headersType?: string) => {
yarn run build return axiosInstance({
url: url,
method: RequestHttpEnum.POST,
data: data,
headers: {
'Content-Type': headersType || ContentTypeEnum.JSON
}
})
}
#Makefile export const put = (url: string, data?: object, headersType?: string) => {
make dist 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: 新功能 * feat: 新功能
- fix: 修复 Bug * fix: 修复 Bug
- docs: 文档修改 * docs: 文档修改
- perf: 性能优化 * perf: 性能优化
- revert: 版本回退 * revert: 版本回退
- ci: CICD 集成相关 * ci: CICD集成相关
- test: 添加测试代码 * test: 添加测试代码
- refactor: 代码重构 * refactor: 代码重构
- build: 影响项目构建或依赖修改 * build: 影响项目构建或依赖修改
- style: 不影响程序逻辑的代码修改 * style: 不影响程序逻辑的代码修改
- chore: 不属于以上类型的其他类型(日常事务) * chore: 不属于以上类型的其他类型(日常事务)
## 交流 ## 交流

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", "name": "go-view",
"version": "1.1.11", "version": "2.2.9",
"engines": { "engines": {
"node": ">=16.14" "node": ">=16.14"
}, },
@@ -48,7 +48,7 @@
"vue-i18n": "9.2.2", "vue-i18n": "9.2.2",
"vue-router": "4.0.12", "vue-router": "4.0.12",
"vue3-lazyload": "^0.2.5-beta", "vue3-lazyload": "^0.2.5-beta",
"vue3-sketch-ruler": "^1.3.3", "vue3-sketch-ruler": "1.3.3",
"vuedraggable": "^4.1.0" "vuedraggable": "^4.1.0"
}, },
"devDependencies": { "devDependencies": {

15
pnpm-lock.yaml generated
View File

@@ -111,8 +111,8 @@ importers:
specifier: ^0.2.5-beta specifier: ^0.2.5-beta
version: 0.2.5-beta(@vue/compiler-sfc@3.5.16)(vue@3.5.16(typescript@4.6.3)) version: 0.2.5-beta(@vue/compiler-sfc@3.5.16)(vue@3.5.16(typescript@4.6.3))
vue3-sketch-ruler: vue3-sketch-ruler:
specifier: ^1.3.3 specifier: 1.3.3
version: 1.3.16(vue@3.5.16(typescript@4.6.3)) version: 1.3.3(vue@3.5.16(typescript@4.6.3))
vuedraggable: vuedraggable:
specifier: ^4.1.0 specifier: ^4.1.0
version: 4.1.0(vue@3.5.16(typescript@4.6.3)) version: 4.1.0(vue@3.5.16(typescript@4.6.3))
@@ -3946,9 +3946,8 @@ packages:
'@vue/compiler-sfc': '>=3.0.0' '@vue/compiler-sfc': '>=3.0.0'
vue: '>=3.0.0' vue: '>=3.0.0'
vue3-sketch-ruler@1.3.16: vue3-sketch-ruler@1.3.3:
resolution: {integrity: sha512-k/TBOwbueU9eWOF7k/emsZMwtEqFk/FxG+h//TlaZ2B8RWbxhIe6hPFgggO4Jng10ARsuH4cMGAR+ZOuN4ozgg==} resolution: {integrity: sha512-k7wK34fWq0v4PiEklF0KAxS37UJS2nm8mMaE8g4Bqv9ZbBY7MxqrkM1wIj9VHmjN/MyQeodFWdg6lJv/ZESKlw==}
deprecated: This version is deprecated. Please upgrade to version 2X for better features and performance.See https://github.com/kakajun/vue3-sketch-ruler
hasBin: true hasBin: true
peerDependencies: peerDependencies:
'@vue/composition-api': ^1.1.0 '@vue/composition-api': ^1.1.0
@@ -4323,7 +4322,7 @@ snapshots:
'@types/node': 20.5.1 '@types/node': 20.5.1
chalk: 4.1.2 chalk: 4.1.2
cosmiconfig: 8.3.6(typescript@5.8.3) cosmiconfig: 8.3.6(typescript@5.8.3)
cosmiconfig-typescript-loader: 4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@5.8.3))(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.8.3))(typescript@5.8.3) cosmiconfig-typescript-loader: 4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@4.6.3))(ts-node@10.9.2(@types/node@16.18.126)(typescript@4.6.3))(typescript@5.8.3)
lodash.isplainobject: 4.0.6 lodash.isplainobject: 4.0.6
lodash.merge: 4.6.2 lodash.merge: 4.6.2
lodash.uniq: 4.5.0 lodash.uniq: 4.5.0
@@ -5556,7 +5555,7 @@ snapshots:
core-util-is@1.0.3: {} core-util-is@1.0.3: {}
cosmiconfig-typescript-loader@4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@5.8.3))(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.8.3))(typescript@5.8.3): cosmiconfig-typescript-loader@4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@4.6.3))(ts-node@10.9.2(@types/node@16.18.126)(typescript@4.6.3))(typescript@5.8.3):
dependencies: dependencies:
'@types/node': 20.5.1 '@types/node': 20.5.1
cosmiconfig: 8.3.6(typescript@5.8.3) cosmiconfig: 8.3.6(typescript@5.8.3)
@@ -8186,7 +8185,7 @@ snapshots:
'@vue/compiler-sfc': 3.5.16 '@vue/compiler-sfc': 3.5.16
vue: 3.5.16(typescript@4.6.3) vue: 3.5.16(typescript@4.6.3)
vue3-sketch-ruler@1.3.16(vue@3.5.16(typescript@4.6.3)): vue3-sketch-ruler@1.3.3(vue@3.5.16(typescript@4.6.3)):
optionalDependencies: optionalDependencies:
vue: 3.5.16(typescript@4.6.3) vue: 3.5.16(typescript@4.6.3)

View File

@@ -17,7 +17,7 @@
import { NConfigProvider } from 'naive-ui' import { NConfigProvider } from 'naive-ui'
import { GoAppProvider } from '@/components/GoAppProvider' import { GoAppProvider } from '@/components/GoAppProvider'
import { I18n } from '@/components/I18n' import { I18n } from '@/components/I18n'
import { useDarkThemeHook, useThemeOverridesHook, useCode, useLang } from '@/hooks' import { useSystemInit, useDarkThemeHook, useThemeOverridesHook, useCode, useLang } from '@/hooks'
// 暗黑主题 // 暗黑主题
const darkTheme = useDarkThemeHook() const darkTheme = useDarkThemeHook()
@@ -28,6 +28,9 @@ const overridesTheme = useThemeOverridesHook()
// 代码主题 // 代码主题
const hljsTheme = useCode() const hljsTheme = useCode()
// 系统全局数据初始化
useSystemInit()
// 全局语言 // 全局语言
const { locale, dateLocale } = useLang() 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,34 +1,93 @@
import axios, { AxiosResponse, InternalAxiosRequestConfig, AxiosError } from 'axios' import axios, { AxiosResponse, AxiosRequestConfig, Axios, AxiosError, InternalAxiosRequestConfig } from 'axios'
import { ResultEnum } from "@/enums/httpEnum" import { RequestHttpHeaderEnum, ResultEnum, ModuleTypeEnum } from '@/enums/httpEnum'
import { ErrorPageNameMap } from "@/enums/pageEnum" import { PageEnum, ErrorPageNameMap } from '@/enums/pageEnum'
import { redirectErrorPage } from '@/utils' 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({ 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, timeout: ResultEnum.TIMEOUT
}) }) as unknown as MyRequestInstance
axiosInstance.interceptors.request.use( axiosInstance.interceptors.request.use(
(config: InternalAxiosRequestConfig) => { (config: InternalAxiosRequestConfig) => {
// 白名单校验
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[userInfo[SystemStoreUserInfoEnum.TOKEN_NAME] || 'token'] = userInfo[SystemStoreUserInfoEnum.USER_TOKEN] || ''
return config return config
}, },
(error: AxiosError) => { (err: AxiosError) => {
Promise.reject(error) Promise.reject(err)
} }
) )
// 响应拦截器 // 响应拦截器
axiosInstance.interceptors.response.use( axiosInstance.interceptors.response.use(
(res: AxiosResponse) => { (res: AxiosResponse) => {
// 预览页面错误不进行处理
if (isPreview()) {
return Promise.resolve(res.data)
}
const { code } = res.data as { code: number } const { code } = res.data as { code: number }
if (code === undefined || code === null) return Promise.resolve(res.data) if (code === undefined || code === null) return Promise.resolve(res.data)
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) return Promise.resolve(res.data)
}, },
(err: AxiosResponse) => { (err: AxiosError) => {
Promise.reject(err) const status = err.response?.status
switch (status) {
case 401:
routerTurnByName(PageEnum.BASE_LOGIN_NAME)
Promise.reject(err)
break
default:
Promise.reject(err)
break
}
} }
) )

View File

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

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,99 @@
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,
fileurl: 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.

Before

Width:  |  Height:  |  Size: 1.3 MiB

View File

@@ -27,7 +27,9 @@
<script lang="ts" setup> <script lang="ts" setup>
import { h, ref } from 'vue' import { h, ref } from 'vue'
import { NAvatar, NText } from 'naive-ui' 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 { logout, renderLang } from '@/utils'
import { GoSystemSet } from '@/components/GoSystemSet/index' import { GoSystemSet } from '@/components/GoSystemSet/index'
import { GoSystemInfo } from '@/components/GoSystemInfo/index' import { GoSystemInfo } from '@/components/GoSystemInfo/index'
@@ -64,7 +66,17 @@ const renderUserInfo = () => {
}), }),
h('div', null, [ h('div', null, [
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; cursor: pointer;
transform: scale(0.7); transform: scale(0.7);
} }
</style> </style>

View File

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

View File

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

View File

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

View File

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

View File

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

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', help: 'Help',
contact: 'About Software', contact: 'About Software',
logout: 'Logout', logout: 'Logout',
logout_success: 'Logout success',
logout_failure: 'Logout Failed',
// system setting // system setting
sys_set: 'System Setting', sys_set: 'System Setting',
lang_set: 'Language Setting', lang_set: 'Language Setting',
@@ -26,8 +28,14 @@ const global = {
r_more: 'More', 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 { export default {
global, global,
http,
login, login,
project project
} }

View File

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

View File

@@ -1,6 +1,8 @@
export default { export default {
create_btn: 'Create', 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', project: 'Project',
my: 'My', my: 'My',
new_project: 'New Project', new_project: 'New Project',

View File

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

View File

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

View File

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

View File

@@ -12,7 +12,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, PropType, onMounted, watch, ref } from 'vue' import { computed, PropType, onMounted, watch } from 'vue'
import VChart from 'vue-echarts' import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook' import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use } from 'echarts/core' import { use } from 'echarts/core'

View File

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

View File

@@ -56,6 +56,7 @@ import {
ArrowDown as ArrowDownIcon, ArrowDown as ArrowDownIcon,
Planet as PawIcon, Planet as PawIcon,
Search as SearchIcon, Search as SearchIcon,
Reload as ReloadIcon,
ChevronUpOutline as ChevronUpOutlineIcon, ChevronUpOutline as ChevronUpOutlineIcon,
ChevronDownOutline as ChevronDownOutlineIcon, ChevronDownOutline as ChevronDownOutlineIcon,
ChevronForward as ChevronForwardIcon, ChevronForward as ChevronForwardIcon,
@@ -98,6 +99,7 @@ import {
FitToScreen as FitToScreenIcon, FitToScreen as FitToScreenIcon,
FitToHeight as FitToHeightIcon, FitToHeight as FitToHeightIcon,
FitToWidth as FitToWidthIcon, FitToWidth as FitToWidthIcon,
Save as SaveIcon,
Carbon3DCursor as Carbon3DCursorIcon, Carbon3DCursor as Carbon3DCursorIcon,
Carbon3DSoftware as Carbon3DSoftwareIcon, Carbon3DSoftware as Carbon3DSoftwareIcon,
Filter as FilterIcon, Filter as FilterIcon,
@@ -221,6 +223,8 @@ const ionicons5 = {
PawIcon, PawIcon,
// 搜索(放大镜) // 搜索(放大镜)
SearchIcon, SearchIcon,
// 加载
ReloadIcon,
// 过滤器 // 过滤器
FilterIcon, FilterIcon,
// 向上 // 向上
@@ -294,6 +298,8 @@ const carbon = {
FitToScreenIcon, FitToScreenIcon,
FitToHeightIcon, FitToHeightIcon,
FitToWidthIcon, FitToWidthIcon,
// 保存
SaveIcon,
// 成组 // 成组
Carbon3DCursorIcon, Carbon3DCursorIcon,
// 解组 // 解组

View File

@@ -1,13 +1,13 @@
import { RouteRecordRaw } from 'vue-router' import { RouteRecordRaw } from 'vue-router'
import type { AppRouteRecordRaw } from '@/router/types'; 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 { PageEnum } from '@/enums/pageEnum'
import { GoReload } from '@/components/GoReload' import { GoReload } from '@/components/GoReload'
export const LoginRoute: RouteRecordRaw = { export const LoginRoute: RouteRecordRaw = {
path: '/login', path: PageEnum.BASE_LOGIN,
name: 'Login', name: PageEnum.BASE_LOGIN_NAME,
component: () => import('@/views/login/index.vue'), component: () => import('@/views/login/index.vue'),
meta: { meta: {
title: '登录', title: '登录',
@@ -60,22 +60,21 @@ export const ReloadRoute: AppRouteRecordRaw = {
}, },
} }
export const RedirectRoute: AppRouteRecordRaw = { export const RedirectRoute: RouteRecordRaw[] = [
path: PageEnum.REDIRECT, {
name: PageEnum.REDIRECT_NAME, path: PageEnum.REDIRECT,
component: Layout, name: PageEnum.REDIRECT_NAME,
meta: { component: RedirectHome,
title: PageEnum.REDIRECT_NAME, 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,
},
}, },
], },
}; {
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 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 Layout = () => import('@/layout/index.vue');
export const ParentLayout = () => import('@/layout/parentLayout.vue'); export const ParentLayout = () => import('@/layout/parentLayout.vue');

View File

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

View File

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

View File

@@ -61,6 +61,9 @@ export const editToJsonInterval = 5000
// 数据请求间隔 // 数据请求间隔
export const requestInterval = 30 export const requestInterval = 30
// 工作台自动保存间隔s
export const saveInterval = 30
// 数据请求间隔单位 // 数据请求间隔单位
export const requestIntervalUnit = RequestHttpIntervalEnum.SECOND 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 { CreateComponentType, CreateComponentGroupType, FilterEnum } from '@/packages/index.d'
import { HistoryActionTypeEnum } from '@/store/modules/chartHistoryStore/chartHistoryStore.d' import { HistoryActionTypeEnum } from '@/store/modules/chartHistoryStore/chartHistoryStore.d'
import { SyncEnum } from '@/enums/editPageEnum'
import { import {
RequestHttpEnum, RequestHttpEnum,
RequestContentTypeEnum, RequestContentTypeEnum,
@@ -12,6 +13,29 @@ import {
import { PreviewScaleEnum } from '@/enums/styleEnum' import { PreviewScaleEnum } from '@/enums/styleEnum'
import type { ChartColorsNameType, CustomColorsType, GlobalThemeJsonType } from '@/settings/chartThemes/index' import type { ChartColorsNameType, CustomColorsType, 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 { export enum EditCanvasTypeEnum {
EDIT_LAYOUT_DOM = 'editLayoutDom', EDIT_LAYOUT_DOM = 'editLayoutDom',
@@ -20,13 +44,14 @@ export enum EditCanvasTypeEnum {
SCALE = 'scale', SCALE = 'scale',
USER_SCALE = 'userScale', USER_SCALE = 'userScale',
LOCK_SCALE = 'lockScale', LOCK_SCALE = 'lockScale',
SAVE_STATUS = 'saveStatus',
IS_CREATE = 'isCreate', IS_CREATE = 'isCreate',
IS_DRAG = 'isDrag', IS_DRAG = 'isDrag',
IS_SELECT = 'isSelect', IS_SELECT = 'isSelect',
IS_CODE_EDIT="isCodeEdit" IS_CODE_EDIT="isCodeEdit"
} }
// 编辑区域 // 编辑区域(临时)
export type EditCanvasType = { export type EditCanvasType = {
// 编辑区域 DOM // 编辑区域 DOM
[EditCanvasTypeEnum.EDIT_LAYOUT_DOM]: HTMLElement | null [EditCanvasTypeEnum.EDIT_LAYOUT_DOM]: HTMLElement | null
@@ -43,13 +68,15 @@ export type EditCanvasType = {
[EditCanvasTypeEnum.IS_CREATE]: boolean [EditCanvasTypeEnum.IS_CREATE]: boolean
// 拖拽中 // 拖拽中
[EditCanvasTypeEnum.IS_DRAG]: boolean [EditCanvasTypeEnum.IS_DRAG]: boolean
// 保存状态
[EditCanvasTypeEnum.SAVE_STATUS]: SyncEnum
// 框选中 // 框选中
[EditCanvasTypeEnum.IS_SELECT]: boolean [EditCanvasTypeEnum.IS_SELECT]: boolean
// 代码编辑中 // 代码编辑中
[EditCanvasTypeEnum.IS_CODE_EDIT]: boolean [EditCanvasTypeEnum.IS_CODE_EDIT]: boolean
} }
// 滤镜/背景色/宽高主题等 // 画布数据/滤镜/背景色/宽高主题等
export enum EditCanvasConfigEnum { export enum EditCanvasConfigEnum {
PROJECT_NAME = 'projectName', PROJECT_NAME = 'projectName',
WIDTH = 'width', WIDTH = 'width',
@@ -64,7 +91,14 @@ export enum EditCanvasConfigEnum {
PREVIEW_SCALE_TYPE = 'previewScaleType' 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 [FilterEnum.FILTERS_SHOW]: boolean
// 滤镜-色相 // 滤镜-色相
@@ -143,6 +177,7 @@ export type RecordChartType = {
// Store 枚举 // Store 枚举
export enum ChartEditStoreEnum { export enum ChartEditStoreEnum {
PROJECT_INFO = 'projectInfo',
EDIT_RANGE = 'editRange', EDIT_RANGE = 'editRange',
EDIT_CANVAS = 'editCanvas', EDIT_CANVAS = 'editCanvas',
RIGHT_MENU_SHOW = 'rightMenuShow', RIGHT_MENU_SHOW = 'rightMenuShow',
@@ -204,6 +239,7 @@ export interface RequestConfigType extends RequestPublicConfigType {
// Store 类型 // Store 类型
export interface ChartEditStoreType { export interface ChartEditStoreType {
[ChartEditStoreEnum.PROJECT_INFO]: ProjectInfoType
[ChartEditStoreEnum.EDIT_CANVAS]: EditCanvasType [ChartEditStoreEnum.EDIT_CANVAS]: EditCanvasType
[ChartEditStoreEnum.EDIT_CANVAS_CONFIG]: EditCanvasConfigType [ChartEditStoreEnum.EDIT_CANVAS_CONFIG]: EditCanvasConfigType
[ChartEditStoreEnum.RIGHT_MENU_SHOW]: boolean [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 { useChartHistoryStore } from '@/store/modules/chartHistoryStore/chartHistoryStore'
// 全局设置 // 全局设置
import { useSettingStore } from '@/store/modules/settingStore/settingStore' import { useSettingStore } from '@/store/modules/settingStore/settingStore'
// 历史类型
import { HistoryActionTypeEnum, HistoryItemType, HistoryTargetTypeEnum } from '@/store/modules/chartHistoryStore/chartHistoryStore.d'
// 画布枚举
import { MenuEnum, SyncEnum } from '@/enums/editPageEnum'
import { import {
HistoryActionTypeEnum, getUUID,
HistoryItemType, loadingStart,
HistoryTargetTypeEnum loadingFinish,
} from '@/store/modules/chartHistoryStore/chartHistoryStore.d' loadingError,
import { MenuEnum } from '@/enums/editPageEnum' isString,
import { getUUID, loadingStart, loadingFinish, loadingError, isString, isArray } from '@/utils' isArray
} from '@/utils'
import { import {
ProjectInfoType,
ChartEditStoreEnum, ChartEditStoreEnum,
ChartEditStorage, ChartEditStorage,
ChartEditStoreType, ChartEditStoreType,
@@ -36,6 +44,14 @@ const settingStore = useSettingStore()
export const useChartEditStore = defineStore({ export const useChartEditStore = defineStore({
id: 'useChartEditStore', id: 'useChartEditStore',
state: (): ChartEditStoreType => ({ state: (): ChartEditStoreType => ({
// 项目数据
projectInfo: {
projectId: '',
projectName: '',
remarks: '',
thumbnail: '',
release: false
},
// 画布属性 // 画布属性
editCanvas: { editCanvas: {
// 编辑区域 Dom // 编辑区域 Dom
@@ -55,6 +71,8 @@ export const useChartEditStore = defineStore({
isDrag: false, isDrag: false,
// 框选中 // 框选中
isSelect: false, isSelect: false,
// 同步中
saveStatus: SyncEnum.PENDING,
// 代码编辑中 // 代码编辑中
isCodeEdit: false isCodeEdit: false
}, },
@@ -140,6 +158,9 @@ export const useChartEditStore = defineStore({
componentList: [] componentList: []
}), }),
getters: { getters: {
getProjectInfo(): ProjectInfoType {
return this.projectInfo
},
getMousePosition(): MousePositionType { getMousePosition(): MousePositionType {
return this.mousePosition return this.mousePosition
}, },
@@ -203,6 +224,10 @@ export const useChartEditStore = defineStore({
setEditCanvasConfig<T extends keyof EditCanvasConfigType, K extends EditCanvasConfigType[T]>(key: T, value: K) { setEditCanvasConfig<T extends keyof EditCanvasConfigType, K extends EditCanvasConfigType[T]>(key: T, value: K) {
this.editCanvasConfig[key] = value this.editCanvasConfig[key] = value
}, },
// * 设置 peojectInfo 数据项
setProjectInfo<T extends keyof ProjectInfoType, K extends ProjectInfoType[T]>(key: T, value: K) {
this.projectInfo[key] = value
},
// * 设置右键菜单 // * 设置右键菜单
setRightMenuShow(value: boolean) { setRightMenuShow(value: boolean) {
this.rightMenuShow = value this.rightMenuShow = value

View File

@@ -4,10 +4,10 @@ import { asideCollapsedWidth } from '@/settings/designSetting'
import { SettingStoreType, ToolsStatusEnum } from './settingStore.d' import { SettingStoreType, ToolsStatusEnum } from './settingStore.d'
import { setLocalStorage, getLocalStorage } from '@/utils' import { setLocalStorage, getLocalStorage } from '@/utils'
import { StorageEnum } from '@/enums/storageEnum' import { StorageEnum } from '@/enums/storageEnum'
const { GO_SYSTEM_SETTING_STORE } = StorageEnum const { GO_SETTING_STORE } = StorageEnum
const storageSetting: SettingStoreType = getLocalStorage( const storageSetting: SettingStoreType = getLocalStorage(
GO_SYSTEM_SETTING_STORE GO_SETTING_STORE
) )
// 全局设置 // 全局设置
@@ -48,7 +48,7 @@ export const useSettingStore = defineStore({
this.$patch(state => { this.$patch(state => {
state[key] = value 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 文件对象 * @param { File } file 文件对象
@@ -51,4 +113,4 @@ export const downloadTextFile = (
// 字符内容转变成blob地址 // 字符内容转变成blob地址
const blob = new Blob([content]) const blob = new Blob([content])
downloadByA(URL.createObjectURL(blob), filename, fileSuffix) 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/components'
export * from '@/utils/type' export * from '@/utils/type'
export * from '@/utils/file' export * from '@/utils/file'
export * from '@/utils/http'

View File

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

View File

@@ -1,11 +1,12 @@
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { ResultEnum } from '@/enums/httpEnum' import { ResultEnum, RequestHttpHeaderEnum } from '@/enums/httpEnum'
import { ErrorPageNameMap, PageEnum } from '@/enums/pageEnum' import { ErrorPageNameMap, PageEnum, PreviewEnum } from '@/enums/pageEnum'
import { docPath, giteeSourceCodePath } from '@/settings/pathConst' 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 { StorageEnum } from '@/enums/storageEnum'
import { clearLocalStorage, getLocalStorage } from './storage' import { clearLocalStorage, getLocalStorage, clearCookie } from './storage'
import router from '@/router' import router from '@/router'
import { logoutApi } from '@/api/path'
/** /**
* * 根据名字跳转路由 * * 根据名字跳转路由
@@ -101,11 +102,20 @@ export const reloadRoutePage = () => {
} }
/** /**
* * 退出 * * 退出登录
*/ */
export const logout = () => { export const logout = async () => {
clearLocalStorage(StorageEnum.GO_LOGIN_INFO_STORE) try {
routerTurnByName(PageEnum.BASE_LOGIN_NAME) 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 * @returns object
*/ */
export const fetchRouteParamsLocation = () => { export const fetchRouteParamsLocation = () => {
try { try {
// 防止添加query参数的时候解析ID异常 // 防止添加query参数的时候解析ID异常
return document.location.hash.split('?')[0].split('/').pop() || '' return document.location.hash.split('?')[0].split('/').pop() || ''
@@ -176,19 +186,29 @@ export const goHome = () => {
} }
/** /**
* * 判断是否登录(现阶段是有 login 数据即可) * * 判断是否登录
* @return boolean * @return boolean
*/ */
export const loginCheck = () => { export const loginCheck = () => {
try { try {
const info = getLocalStorage(StorageEnum.GO_LOGIN_INFO_STORE) const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
if (!info) return false if (!info) return false
const decodeInfo = cryptoDecode(info) if (info[SystemStoreEnum.USER_INFO][SystemStoreUserInfoEnum.USER_TOKEN]) {
if (decodeInfo) {
return true return true
} }
return false return false
} catch (error) { } catch (error) {
return false 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

@@ -70,3 +70,41 @@ export const getSessionStorage: (k: string) => any = (k: string) => {
export const clearSessioStorage = (name: string) => { export const clearSessioStorage = (name: string) => {
window.sessionStorage.removeItem(name) 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

@@ -114,29 +114,6 @@ export const isMac = () => {
return /macintosh|mac os x/i.test(navigator.userAgent) 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)
}
}
}
/** /**
* * 挂载监听 * * 挂载监听
*/ */
@@ -357,3 +334,23 @@ export const JSONParse = (data: string) => {
export const setTitle = (title?: string) => { export const setTitle = (title?: string) => {
title && (document.title = title) title && (document.title = title)
} }
/**
* 处理网页关闭事件
*/
export const addWindowUnload = () => {
// 关闭网页出现离开提示
window.onbeforeunload = function (e) {
e = e || window.event
// 兼容IE8和Firefox 4之前的版本
if (e) {
e.returnValue = '您确定要离开当前页面吗?请确认是否保存数据!'
}
// Chrome, Safari, Firefox 4+, Opera 12+ , IE 9+
return '您确定要离开当前页面吗?请确认是否保存数据!'
}
// 返回销毁事件函数
return () => {
window.onbeforeunload = null
}
}

View File

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

View File

@@ -43,6 +43,7 @@ import { RequestContentTypeEnum } from '@/enums/httpEnum'
import { useTargetData } from '../../../hooks/useTargetData.hook' import { useTargetData } from '../../../hooks/useTargetData.hook'
import { RequestGlobalConfig } from './components/RequestGlobalConfig' import { RequestGlobalConfig } from './components/RequestGlobalConfig'
import { RequestTargetConfig } from './components/RequestTargetConfig' import { RequestTargetConfig } from './components/RequestTargetConfig'
import { useSync } from '@/views/chart/hooks/useSync.hook'
import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d' import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
const props = defineProps({ const props = defineProps({
@@ -52,6 +53,9 @@ const props = defineProps({
}) })
const emit = defineEmits(['update:modelShow', 'sendHandle']) const emit = defineEmits(['update:modelShow', 'sendHandle'])
const { targetData } = useTargetData()
const { dataSyncUpdate } = useSync()
// 解构基础配置 // 解构基础配置
const { chartConfig } = toRefs(props.targetData as CreateComponentType) const { chartConfig } = toRefs(props.targetData as CreateComponentType)
const { requestContentType } = toRefs((props.targetData as CreateComponentType).request) const { requestContentType } = toRefs((props.targetData as CreateComponentType).request)
@@ -78,6 +82,7 @@ const closeHandle = () => {
const closeAndSendHandle = () => { const closeAndSendHandle = () => {
emit('update:modelShow', false) emit('update:modelShow', false)
emit('sendHandle') emit('sendHandle')
dataSyncUpdate()
} }
const onEsc = () => { const onEsc = () => {

View File

@@ -54,6 +54,7 @@ import { useTargetData } from '../../../hooks/useTargetData.hook'
import { RequestGlobalConfig } from './components/RequestGlobalConfig' import { RequestGlobalConfig } from './components/RequestGlobalConfig'
import { RequestTargetConfig } from './components/RequestTargetConfig' import { RequestTargetConfig } from './components/RequestTargetConfig'
import { RequestDataPondItemType } from '@/store/modules/chartEditStore/chartEditStore.d' import { RequestDataPondItemType } from '@/store/modules/chartEditStore/chartEditStore.d'
import { useSync } from '@/views/chart/hooks/useSync.hook'
import { goDialog } from '@/utils' import { goDialog } from '@/utils'
const props = defineProps({ const props = defineProps({
@@ -62,6 +63,7 @@ const props = defineProps({
}) })
const emit = defineEmits(['update:modelShow', 'editSaveHandle']) const emit = defineEmits(['update:modelShow', 'editSaveHandle'])
const { dataSyncUpdate } = useSync()
const pondName = ref() const pondName = ref()
const inputInstRef = ref() const inputInstRef = ref()
const modelShowRef = ref(false) const modelShowRef = ref(false)
@@ -90,6 +92,7 @@ const closeAndSendHandle = () => {
onPositiveCallback: () => { onPositiveCallback: () => {
emit('update:modelShow', false) emit('update:modelShow', false)
emit('editSaveHandle', props.targetDataRequest) emit('editSaveHandle', props.targetDataRequest)
dataSyncUpdate()
} }
}) })
} }

View File

@@ -5,6 +5,8 @@
<edit-history></edit-history> <edit-history></edit-history>
<!-- CTRL按键触发展示 --> <!-- CTRL按键触发展示 -->
<n-text id="keyboard-dress-show" depth="3"></n-text> <n-text id="keyboard-dress-show" depth="3"></n-text>
<n-divider vertical />
<edit-data-sync></edit-data-sync>
</n-space> </n-space>
<n-space class="bottom-ri"> <n-space class="bottom-ri">
@@ -57,7 +59,8 @@ import { SelectInst } from 'naive-ui'
import { reactive, ref, toRefs, watchEffect } from 'vue' import { reactive, ref, toRefs, watchEffect } from 'vue'
import { icon } from '@/plugins' import { icon } from '@/plugins'
import { EditHistory } from '../EditHistory/index' 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 { useDesignStore } from '@/store/modules/designStore/designStore'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d' import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
@@ -152,6 +155,10 @@ $max-width: 670px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: 0 10px;
width: 100%;
min-width: $min-width;
height: 40px;
.bottom-ri { .bottom-ri {
position: relative; position: relative;
top: 15px; 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> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.mr-10 {
margin-right: 10px;
}
.edit-history-popover { .edit-history-popover {
.btn-text { .btn-text {
font-size: 12px; font-size: 12px;

View File

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

View File

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

View File

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

View File

@@ -9,7 +9,7 @@ import { SavePageEnum } from '@/enums/editPageEnum'
import { editToJsonInterval } from '@/settings/designSetting' import { editToJsonInterval } from '@/settings/designSetting'
import { goDialog } from '@/utils' import { goDialog } from '@/utils'
const { updateComponent } = useSync() const { updateComponent, dataSyncUpdate } = useSync()
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
export const syncData = () => { export const syncData = () => {
@@ -17,8 +17,9 @@ export const syncData = () => {
message: '是否覆盖源视图内容,此操作不可撤回?', message: '是否覆盖源视图内容,此操作不可撤回?',
isMaskClosable: true, isMaskClosable: true,
transformOrigin: 'center', transformOrigin: 'center',
onPositiveCallback: () => { onPositiveCallback: async () => {
window['$message'].success('正在同步编辑器...') window['$message'].success('正在同步编辑器...')
dataSyncUpdate && (await dataSyncUpdate())
dispatchEvent(new CustomEvent(SavePageEnum.CHART, { detail: chartEditStore.getStorageInfo() })) dispatchEvent(new CustomEvent(SavePageEnum.CHART, { detail: chartEditStore.getStorageInfo() }))
} }
}) })

View File

@@ -87,13 +87,21 @@ import { onMounted, computed, provide, watch } from 'vue'
import { chartColors } from '@/settings/chartThemes/index' import { chartColors } from '@/settings/chartThemes/index'
import { MenuEnum } from '@/enums/editPageEnum' import { MenuEnum } from '@/enums/editPageEnum'
import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d' import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
import { animationsClass, getFilterStyle, getTransformStyle, getBlendModeStyle, colorCustomMerge } from '@/utils' import {
animationsClass,
getFilterStyle,
getTransformStyle,
getBlendModeStyle,
colorCustomMerge,
addWindowUnload
} from '@/utils'
import { useContextMenu } from '@/views/chart/hooks/useContextMenu.hook' import { useContextMenu } from '@/views/chart/hooks/useContextMenu.hook'
import { MenuOptionsItemType } from '@/views/chart/hooks/useContextMenu.hook.d' import { MenuOptionsItemType } from '@/views/chart/hooks/useContextMenu.hook.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { SCALE_KEY } from '@/views/preview/hooks/useScale.hook' import { SCALE_KEY } from '@/views/preview/hooks/useScale.hook'
import { useLayout } from './hooks/useLayout.hook' import { useLayout } from './hooks/useLayout.hook'
import { useAddKeyboard } from '../hooks/useKeyboard.hook' import { useAddKeyboard } from '../hooks/useKeyboard.hook'
import { useSync } from '../hooks/useSync.hook'
import { dragHandle, dragoverHandle, mousedownHandleUnStop, useMouseHandle } from './hooks/useDrag.hook' import { dragHandle, dragoverHandle, mousedownHandleUnStop, useMouseHandle } from './hooks/useDrag.hook'
import { useComponentStyle, useSizeStyle } from './hooks/useStyle.hook' import { useComponentStyle, useSizeStyle } from './hooks/useStyle.hook'
import { useInitVChartsTheme } from '@/hooks' import { useInitVChartsTheme } from '@/hooks'
@@ -108,6 +116,10 @@ import { EditTools } from './components/EditTools'
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
const { handleContextMenu } = useContextMenu() const { handleContextMenu } = useContextMenu()
const { dataSyncFetch, intervalDataSyncUpdate } = useSync()
// 加入网页关闭提示
addWindowUnload()
// 编辑时注入scale变量消除警告 // 编辑时注入scale变量消除警告
provide(SCALE_KEY, null) provide(SCALE_KEY, null)
@@ -183,7 +195,12 @@ useInitVChartsTheme(chartEditStore)
// 键盘事件 // 键盘事件
onMounted(() => { onMounted(() => {
// 键盘事件
useAddKeyboard() useAddKeyboard()
// 获取数据
dataSyncFetch()
// 定时更新数据
// intervalDataSyncUpdate()
}) })
</script> </script>

View File

@@ -29,26 +29,44 @@
</template> </template>
<span>{{ item.title }}</span> <span>{{ item.title }}</span>
</n-tooltip> </n-tooltip>
<n-divider vertical />
<!-- 保存 -->
<n-tooltip placement="bottom" trigger="hover">
<template #trigger>
<div class="save-btn" >
<n-button size="small" type="primary" ghost @click="dataSyncUpdate()">
<template #icon>
<n-icon>
<SaveIcon></SaveIcon>
</n-icon>
</template>
</n-button>
</div>
</template>
<span>保存</span>
</n-tooltip>
</n-space> </n-space>
</n-space> </n-space>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { toRefs, Ref, reactive, computed } from 'vue' import { toRefs, ref, Ref, reactive, computed } from 'vue'
import { renderIcon, goDialog, goHome } from '@/utils' import { renderIcon, goDialog, goHome } from '@/utils'
import { icon } from '@/plugins' import { icon } from '@/plugins'
import { useRemoveKeyboard } from '../../hooks/useKeyboard.hook' import { useRemoveKeyboard } from '../../hooks/useKeyboard.hook'
import { useSync } from '../../hooks/useSync.hook'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { useChartHistoryStore } from '@/store/modules/chartHistoryStore/chartHistoryStore' import { useChartHistoryStore } from '@/store/modules/chartHistoryStore/chartHistoryStore'
import { HistoryStackEnum } from '@/store/modules/chartHistoryStore/chartHistoryStore.d' import { HistoryStackEnum } from '@/store/modules/chartHistoryStore/chartHistoryStore.d'
import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore' import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore'
import { ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d' import { ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d'
const { LayersIcon, BarChartIcon, PrismIcon, HomeIcon, ArrowBackIcon, ArrowForwardIcon } = icon.ionicons5 const { LayersIcon, BarChartIcon, PrismIcon, HomeIcon, ArrowBackIcon, ArrowForwardIcon } = icon.ionicons5
const { SaveIcon } = icon.carbon
const { setItem } = useChartLayoutStore() const { setItem } = useChartLayoutStore()
const { dataSyncUpdate } = useSync()
const { getLayers, getCharts, getDetails } = toRefs(useChartLayoutStore()) const { getLayers, getCharts, getDetails } = toRefs(useChartLayoutStore())
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
const chartHistoryStore = useChartHistoryStore() const chartHistoryStore = useChartHistoryStore()
@@ -130,7 +148,7 @@ const clickHistoryHandle = (item: ItemType<HistoryStackEnum>) => {
// 返回首页 // 返回首页
const goHomeHandle = () => { const goHomeHandle = () => {
goDialog({ goDialog({
message: '返回将不会保存任何操作', message: '确定已保存了数据Ctrl / ⌘ + S并返回到首页吗',
isMaskClosable: true, isMaskClosable: true,
onPositiveCallback: () => { onPositiveCallback: () => {
goHome() goHome()

View File

@@ -1,30 +1,92 @@
<template> <template>
<n-space class="go-mt-0" :wrap="false"> <n-space class="go-mt-0" :wrap="false">
<n-button v-for="item in comBtnList" :key="item.title" :type="item.type" ghost @click="item.event"> <n-button v-for="item in comBtnList" :key="item.key" :type="item.type()" ghost @click="item.event">
<template #icon> <template #icon>
<component :is="item.icon"></component> <component :is="item.icon"></component>
</template> </template>
<span>{{ item.title }}</span> <span>{{ item.title() }}</span>
</n-button> </n-button>
</n-space> </n-space>
<!-- 发布管理弹窗 -->
<n-modal v-model:show="modelShow" @afterLeave="closeHandle">
<n-list bordered class="go-system-setting">
<template #header>
<n-space justify="space-between">
<n-h3 class="go-mb-0">发布管理</n-h3>
<n-icon size="20" class="go-cursor-pointer" @click="closeHandle">
<close-icon></close-icon>
</n-icon>
</n-space>
</template>
<n-list-item>
<n-space :size="10">
<n-alert :show-icon="false" title="预览地址:" type="success">
{{ previewPath() }}
</n-alert>
<n-space vertical>
<n-button tertiary type="primary" @click="copyPreviewPath()"> 复制地址 </n-button>
<n-button :type="release ? 'warning' : 'primary'" @click="sendHandle">
{{ release ? '取消发布' : '发布大屏' }}
</n-button>
</n-space>
</n-space>
</n-list-item>
<n-list-item>
<n-space :size="10">
<n-button @click="modelShowHandle">关闭弹窗</n-button>
</n-space>
</n-list-item>
</n-list>
</n-modal>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { ref, computed, watchEffect } from 'vue'
import { renderIcon, goDialog, fetchPathByName, routerTurnByPath, setSessionStorage, getSessionStorage } from '@/utils' import { useRoute } from 'vue-router'
import { useClipboard } from '@vueuse/core'
import { PreviewEnum } from '@/enums/pageEnum' import { PreviewEnum } from '@/enums/pageEnum'
import { StorageEnum } from '@/enums/storageEnum' import { StorageEnum } from '@/enums/storageEnum'
import { useRoute } from 'vue-router' import { ResultEnum } from '@/enums/httpEnum'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { syncData } from '../../ContentEdit/components/EditTools/hooks/useSyncUpdate.hook' import { syncData } from '../../ContentEdit/components/EditTools/hooks/useSyncUpdate.hook'
import { ProjectInfoEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
import { changeProjectReleaseApi } from '@/api/path'
import {
previewPath,
renderIcon,
fetchPathByName,
routerTurnByPath,
setSessionStorage,
getSessionStorage,
httpErrorHandle,
fetchRouteParamsLocation
} from '@/utils'
import { icon } from '@/plugins' import { icon } from '@/plugins'
import { cloneDeep } from 'lodash' import { cloneDeep } from 'lodash'
const { BrowsersOutlineIcon, SendIcon, AnalyticsIcon } = icon.ionicons5 const { BrowsersOutlineIcon, SendIcon, AnalyticsIcon, CloseIcon } = icon.ionicons5
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
const previewPathRef = ref(previewPath())
const { copy, isSupported } = useClipboard({ source: previewPathRef })
const routerParamsInfo = useRoute() const routerParamsInfo = useRoute()
const modelShow = ref<boolean>(false)
const release = ref<boolean>(false)
watchEffect(() => {
release.value = chartEditStore.getProjectInfo.release || false
})
// 关闭弹窗
const closeHandle = () => {
modelShow.value = false
}
// 预览 // 预览
const previewHandle = () => { const previewHandle = () => {
const path = fetchPathByName(PreviewEnum.CHART_PREVIEW_NAME, 'href') const path = fetchPathByName(PreviewEnum.CHART_PREVIEW_NAME, 'href')
@@ -39,7 +101,10 @@ const previewHandle = () => {
const repeateIndex = sessionStorageInfo.findIndex((e: { id: string }) => e.id === previewId) const repeateIndex = sessionStorageInfo.findIndex((e: { id: string }) => e.id === previewId)
// 重复替换 // 重复替换
if (repeateIndex !== -1) { if (repeateIndex !== -1) {
sessionStorageInfo.splice(repeateIndex, 1, { id: previewId, ...storageInfo }) sessionStorageInfo.splice(repeateIndex, 1, {
id: previewId,
...storageInfo
})
setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, sessionStorageInfo) setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, sessionStorageInfo)
} else { } else {
sessionStorageInfo.push({ sessionStorageInfo.push({
@@ -55,35 +120,63 @@ const previewHandle = () => {
routerTurnByPath(path, [previewId], undefined, true) routerTurnByPath(path, [previewId], undefined, true)
} }
// 模态弹窗
const modelShowHandle = () => {
modelShow.value = !modelShow.value
}
// 复制预览地址
const copyPreviewPath = (successText?: string, failureText?: string) => {
if (isSupported) {
copy()
window['$message'].success(successText || '复制成功!')
} else {
window['$message'].error(failureText || '复制失败!')
}
}
// 发布 // 发布
const sendHandle = () => { const sendHandle = async () => {
goDialog({ const res = await changeProjectReleaseApi({
message: '想体验发布功能,请前往 master-fetch 分支查看: https://gitee.com/MTrun/go-view/tree/master-fetch', id: fetchRouteParamsLocation(),
positiveText: '了然', // 反过来
closeNegativeText: true, state: release.value ? -1 : 1
onPositiveCallback: () => {}
}) })
if (res && res.code === ResultEnum.SUCCESS) {
modelShowHandle()
if (!release.value) {
copyPreviewPath('发布成功!已复制地址到剪贴板~', '发布成功!')
} else {
window['$message'].success(`已取消发布`)
}
chartEditStore.setProjectInfo(ProjectInfoEnum.RELEASE, !release.value)
} else {
httpErrorHandle()
}
} }
const btnList = [ const btnList = [
{ {
select: true, select: true,
title: '同步内容', title: () => '同步内容',
type: 'primary', type: () => 'primary',
icon: renderIcon(AnalyticsIcon), icon: renderIcon(AnalyticsIcon),
event: syncData event: syncData
}, },
{ {
select: true, key: 'preview',
title: '预览', title: () => '预览',
type: () => 'default',
icon: renderIcon(BrowsersOutlineIcon), icon: renderIcon(BrowsersOutlineIcon),
event: previewHandle event: previewHandle
}, },
{ {
select: true, key: 'release',
title: '发布', title: () => (release.value ? '已发布' : '发布'),
icon: renderIcon(SendIcon), icon: renderIcon(SendIcon),
event: sendHandle type: () => (release.value ? 'primary' : 'default'),
event: modelShowHandle
} }
] ]
@@ -98,7 +191,15 @@ const comBtnList = computed(() => {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.align-center { @include go('system-setting') {
margin-top: -4px; @extend .go-background-filter;
min-width: 100px;
max-width: 60vw;
padding-bottom: 20px;
@include deep() {
.n-list-item:not(:last-child) {
border-bottom: 0;
}
}
} }
</style> </style>

View File

@@ -28,28 +28,27 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, nextTick, computed } from 'vue' import { ref, nextTick, computed, watchEffect } from 'vue'
import { fetchRouteParamsLocation, setTitle } from '@/utils' import { ResultEnum } from '@/enums/httpEnum'
import { fetchRouteParamsLocation, httpErrorHandle, setTitle } from '@/utils'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d' import { ProjectInfoEnum, EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
import { updateProjectApi } from '@/api/path'
import { useSync } from '../../hooks/useSync.hook'
import { icon } from '@/plugins' import { icon } from '@/plugins'
const { FishIcon } = icon.ionicons5
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
const { dataSyncUpdate } = useSync()
const { FishIcon } = icon.ionicons5
const focus = ref<boolean>(false) const focus = ref<boolean>(false)
const inputInstRef = ref(null) const inputInstRef = ref(null)
// 根据路由 id 参数获取项目信息 const title = ref<string>(fetchRouteParamsLocation())
const fetchProhectInfoById = () => {
const id = fetchRouteParamsLocation()
if (id.length) {
return id[0]
}
return ''
}
const title = ref<string>(fetchProhectInfoById() || '') watchEffect(() => {
title.value = chartEditStore.getProjectInfo.projectName || ''
})
const comTitle = computed(() => { const comTitle = computed(() => {
// eslint-disable-next-line vue/no-side-effects-in-computed-properties // eslint-disable-next-line vue/no-side-effects-in-computed-properties
@@ -67,8 +66,18 @@ const handleFocus = () => {
}) })
} }
const handleBlur = () => { const handleBlur = async () => {
focus.value = false focus.value = false
chartEditStore.setProjectInfo(ProjectInfoEnum.PROJECT_NAME, title.value || '')
const res = (await updateProjectApi({
id: fetchRouteParamsLocation(),
projectName: title.value
}))
if (res && res.code === ResultEnum.SUCCESS) {
dataSyncUpdate()
} else {
httpErrorHandle()
}
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -1,4 +1,5 @@
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { useSync } from './useSync.hook'
import { WinKeyboard, MacKeyboard, MenuEnum } from '@/enums/editPageEnum' import { WinKeyboard, MacKeyboard, MenuEnum } from '@/enums/editPageEnum'
import throttle from 'lodash/throttle' import throttle from 'lodash/throttle'
import debounce from 'lodash/debounce' import debounce from 'lodash/debounce'
@@ -7,7 +8,7 @@ import { setKeyboardDressShow } from '@/utils'
// Keymaster可以支持识别以下组合键shiftoptionaltctrlcontrolcommand和⌘ // Keymaster可以支持识别以下组合键shiftoptionaltctrlcontrolcommand和⌘
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
const useSyncIns = useSync()
const winCtrlMerge = (e: string) => `${WinKeyboard.CTRL}+${e}` const winCtrlMerge = (e: string) => `${WinKeyboard.CTRL}+${e}`
const winShiftMerge = (e: string) => `${WinKeyboard.SHIFT}+${e}` const winShiftMerge = (e: string) => `${WinKeyboard.SHIFT}+${e}`
const winAltMerge = (e: string) => `${WinKeyboard.ALT}+${e}` const winAltMerge = (e: string) => `${WinKeyboard.ALT}+${e}`
@@ -23,6 +24,7 @@ export const winKeyboardValue = {
[MenuEnum.DELETE]: 'delete', [MenuEnum.DELETE]: 'delete',
[MenuEnum.BACK]: winCtrlMerge('z'), [MenuEnum.BACK]: winCtrlMerge('z'),
[MenuEnum.FORWORD]: winCtrlMerge(winShiftMerge('z')), [MenuEnum.FORWORD]: winCtrlMerge(winShiftMerge('z')),
[MenuEnum.SAVE]: winCtrlMerge('s'),
[MenuEnum.GROUP]: winCtrlMerge('g'), [MenuEnum.GROUP]: winCtrlMerge('g'),
[MenuEnum.UN_GROUP]: winCtrlMerge(winShiftMerge('g')), [MenuEnum.UN_GROUP]: winCtrlMerge(winShiftMerge('g')),
[MenuEnum.LOCK]: winCtrlMerge('l'), [MenuEnum.LOCK]: winCtrlMerge('l'),
@@ -48,6 +50,7 @@ export const macKeyboardValue = {
[MenuEnum.DELETE]: macCtrlMerge('backspace'), [MenuEnum.DELETE]: macCtrlMerge('backspace'),
[MenuEnum.BACK]: macCtrlMerge('z'), [MenuEnum.BACK]: macCtrlMerge('z'),
[MenuEnum.FORWORD]: macCtrlMerge(macShiftMerge('z')), [MenuEnum.FORWORD]: macCtrlMerge(macShiftMerge('z')),
[MenuEnum.SAVE]: macCtrlMerge('s'),
[MenuEnum.GROUP]: macCtrlMerge('g'), [MenuEnum.GROUP]: macCtrlMerge('g'),
[MenuEnum.UN_GROUP]: macCtrlMerge(macShiftMerge('g')), [MenuEnum.UN_GROUP]: macCtrlMerge(macShiftMerge('g')),
[MenuEnum.LOCK]: macCtrlMerge('l'), [MenuEnum.LOCK]: macCtrlMerge('l'),
@@ -71,6 +74,7 @@ const winKeyList: Array<string> = [
winKeyboardValue.back, winKeyboardValue.back,
winKeyboardValue.forward, winKeyboardValue.forward,
winKeyboardValue.save,
winKeyboardValue.group, winKeyboardValue.group,
winKeyboardValue.unGroup, winKeyboardValue.unGroup,
@@ -96,6 +100,7 @@ const macKeyList: Array<string> = [
macKeyboardValue.back, macKeyboardValue.back,
macKeyboardValue.forward, macKeyboardValue.forward,
macKeyboardValue.save,
macKeyboardValue.group, macKeyboardValue.group,
macKeyboardValue.unGroup, macKeyboardValue.unGroup,
@@ -215,6 +220,11 @@ export const useAddKeyboard = () => {
case keyboardValue.show: case keyboardValue.show:
keymaster(e, throttle(() => { chartEditStore.setShow(); return false }, throttleTime)) keymaster(e, throttle(() => { chartEditStore.setShow(); return false }, throttleTime))
break; break;
// 保存 ct+s
case keyboardValue.save:
keymaster(e, throttle(() => { useSyncIns.dataSyncUpdate(); return false }, 200))
break;
} }
} }
winKeyList.forEach((key: string) => { winKeyList.forEach((key: string) => {

View File

@@ -1,11 +1,23 @@
import { getUUID } from '@/utils' import { onUnmounted } from 'vue';
import html2canvas from 'html2canvas'
import { getUUID, httpErrorHandle, fetchRouteParamsLocation, base64toFile, JSONStringify, JSONParse } from '@/utils'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { ChartEditStoreEnum, ChartEditStorage } from '@/store/modules/chartEditStore/chartEditStore.d' import { EditCanvasTypeEnum, ChartEditStoreEnum, ProjectInfoEnum, ChartEditStorage } from '@/store/modules/chartEditStore/chartEditStore.d'
import { useChartHistoryStore } from '@/store/modules/chartHistoryStore/chartHistoryStore' import { useChartHistoryStore } from '@/store/modules/chartHistoryStore/chartHistoryStore'
import { StylesSetting } from '@/components/Pages/ChartItemSetting'
import { useSystemStore } from '@/store/modules/systemStore/systemStore'
import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore' import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore'
import { ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d' import { ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d'
import { fetchChartComponent, fetchConfigComponent, createComponent } from '@/packages/index' import { fetchChartComponent, fetchConfigComponent, createComponent } from '@/packages/index'
import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d' import { saveInterval } from '@/settings/designSetting'
import throttle from 'lodash/throttle'
// 接口状态
import { ResultEnum } from '@/enums/httpEnum'
// 接口
import { saveProjectApi, fetchProjectApi, uploadFile, updateProjectApi } from '@/api/path'
// 画布枚举
import { SyncEnum } from '@/enums/editPageEnum'
import { CreateComponentType, CreateComponentGroupType, ConfigType } from '@/packages/index.d'
import { BaseEvent, EventLife } from '@/enums/eventEnum' import { BaseEvent, EventLife } from '@/enums/eventEnum'
import { PublicGroupConfigClass } from '@/packages/public/publicConfig' import { PublicGroupConfigClass } from '@/packages/public/publicConfig'
import merge from 'lodash/merge' import merge from 'lodash/merge'
@@ -89,6 +101,7 @@ const componentMerge = (newObject: any, sources: any, notComponent = false) => {
export const useSync = () => { export const useSync = () => {
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
const chartHistoryStore = useChartHistoryStore() const chartHistoryStore = useChartHistoryStore()
const systemStore = useSystemStore()
const chartLayoutStore = useChartLayoutStore() const chartLayoutStore = useChartLayoutStore()
/** /**
* * 组件动态注册 * * 组件动态注册
@@ -205,7 +218,142 @@ export const useSync = () => {
chartLayoutStore.setItemUnHandle(ChartLayoutStoreEnum.PERCENTAGE, 0) chartLayoutStore.setItemUnHandle(ChartLayoutStoreEnum.PERCENTAGE, 0)
} }
/**
* * 赋值全局数据
* @param projectData 项目数据
* @returns
*/
const updateStoreInfo = (projectData: {
id: string,
projectName: string,
indexImage: string,
remarks: string,
state: number
}) => {
const { id, projectName, remarks, indexImage, state } = projectData
// ID
chartEditStore.setProjectInfo(ProjectInfoEnum.PROJECT_ID, id)
// 名称
chartEditStore.setProjectInfo(ProjectInfoEnum.PROJECT_NAME, projectName)
// 描述
chartEditStore.setProjectInfo(ProjectInfoEnum.REMARKS, remarks)
// 缩略图
chartEditStore.setProjectInfo(ProjectInfoEnum.THUMBNAIL, indexImage)
// 发布
chartEditStore.setProjectInfo(ProjectInfoEnum.RELEASE, state === 1)
}
// * 数据获取
const dataSyncFetch = async () => {
// FIX:重新执行dataSyncFetch需清空chartEditStore.componentList,否则会导致图层重复
// 切换语言等操作会导致重新执行 dataSyncFetch,此时pinia中并未清空chartEditStore.componentList导致图层重复
chartEditStore.componentList = []
chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.START)
try {
const res = await fetchProjectApi({ projectId: fetchRouteParamsLocation() })
if (res && res.code === ResultEnum.SUCCESS) {
if (res.data) {
updateStoreInfo(res.data)
// 更新全局数据
await updateComponent(JSONParse(res.data.content))
return
}else {
chartEditStore.setProjectInfo(ProjectInfoEnum.PROJECT_ID, fetchRouteParamsLocation())
}
setTimeout(() => {
chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.SUCCESS)
}, 1000)
return
}
chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.FAILURE)
} catch (error) {
chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.FAILURE)
httpErrorHandle()
}
}
// * 数据保存
const dataSyncUpdate = throttle(async (updateImg = true) => {
if(!fetchRouteParamsLocation()) return
let projectId = chartEditStore.getProjectInfo[ProjectInfoEnum.PROJECT_ID];
if(projectId === null || projectId === ''){
window['$message'].error('数据初未始化成功,请刷新页面!')
return
}
chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.START)
// 异常处理缩略图上传失败不影响JSON的保存
try {
if (updateImg) {
// 获取缩略图片
const range = document.querySelector('.go-edit-range') as HTMLElement
// 生成图片
const canvasImage: HTMLCanvasElement = await html2canvas(range, {
backgroundColor: null,
allowTaint: true,
useCORS: true
})
// 上传预览图
let uploadParams = new FormData()
uploadParams.append('object', base64toFile(canvasImage.toDataURL(), `${fetchRouteParamsLocation()}_index_preview.png`))
const uploadRes = await uploadFile(uploadParams)
// 保存预览图
if(uploadRes && uploadRes.code === ResultEnum.SUCCESS) {
if (uploadRes.data.fileurl) {
await updateProjectApi({
id: fetchRouteParamsLocation(),
indexImage: `${uploadRes.data.fileurl}`
})
} else {
await updateProjectApi({
id: fetchRouteParamsLocation(),
indexImage: `${systemStore.getFetchInfo.OSSUrl}${uploadRes.data.fileName}`
})
}
}
}
} catch (e) {
console.log(e)
}
// 保存数据
let params = new FormData()
params.append('projectId', projectId)
params.append('content', JSONStringify(chartEditStore.getStorageInfo() || {}))
const res= await saveProjectApi(params)
if (res && res.code === ResultEnum.SUCCESS) {
// 成功状态
setTimeout(() => {
chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.SUCCESS)
}, 1000)
return
}
// 失败状态
chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.FAILURE)
}, 3000)
// * 定时处理
const intervalDataSyncUpdate = () => {
// 定时获取数据
const syncTiming = setInterval(() => {
dataSyncUpdate()
}, saveInterval * 1000)
// 销毁
onUnmounted(() => {
clearInterval(syncTiming)
})
}
return { return {
updateComponent updateComponent,
updateStoreInfo,
dataSyncFetch,
dataSyncUpdate,
intervalDataSyncUpdate
} }
} }

View File

@@ -35,7 +35,7 @@
lineNumbers: 'on', lineNumbers: 'on',
minimap: { enabled: true } minimap: { enabled: true }
}" }"
/> />
</n-layout-content> </n-layout-content>
</n-layout> </n-layout>
</div> </div>
@@ -46,11 +46,17 @@ import { ref } from 'vue'
import { MonacoEditor } from '@/components/Pages/MonacoEditor' import { MonacoEditor } from '@/components/Pages/MonacoEditor'
import { SavePageEnum } from '@/enums/editPageEnum' import { SavePageEnum } from '@/enums/editPageEnum'
import { getSessionStorageInfo } from '../preview/utils' import { getSessionStorageInfo } from '../preview/utils'
import { setSessionStorage, JSONStringify, JSONParse, setTitle, goDialog } from '@/utils' import { setSessionStorage, fetchRouteParamsLocation, JSONStringify, JSONParse, setTitle, goDialog } from '@/utils'
import { StorageEnum } from '@/enums/storageEnum' import { StorageEnum } from '@/enums/storageEnum'
import { icon } from '@/plugins' import { icon } from '@/plugins'
import { useSync } from '@/views/chart/hooks/useSync.hook'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { ProjectInfoEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
import type { ChartEditStorageType } from '../preview/index.d' import type { ChartEditStorageType } from '../preview/index.d'
const chartEditStore = useChartEditStore()
const { dataSyncUpdate } = useSync()
const { ChevronBackOutlineIcon, DownloadIcon, AnalyticsIcon } = icon.ionicons5 const { ChevronBackOutlineIcon, DownloadIcon, AnalyticsIcon } = icon.ionicons5
const showOpenFilePicker: Function = (window as any).showOpenFilePicker const showOpenFilePicker: Function = (window as any).showOpenFilePicker
const content = ref('') const content = ref('')
@@ -122,11 +128,16 @@ async function updateSync() {
message: '是否覆盖源视图内容? 此操作不可撤!', message: '是否覆盖源视图内容? 此操作不可撤!',
isMaskClosable: true, isMaskClosable: true,
transformOrigin: 'center', transformOrigin: 'center',
onPositiveCallback: () => { onPositiveCallback: async () => {
try { try {
const detail = JSONParse(content.value) const detail = JSONParse(content.value)
delete detail.id delete detail.id
// 保持id不变 // 保持id不变
// 带后端版本额外处理请求
if (dataSyncUpdate) {
chartEditStore.setProjectInfo(ProjectInfoEnum.PROJECT_ID, fetchRouteParamsLocation())
await dataSyncUpdate(false) // JSON界面保存不上传缩略图
}
window.opener.dispatchEvent(new CustomEvent(SavePageEnum.JSON, { detail })) window.opener.dispatchEvent(new CustomEvent(SavePageEnum.JSON, { detail }))
window['$message'].success('正在同步内容...') window['$message'].success('正在同步内容...')
} catch (e) { } catch (e) {

View File

@@ -4,7 +4,7 @@
<img src="~@/assets/images/exception/403.svg" alt="" /> <img src="~@/assets/images/exception/403.svg" alt="" />
</div> </div>
<div class="text-center"> <div class="text-center">
<h1 class="text-base text-gray-500">抱歉你无权访问该页面</h1> <h1>抱歉你无权访问该页面</h1>
</div> </div>
<n-button type="primary" @click="goHome">回到首页</n-button> <n-button type="primary" @click="goHome">回到首页</n-button>
</div> </div>

View File

@@ -4,7 +4,7 @@
<img src="~@/assets/images/exception/404.svg" alt="" /> <img src="~@/assets/images/exception/404.svg" alt="" />
</div> </div>
<div class="text-center"> <div class="text-center">
<h1 class="text-base text-gray-500">抱歉你访问的页面不存在</h1> <h1>抱歉你访问的页面不存在</h1>
</div> </div>
<n-button type="primary" @click="goHome">回到首页</n-button> <n-button type="primary" @click="goHome">回到首页</n-button>
</div> </div>

View File

@@ -4,9 +4,9 @@
<img src="~@/assets/images/exception/500.svg" alt="" /> <img src="~@/assets/images/exception/500.svg" alt="" />
</div> </div>
<div class="text-center"> <div class="text-center">
<h1 class="text-base text-gray-500">抱歉服务器出错了</h1> <h1 class="text-base text-gray-500">抱歉服务器出错了建议您重新登录呢</h1>
</div> </div>
<n-button type="primary" secondary @click="goHome">回到首页</n-button> <n-button type="primary" secondary @click="goLogin">重新登录</n-button>
</div> </div>
</template> </template>
@@ -14,8 +14,8 @@
import { PageEnum } from '@/enums/pageEnum' import { PageEnum } from '@/enums/pageEnum'
import { routerTurnByName } from '@/utils' import { routerTurnByName } from '@/utils'
function goHome() { function goLogin() {
routerTurnByName(PageEnum.BASE_HOME_NAME) routerTurnByName(PageEnum.BASE_LOGIN_NAME)
} }
</script> </script>

View File

@@ -117,42 +117,29 @@
import { reactive, ref, onMounted } from 'vue' import { reactive, ref, onMounted } from 'vue'
import shuffle from 'lodash/shuffle' import shuffle from 'lodash/shuffle'
import { carouselInterval } from '@/settings/designSetting' import { carouselInterval } from '@/settings/designSetting'
import { useDesignStore } from '@/store/modules/designStore/designStore' import { useSystemStore } from '@/store/modules/systemStore/systemStore'
import { SystemStoreUserInfoEnum, SystemStoreEnum } from '@/store/modules/systemStore/systemStore.d'
import { GoThemeSelect } from '@/components/GoThemeSelect' import { GoThemeSelect } from '@/components/GoThemeSelect'
import { GoLangSelect } from '@/components/GoLangSelect' import { GoLangSelect } from '@/components/GoLangSelect'
import { LayoutHeader } from '@/layout/components/LayoutHeader' import { LayoutHeader } from '@/layout/components/LayoutHeader'
import { LayoutFooter } from '@/layout/components/LayoutFooter' import { LayoutFooter } from '@/layout/components/LayoutFooter'
import { PageEnum } from '@/enums/pageEnum' import { PageEnum } from '@/enums/pageEnum'
import { icon } from '@/plugins'
import { StorageEnum } from '@/enums/storageEnum' import { StorageEnum } from '@/enums/storageEnum'
import { routerTurnByName, cryptoEncode, setLocalStorage } from '@/utils' import { icon } from '@/plugins'
const { GO_LOGIN_INFO_STORE } = StorageEnum import { routerTurnByName } from '@/utils'
import { loginApi } from '@/api/path'
const { PersonOutlineIcon, LockClosedOutlineIcon } = icon.ionicons5 const { PersonOutlineIcon, LockClosedOutlineIcon } = icon.ionicons5
interface FormState {
username: string
password: string
}
const formRef = ref() const formRef = ref()
const loading = ref(false) const loading = ref(false)
const autoLogin = ref(true) const autoLogin = ref(true)
const show = ref(false) const show = ref(false)
const showBg = ref(false) const showBg = ref(false)
const designStore = useDesignStore() const systemStore = useSystemStore()
const t = window['$t'] const t = window['$t']
onMounted(() => {
setTimeout(() => {
show.value = true
}, 300)
setTimeout(() => {
showBg.value = true
}, 100)
})
const formInline = reactive({ const formInline = reactive({
username: 'admin', username: 'admin',
password: '123456', password: '123456',
@@ -195,38 +182,58 @@ const getImageUrl = (name: string, folder: string) => {
return new URL(`../../assets/images/${folder}/${name}.png`, import.meta.url).href return new URL(`../../assets/images/${folder}/${name}.png`, import.meta.url).href
} }
// 打乱 // 打乱图片顺序
const shuffleHandle = () => { const shuffleHandle = () => {
shuffleTimiing.value = setInterval(() => { shuffleTimiing.value = setInterval(() => {
bgList.value = shuffle(bgList.value) bgList.value = shuffle(bgList.value)
}, carouselInterval) }, carouselInterval)
} }
// 点击事件 // 登录
const handleSubmit = (e: Event) => { const handleSubmit = async (e: Event) => {
e.preventDefault() e.preventDefault()
formRef.value.validate(async (errors: any) => { formRef.value.validate(async (errors: any) => {
if (!errors) { if (!errors) {
const { username, password } = formInline const { username, password } = formInline
loading.value = true loading.value = true
setLocalStorage( // 提交请求
GO_LOGIN_INFO_STORE, const res = await loginApi({
cryptoEncode( username,
JSON.stringify({ password
username, })
password, if(res && res.data) {
}) const { tokenValue, tokenName } = res.data.token
) const { nickname, username, id } = res.data.userinfo
)
window['$message'].success(`${t('login.login_success')}!`) // 存储到 pinia
routerTurnByName(PageEnum.BASE_HOME_NAME, true) systemStore.setItem(SystemStoreEnum.USER_INFO, {
[SystemStoreUserInfoEnum.USER_TOKEN]: tokenValue,
[SystemStoreUserInfoEnum.TOKEN_NAME]: tokenName,
[SystemStoreUserInfoEnum.USER_ID]: id,
[SystemStoreUserInfoEnum.USER_NAME]: username,
[SystemStoreUserInfoEnum.NICK_NAME]: nickname,
t
})
window['$message'].success(t('login.login_success'))
routerTurnByName(PageEnum.BASE_HOME_NAME, true)
}
loading.value = false
} else { } else {
window['$message'].error(`${t('login.login_message')}!`) window['$message'].error(t('login.login_message'))
} }
}) })
} }
onMounted(() => { onMounted(() => {
setTimeout(() => {
show.value = true
}, 300)
setTimeout(() => {
showBg.value = true
}, 100)
shuffleHandle() shuffleHandle()
}) })
</script> </script>

View File

@@ -8,7 +8,7 @@ export const useComInstall = (localStorageInfo: ChartEditStorageType) => {
// 注册组件(一开始无法获取window['$vue']) // 注册组件(一开始无法获取window['$vue'])
const intervalTiming = setInterval(() => { const intervalTiming = setInterval(() => {
if (window['$vue'].component) { if (window['$vue']?.component) {
clearInterval(intervalTiming) clearInterval(intervalTiming)
const intComponent = (target: CreateComponentType) => { const intComponent = (target: CreateComponentType) => {

View File

@@ -6,6 +6,7 @@ import { PreviewScaleEnum } from '@/enums/styleEnum'
export const SCALE_KEY = 'scale-value' export const SCALE_KEY = 'scale-value'
export const useScale = (localStorageInfo: ChartEditStorageType) => { export const useScale = (localStorageInfo: ChartEditStorageType) => {
const entityRef = ref() const entityRef = ref()
const previewRef = ref() const previewRef = ref()
const width = ref(localStorageInfo.editCanvasConfig.width) const width = ref(localStorageInfo.editCanvasConfig.width)

View File

@@ -1,5 +1,6 @@
import { ChartEditStorage } from '@/store/modules/chartEditStore/chartEditStore.d' import { ChartEditStorage } from '@/store/modules/chartEditStore/chartEditStore.d'
export interface ChartEditStorageType extends ChartEditStorage { export interface ChartEditStorageType extends ChartEditStorage {
id: string id: string,
isRelease?: boolean
} }

View File

@@ -1,6 +1,8 @@
import { getSessionStorage } from '@/utils' import { getSessionStorage, fetchRouteParamsLocation, httpErrorHandle, JSONParse } from '@/utils'
import { ResultEnum } from '@/enums/httpEnum'
import { StorageEnum } from '@/enums/storageEnum' import { StorageEnum } from '@/enums/storageEnum'
import { ChartEditStorage } from '@/store/modules/chartEditStore/chartEditStore.d' import { ChartEditStorage } from '@/store/modules/chartEditStore/chartEditStore.d'
import { fetchProjectApi } from '@/api/path'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
@@ -10,16 +12,31 @@ export interface ChartEditStorageType extends ChartEditStorage {
} }
// 根据路由 id 获取存储数据的信息 // 根据路由 id 获取存储数据的信息
export const getSessionStorageInfo = () => { export const getSessionStorageInfo = async () => {
const urlHash = document.location.hash const id = fetchRouteParamsLocation()
const toPathArray = urlHash.split('/') const storageList: ChartEditStorageType[] = getSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST)
const id = toPathArray && toPathArray[toPathArray.length - 1]
const storageList: ChartEditStorageType[] = getSessionStorage( // 是否本地预览
StorageEnum.GO_CHART_STORAGE_LIST if (!storageList || storageList.findIndex(e => e.id === id.toString()) === -1) {
) // 接口调用
const res = await fetchProjectApi({ projectId: id })
if (storageList) { if (res && res.code === ResultEnum.SUCCESS) {
const { content, state } = res.data
if (state === -1) {
// 跳转未发布页
return { isRelease: false }
}
const parseData = { ...JSONParse(content), id }
const { editCanvasConfig, requestGlobalConfig, componentList } = parseData
chartEditStore.editCanvasConfig = editCanvasConfig
chartEditStore.requestGlobalConfig = requestGlobalConfig
chartEditStore.componentList = componentList
return parseData
} else {
httpErrorHandle()
}
} else {
// 本地读取
for (let i = 0; i < storageList.length; i++) { for (let i = 0; i < storageList.length; i++) {
if (id.toString() === storageList[i]['id']) { if (id.toString() === storageList[i]['id']) {
const { editCanvasConfig, requestGlobalConfig, componentList } = storageList[i] const { editCanvasConfig, requestGlobalConfig, componentList } = storageList[i]
@@ -30,4 +47,4 @@ export const getSessionStorageInfo = () => {
} }
} }
} }
} }

View File

@@ -27,6 +27,16 @@
import { ProjectLayoutSider } from './layout/components/ProjectLayoutSider' import { ProjectLayoutSider } from './layout/components/ProjectLayoutSider'
import { LayoutHeaderPro } from '@/layout/components/LayoutHeaderPro' import { LayoutHeaderPro } from '@/layout/components/LayoutHeaderPro'
import { LayoutTransitionMain } from '@/layout/components/LayoutTransitionMain/index' import { LayoutTransitionMain } from '@/layout/components/LayoutTransitionMain/index'
import { goDialog } from '@/utils'
// 提示
goDialog({
message: '不要在官方后端上发布任何私密数据,任何人都看得到并进行删除!!!!',
isMaskClosable: true,
closeNegativeText: true,
transformOrigin: 'center',
onPositiveCallback: () => {}
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -7,7 +7,7 @@
<mac-os-control-btn <mac-os-control-btn
class="top-btn" class="top-btn"
:hidden="['remove']" :hidden="['remove']"
@close="deleteHanlde" @close="deleteHandle"
@resize="resizeHandle" @resize="resizeHandle"
></mac-os-control-btn> ></mac-os-control-btn>
</div> </div>
@@ -17,9 +17,7 @@
object-fit="contain" object-fit="contain"
height="180" height="180"
preview-disabled preview-disabled
:src=" :src="`${cardData.image}?time=${new Date().getTime()}`"
requireUrl('project/moke-20211219181327.png')
"
:alt="cardData.title" :alt="cardData.title"
:fallback-src="requireErrorImg()" :fallback-src="requireErrorImg()"
></n-image> ></n-image>
@@ -27,8 +25,8 @@
</div> </div>
<template #action> <template #action>
<div class="go-flex-items-center list-footer" justify="space-between"> <div class="go-flex-items-center list-footer" justify="space-between">
<n-text class="go-ellipsis-1" :title="cardData.title"> <n-text class="go-ellipsis-1">
{{ cardData.title || '' }} {{ cardData.title || cardData.id || '未命名' }}
</n-text> </n-text>
<!-- 工具 --> <!-- 工具 -->
<div class="go-flex-items-center list-footer-ri"> <div class="go-flex-items-center list-footer-ri">
@@ -75,8 +73,8 @@
</n-tooltip> </n-tooltip>
</template> </template>
</n-space> </n-space>
</div>
<!-- end --> <!-- end -->
</div>
</div> </div>
</template> </template>
</n-card> </n-card>
@@ -101,17 +99,12 @@ const {
SendIcon SendIcon
} = icon.ionicons5 } = icon.ionicons5
const emit = defineEmits(['delete', 'resize', 'edit']) const emit = defineEmits(['preview', 'delete', 'resize', 'edit', 'release'])
const props = defineProps({ const props = defineProps({
cardData: Object as PropType<Chartype> cardData: Object as PropType<Chartype>
}) })
// 处理url获取
const requireUrl = (name: string) => {
return new URL(`../../../../../assets/images/${name}`, import.meta.url).href
}
const fnBtnList = reactive([ const fnBtnList = reactive([
{ {
label: renderLang('global.r_edit'), label: renderLang('global.r_edit'),
@@ -135,7 +128,7 @@ const selectOptions = ref([
label: props.cardData?.release label: props.cardData?.release
? renderLang('global.r_unpublish') ? renderLang('global.r_unpublish')
: renderLang('global.r_publish'), : renderLang('global.r_publish'),
key: 'send', key: 'release',
icon: renderIcon(SendIcon) icon: renderIcon(SendIcon)
}, },
{ {
@@ -147,8 +140,14 @@ const selectOptions = ref([
const handleSelect = (key: string) => { const handleSelect = (key: string) => {
switch (key) { switch (key) {
case 'preview':
previewHandle()
break
case 'delete': case 'delete':
deleteHanlde() deleteHandle()
break
case 'release':
releaseHandle()
break break
case 'edit': case 'edit':
editHandle() editHandle()
@@ -156,8 +155,13 @@ const handleSelect = (key: string) => {
} }
} }
// 预览处理
const previewHandle = () => {
emit('preview', props.cardData)
}
// 删除处理 // 删除处理
const deleteHanlde = () => { const deleteHandle = () => {
emit('delete', props.cardData) emit('delete', props.cardData)
} }
@@ -166,6 +170,11 @@ const editHandle = () => {
emit('edit', props.cardData) emit('edit', props.cardData)
} }
// 编辑处理
const releaseHandle = () => {
emit('release', props.cardData)
}
// 放大处理 // 放大处理
const resizeHandle = () => { const resizeHandle = () => {
emit('resize', props.cardData) emit('resize', props.cardData)

View File

@@ -1,58 +1,124 @@
import { ref } from 'vue' import { ref, reactive } from 'vue'
import { goDialog } from '@/utils' import { goDialog, httpErrorHandle } from '@/utils'
import { DialogEnum } from '@/enums/pluginEnum' import { DialogEnum } from '@/enums/pluginEnum'
import { ChartList } from '../../..' import { projectListApi, deleteProjectApi, changeProjectReleaseApi } from '@/api/path'
import { Chartype, ChartList } from '../../../index.d'
import { ResultEnum } from '@/enums/httpEnum'
// 数据初始化 // 数据初始化
export const useDataListInit = () => { export const useDataListInit = () => {
const list = ref<ChartList>([ const loading = ref(true)
{
id: 1,
title: '物料1-假数据不可用',
release: true,
label: '官方案例'
},
{
id: 2,
title: '物料2-假数据不可用',
release: false,
label: '官方案例'
},
{
id: 3,
title: '物料3-假数据不可用',
release: false,
label: '官方案例'
},
{
id: 4,
title: '物料4-假数据不可用',
release: false,
label: '官方案例'
},
{
id: 5,
title: '物料5-假数据不可用',
release: false,
label: '官方案例'
}
])
// 删除 const paginat = reactive({
const deleteHandle = (cardData: object, index: number) => { // 当前页数
page: 1,
// 每页值
limit: 12,
// 总数
count: 10
})
const list = ref<ChartList>([])
// 数据请求
const fetchList = async () => {
loading.value = true
const res = await projectListApi({
page: paginat.page,
limit: paginat.limit
})
if (res && res.data) {
const { count } = res as any // 这里的count与data平级不在Response结构中
paginat.count = count
list.value = res.data.map(e => {
const { id, projectName, state, createTime, indexImage, createUserId } = e
return {
id: id,
title: projectName,
createId: createUserId,
time: createTime,
image: indexImage,
release: state !== -1
}
})
setTimeout(() => {
loading.value = false
}, 500)
return
}
httpErrorHandle()
}
// 修改页数
const changePage = (_page: number) => {
paginat.page = _page
fetchList()
}
// 修改大小
const changeSize = (_size: number) => {
paginat.limit = _size
fetchList()
}
// 删除处理
const deleteHandle = (cardData: Chartype) => {
goDialog({ goDialog({
type: DialogEnum.DELETE, type: DialogEnum.DELETE,
promise: true, promise: true,
onPositiveCallback: () => onPositiveCallback: () =>
new Promise(res => setTimeout(() => res(1), 1000)), new Promise(res => {
promiseResCallback: (e: any) => { res(
window.$message.success('删除成功') deleteProjectApi({
list.value.splice(index, 1) ids: cardData.id
})
)
}),
promiseResCallback: (res: any) => {
if (res.code === ResultEnum.SUCCESS) {
window['$message'].success(window['$t']('global.r_delete_success'))
fetchList()
return
}
httpErrorHandle()
} }
}) })
} }
// 发布处理
const releaseHandle = async (cardData: Chartype, index: number) => {
const { id, release } = cardData
const res = await changeProjectReleaseApi({
id: id,
// [-1未发布, 1发布]
state: !release ? 1 : -1
})
if (res && res.code === ResultEnum.SUCCESS) {
list.value = []
fetchList()
// 发布 -> 未发布
if (release) {
window['$message'].success(window['$t']('global.r_unpublish_success'))
return
}
// 未发布 -> 发布
window['$message'].success(window['$t']('global.r_publish_success'))
return
}
httpErrorHandle()
}
// 立即请求
fetchList()
return { return {
loading,
paginat,
list, list,
fetchList,
releaseHandle,
changeSize,
changePage,
deleteHandle deleteHandle
} }
} }

View File

@@ -1,8 +1,7 @@
import { ref } from 'vue' import { ref } from 'vue'
import { ChartEnum } from '@/enums/pageEnum' import { ChartEnum } from '@/enums/pageEnum'
import { fetchPathByName, routerTurnByPath } from '@/utils' import { fetchPathByName, routerTurnByPath, openNewWindow, previewPath } from '@/utils'
import { Chartype } from '../../../index.d' import { Chartype } from '../../../index.d'
export const useModalDataInit = () => { export const useModalDataInit = () => {
const modalShow = ref<boolean>(false) const modalShow = ref<boolean>(false)
const modalData = ref<Chartype | null>(null) const modalData = ref<Chartype | null>(null)
@@ -13,25 +12,31 @@ export const useModalDataInit = () => {
modalData.value = null modalData.value = null
} }
// 打开 modal // 缩放处理
const resizeHandle = (cardData: Chartype) => { const resizeHandle = (cardData: Chartype) => {
if(!cardData) return if (!cardData) return
modalShow.value = true modalShow.value = true
modalData.value = cardData modalData.value = cardData
} }
// 打开 modal // 编辑处理
const editHandle = (cardData: Chartype) => { const editHandle = (cardData: Chartype) => {
if(!cardData) return if (!cardData) return
const path = fetchPathByName(ChartEnum.CHART_HOME_NAME, 'href') const path = fetchPathByName(ChartEnum.CHART_HOME_NAME, 'href')
routerTurnByPath(path, [cardData.id], undefined, true) routerTurnByPath(path, [cardData.id], undefined, true)
} }
// 预览处理
const previewHandle = (cardData: Chartype) => {
openNewWindow(previewPath(cardData.id))
}
return { return {
modalData, modalData,
modalShow, modalShow,
closeModal, closeModal,
resizeHandle, resizeHandle,
editHandle editHandle,
previewHandle
} }
} }

View File

@@ -1,28 +1,40 @@
<template> <template>
<div class="go-items-list"> <div class="go-items-list">
<n-grid <!-- 加载 -->
:x-gap="20" <div v-show="loading">
:y-gap="20" <go-loading></go-loading>
cols="2 s:2 m:3 l:4 xl:4 xxl:4" </div>
responsive="screen" <!-- 列表 -->
> <div v-show="!loading">
<n-grid-item v-for="(item, index) in list" :key="item.id"> <n-grid :x-gap="20" :y-gap="20" cols="2 s:2 m:3 l:4 xl:4 xxl:4" responsive="screen">
<project-items-card <n-grid-item v-for="(item, index) in list" :key="item.id">
:cardData="item" <project-items-card
@resize="resizeHandle" :cardData="item"
@delete="deleteHandle($event, index)" @preview="previewHandle"
@edit="editHandle" @resize="resizeHandle"
></project-items-card> @delete="deleteHandle(item)"
</n-grid-item> @release="releaseHandle(item, index)"
</n-grid> @edit="editHandle"
></project-items-card>
</n-grid-item>
</n-grid>
</div>
<!-- 分页 -->
<div class="list-pagination"> <div class="list-pagination">
<n-pagination <n-pagination
:item-count="10" :page="paginat.page"
:page-sizes="[10, 20, 30, 40]" :page-size="paginat.limit"
:item-count="paginat.count"
:page-sizes="[12, 24, 36, 48]"
@update:page="changePage"
@update:page-size="changeSize"
show-size-picker show-size-picker
/> />
</div> </div>
</div> </div>
<!-- model -->
<project-items-modal-card <project-items-modal-card
v-if="modalData" v-if="modalData"
:modalShow="modalShow" :modalShow="modalShow"
@@ -40,8 +52,8 @@ import { useModalDataInit } from './hooks/useModal.hook'
import { useDataListInit } from './hooks/useData.hook' import { useDataListInit } from './hooks/useData.hook'
const { CopyIcon, EllipsisHorizontalCircleSharpIcon } = icon.ionicons5 const { CopyIcon, EllipsisHorizontalCircleSharpIcon } = icon.ionicons5
const { list, deleteHandle } = useDataListInit() const { modalData, modalShow, closeModal, previewHandle, resizeHandle, editHandle } = useModalDataInit()
const { modalData, modalShow, closeModal, resizeHandle, editHandle } = useModalDataInit() const { loading, paginat, list, changeSize, changePage, releaseHandle, deleteHandle } = useDataListInit()
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@@ -50,7 +62,7 @@ $contentHeight: 250px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: space-between;
min-height: calc(100vh - #{$--header-height} * 2 - 2px); min-height: calc(100vh - #{$--header-height} - 40px - 2px);
.list-content { .list-content {
position: relative; position: relative;
height: $contentHeight; height: $contentHeight;

View File

@@ -11,7 +11,7 @@
<n-space class="list-content-top go-px-0" justify="center"> <n-space class="list-content-top go-px-0" justify="center">
<n-space> <n-space>
<n-text> <n-text>
{{ cardData?.title || '' }} {{ cardData?.title || cardData?.id || '未命名' }}
</n-text> </n-text>
</n-space> </n-space>
</n-space> </n-space>
@@ -26,9 +26,7 @@
<!-- 中间 --> <!-- 中间 -->
<div class="list-content-img"> <div class="list-content-img">
<img <img
:src=" :src="cardData?.image"
requireUrl('project/moke-20211219181327.png')
"
:alt="cardData?.title" :alt="cardData?.title"
/> />
</div> </div>
@@ -75,10 +73,11 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, watch } from 'vue' import { ref, reactive, PropType, watch } from 'vue'
import { renderIcon, renderLang } from '@/utils' import { renderIcon, renderLang } from '@/utils'
import { icon } from '@/plugins' import { icon } from '@/plugins'
import { MacOsControlBtn } from '@/components/Tips/MacOsControlBtn' import { MacOsControlBtn } from '@/components/Tips/MacOsControlBtn'
import { Chartype } from '../../index.d'
const { HammerIcon } = icon.ionicons5 const { HammerIcon } = icon.ionicons5
const showRef = ref(false) const showRef = ref(false)
@@ -140,12 +139,14 @@ const closeHandle = () => {
<style lang="scss" scoped> <style lang="scss" scoped>
$padding: 30px; $padding: 30px;
$contentHeight: calc(80vh); $contentHeight: calc(80vh);
$imageHeight: calc(80vh - 110px);
$contentWidth: calc(82vw); $contentWidth: calc(82vw);
@include go('modal-box') { @include go('modal-box') {
width: $contentWidth; width: $contentWidth;
height: $contentHeight;
.list-content { .list-content {
margin-top: 28px; margin-top: 20px;
border-radius: $--border-radius-base; border-radius: $--border-radius-base;
overflow: hidden; overflow: hidden;
@include background-image('background-point'); @include background-image('background-point');
@@ -160,8 +161,9 @@ $contentWidth: calc(82vw);
} }
&-img { &-img {
@extend .go-flex-center; @extend .go-flex-center;
padding: 6px 0;
img { img {
max-height: $contentHeight; height: $imageHeight;
min-height: 200px; min-height: 200px;
max-width: 100%; max-width: 100%;
@extend .go-border-radius; @extend .go-border-radius;

View File

@@ -1,8 +1,11 @@
export type Chartype = { export type Chartype = {
id: number | string id: number | string
title: string // 标题 title: string // 标题
label: string // 标签 label?: string // 标签
release: boolean // 0未发布 | 1已发布 time: string, // 时间
image: string, // 预览图地址
createId: string, // 创建者
release: boolean // false 未发布 | true 已发布
} }
export type ChartList = Chartype[] export type ChartList = Chartype[]

View File

@@ -10,6 +10,6 @@ import { ProjectItemsList } from './components/ProjectItemsList'
<style lang="scss" scoped> <style lang="scss" scoped>
@include go(project-items) { @include go(project-items) {
padding: 30px 20px; padding: 20px 20px;
} }
</style> </style>

View File

@@ -18,7 +18,7 @@
:disabled="item.disabled" :disabled="item.disabled"
v-for="item in typeList" v-for="item in typeList"
:key="item.key" :key="item.key"
@click="btnHandle" @click="btnHandle(item.key)"
> >
<component :is="item.title"></component> <component :is="item.title"></component>
<template #icon> <template #icon>
@@ -38,7 +38,9 @@
import { ref, watch, shallowRef } from 'vue' import { ref, watch, shallowRef } from 'vue'
import { icon } from '@/plugins' import { icon } from '@/plugins'
import { PageEnum, ChartEnum } from '@/enums/pageEnum' import { PageEnum, ChartEnum } from '@/enums/pageEnum'
import { ResultEnum } from '@/enums/httpEnum'
import { fetchPathByName, routerTurnByPath, renderLang, getUUID } from '@/utils' import { fetchPathByName, routerTurnByPath, renderLang, getUUID } from '@/utils'
import { createProjectApi } from '@/api/path'
const { FishIcon, CloseIcon } = icon.ionicons5 const { FishIcon, CloseIcon } = icon.ionicons5
const { StoreIcon, ObjectStorageIcon } = icon.carbon const { StoreIcon, ObjectStorageIcon } = icon.carbon
@@ -70,8 +72,8 @@ const typeList = shallowRef([
} }
]) ])
watch(props, newValue => { watch(() => props.show, newValue => {
showRef.value = newValue.show showRef.value = newValue
}) })
// 关闭对话框 // 关闭对话框
@@ -80,11 +82,32 @@ const closeHandle = () => {
} }
// 处理按钮点击 // 处理按钮点击
const btnHandle = (key: string) => { const btnHandle = async (key: string) => {
closeHandle() switch (key) {
const id = getUUID() case ChartEnum.CHART_HOME_NAME:
const path = fetchPathByName(ChartEnum.CHART_HOME_NAME, 'href') try {
routerTurnByPath(path, [id], undefined, true) // 新增项目
const res = await createProjectApi({
// 项目名称
projectName: getUUID(),
// remarks
remarks: null,
// 图片地址
indexImage: null,
})
if(res && res.code === ResultEnum.SUCCESS) {
window['$message'].success(window['$t']('project.create_success'))
const { id } = res.data
const path = fetchPathByName(ChartEnum.CHART_HOME_NAME, 'href')
routerTurnByPath(path, [id], undefined, true)
closeHandle()
}
} catch (error) {
window['$message'].error(window['$t']('project.create_failure'))
}
break;
}
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -0,0 +1,35 @@
<template>
<div class="go-redirect-un-publish">
<div class="text-center">
<img src="~@/assets/images/exception/nodata.svg" alt="" />
</div>
<div class="text-center">
<h1>当前项目暂未发布</h1>
</div>
</div>
</template>
<style lang="scss" scoped>
@include go(redirect-un-publish) {
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
width: 100vw;
height: 100vh;
overflow: hidden;
padding: 100px 0;
@include background-image('background-image');
.text-center {
h1 {
color: #666;
padding: 20px 0;
}
}
img {
width: 350px;
margin: 0 auto;
}
}
</style>

View File

@@ -1,9 +1,11 @@
<template> <template>
<n-empty description="你什么也找不到"> <div class="go-redirect">
<template #extra> <n-empty description="你什么也找不到">
<n-button size="small" @click="goHome">看看别的</n-button> <template #extra>
</template> <n-button size="small" @click="goHome">看看别的</n-button>
</n-empty> </template>
</n-empty>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { onBeforeMount } from 'vue' import { onBeforeMount } from 'vue'
@@ -14,3 +16,16 @@ const goHome = () => {
router.replace({ path: '/' }) router.replace({ path: '/' })
} }
</script> </script>
<style lang="scss" scoped>
@include go(redirect) {
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
width: 100vw;
height: 100vh;
overflow: hidden;
padding: 100px 0;
@include background-image('background-image');
}
</style>

2
types/vite-env.d.ts vendored
View File

@@ -1,8 +1,6 @@
/// <reference types="vite/client" /> /// <reference types="vite/client" />
interface ImportMetaEnv { interface ImportMetaEnv {
// 标题
VITE_GLOB_APP_TITLE: string;
// 端口 // 端口
VITE_DEV_PORT: string; VITE_DEV_PORT: string;
// 开发地址 // 开发地址

View File

@@ -1,8 +1,9 @@
import { defineConfig } from 'vite' import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue' import vue from '@vitejs/plugin-vue'
import { resolve } from 'path' import { resolve } from 'path'
import { OUTPUT_DIR, brotliSize, chunkSizeWarningLimit, terserOptions, rollupOptions } from './build/constant' import { OUTPUT_DIR, brotliSize, chunkSizeWarningLimit, terserOptions, rollupOptions } from './build/constant'
import viteCompression from 'vite-plugin-compression' import viteCompression from 'vite-plugin-compression'
import { axiosPre } from './src/settings/httpSetting'
import { viteMockServe } from 'vite-plugin-mock' import { viteMockServe } from 'vite-plugin-mock'
import monacoEditorPlugin from 'vite-plugin-monaco-editor' import monacoEditorPlugin from 'vite-plugin-monaco-editor'
@@ -10,8 +11,8 @@ function pathResolve(dir: string) {
return resolve(process.cwd(), '.', dir) return resolve(process.cwd(), '.', dir)
} }
export default defineConfig({ export default ({ mode }) => defineConfig({
base: '/', base: process.env.NODE_ENV === 'production' ? './' : '/',
// 路径重定向 // 路径重定向
resolve: { resolve: {
alias: [ alias: [
@@ -39,6 +40,21 @@ export default defineConfig({
} }
} }
}, },
// 开发服务器配置
server: {
host: true,
open: true,
port: 3000,
proxy: {
[axiosPre]: {
// @ts-ignore
target: loadEnv(mode, process.cwd()).VITE_DEV_PATH,
changeOrigin: true,
ws: true,
secure: true,
}
}
},
define: { define: {
// enable hydration mismatch details in production build // enable hydration mismatch details in production build
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'true' __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'true'