mirror of
https://gitee.com/dromara/go-view.git
synced 2026-02-22 00:00:02 +08:00
Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ac9ffc73c | ||
|
|
5ea963fb93 | ||
|
|
c420ae467f | ||
|
|
be014225c1 | ||
|
|
8334fe5bcc | ||
|
|
f99edce6f4 | ||
|
|
936d78975e | ||
|
|
a25f9bc5a1 | ||
|
|
5454f19f3d | ||
|
|
b95cf946a8 | ||
|
|
1b9a3f6f5b | ||
|
|
d91cd00310 | ||
|
|
e4f821f46d | ||
|
|
ed5a452e2f | ||
|
|
907a0afb77 | ||
|
|
b32c718780 | ||
|
|
adbdad1e88 | ||
|
|
f8229a0518 | ||
|
|
48f00e44f6 | ||
|
|
8c089b800a | ||
|
|
44199fa4c4 | ||
|
|
5e20689356 | ||
|
|
9a9b752a96 | ||
|
|
1ddf056ca6 | ||
|
|
572ab73c92 | ||
|
|
afc8f907ce | ||
|
|
f6bad1513b | ||
|
|
fce514c490 | ||
|
|
30a9deaee7 | ||
|
|
f47acca703 | ||
|
|
73a6c6b920 | ||
|
|
672f7a0a7c | ||
|
|
de78fb2149 | ||
|
|
4a59e69bbe | ||
|
|
a442e13a7b | ||
|
|
4d093a4a80 | ||
|
|
7e59d8d36c | ||
|
|
8241077495 | ||
|
|
82b29a2f8b | ||
|
|
b789d80f98 | ||
|
|
a8c80e2366 | ||
|
|
bdbdd37789 | ||
|
|
c8fb5b9152 | ||
|
|
aef155e039 | ||
|
|
443573455b | ||
|
|
d811ab7dfa | ||
|
|
5f79ab6e6d | ||
|
|
502edbca5d | ||
|
|
1a04267cb7 | ||
|
|
9c2c1bdfa1 | ||
|
|
72e93f3768 | ||
|
|
e6f2066d42 | ||
|
|
2812c39524 | ||
|
|
491485856e | ||
|
|
abde7e176d | ||
|
|
bab8faadee | ||
|
|
427d72fb8b | ||
|
|
dc5b20a329 | ||
|
|
4cb934eef3 | ||
|
|
35e8cea0b5 |
12
.env
12
.env
@@ -1,8 +1,14 @@
|
||||
# port
|
||||
VITE_DEV_PORT = '8080'
|
||||
VITE_DEV_PORT = '8001'
|
||||
|
||||
# development path
|
||||
VITE_DEV_PATH = 'https://demo.mtruning.club'
|
||||
VITE_DEV_PATH = '/'
|
||||
|
||||
# production path
|
||||
VITE_PRO_PATH = 'https://demo.mtruning.club'
|
||||
VITE_PRO_PATH = '/'
|
||||
|
||||
# spa-title
|
||||
VITE_GLOB_APP_TITLE = GoView
|
||||
|
||||
# spa shortname
|
||||
VITE_GLOB_APP_SHORT_NAME = GoView
|
||||
|
||||
51
.workflow/branch-pipeline.yml
Normal file
51
.workflow/branch-pipeline.yml
Normal file
@@ -0,0 +1,51 @@
|
||||
version: '1.0'
|
||||
name: branch-pipeline
|
||||
displayName: BranchPipeline
|
||||
stages:
|
||||
- stage:
|
||||
name: compile
|
||||
displayName: 编译
|
||||
steps:
|
||||
- step: build@nodejs
|
||||
name: build_nodejs
|
||||
displayName: Nodejs 构建
|
||||
# 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
|
||||
nodeVersion: 14.16.0
|
||||
# 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
|
||||
commands:
|
||||
- npm install && rm -rf ./dist && npm run build
|
||||
# 非必填字段,开启后表示将构建产物暂存,但不会上传到制品库中,7天后自动清除
|
||||
artifacts:
|
||||
# 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
|
||||
- name: BUILD_ARTIFACT
|
||||
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
|
||||
path:
|
||||
- ./dist
|
||||
- step: publish@general_artifacts
|
||||
name: publish_general_artifacts
|
||||
displayName: 上传制品
|
||||
# 上游构建任务定义的产物名,默认BUILD_ARTIFACT
|
||||
dependArtifact: BUILD_ARTIFACT
|
||||
# 上传到制品库时的制品命名,默认output
|
||||
artifactName: output
|
||||
dependsOn: build_nodejs
|
||||
- stage:
|
||||
name: release
|
||||
displayName: 发布
|
||||
steps:
|
||||
- step: publish@release_artifacts
|
||||
name: publish_release_artifacts
|
||||
displayName: '发布'
|
||||
# 上游上传制品任务的产出
|
||||
dependArtifact: output
|
||||
# 发布制品版本号
|
||||
version: '1.0.0.0'
|
||||
# 是否开启版本号自增,默认开启
|
||||
autoIncrement: true
|
||||
triggers:
|
||||
push:
|
||||
branches:
|
||||
exclude:
|
||||
- master
|
||||
include:
|
||||
- .*
|
||||
49
.workflow/master-pipeline.yml
Normal file
49
.workflow/master-pipeline.yml
Normal file
@@ -0,0 +1,49 @@
|
||||
version: '1.0'
|
||||
name: master-pipeline
|
||||
displayName: MasterPipeline
|
||||
stages:
|
||||
- stage:
|
||||
name: compile
|
||||
displayName: 编译
|
||||
steps:
|
||||
- step: build@nodejs
|
||||
name: build_nodejs
|
||||
displayName: Nodejs 构建
|
||||
# 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
|
||||
nodeVersion: 14.16.0
|
||||
# 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
|
||||
commands:
|
||||
- npm install && rm -rf ./dist && npm run build
|
||||
# 非必填字段,开启后表示将构建产物暂存,但不会上传到制品库中,7天后自动清除
|
||||
artifacts:
|
||||
# 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
|
||||
- name: BUILD_ARTIFACT
|
||||
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
|
||||
path:
|
||||
- ./dist
|
||||
- step: publish@general_artifacts
|
||||
name: publish_general_artifacts
|
||||
displayName: 上传制品
|
||||
# 上游构建任务定义的产物名,默认BUILD_ARTIFACT
|
||||
dependArtifact: BUILD_ARTIFACT
|
||||
# 上传到制品库时的制品命名,默认output
|
||||
artifactName: output
|
||||
dependsOn: build_nodejs
|
||||
- stage:
|
||||
name: release
|
||||
displayName: 发布
|
||||
steps:
|
||||
- step: publish@release_artifacts
|
||||
name: publish_release_artifacts
|
||||
displayName: '发布'
|
||||
# 上游上传制品任务的产出
|
||||
dependArtifact: output
|
||||
# 发布制品版本号
|
||||
version: '1.0.0.0'
|
||||
# 是否开启版本号自增,默认开启
|
||||
autoIncrement: true
|
||||
triggers:
|
||||
push:
|
||||
branches:
|
||||
include:
|
||||
- master
|
||||
36
.workflow/pr-pipeline.yml
Normal file
36
.workflow/pr-pipeline.yml
Normal file
@@ -0,0 +1,36 @@
|
||||
version: '1.0'
|
||||
name: pr-pipeline
|
||||
displayName: PRPipeline
|
||||
stages:
|
||||
- stage:
|
||||
name: compile
|
||||
displayName: 编译
|
||||
steps:
|
||||
- step: build@nodejs
|
||||
name: build_nodejs
|
||||
displayName: Nodejs 构建
|
||||
# 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
|
||||
nodeVersion: 14.16.0
|
||||
# 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
|
||||
commands:
|
||||
- npm install && rm -rf ./dist && npm run build
|
||||
# 非必填字段,开启后表示将构建产物暂存,但不会上传到制品库中,7天后自动清除
|
||||
artifacts:
|
||||
# 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
|
||||
- name: BUILD_ARTIFACT
|
||||
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
|
||||
path:
|
||||
- ./dist
|
||||
- step: publish@general_artifacts
|
||||
name: publish_general_artifacts
|
||||
displayName: 上传制品
|
||||
# 上游构建任务定义的产物名,默认BUILD_ARTIFACT
|
||||
dependArtifact: BUILD_ARTIFACT
|
||||
# 上传到制品库时的制品命名,默认output
|
||||
artifactName: output
|
||||
dependsOn: build_nodejs
|
||||
triggers:
|
||||
pr:
|
||||
branches:
|
||||
include:
|
||||
- master
|
||||
213
README.md
213
README.md
@@ -1,122 +1,165 @@
|
||||
## 总览
|
||||
|
||||

