mirror of
https://gitee.com/dromara/go-view.git
synced 2026-01-30 00:05:29 +08:00
Compare commits
319 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81e2e4784d | ||
|
|
ff403c5e6a | ||
|
|
d925a8e104 | ||
|
|
d7f0986cec | ||
|
|
278d67945a | ||
|
|
e62f9cbd02 | ||
|
|
131abbb28e | ||
|
|
a54652c072 | ||
|
|
656949f7b8 | ||
|
|
601e1a2ea7 | ||
|
|
c228bc97fb | ||
|
|
75c47dc97e | ||
|
|
b825e41707 | ||
|
|
bb1bfc564d | ||
|
|
e07be55f65 | ||
|
|
0cf5e175cf | ||
|
|
b06b5f252b | ||
|
|
6e55c9951b | ||
|
|
52aeca9dd4 | ||
|
|
87aa938e60 | ||
|
|
006a0edca9 | ||
|
|
58a4a4ca17 | ||
|
|
97bb192696 | ||
|
|
d6f4f20be0 | ||
|
|
d9fec13eae | ||
|
|
634f689f07 | ||
|
|
f4c9787807 | ||
|
|
24bcccdf2b | ||
|
|
6c968d9a24 | ||
|
|
586db5aca1 | ||
|
|
491604527e | ||
|
|
70da85c1e9 | ||
|
|
9dce33ee01 | ||
|
|
e903489a52 | ||
|
|
5b932af6c8 | ||
|
|
84f6bfcb8a | ||
|
|
2f43ddd59b | ||
|
|
45254c3dc4 | ||
|
|
afc6cf04a1 | ||
|
|
5340e89f7d | ||
|
|
4d05697b1c | ||
|
|
68c77760ca | ||
|
|
307480ded2 | ||
|
|
817b25f1a8 | ||
|
|
d457cc7135 | ||
|
|
8f996173b3 | ||
|
|
a06e8fb7a4 | ||
|
|
276bcbe831 | ||
|
|
2c6086edca | ||
|
|
55a6bd93ad | ||
|
|
622fec4e73 | ||
|
|
bdfad88357 | ||
|
|
c8e0b6c474 | ||
|
|
6b7f759071 | ||
|
|
dfe97bf5d5 | ||
|
|
8809022e8c | ||
|
|
fe87d0e433 | ||
|
|
f37264fdbb | ||
|
|
092a252ac4 | ||
|
|
0309c567e6 | ||
|
|
f23439d31f | ||
|
|
03be42b910 | ||
|
|
c3b7711f0a | ||
|
|
0a775af9bb | ||
|
|
15f2d77bec | ||
|
|
2e6611bf8b | ||
|
|
73524283ed | ||
|
|
6038bc8e58 | ||
|
|
5fce7f163e | ||
|
|
3be567ada8 | ||
|
|
2acf1f4351 | ||
|
|
8edc2767f9 | ||
|
|
29339c4c7c | ||
|
|
7836332a97 | ||
|
|
b5fe803059 | ||
|
|
30f1f058c7 | ||
|
|
afe17efde9 | ||
|
|
23e459de94 | ||
|
|
bcbf53d08f | ||
|
|
43aefe7b6e | ||
|
|
b7fda10caf | ||
|
|
824c7a29d8 | ||
|
|
326ad82182 | ||
|
|
92f50f0be2 | ||
|
|
dd0170eecc | ||
|
|
02500aff30 | ||
|
|
c31fa20b02 | ||
|
|
31cdbe2a57 | ||
|
|
5605e6a831 | ||
|
|
aef798c382 | ||
|
|
1922213f8b | ||
|
|
92afc0f366 | ||
|
|
7f9cde3c67 | ||
|
|
effd870897 | ||
|
|
dd7e1692d6 | ||
|
|
a3bbe95643 | ||
|
|
ef39ecb3c6 | ||
|
|
85fe91705b | ||
|
|
7ff21d6156 | ||
|
|
b53dd405a5 | ||
|
|
a53d9c4da2 | ||
|
|
de6b2e8bf9 | ||
|
|
968edea932 | ||
|
|
682419d174 | ||
|
|
e586311744 | ||
|
|
edaa9f7b99 | ||
|
|
0fdbde1cc1 | ||
|
|
3eb1ce7ec5 | ||
|
|
6e3302fed6 | ||
|
|
0d52a8bc5e | ||
|
|
09ac83a62b | ||
|
|
f04864ed7f | ||
|
|
4c968aee18 | ||
|
|
0fd8d11107 | ||
|
|
661b3570a5 | ||
|
|
4ffc6a608b | ||
|
|
2308e1c22b | ||
|
|
2967a6c763 | ||
|
|
327d23ebac | ||
|
|
15c12ca367 | ||
|
|
4351aef5cd | ||
|
|
8186595d84 | ||
|
|
16e58749a7 | ||
|
|
8214b30653 | ||
|
|
7dfa156e30 | ||
|
|
648f4f479e | ||
|
|
dff9ff2caf | ||
|
|
9a4f436b27 | ||
|
|
83e50d6e96 | ||
|
|
2d752f119d | ||
|
|
ab22db62f7 | ||
|
|
cb750c73b9 | ||
|
|
18784d4455 | ||
|
|
08b1c14a1c | ||
|
|
8cf47e9005 | ||
|
|
666841458e | ||
|
|
dafdbeca4b | ||
|
|
5aac8c0546 | ||
|
|
0609b95a28 | ||
|
|
6f9b109022 | ||
|
|
2f6bdcc8c8 | ||
|
|
4886af4bb5 | ||
|
|
b57cf1bf59 | ||
|
|
183349dce8 | ||
|
|
1b9d220abd | ||
|
|
70ee06d622 | ||
|
|
ae7f1bcb3e | ||
|
|
74c9d1df65 | ||
|
|
b270e0ad43 | ||
|
|
7b327df38e | ||
|
|
2ec4f56943 | ||
|
|
367d0a23ca | ||
|
|
4d6b68ee60 | ||
|
|
a34544296a | ||
|
|
e8399875e5 | ||
|
|
d78be0093e | ||
|
|
09fb1aff92 | ||
|
|
b79c2b2fdb | ||
|
|
656adfcf56 | ||
|
|
786458adfe | ||
|
|
31b5a6961b | ||
|
|
babab39710 | ||
|
|
60a2bf7f4f | ||
|
|
9e25e1866d | ||
|
|
781151319c | ||
|
|
d3c3cf86b2 | ||
|
|
5f7d505f20 | ||
|
|
cd8bdc5d1d | ||
|
|
d8117b66ca | ||
|
|
b26a45a7b6 | ||
|
|
37eb0ed357 | ||
|
|
858ee8515d | ||
|
|
7313f8707e | ||
|
|
564f8d0ae2 | ||
|
|
37df8a7fa1 | ||
|
|
8039213380 | ||
|
|
c5a704767d | ||
|
|
20be7f2e45 | ||
|
|
d43823794d | ||
|
|
5e09105a70 | ||
|
|
7d2a98ab85 | ||
|
|
2d302bb468 | ||
|
|
789328b02e | ||
|
|
b93a2a516a | ||
|
|
c8662537ca | ||
|
|
b083bd9724 | ||
|
|
5fd6870cfe | ||
|
|
9004a55b8c | ||
|
|
c349e6384e | ||
|
|
4e298efaa0 | ||
|
|
c7cbb9b72a | ||
|
|
bd5e06350d | ||
|
|
c311dd08e3 | ||
|
|
504a1f4703 | ||
|
|
a67cc9f876 | ||
|
|
e0d2e8031d | ||
|
|
bcec26374f | ||
|
|
a5981a4387 | ||
|
|
0d26dce512 | ||
|
|
6359ec15b3 | ||
|
|
32ca138e6a | ||
|
|
171e0aa408 | ||
|
|
52009a415b | ||
|
|
da809f13b3 | ||
|
|
801aa1f82f | ||
|
|
72c26b71f3 | ||
|
|
3b8181ae10 | ||
|
|
c2a9642393 | ||
|
|
3c04f81147 | ||
|
|
ec28ccf09c | ||
|
|
fa34300401 | ||
|
|
f506ccd2e4 | ||
|
|
f379f7652c | ||
|
|
e8760c81ac | ||
|
|
a9bb294f60 | ||
|
|
0b5f35752b | ||
|
|
7322817cb5 | ||
|
|
437ad1bd9f | ||
|
|
cd20e68480 | ||
|
|
35968475b9 | ||
|
|
78eb3ccc3f | ||
|
|
7cccbabca4 | ||
|
|
cdccfa3e12 | ||
|
|
e8c5455748 | ||
|
|
8e40416e72 | ||
|
|
d058361e01 | ||
|
|
2491f7ff57 | ||
|
|
c5908f6d92 | ||
|
|
7e64d30258 | ||
|
|
437818abce | ||
|
|
5197eb9292 | ||
|
|
3cf01f0c51 | ||
|
|
db815661e8 | ||
|
|
6edbb7c8a7 | ||
|
|
799c445c4b | ||
|
|
70fbf5de3e | ||
|
|
73c7697443 | ||
|
|
8092edab81 | ||
|
|
ef4f45ddb0 | ||
|
|
3e969e4ae5 | ||
|
|
bcd1dfd7bd | ||
|
|
c1dfd78d18 | ||
|
|
39aa1645c9 | ||
|
|
d3afea8c5e | ||
|
|
2499cbdd44 | ||
|
|
3cc3714e94 | ||
|
|
be0aa6d099 | ||
|
|
34d27c1004 | ||
|
|
85f3b4e9e3 | ||
|
|
0fb9a79df9 | ||
|
|
6b805fbdfb | ||
|
|
abe76aeb59 | ||
|
|
5f49bc1aa8 | ||
|
|
71807be01d | ||
|
|
e74f796203 | ||
|
|
041d7da9d8 | ||
|
|
a99d949b29 | ||
|
|
c2a9e2a469 | ||
|
|
80b05db764 | ||
|
|
340cab11b7 | ||
|
|
712233c215 | ||
|
|
b9b915e913 | ||
|
|
044143571f | ||
|
|
06fe805736 | ||
|
|
077881e499 | ||
|
|
f655a57e61 | ||
|
|
0b04bf4929 | ||
|
|
2fcd3b1132 | ||
|
|
568fd6c105 | ||
|
|
221351ec11 | ||
|
|
6ab34a0996 | ||
|
|
6b551ae68b | ||
|
|
2917cde2e5 | ||
|
|
294a4a6cdf | ||
|
|
1e678b7492 | ||
|
|
2ceca7287f | ||
|
|
7f4dd5295b | ||
|
|
ffd628fa82 | ||
|
|
d639e445eb | ||
|
|
b263681dda | ||
|
|
e16413b570 | ||
|
|
63b5186c3e | ||
|
|
ba20316761 | ||
|
|
437dd1c411 | ||
|
|
d0d5f5b77d | ||
|
|
efd9228cc9 | ||
|
|
ebd6132385 | ||
|
|
9098443c83 | ||
|
|
423890a4df | ||
|
|
fb2edeb7d2 | ||
|
|
b861587f01 | ||
|
|
c3738fab45 | ||
|
|
24fba75f28 | ||
|
|
00b6b63e1e | ||
|
|
5dab8fa7d9 | ||
|
|
9a5d71fb5c | ||
|
|
c930efba0c | ||
|
|
ff7c820b1f | ||
|
|
4252725d9d | ||
|
|
deeb3a472c | ||
|
|
763173de44 | ||
|
|
f46e6ad8c8 | ||
|
|
09b31547e1 | ||
|
|
dee2ff8dee | ||
|
|
7f315b95ce | ||
|
|
093e7d1edb | ||
|
|
a4e18f8893 | ||
|
|
c754a36ee5 | ||
|
|
a07d4daed5 | ||
|
|
39023832e3 | ||
|
|
5b8dda60bd | ||
|
|
f7ade54e93 | ||
|
|
4ae7e9dd2e | ||
|
|
7e237b508a | ||
|
|
28bb82e579 | ||
|
|
bcabcb0831 | ||
|
|
c24b03f3da | ||
|
|
63dd03e755 | ||
|
|
f3f1f57b01 |
12
.env
12
.env
@@ -1,14 +1,8 @@
|
||||
# port
|
||||
VITE_DEV_PORT = '8001'
|
||||
VITE_DEV_PORT = '8080'
|
||||
|
||||
# development path
|
||||
VITE_DEV_PATH = '/'
|
||||
VITE_DEV_PATH = 'https://demo.mtruning.club'
|
||||
|
||||
# production path
|
||||
VITE_PRO_PATH = '/'
|
||||
|
||||
# spa-title
|
||||
VITE_GLOB_APP_TITLE = GoView
|
||||
|
||||
# spa shortname
|
||||
VITE_GLOB_APP_SHORT_NAME = GoView
|
||||
VITE_PRO_PATH = 'https://demo.mtruning.club'
|
||||
202
README.md
202
README.md
@@ -1,146 +1,114 @@
|
||||
## 总览
|
||||
|
||||