|
||||
<p align="center">
|
||||
<img src="readme/logo-t-y.png" alt="go-view" />
|
||||
</p>
|
||||
|
||||
**`master-fetch` 分支是带有后端接口请求的分支**
|
||||
<h4 align="center">开源、精美、便捷的「数据可视化」低代码开发平台</h4>
|
||||
|
||||
**后端项目地址:[https://gitee.com/MTrun/go-view-serve](https://gitee.com/MTrun/go-view-serve)**
|
||||
#### 😶 **纯前端** 分支: **`master`**
|
||||
|
||||
**接口说明地址:[https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb](https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb)**
|
||||
#### 👻 携带 **后端** 请求分支: **`master-fetch`**
|
||||
|
||||
## 使用
|
||||
#### 📚 GoView **文档** 地址:[https://www.mtruning.club/](https://www.mtruning.club/)
|
||||
|
||||
所有的接口地址位置:`src\api\path\*`
|
||||
项目纯前端-Demo 地址:[https://vue.mtruning.club/](https://vue.mtruning.club/)
|
||||
|
||||
接口地址修改:`.env`
|
||||
项目带后端-Demo 地址:[https://demo.mtruning.club/](https://demo.mtruning.club/)
|
||||
|
||||
### 🤯 后端项目
|
||||
文档-源码地址:[https://gitee.com/MTrun/go-view-doc](https://gitee.com/MTrun/go-view-doc)
|
||||
|
||||
后端项目gitee地址:[https://gitee.com/MTrun/go-view-serve](https://gitee.com/MTrun/go-view-serve)
|
||||
#### 🤯 后端项目看这里!
|
||||
|
||||
后端项目 gitee 地址:[https://gitee.com/MTrun/go-view-serve](https://gitee.com/MTrun/go-view-serve)
|
||||
|
||||
接口说明地址:[https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb](https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb)
|
||||
|
||||
```shell
|
||||
# port
|
||||
VITE_DEV_PORT = '8080'
|
||||
其它后端方案地址:
|
||||
|
||||
# development path
|
||||
VITE_DEV_PATH = 'http://127.0.0.1:8080'
|
||||
- 【.NET】[https://gitee.com/sun_xiang_yu/go-view-dotnet](https://gitee.com/sun_xiang_yu/go-view-dotnet)
|
||||
|
||||
# production path
|
||||
VITE_PRO_PATH = 'http://127.0.0.1:8080'
|
||||
```
|
||||
#### 整体介绍
|
||||
|
||||
公共前缀修改:`src\settings\httpSetting.ts`
|
||||
- 框架:基于 `Vue3` 框架编写,使用 `hooks` 写法抽离部分逻辑,使代码结构更加清晰;
|
||||
|
||||
- 类型:使用 `TypeScript` 进行类型约束,减少未知错误发生概率,可以大胆修改逻辑内容;
|
||||
|
||||
- 性能:多处性能优化,使用页面懒加载、组件动态注册、数据滚动加载等方式,提升页面渲染速度;
|
||||
|
||||
- 存储:拥有本地记忆,部分配置项采用 `storage` 存储本地,提升使用体验;
|
||||
|
||||
- 封装:项目进行了详细的工具类封装如:路由、存储、加/解密、文件处理、主题、NaiveUI 全局方法、组件等
|
||||
|
||||
说明文档:
|
||||

|
||||
|
||||
工作台:
|
||||

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

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

|
||||
|
||||
高级事件编辑:
|
||||

|
||||
|
||||
快捷主页:
|
||||

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

|
||||
|
||||
亮白主题:
|
||||

|
||||
|
||||
主要技术栈为:
|
||||
|
||||
| 名称 | 版本 | 名称 | 版本 |
|
||||
| ------------------- | ----- | ----------- | ------ |
|
||||
| Vue | 3.2.x | TypeScript4 | 4.6.x |
|
||||
| Vite | 2.9.x | NaiveUI | 2.27.x |
|
||||
| ECharts | 5.3.x | Pinia | 2.0.x |
|
||||
| 详见 `package.json` | 😁 | 🥰 | 🤗 |
|
||||
|
||||
开发环境:
|
||||
|
||||
| 名称 | 版本 | 名称 | 版本 |
|
||||
| ---- | ------- | ------- | ----- |
|
||||
| node | 16.14.x | npm | 8.5.x |
|
||||
| pnpm | 7.1.x | windows | 11 |
|
||||
|
||||
已完成图表:
|
||||
|
||||
| 分类 | 名称 | 名称 | 名称 | 名称 |
|
||||
| ------ | ---------------- | ---------- | -------------- | ------------------------ |
|
||||
| 图表 | 柱状图 | 横向柱状图 | 折线图 | 单/多 折线面积图(渐变色) |
|
||||
| \* | 饼图 | 环形图 | 水球图 | 雷达图 |
|
||||
| \* | NaiveUI 多种进度 | 散点图 | 对数回归散点图 | 热力图 |
|
||||
| \* | 漏斗图 | 中国地图 | 高德地图 | 🦊 |
|
||||
| 信息 | 文字 | 渐变文字 | 词云 | 嵌套网页 |
|
||||
| \* | 图片 | 视频 | 😺 | 🐯 |
|
||||
| 列表 | 滚动排名列表 | 滚动表格 | 🐮 | 🐐 |
|
||||
| 小组件 | 边框-01~13 | 装饰-01~05 | 数字翻牌 | 通用时间 |
|
||||
| \* | 数字计数 | 倒计时 | 时钟 | 🦁 |
|
||||
|
||||
## 浏览器支持
|
||||
|
||||
开发和测试平台均在 `Google` 和最新版 `EDGE` 上完成,暂未测试 `IE11` 等其它浏览器,如有需求请自行测试与兼容。
|
||||
|
||||
## 安装
|
||||
|
||||
本项目采用` pnpm` 进行包管理
|
||||
|
||||
```shell
|
||||
// 请求前缀
|
||||
export const axiosPre = '/api/goview'
|
||||
#建议使用 nrm 切换到淘宝源 https://registry.npmmirror.com/
|
||||
#pnpm
|
||||
pnpm install
|
||||
|
||||
#yarn
|
||||
yarn install
|
||||
|
||||
#npm
|
||||
npm install
|
||||
```
|
||||
|
||||
接口封装:`src\api\http.ts`
|
||||
## 启动
|
||||
|
||||
```ts
|
||||
import axiosInstance from './axios'
|
||||
import { RequestHttpEnum, ContentTypeEnum } from '@/enums/httpEnum'
|
||||
```shell
|
||||
#pnpm
|
||||
pnpm dev
|
||||
|
||||
export const get = (url: string, params?: object) => {
|
||||
return axiosInstance({
|
||||
url: url,
|
||||
method: RequestHttpEnum.GET,
|
||||
params: params,
|
||||
})
|
||||
}
|
||||
# npm
|
||||
npm run dev
|
||||
|
||||
export const post = (url: string, data?: object, headersType?: string) => {
|
||||
return axiosInstance({
|
||||
url: url,
|
||||
method: RequestHttpEnum.POST,
|
||||
data: data,
|
||||
headers: {
|
||||
'Content-Type': headersType || ContentTypeEnum.JSON
|
||||
}
|
||||
})
|
||||
}
|
||||
#yarn
|
||||
yarn dev
|
||||
|
||||
export const put = (url: string, data?: object, headersType?: string) => {
|
||||
return axiosInstance({
|
||||
url: url,
|
||||
method: RequestHttpEnum.PUT,
|
||||
data: data,
|
||||
headers: {
|
||||
'Content-Type': headersType || ContentTypeEnum.JSON
|
||||
}
|
||||
})
|
||||
}
|
||||
#Makefile
|
||||
make dev
|
||||
```
|
||||
|
||||
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
|
||||
```shell
|
||||
#pnpm
|
||||
pnpm run build
|
||||
|
||||
case RequestHttpEnum.POST:
|
||||
return post
|
||||
# npm
|
||||
npm run build
|
||||
|
||||
case RequestHttpEnum.PUT:
|
||||
return put
|
||||
#yarn
|
||||
yarn run build
|
||||
|
||||
case RequestHttpEnum.DELETE:
|
||||
return del
|
||||
|
||||
default:
|
||||
return get
|
||||
}
|
||||
}
|
||||
#Makefile
|
||||
make dist
|
||||
|
||||
```
|
||||
|
||||
## 代码提交
|
||||
|
||||
* 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: 不属于以上类型的其他类型(日常事务)
|
||||
|
||||
## 交流
|
||||
|
||||
|
||||
9
build/getConfigFileName.ts
Normal file
9
build/getConfigFileName.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* 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,6 +1,6 @@
|
||||
{
|
||||
"name": "go-view",
|
||||
"version": "2.1.1",
|
||||
"version": "1.1.5",
|
||||
"scripts": {
|
||||
"dev": "vite --host",
|
||||
"build": "vue-tsc --noEmit && vite build",
|
||||
@@ -35,7 +35,7 @@
|
||||
"three": "^0.145.0",
|
||||
"vue": "^3.2.31",
|
||||
"vue-demi": "^0.13.1",
|
||||
"vue-i18n": "9.1.10",
|
||||
"vue-i18n": "9.1.9",
|
||||
"vue-router": "4.0.12",
|
||||
"vue3-lazyload": "^0.2.5-beta",
|
||||
"vue3-sketch-ruler": "^1.3.3",
|
||||
|
||||
72
pnpm-lock.yaml
generated
72
pnpm-lock.yaml
generated
@@ -59,7 +59,7 @@ specifiers:
|
||||
vue: ^3.2.31
|
||||
vue-demi: ^0.13.1
|
||||
vue-echarts: ^6.0.2
|
||||
vue-i18n: 9.1.10
|
||||
vue-i18n: 9.1.9
|
||||
vue-router: 4.0.12
|
||||
vue-tsc: ^0.28.10
|
||||
vue3-lazyload: ^0.2.5-beta
|
||||
@@ -91,7 +91,7 @@ dependencies:
|
||||
three: 0.145.0
|
||||
vue: 3.2.37
|
||||
vue-demi: 0.13.1_vue@3.2.37
|
||||
vue-i18n: 9.1.10_vue@3.2.37
|
||||
vue-i18n: 9.1.9_vue@3.2.37
|
||||
vue-router: 4.0.12_vue@3.2.37
|
||||
vue3-lazyload: 0.2.5-beta_2yymnzrok6eda47acnj2yjm3ae
|
||||
vue3-sketch-ruler: 1.3.4_vue@3.2.37
|
||||
@@ -671,60 +671,60 @@ packages:
|
||||
resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==}
|
||||
dev: true
|
||||
|
||||
/@intlify/core-base/9.1.10:
|
||||
resolution: {integrity: sha512-So9CNUavB/IsZ+zBmk2Cv6McQp6vc2wbGi1S0XQmJ8Vz+UFcNn9MFXAe9gY67PreIHrbLsLxDD0cwo1qsxM1Nw==}
|
||||
/@intlify/core-base/9.1.9:
|
||||
resolution: {integrity: sha512-x5T0p/Ja0S8hs5xs+ImKyYckVkL4CzcEXykVYYV6rcbXxJTe2o58IquSqX9bdncVKbRZP7GlBU1EcRaQEEJ+vw==}
|
||||
engines: {node: '>= 10'}
|
||||
dependencies:
|
||||
'@intlify/devtools-if': 9.1.10
|
||||
'@intlify/message-compiler': 9.1.10
|
||||
'@intlify/message-resolver': 9.1.10
|
||||
'@intlify/runtime': 9.1.10
|
||||
'@intlify/shared': 9.1.10
|
||||
'@intlify/vue-devtools': 9.1.10
|
||||
'@intlify/devtools-if': 9.1.9
|
||||
'@intlify/message-compiler': 9.1.9
|
||||
'@intlify/message-resolver': 9.1.9
|
||||
'@intlify/runtime': 9.1.9
|
||||
'@intlify/shared': 9.1.9
|
||||
'@intlify/vue-devtools': 9.1.9
|
||||
dev: false
|
||||
|
||||
/@intlify/devtools-if/9.1.10:
|
||||
resolution: {integrity: sha512-SHaKoYu6sog3+Q8js1y3oXLywuogbH1sKuc7NSYkN3GElvXSBaMoCzW+we0ZSFqj/6c7vTNLg9nQ6rxhKqYwnQ==}
|
||||
/@intlify/devtools-if/9.1.9:
|
||||
resolution: {integrity: sha512-oKSMKjttG3Ut/1UGEZjSdghuP3fwA15zpDPcjkf/1FjlOIm6uIBGMNS5jXzsZy593u+P/YcnrZD6cD3IVFz9vQ==}
|
||||
engines: {node: '>= 10'}
|
||||
dependencies:
|
||||
'@intlify/shared': 9.1.10
|
||||
'@intlify/shared': 9.1.9
|
||||
dev: false
|
||||
|
||||
/@intlify/message-compiler/9.1.10:
|
||||
resolution: {integrity: sha512-+JiJpXff/XTb0EadYwdxOyRTB0hXNd4n1HaJ/a4yuV960uRmPXaklJsedW0LNdcptd/hYUZtCkI7Lc9J5C1gxg==}
|
||||
/@intlify/message-compiler/9.1.9:
|
||||
resolution: {integrity: sha512-6YgCMF46Xd0IH2hMRLCssZI3gFG4aywidoWQ3QP4RGYQXQYYfFC54DxhSgfIPpVoPLQ+4AD29eoYmhiHZ+qLFQ==}
|
||||
engines: {node: '>= 10'}
|
||||
dependencies:
|
||||
'@intlify/message-resolver': 9.1.10
|
||||
'@intlify/shared': 9.1.10
|
||||
'@intlify/message-resolver': 9.1.9
|
||||
'@intlify/shared': 9.1.9
|
||||
source-map: 0.6.1
|
||||
dev: false
|
||||
|
||||
/@intlify/message-resolver/9.1.10:
|
||||
resolution: {integrity: sha512-5YixMG/M05m0cn9+gOzd4EZQTFRUu8RGhzxJbR1DWN21x/Z3bJ8QpDYj6hC4FwBj5uKsRfKpJQ3Xqg98KWoA+w==}
|
||||
/@intlify/message-resolver/9.1.9:
|
||||
resolution: {integrity: sha512-Lx/DBpigeK0sz2BBbzv5mu9/dAlt98HxwbG7xLawC3O2xMF9MNWU5FtOziwYG6TDIjNq0O/3ZbOJAxwITIWXEA==}
|
||||
engines: {node: '>= 10'}
|
||||
dev: false
|
||||
|
||||
/@intlify/runtime/9.1.10:
|
||||
resolution: {integrity: sha512-7QsuByNzpe3Gfmhwq6hzgXcMPpxz8Zxb/XFI6s9lQdPLPe5Lgw4U1ovRPZTOs6Y2hwitR3j/HD8BJNGWpJnOFA==}
|
||||
/@intlify/runtime/9.1.9:
|
||||
resolution: {integrity: sha512-XgPw8+UlHCiie3fI41HPVa/VDJb3/aSH7bLhY1hJvlvNV713PFtb4p4Jo+rlE0gAoMsMCGcsiT982fImolSltg==}
|
||||
engines: {node: '>= 10'}
|
||||
dependencies:
|
||||
'@intlify/message-compiler': 9.1.10
|
||||
'@intlify/message-resolver': 9.1.10
|
||||
'@intlify/shared': 9.1.10
|
||||
'@intlify/message-compiler': 9.1.9
|
||||
'@intlify/message-resolver': 9.1.9
|
||||
'@intlify/shared': 9.1.9
|
||||
dev: false
|
||||
|
||||
/@intlify/shared/9.1.10:
|
||||
resolution: {integrity: sha512-Om54xJeo1Vw+K1+wHYyXngE8cAbrxZHpWjYzMR9wCkqbhGtRV5VLhVc214Ze2YatPrWlS2WSMOWXR8JktX/IgA==}
|
||||
/@intlify/shared/9.1.9:
|
||||
resolution: {integrity: sha512-xKGM1d0EAxdDFCWedcYXOm6V5Pfw/TMudd6/qCdEb4tv0hk9EKeg7lwQF1azE0dP2phvx0yXxrt7UQK+IZjNdw==}
|
||||
engines: {node: '>= 10'}
|
||||
dev: false
|
||||
|
||||
/@intlify/vue-devtools/9.1.10:
|
||||
resolution: {integrity: sha512-5l3qYARVbkWAkagLu1XbDUWRJSL8br1Dj60wgMaKB0+HswVsrR6LloYZTg7ozyvM621V6+zsmwzbQxbVQyrytQ==}
|
||||
/@intlify/vue-devtools/9.1.9:
|
||||
resolution: {integrity: sha512-YPehH9uL4vZcGXky4Ev5qQIITnHKIvsD2GKGXgqf+05osMUI6WSEQHaN9USRa318Rs8RyyPCiDfmA0hRu3k7og==}
|
||||
engines: {node: '>= 10'}
|
||||
dependencies:
|
||||
'@intlify/message-resolver': 9.1.10
|
||||
'@intlify/runtime': 9.1.10
|
||||
'@intlify/shared': 9.1.10
|
||||
'@intlify/message-resolver': 9.1.9
|
||||
'@intlify/runtime': 9.1.9
|
||||
'@intlify/shared': 9.1.9
|
||||
dev: false
|
||||
|
||||
/@jridgewell/gen-mapping/0.1.1:
|
||||
@@ -5385,15 +5385,15 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/vue-i18n/9.1.10_vue@3.2.37:
|
||||
resolution: {integrity: sha512-jpr7gV5KPk4n+sSPdpZT8Qx3XzTcNDWffRlHV/cT2NUyEf+sEgTTmLvnBAibjOFJ0zsUyZlVTAWH5DDnYep+1g==}
|
||||
/vue-i18n/9.1.9_vue@3.2.37:
|
||||
resolution: {integrity: sha512-JeRdNVxS2OGp1E+pye5XB6+M6BBkHwAv9C80Q7+kzoMdUDGRna06tjC0vCB/jDX9aWrl5swxOMFcyAr7or8XTA==}
|
||||
engines: {node: '>= 10'}
|
||||
peerDependencies:
|
||||
vue: ^3.0.0
|
||||
dependencies:
|
||||
'@intlify/core-base': 9.1.10
|
||||
'@intlify/shared': 9.1.10
|
||||
'@intlify/vue-devtools': 9.1.10
|
||||
'@intlify/core-base': 9.1.9
|
||||
'@intlify/shared': 9.1.9
|
||||
'@intlify/vue-devtools': 9.1.9
|
||||
'@vue/devtools-api': 6.1.4
|
||||
vue: 3.2.37
|
||||
dev: false
|
||||
|
||||
BIN
readme/go-view-doc.png
Normal file
BIN
readme/go-view-doc.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 159 KiB |
BIN
readme/go-view-indexpage.png
Normal file
BIN
readme/go-view-indexpage.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 167 KiB |
BIN
readme/go-view-theme.png
Normal file
BIN
readme/go-view-theme.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 404 KiB |
@@ -17,7 +17,7 @@
|
||||
import { NConfigProvider } from 'naive-ui'
|
||||
import { GoAppProvider } from '@/components/GoAppProvider'
|
||||
import { I18n } from '@/components/I18n'
|
||||
import { useSystemInit, useDarkThemeHook, useThemeOverridesHook, useCode, useLang } from '@/hooks'
|
||||
import { useDarkThemeHook, useThemeOverridesHook, useCode, useLang } from '@/hooks'
|
||||
|
||||
// 暗黑主题
|
||||
const darkTheme = useDarkThemeHook()
|
||||
@@ -28,9 +28,6 @@ const overridesTheme = useThemeOverridesHook()
|
||||
// 代码主题
|
||||
const hljsTheme = useCode()
|
||||
|
||||
// 系统全局数据初始化
|
||||
useSystemInit()
|
||||
|
||||
// 全局语言
|
||||
const { locale, dateLocale } = useLang()
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import { ModuleTypeEnum } from '@/enums/httpEnum'
|
||||
|
||||
// 接口白名单(免登录)
|
||||
export const fetchAllowList = [
|
||||
// 登录
|
||||
`${ModuleTypeEnum.SYSTEM}/login`,
|
||||
// 获取 OSS 接口
|
||||
`${ModuleTypeEnum.SYSTEM}/getOssInfo`,
|
||||
// 预览获取数据
|
||||
`${ModuleTypeEnum.PROJECT}/getData`,
|
||||
]
|
||||
|
||||
// 接口黑名单
|
||||
export const fetchBlockList = []
|
||||
@@ -1,38 +1,19 @@
|
||||
import axios, { AxiosResponse, AxiosRequestConfig } from 'axios'
|
||||
import { ResultEnum } 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, httpErrorHandle } from '@/utils'
|
||||
import { fetchAllowList } from './axios.config'
|
||||
import includes from 'lodash/includes'
|
||||
import { ErrorPageNameMap } from "@/enums/pageEnum"
|
||||
import { redirectErrorPage } from '@/utils'
|
||||
|
||||
const axiosInstance = axios.create({
|
||||
baseURL: `${import.meta.env.PROD ? import.meta.env.VITE_PRO_PATH : ''}${axiosPre}`,
|
||||
baseURL: import.meta.env.DEV ? import.meta.env.VITE_DEV_PATH : import.meta.env.VITE_PRO_PATH,
|
||||
timeout: ResultEnum.TIMEOUT,
|
||||
})
|
||||
|
||||
axiosInstance.interceptors.request.use(
|
||||
(config: AxiosRequestConfig) => {
|
||||
// 白名单校验
|
||||
if (includes(fetchAllowList, config.url)) return config
|
||||
// 获取 token
|
||||
const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
|
||||
// 重新登录
|
||||
if (!info) {
|
||||
routerTurnByName(PageEnum.BASE_LOGIN_NAME)
|
||||
return config
|
||||
}
|
||||
const userInfo = info[SystemStoreEnum.USER_INFO]
|
||||
config.headers = {
|
||||
...config.headers,
|
||||
[userInfo[SystemStoreUserInfoEnum.TOKEN_NAME] || 'token']: userInfo[SystemStoreUserInfoEnum.USER_TOKEN] || ''
|
||||
}
|
||||
return config
|
||||
},
|
||||
(err: AxiosRequestConfig) => {
|
||||
Promise.reject(err)
|
||||
(error: AxiosRequestConfig) => {
|
||||
Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -40,27 +21,9 @@ axiosInstance.interceptors.request.use(
|
||||
axiosInstance.interceptors.response.use(
|
||||
(res: AxiosResponse) => {
|
||||
const { code } = res.data as { code: number }
|
||||
|
||||
// 成功
|
||||
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))
|
||||
if (code === ResultEnum.DATA_SUCCESS) return Promise.resolve(res.data)
|
||||
// 重定向
|
||||
if (ErrorPageNameMap.get(code)) redirectErrorPage(code)
|
||||
return Promise.resolve(res.data)
|
||||
},
|
||||
(err: AxiosResponse) => {
|
||||
|
||||
@@ -13,7 +13,7 @@ export const get = (url: string, params?: object) => {
|
||||
return axiosInstance({
|
||||
url: url,
|
||||
method: RequestHttpEnum.GET,
|
||||
params: params,
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from '@/api/path/project.api'
|
||||
export * from '@/api/path/system.api'
|
||||
@@ -1,84 +0,0 @@
|
||||
import { http } from '@/api/http'
|
||||
import { httpErrorHandle } from '@/utils'
|
||||
import { ContentTypeEnum, RequestHttpEnum, ModuleTypeEnum } from '@/enums/httpEnum'
|
||||
|
||||
// * 项目列表
|
||||
export const projectListApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.GET)(`${ModuleTypeEnum.PROJECT}/list`, data);
|
||||
return res;
|
||||
} catch {
|
||||
httpErrorHandle();
|
||||
}
|
||||
}
|
||||
|
||||
// * 新增项目
|
||||
export const createProjectApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.PROJECT}/create`, data);
|
||||
return res;
|
||||
} catch {
|
||||
httpErrorHandle();
|
||||
}
|
||||
}
|
||||
|
||||
// * 获取项目
|
||||
export const fetchProjectApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.GET)(`${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)(`${ModuleTypeEnum.PROJECT}/upload`, data, ContentTypeEnum.FORM_DATA);
|
||||
return res;
|
||||
} catch {
|
||||
httpErrorHandle();
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import { http } from '@/api/http'
|
||||
import { httpErrorHandle } from '@/utils'
|
||||
import { RequestHttpEnum, ModuleTypeEnum } from '@/enums/httpEnum'
|
||||
|
||||
// * 登录
|
||||
export const loginApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.POST)(`${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)(`${ModuleTypeEnum.SYSTEM}/getOssInfo`, data);
|
||||
return res;
|
||||
} catch(err) {
|
||||
httpErrorHandle();
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,7 @@ export enum MenuEnum {
|
||||
UN_GROUP = 'unGroup',
|
||||
// 后退
|
||||
BACK = 'back',
|
||||
// 前进
|
||||
FORWORD = 'forward',
|
||||
// 保存
|
||||
SAVE = 'save',
|
||||
@@ -79,15 +80,3 @@ export enum MacKeyboard {
|
||||
SHIFT_SOURCE_KEY = '⇧',
|
||||
ALT_SOURCE_KEY = '⌥'
|
||||
}
|
||||
|
||||
// 同步状态枚举
|
||||
export enum SyncEnum {
|
||||
// 等待
|
||||
PENDING,
|
||||
// 开始
|
||||
START,
|
||||
// 成功
|
||||
SUCCESS,
|
||||
// 失败
|
||||
FAILURE
|
||||
}
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
// 模块 Path 前缀分类
|
||||
export enum ModuleTypeEnum {
|
||||
SYSTEM = 'sys',
|
||||
PROJECT = 'project',
|
||||
}
|
||||
|
||||
// 请求结果集
|
||||
/**
|
||||
* @description: 请求结果集
|
||||
*/
|
||||
export enum ResultEnum {
|
||||
DATA_SUCCESS = 0,
|
||||
SUCCESS = 200,
|
||||
SERVER_ERROR = 500,
|
||||
SERVER_FORBIDDEN = 403,
|
||||
NOT_FOUND = 404,
|
||||
TOKEN_OVERDUE = 886,
|
||||
TIMEOUT = 60000,
|
||||
TIMEOUT = 60000
|
||||
}
|
||||
|
||||
// 数据相关
|
||||
@@ -31,13 +26,9 @@ export enum RequestContentTypeEnum {
|
||||
SQL = 1
|
||||
}
|
||||
|
||||
// 头部
|
||||
export enum RequestHttpHeaderEnum {
|
||||
TOKEN = 'Token',
|
||||
COOKIE = 'Cookie'
|
||||
}
|
||||
|
||||
// 请求方法
|
||||
/**
|
||||
* @description: 请求方法
|
||||
*/
|
||||
export enum RequestHttpEnum {
|
||||
GET = 'get',
|
||||
POST = 'post',
|
||||
@@ -118,7 +109,9 @@ export type RequestParams = {
|
||||
}
|
||||
}
|
||||
|
||||
// 常用的contentTyp类型
|
||||
/**
|
||||
* @description: 常用的contentTyp类型
|
||||
*/
|
||||
export enum ContentTypeEnum {
|
||||
// json
|
||||
JSON = 'application/json;charset=UTF-8',
|
||||
|
||||
@@ -26,15 +26,10 @@ 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,8 +1,10 @@
|
||||
export enum StorageEnum {
|
||||
// 全局设置
|
||||
GO_SETTING_STORE = 'GO_SETTING',
|
||||
GO_SYSTEM_SETTING_STORE = 'GO_SYSTEM_SETTING',
|
||||
// token 等信息
|
||||
GO_ACCESS_TOKEN_STORE = 'GO_ACCESS_TOKEN',
|
||||
// 登录信息
|
||||
GO_SYSTEM_STORE = 'GO_SYSTEM',
|
||||
GO_LOGIN_INFO_STORE = 'GO_LOGIN_INFO',
|
||||
// 语言
|
||||
GO_LANG_STORE = 'GO_LANG',
|
||||
// 当前选择的主题
|
||||
|
||||
@@ -2,6 +2,6 @@ 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'
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ref, toRefs, toRaw } from 'vue'
|
||||
import type VChart from 'vue-echarts'
|
||||
import { customizeHttp } from '@/api/http'
|
||||
import { useChartDataPondFetch } from '@/hooks/'
|
||||
import { CreateComponentType, ChartFrameEnum } from '@/packages/index.d'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { RequestDataTypeEnum } from '@/enums/httpEnum'
|
||||
@@ -23,6 +24,22 @@ export const useChartDataFetch = (
|
||||
const vChartRef = ref<typeof VChart | null>(null)
|
||||
let fetchInterval: any = 0
|
||||
|
||||
// 数据池
|
||||
const { addGlobalDataInterface } = useChartDataPondFetch()
|
||||
const { requestDataPondId } = toRefs(targetComponent.request)
|
||||
|
||||
// 组件类型
|
||||
const { chartFrame } = targetComponent.chartConfig
|
||||
|
||||
// eCharts 组件配合 vChart 库更新方式
|
||||
const echartsUpdateHandle = (dataset: any) => {
|
||||
if (chartFrame === ChartFrameEnum.ECHARTS) {
|
||||
if (vChartRef.value) {
|
||||
vChartRef.value.setOption({ dataset: dataset })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const requestIntervalFn = () => {
|
||||
const chartEditStore = useChartEditStore()
|
||||
|
||||
@@ -41,9 +58,6 @@ export const useChartDataFetch = (
|
||||
requestInterval: targetInterval
|
||||
} = toRefs(targetComponent.request)
|
||||
|
||||
// 组件类型
|
||||
const { chartFrame } = targetComponent.chartConfig
|
||||
|
||||
// 非请求类型
|
||||
if (requestDataType.value !== RequestDataTypeEnum.AJAX) return
|
||||
|
||||
@@ -58,16 +72,11 @@ export const useChartDataFetch = (
|
||||
clearInterval(fetchInterval)
|
||||
|
||||
const fetchFn = async () => {
|
||||
const res = await customizeHttp(toRaw(targetComponent.request), toRaw(chartEditStore.requestGlobalConfig))
|
||||
const res = await customizeHttp(toRaw(targetComponent.request), toRaw(chartEditStore.getRequestGlobalConfig))
|
||||
if (res) {
|
||||
try {
|
||||
const filter = targetComponent.filter
|
||||
// eCharts 组件配合 vChart 库更新方式
|
||||
if (chartFrame === ChartFrameEnum.ECHARTS) {
|
||||
if (vChartRef.value) {
|
||||
vChartRef.value.setOption({ dataset: newFunctionHandle(res?.data, res, filter) })
|
||||
}
|
||||
}
|
||||
echartsUpdateHandle(newFunctionHandle(res?.data, res, filter))
|
||||
// 更新回调函数
|
||||
if (updateCallback) {
|
||||
updateCallback(newFunctionHandle(res?.data, res, filter))
|
||||
@@ -94,6 +103,11 @@ export const useChartDataFetch = (
|
||||
}
|
||||
}
|
||||
|
||||
isPreview() && requestIntervalFn()
|
||||
if (isPreview()) {
|
||||
// 判断是否有数据池对应 id
|
||||
requestDataPondId
|
||||
? addGlobalDataInterface(targetComponent, useChartEditStore, updateCallback || echartsUpdateHandle)
|
||||
: requestIntervalFn()
|
||||
}
|
||||
return { vChartRef }
|
||||
}
|
||||
|
||||
93
src/hooks/useChartDataPondFetch.hook.ts
Normal file
93
src/hooks/useChartDataPondFetch.hook.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import { toRaw } from 'vue'
|
||||
import { customizeHttp } from '@/api/http'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { RequestGlobalConfigType, RequestDataPondItemType } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
import { newFunctionHandle } from '@/utils'
|
||||
|
||||
// 获取类型
|
||||
type ChartEditStoreType = typeof useChartEditStore
|
||||
|
||||
// 数据池存储的数据类型
|
||||
type DataPondMapType = {
|
||||
updateCallback: (...args: any) => any
|
||||
filter?: string | undefined
|
||||
}
|
||||
|
||||
// 数据池 Map 中请求对应 callback
|
||||
const mittDataPondMap = new Map<string, DataPondMapType[]>()
|
||||
|
||||
// 创建单个数据项轮询接口
|
||||
const newPondItemInterval = (
|
||||
requestGlobalConfig: RequestGlobalConfigType,
|
||||
requestDataPondItem: RequestDataPondItemType,
|
||||
dataPondMapItem?: DataPondMapType[]
|
||||
) => {
|
||||
if (!dataPondMapItem) return
|
||||
|
||||
// 请求
|
||||
const fetchFn = async () => {
|
||||
try {
|
||||
const res = await customizeHttp(toRaw(requestDataPondItem.dataPondRequestConfig), toRaw(requestGlobalConfig))
|
||||
|
||||
if (res) {
|
||||
try {
|
||||
// 遍历更新回调函数
|
||||
dataPondMapItem.forEach(item => {
|
||||
item.updateCallback(newFunctionHandle(res?.data, res, item.filter))
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return error
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return error
|
||||
}
|
||||
}
|
||||
|
||||
// 立即调用
|
||||
fetchFn()
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据池接口处理
|
||||
*/
|
||||
export const useChartDataPondFetch = () => {
|
||||
// 新增全局接口
|
||||
const addGlobalDataInterface = (
|
||||
targetComponent: CreateComponentType,
|
||||
useChartEditStore: ChartEditStoreType,
|
||||
updateCallback: (...args: any) => any
|
||||
) => {
|
||||
const chartEditStore = useChartEditStore()
|
||||
const { requestDataPond } = chartEditStore.getRequestGlobalConfig
|
||||
|
||||
// 组件对应的数据池 Id
|
||||
const requestDataPondId = '111' || (targetComponent.request.requestDataPondId as string)
|
||||
// 新增数据项
|
||||
const mittPondIdArr = mittDataPondMap.get(requestDataPondId) || []
|
||||
mittPondIdArr.push({
|
||||
updateCallback: updateCallback,
|
||||
filter: targetComponent.filter
|
||||
})
|
||||
mittDataPondMap.set(requestDataPondId, mittPondIdArr)
|
||||
}
|
||||
|
||||
// 初始化数据池
|
||||
const initDataPond = (requestGlobalConfig: RequestGlobalConfigType) => {
|
||||
const { requestDataPond } = requestGlobalConfig
|
||||
// 根据 mapId 查找对应的数据池配置
|
||||
for (let pondKey of mittDataPondMap.keys()) {
|
||||
const requestDataPondItem = requestDataPond.find(item => item.dataPondId === pondKey)
|
||||
if (requestDataPondItem) {
|
||||
newPondItemInterval(requestGlobalConfig, requestDataPondItem, mittDataPondMap.get(pondKey))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
addGlobalDataInterface,
|
||||
initDataPond
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CreateComponentType, EventLife } from '@/packages/index.d'
|
||||
import { CreateComponentType, CreateComponentGroupType, EventLife, BaseEvent } from '@/packages/index.d'
|
||||
import * as echarts from 'echarts'
|
||||
|
||||
// 所有图表组件集合对象
|
||||
@@ -7,26 +7,57 @@ const components: { [K in string]?: any } = {}
|
||||
// 项目提供的npm 包变量
|
||||
export const npmPkgs = { echarts }
|
||||
|
||||
export const useLifeHandler = (chartConfig: CreateComponentType) => {
|
||||
const events = chartConfig.events || {}
|
||||
// 组件事件处理 hook
|
||||
export const useLifeHandler = (chartConfig: CreateComponentType | CreateComponentGroupType) => {
|
||||
if (!chartConfig.events) return {}
|
||||
|
||||
// 处理基础事件
|
||||
const baseEvent: { [key: string]: any } = {}
|
||||
for (const key in chartConfig.events.baseEvent) {
|
||||
const fnStr: string | undefined = (chartConfig.events.baseEvent as any)[key]
|
||||
// 动态绑定基础事件
|
||||
if (fnStr) {
|
||||
baseEvent[key] = generateBaseFunc(fnStr)
|
||||
}
|
||||
}
|
||||
|
||||
// 生成生命周期事件
|
||||
const events = chartConfig.events.advancedEvents || {}
|
||||
const lifeEvents = {
|
||||
[EventLife.BEFORE_MOUNT](e: any) {
|
||||
[EventLife.VNODE_BEFORE_MOUNT](e: any) {
|
||||
// 存储组件
|
||||
components[chartConfig.id] = e.component
|
||||
const fnStr = (events[EventLife.BEFORE_MOUNT] || '').trim()
|
||||
const fnStr = (events[EventLife.VNODE_BEFORE_MOUNT] || '').trim()
|
||||
generateFunc(fnStr, e)
|
||||
},
|
||||
[EventLife.MOUNTED](e: any) {
|
||||
const fnStr = (events[EventLife.MOUNTED] || '').trim()
|
||||
[EventLife.VNODE_MOUNTED](e: any) {
|
||||
const fnStr = (events[EventLife.VNODE_MOUNTED] || '').trim()
|
||||
generateFunc(fnStr, e)
|
||||
}
|
||||
}
|
||||
return lifeEvents
|
||||
return { ...baseEvent, ...lifeEvents }
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 生成基础函数
|
||||
* @param fnStr 用户方法体代码
|
||||
* @param event 鼠标事件
|
||||
*/
|
||||
export function generateBaseFunc(fnStr: string) {
|
||||
try {
|
||||
return new Function(`
|
||||
return (
|
||||
async function(mouseEvent){
|
||||
${fnStr}
|
||||
}
|
||||
)`)()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成高级函数
|
||||
* @param fnStr 用户方法体代码
|
||||
* @param e 执行生命周期的动态组件实例
|
||||
*/
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
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({}) as unknown as MyResponseType
|
||||
if (res.code === ResultEnum.SUCCESS) {
|
||||
systemStore.setItem(SystemStoreEnum.FETCH_INFO, {
|
||||
OSSUrl: res.data?.bucketURL
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 执行
|
||||
getOssUrl()
|
||||
}
|
||||
@@ -11,8 +11,6 @@ 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',
|
||||
@@ -28,14 +26,8 @@ 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,8 +1,6 @@
|
||||
export default {
|
||||
create_btn: 'Creat',
|
||||
create_success: 'Creat Success!',
|
||||
create_failure: 'Failed to create, please try again later!',
|
||||
create_tip: 'Please select a content for development!',
|
||||
create_tip: 'Please select a content for development',
|
||||
project: 'Project',
|
||||
my: 'My',
|
||||
new_project: 'New Project',
|
||||
|
||||
@@ -11,8 +11,6 @@ const global = {
|
||||
help: '帮助中心',
|
||||
contact: '关于软件',
|
||||
logout: '退出登录',
|
||||
logout_success: '退出成功!',
|
||||
logout_failure: '退出失败!',
|
||||
// 系统设置
|
||||
sys_set: '系统设置',
|
||||
lang_set: '语言设置',
|
||||
@@ -20,27 +18,16 @@ 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,8 +1,6 @@
|
||||
export default {
|
||||
// aside
|
||||
create_btn: '新建',
|
||||
create_success: '新建成功!',
|
||||
create_failure: '新建失败,请稍后重试!',
|
||||
create_tip: '从哪里出发好呢?',
|
||||
project: '项目',
|
||||
my: '我的',
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div
|
||||
v-if="state.mergedConfig"
|
||||
class="go-dv-capsule-chart"
|
||||
:style="{
|
||||
:style="{
|
||||
fontSize: numberSizeHandle(state.mergedConfig.valueFontSize),
|
||||
paddingLeft: numberSizeHandle(state.mergedConfig.paddingLeft),
|
||||
paddingRight: numberSizeHandle(state.mergedConfig.paddingRight)
|
||||
@@ -53,11 +53,10 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, watch, reactive, PropType } from 'vue'
|
||||
import merge from 'lodash/merge'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import { useChartDataFetch } from '@/hooks'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import config, { option } from './config'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
|
||||
type DataProps = {
|
||||
name: string | number
|
||||
@@ -114,12 +113,11 @@ watch(
|
||||
|
||||
const calcData = (data: any) => {
|
||||
mergeConfig(props.chartConfig.option)
|
||||
|
||||
calcCapsuleLengthAndLabelData()
|
||||
}
|
||||
|
||||
const mergeConfig = (data: any) => {
|
||||
state.mergedConfig = merge(cloneDeep(state.defaultConfig), data || {})
|
||||
state.mergedConfig = cloneDeep(data || {})
|
||||
}
|
||||
|
||||
// 数据解析
|
||||
|
||||
@@ -2,6 +2,7 @@ import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
|
||||
import { LineCommonConfig } from './index'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import { defaultTheme, chartColorsSearch } from '@/settings/chartThemes/index'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import dataJson from './data.json'
|
||||
|
||||
export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
|
||||
@@ -47,7 +48,7 @@ export const option = {
|
||||
|
||||
export default class Config extends PublicConfigClass implements CreateComponentType {
|
||||
public key: string = LineCommonConfig.key
|
||||
public chartConfig = LineCommonConfig
|
||||
public chartConfig = cloneDeep(LineCommonConfig)
|
||||
// 图表配置项
|
||||
public option = echartOptionProfixHandle(option, includes)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { LineGradientSingleConfig } from './index'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import { graphic } from 'echarts/core'
|
||||
import { defaultTheme, chartColorsSearch } from '@/settings/chartThemes/index'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import dataJson from './data.json'
|
||||
|
||||
export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
|
||||
@@ -58,7 +59,7 @@ const options = {
|
||||
|
||||
export default class Config extends PublicConfigClass implements CreateComponentType {
|
||||
public key: string = LineGradientSingleConfig.key
|
||||
public chartConfig = LineGradientSingleConfig
|
||||
public chartConfig = cloneDeep(LineGradientSingleConfig)
|
||||
// 图表配置项
|
||||
public option = echartOptionProfixHandle(options, includes)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { LineGradientsConfig } from './index'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import { graphic } from 'echarts/core'
|
||||
import { defaultTheme, chartColorsSearch } from '@/settings/chartThemes/index'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import dataJson from './data.json'
|
||||
|
||||
export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
|
||||
@@ -85,7 +86,7 @@ const option = {
|
||||
|
||||
export default class Config extends PublicConfigClass implements CreateComponentType {
|
||||
public key: string = LineGradientsConfig.key
|
||||
public chartConfig = LineGradientsConfig
|
||||
public chartConfig = cloneDeep(LineGradientsConfig)
|
||||
// 图表配置项
|
||||
public option = echartOptionProfixHandle(option, includes)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
|
||||
import { LineLinearSingleConfig } from './index'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import { defaultTheme, chartColorsSearch } from '@/settings/chartThemes/index'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import dataJson from './data.json'
|
||||
|
||||
export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
|
||||
@@ -54,7 +55,7 @@ export const option = {
|
||||
|
||||
export default class Config extends PublicConfigClass implements CreateComponentType {
|
||||
public key: string = LineLinearSingleConfig.key
|
||||
public chartConfig = LineLinearSingleConfig
|
||||
public chartConfig = cloneDeep(LineLinearSingleConfig)
|
||||
// 图表配置项
|
||||
public option = echartOptionProfixHandle(option, includes)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
|
||||
import { MapBaseConfig } from './index'
|
||||
import { chartInitConfig } from '@/settings/designSetting'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import dataJson from './data.json'
|
||||
|
||||
export const includes = []
|
||||
@@ -151,6 +152,6 @@ export const MapDefaultConfig = { ...option }
|
||||
export default class Config extends PublicConfigClass implements CreateComponentType {
|
||||
public key: string = MapBaseConfig.key
|
||||
public attr = { ...chartInitConfig, w: 750, h: 800, zIndex: -1 }
|
||||
public chartConfig = MapBaseConfig
|
||||
public chartConfig = cloneDeep(MapBaseConfig)
|
||||
public option = echartOptionProfixHandle(option, includes)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
|
||||
import { PieCircleConfig } from './index'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
|
||||
export const includes = []
|
||||
|
||||
@@ -57,7 +58,7 @@ const option = {
|
||||
export default class Config extends PublicConfigClass implements CreateComponentType {
|
||||
public key: string = PieCircleConfig.key
|
||||
|
||||
public chartConfig = PieCircleConfig
|
||||
public chartConfig = cloneDeep(PieCircleConfig)
|
||||
|
||||
// 图表配置项
|
||||
public option = echartOptionProfixHandle(option, includes)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
|
||||
import { PieCommonConfig } from './index'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import dataJson from './data.json'
|
||||
|
||||
export const includes = ['legend']
|
||||
@@ -61,7 +62,7 @@ const option = {
|
||||
export default class Config extends PublicConfigClass implements CreateComponentType {
|
||||
public key: string = PieCommonConfig.key
|
||||
|
||||
public chartConfig = PieCommonConfig
|
||||
public chartConfig = cloneDeep(PieCommonConfig)
|
||||
|
||||
// 图表配置项
|
||||
public option = echartOptionProfixHandle(option, includes)
|
||||
|
||||
@@ -62,7 +62,7 @@ const status = reactive({
|
||||
const calcRowsData = () => {
|
||||
let { dataset, rowNum, sort } = status.mergedConfig
|
||||
// @ts-ignore
|
||||
sort && dataset.sort(({ value: a }, { value: b }) => {
|
||||
sort &&dataset.sort(({ value: a }, { value: b } ) => {
|
||||
if (a > b) return -1
|
||||
if (a < b) return 1
|
||||
if (a === b) return 0
|
||||
@@ -94,6 +94,7 @@ const calcHeights = (onresize = false) => {
|
||||
const { rowNum, dataset } = status.mergedConfig
|
||||
const avgHeight = h.value / rowNum
|
||||
status.avgHeight = avgHeight
|
||||
|
||||
if (!onresize) status.heights = new Array(dataset.length).fill(avgHeight)
|
||||
}
|
||||
|
||||
@@ -131,12 +132,17 @@ const stopAnimation = () => {
|
||||
const onRestart = async () => {
|
||||
try {
|
||||
if (!status.mergedConfig) return
|
||||
let { dataset, rowNum, sort } = status.mergedConfig
|
||||
stopAnimation()
|
||||
calcRowsData()
|
||||
calcHeights(true)
|
||||
animation(true)
|
||||
let flag = true
|
||||
if (dataset.length <= rowNum) {
|
||||
flag=false
|
||||
}
|
||||
calcHeights(flag)
|
||||
animation(flag)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
27
src/packages/index.d.ts
vendored
27
src/packages/index.d.ts
vendored
@@ -90,12 +90,24 @@ export const BlendModeEnumList = [
|
||||
{ label: '亮度', value: 'luminosity' }
|
||||
]
|
||||
|
||||
// 基础事件类型(vue不加 on)
|
||||
export enum BaseEvent {
|
||||
// 点击
|
||||
ON_CLICK = 'click',
|
||||
// 双击
|
||||
ON_DBL_CLICK = 'dblclick',
|
||||
// 移入
|
||||
ON_MOUSE_ENTER = 'mouseenter',
|
||||
// 移出
|
||||
ON_MOUSE_LEAVE = 'mouseleave',
|
||||
}
|
||||
|
||||
// vue3 生命周期事件
|
||||
export enum EventLife {
|
||||
export enum EventLife {
|
||||
// 渲染之后
|
||||
MOUNTED = 'vnodeMounted',
|
||||
VNODE_MOUNTED = 'vnodeMounted',
|
||||
// 渲染之前
|
||||
BEFORE_MOUNT = 'vnodeBeforeMount',
|
||||
VNODE_BEFORE_MOUNT = 'vnodeBeforeMount',
|
||||
}
|
||||
|
||||
// 组件实例类
|
||||
@@ -123,8 +135,13 @@ export interface PublicConfigType {
|
||||
}
|
||||
filter?: string
|
||||
status: StatusType
|
||||
events?: {
|
||||
[K in EventLife]?: string
|
||||
events: {
|
||||
baseEvent: {
|
||||
[K in BaseEvent]?: string
|
||||
},
|
||||
advancedEvents: {
|
||||
[K in EventLife]?: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { getUUID } from '@/utils'
|
||||
import { ChartFrameEnum, PublicConfigType, CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
|
||||
import { RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
import { groupTitle } from '@/settings/designSetting'
|
||||
import {
|
||||
@@ -9,6 +8,14 @@ import {
|
||||
RequestContentTypeEnum,
|
||||
RequestBodyEnum
|
||||
} from '@/enums/httpEnum'
|
||||
import {
|
||||
BaseEvent,
|
||||
EventLife,
|
||||
ChartFrameEnum,
|
||||
PublicConfigType,
|
||||
CreateComponentType,
|
||||
CreateComponentGroupType
|
||||
} from '@/packages/index.d'
|
||||
import { chartInitConfig } from '@/settings/designSetting'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
|
||||
@@ -82,7 +89,18 @@ export class PublicConfigClass implements PublicConfigType {
|
||||
// 数据过滤
|
||||
public filter = undefined
|
||||
// 事件
|
||||
public events = undefined
|
||||
public events = {
|
||||
baseEvent: {
|
||||
[BaseEvent.ON_CLICK]: undefined,
|
||||
[BaseEvent.ON_DBL_CLICK]: undefined,
|
||||
[BaseEvent.ON_MOUSE_ENTER]: undefined,
|
||||
[BaseEvent.ON_MOUSE_LEAVE]: undefined
|
||||
},
|
||||
advancedEvents: {
|
||||
[EventLife.VNODE_MOUNTED]: undefined,
|
||||
[EventLife.VNODE_BEFORE_MOUNT]: undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 多选成组类
|
||||
|
||||
@@ -8,10 +8,7 @@ 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)
|
||||
}
|
||||
|
||||
@@ -54,7 +54,6 @@ import {
|
||||
ArrowForward as ArrowForwardIcon,
|
||||
Planet as PawIcon,
|
||||
Search as SearchIcon,
|
||||
Reload as ReloadIcon,
|
||||
ChevronUpOutline as ChevronUpOutlineIcon,
|
||||
ChevronDownOutline as ChevronDownOutlineIcon,
|
||||
Pulse as PulseIcon,
|
||||
@@ -64,7 +63,8 @@ import {
|
||||
Images as ImagesIcon,
|
||||
List as ListIcon,
|
||||
EyeOutline as EyeOutlineIcon,
|
||||
EyeOffOutline as EyeOffOutlineIcon
|
||||
EyeOffOutline as EyeOffOutlineIcon,
|
||||
Albums as AlbumsIcon
|
||||
} from '@vicons/ionicons5'
|
||||
|
||||
import {
|
||||
@@ -93,11 +93,11 @@ import {
|
||||
FitToScreen as FitToScreenIcon,
|
||||
FitToHeight as FitToHeightIcon,
|
||||
FitToWidth as FitToWidthIcon,
|
||||
Save as SaveIcon,
|
||||
Carbon3DCursor as Carbon3DCursorIcon,
|
||||
Carbon3DSoftware as Carbon3DSoftwareIcon,
|
||||
Filter as FilterIcon,
|
||||
FilterEdit as FilterEditIcon
|
||||
FilterEdit as FilterEditIcon,
|
||||
Laptop as LaptopIcon
|
||||
} from '@vicons/carbon'
|
||||
|
||||
const ionicons5 = {
|
||||
@@ -210,8 +210,6 @@ const ionicons5 = {
|
||||
PawIcon,
|
||||
// 搜索(放大镜)
|
||||
SearchIcon,
|
||||
// 加载
|
||||
ReloadIcon,
|
||||
// 过滤器
|
||||
FilterIcon,
|
||||
// 向上
|
||||
@@ -232,7 +230,9 @@ const ionicons5 = {
|
||||
ListIcon,
|
||||
// 眼睛
|
||||
EyeOutlineIcon,
|
||||
EyeOffOutlineIcon
|
||||
EyeOffOutlineIcon,
|
||||
// 图表列表
|
||||
AlbumsIcon
|
||||
}
|
||||
|
||||
const carbon = {
|
||||
@@ -277,15 +277,15 @@ const carbon = {
|
||||
FitToScreenIcon,
|
||||
FitToHeightIcon,
|
||||
FitToWidthIcon,
|
||||
// 保存
|
||||
SaveIcon,
|
||||
// 成组
|
||||
Carbon3DCursorIcon,
|
||||
// 解组
|
||||
Carbon3DSoftwareIcon,
|
||||
// 过滤器
|
||||
FilterIcon,
|
||||
FilterEditIcon
|
||||
FilterEditIcon,
|
||||
// 图层
|
||||
LaptopIcon
|
||||
}
|
||||
|
||||
// https://www.xicons.org/#/ 还有很多
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { RouteRecordRaw } from 'vue-router'
|
||||
import type { AppRouteRecordRaw } from '@/router/types';
|
||||
import { ErrorPage404, ErrorPage403, ErrorPage500, Layout, RedirectHome, RedirectUnPublish } from '@/router/constant';
|
||||
import { ErrorPage404, ErrorPage403, ErrorPage500, Layout } from '@/router/constant';
|
||||
import { PageEnum } from '@/enums/pageEnum'
|
||||
import { GoReload } from '@/components/GoReload'
|
||||
|
||||
|
||||
export const LoginRoute: RouteRecordRaw = {
|
||||
path: PageEnum.BASE_LOGIN,
|
||||
name: PageEnum.BASE_LOGIN_NAME,
|
||||
path: '/login',
|
||||
name: 'Login',
|
||||
component: () => import('@/views/login/index.vue'),
|
||||
meta: {
|
||||
title: '登录',
|
||||
@@ -60,21 +60,22 @@ export const ReloadRoute: AppRouteRecordRaw = {
|
||||
},
|
||||
}
|
||||
|
||||
export const RedirectRoute: RouteRecordRaw[] = [
|
||||
{
|
||||
path: PageEnum.REDIRECT,
|
||||
name: PageEnum.REDIRECT_NAME,
|
||||
component: RedirectHome,
|
||||
meta: {
|
||||
title: PageEnum.REDIRECT_NAME,
|
||||
},
|
||||
export const RedirectRoute: AppRouteRecordRaw = {
|
||||
path: PageEnum.REDIRECT,
|
||||
name: PageEnum.REDIRECT_NAME,
|
||||
component: Layout,
|
||||
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,
|
||||
children: [
|
||||
{
|
||||
path: '/redirect/:path(.*)',
|
||||
name: PageEnum.REDIRECT_NAME,
|
||||
component: () => import('@/views/redirect/index.vue'),
|
||||
meta: {
|
||||
title: PageEnum.REDIRECT_NAME,
|
||||
hideBreadcrumb: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
],
|
||||
};
|
||||
|
||||
@@ -4,10 +4,6 @@ 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,8 +1,9 @@
|
||||
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, RedirectRoute } from '@/router/base'
|
||||
import { HttpErrorPage, LoginRoute, ReloadRoute } from '@/router/base'
|
||||
import { Layout } from '@/router/constant'
|
||||
|
||||
import modules from '@/router/modules'
|
||||
@@ -18,7 +19,6 @@ 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, ReloadRoute];
|
||||
export const constantRouter: any[] = [LoginRoute, ...RootRoute, RedirectRoute, ReloadRoute];
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(''),
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
import { Router } from 'vue-router';
|
||||
import { PageEnum, PreviewEnum } from '@/enums/pageEnum'
|
||||
import { PageEnum } 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) => {
|
||||
@@ -20,8 +12,10 @@ export function createRouterGuards(router: Router) {
|
||||
next({ name: PageEnum.ERROR_PAGE_NAME_404 })
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
if (!routerAllowList.includes(to.name) && !loginCheck()) {
|
||||
if (!loginCheck()) {
|
||||
if (to.name === PageEnum.BASE_LOGIN_NAME) {
|
||||
next()
|
||||
}
|
||||
next({ name: PageEnum.BASE_LOGIN_NAME })
|
||||
}
|
||||
next()
|
||||
|
||||
@@ -61,9 +61,6 @@ export const editToJsonInterval = 5000
|
||||
// 数据请求间隔
|
||||
export const requestInterval = 30
|
||||
|
||||
// 工作台自动保存间隔(s)
|
||||
export const saveInterval = 30
|
||||
|
||||
// 数据请求间隔单位
|
||||
export const requestIntervalUnit = RequestHttpIntervalEnum.SECOND
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
// 请求前缀
|
||||
export const axiosPre = '/api/goview'
|
||||
@@ -1,6 +1,5 @@
|
||||
import { CreateComponentType, CreateComponentGroupType, FilterEnum } from '@/packages/index.d'
|
||||
import { HistoryActionTypeEnum } from '@/store/modules/chartHistoryStore/chartHistoryStore.d'
|
||||
import { SyncEnum } from '@/enums/editPageEnum'
|
||||
import {
|
||||
RequestHttpEnum,
|
||||
RequestContentTypeEnum,
|
||||
@@ -13,29 +12,6 @@ import {
|
||||
import { PreviewScaleEnum } from '@/enums/styleEnum'
|
||||
import type { ChartColorsNameType, GlobalThemeJsonType } from '@/settings/chartThemes/index'
|
||||
|
||||
// 项目数据枚举
|
||||
export enum ProjectInfoEnum {
|
||||
// ID
|
||||
PROJECT_ID = "projectId",
|
||||
// 名称
|
||||
PROJECT_NAME = 'projectName',
|
||||
// 描述
|
||||
REMARKS = 'remarks',
|
||||
// 缩略图
|
||||
THUMBNAIL= 'thumbnail',
|
||||
// 是否公开发布
|
||||
RELEASE = 'release'
|
||||
}
|
||||
|
||||
// 项目数据
|
||||
export type ProjectInfoType = {
|
||||
[ProjectInfoEnum.PROJECT_ID]: string,
|
||||
[ProjectInfoEnum.PROJECT_NAME]: string,
|
||||
[ProjectInfoEnum.REMARKS]: string,
|
||||
[ProjectInfoEnum.THUMBNAIL]: string,
|
||||
[ProjectInfoEnum.RELEASE]: boolean
|
||||
}
|
||||
|
||||
// 编辑画布属性
|
||||
export enum EditCanvasTypeEnum {
|
||||
EDIT_LAYOUT_DOM = 'editLayoutDom',
|
||||
@@ -44,13 +20,12 @@ export enum EditCanvasTypeEnum {
|
||||
SCALE = 'scale',
|
||||
USER_SCALE = 'userScale',
|
||||
LOCK_SCALE = 'lockScale',
|
||||
SAVE_STATUS = 'saveStatus',
|
||||
IS_CREATE = 'isCreate',
|
||||
IS_DRAG = 'isDrag',
|
||||
IS_SELECT = 'isSelect'
|
||||
}
|
||||
|
||||
// 编辑区域(临时)
|
||||
// 编辑区域
|
||||
export type EditCanvasType = {
|
||||
// 编辑区域 DOM
|
||||
[EditCanvasTypeEnum.EDIT_LAYOUT_DOM]: HTMLElement | null
|
||||
@@ -67,13 +42,11 @@ export type EditCanvasType = {
|
||||
[EditCanvasTypeEnum.IS_CREATE]: boolean
|
||||
// 拖拽中
|
||||
[EditCanvasTypeEnum.IS_DRAG]: boolean
|
||||
// 保存状态
|
||||
[EditCanvasTypeEnum.SAVE_STATUS]: SyncEnum
|
||||
// 框选中
|
||||
[EditCanvasTypeEnum.IS_SELECT]: boolean
|
||||
}
|
||||
|
||||
// 画布数据/滤镜/背景色/宽高主题等
|
||||
// 滤镜/背景色/宽高主题等
|
||||
export enum EditCanvasConfigEnum {
|
||||
WIDTH = 'width',
|
||||
HEIGHT = 'height',
|
||||
@@ -85,14 +58,7 @@ export enum EditCanvasConfigEnum {
|
||||
PREVIEW_SCALE_TYPE = 'previewScaleType'
|
||||
}
|
||||
|
||||
// 画布属性(需保存)
|
||||
export type EditCanvasConfigType = {
|
||||
// ID
|
||||
[EditCanvasConfigEnum.PROJECT_ID]: string,
|
||||
// 项目名称
|
||||
[EditCanvasConfigEnum.PROJECT_NAME]: string,
|
||||
// 项目描述
|
||||
[EditCanvasConfigEnum.REMARKS]: string,
|
||||
export interface EditCanvasConfigType {
|
||||
// 滤镜-启用
|
||||
[FilterEnum.FILTERS_SHOW]: boolean
|
||||
// 滤镜-色相
|
||||
@@ -164,7 +130,6 @@ export type RecordChartType = {
|
||||
|
||||
// Store 枚举
|
||||
export enum ChartEditStoreEnum {
|
||||
PROJECT_INFO = 'projectInfo',
|
||||
EDIT_RANGE = 'editRange',
|
||||
EDIT_CANVAS = 'editCanvas',
|
||||
RIGHT_MENU_SHOW = 'rightMenuShow',
|
||||
@@ -185,16 +150,27 @@ type RequestPublicConfigType = {
|
||||
requestParams: RequestParams
|
||||
}
|
||||
|
||||
// 数据池项类型
|
||||
export type RequestDataPondItemType = {
|
||||
dataPondId: string,
|
||||
dataPondName: string,
|
||||
dataPondRequestConfig: RequestConfigType
|
||||
}
|
||||
|
||||
// 全局的图表请求配置
|
||||
export interface RequestGlobalConfigType extends RequestPublicConfigType {
|
||||
// 组件定制轮询时间
|
||||
requestInterval: number
|
||||
// 请求源地址
|
||||
requestOriginUrl?: string
|
||||
// 公共数据池
|
||||
requestDataPond: RequestDataPondItemType[]
|
||||
}
|
||||
|
||||
// 单个图表请求配置
|
||||
export interface RequestConfigType extends RequestPublicConfigType {
|
||||
// 所选全局数据池的对应 id
|
||||
requestDataPondId?: string
|
||||
// 组件定制轮询时间
|
||||
requestInterval?: number
|
||||
// 获取数据的方式
|
||||
@@ -215,7 +191,6 @@ 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,22 +10,14 @@ 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 {
|
||||
getUUID,
|
||||
loadingStart,
|
||||
loadingFinish,
|
||||
loadingError,
|
||||
isString,
|
||||
isArray
|
||||
} from '@/utils'
|
||||
|
||||
HistoryActionTypeEnum,
|
||||
HistoryItemType,
|
||||
HistoryTargetTypeEnum
|
||||
} from '@/store/modules/chartHistoryStore/chartHistoryStore.d'
|
||||
import { MenuEnum } from '@/enums/editPageEnum'
|
||||
import { getUUID, loadingStart, loadingFinish, loadingError, isString, isArray } from '@/utils'
|
||||
import {
|
||||
ProjectInfoType,
|
||||
ChartEditStoreEnum,
|
||||
ChartEditStorage,
|
||||
ChartEditStoreType,
|
||||
@@ -44,14 +36,6 @@ const settingStore = useSettingStore()
|
||||
export const useChartEditStore = defineStore({
|
||||
id: 'useChartEditStore',
|
||||
state: (): ChartEditStoreType => ({
|
||||
// 项目数据
|
||||
projectInfo: {
|
||||
projectId: '',
|
||||
projectName: '',
|
||||
remarks: '',
|
||||
thumbnail: '',
|
||||
release: false
|
||||
},
|
||||
// 画布属性
|
||||
editCanvas: {
|
||||
// 编辑区域 Dom
|
||||
@@ -70,9 +54,7 @@ export const useChartEditStore = defineStore({
|
||||
// 拖拽中
|
||||
isDrag: false,
|
||||
// 框选中
|
||||
isSelect: false,
|
||||
// 同步中
|
||||
saveStatus: SyncEnum.PENDING
|
||||
isSelect: false
|
||||
},
|
||||
// 右键菜单
|
||||
rightMenuShow: false,
|
||||
@@ -126,11 +108,12 @@ export const useChartEditStore = defineStore({
|
||||
chartThemeColor: defaultTheme || 'dark',
|
||||
// 全局配置
|
||||
chartThemeSetting: globalThemeJson,
|
||||
// 预览方式
|
||||
// 适配方式
|
||||
previewScaleType: previewScaleType
|
||||
},
|
||||
// 数据请求处理(需存储给后端)
|
||||
requestGlobalConfig: {
|
||||
requestDataPond: [],
|
||||
requestOriginUrl: '',
|
||||
requestInterval: requestInterval,
|
||||
requestIntervalUnit: requestIntervalUnit,
|
||||
@@ -149,9 +132,6 @@ export const useChartEditStore = defineStore({
|
||||
componentList: []
|
||||
}),
|
||||
getters: {
|
||||
getProjectInfo(): ProjectInfoType {
|
||||
return this.projectInfo
|
||||
},
|
||||
getMousePosition(): MousePositionType {
|
||||
return this.mousePosition
|
||||
},
|
||||
@@ -186,10 +166,6 @@ export const useChartEditStore = defineStore({
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
// * 设置 peojectInfo 数据项
|
||||
setProjectInfo<T extends keyof ProjectInfoType, K extends ProjectInfoType[T]>(key: T, value: K) {
|
||||
this.projectInfo[key] = value
|
||||
},
|
||||
// * 设置 editCanvas 数据项
|
||||
setEditCanvas<T extends keyof EditCanvasType, K extends EditCanvasType[T]>(key: T, value: K) {
|
||||
this.editCanvas[key] = value
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
export enum ChartModeEnum {
|
||||
SINGLE= 'single',
|
||||
DOUBLE = 'double'
|
||||
}
|
||||
|
||||
export enum LayerModeEnum {
|
||||
THUMBNAIL = 'thumbnail',
|
||||
TEXT = 'text'
|
||||
@@ -7,6 +12,7 @@ export enum ChartLayoutStoreEnum {
|
||||
LAYERS = 'layers',
|
||||
CHARTS = 'charts',
|
||||
DETAILS = 'details',
|
||||
Chart_TYPE = 'chartType',
|
||||
LAYER_TYPE = 'layerType'
|
||||
}
|
||||
|
||||
@@ -17,6 +23,8 @@ export interface ChartLayoutType {
|
||||
[ChartLayoutStoreEnum.CHARTS]: boolean
|
||||
// 详情设置
|
||||
[ChartLayoutStoreEnum.DETAILS]: boolean
|
||||
// 组件展示方式
|
||||
[ChartLayoutStoreEnum.Chart_TYPE]: ChartModeEnum
|
||||
// 层级展示方式
|
||||
[ChartLayoutStoreEnum.LAYER_TYPE]: LayerModeEnum
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ChartLayoutType, LayerModeEnum } from './chartLayoutStore.d'
|
||||
import { ChartLayoutType, LayerModeEnum, ChartModeEnum } from './chartLayoutStore.d'
|
||||
import { setLocalStorage, getLocalStorage } from '@/utils'
|
||||
import { StorageEnum } from '@/enums/storageEnum'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
@@ -8,22 +8,25 @@ const chartEditStore = useChartEditStore()
|
||||
|
||||
const { GO_CHART_LAYOUT_STORE } = StorageEnum
|
||||
|
||||
const storageChartLayout: ChartLayoutType = getLocalStorage(GO_CHART_LAYOUT_STORE)
|
||||
const storageChartLayout: Partial<ChartLayoutType> = getLocalStorage(GO_CHART_LAYOUT_STORE)
|
||||
|
||||
// 编辑区域布局和静态设置
|
||||
export const useChartLayoutStore = defineStore({
|
||||
id: 'useChartLayoutStore',
|
||||
state: (): ChartLayoutType =>
|
||||
storageChartLayout || {
|
||||
// 图层控制
|
||||
layers: true,
|
||||
// 图表组件
|
||||
charts: true,
|
||||
// 详情设置(收缩为true)
|
||||
details: false,
|
||||
// 图层类型(默认图片)
|
||||
layerType: LayerModeEnum.THUMBNAIL
|
||||
},
|
||||
state: (): ChartLayoutType => ({
|
||||
// 图层控制
|
||||
layers: true,
|
||||
// 图表组件
|
||||
charts: true,
|
||||
// 详情设置(收缩为true)
|
||||
details: false,
|
||||
// 组件列表展示类型(默认单列)
|
||||
chartType: ChartModeEnum.SINGLE,
|
||||
// 图层类型(默认图片)
|
||||
layerType: LayerModeEnum.THUMBNAIL,
|
||||
// 防止值不存在
|
||||
...storageChartLayout
|
||||
}),
|
||||
getters: {
|
||||
getLayers(): boolean {
|
||||
return this.layers
|
||||
@@ -34,6 +37,9 @@ export const useChartLayoutStore = defineStore({
|
||||
getDetails(): boolean {
|
||||
return this.details
|
||||
},
|
||||
getChartType(): ChartModeEnum {
|
||||
return this.chartType
|
||||
},
|
||||
getLayerType(): LayerModeEnum {
|
||||
return this.layerType
|
||||
}
|
||||
@@ -41,8 +47,8 @@ export const useChartLayoutStore = defineStore({
|
||||
actions: {
|
||||
setItem<T extends keyof ChartLayoutType, K extends ChartLayoutType[T]>(key: T, value: K): void {
|
||||
this.$patch(state => {
|
||||
state[key]= value
|
||||
});
|
||||
state[key] = value
|
||||
})
|
||||
setLocalStorage(GO_CHART_LAYOUT_STORE, this.$state)
|
||||
// 重新计算拖拽区域缩放比例
|
||||
setTimeout(() => {
|
||||
|
||||
@@ -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_SETTING_STORE } = StorageEnum
|
||||
const { GO_SYSTEM_SETTING_STORE } = StorageEnum
|
||||
|
||||
const storageSetting: SettingStoreType = getLocalStorage(
|
||||
GO_SETTING_STORE
|
||||
GO_SYSTEM_SETTING_STORE
|
||||
)
|
||||
|
||||
// 全局设置
|
||||
@@ -48,7 +48,7 @@ export const useSettingStore = defineStore({
|
||||
this.$patch(state => {
|
||||
state[key] = value
|
||||
})
|
||||
setLocalStorage(GO_SETTING_STORE, this.$state)
|
||||
setLocalStorage(GO_SYSTEM_SETTING_STORE, this.$state)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
31
src/store/modules/systemStore/systemStore.d.ts
vendored
31
src/store/modules/systemStore/systemStore.d.ts
vendored
@@ -1,31 +0,0 @@
|
||||
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
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
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,65 +1,3 @@
|
||||
/**
|
||||
* * 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 文件对象
|
||||
@@ -113,4 +51,4 @@ export const downloadTextFile = (
|
||||
// 字符内容转变成blob地址
|
||||
const blob = new Blob([content])
|
||||
downloadByA(URL.createObjectURL(blob), filename, fileSuffix)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
/**
|
||||
* * 请求失败统一处理
|
||||
*/
|
||||
export const httpErrorHandle = () => {
|
||||
window['$message'].error(window['$t']('http.error_message'))
|
||||
}
|
||||
@@ -7,4 +7,3 @@ 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,12 +1,11 @@
|
||||
import { useRoute } from 'vue-router'
|
||||
import { ResultEnum, RequestHttpHeaderEnum } from '@/enums/httpEnum'
|
||||
import { ErrorPageNameMap, PageEnum, PreviewEnum } from '@/enums/pageEnum'
|
||||
import { ResultEnum } from '@/enums/httpEnum'
|
||||
import { ErrorPageNameMap, PageEnum } from '@/enums/pageEnum'
|
||||
import { docPath, giteeSourceCodePath } from '@/settings/pathConst'
|
||||
import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'
|
||||
import { cryptoDecode } from './crypto'
|
||||
import { StorageEnum } from '@/enums/storageEnum'
|
||||
import { clearLocalStorage, getLocalStorage, clearCookie } from './storage'
|
||||
import { clearLocalStorage, getLocalStorage } from './storage'
|
||||
import router from '@/router'
|
||||
import { logoutApi } from '@/api/path'
|
||||
|
||||
/**
|
||||
* * 根据名字跳转路由
|
||||
@@ -102,20 +101,11 @@ export const reloadRoutePage = () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* * 退出登录
|
||||
* * 退出
|
||||
*/
|
||||
export const logout = async () => {
|
||||
try {
|
||||
const res = await logoutApi() as unknown as MyResponseType
|
||||
if(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'))
|
||||
}
|
||||
export const logout = () => {
|
||||
clearLocalStorage(StorageEnum.GO_LOGIN_INFO_STORE)
|
||||
routerTurnByName(PageEnum.BASE_LOGIN_NAME)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,7 +157,7 @@ export const fetchRouteParams = () => {
|
||||
* * 通过硬解析获取当前路由下的参数
|
||||
* @returns object
|
||||
*/
|
||||
export const fetchRouteParamsLocation = () => {
|
||||
export const fetchRouteParamsLocation = () => {
|
||||
try {
|
||||
return document.location.hash.split('/').pop() || ''
|
||||
} catch (error) {
|
||||
@@ -185,29 +175,19 @@ export const goHome = () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* * 判断是否登录
|
||||
* * 判断是否登录(现阶段是有 login 数据即可)
|
||||
* @return boolean
|
||||
*/
|
||||
export const loginCheck = () => {
|
||||
try {
|
||||
const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
|
||||
const info = getLocalStorage(StorageEnum.GO_LOGIN_INFO_STORE)
|
||||
if (!info) return false
|
||||
if (info[SystemStoreEnum.USER_INFO][SystemStoreUserInfoEnum.USER_TOKEN]) {
|
||||
const decodeInfo = cryptoDecode(info)
|
||||
if (decodeInfo) {
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -68,41 +68,3 @@ 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);
|
||||
}
|
||||
|
||||
@@ -113,6 +113,29 @@ 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* * 挂载监听
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="go-content-charts-item-box">
|
||||
<div class="go-content-charts-item-box" :class="{ double: chartMode === ChartModeEnum.DOUBLE }">
|
||||
<!-- 每一项组件的渲染 -->
|
||||
<div
|
||||
class="item-box"
|
||||
@@ -11,21 +11,30 @@
|
||||
@dblclick="dblclickHandle(item)"
|
||||
>
|
||||
<div class="list-header">
|
||||
<mac-os-control-btn :mini="true" :disabled="true"></mac-os-control-btn>
|
||||
<n-text class="list-header-text" depth="3">{{ item.title }}</n-text>
|
||||
<mac-os-control-btn class="list-header-control-btn" :mini="true" :disabled="true"></mac-os-control-btn>
|
||||
<n-text class="list-header-text" depth="3">
|
||||
<n-ellipsis>{{ item.title }}</n-ellipsis>
|
||||
</n-text>
|
||||
</div>
|
||||
<div class="list-center go-flex-center">
|
||||
<img class="list-img" v-lazy="item.image" alt="图表图片" />
|
||||
</div>
|
||||
<div class="list-bottom">
|
||||
<n-text class="list-bottom-text" depth="3">
|
||||
<n-ellipsis style="max-width: 90%">{{ item.title }}</n-ellipsis>
|
||||
</n-text>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PropType } from 'vue'
|
||||
import { PropType, ref, Ref, computed } from 'vue'
|
||||
import { MacOsControlBtn } from '@/components/Tips/MacOsControlBtn/index'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
import { ChartModeEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d'
|
||||
import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore'
|
||||
import { componentInstall, loadingStart, loadingFinish, loadingError } from '@/utils'
|
||||
import { DragKeyEnum } from '@/enums/editPageEnum'
|
||||
import { createComponent } from '@/packages'
|
||||
@@ -41,6 +50,13 @@ defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const chartLayoutStore = useChartLayoutStore()
|
||||
|
||||
// 组件展示状态
|
||||
const chartMode: Ref<ChartModeEnum> = computed(() => {
|
||||
return chartLayoutStore.getChartType
|
||||
})
|
||||
|
||||
// 拖拽处理
|
||||
const dragStartHandle = (e: DragEvent, item: ConfigType) => {
|
||||
// 动态注册图表组件
|
||||
@@ -80,13 +96,19 @@ const dblclickHandle = async (item: ConfigType) => {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 列表项宽度 */
|
||||
$itemWidth: 86%;
|
||||
$itemWidth: 100%;
|
||||
$halfItemWidth: 46%;
|
||||
/* 内容高度 */
|
||||
$centerHeight: 100px;
|
||||
$halfCenterHeight: 50px;
|
||||
@include go('content-charts-item-box') {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
gap: 9px;
|
||||
padding: 10px;
|
||||
.item-box {
|
||||
margin: 0 7%;
|
||||
margin-bottom: 15px;
|
||||
margin: 0;
|
||||
width: $itemWidth;
|
||||
overflow: hidden;
|
||||
border-radius: 6px;
|
||||
@@ -122,6 +144,39 @@ $centerHeight: 100px;
|
||||
@extend .go-transition;
|
||||
}
|
||||
}
|
||||
.list-bottom {
|
||||
display: none;
|
||||
.list-bottom-text {
|
||||
font-size: 12px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 缩小展示 */
|
||||
&.double {
|
||||
.list-header {
|
||||
padding: 2px 5px;
|
||||
.list-header-text {
|
||||
display: none;
|
||||
}
|
||||
.list-header-control-btn {
|
||||
transform: scale(0.7);
|
||||
}
|
||||
}
|
||||
.item-box {
|
||||
width: $halfItemWidth;
|
||||
}
|
||||
.list-center {
|
||||
height: $halfCenterHeight;
|
||||
padding-bottom: 0px;
|
||||
.list-img {
|
||||
height: $halfCenterHeight;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
.list-bottom {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -123,7 +123,6 @@ $menuWidth: 65px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 10px 0;
|
||||
}
|
||||
@include deep() {
|
||||
.n-menu-item {
|
||||
|
||||
@@ -1,82 +1,104 @@
|
||||
<template>
|
||||
<div class="go-chart-search">
|
||||
<n-popover
|
||||
class="chart-search-popover"
|
||||
:show-arrow="false"
|
||||
:show="showPopover"
|
||||
:to="false"
|
||||
trigger="hover"
|
||||
placement="bottom-start"
|
||||
>
|
||||
<template #trigger>
|
||||
<n-input-group>
|
||||
<n-input
|
||||
v-model:value.trim="search"
|
||||
size="small"
|
||||
:loading="loading"
|
||||
placeholder="请输入组件名称"
|
||||
@update:value="searchHandle"
|
||||
>
|
||||
<template #suffix>
|
||||
<n-icon v-show="!loading" :component="SearchIcon" />
|
||||
</template>
|
||||
</n-input>
|
||||
</n-input-group>
|
||||
</template>
|
||||
<div class="go-chart-search-box">
|
||||
<div class="chart-search go-transition" :class="{ 'chart-search-focus': isFocus }">
|
||||
<n-popover
|
||||
class="chart-search-popover"
|
||||
:show-arrow="false"
|
||||
:show="showPopover"
|
||||
:to="false"
|
||||
trigger="hover"
|
||||
placement="bottom-start"
|
||||
>
|
||||
<template #trigger>
|
||||
<n-input-group>
|
||||
<n-input
|
||||
size="small"
|
||||
placeholder="搜索组件"
|
||||
v-model:value.trim="search"
|
||||
:loading="loading"
|
||||
@focus="focusHandle(true)"
|
||||
@blur="focusHandle(false)"
|
||||
@update:value="searchHandle"
|
||||
>
|
||||
<template #suffix>
|
||||
<n-icon v-show="!loading" :component="SearchIcon" />
|
||||
</template>
|
||||
</n-input>
|
||||
</n-input-group>
|
||||
</template>
|
||||
|
||||
<div class="search-list-box">
|
||||
<n-scrollbar style="max-height: 500px">
|
||||
<n-empty
|
||||
v-show="!searchRes.length"
|
||||
size="small"
|
||||
description="没有找到组件~"
|
||||
></n-empty>
|
||||
<div
|
||||
class="list-item go-flex-items-center go-ellipsis-1"
|
||||
v-for="item in searchRes"
|
||||
:key="item.key"
|
||||
:title="item.title"
|
||||
@click="selectChartHandle(item)"
|
||||
>
|
||||
<img class="list-item-img" v-lazy="item.image" alt="展示图" />
|
||||
<n-text class="list-item-fs" depth="2">{{ item.title }}</n-text>
|
||||
</div>
|
||||
</n-scrollbar>
|
||||
<div class="popover-modal"></div>
|
||||
</div>
|
||||
</n-popover>
|
||||
<div class="search-list-box">
|
||||
<n-scrollbar style="max-height: 500px">
|
||||
<n-empty v-show="!searchRes.length" size="small" description="没有找到组件~"></n-empty>
|
||||
<div
|
||||
class="list-item go-flex-items-center go-ellipsis-1"
|
||||
v-for="item in searchRes"
|
||||
:key="item.key"
|
||||
:title="item.title"
|
||||
@click="selectChartHandle(item)"
|
||||
>
|
||||
<img class="list-item-img" v-lazy="item.image" alt="展示图" />
|
||||
<n-text class="list-item-fs" depth="2">{{ item.title }}</n-text>
|
||||
</div>
|
||||
</n-scrollbar>
|
||||
<div class="popover-modal"></div>
|
||||
</div>
|
||||
</n-popover>
|
||||
</div>
|
||||
<n-button-group class="btn-group go-transition" :class="{ 'btn-group-focus': isFocus }" style="display: flex">
|
||||
<n-button
|
||||
ghost
|
||||
size="small"
|
||||
:key="index"
|
||||
:type="chartMode === item.value ? 'primary' : 'tertiary'"
|
||||
v-for="(item, index) in chartModeList"
|
||||
@click="changeChartModeType(item.value)"
|
||||
>
|
||||
<n-tooltip :show-arrow="false" trigger="hover">
|
||||
<template #trigger>
|
||||
<n-icon size="14" :component="item.icon" />
|
||||
</template>
|
||||
{{ item.label }}
|
||||
</n-tooltip>
|
||||
</n-button>
|
||||
</n-button-group>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onUnmounted } from 'vue'
|
||||
import { icon } from '@/plugins'
|
||||
import { createComponent } from '@/packages'
|
||||
import { ConfigType, CreateComponentType } from '@/packages/index.d'
|
||||
import { themeColor, MenuOptionsType } from '../../hooks/useAside.hook'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { ConfigType, CreateComponentType } from '@/packages/index.d'
|
||||
import { createComponent } from '@/packages'
|
||||
import { ChartModeEnum, ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d'
|
||||
import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore'
|
||||
import { isString, addEventListener, removeEventListener } from '@/utils'
|
||||
import { fetchConfigComponent, fetchChartComponent } from '@/packages/index'
|
||||
import {
|
||||
componentInstall,
|
||||
loadingStart,
|
||||
loadingFinish,
|
||||
loadingError,
|
||||
} from '@/utils'
|
||||
import { componentInstall, loadingStart, loadingFinish, loadingError } from '@/utils'
|
||||
|
||||
const props = defineProps({
|
||||
menuOptions: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
|
||||
const { SearchIcon } = icon.ionicons5
|
||||
const chartEditStore = useChartEditStore()
|
||||
const chartLayoutStore = useChartLayoutStore()
|
||||
const { SearchIcon, AlbumsIcon, GridIcon } = icon.ionicons5
|
||||
const isFocus = ref<boolean>(false)
|
||||
const showPopover = ref<boolean>(false)
|
||||
const loading = ref<boolean | undefined>(undefined)
|
||||
const search = ref<string | null>(null)
|
||||
const searchRes = ref<ConfigType[]>([])
|
||||
const chartMode = ref<ChartModeEnum>(chartLayoutStore.getChartType)
|
||||
|
||||
const chartModeList = [
|
||||
{ label: '单列', icon: AlbumsIcon, value: ChartModeEnum.SINGLE },
|
||||
{ label: '双列', icon: GridIcon, value: ChartModeEnum.DOUBLE }
|
||||
]
|
||||
|
||||
// 组件数组提取
|
||||
const listFormatHandle = (options: any[]) => {
|
||||
@@ -106,9 +128,7 @@ const searchHandle = (key: string | null) => {
|
||||
}
|
||||
loading.value = true
|
||||
showPopover.value = true
|
||||
searchRes.value = List.filter(
|
||||
(e: ConfigType) => !key || e.title.toLowerCase().includes(key.toLowerCase())
|
||||
)
|
||||
searchRes.value = List.filter((e: ConfigType) => !key || e.title.toLowerCase().includes(key.toLowerCase()))
|
||||
setTimeout(() => {
|
||||
loading.value = undefined
|
||||
}, 500)
|
||||
@@ -145,6 +165,17 @@ const selectChartHandle = async (item: ConfigType) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 聚焦设置
|
||||
const focusHandle = (value: boolean) => {
|
||||
isFocus.value = value
|
||||
}
|
||||
|
||||
// 修改图表展示方式
|
||||
const changeChartModeType = (value: ChartModeEnum) => {
|
||||
chartMode.value = value
|
||||
chartLayoutStore.setItem(ChartLayoutStoreEnum.Chart_TYPE, value)
|
||||
}
|
||||
|
||||
addEventListener(document, 'click', (e: Event) => {
|
||||
listenerCloseHandle(e)
|
||||
})
|
||||
@@ -155,54 +186,78 @@ onUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$width: 178px;
|
||||
@include go('chart-search') {
|
||||
width: $width;
|
||||
margin-right: -12px;
|
||||
.chart-search-popover {
|
||||
.search-list-box {
|
||||
width: calc(#{$width} - 30px);
|
||||
.list-item {
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
padding: 2px;
|
||||
padding-left: 6px;
|
||||
margin-bottom: 5px;
|
||||
&-fs {
|
||||
font-size: 12px;
|
||||
}
|
||||
&-img {
|
||||
height: 28px;
|
||||
margin-right: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
&:hover {
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 3px;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
border-radius: 2px;
|
||||
background-color: v-bind('themeColor');
|
||||
$width: 98px;
|
||||
$searchWidth: 176px;
|
||||
|
||||
@include go('chart-search-box') {
|
||||
display: flex;
|
||||
.chart-search {
|
||||
width: $width;
|
||||
margin-right: 10px;
|
||||
&.chart-search-focus {
|
||||
width: $searchWidth;
|
||||
&.chart-search {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
@include deep() {
|
||||
.chart-search-popover {
|
||||
padding-left: 5px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
}
|
||||
.chart-search-popover {
|
||||
.search-list-box {
|
||||
width: 163px;
|
||||
.list-item {
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
padding: 2px;
|
||||
padding-left: 6px;
|
||||
margin-bottom: 5px;
|
||||
&-fs {
|
||||
font-size: 12px;
|
||||
}
|
||||
&::after {
|
||||
z-index: -1;
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.1;
|
||||
left: 0;
|
||||
top: 0;
|
||||
&-img {
|
||||
height: 28px;
|
||||
margin-right: 5px;
|
||||
border-radius: 5px;
|
||||
background-color: v-bind('themeColor');
|
||||
}
|
||||
&:hover {
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 3px;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
border-radius: 2px;
|
||||
background-color: v-bind('themeColor');
|
||||
}
|
||||
&::after {
|
||||
z-index: -1;
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.1;
|
||||
left: 0;
|
||||
top: 0;
|
||||
border-radius: 5px;
|
||||
background-color: v-bind('themeColor');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn-group {
|
||||
width: 68px;
|
||||
overflow: hidden;
|
||||
&.btn-group-focus {
|
||||
width: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
</n-button>
|
||||
</n-space>
|
||||
<n-space>
|
||||
<n-text>预览方式</n-text>
|
||||
<n-text>适配方式</n-text>
|
||||
<n-button-group>
|
||||
<n-button
|
||||
v-for="item in previewTypeList"
|
||||
@@ -131,20 +131,16 @@ import { backgroundImageSize } from '@/settings/designSetting'
|
||||
import { FileTypeEnum } from '@/enums/fileTypeEnum'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
import { useSystemStore } from '@/store/modules/systemStore/systemStore'
|
||||
import { StylesSetting } from '@/components/Pages/ChartItemSetting'
|
||||
import { UploadCustomRequestOptions } from 'naive-ui'
|
||||
import { loadAsyncComponent, fetchRouteParamsLocation } from '@/utils'
|
||||
import { fileToUrl, loadAsyncComponent } 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
|
||||
|
||||
@@ -272,37 +268,18 @@ const clearColor = () => {
|
||||
// 自定义上传操作
|
||||
const customRequest = (options: UploadCustomRequestOptions) => {
|
||||
const { file } = options
|
||||
nextTick(async () => {
|
||||
nextTick(() => {
|
||||
if (file.file) {
|
||||
// 修改名称
|
||||
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) as unknown as MyResponseType
|
||||
|
||||
if(uploadRes.code === ResultEnum.SUCCESS) {
|
||||
chartEditStore.setEditCanvasConfig(
|
||||
EditCanvasConfigEnum.BACKGROUND_IMAGE,
|
||||
`${systemStore.getFetchInfo.OSSUrl}${uploadRes.data.fileName}?time=${new Date().getTime()}`
|
||||
)
|
||||
chartEditStore.setEditCanvasConfig(
|
||||
EditCanvasConfigEnum.SELECT_COLOR,
|
||||
false
|
||||
)
|
||||
return
|
||||
}
|
||||
window['$message'].error('添加图片失败,请稍后重试!')
|
||||
const ImageUrl = fileToUrl(file.file)
|
||||
chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.BACKGROUND_IMAGE, ImageUrl)
|
||||
chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.SELECT_COLOR, false)
|
||||
} else {
|
||||
window['$message'].error('添加图片失败,请稍后重试!')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 选择预览方式
|
||||
// 选择适配方式
|
||||
const selectPreviewType = (key: PreviewScaleEnum) => {
|
||||
chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.PREVIEW_SCALE_TYPE, key)
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ const sendHandle = async () => {
|
||||
if (!targetData.value?.request) return
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.requestGlobalConfig))
|
||||
const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.getRequestGlobalConfig))
|
||||
loading.value = false
|
||||
if (res) {
|
||||
if(!res?.data && !targetData.value.filter) window['$message'].warning('您的数据不符合默认格式,请配置过滤器!')
|
||||
|
||||
@@ -102,12 +102,11 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, watch, toRefs, toRaw } from 'vue'
|
||||
import { MonacoEditor } from '@/components/Pages/MonacoEditor'
|
||||
import { useTargetData } from '../../../hooks/useTargetData.hook'
|
||||
import { RequestHttpEnum, RequestDataTypeEnum, ResultEnum } from '@/enums/httpEnum'
|
||||
import { MonacoEditor } from '@/components/Pages/MonacoEditor'
|
||||
import { icon } from '@/plugins'
|
||||
import { goDialog, toString } from '@/utils'
|
||||
import { http, customizeHttp } from '@/api/http'
|
||||
import { customizeHttp } from '@/api/http'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
|
||||
const { DocumentTextIcon } = icon.ionicons5
|
||||
@@ -128,7 +127,7 @@ const sourceData = ref<any>('')
|
||||
// 动态获取数据
|
||||
const fetchTargetData = async () => {
|
||||
try {
|
||||
const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.requestGlobalConfig))
|
||||
const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.getRequestGlobalConfig))
|
||||
if (res) {
|
||||
sourceData.value = res
|
||||
return
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
<n-divider class="go-my-3" title-placement="left"></n-divider>
|
||||
<setting-item-box
|
||||
:itemRightStyle="{
|
||||
gridTemplateColumns: '5fr 2fr 1fr'
|
||||
gridTemplateColumns: '6fr 2fr'
|
||||
}"
|
||||
style="padding-right: 25px;"
|
||||
>
|
||||
<template #name>
|
||||
地址
|
||||
@@ -134,7 +135,7 @@ const apiList = [
|
||||
},
|
||||
{
|
||||
value: `【三维地球】${threeEarth01Url}`
|
||||
},
|
||||
}
|
||||
]
|
||||
</script>
|
||||
|
||||
|
||||
@@ -32,12 +32,10 @@ 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'
|
||||
|
||||
const emit = defineEmits(['update:modelShow', 'sendHandle'])
|
||||
|
||||
const { targetData } = useTargetData()
|
||||
const { dataSyncUpdate } = useSync()
|
||||
// 解构基础配置
|
||||
const { chartConfig } = toRefs(targetData.value)
|
||||
const { requestContentType } = toRefs(targetData.value.request)
|
||||
@@ -53,7 +51,6 @@ defineProps({
|
||||
const closeHandle = () => {
|
||||
emit('update:modelShow', false)
|
||||
emit('sendHandle')
|
||||
dataSyncUpdate()
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
import ChartEventAdvancedHandle from './index.vue'
|
||||
|
||||
export { ChartEventAdvancedHandle }
|
||||
@@ -10,13 +10,17 @@
|
||||
编辑
|
||||
</n-button>
|
||||
</template>
|
||||
<n-card>
|
||||
<n-card class="collapse-show-box">
|
||||
<!-- 函数体 -->
|
||||
<div v-for="eventName in EventLife" :key="eventName">
|
||||
<p>
|
||||
<span class="func-annotate">// {{ EventLifeName[eventName] }}</span>
|
||||
<br />
|
||||
<span class="func-keyword">async {{ eventName }}</span> (e, components, echarts, node_modules) {
|
||||
</p>
|
||||
<p class="go-ml-4"><n-code :code="(targetData.events || {})[eventName]" language="typescript"></n-code></p>
|
||||
<p class="go-ml-4">
|
||||
<n-code :code="(targetData.events.advancedEvents || {})[eventName] || ''" language="typescript"></n-code>
|
||||
</p>
|
||||
<p>}<span>,</span></p>
|
||||
</div>
|
||||
</n-card>
|
||||
@@ -30,13 +34,15 @@
|
||||
<n-text>高级事件编辑器(配合源码使用)</n-text>
|
||||
</n-space>
|
||||
</template>
|
||||
|
||||
<template #header-extra> </template>
|
||||
|
||||
<n-layout has-sider sider-placement="right">
|
||||
<n-layout style="height: 580px; padding-right: 20px">
|
||||
<n-tabs v-model:value="editTab" type="card" tab-style="min-width: 100px;">
|
||||
<!-- 提示 -->
|
||||
<template #suffix>
|
||||
<n-text class="tab-tip" type="warning">tips: {{ EventLifeTip[editTab] }}</n-text>
|
||||
<n-text class="tab-tip" type="warning">提示: {{ EventLifeTip[editTab] }}</n-text>
|
||||
</template>
|
||||
<n-tab-pane
|
||||
v-for="(eventName, index) in EventLife"
|
||||
@@ -50,7 +56,7 @@
|
||||
<span class="func-keyNameWord">{{ eventName }}(e, components, echarts, node_modules) {</span>
|
||||
</p>
|
||||
<!-- 编辑主体 -->
|
||||
<monaco-editor v-model:modelValue="events[eventName]" height="480px" language="javascript" />
|
||||
<monaco-editor v-model:modelValue="advancedEvents[eventName]" height="480px" language="javascript" />
|
||||
<!-- 函数结束 -->
|
||||
<p class="go-pl-3 func-keyNameWord">}</p>
|
||||
</n-tab-pane>
|
||||
@@ -136,7 +142,7 @@
|
||||
<template #icon>
|
||||
<n-icon :component="DocumentTextIcon" />
|
||||
</template>
|
||||
提示
|
||||
说明
|
||||
</n-tag>
|
||||
<n-text class="go-ml-2" depth="2">通过提供的参数可为图表增加定制化的tooltip、交互事件等等</n-text>
|
||||
</div>
|
||||
@@ -158,29 +164,27 @@ import { useTargetData } from '../../../hooks/useTargetData.hook'
|
||||
import { templateList } from './importTemplate'
|
||||
import { npmPkgs } from '@/hooks'
|
||||
import { icon } from '@/plugins'
|
||||
import { goDialog, toString } from '@/utils'
|
||||
import { CreateComponentType, EventLife } from '@/packages/index.d'
|
||||
import { Script } from 'vm'
|
||||
|
||||
const { targetData, chartEditStore } = useTargetData()
|
||||
const { DocumentTextIcon, ChevronDownIcon, PencilIcon } = icon.ionicons5
|
||||
|
||||
const EventLifeName = {
|
||||
[EventLife.BEFORE_MOUNT]: '渲染之前',
|
||||
[EventLife.MOUNTED]: '渲染之后'
|
||||
[EventLife.VNODE_BEFORE_MOUNT]: '渲染之前',
|
||||
[EventLife.VNODE_MOUNTED]: '渲染之后'
|
||||
}
|
||||
|
||||
const EventLifeTip = {
|
||||
[EventLife.BEFORE_MOUNT]: '此时组件 DOM 还未存在',
|
||||
[EventLife.MOUNTED]: '此时组件 DOM 已经存在'
|
||||
[EventLife.VNODE_BEFORE_MOUNT]: '此时组件 DOM 还未存在',
|
||||
[EventLife.VNODE_MOUNTED]: '此时组件 DOM 已经存在'
|
||||
}
|
||||
|
||||
// 受控弹窗
|
||||
const showModal = ref(false)
|
||||
// 编辑区域控制
|
||||
const editTab = ref(EventLife.MOUNTED)
|
||||
const editTab = ref(EventLife.VNODE_MOUNTED)
|
||||
// events 函数模板
|
||||
let events = ref({ ...targetData.value.events })
|
||||
let advancedEvents = ref({ ...targetData.value.events.advancedEvents })
|
||||
// 事件错误标识
|
||||
const errorFlag = ref(false)
|
||||
|
||||
@@ -190,7 +194,7 @@ const validEvents = () => {
|
||||
let message = ''
|
||||
let name = ''
|
||||
|
||||
errorFlag.value = Object.entries(events.value).every(([eventName, str]) => {
|
||||
errorFlag.value = Object.entries(advancedEvents.value).every(([eventName, str]) => {
|
||||
try {
|
||||
// 支持await,验证语法
|
||||
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor
|
||||
@@ -221,11 +225,14 @@ const saveEvents = () => {
|
||||
window['$message'].error('事件函数错误,无法进行保存')
|
||||
return
|
||||
}
|
||||
if (Object.values(events.value).join('').trim() === '') {
|
||||
if (Object.values(advancedEvents.value).join('').trim() === '') {
|
||||
// 清空事件
|
||||
targetData.value.events = undefined
|
||||
targetData.value.events.advancedEvents = {
|
||||
vnodeBeforeMount: undefined,
|
||||
vnodeMounted: undefined
|
||||
}
|
||||
} else {
|
||||
targetData.value.events = { ...events.value }
|
||||
targetData.value.events.advancedEvents = { ...advancedEvents.value }
|
||||
}
|
||||
closeEvents()
|
||||
}
|
||||
@@ -234,52 +241,12 @@ watch(
|
||||
() => showModal.value,
|
||||
(newData: boolean) => {
|
||||
if (newData) {
|
||||
events.value = { ...targetData.value.events }
|
||||
advancedEvents.value = { ...targetData.value.events.advancedEvents }
|
||||
}
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 外层也要使用 */
|
||||
.func-keyword {
|
||||
color: #b478cf;
|
||||
}
|
||||
|
||||
@include go('chart-data-monaco-editor') {
|
||||
.func-keyNameWord {
|
||||
color: #70c0e8;
|
||||
}
|
||||
.tab-tip {
|
||||
font-size: 12px;
|
||||
}
|
||||
&.n-card.n-modal,
|
||||
.n-card {
|
||||
@extend .go-background-filter;
|
||||
}
|
||||
}
|
||||
@include deep() {
|
||||
.n-layout,
|
||||
.n-layout-sider {
|
||||
background-color: transparent;
|
||||
}
|
||||
.go-editor-area {
|
||||
max-height: 530px;
|
||||
}
|
||||
.checkbox--hidden:checked {
|
||||
& + label {
|
||||
.n-icon {
|
||||
transition: all 0.3s;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
& ~ .go-editor-area {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
// 优化代码换行
|
||||
.n-code > pre {
|
||||
white-space: break-spaces;
|
||||
}
|
||||
}
|
||||
@import '../index.scss';
|
||||
</style>
|
||||
@@ -0,0 +1,3 @@
|
||||
import ChartEventBaseHandle from './index.vue'
|
||||
|
||||
export { ChartEventBaseHandle }
|
||||
@@ -0,0 +1,215 @@
|
||||
<template>
|
||||
<n-collapse-item title="基础事件配置" name="1">
|
||||
<template #header-extra>
|
||||
<n-button type="primary" tertiary size="small" @click.stop="showModal = true">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<pencil-icon />
|
||||
</n-icon>
|
||||
</template>
|
||||
编辑
|
||||
</n-button>
|
||||
</template>
|
||||
<n-card class="collapse-show-box">
|
||||
<!-- 函数体 -->
|
||||
<div v-for="eventName in BaseEvent" :key="eventName">
|
||||
<p>
|
||||
<span class="func-annotate">// {{ EventTypeName[eventName] }}</span>
|
||||
<br />
|
||||
<span class="func-keyword">async {{ eventName }}</span> (mouseEvent) {
|
||||
</p>
|
||||
<p class="go-ml-4">
|
||||
<n-code :code="(targetData.events.baseEvent || {})[eventName] || ''" language="typescript"></n-code>
|
||||
</p>
|
||||
<p>}<span>,</span></p>
|
||||
</div>
|
||||
</n-card>
|
||||
</n-collapse-item>
|
||||
|
||||
<!-- 弹窗 -->
|
||||
<n-modal class="go-chart-data-monaco-editor" v-model:show="showModal" :mask-closable="false">
|
||||
<n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 1200px; height: 700px">
|
||||
<template #header>
|
||||
<n-space>
|
||||
<n-text>基础事件编辑器</n-text>
|
||||
</n-space>
|
||||
</template>
|
||||
|
||||
<template #header-extra> </template>
|
||||
<n-layout has-sider sider-placement="right">
|
||||
<n-layout style="height: 580px; padding-right: 20px">
|
||||
<n-tabs v-model:value="editTab" type="card" tab-style="min-width: 100px;">
|
||||
<!-- 提示 -->
|
||||
<template #suffix>
|
||||
<n-text class="tab-tip" type="warning">提示: ECharts 组件会拦截鼠标事件</n-text>
|
||||
</template>
|
||||
<n-tab-pane
|
||||
v-for="(eventName, index) in BaseEvent"
|
||||
:key="index"
|
||||
:tab="`${EventTypeName[eventName]}-${eventName}`"
|
||||
:name="eventName"
|
||||
>
|
||||
<!-- 函数名称 -->
|
||||
<p class="go-pl-3">
|
||||
<span class="func-keyword">async function </span>
|
||||
<span class="func-keyNameWord">{{ eventName }}(mouseEvent) {</span>
|
||||
</p>
|
||||
<!-- 编辑主体 -->
|
||||
<monaco-editor v-model:modelValue="baseEvent[eventName]" height="480px" language="javascript" />
|
||||
<!-- 函数结束 -->
|
||||
<p class="go-pl-3 func-keyNameWord">}</p>
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
</n-layout>
|
||||
<n-layout-sider
|
||||
:collapsed-width="14"
|
||||
:width="340"
|
||||
show-trigger="bar"
|
||||
collapse-mode="transform"
|
||||
content-style="padding: 12px 12px 0px 12px;margin-left: 3px;"
|
||||
>
|
||||
<n-tabs default-value="1" justify-content="space-evenly" type="segment">
|
||||
<!-- 验证结果 -->
|
||||
<n-tab-pane tab="验证结果" name="1" size="small">
|
||||
<n-scrollbar trigger="none" style="max-height: 505px">
|
||||
<n-collapse class="go-px-3" arrow-placement="right" :default-expanded-names="[1, 2, 3]">
|
||||
<template v-for="error in [validEvents()]" :key="error">
|
||||
<n-collapse-item title="错误函数" :name="1">
|
||||
<n-text depth="3">{{ error.errorFn || '暂无' }}</n-text>
|
||||
</n-collapse-item>
|
||||
<n-collapse-item title="错误信息" :name="2">
|
||||
<n-text depth="3">{{ error.name || '暂无' }}</n-text>
|
||||
</n-collapse-item>
|
||||
<n-collapse-item title="堆栈信息" :name="3">
|
||||
<n-text depth="3">{{ error.message || '暂无' }}</n-text>
|
||||
</n-collapse-item>
|
||||
</template>
|
||||
</n-collapse>
|
||||
</n-scrollbar>
|
||||
</n-tab-pane>
|
||||
<!-- 辅助说明 -->
|
||||
<n-tab-pane tab="变量说明" name="2">
|
||||
<n-scrollbar trigger="none" style="max-height: 505px">
|
||||
<n-collapse class="go-px-3" arrow-placement="right" :default-expanded-names="[1, 2]">
|
||||
<n-collapse-item title="mouseEvent" :name="1">
|
||||
<n-text depth="3">鼠标事件对象</n-text>
|
||||
</n-collapse-item>
|
||||
</n-collapse>
|
||||
</n-scrollbar>
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
</n-layout-sider>
|
||||
</n-layout>
|
||||
|
||||
<template #action>
|
||||
<n-space justify="space-between">
|
||||
<div class="go-flex-items-center">
|
||||
<n-tag :bordered="false" type="primary">
|
||||
<template #icon>
|
||||
<n-icon :component="DocumentTextIcon" />
|
||||
</template>
|
||||
说明
|
||||
</n-tag>
|
||||
<n-text class="go-ml-2" depth="2">编写方式同正常 JavaScript 写法</n-text>
|
||||
</div>
|
||||
|
||||
<n-space>
|
||||
<n-button size="medium" @click="closeEvents">取消</n-button>
|
||||
<n-button size="medium" type="primary" @click="saveEvents">保存</n-button>
|
||||
</n-space>
|
||||
</n-space>
|
||||
</template>
|
||||
</n-card>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, toRefs, toRaw } from 'vue'
|
||||
import { MonacoEditor } from '@/components/Pages/MonacoEditor'
|
||||
import { useTargetData } from '../../../hooks/useTargetData.hook'
|
||||
import { CreateComponentType, BaseEvent } from '@/packages/index.d'
|
||||
import { icon } from '@/plugins'
|
||||
|
||||
const { targetData, chartEditStore } = useTargetData()
|
||||
const { DocumentTextIcon, ChevronDownIcon, PencilIcon } = icon.ionicons5
|
||||
|
||||
const EventTypeName = {
|
||||
[BaseEvent.ON_CLICK]: '单击',
|
||||
[BaseEvent.ON_DBL_CLICK]: '双击',
|
||||
[BaseEvent.ON_MOUSE_ENTER]: '鼠标进入',
|
||||
[BaseEvent.ON_MOUSE_LEAVE]: '鼠标移出'
|
||||
}
|
||||
|
||||
// 受控弹窗
|
||||
const showModal = ref(false)
|
||||
// 编辑区域控制
|
||||
const editTab = ref(BaseEvent.ON_CLICK)
|
||||
// events 函数模板
|
||||
let baseEvent = ref({ ...targetData.value.events.baseEvent })
|
||||
// 事件错误标识
|
||||
const errorFlag = ref(false)
|
||||
|
||||
// 验证语法
|
||||
const validEvents = () => {
|
||||
let errorFn = ''
|
||||
let message = ''
|
||||
let name = ''
|
||||
|
||||
errorFlag.value = Object.entries(baseEvent.value).every(([eventName, str]) => {
|
||||
try {
|
||||
// 支持await,验证语法
|
||||
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor
|
||||
new AsyncFunction(str)
|
||||
return true
|
||||
} catch (error: any) {
|
||||
message = error.message
|
||||
name = error.name
|
||||
errorFn = eventName
|
||||
return false
|
||||
}
|
||||
})
|
||||
return {
|
||||
errorFn,
|
||||
message,
|
||||
name
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭事件
|
||||
const closeEvents = () => {
|
||||
showModal.value = false
|
||||
}
|
||||
|
||||
// 新增事件
|
||||
const saveEvents = () => {
|
||||
if (validEvents().errorFn) {
|
||||
window['$message'].error('事件函数错误,无法进行保存')
|
||||
return
|
||||
}
|
||||
if (Object.values(baseEvent.value).join('').trim() === '') {
|
||||
// 清空事件
|
||||
targetData.value.events.baseEvent = {
|
||||
[BaseEvent.ON_CLICK]: undefined,
|
||||
[BaseEvent.ON_DBL_CLICK]: undefined,
|
||||
[BaseEvent.ON_MOUSE_ENTER]: undefined,
|
||||
[BaseEvent.ON_MOUSE_LEAVE]: undefined
|
||||
}
|
||||
} else {
|
||||
targetData.value.events.baseEvent = { ...baseEvent.value }
|
||||
}
|
||||
closeEvents()
|
||||
}
|
||||
|
||||
watch(
|
||||
() => showModal.value,
|
||||
(newData: boolean) => {
|
||||
if (newData) {
|
||||
baseEvent.value = { ...targetData.value.events.baseEvent }
|
||||
}
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../index.scss';
|
||||
</style>
|
||||
@@ -1,3 +0,0 @@
|
||||
import ChartEventMonacoEditor from './index.vue'
|
||||
|
||||
export { ChartEventMonacoEditor }
|
||||
@@ -0,0 +1,51 @@
|
||||
/* 外层也要使用 */
|
||||
.func-keyword {
|
||||
color: #b478cf;
|
||||
}
|
||||
|
||||
.func-annotate {
|
||||
color: #70c0e8;
|
||||
}
|
||||
|
||||
@include go('chart-data-monaco-editor') {
|
||||
.func-keyNameWord {
|
||||
color: #70c0e8;
|
||||
}
|
||||
.tab-tip {
|
||||
font-size: 12px;
|
||||
}
|
||||
&.n-card.n-modal,
|
||||
.n-card {
|
||||
@extend .go-background-filter;
|
||||
}
|
||||
}
|
||||
@include deep() {
|
||||
.n-layout,
|
||||
.n-layout-sider {
|
||||
background-color: transparent;
|
||||
}
|
||||
.collapse-show-box {
|
||||
.n-card__content {
|
||||
padding-left: 20px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
}
|
||||
.go-editor-area {
|
||||
max-height: 530px;
|
||||
}
|
||||
.checkbox--hidden:checked {
|
||||
& + label {
|
||||
.n-icon {
|
||||
transition: all 0.3s;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
& ~ .go-editor-area {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
// 优化代码换行
|
||||
.n-code > pre {
|
||||
white-space: break-spaces;
|
||||
}
|
||||
}
|
||||
@@ -5,20 +5,15 @@
|
||||
组件 id:
|
||||
<n-text>{{ targetData.id }}</n-text>
|
||||
</n-text>
|
||||
<n-collapse-item title="基础事件配置" name="1">
|
||||
<div class="go-event">
|
||||
<n-text depth="3">【单击、双击、移入、移出】在开发中,即将上线!</n-text>
|
||||
<br/>
|
||||
<n-text depth="3">(备注:高级事件模块可自行实现上述功能)</n-text>
|
||||
</div>
|
||||
</n-collapse-item>
|
||||
<chart-event-monaco-editor></chart-event-monaco-editor>
|
||||
<chart-event-base-handle></chart-event-base-handle>
|
||||
<chart-event-advanced-handle></chart-event-advanced-handle>
|
||||
</n-collapse>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { ChartEventMonacoEditor } from './components/ChartEventMonacoEditor'
|
||||
import { ChartEventAdvancedHandle } from './components/ChartEventAdvancedHandle'
|
||||
import { ChartEventBaseHandle } from './components/ChartEventBaseHandle'
|
||||
import { useTargetData } from '../hooks/useTargetData.hook'
|
||||
|
||||
const { targetData } = useTargetData()
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
<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,8 +55,7 @@
|
||||
import { reactive, ref, toRefs, watchEffect } from 'vue'
|
||||
import { icon } from '@/plugins'
|
||||
import { EditHistory } from '../EditHistory/index'
|
||||
import { EditShortcutKey } from '../EditShortcutKey/index'
|
||||
import { EditDataSync } from '../EditDataSync/index'
|
||||
import EditShortcutKey from '../EditShortcutKey/index.vue'
|
||||
import { useDesignStore } from '@/store/modules/designStore/designStore'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
@@ -147,10 +144,6 @@ $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;
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import EditDataSync from './index.vue'
|
||||
|
||||
export { EditDataSync }
|
||||
@@ -1,97 +0,0 @@
|
||||
<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,6 +133,9 @@ const options = computed(() => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.mr-10 {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.edit-history-popover {
|
||||
.btn-text {
|
||||
font-size: 12px;
|
||||
|
||||
@@ -113,25 +113,20 @@ 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.toUpperCase()} + 🖱️ `
|
||||
mac: `${MacKeyboard.CTRL_SOURCE_KEY.toUpperCase()} + 🖱️ `
|
||||
},
|
||||
{
|
||||
label: '创建分组',
|
||||
win: `${WinKeyboard.CTRL.toUpperCase()} + G / 🖱️ `,
|
||||
mac: `${MacKeyboard.CTRL.toUpperCase()} + G / 🖱️`
|
||||
mac: `${MacKeyboard.CTRL_SOURCE_KEY.toUpperCase()} + G / 🖱️`
|
||||
},
|
||||
{
|
||||
label: '解除分组',
|
||||
win: `${WinKeyboard.CTRL.toUpperCase()} + ${WinKeyboard.SHIFT.toUpperCase()} + G `,
|
||||
mac: `${MacKeyboard.CTRL.toUpperCase()} + ${WinKeyboard.SHIFT.toUpperCase()} + G `
|
||||
mac: `${MacKeyboard.CTRL_SOURCE_KEY.toUpperCase()} + ${WinKeyboard.SHIFT.toUpperCase()} + G `
|
||||
}
|
||||
]
|
||||
const closeHandle = () => {
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
import EditShortcutKey from './index.vue'
|
||||
|
||||
export { EditShortcutKey }
|
||||
@@ -7,6 +7,7 @@ import { useSync } from '@/views/chart/hooks/useSync.hook'
|
||||
export const useFile = () => {
|
||||
const importUploadFileListRef = ref()
|
||||
const { updateComponent } = useSync()
|
||||
|
||||
// 上传-前置
|
||||
//@ts-ignore
|
||||
const importBeforeUpload = ({ file }) => {
|
||||
@@ -37,6 +38,7 @@ export const useFile = () => {
|
||||
await updateComponent(fileData, false, true)
|
||||
window['$message'].success('导入成功!')
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
window['$message'].error('组件导入失败,请检查文件完整性!')
|
||||
}
|
||||
},
|
||||
@@ -47,6 +49,7 @@ export const useFile = () => {
|
||||
await updateComponent(fileData, true, true)
|
||||
window['$message'].success('导入成功!')
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
window['$message'].error('组件导入失败,请检查文件完整性!')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import { watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { useSync } from '@/views/chart/hooks/useSync.hook'
|
||||
import { ChartEnum } from '@/enums/pageEnum'
|
||||
import { SavePageEnum } from '@/enums/editPageEnum'
|
||||
import { editToJsonInterval } from '@/settings/designSetting'
|
||||
|
||||
const { updateComponent } = useSync()
|
||||
const chartEditStore = useChartEditStore()
|
||||
|
||||
// 侦听器更新
|
||||
const useSyncUpdateHandle = () => {
|
||||
// 定义侦听器变量
|
||||
let timer: any
|
||||
const updateFn = (e: any) => updateComponent(e!.detail, true, false)
|
||||
const syncData = async () => {
|
||||
dispatchEvent(new CustomEvent(SavePageEnum.CHART, { detail: chartEditStore.getStorageInfo }))
|
||||
}
|
||||
|
||||
// 开启侦听
|
||||
const use = () => {
|
||||
// // 1、定时同步数据
|
||||
// timer = setInterval(() => {
|
||||
// // 窗口激活并且处于工作台
|
||||
// document.hasFocus() && syncData()
|
||||
// }, editToJsonInterval)
|
||||
// 2、失焦同步数据
|
||||
addEventListener('blur', syncData)
|
||||
|
||||
// 【监听JSON代码 刷新工作台图表】
|
||||
addEventListener(SavePageEnum.JSON, updateFn)
|
||||
}
|
||||
|
||||
// 关闭侦听
|
||||
const unUse = () => {
|
||||
// clearInterval(timer)
|
||||
removeEventListener(SavePageEnum.JSON, updateFn)
|
||||
removeEventListener('blur', syncData)
|
||||
}
|
||||
|
||||
// 路由变更时处理
|
||||
const watchHandler = (toName: any, fromName: any) => {
|
||||
if (fromName == ChartEnum.CHART_HOME_NAME) {
|
||||
unUse()
|
||||
}
|
||||
if (toName == ChartEnum.CHART_HOME_NAME) {
|
||||
use()
|
||||
}
|
||||
}
|
||||
|
||||
return watchHandler
|
||||
}
|
||||
|
||||
export const useSyncUpdate = () => {
|
||||
const routerParamsInfo = useRoute()
|
||||
watch(() => routerParamsInfo.name, useSyncUpdateHandle(), { immediate: true })
|
||||
}
|
||||
@@ -62,20 +62,18 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, h, watch } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import { useSettingStore } from '@/store/modules/settingStore/settingStore'
|
||||
import { ToolsStatusEnum } from '@/store/modules/settingStore/settingStore.d'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { fetchPathByName, routerTurnByPath, setSessionStorage, getLocalStorage } from '@/utils'
|
||||
import { editToJsonInterval } from '@/settings/designSetting'
|
||||
import { EditEnum, ChartEnum } from '@/enums/pageEnum'
|
||||
import { fetchRouteParamsLocation, fetchPathByName, routerTurnByPath, setSessionStorage, getLocalStorage } from '@/utils'
|
||||
import { EditEnum } from '@/enums/pageEnum'
|
||||
import { StorageEnum } from '@/enums/storageEnum'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useSync } from '@/views/chart/hooks/useSync.hook'
|
||||
import { SavePageEnum } from '@/enums/editPageEnum'
|
||||
import { GoSystemSet } from '@/components/GoSystemSet/index'
|
||||
import { exportHandle } from './utils'
|
||||
import { useFile } from './hooks/useFile.hooks'
|
||||
import { useSyncUpdate } from './hooks/useSyncUpdate.hook'
|
||||
import { BtnListType, TypeEnum } from './index.d'
|
||||
import { icon } from '@/plugins'
|
||||
|
||||
@@ -83,7 +81,8 @@ const { DownloadIcon, ShareIcon, PawIcon, SettingsSharpIcon, CreateIcon } = icon
|
||||
const settingStore = useSettingStore()
|
||||
const chartEditStore = useChartEditStore()
|
||||
const routerParamsInfo = useRoute()
|
||||
const { updateComponent } = useSync()
|
||||
// 初始化编辑 JSON 模块
|
||||
useSyncUpdate()
|
||||
|
||||
// 鼠标悬停定时器
|
||||
let mouseTime: any = null
|
||||
@@ -138,13 +137,13 @@ const toolsMouseoutHandle = () => {
|
||||
|
||||
// 编辑处理
|
||||
const editHandle = () => {
|
||||
window['$message'].warning('将开启失焦更新与 5 秒同步更新!')
|
||||
window['$message'].warning('将开启失焦更新!')
|
||||
// window['$message'].warning('将开启失焦更新与 5 秒同步更新!')
|
||||
setTimeout(() => {
|
||||
// 获取id路径
|
||||
const path = fetchPathByName(EditEnum.CHART_EDIT_NAME, 'href')
|
||||
if (!path) return
|
||||
let { id } = routerParamsInfo.params as any
|
||||
id = typeof id === 'string' ? id : id[0]
|
||||
const id = fetchRouteParamsLocation()
|
||||
updateToSession(id)
|
||||
routerTurnByPath(path, [id], undefined, true)
|
||||
}, 1000)
|
||||
@@ -170,51 +169,6 @@ const updateToSession = (id: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 侦听器更新
|
||||
const useSyncUpdate = () => {
|
||||
// 定义侦听器变量
|
||||
let timer: any
|
||||
const updateFn = (e: any) => updateComponent(e!.detail, true, false)
|
||||
const syncData = () => {
|
||||
if (routerParamsInfo.name == ChartEnum.CHART_HOME_NAME) {
|
||||
dispatchEvent(new CustomEvent(SavePageEnum.CHART, { detail: chartEditStore.getStorageInfo }))
|
||||
}
|
||||
}
|
||||
|
||||
// 开启侦听
|
||||
const use = () => {
|
||||
// 1、定时同步数据
|
||||
timer = setInterval(() => {
|
||||
// 窗口激活并且处于工作台
|
||||
document.hasFocus() && syncData()
|
||||
}, editToJsonInterval)
|
||||
// 2、失焦同步数据
|
||||
addEventListener('blur', syncData)
|
||||
|
||||
// 【监听JSON代码 刷新工作台图表】
|
||||
addEventListener(SavePageEnum.JSON, updateFn)
|
||||
}
|
||||
|
||||
// 关闭侦听
|
||||
const unUse = () => {
|
||||
clearInterval(timer)
|
||||
removeEventListener(SavePageEnum.JSON, updateFn)
|
||||
removeEventListener('blur', syncData)
|
||||
}
|
||||
|
||||
// 路由变更时处理
|
||||
const watchHandler = (toName: any, fromName: any) => {
|
||||
if (fromName == ChartEnum.CHART_HOME_NAME) {
|
||||
unUse()
|
||||
}
|
||||
if (toName == ChartEnum.CHART_HOME_NAME) {
|
||||
use()
|
||||
}
|
||||
}
|
||||
return watchHandler
|
||||
}
|
||||
|
||||
watch(() => routerParamsInfo.name, useSyncUpdate(), { immediate: true })
|
||||
|
||||
// 配置列表
|
||||
const btnList: BtnListType[] = [
|
||||
@@ -234,7 +188,7 @@ const btnList: BtnListType[] = [
|
||||
{
|
||||
key: 'edit',
|
||||
type: TypeEnum.BUTTON,
|
||||
name: '编辑JSON',
|
||||
name: '编辑',
|
||||
icon: CreateIcon,
|
||||
handle: editHandle
|
||||
},
|
||||
|
||||
@@ -9,7 +9,7 @@ export const exportHandle = () => {
|
||||
|
||||
// 导出数据
|
||||
downloadTextFile(
|
||||
JSON.stringify(chartEditStore.getStorageInfo || {}, (k, v) => {
|
||||
JSON.stringify(chartEditStore.getStorageInfo || [], (k, v) => {
|
||||
return v === undefined ? null : v
|
||||
}),
|
||||
undefined,
|
||||
|
||||
@@ -91,7 +91,6 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore
|
||||
|
||||
import { useLayout } from './hooks/useLayout.hook'
|
||||
import { useAddKeyboard } from '../hooks/useKeyboard.hook'
|
||||
import { useSync } from '../hooks/useSync.hook'
|
||||
import { dragHandle, dragoverHandle, mousedownHandleUnStop, useMouseHandle } from './hooks/useDrag.hook'
|
||||
import { useComponentStyle, useSizeStyle } from './hooks/useStyle.hook'
|
||||
|
||||
@@ -105,7 +104,6 @@ import { EditTools } from './components/EditTools'
|
||||
|
||||
const chartEditStore = useChartEditStore()
|
||||
const { handleContextMenu } = useContextMenu()
|
||||
const { dataSyncFetch, intervalDataSyncUpdate } = useSync()
|
||||
|
||||
// 布局处理
|
||||
useLayout()
|
||||
@@ -174,13 +172,9 @@ const rangeStyle = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
// 键盘事件
|
||||
onMounted(() => {
|
||||
// 键盘事件
|
||||
useAddKeyboard()
|
||||
// 获取数据
|
||||
dataSyncFetch()
|
||||
// 定时更新数据
|
||||
intervalDataSyncUpdate()
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -29,44 +29,26 @@
|
||||
</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, Ref, reactive, computed } from 'vue'
|
||||
import { toRefs, 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()
|
||||
@@ -148,7 +130,7 @@ const clickHistoryHandle = (item: ItemType<HistoryStackEnum>) => {
|
||||
// 返回首页
|
||||
const goHomeHandle = () => {
|
||||
goDialog({
|
||||
message: '确定已保存了数据(Ctrl / ⌘ + S),并返回到首页吗?',
|
||||
message: '返回将不会保存任何操作',
|
||||
isMaskClosable: true,
|
||||
onPositiveCallback: () => {
|
||||
goHome()
|
||||
|
||||
@@ -1,98 +1,29 @@
|
||||
<template>
|
||||
<n-space>
|
||||
<n-button
|
||||
v-for="item in btnList"
|
||||
:key="item.key"
|
||||
:type="item.type()"
|
||||
ghost
|
||||
@click="item.event"
|
||||
>
|
||||
<n-space class="go-mt-0">
|
||||
<n-button v-for="item in btnList" :key="item.title" 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 { ref, shallowReactive, watchEffect } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useClipboard } from '@vueuse/core'
|
||||
import { shallowReactive } from 'vue'
|
||||
import { renderIcon, goDialog, fetchPathByName, routerTurnByPath, setSessionStorage, getLocalStorage } from '@/utils'
|
||||
import { PreviewEnum } from '@/enums/pageEnum'
|
||||
import { StorageEnum } from '@/enums/storageEnum'
|
||||
import { ResultEnum } from '@/enums/httpEnum'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
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 { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
import { icon } from '@/plugins'
|
||||
|
||||
const { BrowsersOutlineIcon, SendIcon, CloseIcon } = icon.ionicons5
|
||||
const { BrowsersOutlineIcon, SendIcon } = 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')
|
||||
@@ -101,100 +32,55 @@ const previewHandle = () => {
|
||||
// id 标识
|
||||
const previewId = typeof id === 'string' ? id : id[0]
|
||||
const storageInfo = chartEditStore.getStorageInfo
|
||||
const sessionStorageInfo =
|
||||
getLocalStorage(StorageEnum.GO_CHART_STORAGE_LIST) || []
|
||||
const sessionStorageInfo = getLocalStorage(StorageEnum.GO_CHART_STORAGE_LIST) || []
|
||||
|
||||
if (sessionStorageInfo?.length) {
|
||||
const repeateIndex = sessionStorageInfo.findIndex(
|
||||
(e: { id: string }) => e.id === previewId
|
||||
)
|
||||
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({
|
||||
id: previewId,
|
||||
...storageInfo,
|
||||
id: previewId, ...storageInfo
|
||||
})
|
||||
setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, sessionStorageInfo)
|
||||
}
|
||||
} else {
|
||||
setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, [
|
||||
{ id: previewId, ...storageInfo },
|
||||
])
|
||||
setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, [{ id: previewId, ...storageInfo }])
|
||||
}
|
||||
// 跳转
|
||||
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 = async () => {
|
||||
const res = (await changeProjectReleaseApi({
|
||||
id: fetchRouteParamsLocation(),
|
||||
// 反过来
|
||||
state: release.value ? -1 : 1,
|
||||
})) as unknown as MyResponseType
|
||||
|
||||
if (res.code === ResultEnum.SUCCESS) {
|
||||
modelShowHandle()
|
||||
if (!release.value) {
|
||||
copyPreviewPath('发布成功!已复制地址到剪贴板~', '发布成功!')
|
||||
} else {
|
||||
window['$message'].success(`已取消发布`)
|
||||
}
|
||||
chartEditStore.setProjectInfo(ProjectInfoEnum.RELEASE, !release.value)
|
||||
} else {
|
||||
httpErrorHandle()
|
||||
}
|
||||
const sendHandle = () => {
|
||||
goDialog({
|
||||
message: '想体验发布功能,请前往 master-fetch 分支查看: https://gitee.com/MTrun/go-view/tree/master-fetch',
|
||||
positiveText: '了然',
|
||||
closeNegativeText: true,
|
||||
onPositiveCallback: () => {}
|
||||
})
|
||||
}
|
||||
|
||||
const btnList = shallowReactive([
|
||||
{
|
||||
key: 'preview',
|
||||
title: () => '预览',
|
||||
type: () => 'default',
|
||||
select: true,
|
||||
title: '预览',
|
||||
icon: renderIcon(BrowsersOutlineIcon),
|
||||
event: previewHandle,
|
||||
event: previewHandle
|
||||
},
|
||||
{
|
||||
key: 'release',
|
||||
title: () => (release.value ? '已发布' : '发布'),
|
||||
select: true,
|
||||
title: '发布',
|
||||
icon: renderIcon(SendIcon),
|
||||
type: () => (release.value ? 'primary' : 'default'),
|
||||
event: modelShowHandle,
|
||||
},
|
||||
])
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@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;
|
||||
}
|
||||
event: sendHandle
|
||||
}
|
||||
])
|
||||
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.align-center {
|
||||
margin-top: -4px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
<n-text @click="handleFocus">
|
||||
工作空间 -
|
||||
<n-button v-show="!focus" secondary round size="tiny">
|
||||
<span class="title">{{ comTitle }}</span>
|
||||
<span class="title">
|
||||
{{ comTitle }}
|
||||
</span>
|
||||
</n-button>
|
||||
</n-text>
|
||||
|
||||
@@ -27,31 +29,29 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, nextTick, computed, watchEffect } from 'vue'
|
||||
import { ResultEnum } from '@/enums/httpEnum'
|
||||
import { fetchRouteParamsLocation, httpErrorHandle } from '@/utils'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { ProjectInfoEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
import { updateProjectApi } from '@/api/path'
|
||||
import { useSync } from '../../hooks/useSync.hook'
|
||||
import { ref, nextTick, computed } from 'vue'
|
||||
import { fetchRouteParamsLocation } from '@/utils'
|
||||
import { icon } from '@/plugins'
|
||||
|
||||
const chartEditStore = useChartEditStore()
|
||||
const { dataSyncUpdate } = useSync()
|
||||
const { FishIcon } = icon.ionicons5
|
||||
|
||||
const focus = ref<boolean>(false)
|
||||
const inputInstRef = ref(null)
|
||||
|
||||
const title = ref<string>(fetchRouteParamsLocation())
|
||||
// 根据路由 id 参数获取项目信息
|
||||
const fetchProhectInfoById = () => {
|
||||
const id = fetchRouteParamsLocation()
|
||||
if (id.length) {
|
||||
return id[0]
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
title.value = chartEditStore.getProjectInfo.projectName || ''
|
||||
})
|
||||
const title = ref<string>(fetchProhectInfoById() || '')
|
||||
|
||||
const comTitle = computed(() => {
|
||||
title.value = title.value && title.value.replace(/\s/g, '')
|
||||
return title.value.length ? title.value : fetchRouteParamsLocation()
|
||||
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
||||
title.value = title.value.replace(/\s/g, '')
|
||||
return title.value.length ? title.value : '新项目'
|
||||
})
|
||||
|
||||
const handleFocus = () => {
|
||||
@@ -61,18 +61,8 @@ const handleFocus = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const handleBlur = async () => {
|
||||
const handleBlur = () => {
|
||||
focus.value = false
|
||||
chartEditStore.setProjectInfo(ProjectInfoEnum.PROJECT_NAME, title.value || '')
|
||||
const res = (await updateProjectApi({
|
||||
id: fetchRouteParamsLocation(),
|
||||
projectName: title.value
|
||||
})) as unknown as MyResponseType
|
||||
if (res.code === ResultEnum.SUCCESS) {
|
||||
dataSyncUpdate()
|
||||
} else {
|
||||
httpErrorHandle()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -81,12 +81,13 @@ import { LayersGroupListItem } from './components/LayersGroupListItem/index'
|
||||
import { icon } from '@/plugins'
|
||||
|
||||
const { LayersIcon, GridIcon, ListIcon } = icon.ionicons5
|
||||
const { LaptopIcon } = icon.carbon
|
||||
const chartLayoutStore = useChartLayoutStore()
|
||||
const chartEditStore = useChartEditStore()
|
||||
const { handleContextMenu, onClickOutSide } = useContextMenu()
|
||||
|
||||
const layerModeList = [
|
||||
{ label: '缩略图', icon: GridIcon, value: LayerModeEnum.THUMBNAIL },
|
||||
{ label: '缩略图', icon: LaptopIcon, value: LayerModeEnum.THUMBNAIL },
|
||||
{ label: '文本列表', icon: ListIcon, value: LayerModeEnum.TEXT }
|
||||
]
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
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'
|
||||
@@ -8,7 +7,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}`
|
||||
@@ -24,7 +23,6 @@ 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'),
|
||||
@@ -50,7 +48,6 @@ 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'),
|
||||
@@ -74,7 +71,6 @@ const winKeyList: Array<string> = [
|
||||
winKeyboardValue.back,
|
||||
winKeyboardValue.forward,
|
||||
|
||||
winKeyboardValue.save,
|
||||
winKeyboardValue.group,
|
||||
winKeyboardValue.unGroup,
|
||||
|
||||
@@ -100,7 +96,6 @@ const macKeyList: Array<string> = [
|
||||
macKeyboardValue.back,
|
||||
macKeyboardValue.forward,
|
||||
|
||||
macKeyboardValue.save,
|
||||
macKeyboardValue.group,
|
||||
macKeyboardValue.unGroup,
|
||||
|
||||
@@ -208,11 +203,6 @@ 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,42 +1,81 @@
|
||||
import { onUnmounted } from 'vue';
|
||||
import html2canvas from 'html2canvas'
|
||||
import { getUUID, httpErrorHandle, fetchRouteParamsLocation, base64toFile } from '@/utils'
|
||||
import { getUUID } from '@/utils'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { EditCanvasTypeEnum, ChartEditStoreEnum, ProjectInfoEnum, ChartEditStorage } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
import { ChartEditStoreEnum, 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 { fetchChartComponent, fetchConfigComponent, createComponent } from '@/packages/index'
|
||||
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, CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
|
||||
import { PublicGroupConfigClass } from '@/packages/public/publicConfig'
|
||||
import merge from 'lodash/merge'
|
||||
|
||||
/**
|
||||
* 合并处理
|
||||
* @param object 模板数据
|
||||
* * 画布-版本升级对旧数据无法兼容的补丁
|
||||
* @param object
|
||||
*/
|
||||
const canvasVersionUpdatePolyfill = (object: any) => {
|
||||
return object
|
||||
}
|
||||
|
||||
/**
|
||||
* * 组件-版本升级对旧数据无法兼容的补丁
|
||||
* @param newObject
|
||||
* @param sources
|
||||
*/
|
||||
const componentVersionUpdatePolyfill = (newObject: any, sources: any) => {
|
||||
try {
|
||||
// 判断是否是组件
|
||||
if (sources.id) {
|
||||
// 处理事件补丁
|
||||
const hasVnodeBeforeMount = 'vnodeBeforeMount' in sources.events
|
||||
const hasVnodeMounted = 'vnodeMounted' in sources.events
|
||||
|
||||
if (hasVnodeBeforeMount) {
|
||||
newObject.events.advancedEvents.vnodeBeforeMount = sources?.events.vnodeBeforeMount
|
||||
}
|
||||
if (hasVnodeMounted) {
|
||||
newObject.events.advancedEvents.vnodeMounted = sources?.events.vnodeMounted
|
||||
}
|
||||
if (hasVnodeBeforeMount || hasVnodeMounted) {
|
||||
sources.events = {
|
||||
baseEvent: {
|
||||
[BaseEvent.ON_CLICK]: undefined,
|
||||
[BaseEvent.ON_DBL_CLICK]: undefined,
|
||||
[BaseEvent.ON_MOUSE_ENTER]: undefined,
|
||||
[BaseEvent.ON_MOUSE_LEAVE]: undefined
|
||||
},
|
||||
advancedEvents: {
|
||||
[EventLife.VNODE_MOUNTED]: undefined,
|
||||
[EventLife.VNODE_BEFORE_MOUNT]: undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
return newObject
|
||||
}
|
||||
} catch (error) {
|
||||
return newObject
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* * 合并处理
|
||||
* @param newObject 新的模板数据
|
||||
* @param sources 新拿到的数据
|
||||
* @returns object
|
||||
*/
|
||||
const componentMerge = (object: any, sources: any, notComponent = false) => {
|
||||
const componentMerge = (newObject: any, sources: any, notComponent = false) => {
|
||||
// 处理组件补丁
|
||||
componentVersionUpdatePolyfill(newObject, sources)
|
||||
|
||||
// 非组件不处理
|
||||
if (notComponent) return merge(object, sources)
|
||||
// 组件排除 options
|
||||
if (notComponent) return merge(newObject, sources)
|
||||
// 组件排除 newObject
|
||||
const option = sources.option
|
||||
if (!option) return merge(object, sources)
|
||||
if (!option) return merge(newObject, sources)
|
||||
|
||||
// 为 undefined 的 sources 来源对象属性将被跳过详见 https://www.lodashjs.com/docs/lodash.merge
|
||||
sources.option = undefined
|
||||
if (option) {
|
||||
return {
|
||||
...merge(object, sources),
|
||||
...merge(newObject, sources),
|
||||
option: option
|
||||
}
|
||||
}
|
||||
@@ -46,7 +85,6 @@ const componentMerge = (object: any, sources: any, notComponent = false) => {
|
||||
export const useSync = () => {
|
||||
const chartEditStore = useChartEditStore()
|
||||
const chartHistoryStore = useChartHistoryStore()
|
||||
const systemStore = useSystemStore()
|
||||
|
||||
/**
|
||||
* * 组件动态注册
|
||||
@@ -62,6 +100,9 @@ export const useSync = () => {
|
||||
chartHistoryStore.clearBackStack()
|
||||
chartHistoryStore.clearForwardStack()
|
||||
}
|
||||
// 画布补丁处理
|
||||
projectData.editCanvasConfig = canvasVersionUpdatePolyfill(projectData.editCanvasConfig)
|
||||
|
||||
// 列表组件注册
|
||||
projectData.componentList.forEach(async (e: CreateComponentType | CreateComponentGroupType) => {
|
||||
const intComponent = (target: CreateComponentType) => {
|
||||
@@ -132,7 +173,7 @@ export const useSync = () => {
|
||||
// 分组插入到列表
|
||||
chartEditStore.addComponentList(groupClass, false, true)
|
||||
} else {
|
||||
await create(comItem as CreateComponentType)
|
||||
await create(comItem as CreateComponentType)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -143,125 +184,7 @@ export const useSync = () => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* * 赋值全局数据
|
||||
* @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 () => {
|
||||
chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.START)
|
||||
try {
|
||||
const res = await fetchProjectApi({ projectId: fetchRouteParamsLocation() }) as unknown as MyResponseType
|
||||
if (res.code === ResultEnum.SUCCESS) {
|
||||
if (res.data) {
|
||||
updateStoreInfo(res.data)
|
||||
// 更新全局数据
|
||||
await updateComponent(JSON.parse(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 () => {
|
||||
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)
|
||||
|
||||
// 获取缩略图片
|
||||
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) as unknown as MyResponseType
|
||||
// 保存预览图
|
||||
if(uploadRes.code === ResultEnum.SUCCESS) {
|
||||
await updateProjectApi({
|
||||
id: fetchRouteParamsLocation(),
|
||||
indexImage: `${systemStore.getFetchInfo.OSSUrl}${uploadRes.data.fileName}`
|
||||
})
|
||||
}
|
||||
|
||||
// 保存数据
|
||||
let params = new FormData()
|
||||
params.append('projectId', projectId)
|
||||
params.append('content', JSON.stringify(chartEditStore.getStorageInfo || {}))
|
||||
const res= await saveProjectApi(params) as unknown as MyResponseType
|
||||
|
||||
if (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,
|
||||
updateStoreInfo,
|
||||
dataSyncFetch,
|
||||
dataSyncUpdate,
|
||||
intervalDataSyncUpdate
|
||||
updateComponent
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,14 +44,13 @@ import { icon } from '@/plugins'
|
||||
|
||||
const { ChevronBackOutlineIcon, DownloadIcon } = icon.ionicons5
|
||||
const showOpenFilePicker: Function = (window as any).showOpenFilePicker
|
||||
let content = ref('')
|
||||
|
||||
const content = ref('')
|
||||
// 从sessionStorage 获取数据
|
||||
function getDataBySession() {
|
||||
const localStorageInfo: ChartEditStorageType = getSessionStorageInfo() as unknown as ChartEditStorageType
|
||||
async function getDataBySession() {
|
||||
const localStorageInfo: ChartEditStorageType = await getSessionStorageInfo() as unknown as ChartEditStorageType
|
||||
content.value = JSON.stringify(localStorageInfo, undefined, 2)
|
||||
}
|
||||
getDataBySession()
|
||||
setTimeout(getDataBySession)
|
||||
|
||||
// 返回父窗口
|
||||
function back() {
|
||||
@@ -86,7 +85,7 @@ document.addEventListener('keydown', function (e) {
|
||||
addEventListener('blur', updateSync)
|
||||
|
||||
// 同步更新
|
||||
function updateSync() {
|
||||
async function updateSync() {
|
||||
if (!window.opener) {
|
||||
return window['$message'].error('源窗口已关闭,视图同步失败')
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user