|
||||
**`master-fetch` 分支是带有后端接口请求的分支**
|
||||
|
||||
GoView 是一个高效的拖拽式低代码数据可视化开发平台,将图表或页面元素封装为基础组件,无需编写代码即可制作数据大屏,减少心智负担。
|
||||
**后端项目地址:[https://gitee.com/MTrun/go-view-serve](https://gitee.com/MTrun/go-view-serve)**
|
||||
|
||||
### 😶 纯 **前端** 分支: **`master`**
|
||||
**接口说明地址:[https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb](https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb)**
|
||||
|
||||
### 👻 携带 **后端** 请求分支: **`master-fetch`**
|
||||
## 使用
|
||||
|
||||
### 📚 GoView **文档** 地址:[http://www.mtruning.club:81/](http://www.mtruning.club:81/)
|
||||
所有的接口地址位置:`src\api\path\*`
|
||||
|
||||
项目纯前端-Demo 地址:[https://www.mtruning.club](https://www.mtruning.club)
|
||||
|
||||
项目带后端-Demo 地址:[后端 Demo 地址](http://1.117.240.165:8080/goview/#/login)
|
||||
|
||||
文档-在线地址:[http://www.mtruning.club:81/](http://www.mtruning.club:81/)
|
||||
|
||||
文档-源码地址:[https://gitee.com/MTrun/go-view-doc](https://gitee.com/MTrun/go-view-doc)
|
||||
|
||||
### 🤯 后端项目
|
||||
|
||||
后端项目 gitee 地址:[https://gitee.com/MTrun/go-view-serve](https://gitee.com/MTrun/go-view-serve)
|
||||
|
||||
接口说明地址:[https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb](https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb)
|
||||
|
||||
技术点:
|
||||
|
||||
- 框架:基于 `Vue3` 框架编写,使用 `hooks` 写法抽离部分逻辑,使代码结构更加清晰;
|
||||
|
||||
- 类型:使用 `TypeScript` 进行类型约束,减少未知错误发生概率,可以大胆修改逻辑内容;
|
||||
|
||||
- 性能:多处性能优化,使用页面懒加载、组件动态注册、数据滚动加载等方式,提升页面渲染速度;
|
||||
|
||||
- 存储:拥有本地记忆,部分配置项采用 `storage` 存储本地,提升使用体验;
|
||||
|
||||
- 封装:项目进行了详细的工具类封装如:路由、存储、加/解密、文件处理、主题、NaiveUI 全局方法、组件等
|
||||
|
||||
工作台:
|
||||

|
||||
|
||||
请求配置:
|
||||

|
||||
|
||||
数据过滤:
|
||||

|
||||
|
||||
主题色:
|
||||

|
||||
|
||||
主要技术栈为:
|
||||
|
||||
| 名称 | 版本 | 名称 | 版本 |
|
||||
| ------------------- | ----- | ----------- | ------ |
|
||||
| Vue | 3.2.x | TypeScript4 | 4.6.x |
|
||||
| Vite | 4.2.x | NaiveUI | 2.34.x |
|
||||
| ECharts | 5.3.x | Pinia | 2.0.x |
|
||||
| 详见 `package.json` | 😁 | 🥰 | 🤗 |
|
||||
|
||||
开发环境:
|
||||
|
||||
| 名称 | 版本 | 名称 | 版本 |
|
||||
| ---- | ------- | ------- | ----- |
|
||||
| node | 16.16.x | npm | 8.5.x |
|
||||
| pnpm | 7.1.x | windows | 11 |
|
||||
|
||||
已完成图表:
|
||||
|
||||
| 分类 | 名称 | 名称 | 名称 |
|
||||
| ------ | ---------------- | ---------------- | -------- |
|
||||
| 图表 | 柱状图 | 横向柱状图 | 折线图 |
|
||||
| \* | 单/多 折线面积图 | 饼图 | 水球图 |
|
||||
| \* | 环形图 | NaiveUI 多种进度 | 🤠 |
|
||||
| 信息 | 文字 | 图片 | 😶 |
|
||||
| 列表 | 滚动排名列表 | 滚动表格 | 🤓 |
|
||||
| 小组件 | 边框-01~13 | 装饰-01~05 | 数字翻牌 |
|
||||
|
||||
## 浏览器支持
|
||||
|
||||
开发和测试平台均在 `Google` 和最新版 `EDGE` 上完成,暂未测试 `IE11` 等其它浏览器,如有需求请自行测试与兼容。
|
||||
|
||||
## 安装
|
||||
|
||||
本项目采用` pnpm` 进行包管理
|
||||
接口地址修改:`.env`
|
||||
|
||||
```shell
|
||||
#建议使用 nrm 切换到淘宝源 https://registry.npmmirror.com/
|
||||
#pnpm
|
||||
pnpm install
|
||||
# port
|
||||
VITE_DEV_PORT = '8080'
|
||||
|
||||
#yarn
|
||||
yarn install
|
||||
# development path
|
||||
VITE_DEV_PATH = 'http://127.0.0.1:8080'
|
||||
|
||||
#npm
|
||||
npm install
|
||||
# production path
|
||||
VITE_PRO_PATH = 'http://127.0.0.1:8080'
|
||||
```
|
||||
|
||||
## 启动
|
||||
公共前缀修改:`src\settings\httpSetting.ts`
|
||||
|
||||
```shell
|
||||
#pnpm
|
||||
pnpm dev
|
||||
|
||||
# npm
|
||||
npm run dev
|
||||
|
||||
#yarn
|
||||
yarn dev
|
||||
|
||||
#Makefile
|
||||
make dev
|
||||
// 请求前缀
|
||||
export const axiosPre = '/api/goview'
|
||||
```
|
||||
|
||||
## 编译
|
||||
接口封装:`src\api\http.ts`
|
||||
|
||||
```shell
|
||||
#pnpm
|
||||
pnpm run build
|
||||
```ts
|
||||
import axiosInstance from './axios'
|
||||
import { RequestHttpEnum, ContentTypeEnum } from '@/enums/httpEnum'
|
||||
|
||||
# npm
|
||||
npm run build
|
||||
export const get = (url: string, params?: object) => {
|
||||
return axiosInstance({
|
||||
url: url,
|
||||
method: RequestHttpEnum.GET,
|
||||
params: params,
|
||||
})
|
||||
}
|
||||
|
||||
#yarn
|
||||
yarn run build
|
||||
export const post = (url: string, data?: object, headersType?: string) => {
|
||||
return axiosInstance({
|
||||
url: url,
|
||||
method: RequestHttpEnum.POST,
|
||||
data: data,
|
||||
headers: {
|
||||
'Content-Type': headersType || ContentTypeEnum.JSON
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#Makefile
|
||||
make dist
|
||||
export const put = (url: string, data?: object, headersType?: string) => {
|
||||
return axiosInstance({
|
||||
url: url,
|
||||
method: RequestHttpEnum.PUT,
|
||||
data: data,
|
||||
headers: {
|
||||
'Content-Type': headersType || ContentTypeEnum.JSON
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const del = (url: string, params?: object) => {
|
||||
return axiosInstance({
|
||||
url: url,
|
||||
method: RequestHttpEnum.DELETE,
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 获取请求函数,默认get
|
||||
export const http = (type?: RequestHttpEnum) => {
|
||||
switch (type) {
|
||||
case RequestHttpEnum.GET:
|
||||
return get
|
||||
|
||||
case RequestHttpEnum.POST:
|
||||
return post
|
||||
|
||||
case RequestHttpEnum.PUT:
|
||||
return put
|
||||
|
||||
case RequestHttpEnum.DELETE:
|
||||
return del
|
||||
|
||||
default:
|
||||
return get
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 代码提交
|
||||
|
||||
- feat: 新功能
|
||||
- fix: 修复 Bug
|
||||
- docs: 文档修改
|
||||
- perf: 性能优化
|
||||
- revert: 版本回退
|
||||
- ci: CICD 集成相关
|
||||
- test: 添加测试代码
|
||||
- refactor: 代码重构
|
||||
- build: 影响项目构建或依赖修改
|
||||
- style: 不影响程序逻辑的代码修改
|
||||
- chore: 不属于以上类型的其他类型(日常事务)
|
||||
* feat: 新功能
|
||||
* fix: 修复 Bug
|
||||
* docs: 文档修改
|
||||
* perf: 性能优化
|
||||
* revert: 版本回退
|
||||
* ci: CICD集成相关
|
||||
* test: 添加测试代码
|
||||
* refactor: 代码重构
|
||||
* build: 影响项目构建或依赖修改
|
||||
* style: 不影响程序逻辑的代码修改
|
||||
* chore: 不属于以上类型的其他类型(日常事务)
|
||||
|
||||
## 交流
|
||||
|
||||
|
||||
@@ -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, '');
|
||||
};
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "go-view",
|
||||
"version": "1.1.11",
|
||||
"version": "2.2.7",
|
||||
"engines": {
|
||||
"node": ">=16.14 <18.0.0"
|
||||
"node": ">=12.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "vite --host",
|
||||
|
||||
79
pnpm-lock.yaml
generated
79
pnpm-lock.yaml
generated
@@ -189,7 +189,7 @@ devDependencies:
|
||||
version: 1.52.3
|
||||
sass-loader:
|
||||
specifier: ^12.6.0
|
||||
version: 12.6.0(sass@1.52.3)(webpack@5.82.1)
|
||||
version: 12.6.0(sass@1.52.3)(webpack@5.88.2)
|
||||
typescript:
|
||||
specifier: 4.6.3
|
||||
version: 4.6.3
|
||||
@@ -1198,8 +1198,8 @@ packages:
|
||||
engines: {node: '>=6.0.0'}
|
||||
dev: true
|
||||
|
||||
/@jridgewell/source-map@0.3.3:
|
||||
resolution: {integrity: sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==}
|
||||
/@jridgewell/source-map@0.3.5:
|
||||
resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==}
|
||||
dependencies:
|
||||
'@jridgewell/gen-mapping': 0.3.3
|
||||
'@jridgewell/trace-mapping': 0.3.18
|
||||
@@ -1318,12 +1318,12 @@ packages:
|
||||
/@types/eslint-scope@3.7.4:
|
||||
resolution: {integrity: sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==}
|
||||
dependencies:
|
||||
'@types/eslint': 8.37.0
|
||||
'@types/eslint': 8.44.2
|
||||
'@types/estree': 1.0.1
|
||||
dev: true
|
||||
|
||||
/@types/eslint@8.37.0:
|
||||
resolution: {integrity: sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ==}
|
||||
/@types/eslint@8.44.2:
|
||||
resolution: {integrity: sha512-sdPRb9K6iL5XZOmBubg8yiFp5yS/JdUDQsq5e6h95km91MCYMuvp7mh1fjPEYUhvHepKpZOjnEaMBR4PxjWDzg==}
|
||||
dependencies:
|
||||
'@types/estree': 1.0.1
|
||||
'@types/json-schema': 7.0.11
|
||||
@@ -1394,7 +1394,7 @@ packages:
|
||||
dev: true
|
||||
|
||||
/@types/node@17.0.43:
|
||||
resolution: {integrity: sha512-jnUpgw8fL9kP2iszfIDyBQtw5Mf4/XSqy0Loc1J9pI14ejL83XcCEvSf50Gs/4ET0I9VCCDoOfufQysj0S66xA==, tarball: https://registry.npm.taobao.org/@types/node/-/node-17.0.43.tgz}
|
||||
resolution: {integrity: sha512-jnUpgw8fL9kP2iszfIDyBQtw5Mf4/XSqy0Loc1J9pI14ejL83XcCEvSf50Gs/4ET0I9VCCDoOfufQysj0S66xA==}
|
||||
|
||||
/@types/normalize-package-data@2.4.1:
|
||||
resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==}
|
||||
@@ -1890,12 +1890,12 @@ packages:
|
||||
through: 2.3.8
|
||||
dev: true
|
||||
|
||||
/acorn-import-assertions@1.9.0(acorn@8.8.2):
|
||||
/acorn-import-assertions@1.9.0(acorn@8.7.1):
|
||||
resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==}
|
||||
peerDependencies:
|
||||
acorn: ^8
|
||||
dependencies:
|
||||
acorn: 8.8.2
|
||||
acorn: 8.7.1
|
||||
dev: true
|
||||
|
||||
/acorn-jsx@5.3.2(acorn@8.7.1):
|
||||
@@ -1917,14 +1917,14 @@ packages:
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/acorn@8.7.1:
|
||||
resolution: {integrity: sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==}
|
||||
/acorn@8.10.0:
|
||||
resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/acorn@8.8.2:
|
||||
resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==}
|
||||
/acorn@8.7.1:
|
||||
resolution: {integrity: sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
@@ -2755,7 +2755,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
/echarts-wordcloud@2.0.0(echarts@5.3.3):
|
||||
resolution: {integrity: sha512-K7l6pTklqdW7ZWzT/1CS0KhBSINr/cd7c5N1fVMzZMwLQHEwT7x+nivK7g5hkVh7WNcAv4Dn6/ZS5zMKRozC1g==, tarball: https://registry.npm.taobao.org/echarts-wordcloud/-/echarts-wordcloud-2.0.0.tgz}
|
||||
resolution: {integrity: sha512-K7l6pTklqdW7ZWzT/1CS0KhBSINr/cd7c5N1fVMzZMwLQHEwT7x+nivK7g5hkVh7WNcAv4Dn6/ZS5zMKRozC1g==}
|
||||
peerDependencies:
|
||||
echarts: ^5.0.1
|
||||
dependencies:
|
||||
@@ -2792,8 +2792,8 @@ packages:
|
||||
engines: {node: '>= 0.8'}
|
||||
dev: true
|
||||
|
||||
/enhanced-resolve@5.14.0:
|
||||
resolution: {integrity: sha512-+DCows0XNwLDcUhbFJPdlQEVnT2zXlCv7hPxemTz86/O+B/hCQ+mb7ydkPKiflpVraqLPCAfu7lDy+hBXueojw==}
|
||||
/enhanced-resolve@5.15.0:
|
||||
resolution: {integrity: sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
dependencies:
|
||||
graceful-fs: 4.2.11
|
||||
@@ -2844,8 +2844,8 @@ packages:
|
||||
unbox-primitive: 1.0.2
|
||||
dev: true
|
||||
|
||||
/es-module-lexer@1.2.1:
|
||||
resolution: {integrity: sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==}
|
||||
/es-module-lexer@1.3.0:
|
||||
resolution: {integrity: sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==}
|
||||
dev: true
|
||||
|
||||
/es-shim-unscopables@1.0.0:
|
||||
@@ -3540,6 +3540,7 @@ packages:
|
||||
|
||||
/graceful-fs@4.2.11:
|
||||
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
|
||||
/gsap@3.11.3:
|
||||
@@ -5156,7 +5157,7 @@ packages:
|
||||
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
||||
dev: true
|
||||
|
||||
/sass-loader@12.6.0(sass@1.52.3)(webpack@5.82.1):
|
||||
/sass-loader@12.6.0(sass@1.52.3)(webpack@5.88.2):
|
||||
resolution: {integrity: sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==}
|
||||
engines: {node: '>= 12.13.0'}
|
||||
peerDependencies:
|
||||
@@ -5178,7 +5179,7 @@ packages:
|
||||
klona: 2.0.5
|
||||
neo-async: 2.6.2
|
||||
sass: 1.52.3
|
||||
webpack: 5.82.1
|
||||
webpack: 5.88.2
|
||||
dev: true
|
||||
|
||||
/sass@1.52.3:
|
||||
@@ -5191,8 +5192,8 @@ packages:
|
||||
source-map-js: 1.0.2
|
||||
dev: true
|
||||
|
||||
/schema-utils@3.1.2:
|
||||
resolution: {integrity: sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==}
|
||||
/schema-utils@3.3.0:
|
||||
resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==}
|
||||
engines: {node: '>= 10.13.0'}
|
||||
dependencies:
|
||||
'@types/json-schema': 7.0.11
|
||||
@@ -5445,8 +5446,8 @@ packages:
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/terser-webpack-plugin@5.3.8(webpack@5.82.1):
|
||||
resolution: {integrity: sha512-WiHL3ElchZMsK27P8uIUh4604IgJyAW47LVXGbEoB21DbQcZ+OuMpGjVYnEUaqcWM6dO8uS2qUbA7LSCWqvsbg==}
|
||||
/terser-webpack-plugin@5.3.9(webpack@5.88.2):
|
||||
resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==}
|
||||
engines: {node: '>= 10.13.0'}
|
||||
peerDependencies:
|
||||
'@swc/core': '*'
|
||||
@@ -5463,19 +5464,19 @@ packages:
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.18
|
||||
jest-worker: 27.5.1
|
||||
schema-utils: 3.1.2
|
||||
schema-utils: 3.3.0
|
||||
serialize-javascript: 6.0.1
|
||||
terser: 5.17.3
|
||||
webpack: 5.82.1
|
||||
terser: 5.19.2
|
||||
webpack: 5.88.2
|
||||
dev: true
|
||||
|
||||
/terser@5.17.3:
|
||||
resolution: {integrity: sha512-AudpAZKmZHkG9jueayypz4duuCFJMMNGRMwaPvQKWfxKedh8Z2x3OCoDqIIi1xx5+iwx1u6Au8XQcc9Lke65Yg==}
|
||||
/terser@5.19.2:
|
||||
resolution: {integrity: sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==}
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@jridgewell/source-map': 0.3.3
|
||||
acorn: 8.8.2
|
||||
'@jridgewell/source-map': 0.3.5
|
||||
acorn: 8.10.0
|
||||
commander: 2.20.3
|
||||
source-map-support: 0.5.21
|
||||
dev: true
|
||||
@@ -6152,8 +6153,8 @@ packages:
|
||||
engines: {node: '>=10.13.0'}
|
||||
dev: true
|
||||
|
||||
/webpack@5.82.1:
|
||||
resolution: {integrity: sha512-C6uiGQJ+Gt4RyHXXYt+v9f+SN1v83x68URwgxNQ98cvH8kxiuywWGP4XeNZ1paOzZ63aY3cTciCEQJNFUljlLw==}
|
||||
/webpack@5.88.2:
|
||||
resolution: {integrity: sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
@@ -6167,12 +6168,12 @@ packages:
|
||||
'@webassemblyjs/ast': 1.11.6
|
||||
'@webassemblyjs/wasm-edit': 1.11.6
|
||||
'@webassemblyjs/wasm-parser': 1.11.6
|
||||
acorn: 8.8.2
|
||||
acorn-import-assertions: 1.9.0(acorn@8.8.2)
|
||||
acorn: 8.7.1
|
||||
acorn-import-assertions: 1.9.0(acorn@8.7.1)
|
||||
browserslist: 4.21.5
|
||||
chrome-trace-event: 1.0.3
|
||||
enhanced-resolve: 5.14.0
|
||||
es-module-lexer: 1.2.1
|
||||
enhanced-resolve: 5.15.0
|
||||
es-module-lexer: 1.3.0
|
||||
eslint-scope: 5.1.1
|
||||
events: 3.3.0
|
||||
glob-to-regexp: 0.4.1
|
||||
@@ -6181,9 +6182,9 @@ packages:
|
||||
loader-runner: 4.3.0
|
||||
mime-types: 2.1.35
|
||||
neo-async: 2.6.2
|
||||
schema-utils: 3.1.2
|
||||
schema-utils: 3.3.0
|
||||
tapable: 2.2.1
|
||||
terser-webpack-plugin: 5.3.8(webpack@5.82.1)
|
||||
terser-webpack-plugin: 5.3.9(webpack@5.88.2)
|
||||
watchpack: 2.4.0
|
||||
webpack-sources: 3.2.3
|
||||
transitivePeerDependencies:
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import { NConfigProvider } from 'naive-ui'
|
||||
import { GoAppProvider } from '@/components/GoAppProvider'
|
||||
import { I18n } from '@/components/I18n'
|
||||
import { useDarkThemeHook, useThemeOverridesHook, useCode, useLang } from '@/hooks'
|
||||
import { useSystemInit, useDarkThemeHook, useThemeOverridesHook, useCode, useLang } from '@/hooks'
|
||||
|
||||
// 暗黑主题
|
||||
const darkTheme = useDarkThemeHook()
|
||||
@@ -28,6 +28,9 @@ const overridesTheme = useThemeOverridesHook()
|
||||
// 代码主题
|
||||
const hljsTheme = useCode()
|
||||
|
||||
// 系统全局数据初始化
|
||||
useSystemInit()
|
||||
|
||||
// 全局语言
|
||||
const { locale, dateLocale } = useLang()
|
||||
//测试提交
|
||||
|
||||
14
src/api/axios.config.ts
Normal file
14
src/api/axios.config.ts
Normal 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 = []
|
||||
@@ -1,34 +1,93 @@
|
||||
import axios, { AxiosResponse, InternalAxiosRequestConfig, AxiosError } from 'axios'
|
||||
import { ResultEnum } from "@/enums/httpEnum"
|
||||
import { ErrorPageNameMap } from "@/enums/pageEnum"
|
||||
import { redirectErrorPage } from '@/utils'
|
||||
import axios, { AxiosResponse, AxiosRequestConfig, Axios, AxiosError, InternalAxiosRequestConfig } from 'axios'
|
||||
import { RequestHttpHeaderEnum, ResultEnum, ModuleTypeEnum } from '@/enums/httpEnum'
|
||||
import { PageEnum, ErrorPageNameMap } from '@/enums/pageEnum'
|
||||
import { StorageEnum } from '@/enums/storageEnum'
|
||||
import { axiosPre } from '@/settings/httpSetting'
|
||||
import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'
|
||||
import { redirectErrorPage, getLocalStorage, routerTurnByName, isPreview } from '@/utils'
|
||||
import { fetchAllowList } from './axios.config'
|
||||
import includes from 'lodash/includes'
|
||||
|
||||
export interface MyResponseType<T> {
|
||||
code: ResultEnum
|
||||
data: T
|
||||
message: string
|
||||
}
|
||||
|
||||
export interface MyRequestInstance extends Axios {
|
||||
<T = any>(config: AxiosRequestConfig): Promise<MyResponseType<T>>
|
||||
}
|
||||
|
||||
const axiosInstance = axios.create({
|
||||
baseURL: import.meta.env.DEV ? import.meta.env.VITE_DEV_PATH : import.meta.env.VITE_PRO_PATH,
|
||||
timeout: ResultEnum.TIMEOUT,
|
||||
})
|
||||
baseURL: `${import.meta.env.PROD ? import.meta.env.VITE_PRO_PATH : ''}${axiosPre}`,
|
||||
timeout: ResultEnum.TIMEOUT
|
||||
}) as unknown as MyRequestInstance
|
||||
|
||||
axiosInstance.interceptors.request.use(
|
||||
(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
|
||||
},
|
||||
(error: AxiosError) => {
|
||||
Promise.reject(error)
|
||||
(err: AxiosError) => {
|
||||
Promise.reject(err)
|
||||
}
|
||||
)
|
||||
|
||||
// 响应拦截器
|
||||
axiosInstance.interceptors.response.use(
|
||||
(res: AxiosResponse) => {
|
||||
// 预览页面错误不进行处理
|
||||
if (isPreview()) {
|
||||
return Promise.resolve(res.data)
|
||||
}
|
||||
const { code } = res.data as { code: number }
|
||||
|
||||
if (code === 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)
|
||||
},
|
||||
(err: AxiosResponse) => {
|
||||
Promise.reject(err)
|
||||
(err: AxiosError) => {
|
||||
const status = err.response?.status
|
||||
switch (status) {
|
||||
case 401:
|
||||
routerTurnByName(PageEnum.BASE_LOGIN_NAME)
|
||||
Promise.reject(err)
|
||||
break
|
||||
|
||||
default:
|
||||
Promise.reject(err)
|
||||
break
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -9,16 +9,16 @@ import {
|
||||
} from '@/enums/httpEnum'
|
||||
import type { RequestGlobalConfigType, RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
|
||||
export const get = (url: string, params?: object) => {
|
||||
return axiosInstance({
|
||||
export const get = <T = any>(url: string, params?: object) => {
|
||||
return axiosInstance<T>({
|
||||
url: url,
|
||||
method: RequestHttpEnum.GET,
|
||||
params: params
|
||||
params: params,
|
||||
})
|
||||
}
|
||||
|
||||
export const post = (url: string, data?: object, headersType?: string) => {
|
||||
return axiosInstance({
|
||||
export const post = <T = any>(url: string, data?: object, headersType?: string) => {
|
||||
return axiosInstance<T>({
|
||||
url: url,
|
||||
method: RequestHttpEnum.POST,
|
||||
data: data,
|
||||
@@ -28,8 +28,8 @@ export const post = (url: string, data?: object, headersType?: string) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const patch = (url: string, data?: object, headersType?: string) => {
|
||||
return axiosInstance({
|
||||
export const patch = <T = any>(url: string, data?: object, headersType?: string) => {
|
||||
return axiosInstance<T>({
|
||||
url: url,
|
||||
method: RequestHttpEnum.PATCH,
|
||||
data: data,
|
||||
@@ -39,8 +39,8 @@ export const patch = (url: string, data?: object, headersType?: string) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const put = (url: string, data?: object, headersType?: ContentTypeEnum) => {
|
||||
return axiosInstance({
|
||||
export const put = <T = any>(url: string, data?: object, headersType?: ContentTypeEnum) => {
|
||||
return axiosInstance<T>({
|
||||
url: url,
|
||||
method: RequestHttpEnum.PUT,
|
||||
data: data,
|
||||
@@ -50,8 +50,8 @@ export const put = (url: string, data?: object, headersType?: ContentTypeEnum) =
|
||||
})
|
||||
}
|
||||
|
||||
export const del = (url: string, params?: object) => {
|
||||
return axiosInstance({
|
||||
export const del = <T = any>(url: string, params?: object) => {
|
||||
return axiosInstance<T>({
|
||||
url: url,
|
||||
method: RequestHttpEnum.DELETE,
|
||||
params
|
||||
@@ -82,11 +82,11 @@ export const http = (type?: RequestHttpEnum) => {
|
||||
}
|
||||
const prefix = 'javascript:'
|
||||
// 对输入字符进行转义处理
|
||||
export const translateStr = (target: string | object) => {
|
||||
export const translateStr = (target: string | Record<any, any>) => {
|
||||
if (typeof target === 'string') {
|
||||
if (target.startsWith(prefix)) {
|
||||
const funcStr = target.split(prefix)[1]
|
||||
let result;
|
||||
let result
|
||||
try {
|
||||
result = new Function(`${funcStr}`)()
|
||||
} catch (error) {
|
||||
@@ -100,8 +100,8 @@ export const translateStr = (target: string | object) => {
|
||||
}
|
||||
for (const key in target) {
|
||||
if (Object.prototype.hasOwnProperty.call(target, key)) {
|
||||
const subTarget = (target as any)[key];
|
||||
(target as any)[key] = translateStr(subTarget)
|
||||
const subTarget = target[key]
|
||||
target[key] = translateStr(subTarget)
|
||||
}
|
||||
}
|
||||
return target
|
||||
|
||||
2
src/api/path/index.ts
Normal file
2
src/api/path/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from '@/api/path/project.api'
|
||||
export * from '@/api/path/system.api'
|
||||
99
src/api/path/project.api.ts
Normal file
99
src/api/path/project.api.ts
Normal 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
39
src/api/path/project.d.ts
vendored
Normal 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
|
||||
}
|
||||
39
src/api/path/system.api.ts
Normal file
39
src/api/path/system.api.ts
Normal 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
26
src/api/path/system.d.ts
vendored
Normal 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 |
@@ -27,7 +27,9 @@
|
||||
<script lang="ts" setup>
|
||||
import { h, ref } from 'vue'
|
||||
import { NAvatar, NText } from 'naive-ui'
|
||||
import { renderIcon } from '@/utils'
|
||||
import { renderIcon, getLocalStorage } from '@/utils'
|
||||
import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'
|
||||
import { StorageEnum } from '@/enums/storageEnum'
|
||||
import { logout, renderLang } from '@/utils'
|
||||
import { GoSystemSet } from '@/components/GoSystemSet/index'
|
||||
import { GoSystemInfo } from '@/components/GoSystemInfo/index'
|
||||
@@ -64,7 +66,17 @@ const renderUserInfo = () => {
|
||||
}),
|
||||
h('div', null, [
|
||||
h('div', null, [
|
||||
h(NText, { depth: 2 }, { default: () => '奔跑的面条' })
|
||||
h(NText, { depth: 2 }, {
|
||||
default: () => {
|
||||
const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
|
||||
if (info) {
|
||||
return info[SystemStoreEnum.USER_INFO][SystemStoreUserInfoEnum.USER_NAME];
|
||||
}
|
||||
else {
|
||||
return 'admin';
|
||||
}
|
||||
}
|
||||
})
|
||||
])
|
||||
])
|
||||
]
|
||||
@@ -137,4 +149,4 @@ const handleSelect = (key: string) => {
|
||||
cursor: pointer;
|
||||
transform: scale(0.7);
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -48,7 +48,6 @@ export enum MenuEnum {
|
||||
UN_GROUP = 'unGroup',
|
||||
// 后退
|
||||
BACK = 'back',
|
||||
// 前进
|
||||
FORWORD = 'forward',
|
||||
// 保存
|
||||
SAVE = 'save',
|
||||
@@ -84,3 +83,15 @@ export enum MacKeyboard {
|
||||
ALT_SOURCE_KEY = '⌥',
|
||||
SPACE = 'Space'
|
||||
}
|
||||
|
||||
// 同步状态枚举
|
||||
export enum SyncEnum {
|
||||
// 等待
|
||||
PENDING,
|
||||
// 开始
|
||||
START,
|
||||
// 成功
|
||||
SUCCESS,
|
||||
// 失败
|
||||
FAILURE
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
/**
|
||||
* @description: 请求结果集
|
||||
*/
|
||||
// 模块 Path 前缀分类
|
||||
export enum ModuleTypeEnum {
|
||||
SYSTEM = 'sys',
|
||||
PROJECT = 'project',
|
||||
}
|
||||
|
||||
// 请求结果集
|
||||
export enum ResultEnum {
|
||||
DATA_SUCCESS = 0,
|
||||
SUCCESS = 200,
|
||||
SERVER_ERROR = 500,
|
||||
SERVER_FORBIDDEN = 403,
|
||||
NOT_FOUND = 404,
|
||||
TIMEOUT = 60000
|
||||
TOKEN_OVERDUE = 886,
|
||||
TIMEOUT = 60000,
|
||||
}
|
||||
|
||||
// 数据相关
|
||||
@@ -28,9 +33,13 @@ export enum RequestContentTypeEnum {
|
||||
SQL = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 请求方法
|
||||
*/
|
||||
// 头部
|
||||
export enum RequestHttpHeaderEnum {
|
||||
TOKEN = 'Token',
|
||||
COOKIE = 'Cookie'
|
||||
}
|
||||
|
||||
// 请求方法
|
||||
export enum RequestHttpEnum {
|
||||
GET = 'get',
|
||||
POST = 'post',
|
||||
@@ -111,9 +120,7 @@ export type RequestParams = {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 常用的contentTyp类型
|
||||
*/
|
||||
// 常用的contentTyp类型
|
||||
export enum ContentTypeEnum {
|
||||
// json
|
||||
JSON = 'application/json;charset=UTF-8',
|
||||
|
||||
@@ -26,10 +26,15 @@ export enum PageEnum {
|
||||
//重定向
|
||||
REDIRECT = '/redirect',
|
||||
REDIRECT_NAME = 'Redirect',
|
||||
|
||||
// 未发布
|
||||
REDIRECT_UN_PUBLISH = '/redirect/unPublish',
|
||||
REDIRECT_UN_PUBLISH_NAME = 'redirect-un-publish',
|
||||
|
||||
// 重载
|
||||
RELOAD = '/reload',
|
||||
RELOAD_NAME = 'Reload',
|
||||
|
||||
|
||||
// 首页
|
||||
BASE_HOME = '/project',
|
||||
BASE_HOME_NAME = 'Project',
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
export enum StorageEnum {
|
||||
// 全局设置
|
||||
GO_SYSTEM_SETTING_STORE = 'GO_SYSTEM_SETTING',
|
||||
// token 等信息
|
||||
GO_ACCESS_TOKEN_STORE = 'GO_ACCESS_TOKEN',
|
||||
GO_SETTING_STORE = 'GO_SETTING',
|
||||
// 登录信息
|
||||
GO_LOGIN_INFO_STORE = 'GO_LOGIN_INFO',
|
||||
GO_SYSTEM_STORE = 'GO_SYSTEM',
|
||||
// 语言
|
||||
GO_LANG_STORE = 'GO_LANG',
|
||||
// 当前选择的主题
|
||||
|
||||
@@ -2,6 +2,7 @@ export * from '@/hooks/useTheme.hook'
|
||||
export * from '@/hooks/usePreviewScale.hook'
|
||||
export * from '@/hooks/useCode.hook'
|
||||
export * from '@/hooks/useChartDataFetch.hook'
|
||||
export * from '@/hooks/useSystemInit.hook'
|
||||
export * from '@/hooks/useChartDataPondFetch.hook'
|
||||
export * from '@/hooks/useLifeHandler.hook'
|
||||
export * from '@/hooks/useLang.hook'
|
||||
|
||||
@@ -116,7 +116,7 @@ export const useChartDataPondFetch = () => {
|
||||
const requestDataPondItem = computed(() => {
|
||||
return requestGlobalConfig.requestDataPond.find(item => item.dataPondId === pondKey)
|
||||
}) as ComputedRef<RequestDataPondItemType>
|
||||
if (requestDataPondItem) {
|
||||
if (requestDataPondItem.value) {
|
||||
newPondItemInterval(chartEditStore.requestGlobalConfig, requestDataPondItem, mittDataPondMap.get(pondKey))
|
||||
}
|
||||
}
|
||||
|
||||
23
src/hooks/useSystemInit.hook.ts
Normal file
23
src/hooks/useSystemInit.hook.ts
Normal 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()
|
||||
}
|
||||
@@ -11,6 +11,8 @@ const global = {
|
||||
help: 'Help',
|
||||
contact: 'About Software',
|
||||
logout: 'Logout',
|
||||
logout_success: 'Logout success!',
|
||||
logout_failure: 'Logout Failed!',
|
||||
// system setting
|
||||
sys_set: 'System Setting',
|
||||
lang_set: 'Language Setting',
|
||||
@@ -26,8 +28,14 @@ const global = {
|
||||
r_more: 'More',
|
||||
}
|
||||
|
||||
const http = {
|
||||
error_message: 'The interface is abnormal, please check the interface!',
|
||||
token_overdue_message: 'Login expired, please log in again!'
|
||||
}
|
||||
|
||||
export default {
|
||||
global,
|
||||
http,
|
||||
login,
|
||||
project
|
||||
}
|
||||
|
||||
@@ -2,6 +2,6 @@ export default {
|
||||
desc: "Login",
|
||||
form_auto: "Sign in automatically",
|
||||
form_button: "Login",
|
||||
login_success: "Login success",
|
||||
login_message: "Please complete the letter",
|
||||
login_success: "Login success!",
|
||||
login_message: "Please complete the letter!",
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
export default {
|
||||
create_btn: 'Create',
|
||||
create_tip: 'Please select a content for development',
|
||||
create_btn: 'Creat',
|
||||
create_success: 'Creat Success!',
|
||||
create_failure: 'Failed to create, please try again later!',
|
||||
create_tip: 'Please select a content for development!',
|
||||
project: 'Project',
|
||||
my: 'My',
|
||||
new_project: 'New Project',
|
||||
|
||||
@@ -11,6 +11,8 @@ const global = {
|
||||
help: '帮助中心',
|
||||
contact: '关于软件',
|
||||
logout: '退出登录',
|
||||
logout_success: '退出成功!',
|
||||
logout_failure: '退出失败!',
|
||||
// 系统设置
|
||||
sys_set: '系统设置',
|
||||
lang_set: '语言设置',
|
||||
@@ -18,16 +20,27 @@ const global = {
|
||||
r_edit: '编辑',
|
||||
r_preview: '预览',
|
||||
r_copy: '克隆',
|
||||
r_copy_success: '克隆成功!',
|
||||
r_rename: '重命名',
|
||||
r_rename_success: '重命名成功!',
|
||||
r_publish: '发布',
|
||||
r_publish_success: '成功发布!',
|
||||
r_unpublish: '取消发布',
|
||||
r_unpublish_success: '取消成功!',
|
||||
r_download: '下载',
|
||||
r_delete: '删除',
|
||||
r_delete_success: '删除成功!',
|
||||
r_more: '更多',
|
||||
}
|
||||
|
||||
const http = {
|
||||
error_message: '获取数据失败,请稍后重试!',
|
||||
token_overdue_message: '登录过期,请重新登录!'
|
||||
}
|
||||
|
||||
export default {
|
||||
global,
|
||||
http,
|
||||
login,
|
||||
project
|
||||
}
|
||||
|
||||
@@ -2,6 +2,6 @@ export default {
|
||||
desc: "登录",
|
||||
form_auto: "自动登录",
|
||||
form_button: "登录",
|
||||
login_success: "登录成功",
|
||||
login_message: "请填写完整信息",
|
||||
login_success: "登录成功!",
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
export default {
|
||||
// aside
|
||||
create_btn: '新建',
|
||||
create_success: '新建成功!',
|
||||
create_failure: '新建失败,请稍后重试!',
|
||||
create_tip: '从哪里出发好呢?',
|
||||
project: '项目',
|
||||
my: '我的',
|
||||
|
||||
@@ -8,7 +8,10 @@ import { SketchRule } from 'vue3-sketch-ruler'
|
||||
* @param app
|
||||
*/
|
||||
export function setupCustomComponents(app: App) {
|
||||
// 骨架屏
|
||||
app.component('GoSkeleton', GoSkeleton)
|
||||
// 加载
|
||||
app.component('GoLoading', GoLoading)
|
||||
// 标尺
|
||||
app.component('SketchRule', SketchRule)
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ import {
|
||||
ArrowDown as ArrowDownIcon,
|
||||
Planet as PawIcon,
|
||||
Search as SearchIcon,
|
||||
Reload as ReloadIcon,
|
||||
ChevronUpOutline as ChevronUpOutlineIcon,
|
||||
ChevronDownOutline as ChevronDownOutlineIcon,
|
||||
Pulse as PulseIcon,
|
||||
@@ -97,6 +98,7 @@ import {
|
||||
FitToScreen as FitToScreenIcon,
|
||||
FitToHeight as FitToHeightIcon,
|
||||
FitToWidth as FitToWidthIcon,
|
||||
Save as SaveIcon,
|
||||
Carbon3DCursor as Carbon3DCursorIcon,
|
||||
Carbon3DSoftware as Carbon3DSoftwareIcon,
|
||||
Filter as FilterIcon,
|
||||
@@ -218,6 +220,8 @@ const ionicons5 = {
|
||||
PawIcon,
|
||||
// 搜索(放大镜)
|
||||
SearchIcon,
|
||||
// 加载
|
||||
ReloadIcon,
|
||||
// 过滤器
|
||||
FilterIcon,
|
||||
// 向上
|
||||
@@ -289,6 +293,8 @@ const carbon = {
|
||||
FitToScreenIcon,
|
||||
FitToHeightIcon,
|
||||
FitToWidthIcon,
|
||||
// 保存
|
||||
SaveIcon,
|
||||
// 成组
|
||||
Carbon3DCursorIcon,
|
||||
// 解组
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { RouteRecordRaw } from 'vue-router'
|
||||
import type { AppRouteRecordRaw } from '@/router/types';
|
||||
import { ErrorPage404, ErrorPage403, ErrorPage500, Layout } from '@/router/constant';
|
||||
import { ErrorPage404, ErrorPage403, ErrorPage500, Layout, RedirectHome, RedirectUnPublish } from '@/router/constant';
|
||||
import { PageEnum } from '@/enums/pageEnum'
|
||||
import { GoReload } from '@/components/GoReload'
|
||||
|
||||
|
||||
export const LoginRoute: RouteRecordRaw = {
|
||||
path: '/login',
|
||||
name: 'Login',
|
||||
path: PageEnum.BASE_LOGIN,
|
||||
name: PageEnum.BASE_LOGIN_NAME,
|
||||
component: () => import('@/views/login/index.vue'),
|
||||
meta: {
|
||||
title: '登录',
|
||||
@@ -60,22 +60,21 @@ export const ReloadRoute: AppRouteRecordRaw = {
|
||||
},
|
||||
}
|
||||
|
||||
export const RedirectRoute: AppRouteRecordRaw = {
|
||||
path: PageEnum.REDIRECT,
|
||||
name: PageEnum.REDIRECT_NAME,
|
||||
component: Layout,
|
||||
meta: {
|
||||
title: PageEnum.REDIRECT_NAME,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '/redirect/:path(.*)',
|
||||
name: PageEnum.REDIRECT_NAME,
|
||||
component: () => import('@/views/redirect/index.vue'),
|
||||
meta: {
|
||||
title: PageEnum.REDIRECT_NAME,
|
||||
hideBreadcrumb: true,
|
||||
},
|
||||
export const RedirectRoute: RouteRecordRaw[] = [
|
||||
{
|
||||
path: PageEnum.REDIRECT,
|
||||
name: PageEnum.REDIRECT_NAME,
|
||||
component: RedirectHome,
|
||||
meta: {
|
||||
title: PageEnum.REDIRECT_NAME,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
{
|
||||
path: PageEnum.REDIRECT_UN_PUBLISH,
|
||||
name: PageEnum.REDIRECT_UN_PUBLISH_NAME,
|
||||
component: RedirectUnPublish,
|
||||
meta: {
|
||||
title: PageEnum.REDIRECT_UN_PUBLISH_NAME,
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
@@ -4,6 +4,10 @@ export const ErrorPage403 = () => import('@/views/exception/403.vue');
|
||||
|
||||
export const ErrorPage500 = () => import('@/views/exception/500.vue');
|
||||
|
||||
export const RedirectHome = () => import('@/views/redirect/index.vue');
|
||||
|
||||
export const RedirectUnPublish = () => import('@/views/redirect/UnPublish.vue');
|
||||
|
||||
export const Layout = () => import('@/layout/index.vue');
|
||||
|
||||
export const ParentLayout = () => import('@/layout/parentLayout.vue');
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import type { App } from 'vue'
|
||||
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
|
||||
import { RedirectRoute } from '@/router/base'
|
||||
import { createRouterGuards } from './router-guards'
|
||||
import { PageEnum } from '@/enums/pageEnum'
|
||||
import { HttpErrorPage, LoginRoute, ReloadRoute } from '@/router/base'
|
||||
import { HttpErrorPage, LoginRoute, ReloadRoute, RedirectRoute } from '@/router/base'
|
||||
import { Layout } from '@/router/constant'
|
||||
|
||||
import modules from '@/router/modules'
|
||||
@@ -19,6 +18,7 @@ const RootRoute: Array<RouteRecordRaw> = [
|
||||
},
|
||||
children: [
|
||||
...HttpErrorPage,
|
||||
...RedirectRoute,
|
||||
modules.projectRoutes,
|
||||
modules.chartRoutes,
|
||||
modules.previewRoutes,
|
||||
@@ -28,7 +28,7 @@ const RootRoute: Array<RouteRecordRaw> = [
|
||||
]
|
||||
|
||||
|
||||
export const constantRouter: any[] = [LoginRoute, ...RootRoute, RedirectRoute, ReloadRoute];
|
||||
export const constantRouter: any[] = [LoginRoute, ...RootRoute, ReloadRoute];
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(''),
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
import { Router } from 'vue-router';
|
||||
import { PageEnum } from '@/enums/pageEnum'
|
||||
import { PageEnum, PreviewEnum } from '@/enums/pageEnum'
|
||||
import { loginCheck } from '@/utils'
|
||||
|
||||
// 路由白名单
|
||||
const routerAllowList = [
|
||||
// 登录
|
||||
PageEnum.BASE_LOGIN_NAME,
|
||||
// 预览
|
||||
PreviewEnum.CHART_PREVIEW_NAME
|
||||
]
|
||||
|
||||
export function createRouterGuards(router: Router) {
|
||||
// 前置
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
@@ -19,10 +27,8 @@ export function createRouterGuards(router: Router) {
|
||||
next({ name: PageEnum.ERROR_PAGE_NAME_404 })
|
||||
}
|
||||
|
||||
if (!loginCheck()) {
|
||||
if (to.name === PageEnum.BASE_LOGIN_NAME) {
|
||||
next()
|
||||
}
|
||||
// @ts-ignore
|
||||
if (!routerAllowList.includes(to.name) && !loginCheck()) {
|
||||
next({ name: PageEnum.BASE_LOGIN_NAME })
|
||||
}
|
||||
next()
|
||||
|
||||
@@ -61,6 +61,9 @@ export const editToJsonInterval = 5000
|
||||
// 数据请求间隔
|
||||
export const requestInterval = 30
|
||||
|
||||
// 工作台自动保存间隔(s)
|
||||
export const saveInterval = 30
|
||||
|
||||
// 数据请求间隔单位
|
||||
export const requestIntervalUnit = RequestHttpIntervalEnum.SECOND
|
||||
|
||||
|
||||
2
src/settings/httpSetting.ts
Normal file
2
src/settings/httpSetting.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
// 请求前缀
|
||||
export const axiosPre = '/api/goview'
|
||||
@@ -1,5 +1,6 @@
|
||||
import { CreateComponentType, CreateComponentGroupType, FilterEnum } from '@/packages/index.d'
|
||||
import { HistoryActionTypeEnum } from '@/store/modules/chartHistoryStore/chartHistoryStore.d'
|
||||
import { SyncEnum } from '@/enums/editPageEnum'
|
||||
import {
|
||||
RequestHttpEnum,
|
||||
RequestContentTypeEnum,
|
||||
@@ -12,6 +13,29 @@ import {
|
||||
import { PreviewScaleEnum } from '@/enums/styleEnum'
|
||||
import type { ChartColorsNameType, 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 {
|
||||
EDIT_LAYOUT_DOM = 'editLayoutDom',
|
||||
@@ -20,13 +44,14 @@ export enum EditCanvasTypeEnum {
|
||||
SCALE = 'scale',
|
||||
USER_SCALE = 'userScale',
|
||||
LOCK_SCALE = 'lockScale',
|
||||
SAVE_STATUS = 'saveStatus',
|
||||
IS_CREATE = 'isCreate',
|
||||
IS_DRAG = 'isDrag',
|
||||
IS_SELECT = 'isSelect',
|
||||
IS_CODE_EDIT="isCodeEdit"
|
||||
}
|
||||
|
||||
// 编辑区域
|
||||
// 编辑区域(临时)
|
||||
export type EditCanvasType = {
|
||||
// 编辑区域 DOM
|
||||
[EditCanvasTypeEnum.EDIT_LAYOUT_DOM]: HTMLElement | null
|
||||
@@ -43,13 +68,15 @@ export type EditCanvasType = {
|
||||
[EditCanvasTypeEnum.IS_CREATE]: boolean
|
||||
// 拖拽中
|
||||
[EditCanvasTypeEnum.IS_DRAG]: boolean
|
||||
// 保存状态
|
||||
[EditCanvasTypeEnum.SAVE_STATUS]: SyncEnum
|
||||
// 框选中
|
||||
[EditCanvasTypeEnum.IS_SELECT]: boolean
|
||||
// 代码编辑中
|
||||
[EditCanvasTypeEnum.IS_CODE_EDIT]: boolean
|
||||
}
|
||||
|
||||
// 滤镜/背景色/宽高主题等
|
||||
// 画布数据/滤镜/背景色/宽高主题等
|
||||
export enum EditCanvasConfigEnum {
|
||||
PROJECT_NAME = 'projectName',
|
||||
WIDTH = 'width',
|
||||
@@ -63,7 +90,14 @@ export enum EditCanvasConfigEnum {
|
||||
PREVIEW_SCALE_TYPE = 'previewScaleType'
|
||||
}
|
||||
|
||||
export interface EditCanvasConfigType {
|
||||
// 画布属性(需保存)
|
||||
export type EditCanvasConfigType = {
|
||||
// ID
|
||||
[EditCanvasConfigEnum.PROJECT_ID]: string,
|
||||
// 项目名称
|
||||
[EditCanvasConfigEnum.PROJECT_NAME]?: string,
|
||||
// 项目描述
|
||||
[EditCanvasConfigEnum.REMARKS]: string,
|
||||
// 滤镜-启用
|
||||
[FilterEnum.FILTERS_SHOW]: boolean
|
||||
// 滤镜-色相
|
||||
@@ -140,6 +174,7 @@ export type RecordChartType = {
|
||||
|
||||
// Store 枚举
|
||||
export enum ChartEditStoreEnum {
|
||||
PROJECT_INFO = 'projectInfo',
|
||||
EDIT_RANGE = 'editRange',
|
||||
EDIT_CANVAS = 'editCanvas',
|
||||
RIGHT_MENU_SHOW = 'rightMenuShow',
|
||||
@@ -201,6 +236,7 @@ export interface RequestConfigType extends RequestPublicConfigType {
|
||||
|
||||
// Store 类型
|
||||
export interface ChartEditStoreType {
|
||||
[ChartEditStoreEnum.PROJECT_INFO]: ProjectInfoType
|
||||
[ChartEditStoreEnum.EDIT_CANVAS]: EditCanvasType
|
||||
[ChartEditStoreEnum.EDIT_CANVAS_CONFIG]: EditCanvasConfigType
|
||||
[ChartEditStoreEnum.RIGHT_MENU_SHOW]: boolean
|
||||
|
||||
@@ -10,14 +10,22 @@ import { requestInterval, previewScaleType, requestIntervalUnit } from '@/settin
|
||||
import { useChartHistoryStore } from '@/store/modules/chartHistoryStore/chartHistoryStore'
|
||||
// 全局设置
|
||||
import { useSettingStore } from '@/store/modules/settingStore/settingStore'
|
||||
// 历史类型
|
||||
import { HistoryActionTypeEnum, HistoryItemType, HistoryTargetTypeEnum } from '@/store/modules/chartHistoryStore/chartHistoryStore.d'
|
||||
// 画布枚举
|
||||
import { MenuEnum, SyncEnum } from '@/enums/editPageEnum'
|
||||
|
||||
import {
|
||||
HistoryActionTypeEnum,
|
||||
HistoryItemType,
|
||||
HistoryTargetTypeEnum
|
||||
} from '@/store/modules/chartHistoryStore/chartHistoryStore.d'
|
||||
import { MenuEnum } from '@/enums/editPageEnum'
|
||||
import { getUUID, loadingStart, loadingFinish, loadingError, isString, isArray } from '@/utils'
|
||||
getUUID,
|
||||
loadingStart,
|
||||
loadingFinish,
|
||||
loadingError,
|
||||
isString,
|
||||
isArray
|
||||
} from '@/utils'
|
||||
|
||||
import {
|
||||
ProjectInfoType,
|
||||
ChartEditStoreEnum,
|
||||
ChartEditStorage,
|
||||
ChartEditStoreType,
|
||||
@@ -36,6 +44,14 @@ const settingStore = useSettingStore()
|
||||
export const useChartEditStore = defineStore({
|
||||
id: 'useChartEditStore',
|
||||
state: (): ChartEditStoreType => ({
|
||||
// 项目数据
|
||||
projectInfo: {
|
||||
projectId: '',
|
||||
projectName: '',
|
||||
remarks: '',
|
||||
thumbnail: '',
|
||||
release: false
|
||||
},
|
||||
// 画布属性
|
||||
editCanvas: {
|
||||
// 编辑区域 Dom
|
||||
@@ -55,6 +71,8 @@ export const useChartEditStore = defineStore({
|
||||
isDrag: false,
|
||||
// 框选中
|
||||
isSelect: false,
|
||||
// 同步中
|
||||
saveStatus: SyncEnum.PENDING,
|
||||
// 代码编辑中
|
||||
isCodeEdit: false
|
||||
},
|
||||
@@ -138,6 +156,9 @@ export const useChartEditStore = defineStore({
|
||||
componentList: []
|
||||
}),
|
||||
getters: {
|
||||
getProjectInfo(): ProjectInfoType {
|
||||
return this.projectInfo
|
||||
},
|
||||
getMousePosition(): MousePositionType {
|
||||
return this.mousePosition
|
||||
},
|
||||
@@ -180,6 +201,10 @@ export const useChartEditStore = defineStore({
|
||||
setEditCanvasConfig<T extends keyof EditCanvasConfigType, K extends EditCanvasConfigType[T]>(key: T, value: K) {
|
||||
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) {
|
||||
this.rightMenuShow = value
|
||||
|
||||
@@ -4,10 +4,10 @@ import { asideCollapsedWidth } from '@/settings/designSetting'
|
||||
import { SettingStoreType, ToolsStatusEnum } from './settingStore.d'
|
||||
import { setLocalStorage, getLocalStorage } from '@/utils'
|
||||
import { StorageEnum } from '@/enums/storageEnum'
|
||||
const { GO_SYSTEM_SETTING_STORE } = StorageEnum
|
||||
const { GO_SETTING_STORE } = StorageEnum
|
||||
|
||||
const storageSetting: SettingStoreType = getLocalStorage(
|
||||
GO_SYSTEM_SETTING_STORE
|
||||
GO_SETTING_STORE
|
||||
)
|
||||
|
||||
// 全局设置
|
||||
@@ -48,7 +48,7 @@ export const useSettingStore = defineStore({
|
||||
this.$patch(state => {
|
||||
state[key] = value
|
||||
})
|
||||
setLocalStorage(GO_SYSTEM_SETTING_STORE, this.$state)
|
||||
setLocalStorage(GO_SETTING_STORE, this.$state)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
31
src/store/modules/systemStore/systemStore.d.ts
vendored
Normal file
31
src/store/modules/systemStore/systemStore.d.ts
vendored
Normal 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
|
||||
}
|
||||
40
src/store/modules/systemStore/systemStore.ts
Normal file
40
src/store/modules/systemStore/systemStore.ts
Normal 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)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -1,3 +1,65 @@
|
||||
/**
|
||||
* * base64转file
|
||||
* @param dataurl
|
||||
* @param fileName
|
||||
* @returns
|
||||
*/
|
||||
export const base64toFile = (dataurl: string, fileName: string) => {
|
||||
let dataArr = dataurl.split(","),
|
||||
mime = (dataArr as any[])[0].match(/:(.*?);/)[1],
|
||||
bstr = atob(dataArr[1]),
|
||||
n = bstr.length,
|
||||
u8arr = new Uint8Array(n);
|
||||
while (n--) {
|
||||
u8arr[n] = bstr.charCodeAt(n);
|
||||
}
|
||||
return new File([u8arr], fileName, { type: mime });
|
||||
}
|
||||
|
||||
/**
|
||||
* * file转url
|
||||
*/
|
||||
export const fileToUrl = (file: File): string => {
|
||||
const Url = URL || window.URL || window.webkitURL
|
||||
const ImageUrl = Url.createObjectURL(file)
|
||||
return ImageUrl
|
||||
}
|
||||
|
||||
/**
|
||||
* * url转file
|
||||
*/
|
||||
export const urlToFile = (fileUrl: string, fileName = `${new Date().getTime()}`): File => {
|
||||
const dataArr = fileUrl.split(',')
|
||||
const mime = (dataArr as any[])[0].match(/:(.*);/)[1]
|
||||
const originStr = atob(dataArr[1])
|
||||
return new File([originStr], `${fileName}`, { type: mime })
|
||||
}
|
||||
|
||||
/**
|
||||
* * file转base64
|
||||
* @param file 文件数据
|
||||
* @param callback 回调函数
|
||||
*/
|
||||
export const fileTobase64 = (file: File, callback: Function) => {
|
||||
let reader = new FileReader()
|
||||
reader.readAsDataURL(file)
|
||||
reader.onload = function (e: ProgressEvent<FileReader>) {
|
||||
if (e.target) {
|
||||
let base64 = e.target.result
|
||||
callback(base64)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* * canvas转file
|
||||
* @param canvas
|
||||
*/
|
||||
export const canvastoFile = (canvas: HTMLCanvasElement, name?: string) => {
|
||||
const dataurl = canvas.toDataURL('image/png')
|
||||
return urlToFile(dataurl, name)
|
||||
}
|
||||
|
||||
/**
|
||||
* *获取上传的文件数据
|
||||
* @param { File } file 文件对象
|
||||
@@ -51,4 +113,4 @@ export const downloadTextFile = (
|
||||
// 字符内容转变成blob地址
|
||||
const blob = new Blob([content])
|
||||
downloadByA(URL.createObjectURL(blob), filename, fileSuffix)
|
||||
}
|
||||
}
|
||||
6
src/utils/http.ts
Normal file
6
src/utils/http.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* * 请求失败统一处理
|
||||
*/
|
||||
export const httpErrorHandle = () => {
|
||||
window['$message'].error(window['$t']('http.error_message'))
|
||||
}
|
||||
@@ -7,3 +7,4 @@ export * from '@/utils/plugin'
|
||||
export * from '@/utils/components'
|
||||
export * from '@/utils/type'
|
||||
export * from '@/utils/file'
|
||||
export * from '@/utils/http'
|
||||
@@ -35,7 +35,7 @@ export const loadingError = () => {
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
export const goDialog = (
|
||||
export const goDialog = (
|
||||
params: {
|
||||
// 基本
|
||||
type?: DialogEnum
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { useRoute } from 'vue-router'
|
||||
import { ResultEnum } from '@/enums/httpEnum'
|
||||
import { ErrorPageNameMap, PageEnum } from '@/enums/pageEnum'
|
||||
import { ResultEnum, RequestHttpHeaderEnum } from '@/enums/httpEnum'
|
||||
import { ErrorPageNameMap, PageEnum, PreviewEnum } from '@/enums/pageEnum'
|
||||
import { docPath, giteeSourceCodePath } from '@/settings/pathConst'
|
||||
import { cryptoDecode } from './crypto'
|
||||
import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'
|
||||
import { StorageEnum } from '@/enums/storageEnum'
|
||||
import { clearLocalStorage, getLocalStorage } from './storage'
|
||||
import { clearLocalStorage, getLocalStorage, clearCookie } from './storage'
|
||||
import router from '@/router'
|
||||
import { logoutApi } from '@/api/path'
|
||||
|
||||
/**
|
||||
* * 根据名字跳转路由
|
||||
@@ -101,11 +102,20 @@ export const reloadRoutePage = () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* * 退出
|
||||
* * 退出登录
|
||||
*/
|
||||
export const logout = () => {
|
||||
clearLocalStorage(StorageEnum.GO_LOGIN_INFO_STORE)
|
||||
routerTurnByName(PageEnum.BASE_LOGIN_NAME)
|
||||
export const logout = async () => {
|
||||
try {
|
||||
const res = await logoutApi()
|
||||
if(res && res.code === ResultEnum.SUCCESS) {
|
||||
window['$message'].success(window['$t']('global.logout_success'))
|
||||
clearCookie(RequestHttpHeaderEnum.COOKIE)
|
||||
clearLocalStorage(StorageEnum.GO_SYSTEM_STORE)
|
||||
routerTurnByName(PageEnum.BASE_LOGIN_NAME)
|
||||
}
|
||||
} catch (error) {
|
||||
window['$message'].success(window['$t']('global.logout_failure'))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -157,7 +167,7 @@ export const fetchRouteParams = () => {
|
||||
* * 通过硬解析获取当前路由下的参数
|
||||
* @returns object
|
||||
*/
|
||||
export const fetchRouteParamsLocation = () => {
|
||||
export const fetchRouteParamsLocation = () => {
|
||||
try {
|
||||
// 防止添加query参数的时候,解析ID异常
|
||||
return document.location.hash.split('?')[0].split('/').pop() || ''
|
||||
@@ -176,19 +186,29 @@ export const goHome = () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* * 判断是否登录(现阶段是有 login 数据即可)
|
||||
* * 判断是否登录
|
||||
* @return boolean
|
||||
*/
|
||||
export const loginCheck = () => {
|
||||
try {
|
||||
const info = getLocalStorage(StorageEnum.GO_LOGIN_INFO_STORE)
|
||||
const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
|
||||
if (!info) return false
|
||||
const decodeInfo = cryptoDecode(info)
|
||||
if (decodeInfo) {
|
||||
if (info[SystemStoreEnum.USER_INFO][SystemStoreUserInfoEnum.USER_TOKEN]) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* * 预览地址
|
||||
* @returns
|
||||
*/
|
||||
export const previewPath = (id?: string | number) => {
|
||||
const { origin, pathname } = document.location
|
||||
const path = fetchPathByName(PreviewEnum.CHART_PREVIEW_NAME, 'href')
|
||||
const previewPath = `${origin}${pathname}${path}/${id || fetchRouteParamsLocation()}`
|
||||
return previewPath
|
||||
}
|
||||
@@ -70,3 +70,41 @@ export const getSessionStorage: (k: string) => any = (k: string) => {
|
||||
export const clearSessioStorage = (name: string) => {
|
||||
window.sessionStorage.removeItem(name)
|
||||
}
|
||||
|
||||
/**
|
||||
* * 设置 cookie
|
||||
* @param name 键名
|
||||
* @param cvalue 键值
|
||||
* @param exdays 过期时间
|
||||
*/
|
||||
export const setCookie = (name: string, cvalue: string, exdays: number) => {
|
||||
const d = new Date();
|
||||
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
|
||||
const expires = "expires=" + d.toUTCString();
|
||||
document.cookie = name + "=" + cvalue + "; " + expires;
|
||||
}
|
||||
|
||||
/**
|
||||
* * 获取 cookie
|
||||
* @param cname 键名
|
||||
* @returns string
|
||||
*/
|
||||
export const getCookie = (cname: string) => {
|
||||
const name = cname + "=";
|
||||
const ca = document.cookie.split(';');
|
||||
for (let i = 0; i < ca.length; i++) {
|
||||
let c = ca[i];
|
||||
while (c.charAt(0) == ' ') c = c.substring(1);
|
||||
if (c.indexOf(name) != -1) return c.substring(name.length, c.length);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* * 清除 cookie
|
||||
* @param name 键名
|
||||
* @returns string
|
||||
*/
|
||||
export const clearCookie = (name: string) => {
|
||||
setCookie(name, "", -1);
|
||||
}
|
||||
|
||||
@@ -114,29 +114,6 @@ export const isMac = () => {
|
||||
return /macintosh|mac os x/i.test(navigator.userAgent)
|
||||
}
|
||||
|
||||
/**
|
||||
* * file转url
|
||||
*/
|
||||
export const fileToUrl = (file: File): string => {
|
||||
const Url = URL || window.URL || window.webkitURL
|
||||
const ImageUrl = Url.createObjectURL(file)
|
||||
return ImageUrl
|
||||
}
|
||||
|
||||
/**
|
||||
* * file转base64
|
||||
*/
|
||||
export const fileTobase64 = (file: File, callback: Function) => {
|
||||
let reader = new FileReader()
|
||||
reader.readAsDataURL(file)
|
||||
reader.onload = function (e: ProgressEvent<FileReader>) {
|
||||
if (e.target) {
|
||||
let base64 = e.target.result
|
||||
callback(base64)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* * 挂载监听
|
||||
*/
|
||||
@@ -353,3 +330,23 @@ export const JSONParse = (data: string) => {
|
||||
export const setTitle = (title?: string) => {
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -132,16 +132,20 @@ import { swatchesColors } from '@/settings/chartThemes/index'
|
||||
import { FileTypeEnum } from '@/enums/fileTypeEnum'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
import { useSystemStore } from '@/store/modules/systemStore/systemStore'
|
||||
import { StylesSetting } from '@/components/Pages/ChartItemSetting'
|
||||
import { UploadCustomRequestOptions } from 'naive-ui'
|
||||
import { fileToUrl, loadAsyncComponent } from '@/utils'
|
||||
import { loadAsyncComponent, fetchRouteParamsLocation } from '@/utils'
|
||||
import { PreviewScaleEnum } from '@/enums/styleEnum'
|
||||
import { ResultEnum } from '@/enums/httpEnum'
|
||||
import { icon } from '@/plugins'
|
||||
import { uploadFile } from '@/api/path'
|
||||
|
||||
const { ColorPaletteIcon } = icon.ionicons5
|
||||
const { ScaleIcon, FitToScreenIcon, FitToHeightIcon, FitToWidthIcon } = icon.carbon
|
||||
|
||||
const chartEditStore = useChartEditStore()
|
||||
const systemStore = useSystemStore()
|
||||
const canvasConfig = chartEditStore.getEditCanvasConfig
|
||||
const editCanvas = chartEditStore.getEditCanvas
|
||||
|
||||
@@ -266,11 +270,32 @@ const clearColor = () => {
|
||||
// 自定义上传操作
|
||||
const customRequest = (options: UploadCustomRequestOptions) => {
|
||||
const { file } = options
|
||||
nextTick(() => {
|
||||
nextTick(async () => {
|
||||
if (file.file) {
|
||||
const ImageUrl = fileToUrl(file.file)
|
||||
chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.BACKGROUND_IMAGE, ImageUrl)
|
||||
chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.SELECT_COLOR, false)
|
||||
// 修改名称
|
||||
const newNameFile = new File([file.file], `${fetchRouteParamsLocation()}_index_background.png`, {
|
||||
type: file.file.type
|
||||
})
|
||||
let uploadParams = new FormData()
|
||||
uploadParams.append('object', newNameFile)
|
||||
const uploadRes = await uploadFile(uploadParams)
|
||||
|
||||
if (uploadRes && uploadRes.code === ResultEnum.SUCCESS) {
|
||||
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 {
|
||||
window['$message'].error('添加图片失败,请稍后重试!')
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import { RequestContentTypeEnum } from '@/enums/httpEnum'
|
||||
import { useTargetData } from '../../../hooks/useTargetData.hook'
|
||||
import { RequestGlobalConfig } from './components/RequestGlobalConfig'
|
||||
import { RequestTargetConfig } from './components/RequestTargetConfig'
|
||||
import { useSync } from '@/views/chart/hooks/useSync.hook'
|
||||
import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
|
||||
|
||||
const props = defineProps({
|
||||
@@ -43,6 +44,9 @@ const props = defineProps({
|
||||
})
|
||||
const emit = defineEmits(['update:modelShow', 'sendHandle'])
|
||||
|
||||
const { targetData } = useTargetData()
|
||||
const { dataSyncUpdate } = useSync()
|
||||
|
||||
// 解构基础配置
|
||||
const { chartConfig } = toRefs(props.targetData as CreateComponentType)
|
||||
const { requestContentType } = toRefs((props.targetData as CreateComponentType).request)
|
||||
@@ -69,6 +73,7 @@ const closeHandle = () => {
|
||||
const closeAndSendHandle = () => {
|
||||
emit('update:modelShow', false)
|
||||
emit('sendHandle')
|
||||
dataSyncUpdate()
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ import { useTargetData } from '../../../hooks/useTargetData.hook'
|
||||
import { RequestGlobalConfig } from './components/RequestGlobalConfig'
|
||||
import { RequestTargetConfig } from './components/RequestTargetConfig'
|
||||
import { RequestDataPondItemType } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
import { useSync } from '@/views/chart/hooks/useSync.hook'
|
||||
import { goDialog } from '@/utils'
|
||||
|
||||
const props = defineProps({
|
||||
@@ -56,6 +57,7 @@ const props = defineProps({
|
||||
})
|
||||
const emit = defineEmits(['update:modelShow', 'editSaveHandle'])
|
||||
|
||||
const { dataSyncUpdate } = useSync()
|
||||
const pondName = ref()
|
||||
const inputInstRef = ref()
|
||||
const modelShowRef = ref(false)
|
||||
@@ -82,6 +84,7 @@ const closeAndSendHandle = () => {
|
||||
onPositiveCallback: () => {
|
||||
emit('update:modelShow', false)
|
||||
emit('editSaveHandle', props.targetDataRequest)
|
||||
dataSyncUpdate()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
<edit-history></edit-history>
|
||||
<!-- CTRL按键触发展示 -->
|
||||
<n-text id="keyboard-dress-show" depth="3"></n-text>
|
||||
<n-divider vertical />
|
||||
<edit-data-sync></edit-data-sync>
|
||||
</n-space>
|
||||
|
||||
<n-space class="bottom-ri">
|
||||
@@ -57,7 +59,8 @@ import { SelectInst } from 'naive-ui'
|
||||
import { reactive, ref, toRefs, watchEffect } from 'vue'
|
||||
import { icon } from '@/plugins'
|
||||
import { EditHistory } from '../EditHistory/index'
|
||||
import EditShortcutKey from '../EditShortcutKey/index.vue'
|
||||
import { EditShortcutKey } from '../EditShortcutKey/index'
|
||||
import { EditDataSync } from '../EditDataSync/index'
|
||||
import { useDesignStore } from '@/store/modules/designStore/designStore'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
@@ -151,6 +154,10 @@ $max-width: 670px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 10px;
|
||||
width: 100%;
|
||||
min-width: $min-width;
|
||||
height: 40px;
|
||||
.bottom-ri {
|
||||
position: relative;
|
||||
top: 15px;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
import EditDataSync from './index.vue'
|
||||
|
||||
export { EditDataSync }
|
||||
@@ -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>
|
||||
@@ -133,9 +133,6 @@ const options = computed(() => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.mr-10 {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.edit-history-popover {
|
||||
.btn-text {
|
||||
font-size: 12px;
|
||||
|
||||
@@ -112,20 +112,25 @@ const shortcutKeyOptions = [
|
||||
win: `${WinKeyboard.CTRL.toUpperCase()} + ${WinKeyboard.SHIFT.toUpperCase()} + Z `,
|
||||
mac: `${MacKeyboard.CTRL.toUpperCase()} + ${MacKeyboard.SHIFT.toUpperCase()} + Z `
|
||||
},
|
||||
{
|
||||
label: '保存',
|
||||
win: `${WinKeyboard.CTRL.toUpperCase()} + S `,
|
||||
mac: `${MacKeyboard.CTRL.toUpperCase()} + S `,
|
||||
},
|
||||
{
|
||||
label: '多选',
|
||||
win: `${WinKeyboard.CTRL.toUpperCase()} + 🖱️ `,
|
||||
mac: `${MacKeyboard.CTRL_SOURCE_KEY.toUpperCase()} + 🖱️ `
|
||||
mac: `${MacKeyboard.CTRL.toUpperCase()} + 🖱️ `
|
||||
},
|
||||
{
|
||||
label: '创建分组',
|
||||
win: `${WinKeyboard.CTRL.toUpperCase()} + G / 🖱️ `,
|
||||
mac: `${MacKeyboard.CTRL_SOURCE_KEY.toUpperCase()} + G / 🖱️`
|
||||
mac: `${MacKeyboard.CTRL.toUpperCase()} + G / 🖱️`
|
||||
},
|
||||
{
|
||||
label: '解除分组',
|
||||
win: `${WinKeyboard.CTRL.toUpperCase()} + ${WinKeyboard.SHIFT.toUpperCase()} + G `,
|
||||
mac: `${MacKeyboard.CTRL_SOURCE_KEY.toUpperCase()} + ${WinKeyboard.SHIFT.toUpperCase()} + G `
|
||||
mac: `${MacKeyboard.CTRL.toUpperCase()} + ${WinKeyboard.SHIFT.toUpperCase()} + G `
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
import EditShortcutKey from './index.vue'
|
||||
|
||||
export { EditShortcutKey }
|
||||
@@ -7,7 +7,6 @@ import { useSync } from '@/views/chart/hooks/useSync.hook'
|
||||
export const useFile = () => {
|
||||
const importUploadFileListRef = ref()
|
||||
const { updateComponent } = useSync()
|
||||
|
||||
// 上传-前置
|
||||
//@ts-ignore
|
||||
const importBeforeUpload = ({ file }) => {
|
||||
|
||||
@@ -9,7 +9,7 @@ import { SavePageEnum } from '@/enums/editPageEnum'
|
||||
import { editToJsonInterval } from '@/settings/designSetting'
|
||||
import { goDialog } from '@/utils'
|
||||
|
||||
const { updateComponent } = useSync()
|
||||
const { updateComponent, dataSyncUpdate } = useSync()
|
||||
const chartEditStore = useChartEditStore()
|
||||
|
||||
export const syncData = () => {
|
||||
@@ -17,8 +17,9 @@ export const syncData = () => {
|
||||
message: '是否覆盖源视图内容,此操作不可撤回?',
|
||||
isMaskClosable: true,
|
||||
transformOrigin: 'center',
|
||||
onPositiveCallback: () => {
|
||||
onPositiveCallback: async () => {
|
||||
window['$message'].success('正在同步编辑器...')
|
||||
dataSyncUpdate && (await dataSyncUpdate())
|
||||
dispatchEvent(new CustomEvent(SavePageEnum.CHART, { detail: chartEditStore.getStorageInfo() }))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -87,13 +87,21 @@ import { onMounted, computed, provide } from 'vue'
|
||||
import { chartColors } from '@/settings/chartThemes/index'
|
||||
import { MenuEnum } from '@/enums/editPageEnum'
|
||||
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 { MenuOptionsItemType } from '@/views/chart/hooks/useContextMenu.hook.d'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { SCALE_KEY } from '@/views/preview/hooks/useScale.hook'
|
||||
import { useLayout } from './hooks/useLayout.hook'
|
||||
import { useAddKeyboard } from '../hooks/useKeyboard.hook'
|
||||
import { useSync } from '../hooks/useSync.hook'
|
||||
import { dragHandle, dragoverHandle, mousedownHandleUnStop, useMouseHandle } from './hooks/useDrag.hook'
|
||||
import { useComponentStyle, useSizeStyle } from './hooks/useStyle.hook'
|
||||
|
||||
@@ -107,6 +115,10 @@ import { EditTools } from './components/EditTools'
|
||||
|
||||
const chartEditStore = useChartEditStore()
|
||||
const { handleContextMenu } = useContextMenu()
|
||||
const { dataSyncFetch, intervalDataSyncUpdate } = useSync()
|
||||
|
||||
// 加入网页关闭提示
|
||||
addWindowUnload()
|
||||
|
||||
// 编辑时注入scale变量,消除警告
|
||||
provide(SCALE_KEY, null)
|
||||
@@ -178,9 +190,13 @@ const rangeStyle = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
// 键盘事件
|
||||
onMounted(() => {
|
||||
// 键盘事件
|
||||
useAddKeyboard()
|
||||
// 获取数据
|
||||
dataSyncFetch()
|
||||
// 定时更新数据
|
||||
// intervalDataSyncUpdate()
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -29,26 +29,44 @@
|
||||
</template>
|
||||
<span>{{ item.title }}</span>
|
||||
</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>
|
||||
</template>
|
||||
|
||||
<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 { icon } from '@/plugins'
|
||||
import { useRemoveKeyboard } from '../../hooks/useKeyboard.hook'
|
||||
|
||||
import { useSync } from '../../hooks/useSync.hook'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
|
||||
import { useChartHistoryStore } from '@/store/modules/chartHistoryStore/chartHistoryStore'
|
||||
import { HistoryStackEnum } from '@/store/modules/chartHistoryStore/chartHistoryStore.d'
|
||||
|
||||
import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore'
|
||||
import { ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d'
|
||||
|
||||
const { LayersIcon, BarChartIcon, PrismIcon, HomeIcon, ArrowBackIcon, ArrowForwardIcon } = icon.ionicons5
|
||||
const { SaveIcon } = icon.carbon
|
||||
const { setItem } = useChartLayoutStore()
|
||||
const { dataSyncUpdate } = useSync()
|
||||
const { getLayers, getCharts, getDetails } = toRefs(useChartLayoutStore())
|
||||
const chartEditStore = useChartEditStore()
|
||||
const chartHistoryStore = useChartHistoryStore()
|
||||
@@ -130,7 +148,7 @@ const clickHistoryHandle = (item: ItemType<HistoryStackEnum>) => {
|
||||
// 返回首页
|
||||
const goHomeHandle = () => {
|
||||
goDialog({
|
||||
message: '返回将不会保存任何操作',
|
||||
message: '确定已保存了数据(Ctrl / ⌘ + S),并返回到首页吗?',
|
||||
isMaskClosable: true,
|
||||
onPositiveCallback: () => {
|
||||
goHome()
|
||||
|
||||
@@ -1,30 +1,92 @@
|
||||
<template>
|
||||
<n-space class="go-mt-0">
|
||||
<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>
|
||||
<component :is="item.icon"></component>
|
||||
</template>
|
||||
<span>{{ item.title }}</span>
|
||||
<span>{{ item.title() }}</span>
|
||||
</n-button>
|
||||
</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>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { renderIcon, goDialog, fetchPathByName, routerTurnByPath, setSessionStorage, getLocalStorage } from '@/utils'
|
||||
import { ref, computed, watchEffect } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useClipboard } from '@vueuse/core'
|
||||
import { PreviewEnum } from '@/enums/pageEnum'
|
||||
import { StorageEnum } from '@/enums/storageEnum'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { ResultEnum } from '@/enums/httpEnum'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
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,
|
||||
getLocalStorage,
|
||||
httpErrorHandle,
|
||||
fetchRouteParamsLocation
|
||||
} from '@/utils'
|
||||
import { icon } from '@/plugins'
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const { BrowsersOutlineIcon, SendIcon, AnalyticsIcon } = icon.ionicons5
|
||||
const { BrowsersOutlineIcon, SendIcon, AnalyticsIcon, CloseIcon } = icon.ionicons5
|
||||
const chartEditStore = useChartEditStore()
|
||||
|
||||
const previewPathRef = ref(previewPath())
|
||||
const { copy, isSupported } = useClipboard({ source: previewPathRef })
|
||||
|
||||
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 path = fetchPathByName(PreviewEnum.CHART_PREVIEW_NAME, 'href')
|
||||
@@ -39,7 +101,10 @@ const previewHandle = () => {
|
||||
const repeateIndex = sessionStorageInfo.findIndex((e: { id: string }) => e.id === previewId)
|
||||
// 重复替换
|
||||
if (repeateIndex !== -1) {
|
||||
sessionStorageInfo.splice(repeateIndex, 1, { id: previewId, ...storageInfo })
|
||||
sessionStorageInfo.splice(repeateIndex, 1, {
|
||||
id: previewId,
|
||||
...storageInfo
|
||||
})
|
||||
setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, sessionStorageInfo)
|
||||
} else {
|
||||
sessionStorageInfo.push({
|
||||
@@ -55,35 +120,63 @@ const previewHandle = () => {
|
||||
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 = () => {
|
||||
goDialog({
|
||||
message: '想体验发布功能,请前往 master-fetch 分支查看: https://gitee.com/MTrun/go-view/tree/master-fetch',
|
||||
positiveText: '了然',
|
||||
closeNegativeText: true,
|
||||
onPositiveCallback: () => {}
|
||||
const sendHandle = async () => {
|
||||
const res = await changeProjectReleaseApi({
|
||||
id: fetchRouteParamsLocation(),
|
||||
// 反过来
|
||||
state: release.value ? -1 : 1
|
||||
})
|
||||
|
||||
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 = [
|
||||
{
|
||||
select: true,
|
||||
title: '同步内容',
|
||||
type: 'primary',
|
||||
title: () => '同步内容',
|
||||
type: () => 'primary',
|
||||
icon: renderIcon(AnalyticsIcon),
|
||||
event: syncData
|
||||
},
|
||||
{
|
||||
select: true,
|
||||
title: '预览',
|
||||
key: 'preview',
|
||||
title: () => '预览',
|
||||
type: () => 'default',
|
||||
icon: renderIcon(BrowsersOutlineIcon),
|
||||
event: previewHandle
|
||||
},
|
||||
{
|
||||
select: true,
|
||||
title: '发布',
|
||||
key: 'release',
|
||||
title: () => (release.value ? '已发布' : '发布'),
|
||||
icon: renderIcon(SendIcon),
|
||||
event: sendHandle
|
||||
type: () => (release.value ? 'primary' : 'default'),
|
||||
event: modelShowHandle
|
||||
}
|
||||
]
|
||||
|
||||
@@ -98,7 +191,15 @@ const comBtnList = computed(() => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.align-center {
|
||||
margin-top: -4px;
|
||||
@include go('system-setting') {
|
||||
@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>
|
||||
|
||||
@@ -28,28 +28,27 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, nextTick, computed } from 'vue'
|
||||
import { fetchRouteParamsLocation, setTitle } from '@/utils'
|
||||
import { ref, nextTick, computed, watchEffect } from 'vue'
|
||||
import { ResultEnum } from '@/enums/httpEnum'
|
||||
import { fetchRouteParamsLocation, httpErrorHandle, setTitle } from '@/utils'
|
||||
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'
|
||||
|
||||
const { FishIcon } = icon.ionicons5
|
||||
const chartEditStore = useChartEditStore()
|
||||
const { dataSyncUpdate } = useSync()
|
||||
const { FishIcon } = icon.ionicons5
|
||||
|
||||
const focus = ref<boolean>(false)
|
||||
const inputInstRef = ref(null)
|
||||
|
||||
// 根据路由 id 参数获取项目信息
|
||||
const fetchProhectInfoById = () => {
|
||||
const id = fetchRouteParamsLocation()
|
||||
if (id.length) {
|
||||
return id[0]
|
||||
}
|
||||
return ''
|
||||
}
|
||||
const title = ref<string>(fetchRouteParamsLocation())
|
||||
|
||||
const title = ref<string>(fetchProhectInfoById() || '')
|
||||
watchEffect(() => {
|
||||
title.value = chartEditStore.getProjectInfo.projectName || ''
|
||||
})
|
||||
|
||||
const comTitle = computed(() => {
|
||||
// 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
|
||||
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>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { useSync } from './useSync.hook'
|
||||
import { WinKeyboard, MacKeyboard, MenuEnum } from '@/enums/editPageEnum'
|
||||
import throttle from 'lodash/throttle'
|
||||
import debounce from 'lodash/debounce'
|
||||
@@ -7,7 +8,7 @@ import { setKeyboardDressShow } from '@/utils'
|
||||
|
||||
// Keymaster可以支持识别以下组合键: ⇧,shift,option,⌥,alt,ctrl,control,command,和⌘
|
||||
const chartEditStore = useChartEditStore()
|
||||
|
||||
const useSyncIns = useSync()
|
||||
const winCtrlMerge = (e: string) => `${WinKeyboard.CTRL}+${e}`
|
||||
const winShiftMerge = (e: string) => `${WinKeyboard.SHIFT}+${e}`
|
||||
const winAltMerge = (e: string) => `${WinKeyboard.ALT}+${e}`
|
||||
@@ -23,6 +24,7 @@ export const winKeyboardValue = {
|
||||
[MenuEnum.DELETE]: 'delete',
|
||||
[MenuEnum.BACK]: winCtrlMerge('z'),
|
||||
[MenuEnum.FORWORD]: winCtrlMerge(winShiftMerge('z')),
|
||||
[MenuEnum.SAVE]: winCtrlMerge('s'),
|
||||
[MenuEnum.GROUP]: winCtrlMerge('g'),
|
||||
[MenuEnum.UN_GROUP]: winCtrlMerge(winShiftMerge('g')),
|
||||
[MenuEnum.LOCK]: winCtrlMerge('l'),
|
||||
@@ -48,6 +50,7 @@ export const macKeyboardValue = {
|
||||
[MenuEnum.DELETE]: macCtrlMerge('backspace'),
|
||||
[MenuEnum.BACK]: macCtrlMerge('z'),
|
||||
[MenuEnum.FORWORD]: macCtrlMerge(macShiftMerge('z')),
|
||||
[MenuEnum.SAVE]: macCtrlMerge('s'),
|
||||
[MenuEnum.GROUP]: macCtrlMerge('g'),
|
||||
[MenuEnum.UN_GROUP]: macCtrlMerge(macShiftMerge('g')),
|
||||
[MenuEnum.LOCK]: macCtrlMerge('l'),
|
||||
@@ -71,6 +74,7 @@ const winKeyList: Array<string> = [
|
||||
winKeyboardValue.back,
|
||||
winKeyboardValue.forward,
|
||||
|
||||
winKeyboardValue.save,
|
||||
winKeyboardValue.group,
|
||||
winKeyboardValue.unGroup,
|
||||
|
||||
@@ -96,6 +100,7 @@ const macKeyList: Array<string> = [
|
||||
macKeyboardValue.back,
|
||||
macKeyboardValue.forward,
|
||||
|
||||
macKeyboardValue.save,
|
||||
macKeyboardValue.group,
|
||||
macKeyboardValue.unGroup,
|
||||
|
||||
@@ -215,6 +220,11 @@ export const useAddKeyboard = () => {
|
||||
case keyboardValue.show:
|
||||
keymaster(e, throttle(() => { chartEditStore.setShow(); return false }, throttleTime))
|
||||
break;
|
||||
|
||||
// 保存 ct+s
|
||||
case keyboardValue.save:
|
||||
keymaster(e, throttle(() => { useSyncIns.dataSyncUpdate(); return false }, 200))
|
||||
break;
|
||||
}
|
||||
}
|
||||
winKeyList.forEach((key: string) => {
|
||||
|
||||
@@ -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 { 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 { StylesSetting } from '@/components/Pages/ChartItemSetting'
|
||||
import { useSystemStore } from '@/store/modules/systemStore/systemStore'
|
||||
import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore'
|
||||
import { ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d'
|
||||
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 { PublicGroupConfigClass } from '@/packages/public/publicConfig'
|
||||
import merge from 'lodash/merge'
|
||||
@@ -89,6 +101,7 @@ const componentMerge = (newObject: any, sources: any, notComponent = false) => {
|
||||
export const useSync = () => {
|
||||
const chartEditStore = useChartEditStore()
|
||||
const chartHistoryStore = useChartHistoryStore()
|
||||
const systemStore = useSystemStore()
|
||||
const chartLayoutStore = useChartLayoutStore()
|
||||
/**
|
||||
* * 组件动态注册
|
||||
@@ -205,7 +218,142 @@ export const useSync = () => {
|
||||
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 {
|
||||
updateComponent
|
||||
updateComponent,
|
||||
updateStoreInfo,
|
||||
dataSyncFetch,
|
||||
dataSyncUpdate,
|
||||
intervalDataSyncUpdate
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
lineNumbers: 'on',
|
||||
minimap: { enabled: true }
|
||||
}"
|
||||
/>
|
||||
/>
|
||||
</n-layout-content>
|
||||
</n-layout>
|
||||
</div>
|
||||
@@ -46,11 +46,17 @@ import { ref } from 'vue'
|
||||
import { MonacoEditor } from '@/components/Pages/MonacoEditor'
|
||||
import { SavePageEnum } from '@/enums/editPageEnum'
|
||||
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 { 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'
|
||||
|
||||
const chartEditStore = useChartEditStore()
|
||||
const { dataSyncUpdate } = useSync()
|
||||
|
||||
const { ChevronBackOutlineIcon, DownloadIcon, AnalyticsIcon } = icon.ionicons5
|
||||
const showOpenFilePicker: Function = (window as any).showOpenFilePicker
|
||||
const content = ref('')
|
||||
@@ -122,11 +128,16 @@ async function updateSync() {
|
||||
message: '是否覆盖源视图内容? 此操作不可撤!',
|
||||
isMaskClosable: true,
|
||||
transformOrigin: 'center',
|
||||
onPositiveCallback: () => {
|
||||
onPositiveCallback: async () => {
|
||||
try {
|
||||
const detail = JSONParse(content.value)
|
||||
delete detail.id
|
||||
// 保持id不变
|
||||
// 带后端版本额外处理请求
|
||||
if (dataSyncUpdate) {
|
||||
chartEditStore.setProjectInfo(ProjectInfoEnum.PROJECT_ID, fetchRouteParamsLocation())
|
||||
await dataSyncUpdate(false) // JSON界面保存不上传缩略图
|
||||
}
|
||||
window.opener.dispatchEvent(new CustomEvent(SavePageEnum.JSON, { detail }))
|
||||
window['$message'].success('正在同步内容...')
|
||||
} catch (e) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<img src="~@/assets/images/exception/403.svg" alt="" />
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<h1 class="text-base text-gray-500">抱歉,你无权访问该页面</h1>
|
||||
<h1>抱歉,你无权访问该页面</h1>
|
||||
</div>
|
||||
<n-button type="primary" @click="goHome">回到首页</n-button>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<img src="~@/assets/images/exception/404.svg" alt="" />
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<h1 class="text-base text-gray-500">抱歉,你访问的页面不存在</h1>
|
||||
<h1>抱歉,你访问的页面不存在</h1>
|
||||
</div>
|
||||
<n-button type="primary" @click="goHome">回到首页</n-button>
|
||||
</div>
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<img src="~@/assets/images/exception/500.svg" alt="" />
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<h1 class="text-base text-gray-500">抱歉,服务器出错了</h1>
|
||||
<h1 class="text-base text-gray-500">抱歉,服务器出错了,建议您重新登录呢</h1>
|
||||
</div>
|
||||
<n-button type="primary" secondary @click="goHome">回到首页</n-button>
|
||||
<n-button type="primary" secondary @click="goLogin">重新登录</n-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
import { PageEnum } from '@/enums/pageEnum'
|
||||
import { routerTurnByName } from '@/utils'
|
||||
|
||||
function goHome() {
|
||||
routerTurnByName(PageEnum.BASE_HOME_NAME)
|
||||
function goLogin() {
|
||||
routerTurnByName(PageEnum.BASE_LOGIN_NAME)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -121,45 +121,38 @@
|
||||
import { reactive, ref, onMounted } from 'vue'
|
||||
import shuffle from 'lodash/shuffle'
|
||||
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 { GoLangSelect } from '@/components/GoLangSelect'
|
||||
import { LayoutHeader } from '@/layout/components/LayoutHeader'
|
||||
import { LayoutFooter } from '@/layout/components/LayoutFooter'
|
||||
import { PageEnum } from '@/enums/pageEnum'
|
||||
import { icon } from '@/plugins'
|
||||
import { StorageEnum } from '@/enums/storageEnum'
|
||||
import { routerTurnByName, cryptoEncode, setLocalStorage } from '@/utils'
|
||||
const { GO_LOGIN_INFO_STORE } = StorageEnum
|
||||
|
||||
const { PersonOutlineIcon, LockClosedOutlineIcon } = icon.ionicons5
|
||||
import { icon } from '@/plugins'
|
||||
import { routerTurnByName } from '@/utils'
|
||||
import { loginApi } from '@/api/path'
|
||||
|
||||
interface FormState {
|
||||
username: string
|
||||
password: string
|
||||
}
|
||||
|
||||
const { GO_SYSTEM_STORE } = StorageEnum
|
||||
const { PersonOutlineIcon, LockClosedOutlineIcon } = icon.ionicons5
|
||||
|
||||
const formRef = ref()
|
||||
const loading = ref(false)
|
||||
const autoLogin = ref(true)
|
||||
const show = ref(false)
|
||||
const showBg = ref(false)
|
||||
const designStore = useDesignStore()
|
||||
const systemStore = useSystemStore()
|
||||
|
||||
const t = window['$t']
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
show.value = true
|
||||
}, 300)
|
||||
setTimeout(() => {
|
||||
showBg.value = true
|
||||
}, 100)
|
||||
})
|
||||
|
||||
const formInline = reactive({
|
||||
username: 'admin',
|
||||
password: '123456',
|
||||
password: 'admin',
|
||||
})
|
||||
|
||||
const rules = {
|
||||
@@ -199,38 +192,58 @@ const getImageUrl = (name: string, folder: string) => {
|
||||
return new URL(`../../assets/images/${folder}/${name}.png`, import.meta.url).href
|
||||
}
|
||||
|
||||
// 打乱
|
||||
// 打乱图片顺序
|
||||
const shuffleHandle = () => {
|
||||
shuffleTimiing.value = setInterval(() => {
|
||||
bgList.value = shuffle(bgList.value)
|
||||
}, carouselInterval)
|
||||
}
|
||||
|
||||
// 点击事件
|
||||
const handleSubmit = (e: Event) => {
|
||||
// 登录
|
||||
const handleSubmit = async (e: Event) => {
|
||||
e.preventDefault()
|
||||
formRef.value.validate(async (errors: any) => {
|
||||
if (!errors) {
|
||||
const { username, password } = formInline
|
||||
loading.value = true
|
||||
setLocalStorage(
|
||||
GO_LOGIN_INFO_STORE,
|
||||
cryptoEncode(
|
||||
JSON.stringify({
|
||||
username,
|
||||
password,
|
||||
})
|
||||
)
|
||||
)
|
||||
window['$message'].success(`${t('login.login_success')}!`)
|
||||
routerTurnByName(PageEnum.BASE_HOME_NAME, true)
|
||||
// 提交请求
|
||||
const res = await loginApi({
|
||||
username,
|
||||
password
|
||||
})
|
||||
if(res && res.data) {
|
||||
const { tokenValue, tokenName } = res.data.token
|
||||
const { nickname, username, id } = res.data.userinfo
|
||||
|
||||
// 存储到 pinia
|
||||
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 {
|
||||
window['$message'].error(`${t('login.login_message')}!`)
|
||||
window['$message'].error(t('login.login_message'))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
show.value = true
|
||||
}, 300)
|
||||
|
||||
setTimeout(() => {
|
||||
showBg.value = true
|
||||
}, 100)
|
||||
|
||||
shuffleHandle()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -8,7 +8,7 @@ export const useComInstall = (localStorageInfo: ChartEditStorageType) => {
|
||||
|
||||
// 注册组件(一开始无法获取window['$vue'])
|
||||
const intervalTiming = setInterval(() => {
|
||||
if (window['$vue'].component) {
|
||||
if (window['$vue']?.component) {
|
||||
clearInterval(intervalTiming)
|
||||
|
||||
const intComponent = (target: CreateComponentType) => {
|
||||
|
||||
@@ -6,6 +6,7 @@ import { PreviewScaleEnum } from '@/enums/styleEnum'
|
||||
export const SCALE_KEY = 'scale-value'
|
||||
|
||||
export const useScale = (localStorageInfo: ChartEditStorageType) => {
|
||||
|
||||
const entityRef = ref()
|
||||
const previewRef = ref()
|
||||
const width = ref(localStorageInfo.editCanvasConfig.width)
|
||||
|
||||
3
src/views/preview/index.d.ts
vendored
3
src/views/preview/index.d.ts
vendored
@@ -1,5 +1,6 @@
|
||||
import { ChartEditStorage } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
|
||||
export interface ChartEditStorageType extends ChartEditStorage {
|
||||
id: string
|
||||
id: string,
|
||||
isRelease?: boolean
|
||||
}
|
||||
@@ -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 { ChartEditStorage } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
import { fetchProjectApi } from '@/api/path'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
|
||||
const chartEditStore = useChartEditStore()
|
||||
@@ -10,16 +12,31 @@ export interface ChartEditStorageType extends ChartEditStorage {
|
||||
}
|
||||
|
||||
// 根据路由 id 获取存储数据的信息
|
||||
export const getSessionStorageInfo = () => {
|
||||
const urlHash = document.location.hash
|
||||
const toPathArray = urlHash.split('/')
|
||||
const id = toPathArray && toPathArray[toPathArray.length - 1]
|
||||
export const getSessionStorageInfo = async () => {
|
||||
const id = fetchRouteParamsLocation()
|
||||
const storageList: ChartEditStorageType[] = getSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST)
|
||||
|
||||
const storageList: ChartEditStorageType[] = getSessionStorage(
|
||||
StorageEnum.GO_CHART_STORAGE_LIST
|
||||
)
|
||||
|
||||
if (storageList) {
|
||||
// 是否本地预览
|
||||
if (!storageList || storageList.findIndex(e => e.id === id.toString()) === -1) {
|
||||
// 接口调用
|
||||
const res = await fetchProjectApi({ projectId: id })
|
||||
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++) {
|
||||
if (id.toString() === storageList[i]['id']) {
|
||||
const { editCanvasConfig, requestGlobalConfig, componentList } = storageList[i]
|
||||
@@ -30,4 +47,4 @@ export const getSessionStorageInfo = () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,16 @@
|
||||
import { ProjectLayoutSider } from './layout/components/ProjectLayoutSider'
|
||||
import { LayoutHeaderPro } from '@/layout/components/LayoutHeaderPro'
|
||||
import { LayoutTransitionMain } from '@/layout/components/LayoutTransitionMain/index'
|
||||
import { goDialog } from '@/utils'
|
||||
|
||||
// 提示
|
||||
goDialog({
|
||||
message: '不要在官方后端上发布任何私密数据,任何人都看得到并进行删除!!!!',
|
||||
isMaskClosable: true,
|
||||
closeNegativeText: true,
|
||||
transformOrigin: 'center',
|
||||
onPositiveCallback: () => {}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<mac-os-control-btn
|
||||
class="top-btn"
|
||||
:hidden="['remove']"
|
||||
@close="deleteHanlde"
|
||||
@close="deleteHandle"
|
||||
@resize="resizeHandle"
|
||||
></mac-os-control-btn>
|
||||
</div>
|
||||
@@ -17,9 +17,7 @@
|
||||
object-fit="contain"
|
||||
height="180"
|
||||
preview-disabled
|
||||
:src="
|
||||
requireUrl('project/moke-20211219181327.png')
|
||||
"
|
||||
:src="`${cardData.image}?time=${new Date().getTime()}`"
|
||||
:alt="cardData.title"
|
||||
:fallback-src="requireErrorImg()"
|
||||
></n-image>
|
||||
@@ -27,8 +25,8 @@
|
||||
</div>
|
||||
<template #action>
|
||||
<div class="go-flex-items-center list-footer" justify="space-between">
|
||||
<n-text class="go-ellipsis-1" :title="cardData.title">
|
||||
{{ cardData.title || '' }}
|
||||
<n-text class="go-ellipsis-1">
|
||||
{{ cardData.title || cardData.id || '未命名' }}
|
||||
</n-text>
|
||||
<!-- 工具 -->
|
||||
<div class="go-flex-items-center list-footer-ri">
|
||||
@@ -75,8 +73,8 @@
|
||||
</n-tooltip>
|
||||
</template>
|
||||
</n-space>
|
||||
</div>
|
||||
<!-- end -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</n-card>
|
||||
@@ -101,17 +99,12 @@ const {
|
||||
SendIcon
|
||||
} = icon.ionicons5
|
||||
|
||||
const emit = defineEmits(['delete', 'resize', 'edit'])
|
||||
const emit = defineEmits(['preview', 'delete', 'resize', 'edit', 'release'])
|
||||
|
||||
const props = defineProps({
|
||||
cardData: Object as PropType<Chartype>
|
||||
})
|
||||
|
||||
// 处理url获取
|
||||
const requireUrl = (name: string) => {
|
||||
return new URL(`../../../../../assets/images/${name}`, import.meta.url).href
|
||||
}
|
||||
|
||||
const fnBtnList = reactive([
|
||||
{
|
||||
label: renderLang('global.r_edit'),
|
||||
@@ -135,7 +128,7 @@ const selectOptions = ref([
|
||||
label: props.cardData?.release
|
||||
? renderLang('global.r_unpublish')
|
||||
: renderLang('global.r_publish'),
|
||||
key: 'send',
|
||||
key: 'release',
|
||||
icon: renderIcon(SendIcon)
|
||||
},
|
||||
{
|
||||
@@ -147,8 +140,14 @@ const selectOptions = ref([
|
||||
|
||||
const handleSelect = (key: string) => {
|
||||
switch (key) {
|
||||
case 'preview':
|
||||
previewHandle()
|
||||
break
|
||||
case 'delete':
|
||||
deleteHanlde()
|
||||
deleteHandle()
|
||||
break
|
||||
case 'release':
|
||||
releaseHandle()
|
||||
break
|
||||
case 'edit':
|
||||
editHandle()
|
||||
@@ -156,8 +155,13 @@ const handleSelect = (key: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 预览处理
|
||||
const previewHandle = () => {
|
||||
emit('preview', props.cardData)
|
||||
}
|
||||
|
||||
// 删除处理
|
||||
const deleteHanlde = () => {
|
||||
const deleteHandle = () => {
|
||||
emit('delete', props.cardData)
|
||||
}
|
||||
|
||||
@@ -166,6 +170,11 @@ const editHandle = () => {
|
||||
emit('edit', props.cardData)
|
||||
}
|
||||
|
||||
// 编辑处理
|
||||
const releaseHandle = () => {
|
||||
emit('release', props.cardData)
|
||||
}
|
||||
|
||||
// 放大处理
|
||||
const resizeHandle = () => {
|
||||
emit('resize', props.cardData)
|
||||
|
||||
@@ -1,58 +1,124 @@
|
||||
import { ref } from 'vue'
|
||||
import { goDialog } from '@/utils'
|
||||
import { ref, reactive } from 'vue'
|
||||
import { goDialog, httpErrorHandle } from '@/utils'
|
||||
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 = () => {
|
||||
const list = ref<ChartList>([
|
||||
{
|
||||
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 loading = ref(true)
|
||||
|
||||
// 删除
|
||||
const deleteHandle = (cardData: object, index: number) => {
|
||||
const paginat = reactive({
|
||||
// 当前页数
|
||||
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({
|
||||
type: DialogEnum.DELETE,
|
||||
promise: true,
|
||||
onPositiveCallback: () =>
|
||||
new Promise(res => setTimeout(() => res(1), 1000)),
|
||||
promiseResCallback: (e: any) => {
|
||||
window.$message.success('删除成功')
|
||||
list.value.splice(index, 1)
|
||||
new Promise(res => {
|
||||
res(
|
||||
deleteProjectApi({
|
||||
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 {
|
||||
loading,
|
||||
paginat,
|
||||
list,
|
||||
fetchList,
|
||||
releaseHandle,
|
||||
changeSize,
|
||||
changePage,
|
||||
deleteHandle
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { ref } from 'vue'
|
||||
import { ChartEnum } from '@/enums/pageEnum'
|
||||
import { fetchPathByName, routerTurnByPath } from '@/utils'
|
||||
import { fetchPathByName, routerTurnByPath, openNewWindow, previewPath } from '@/utils'
|
||||
import { Chartype } from '../../../index.d'
|
||||
|
||||
export const useModalDataInit = () => {
|
||||
const modalShow = ref<boolean>(false)
|
||||
const modalData = ref<Chartype | null>(null)
|
||||
@@ -13,25 +12,31 @@ export const useModalDataInit = () => {
|
||||
modalData.value = null
|
||||
}
|
||||
|
||||
// 打开 modal
|
||||
// 缩放处理
|
||||
const resizeHandle = (cardData: Chartype) => {
|
||||
if(!cardData) return
|
||||
if (!cardData) return
|
||||
modalShow.value = true
|
||||
modalData.value = cardData
|
||||
}
|
||||
|
||||
// 打开 modal
|
||||
// 编辑处理
|
||||
const editHandle = (cardData: Chartype) => {
|
||||
if(!cardData) return
|
||||
if (!cardData) return
|
||||
const path = fetchPathByName(ChartEnum.CHART_HOME_NAME, 'href')
|
||||
routerTurnByPath(path, [cardData.id], undefined, true)
|
||||
}
|
||||
|
||||
// 预览处理
|
||||
const previewHandle = (cardData: Chartype) => {
|
||||
openNewWindow(previewPath(cardData.id))
|
||||
}
|
||||
|
||||
return {
|
||||
modalData,
|
||||
modalShow,
|
||||
closeModal,
|
||||
resizeHandle,
|
||||
editHandle
|
||||
editHandle,
|
||||
previewHandle
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,40 @@
|
||||
<template>
|
||||
<div class="go-items-list">
|
||||
<n-grid
|
||||
:x-gap="20"
|
||||
:y-gap="20"
|
||||
cols="2 s:2 m:3 l:4 xl:4 xxl:4"
|
||||
responsive="screen"
|
||||
>
|
||||
<n-grid-item v-for="(item, index) in list" :key="item.id">
|
||||
<project-items-card
|
||||
:cardData="item"
|
||||
@resize="resizeHandle"
|
||||
@delete="deleteHandle($event, index)"
|
||||
@edit="editHandle"
|
||||
></project-items-card>
|
||||
</n-grid-item>
|
||||
</n-grid>
|
||||
<!-- 加载 -->
|
||||
<div v-show="loading">
|
||||
<go-loading></go-loading>
|
||||
</div>
|
||||
<!-- 列表 -->
|
||||
<div v-show="!loading">
|
||||
<n-grid :x-gap="20" :y-gap="20" cols="2 s:2 m:3 l:4 xl:4 xxl:4" responsive="screen">
|
||||
<n-grid-item v-for="(item, index) in list" :key="item.id">
|
||||
<project-items-card
|
||||
:cardData="item"
|
||||
@preview="previewHandle"
|
||||
@resize="resizeHandle"
|
||||
@delete="deleteHandle(item)"
|
||||
@release="releaseHandle(item, index)"
|
||||
@edit="editHandle"
|
||||
></project-items-card>
|
||||
</n-grid-item>
|
||||
</n-grid>
|
||||
</div>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="list-pagination">
|
||||
<n-pagination
|
||||
:item-count="10"
|
||||
:page-sizes="[10, 20, 30, 40]"
|
||||
:page="paginat.page"
|
||||
:page-size="paginat.limit"
|
||||
:item-count="paginat.count"
|
||||
:page-sizes="[12, 24, 36, 48]"
|
||||
@update:page="changePage"
|
||||
@update:page-size="changeSize"
|
||||
show-size-picker
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- model -->
|
||||
<project-items-modal-card
|
||||
v-if="modalData"
|
||||
:modalShow="modalShow"
|
||||
@@ -40,8 +52,8 @@ import { useModalDataInit } from './hooks/useModal.hook'
|
||||
import { useDataListInit } from './hooks/useData.hook'
|
||||
|
||||
const { CopyIcon, EllipsisHorizontalCircleSharpIcon } = icon.ionicons5
|
||||
const { list, deleteHandle } = useDataListInit()
|
||||
const { modalData, modalShow, closeModal, resizeHandle, editHandle } = useModalDataInit()
|
||||
const { modalData, modalShow, closeModal, previewHandle, resizeHandle, editHandle } = useModalDataInit()
|
||||
const { loading, paginat, list, changeSize, changePage, releaseHandle, deleteHandle } = useDataListInit()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -50,7 +62,7 @@ $contentHeight: 250px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
min-height: calc(100vh - #{$--header-height} * 2 - 2px);
|
||||
min-height: calc(100vh - #{$--header-height} - 40px - 2px);
|
||||
.list-content {
|
||||
position: relative;
|
||||
height: $contentHeight;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<n-space class="list-content-top go-px-0" justify="center">
|
||||
<n-space>
|
||||
<n-text>
|
||||
{{ cardData?.title || '' }}
|
||||
{{ cardData?.title || cardData?.id || '未命名' }}
|
||||
</n-text>
|
||||
</n-space>
|
||||
</n-space>
|
||||
@@ -26,9 +26,7 @@
|
||||
<!-- 中间 -->
|
||||
<div class="list-content-img">
|
||||
<img
|
||||
:src="
|
||||
requireUrl('project/moke-20211219181327.png')
|
||||
"
|
||||
:src="cardData?.image"
|
||||
:alt="cardData?.title"
|
||||
/>
|
||||
</div>
|
||||
@@ -75,10 +73,11 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, watch } from 'vue'
|
||||
import { ref, reactive, PropType, watch } from 'vue'
|
||||
import { renderIcon, renderLang } from '@/utils'
|
||||
import { icon } from '@/plugins'
|
||||
import { MacOsControlBtn } from '@/components/Tips/MacOsControlBtn'
|
||||
import { Chartype } from '../../index.d'
|
||||
|
||||
const { HammerIcon } = icon.ionicons5
|
||||
const showRef = ref(false)
|
||||
@@ -140,12 +139,14 @@ const closeHandle = () => {
|
||||
<style lang="scss" scoped>
|
||||
$padding: 30px;
|
||||
$contentHeight: calc(80vh);
|
||||
$imageHeight: calc(80vh - 110px);
|
||||
$contentWidth: calc(82vw);
|
||||
|
||||
@include go('modal-box') {
|
||||
width: $contentWidth;
|
||||
height: $contentHeight;
|
||||
.list-content {
|
||||
margin-top: 28px;
|
||||
margin-top: 20px;
|
||||
border-radius: $--border-radius-base;
|
||||
overflow: hidden;
|
||||
@include background-image('background-point');
|
||||
@@ -160,8 +161,9 @@ $contentWidth: calc(82vw);
|
||||
}
|
||||
&-img {
|
||||
@extend .go-flex-center;
|
||||
padding: 6px 0;
|
||||
img {
|
||||
max-height: $contentHeight;
|
||||
height: $imageHeight;
|
||||
min-height: 200px;
|
||||
max-width: 100%;
|
||||
@extend .go-border-radius;
|
||||
|
||||
7
src/views/project/items/index.d.ts
vendored
7
src/views/project/items/index.d.ts
vendored
@@ -1,8 +1,11 @@
|
||||
export type Chartype = {
|
||||
id: number | string
|
||||
title: string // 标题
|
||||
label: string // 标签
|
||||
release: boolean // 0未发布 | 1已发布
|
||||
label?: string // 标签
|
||||
time: string, // 时间
|
||||
image: string, // 预览图地址
|
||||
createId: string, // 创建者
|
||||
release: boolean // false 未发布 | true 已发布
|
||||
}
|
||||
|
||||
export type ChartList = Chartype[]
|
||||
@@ -10,6 +10,6 @@ import { ProjectItemsList } from './components/ProjectItemsList'
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@include go(project-items) {
|
||||
padding: 30px 20px;
|
||||
padding: 20px 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
:disabled="item.disabled"
|
||||
v-for="item in typeList"
|
||||
:key="item.key"
|
||||
@click="btnHandle"
|
||||
@click="btnHandle(item.key)"
|
||||
>
|
||||
<component :is="item.title"></component>
|
||||
<template #icon>
|
||||
@@ -38,7 +38,9 @@
|
||||
import { ref, watch, shallowRef } from 'vue'
|
||||
import { icon } from '@/plugins'
|
||||
import { PageEnum, ChartEnum } from '@/enums/pageEnum'
|
||||
import { ResultEnum } from '@/enums/httpEnum'
|
||||
import { fetchPathByName, routerTurnByPath, renderLang, getUUID } from '@/utils'
|
||||
import { createProjectApi } from '@/api/path'
|
||||
|
||||
const { FishIcon, CloseIcon } = icon.ionicons5
|
||||
const { StoreIcon, ObjectStorageIcon } = icon.carbon
|
||||
@@ -70,8 +72,8 @@ const typeList = shallowRef([
|
||||
}
|
||||
])
|
||||
|
||||
watch(props, newValue => {
|
||||
showRef.value = newValue.show
|
||||
watch(() => props.show, newValue => {
|
||||
showRef.value = newValue
|
||||
})
|
||||
|
||||
// 关闭对话框
|
||||
@@ -80,11 +82,32 @@ const closeHandle = () => {
|
||||
}
|
||||
|
||||
// 处理按钮点击
|
||||
const btnHandle = (key: string) => {
|
||||
closeHandle()
|
||||
const id = getUUID()
|
||||
const path = fetchPathByName(ChartEnum.CHART_HOME_NAME, 'href')
|
||||
routerTurnByPath(path, [id], undefined, true)
|
||||
const btnHandle = async (key: string) => {
|
||||
switch (key) {
|
||||
case ChartEnum.CHART_HOME_NAME:
|
||||
try {
|
||||
// 新增项目
|
||||
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>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
35
src/views/redirect/UnPublish.vue
Normal file
35
src/views/redirect/UnPublish.vue
Normal 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>
|
||||
@@ -1,9 +1,11 @@
|
||||
<template>
|
||||
<n-empty description="你什么也找不到">
|
||||
<template #extra>
|
||||
<n-button size="small" @click="goHome">看看别的</n-button>
|
||||
</template>
|
||||
</n-empty>
|
||||
<div class="go-redirect">
|
||||
<n-empty description="你什么也找不到">
|
||||
<template #extra>
|
||||
<n-button size="small" @click="goHome">看看别的</n-button>
|
||||
</template>
|
||||
</n-empty>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onBeforeMount } from 'vue'
|
||||
@@ -14,3 +16,16 @@ const goHome = () => {
|
||||
router.replace({ path: '/' })
|
||||
}
|
||||
</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
2
types/vite-env.d.ts
vendored
@@ -1,8 +1,6 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
interface ImportMetaEnv {
|
||||
// 标题
|
||||
VITE_GLOB_APP_TITLE: string;
|
||||
// 端口
|
||||
VITE_DEV_PORT: string;
|
||||
// 开发地址
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import { defineConfig, loadEnv } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import { resolve } from 'path'
|
||||
import { OUTPUT_DIR, brotliSize, chunkSizeWarningLimit, terserOptions, rollupOptions } from './build/constant'
|
||||
import viteCompression from 'vite-plugin-compression'
|
||||
import { axiosPre } from './src/settings/httpSetting'
|
||||
import { viteMockServe } from 'vite-plugin-mock'
|
||||
import monacoEditorPlugin from 'vite-plugin-monaco-editor'
|
||||
|
||||
@@ -10,8 +11,8 @@ function pathResolve(dir: string) {
|
||||
return resolve(process.cwd(), '.', dir)
|
||||
}
|
||||
|
||||
export default defineConfig({
|
||||
base: '/',
|
||||
export default ({ mode }) => defineConfig({
|
||||
base: process.env.NODE_ENV === 'production' ? './' : '/',
|
||||
// 路径重定向
|
||||
resolve: {
|
||||
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,
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
vue({
|
||||
template: {
|
||||
|
||||
Reference in New Issue
Block a user