Compare commits

..

42 Commits

Author SHA1 Message Date
奔跑的面条
f9c715c72c build: 升级版本到1.1.6 2022-12-16 14:01:47 +08:00
奔跑的面条
e2b3118d9d Merge branch 'dev' 2022-12-16 13:57:02 +08:00
奔跑的面条
f4c3a2b04f docs: 修改首页说明 2022-12-16 10:04:25 +08:00
奔跑的面条
31a8957de9 !106 docs: add Cloud IDE preview link
Merge pull request !106 from aresn/master
2022-12-16 01:49:34 +00:00
奔跑的面条
46f20f61b5 update README.md.
Signed-off-by: 奔跑的面条 <1262327911@qq.com>
2022-12-09 08:11:47 +00:00
aresn
dba5ab3ef3 update README.md.
Signed-off-by: aresn <admin@aresn.com>
2022-12-07 09:51:33 +00:00
aresn
2251bebee6 add preview.yml.
Signed-off-by: aresn <admin@aresn.com>
2022-12-07 09:49:48 +00:00
奔跑的面条
3ac9ffc73c Merge branch 'dev' 2022-11-22 12:44:51 +08:00
奔跑的面条
c420ae467f Merge branch 'dev' 2022-11-21 10:49:25 +08:00
奔跑的面条
8334fe5bcc build: 升级版本到 1.1.5 2022-11-19 21:04:53 +08:00
奔跑的面条
f99edce6f4 Merge branch 'dev' 2022-11-19 21:04:32 +08:00
奔跑的面条
f47acca703 update README.md.
Signed-off-by: 奔跑的面条 <1262327911@qq.com>
2022-11-10 10:13:19 +00:00
奔跑的面条
73a6c6b920 update README.md.
Signed-off-by: 奔跑的面条 <1262327911@qq.com>
2022-11-10 10:10:58 +00:00
奔跑的面条
672f7a0a7c Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-11-05 21:46:26 +08:00
奔跑的面条
de78fb2149 docs: 新增文档截图 2022-11-05 18:19:33 +08:00
奔跑的面条
4a59e69bbe docs: 修改首页地址 2022-11-02 19:46:19 +08:00
奔跑的面条
a442e13a7b feat: 升级版本到1.1.4 2022-11-02 19:05:16 +08:00
奔跑的面条
4d093a4a80 Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-11-02 19:02:38 +08:00
奔跑的面条
7e59d8d36c docs: 修改链接地址 2022-11-02 09:57:28 +08:00
奔跑的面条
8241077495 update README.md.
Signed-off-by: 奔跑的面条 <1262327911@qq.com>
2022-10-29 12:09:36 +00:00
奔跑的面条
82b29a2f8b docs: 优化说明文档 2022-10-29 19:57:02 +08:00
奔跑的面条
b789d80f98 fix: 修改主页说明 2022-10-29 19:51:33 +08:00
奔跑的面条
a8c80e2366 docs: 修改主页说明 2022-10-29 19:50:30 +08:00
奔跑的面条
bdbdd37789 build: 升级版本到1.1.3 2022-10-15 17:17:34 +08:00
奔跑的面条
c8fb5b9152 Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-10-15 17:12:13 +08:00
奔跑的面条
aef155e039 fix: 修复组件导入数据错乱的问题 2022-10-09 16:37:30 +08:00
奔跑的面条
443573455b Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-10-09 09:28:38 +08:00
奔跑的面条
d811ab7dfa build: 撤回错误版本号 2022-10-08 21:12:58 +08:00
奔跑的面条
5f79ab6e6d build: 升级版本到1.1.2 2022-10-08 21:12:27 +08:00
奔跑的面条
502edbca5d Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-10-08 21:05:48 +08:00
奔跑的面条
1a04267cb7 build: 升级版本到1.1.1 2022-10-08 20:59:55 +08:00
奔跑的面条
9c2c1bdfa1 Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-10-08 20:59:25 +08:00
奔跑的面条
72e93f3768 Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-09-27 20:16:07 +08:00
奔跑的面条
e6f2066d42 Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-09-22 14:15:00 +08:00
奔跑的面条
2812c39524 Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-09-21 19:54:29 +08:00
奔跑的面条
491485856e Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-09-19 20:46:37 +08:00
奔跑的面条
abde7e176d Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-09-19 20:13:50 +08:00
奔跑的面条
bab8faadee add default pipeline template yaml 2022-09-19 11:58:32 +00:00
奔跑的面条
427d72fb8b Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-09-18 16:48:28 +08:00
奔跑的面条
dc5b20a329 build: 升级版本到1.1.0 2022-09-18 16:33:26 +08:00
奔跑的面条
4cb934eef3 Merge branch 'dev' of https://gitee.com/MTrun/go-view 2022-09-18 16:32:34 +08:00
奔跑的面条
35e8cea0b5 docs: 更新已完成图表说明 2022-09-17 23:00:51 +08:00
308 changed files with 3314 additions and 10939 deletions

12
.env
View File

@@ -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

217
README.md
View File

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

View 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, '');
};

View File

@@ -1,9 +1,6 @@
{
"name": "go-view",
"version": "2.2.2",
"engines": {
"node": ">=12.0"
},
"version": "1.1.6",
"scripts": {
"dev": "vite --host",
"build": "vue-tsc --noEmit && vite build",
@@ -24,8 +21,6 @@
"axios": "^0.27.2",
"color": "^4.2.3",
"crypto-js": "^4.1.1",
"dayjs": "^1.11.7",
"dom-helpers": "^5.2.1",
"echarts-liquidfill": "^3.1.0",
"echarts-stat": "^1.2.0",
"echarts-wordcloud": "^2.0.0",
@@ -34,13 +29,13 @@
"html2canvas": "^1.4.1",
"keymaster": "^1.6.2",
"monaco-editor": "^0.33.0",
"naive-ui": "2.34.3",
"naive-ui": "2.33.4",
"pinia": "^2.0.13",
"screenfull": "^6.0.1",
"three": "^0.145.0",
"vue": "^3.2.31",
"vue-demi": "^0.13.1",
"vue-i18n": "^9.2.2",
"vue-i18n": "9.1.9",
"vue-router": "4.0.12",
"vue3-lazyload": "^0.2.5-beta",
"vue3-sketch-ruler": "^1.3.3",
@@ -75,7 +70,7 @@
"sass": "^1.49.11",
"sass-loader": "^12.6.0",
"typescript": "4.6.3",
"vite": "4.2.1",
"vite": "2.9.9",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-importer": "^0.2.5",
"vite-plugin-mock": "^2.9.6",
@@ -83,4 +78,4 @@
"vue-echarts": "^6.0.2",
"vue-tsc": "^0.28.10"
}
}
}

2916
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

10
preview.yml Normal file
View File

@@ -0,0 +1,10 @@
# preview.yml
autoOpen: true # 打开工作空间时是否自动开启所有应用的预览
apps:
- port: 3000 # 应用的端口
run: npm i --registry=https://registry.npmmirror.com && npm run dev # 应用的启动命令
command: # 使用此命令启动服务且不执行run
root: ./ # 应用的启动目录
name: GoView # 应用名称
description: 开源、精美、便捷的「数据可视化」低代码开发平台 # 应用描述
autoOpen: true # 打开工作空间时是否自动开启预览(优先级高于根级 autoOpen)

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 KiB

View File

@@ -17,7 +17,7 @@
import { NConfigProvider } from 'naive-ui'
import { GoAppProvider } from '@/components/GoAppProvider'
import { I18n } from '@/components/I18n'
import { 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()

View File

@@ -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 = []

View File

@@ -1,82 +1,29 @@
import axios, { AxiosResponse, AxiosRequestConfig, Axios } from 'axios'
import { ResultEnum, ModuleTypeEnum } from "@/enums/httpEnum"
import { PageEnum, ErrorPageNameMap } from "@/enums/pageEnum"
import { StorageEnum } from '@/enums/storageEnum'
import { axiosPre } from '@/settings/httpSetting'
import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'
import { redirectErrorPage, getLocalStorage, routerTurnByName, isPreview } from '@/utils'
import { fetchAllowList } from './axios.config'
import includes from 'lodash/includes'
export interface MyResponseType<T> {
code: ResultEnum
data: T
message: string
}
export interface MyRequestInstance extends Axios {
<T = any>(config: AxiosRequestConfig): Promise<MyResponseType<T>>
}
import axios, { AxiosResponse, AxiosRequestConfig } from 'axios'
import { ResultEnum } from "@/enums/httpEnum"
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,
}) as unknown as MyRequestInstance
})
axiosInstance.interceptors.request.use(
(config: AxiosRequestConfig) => {
// 白名单校验
if (includes(fetchAllowList, config.url)) return config
// 获取 token
const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
// 重新登录
if (!info) {
routerTurnByName(PageEnum.BASE_LOGIN_NAME)
return config
}
const userInfo = info[SystemStoreEnum.USER_INFO]
config.headers = {
...config.headers,
[userInfo[SystemStoreUserInfoEnum.TOKEN_NAME] || 'token']: userInfo[SystemStoreUserInfoEnum.USER_TOKEN] || ''
}
return config
},
(err: AxiosRequestConfig) => {
Promise.reject(err)
(error: AxiosRequestConfig) => {
Promise.reject(error)
}
)
// 响应拦截器
axiosInstance.interceptors.response.use(
(res: AxiosResponse) => {
// 预览页面错误不进行处理
if (isPreview()) {
return Promise.resolve(res.data)
}
const { code } = res.data as { code: number }
if (code === undefined || code === null) return Promise.resolve(res.data)
// 成功
if (code === ResultEnum.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) => {

View File

@@ -9,16 +9,16 @@ import {
} from '@/enums/httpEnum'
import type { RequestGlobalConfigType, RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
export const get = <T = any>(url: string, params?: object) => {
return axiosInstance<T>({
export const get = (url: string, params?: object) => {
return axiosInstance({
url: url,
method: RequestHttpEnum.GET,
params: params,
params: params
})
}
export const post = <T = any>(url: string, data?: object, headersType?: string) => {
return axiosInstance<T>({
export const post = (url: string, data?: object, headersType?: string) => {
return axiosInstance({
url: url,
method: RequestHttpEnum.POST,
data: data,
@@ -28,8 +28,8 @@ export const post = <T = any>(url: string, data?: object, headersType?: string)
})
}
export const patch = <T = any>(url: string, data?: object, headersType?: string) => {
return axiosInstance<T>({
export const patch = (url: string, data?: object, headersType?: string) => {
return axiosInstance({
url: url,
method: RequestHttpEnum.PATCH,
data: data,
@@ -39,8 +39,8 @@ export const patch = <T = any>(url: string, data?: object, headersType?: string)
})
}
export const put = <T = any>(url: string, data?: object, headersType?: ContentTypeEnum) => {
return axiosInstance<T>({
export const put = (url: string, data?: object, headersType?: ContentTypeEnum) => {
return axiosInstance({
url: url,
method: RequestHttpEnum.PUT,
data: data,
@@ -50,8 +50,8 @@ export const put = <T = any>(url: string, data?: object, headersType?: ContentTy
})
}
export const del = <T = any>(url: string, params?: object) => {
return axiosInstance<T>({
export const del = (url: string, params?: object) => {
return axiosInstance({
url: url,
method: RequestHttpEnum.DELETE,
params
@@ -82,11 +82,11 @@ export const http = (type?: RequestHttpEnum) => {
}
const prefix = 'javascript:'
// 对输入字符进行转义处理
export const translateStr = (target: string | Record<any, any>) => {
export const translateStr = (target: string | object) => {
if (typeof target === 'string') {
if (target.startsWith(prefix)) {
const funcStr = target.split(prefix)[1]
let result
let result;
try {
result = new Function(`${funcStr}`)()
} catch (error) {
@@ -100,8 +100,8 @@ export const translateStr = (target: string | Record<any, any>) => {
}
for (const key in target) {
if (Object.prototype.hasOwnProperty.call(target, key)) {
const subTarget = target[key]
target[key] = translateStr(subTarget)
const subTarget = (target as any)[key];
(target as any)[key] = translateStr(subTarget)
}
}
return target
@@ -172,9 +172,7 @@ export const customizeHttp = (targetParams: RequestConfigType, globalParams: Req
case RequestBodyEnum.JSON:
headers['Content-Type'] = ContentTypeEnum.JSON
//json对象也能使用'javasctipt:'来动态拼接参数
data = translateStr(targetRequestParams.Body['json'])
if(typeof data === 'string') data = JSON.parse(data)
data = translateStr(JSON.parse(targetRequestParams.Body['json']))
// json 赋值给 data
break

View File

@@ -1,100 +0,0 @@
{
"nodes": [
{
"id": "0",
"name": "Myriel",
"symbolSize": "@integer(0, 50)",
"x": -266.82776,
"y": 299.6904,
"value": "@integer(0, 50)",
"category": 3
},
{
"id": "1",
"name": "Napoleon",
"symbolSize": "@integer(0, 50)",
"x": -418.08344,
"y": 446.8853,
"value": "@integer(0, 50)",
"category": 5
},
{
"id": "2",
"name": "MlleBaptistine",
"symbolSize": "@integer(0, 50)",
"x": -212.76357,
"y": 245.29176,
"value": "@integer(0, 50)",
"category": 1
},
{
"id": "3",
"name": "MmeMagloire",
"symbolSize": "@integer(0, 50)",
"x": -242.82404,
"y": 235.26283,
"value": "@integer(0, 50)",
"category": 1
},
{
"id": "4",
"name": "CountessDeLo",
"symbolSize": "@integer(0, 50)",
"x": -379.30386,
"y": 429.06424,
"value": "@integer(0, 50)",
"category": 0
}
],
"links": [
{
"source": "1",
"target": "@integer(2, 4)"
},
{
"source": "2",
"target": "@integer(3, 4)"
},
{
"source": "3",
"target": "@integer(0, 2)"
},
{
"source": "3",
"target": "@integer(0, 1)"
},
{
"source": "4",
"target": "@integer(0, 3)"
}
],
"categories": [
{
"name": "A"
},
{
"name": "B"
},
{
"name": "C"
},
{
"name": "D"
},
{
"name": "E"
},
{
"name": "F"
},
{
"name": "G"
},
{
"name": "H"
},
{
"name": "I"
}
]
}

View File

@@ -19,8 +19,6 @@ export const capsuleUrl = '/mock/capsule'
export const wordCloudUrl = '/mock/wordCloud'
export const treemapUrl = '/mock/treemap'
export const threeEarth01Url = '/mock/threeEarth01Data'
export const sankeyUrl = '/mock/sankey'
export const graphUrl = '/mock/graphData'
const mockObject: MockMethod[] = [
{
@@ -105,16 +103,6 @@ const mockObject: MockMethod[] = [
method: RequestHttpEnum.GET,
response: () => test.threeEarth01Data
},
{
url: sankeyUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchSankey
},
{
url: graphUrl,
method: RequestHttpEnum.GET,
response: () => test.graphData
},
]
export default mockObject

View File

@@ -1,86 +0,0 @@
{
"label": [
{
"name": "a"
},
{
"name": "b"
},
{
"name": "a1"
},
{
"name": "a2"
},
{
"name": "b1"
},
{
"name": "b2"
}
],
"links": [
{
"source": "a",
"target": "a1",
"value": "@integer(0, 10)"
},
{
"source": "a",
"target": "a2",
"value": "@integer(0, 10)"
},
{
"source": "b",
"target": "b1",
"value": "@integer(0, 10)"
},
{
"source": "a",
"target": "b1",
"value": "@integer(0, 10)"
},
{
"source": "b1",
"target": "a1",
"value": "@integer(0, 10)"
},
{
"source": "b1",
"target": "b2",
"value": "@integer(0, 10)"
}
],
"levels": [
{
"depth": 0,
"itemStyle": {
"color": "#decbe4"
},
"lineStyle": {
"color": "source",
"opacity": 0.9
}
},
{
"depth": 1,
"itemStyle": {
"color": "#b3cde3"
},
"lineStyle": {
"color": "source",
"opacity": 0.6
}
},
{
"depth": 2,
"itemStyle": {
"color": "#ccebc5"
},
"lineStyle": {
"color": "source",
"opacity": 0.6
}
}
]
}

View File

@@ -2,8 +2,6 @@ import heatmapJson from './heatMapData.json'
import scatterJson from './scatter.json'
import mapJson from './map.json'
import tTreemapJson from './treemap.json'
import sankeyJson from './sankey.json'
import graphDataJson from './graph.json'
export default {
// 单图表
@@ -12,8 +10,8 @@ export default {
status: 200,
msg: '请求成功',
data: {
dimensions: ['product', 'dataOne'],
'source|20': [
dimensions: ['product', 'dataOne'],
'source|50': [
{
product: '@name',
'dataOne|0-900': 3
@@ -28,8 +26,12 @@ export default {
msg: '请求成功',
data: {
dimensions: ['name', 'value'],
"source|2-5": [
{ 'name|+1': ["厦门","福州","北京","上海","新疆","郑州","湖南","内蒙古"], 'value|0-40': 20 },
source: [
{ name: '厦门', 'value|0-40': 20 },
{ name: '南阳', 'value|20-60': 40 },
{ name: '北京', 'value|40-80': 60 },
{ name: '上海', 'value|60-100': 80 },
{ name: '新疆', value: 100 }
]
}
},
@@ -39,13 +41,12 @@ export default {
status: 200,
msg: '请求成功',
data: {
dimensions: ['product', 'dataOne', 'dataTwo', 'dataThree'],
'source|20': [
dimensions: ['product', 'dataOne', 'dataTwo'],
'source|50': [
{
product: '@name',
'dataOne|100-900': 3,
'dataTwo|100-900': 3,
'dataThree|100-900': 3
'dataTwo|100-900': 3
}
]
}
@@ -221,19 +222,5 @@ export default {
'endArray|10': [{ name: '@name', N: '@integer(10, 100)', E: '@integer(10, 100)' }]
}
]
},
// 桑基图
fetchSankey: {
code: 0,
status: 200,
msg: '请求成功',
data: sankeyJson
},
// 关系图
graphData: {
code: 0,
status: 200,
msg: '请求成功',
data: graphDataJson
},
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 377 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -14,19 +14,16 @@
</template>
<script lang="ts" setup>
import { useI18n } from "vue-i18n";
import { useLangStore } from '@/store/modules/langStore/langStore'
import { langList } from '@/i18n/index'
import { LangEnum } from '@/enums/styleEnum'
import { icon } from '@/plugins'
const { LanguageIcon } = icon.ionicons5
const { locale } = useI18n();
const langStore = useLangStore()
const options = langList
const handleSelect = (key: LangEnum) => {
locale.value = key;
langStore.changeLang(key)
}
</script>

View File

@@ -1,5 +1,5 @@
<template>
<n-modal v-model:show="modelShowRef" @afterLeave="closeHandle">
<n-modal v-model:show="modelShow" @afterLeave="closeHandle">
<n-list bordered class="go-system-info">
<template #header>
<n-space justify="space-between">
@@ -51,10 +51,10 @@ const props = defineProps({
const emit = defineEmits(['update:modelShow'])
const { HelpOutlineIcon, CloseIcon } = icon.ionicons5
const modelShowRef = ref(false)
const modelShow = ref(false)
watch(() => props.modelShow, (newValue) => {
modelShowRef.value = newValue
modelShow.value = newValue
})
const closeHandle = () => {

View File

@@ -1,5 +1,5 @@
<template>
<n-modal v-model:show="modelShowRef" @afterLeave="closeHandle">
<n-modal v-model:show="modelShow" @afterLeave="closeHandle">
<n-list bordered class="go-system-setting">
<template #header>
<n-space justify="space-between">
@@ -82,7 +82,7 @@ const props = defineProps({
const emit = defineEmits(['update:modelShow'])
const { HelpOutlineIcon, CloseIcon } = icon.ionicons5
const settingStore = useSettingStore()
const modelShowRef = ref(false)
const modelShow = ref(false)
const list = reactive<ListType[]>([
{
@@ -168,7 +168,7 @@ const list = reactive<ListType[]>([
])
watch(() => props.modelShow, (newValue) => {
modelShowRef.value = newValue
modelShow.value = newValue
})
const closeHandle = () => {

View File

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

View File

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

View File

@@ -1,31 +0,0 @@
<template>
<img class="list-img" v-lazy="imageInfo" alt="图表图片" />
</template>
<script setup lang="ts">
import { ref, PropType, watch } from 'vue'
import { fetchImages } from '@/packages'
import { ConfigType } from '@/packages/index.d'
const props = defineProps({
chartConfig: {
type: Object as PropType<ConfigType>,
required: true
}
})
const imageInfo = ref('')
// 获取图片
const fetchImageUrl = async () => {
imageInfo.value = await fetchImages(props.chartConfig)
}
watch(
() => props.chartConfig.key,
() => fetchImageUrl(),
{
immediate: true
}
)
</script>

View File

@@ -1,45 +0,0 @@
<template>
<n-radio-group :value="props.modelValue || INHERIT_VALUE" @update:value="handleChange">
<n-space>
<n-tooltip :show-arrow="false" trigger="hover" v-for="item in rendererList" :key="item.value">
<template #trigger>
<n-radio :value="item.value">
{{ item.value }}
</n-radio>
</template>
{{ item.desc }}
</n-tooltip>
</n-space>
</n-radio-group>
</template>
<script setup lang="ts">
import { type EchartsRenderer } from '@/settings/chartThemes'
const props = defineProps<{ modelValue?: EchartsRenderer; includeInherit?: boolean }>()
const emits = defineEmits(['update:modelValue'])
const INHERIT_VALUE = 'inherit'
const handleChange = (val: EchartsRenderer & typeof INHERIT_VALUE) => {
emits('update:modelValue', val === INHERIT_VALUE ? undefined : val)
}
const rendererList = [
{
value: 'svg',
desc: '在缩放场景下具有更好的表现'
},
{
value: 'canvas',
desc: '数据量较大(经验判断 > 1k、较多交互时建议选择'
},
...(props.includeInherit
? [
{
value: INHERIT_VALUE,
desc: '默认继承全局配置'
}
]
: [])
]
</script>

View File

@@ -1,34 +1,4 @@
<template>
<collapse-item name="渲染器">
<setting-item-box :alone="true">
<template #name>
<n-text>全局</n-text>
<n-tooltip trigger="hover">
<template #trigger>
<n-icon size="21" :depth="3">
<help-outline-icon></help-outline-icon>
</n-icon>
</template>
<n-text>所有echarts图表组件默认都将采用所选的渲染器进行渲染</n-text>
</n-tooltip>
</template>
<EchartsRendererSetting v-model="themeSetting.renderer" />
</setting-item-box>
<setting-item-box :alone="true">
<template #name>
<n-text>当前</n-text>
<n-tooltip trigger="hover">
<template #trigger>
<n-icon size="21" :depth="3">
<help-outline-icon></help-outline-icon>
</n-icon>
</template>
<n-text>仅当前组件采用指定渲染器渲染</n-text>
</n-tooltip>
</template>
<EchartsRendererSetting v-model="optionData.renderer" includeInherit />
</setting-item-box>
</collapse-item>
<collapse-item v-if="title" name="标题">
<template #header>
<n-switch v-model:value="title.show" size="small"></n-switch>
@@ -313,11 +283,6 @@ import { PropType, computed } from 'vue'
import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
import { axisConfig } from '@/packages/chartConfiguration/echarts/index'
import { CollapseItem, SettingItemBox, SettingItem, GlobalSettingPosition } from '@/components/Pages/ChartItemSetting'
import { icon } from '@/plugins'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import EchartsRendererSetting from './EchartsRendererSetting.vue'
const { HelpOutlineIcon } = icon.ionicons5
const props = defineProps({
optionData: {
@@ -331,12 +296,6 @@ const props = defineProps({
}
})
const chartEditStore = useChartEditStore()
const themeSetting = computed(() => {
const chartThemeSetting = chartEditStore.getEditCanvasConfig.chartThemeSetting
return chartThemeSetting
})
const title = computed(() => {
return props.optionData.title
})

View File

@@ -36,7 +36,7 @@
</div>
<div class="model-footer">
中国色列表来自于
<n-a href="http://zhongguose.com" target="_blank">http://zhongguose.com</n-a>
<n-a href="http://zhongguose.com">http://zhongguose.com</n-a>
</div>
</div>
</n-modal>
@@ -157,7 +157,6 @@ $height: 85vh;
}
}
.model-footer {
z-index: 1;
text-align: end;
}
}

View File

@@ -12,9 +12,7 @@ export enum DragKeyEnum {
// 不同页面保存操作
export enum SavePageEnum {
CHART = 'SaveChart',
CHART_TO_PREVIEW = 'ChartToPreview',
JSON = 'SaveJSON',
CLOSE = 'close'
JSON = 'SaveJSON'
}
// 操作枚举
@@ -48,6 +46,7 @@ export enum MenuEnum {
UN_GROUP = 'unGroup',
// 后退
BACK = 'back',
// 前进
FORWORD = 'forward',
// 保存
SAVE = 'save',
@@ -68,8 +67,7 @@ export enum WinKeyboard {
ALT = ' alt',
CTRL_SOURCE_KEY = 'control',
SHIFT_SOURCE_KEY = 'shift',
ALT_SOURCE_KEY = 'alt',
SPACE = 'Space'
ALT_SOURCE_KEY = 'alt'
}
// Mac 键盘枚举
@@ -80,18 +78,5 @@ export enum MacKeyboard {
ALT = '⌥',
CTRL_SOURCE_KEY = '⌘',
SHIFT_SOURCE_KEY = '⇧',
ALT_SOURCE_KEY = '⌥',
SPACE = 'Space'
}
// 同步状态枚举
export enum SyncEnum {
// 等待
PENDING,
// 开始
START,
// 成功
SUCCESS,
// 失败
FAILURE
ALT_SOURCE_KEY = '⌥'
}

View File

@@ -1,59 +0,0 @@
// 基础事件类型(vue不加 on)
export enum BaseEvent {
// 点击
ON_CLICK = 'click',
// 双击
ON_DBL_CLICK = 'dblclick',
// 移入
ON_MOUSE_ENTER = 'mouseenter',
// 移出
ON_MOUSE_LEAVE = 'mouseleave'
}
// 组件交互回调事件
export enum InteractEvents {
INTERACT_ON = 'interactOn',
INTERACT_COMPONENT_ID = 'interactComponentId',
INTERACT_FN = 'interactFn'
}
// 全局组件交互回调事件触发的类型(当然可以自定义名称)
export enum InteractEventOn {
CLICK = 'click',
CHANGE = 'change'
}
// 确定交互组件触发类型 key名称
export const COMPONENT_INTERACT_EVENT_KET = 'componentInteractEventKey'
// 交互式组件的触发配置
export type InteractActionsType = {
interactType: InteractEventOn
interactName: string
componentEmitEvents: { [T: string]: { value: any; label: string }[] }
}
// vue3 生命周期事件
export enum EventLife {
// 渲染之后
VNODE_MOUNTED = 'vnodeMounted',
// 渲染之前
VNODE_BEFORE_MOUNT = 'vnodeBeforeMount'
}
// 内置字符串函数对象列表
export const excludeParseEventKeyList = [
EventLife.VNODE_BEFORE_MOUNT,
EventLife.VNODE_MOUNTED,
BaseEvent.ON_CLICK,
BaseEvent.ON_DBL_CLICK,
BaseEvent.ON_MOUSE_ENTER,
BaseEvent.ON_MOUSE_LEAVE,
//过滤器
'filter'
]
// 内置字符串函数键值列表
export const excludeParseEventValueList = [
// 请求里的函数语句
'javascript:'
]

View File

@@ -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
}
// 数据相关
@@ -33,13 +28,9 @@ export enum RequestContentTypeEnum {
SQL = 1
}
// 头部
export enum RequestHttpHeaderEnum {
TOKEN = 'Token',
COOKIE = 'Cookie'
}
// 请求方法
/**
* @description: 请求方法
*/
export enum RequestHttpEnum {
GET = 'get',
POST = 'post',
@@ -120,7 +111,9 @@ export type RequestParams = {
}
}
// 常用的contentTyp类型
/**
* @description: 常用的contentTyp类型
*/
export enum ContentTypeEnum {
// json
JSON = 'application/json;charset=UTF-8',

View File

@@ -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',

View File

@@ -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',
// 当前选择的主题

View File

@@ -2,8 +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'
export * from '@/hooks/useChartInteract.hook'
export * from '@/hooks/useLang.hook'

View File

@@ -1,26 +0,0 @@
import { inject, type Ref } from 'vue'
import { EchartsRenderer } from '@/settings/chartThemes'
import { SCALE_KEY } from '@/views/preview/hooks/useScale.hook'
import { use } from 'echarts/core'
import { CanvasRenderer, SVGRenderer } from 'echarts/renderers'
use([CanvasRenderer, SVGRenderer])
type InitOptions = {
renderer: EchartsRenderer
devicePixelRatio?: number
}
// 获取需要给当前echarts组件设置什么初始值
export function useCanvasInitOptions(option: any, themeSetting: any) {
const renderer = option.renderer || themeSetting.renderer
const initOptions: InitOptions = { renderer }
const scaleRef = inject<Ref<{ width: number; height: number }>>(SCALE_KEY) || { value: { width: 1, height: 1 } }
if (renderer === 'canvas') {
initOptions.devicePixelRatio = Math.ceil(
Math.max(window.devicePixelRatio, scaleRef.value.width, scaleRef.value.height)
)
}
return initOptions
}

View File

@@ -1,123 +1,111 @@
import { ref, toRefs, toRaw, watch } 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'
import { isPreview, newFunctionHandle, intervalUnitHandle } from '@/utils'
import { setOption } from '@/packages/public/chart'
// 获取类型
type ChartEditStoreType = typeof useChartEditStore
/**
* setdata 数据监听与更改
* @param targetComponent
* @param useChartEditStore 若直接引会报错,只能动态传递
* @param updateCallback 自定义更新函数
*/
export const useChartDataFetch = (
targetComponent: CreateComponentType,
useChartEditStore: ChartEditStoreType,
updateCallback?: (...args: any) => any
) => {
const vChartRef = ref<typeof VChart | null>(null)
let fetchInterval: any = 0
// 数据池
const { addGlobalDataInterface } = useChartDataPondFetch()
// 组件类型
const { chartFrame } = targetComponent.chartConfig
// eCharts 组件配合 vChart 库更新方式
const echartsUpdateHandle = (dataset: any) => {
if (chartFrame === ChartFrameEnum.ECHARTS) {
if (vChartRef.value) {
setOption(vChartRef.value, { dataset: dataset })
}
}
}
const requestIntervalFn = () => {
const chartEditStore = useChartEditStore()
// 全局数据
const {
requestOriginUrl,
requestIntervalUnit: globalUnit,
requestInterval: globalRequestInterval
} = toRefs(chartEditStore.getRequestGlobalConfig)
// 目标组件
const {
requestDataType,
requestUrl,
requestIntervalUnit: targetUnit,
requestInterval: targetInterval
} = toRefs(targetComponent.request)
// 非请求类型
if (requestDataType.value !== RequestDataTypeEnum.AJAX) return
try {
// 处理地址
// @ts-ignore
if (requestUrl?.value) {
// requestOriginUrl 允许为空
const completePath = requestOriginUrl && requestOriginUrl.value + requestUrl.value
if (!completePath) return
clearInterval(fetchInterval)
const fetchFn = async () => {
const res = await customizeHttp(toRaw(targetComponent.request), toRaw(chartEditStore.getRequestGlobalConfig))
if (res) {
try {
const filter = targetComponent.filter
const { data } = res
echartsUpdateHandle(newFunctionHandle(data, res, filter))
// 更新回调函数
if (updateCallback) {
updateCallback(newFunctionHandle(data, res, filter))
}
} catch (error) {
console.error(error)
}
}
}
// 普通初始化与组件交互处理监听
watch(
() => targetComponent.request,
() => {
fetchFn()
},
{
immediate: true,
deep: true
}
)
// 定时时间
const time = targetInterval && targetInterval.value ? targetInterval.value : globalRequestInterval.value
// 单位
const unit = targetInterval && targetInterval.value ? targetUnit.value : globalUnit.value
// 开启轮询
if (time) fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit))
}
// eslint-disable-next-line no-empty
} catch (error) {
console.log(error)
}
}
if (isPreview()) {
// 判断是否是数据池类型
targetComponent.request.requestDataType === RequestDataTypeEnum.Pond
? addGlobalDataInterface(targetComponent, useChartEditStore, updateCallback || echartsUpdateHandle)
: requestIntervalFn()
}
return { vChartRef }
}
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'
import { isPreview, newFunctionHandle, intervalUnitHandle } from '@/utils'
// 获取类型
type ChartEditStoreType = typeof useChartEditStore
/**
* setdata 数据监听与更改
* @param targetComponent
* @param useChartEditStore 若直接引会报错,只能动态传递
* @param updateCallback 自定义更新函数
*/
export const useChartDataFetch = (
targetComponent: CreateComponentType,
useChartEditStore: ChartEditStoreType,
updateCallback?: (...args: any) => any
) => {
const vChartRef = ref<typeof VChart | null>(null)
let fetchInterval: any = 0
// 数据池
const { addGlobalDataInterface } = useChartDataPondFetch()
// 组件类型
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()
// 全局数据
const {
requestOriginUrl,
requestIntervalUnit: globalUnit,
requestInterval: globalRequestInterval
} = toRefs(chartEditStore.getRequestGlobalConfig)
// 目标组件
const {
requestDataType,
requestUrl,
requestIntervalUnit: targetUnit,
requestInterval: targetInterval
} = toRefs(targetComponent.request)
// 非请求类型
if (requestDataType.value !== RequestDataTypeEnum.AJAX) return
try {
// 处理地址
// @ts-ignore
if (requestUrl?.value) {
// requestOriginUrl 允许为空
const completePath = requestOriginUrl && requestOriginUrl.value + requestUrl.value
if (!completePath) return
clearInterval(fetchInterval)
const fetchFn = async () => {
const res = await customizeHttp(toRaw(targetComponent.request), toRaw(chartEditStore.getRequestGlobalConfig))
if (res) {
try {
const filter = targetComponent.filter
echartsUpdateHandle(newFunctionHandle(res?.data, res, filter))
// 更新回调函数
if (updateCallback) {
updateCallback(newFunctionHandle(res?.data, res, filter))
}
} catch (error) {
console.error(error)
}
}
}
// 立即调用
fetchFn()
// 定时时间
const time = targetInterval && targetInterval.value ? targetInterval.value : globalRequestInterval.value
// 单位
const unit = targetInterval && targetInterval.value ? targetUnit.value : globalUnit.value
// 开启轮询
if (time) fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit))
}
// eslint-disable-next-line no-empty
} catch (error) {
console.log(error)
}
}
if (isPreview()) {
// 判断是否是数据池类型
targetComponent.request.requestDataType === RequestDataTypeEnum.Pond
? addGlobalDataInterface(targetComponent, useChartEditStore, updateCallback || echartsUpdateHandle)
: requestIntervalFn()
}
return { vChartRef }
}

View File

@@ -1,40 +0,0 @@
import { toRefs } from 'vue'
import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
// 获取类型
type ChartEditStoreType = typeof useChartEditStore
// Params 参数修改触发 api 更新图表请求
export const useChartInteract = (
chartConfig: CreateComponentType,
useChartEditStore: ChartEditStoreType,
param: { [T: string]: any },
interactEventOn: string
) => {
const chartEditStore = useChartEditStore()
const { interactEvents } = chartConfig.events
const fnOnEvent = interactEvents.filter(item => {
return item.interactOn === interactEventOn
})
if (fnOnEvent.length === 0) return
fnOnEvent.forEach(item => {
const index = chartEditStore.fetchTargetIndex(item.interactComponentId)
if (index === -1) return
const { Params, Header } = toRefs(chartEditStore.componentList[index].request.requestParams)
Object.keys(item.interactFn).forEach(key => {
if (Params.value[key]) {
Params.value[key] = param[item.interactFn[key]]
}
if (Header.value[key]) {
Header.value[key] = param[item.interactFn[key]]
}
})
})
}
// 联动事件触发的 type 变更时,清除当前绑定内容
export const clearInteractEvent = (chartConfig: CreateComponentType) => {
}

View File

@@ -1,5 +1,4 @@
import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
import { EventLife } from '@/enums/eventEnum'
import { CreateComponentType, CreateComponentGroupType, EventLife, BaseEvent } from '@/packages/index.d'
import * as echarts from 'echarts'
// 所有图表组件集合对象

View File

@@ -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({})
if (res && res.code === ResultEnum.SUCCESS) {
systemStore.setItem(SystemStoreEnum.FETCH_INFO, {
OSSUrl: res.data?.bucketURL
})
}
}
// 执行
getOssUrl()
}

View File

@@ -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
}

View File

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

View File

@@ -1,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',

View File

@@ -23,8 +23,6 @@ export const langList = [
]
const i18n = createI18n({
legacy: false,
globalInjection:true,
locale: langStorage?.lang || lang,
fallbackLocale: langStorage?.lang || lang,
messages: {

View File

@@ -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
}

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
<template>
<n-layout-header bordered class="go-header">
<header class="go-header-box" :class="{ 'is-project': isProject }">
<header class="go-header-box">
<div class="header-item left">
<n-space>
<slot name="left"></slot>
@@ -23,29 +23,17 @@
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import { GoThemeSelect } from '@/components/GoThemeSelect'
import { GoLangSelect } from '@/components/GoLangSelect'
import { ThemeColorSelect } from '@/components/Pages/ThemeColorSelect'
import { PageEnum } from '@/enums/pageEnum'
const route = useRoute()
const isProject = computed(() => {
return route.fullPath === PageEnum.BASE_HOME_ITEMS
})
</script>
<style lang="scss" scoped>
$min-width: 520px;
$min-width: 400px;
@include go(header) {
&-box {
display: grid;
grid-template-columns: repeat(3, 33%);
&.is-project {
grid-template-columns: none;
}
grid-template-columns: repeat(3, 33.33%);
.header-item {
display: flex;
align-items: center;
@@ -61,7 +49,7 @@ $min-width: 520px;
}
}
height: $--header-height;
padding: 0 20px 0 60px;
padding: 0 60px;
}
}
</style>

View File

@@ -1,9 +1,13 @@
<template>
<router-view>
<template #default="{ Component, route }">
<component v-if="route.meta.noKeepAlive" :is="Component"></component>
<component
v-if="route.noKeepAlive"
:is="Component"
:key="route.fullPath"
></component>
<keep-alive v-else>
<component :is="Component"></component>
<component :is="Component" :key="route.fullPath"></component>
</keep-alive>
</template>
</router-view>

View File

@@ -1,14 +1,14 @@
<template>
<router-view #default="{ Component, route }">
<transition name="fade" mode="out-in" appear>
<component
v-if="route.meta.noKeepAlive"
:is="Component"
:key="route.fullPath"
></component>
<keep-alive v-else>
<component :is="Component" :key="route.fullPath"></component>
</keep-alive>
</transition>
</router-view>
</template>
<template>
<router-view #default="{ Component, route }">
<transition name="fade" mode="out-in" appear>
<component
v-if="route.noKeepAlive"
:is="Component"
:key="route.fullPath"
></component>
<keep-alive v-else>
<component :is="Component" :key="route.fullPath"></component>
</keep-alive>
</transition>
</router-view>
</template>

View File

@@ -3,7 +3,7 @@ import App from './App.vue'
import router, { setupRouter } from '@/router'
import i18n from '@/i18n/index'
import { setupStore } from '@/store'
import { setupNaive, setupDirectives, setupCustomComponents, initFunction } from '@/plugins'
import { setupNaive, setupDirectives, setupCustomComponents } from '@/plugins'
import { GoAppProvider } from '@/components/GoAppProvider/index'
import { setHtmlTheme } from '@/utils'
@@ -53,7 +53,4 @@ async function appInit() {
window['$vue'] = app
}
appInit().then(() => {
initFunction()
})
void appInit()

View File

@@ -1,3 +1,4 @@
import image from '@/assets/images/chart/charts/bar_x.png'
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
@@ -10,5 +11,5 @@ export const BarCommonConfig: ConfigType = {
categoryName: ChatCategoryEnumName.BAR,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.ECHARTS,
image: 'bar_x.png'
image
}

View File

@@ -1,14 +1,19 @@
<template>
<v-chart ref="vChartRef" :init-options="initOptions" :theme="themeColor" :option="option" :manual-update="isPreview()"
<v-chart
ref="vChartRef"
:theme="themeColor"
:option="option"
:manual-update="isPreview()"
:update-options="{
replaceMerge: replaceMergeArr
}" autoresize></v-chart>
}"
autoresize
></v-chart>
</template>
<script setup lang="ts">
import { ref, nextTick, computed, watch, PropType } from 'vue'
import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { BarChart } from 'echarts/charts'
@@ -20,7 +25,6 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore
import { isPreview } from '@/utils'
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import isObject from 'lodash/isObject'
import cloneDeep from 'lodash/cloneDeep'
const props = defineProps({
themeSetting: {
@@ -37,8 +41,6 @@ const props = defineProps({
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
use([DatasetComponent, CanvasRenderer, BarChart, GridComponent, TooltipComponent, LegendComponent])
const replaceMergeArr = ref<string[]>()
@@ -55,23 +57,11 @@ watch(
if (!isObject(newData) || !('dimensions' in newData)) return
if (Array.isArray(newData?.dimensions)) {
const seriesArr = []
// 对oldData进行判断防止传入错误数据之后对旧维度判断产生干扰
// 此处计算的是dimensions的Y轴维度若是dimensions.length为0或1则默认为1排除X轴维度干扰
const oldDimensions = Array.isArray(oldData?.dimensions)&&oldData.dimensions.length >= 1 ? oldData.dimensions.length : 1;
const newDimensions = newData.dimensions.length >= 1 ? newData.dimensions.length : 1;
const dimensionsGap = newDimensions - oldDimensions;
if (dimensionsGap < 0) {
props.chartConfig.option.series.splice(newDimensions - 1)
} else if (dimensionsGap > 0) {
if(!oldData || !oldData?.dimensions || !Array.isArray(oldData?.dimensions) || !oldData?.dimensions.length ) {
props.chartConfig.option.series=[]
}
for (let i = 0; i < dimensionsGap; i++) {
seriesArr.push(cloneDeep(seriesItem))
}
props.chartConfig.option.series.push(...seriesArr)
for (let i = 0; i < newData.dimensions.length - 1; i++) {
seriesArr.push(seriesItem)
}
replaceMergeArr.value = ['series']
props.chartConfig.option.series = seriesArr
nextTick(() => {
replaceMergeArr.value = []
})

View File

@@ -1,3 +1,4 @@
import image from '@/assets/images/chart/charts/bar_y.png'
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
@@ -10,5 +11,5 @@ export const BarCrossrangeConfig: ConfigType = {
categoryName: ChatCategoryEnumName.BAR,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.ECHARTS,
image: 'bar_y.png'
image
}

View File

@@ -1,7 +1,6 @@
<template>
<v-chart
ref="vChartRef"
:init-options="initOptions"
:theme="themeColor"
:option="option"
:manual-update="isPreview()"
@@ -15,7 +14,6 @@
<script setup lang="ts">
import { ref, nextTick, computed, watch, PropType } from 'vue'
import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { BarChart } from 'echarts/charts'
@@ -26,7 +24,6 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore
import { isPreview } from '@/utils'
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import isObject from 'lodash/isObject'
import cloneDeep from 'lodash/cloneDeep'
const props = defineProps({
themeSetting: {
@@ -43,8 +40,6 @@ const props = defineProps({
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
use([DatasetComponent, CanvasRenderer, BarChart, GridComponent, TooltipComponent, LegendComponent])
const replaceMergeArr = ref<string[]>()
@@ -62,7 +57,7 @@ watch(
if (Array.isArray(newData?.dimensions)) {
const seriesArr = []
for (let i = 0; i < newData.dimensions.length - 1; i++) {
seriesArr.push(cloneDeep(seriesItem))
seriesArr.push(seriesItem)
}
replaceMergeArr.value = ['series']
props.chartConfig.option.series = seriesArr

View File

@@ -1,3 +1,4 @@
import image from '@/assets/images/chart/charts/capsule.png'
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
@@ -10,5 +11,5 @@ export const CapsuleChartConfig: ConfigType = {
categoryName: ChatCategoryEnumName.BAR,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.COMMON,
image: 'capsule.png'
image
}

View File

@@ -111,39 +111,34 @@ watch(
}
)
const calcData = (data: any, type?: string) => {
let cloneConfig = cloneDeep(props.chartConfig.option || {})
state.mergedConfig = cloneConfig
if (type == 'preview') {
cloneConfig.dataset = data
}
calcCapsuleLengthAndLabelData(state.mergedConfig.dataset)
const calcData = (data: any) => {
mergeConfig(props.chartConfig.option)
calcCapsuleLengthAndLabelData()
}
const mergeConfig = (data: any) => {
state.mergedConfig = cloneDeep(data || {})
}
// 数据解析
const calcCapsuleLengthAndLabelData = (dataset: any) => {
try {
const { source } = dataset
if (!source || !source.length) return
const calcCapsuleLengthAndLabelData = () => {
const { source } = state.mergedConfig.dataset
if (!source.length) return
state.capsuleItemHeight = numberSizeHandle(state.mergedConfig.itemHeight)
const capsuleValue = source.map((item: DataProps) => item[state.mergedConfig.dataset.dimensions[1]])
state.capsuleItemHeight = numberSizeHandle(state.mergedConfig.itemHeight)
const capsuleValue = source.map((item: DataProps) => item[state.mergedConfig.dataset.dimensions[1]])
const maxValue = Math.max(...capsuleValue)
const maxValue = Math.max(...capsuleValue)
state.capsuleValue = capsuleValue
state.capsuleValue = capsuleValue
state.capsuleLength = capsuleValue.map((v: any) => (maxValue ? v / maxValue : 0))
state.capsuleLength = capsuleValue.map((v: any) => (maxValue ? v / maxValue : 0))
const oneFifth = maxValue / 5
const oneFifth = maxValue / 5
const labelData = Array.from(new Set(new Array(6).fill(0).map((v, i) => Math.ceil(i * oneFifth))))
const labelData = Array.from(new Set(new Array(6).fill(0).map((v, i) => Math.ceil(i * oneFifth))))
state.labelData = labelData
} catch (error) {
console.warn(error);
}
state.labelData = labelData
}
const numberSizeHandle = (val: string | number) => {
@@ -156,7 +151,7 @@ onMounted(() => {
// 预览
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
calcData(newData, 'preview')
calcData(newData)
})
</script>

View File

@@ -1,6 +1,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'

View File

@@ -1,3 +1,4 @@
import image from '@/assets/images/chart/charts/line.png'
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
@@ -10,5 +11,5 @@ export const LineCommonConfig: ConfigType = {
categoryName: ChatCategoryEnumName.LINE,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.ECHARTS,
image: 'line.png'
image
}

View File

@@ -1,7 +1,6 @@
<template>
<v-chart
ref="vChartRef"
:init-options="initOptions"
:theme="themeColor"
:option="option"
:manual-update="isPreview()"
@@ -16,7 +15,6 @@
<script setup lang="ts">
import { PropType, computed, watch, ref, nextTick } from 'vue'
import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { LineChart } from 'echarts/charts'
@@ -43,8 +41,6 @@ const props = defineProps({
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
use([DatasetComponent, CanvasRenderer, LineChart, GridComponent, TooltipComponent, LegendComponent])
const replaceMergeArr = ref<string[]>()

View File

@@ -1,3 +1,4 @@
import image from '@/assets/images/chart/charts/line_gradient_single.png'
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
@@ -10,5 +11,5 @@ export const LineGradientSingleConfig: ConfigType = {
categoryName: ChatCategoryEnumName.LINE,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.ECHARTS,
image: 'line_gradient_single.png'
image
}

View File

@@ -1,12 +1,11 @@
<template>
<v-chart ref="vChartRef" :init-options="initOptions" :theme="themeColor" :option="option.value" :manual-update="isPreview()" autoresize>
<v-chart ref="vChartRef" :theme="themeColor" :option="option.value" :manual-update="isPreview()" autoresize>
</v-chart>
</template>
<script setup lang="ts">
import { reactive, watch, PropType } from 'vue'
import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use, graphic } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { LineChart } from 'echarts/charts'
@@ -16,7 +15,7 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore
import { chartColorsSearch, defaultTheme } from '@/settings/chartThemes/index'
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import { useChartDataFetch } from '@/hooks'
import { isPreview, colorGradientCustomMerge} from '@/utils'
import { isPreview } from '@/utils'
const props = defineProps({
themeSetting: {
@@ -33,8 +32,6 @@ const props = defineProps({
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
use([DatasetComponent, CanvasRenderer, LineChart, GridComponent, TooltipComponent, LegendComponent])
const chartEditStore = useChartEditStore()
@@ -48,9 +45,7 @@ watch(
(newColor: keyof typeof chartColorsSearch) => {
try {
if (!isPreview()) {
const themeColor =
colorGradientCustomMerge(chartEditStore.getEditCanvasConfig.chartCustomThemeColorInfo)[newColor] ||
colorGradientCustomMerge(chartEditStore.getEditCanvasConfig.chartCustomThemeColorInfo)[defaultTheme]
const themeColor = chartColorsSearch[newColor] || chartColorsSearch[defaultTheme]
props.chartConfig.option.series.forEach((value: any, index: number) => {
value.areaStyle.color = new graphic.LinearGradient(0, 0, 0, 1, [
{

View File

@@ -1,3 +1,4 @@
import image from '@/assets/images/chart/charts/line_gradient.png'
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
@@ -10,5 +11,5 @@ export const LineGradientsConfig: ConfigType = {
categoryName: ChatCategoryEnumName.LINE,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.ECHARTS,
image: 'line_gradient.png'
image
}

View File

@@ -1,11 +1,10 @@
<template>
<v-chart ref="vChartRef" :init-options="initOptions" :theme="themeColor" :option="option.value" :manual-update="isPreview()" autoresize></v-chart>
<v-chart ref="vChartRef" :theme="themeColor" :option="option.value" :manual-update="isPreview()" autoresize></v-chart>
</template>
<script setup lang="ts">
import { reactive, watch, PropType } from 'vue'
import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use, graphic } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { LineChart } from 'echarts/charts'
@@ -15,7 +14,7 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore
import { chartColorsSearch, defaultTheme } from '@/settings/chartThemes/index'
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import { useChartDataFetch } from '@/hooks'
import { isPreview, colorGradientCustomMerge} from '@/utils'
import { isPreview } from '@/utils'
const props = defineProps({
themeSetting: {
@@ -32,8 +31,6 @@ const props = defineProps({
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
use([DatasetComponent, CanvasRenderer, LineChart, GridComponent, TooltipComponent, LegendComponent])
const chartEditStore = useChartEditStore()
@@ -47,9 +44,7 @@ watch(
(newColor: keyof typeof chartColorsSearch) => {
try {
if (!isPreview()) {
const themeColor =
colorGradientCustomMerge(chartEditStore.getEditCanvasConfig.chartCustomThemeColorInfo)[newColor] ||
colorGradientCustomMerge(chartEditStore.getEditCanvasConfig.chartCustomThemeColorInfo)[defaultTheme]
const themeColor = chartColorsSearch[newColor] || chartColorsSearch[defaultTheme]
props.chartConfig.option.series.forEach((value: any, index: number) => {
value.areaStyle.color = new graphic.LinearGradient(0, 0, 0, 1, [
{

View File

@@ -1,3 +1,4 @@
import image from '@/assets/images/chart/charts/line_linear_single.png'
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
@@ -10,5 +11,5 @@ export const LineLinearSingleConfig: ConfigType = {
categoryName: ChatCategoryEnumName.LINE,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.ECHARTS,
image: 'line_linear_single.png'
image
}

View File

@@ -1,12 +1,11 @@
<template>
<v-chart ref="vChartRef" :init-options="initOptions" :theme="themeColor" :option="option.value" :manual-update="isPreview()" autoresize>
<v-chart ref="vChartRef" :theme="themeColor" :option="option.value" :manual-update="isPreview()" autoresize>
</v-chart>
</template>
<script setup lang="ts">
import { PropType, watch, reactive } from 'vue'
import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { LineChart } from 'echarts/charts'
@@ -16,7 +15,7 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore
import { chartColorsSearch, defaultTheme } from '@/settings/chartThemes/index'
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import { useChartDataFetch } from '@/hooks'
import { isPreview, colorGradientCustomMerge } from '@/utils'
import { isPreview } from '@/utils'
const props = defineProps({
themeSetting: {
@@ -33,8 +32,6 @@ const props = defineProps({
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
use([DatasetComponent, CanvasRenderer, LineChart, GridComponent, TooltipComponent, LegendComponent])
const chartEditStore = useChartEditStore()
@@ -48,9 +45,7 @@ watch(
(newColor: keyof typeof chartColorsSearch) => {
try {
if (!isPreview()) {
const themeColor =
colorGradientCustomMerge(chartEditStore.getEditCanvasConfig.chartCustomThemeColorInfo)[newColor] ||
colorGradientCustomMerge(chartEditStore.getEditCanvasConfig.chartCustomThemeColorInfo)[defaultTheme]
const themeColor = chartColorsSearch[newColor] || chartColorsSearch[defaultTheme]
props.chartConfig.option.series.forEach((value: any) => {
value.lineStyle.shadowColor = themeColor[2]
value.lineStyle.color.colorStops.forEach((v: { color: string }, i: number) => {

View File

@@ -1,4 +1,5 @@
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import image from '@/assets/images/chart/charts/map_amap.png'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
export const MapAmapConfig: ConfigType = {
@@ -10,5 +11,5 @@ export const MapAmapConfig: ConfigType = {
categoryName: ChatCategoryEnumName.MAP,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.COMMON,
image: 'map_amap.png'
image
}

View File

@@ -1,4 +1,5 @@
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import image from '@/assets/images/chart/charts/map.png'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
export const MapBaseConfig: ConfigType = {
@@ -10,5 +11,5 @@ export const MapBaseConfig: ConfigType = {
categoryName: ChatCategoryEnumName.MAP,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.COMMON,
image: 'map.png'
}
image
}

View File

@@ -1,5 +1,5 @@
<template>
<v-chart ref="vChartRef" :init-options="initOptions" :theme="themeColor" :option="option.value" :manual-update="isPreview()" autoresize>
<v-chart ref="vChartRef" :theme="themeColor" :option="option.value" :manual-update="isPreview()" autoresize>
</v-chart>
</template>
@@ -7,12 +7,11 @@
import { PropType, reactive, watch, ref, nextTick } from 'vue'
import config, { includes } from './config'
import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use, registerMap } from 'echarts/core'
import { EffectScatterChart, MapChart } from 'echarts/charts'
import { CanvasRenderer } from 'echarts/renderers'
import { useChartDataFetch } from '@/hooks'
import { mergeTheme, setOption } from '@/packages/public/chart'
import { mergeTheme } from '@/packages/public/chart'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { isPreview } from '@/utils'
import mapJsonWithoutHainanIsLands from './mapWithoutHainanIsLands.json'
@@ -33,8 +32,6 @@ const props = defineProps({
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
use([
MapChart,
DatasetComponent,
@@ -62,14 +59,13 @@ const getGeojson = (regionId: string) => {
}
//异步时先注册空的 保证初始化不报错
registerMap(`${props.chartConfig.option.mapRegion.adcode}`, { geoJSON: {} as any, specialAreas: {} })
registerMap(props.chartConfig.option.mapRegion.adcode, { geoJSON: {} as any, specialAreas: {} })
// 进行更换初始化地图 如果为china 单独处理
const registerMapInitAsync = async () => {
await nextTick()
const adCode = `${props.chartConfig.option.mapRegion.adcode}`;
if (adCode !== 'china') {
await getGeojson(adCode)
if (props.chartConfig.option.mapRegion.adcode != 'china') {
await getGeojson(props.chartConfig.option.mapRegion.adcode)
} else {
await hainanLandsHandle(props.chartConfig.option.mapRegion.showHainanIsLands)
}
@@ -80,7 +76,7 @@ registerMapInitAsync()
// 手动触发渲染
const vEchartsSetOption = () => {
option.value = props.chartConfig.option
setOption(vChartRef.value, props.chartConfig.option)
vChartRef.value?.setOption(props.chartConfig.option)
}
// 更新数据处理
@@ -131,7 +127,7 @@ watch(
//监听地图展示区域发生变化
watch(
() => `${props.chartConfig.option.mapRegion.adcode}`,
() => props.chartConfig.option.mapRegion.adcode,
async newData => {
try {
await getGeojson(newData)

View File

@@ -1,91 +0,0 @@
import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
import { DialConfig } from './index'
import { CreateComponentType } from '@/packages/index.d'
import cloneDeep from 'lodash/cloneDeep'
export const includes = []
const option = {
backgroundColor: '#0E1327',
dataset:70,
series: [{
type: "gauge",
data: [{
value: 70,
itemStyle: { // 指针样式
color: '#2AF4FF'
}
}],
min: 0, //最小刻度
max: 100, //最大刻度
splitNumber: 10, //刻度数量
center: ['50%', '55%'],
radius: '80%',
axisLine: {
lineStyle: {
color: [
[0, 'rgba(0,212,230,0.5)'],
[1, 'rgba(28,128,245,0)']
],
width: 170
}
},
axisLabel: { // 文字样式
color: '#eee',
fontSize: 14,
},
axisTick: {
show: false,
},
splitLine: {
show: false,
},
detail: {
show: false,
},
pointer: {
length: '80%',
width: 4
},
animationDuration: 2000,
},
{
name: '外部刻度',
type: 'gauge',
center: ['50%', '55%'],
radius: '90%',
axisLine: {
show: true,
lineStyle: {
width: 25,
color: [ // 表盘外部颜色
[0, '#1369E380'],
[1, '#1369E380']
],
}
},
axisLabel: {
show:false,
},
axisTick: {
splitNumber: 5,
lineStyle: { //刻度颜色
color: '#42E5FB',
width: 2,
},
},
splitLine: {
length: 15,
lineStyle: {
color: '#42E5FB',
}
},
},
]
};
export default class Config extends PublicConfigClass implements CreateComponentType {
public key: string = DialConfig.key
public chartConfig = cloneDeep(DialConfig)
// 图表配置项
public option = echartOptionProfixHandle(option, includes)
}

View File

@@ -1,84 +0,0 @@
<template>
<!-- 遍历 seriesList -->
<CollapseItem :name="`圆环`" :expanded="true">
<SettingItemBox name="数据">
<SettingItem name="数值">
<n-input-number v-model:value="config.dataset" :min="dialConfig.min" :max="dialConfig.max" :step="1" size="small" placeholder="数值">
</n-input-number>
</SettingItem>
</SettingItemBox>
<!-- Echarts 全局设置 -->
<!-- 表盘刻度字体 -->
<SettingItemBox name="字体">
<SettingItem name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="dialConfig.axisLabel.color"></n-color-picker>
</SettingItem>
<SettingItem name="字体大小">
<n-input-number
v-model:value="dialConfig.axisLabel.fontSize"
:min="0"
:step="1"
size="small"
placeholder="字体大小"
>
</n-input-number>
</SettingItem>
</SettingItemBox>
<!-- 表盘 -->
<SettingItemBox name="表盘外部">
<SettingItem name="颜色" >
<n-color-picker size="small" :modes="['hex']" v-model:value="config.series[1].axisLine.lineStyle.color[1][1]"></n-color-picker>
</SettingItem>
</SettingItemBox>
<!-- 指针 -->
<SettingItemBox name="指针">
<SettingItem name="颜色" >
<n-color-picker size="small" :modes="['hex']" v-model:value="dialConfig.data[0].itemStyle.color"></n-color-picker>
</SettingItem>
<SettingItem name="宽度">
<n-input-number v-model:value="dialConfig.pointer.width" :min="0" :step="1" size="small" placeholder="数值">
</n-input-number>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="刻度">
<SettingItem name="最小值">
<n-input-number v-model:value="dialConfig.min" :min="0" :step="1" size="small" placeholder="数值">
</n-input-number>
</SettingItem>
<SettingItem name="最大值">
<n-input-number v-model:value="dialConfig.max" :min="0" :step="1" size="small" placeholder="数值">
</n-input-number>
</SettingItem>
<SettingItem name="颜色" >
<n-color-picker size="small" :modes="['hex']" v-model:value="config.series[1].axisTick.lineStyle.color" @update:value="updateClick"></n-color-picker>
</SettingItem>
</SettingItemBox>
</CollapseItem>
</template>
<script setup lang="ts">
import { PropType, computed } from 'vue'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { GlobalThemeJsonType } from '@/settings/chartThemes'
const props = defineProps({
optionData: {
type: Object as PropType<GlobalThemeJsonType>,
required: true
}
})
const config = computed(() => {
return props.optionData
})
const dialConfig = computed(() => {
return props.optionData.series[0]
})
const updateClick = (val: any) => {
props.optionData.series[1].splitLine.lineStyle.color=val
}
</script>

View File

@@ -1,14 +0,0 @@
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
export const DialConfig: ConfigType = {
key: 'Dial',
chartKey: 'VDial',
conKey: 'VCDial',
title: '表盘',
category: ChatCategoryEnum.MORE,
categoryName: ChatCategoryEnumName.MORE,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.COMMON,
image:'dial.png'
}

View File

@@ -1,69 +0,0 @@
<template>
<v-chart :theme="themeColor" :init-options="initOptions" :option="option.value" autoresize> </v-chart>
</template>
<script setup lang="ts">
import { PropType, reactive, watch } from 'vue'
import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { PieChart } from 'echarts/charts'
import { mergeTheme } from '@/packages/public/chart'
import config, { includes } from './config'
import { useChartDataFetch } from '@/hooks'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent, TitleComponent } from 'echarts/components'
const props = defineProps({
themeSetting: {
type: Object,
required: true
},
themeColor: {
type: Object,
required: true
},
chartConfig: {
type: Object as PropType<config>,
required: true
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
use([DatasetComponent, CanvasRenderer, PieChart, GridComponent, TooltipComponent, LegendComponent, TitleComponent])
const option = reactive({
value: {}
})
const dataHandle = (newData: any) => {
let config = props.chartConfig.option
config.series[0].data[0].value = newData
option.value = mergeTheme(props.chartConfig.option, props.themeSetting, includes)
option.value = props.chartConfig.option
}
// 配置时
watch(
() => props.chartConfig.option.dataset,
newData => {
try {
dataHandle(newData)
} catch (error) {
console.log(error)
}
},
{
immediate: true,
deep: false
}
)
// 预览时
useChartDataFetch(props.chartConfig, useChartEditStore, (resData: number) => {
// @ts-ignore
option.value.series[0].data[0].value = resData
})
</script>

View File

@@ -1,3 +1,4 @@
import image from '@/assets/images/chart/charts/funnel.png'
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
@@ -10,5 +11,5 @@ export const FunnelConfig: ConfigType = {
categoryName: ChatCategoryEnumName.MORE,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.ECHARTS,
image: 'funnel.png'
image
}

View File

@@ -1,11 +1,10 @@
<template>
<v-chart ref="vChartRef" :init-options="initOptions" :theme="themeColor" :option="option" :manual-update="isPreview()" autoresize></v-chart>
<v-chart ref="vChartRef" :theme="themeColor" :option="option" :manual-update="isPreview()" autoresize></v-chart>
</template>
<script setup lang="ts">
import { computed, PropType } from 'vue'
import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { FunnelChart } from 'echarts/charts'
@@ -32,8 +31,6 @@ const props = defineProps({
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
use([DatasetComponent, CanvasRenderer, FunnelChart, GridComponent, TooltipComponent, LegendComponent])
const option = computed(() => {

View File

@@ -1,71 +0,0 @@
import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
import { GraphConfig } from './index'
import { CreateComponentType } from '@/packages/index.d'
import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json'
export const includes = []
// 关系图布局
export const GraphLayout = [
{ label: '无', value: 'none' },
{ label: '环形', value: 'circular' }
]
// 标签开关
export const LabelSwitch = [
{ label: '开启', value: 1 },
{ label: '关闭', value: 0 }
]
// 标签位置
export const LabelPosition = [
{ label: '左侧', value: 'left' },
{ label: '右侧', value: 'right' },
{ label: '顶部', value: 'top' },
{ label: '底部', value: 'bottom' },
{ label: '内部', value: 'inside' },
]
export const option = {
dataset: { ...dataJson },
tooltip: {},
legend:{
show:true,
textStyle:{
color:"#eee",
fontSize: 14 ,
},
data: dataJson.categories.map(function (a) {
return a.name;
})
},
series: [
{
type: 'graph',
layout: 'none', // none circular环形布局
data: dataJson.nodes,
links: dataJson.links,
categories: dataJson.categories,
label: { // 标签
show: 1,
position: 'right',
formatter: '{b}'
},
labelLayout: {
hideOverlap: true
},
lineStyle: {
color: 'source', // 线条颜色
curveness: 0.2 // 线条卷曲程度
}
}
]
};
export default class Config extends PublicConfigClass implements CreateComponentType {
public key = GraphConfig.key
public chartConfig = cloneDeep(GraphConfig)
// 图表配置项
public option = echartOptionProfixHandle(option, includes)
}

View File

@@ -1,62 +0,0 @@
<template>
<div>
<CollapseItem name="关系图" :expanded="true">
<SettingItemBox name="样式">
<setting-item name="布局">
<n-select v-model:value="graphConfig.layout" :options="GraphLayout" size="small" />
</setting-item>
</SettingItemBox>
<SettingItemBox name="标签">
<setting-item name="展示">
<n-select v-model:value="graphConfig.label.show" :options="LabelSwitch" size="small" />
</setting-item>
<setting-item name="位置">
<n-select v-model:value="graphConfig.label.position" :options="LabelPosition" size="small" />
</setting-item>
</SettingItemBox>
<SettingItemBox name="线条">
<SettingItem name="弧线">
<!-- 需要输入两位的小数才会变化 -->
<n-input-number
v-model:value="optionData.series[0].lineStyle.curveness"
:min="0"
:step="0.01"
placeholder="弯曲程度"
size="small"
></n-input-number>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="图例">
<SettingItem name="颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="optionData.legend.textStyle.color"
></n-color-picker>
</SettingItem>
<SettingItem name="文本">
<n-input-number v-model:value="optionData.legend.textStyle.fontSize" :min="0" :step="1" size="small" placeholder="文字大小">
</n-input-number>
</SettingItem>
</SettingItemBox>
</CollapseItem>
</div>
</template>
<script setup lang="ts">
import { PropType, computed } from 'vue'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { option, GraphLayout, LabelSwitch, LabelPosition } from './config'
import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
const props = defineProps({
optionData: {
type: Object as PropType<typeof option & GlobalThemeJsonType>,
required: true
}
})
const graphConfig = computed<typeof option.series[0]>(() => {
return props.optionData.series[0]
})
</script>

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +0,0 @@
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
export const GraphConfig: ConfigType = {
key: 'Graph',
chartKey: 'VGraph',
conKey: 'VCGraph',
title: '关系图',
category: ChatCategoryEnum.MORE,
categoryName: ChatCategoryEnumName.MORE,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.COMMON,
image: 'graph.png'
}

View File

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

View File

@@ -1,3 +1,4 @@
import image from '@/assets/images/chart/charts/heatmap.png'
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
@@ -10,5 +11,5 @@ export const HeatmapConfig: ConfigType = {
categoryName: ChatCategoryEnumName.MORE,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.COMMON,
image: 'heatmap.png'
image
}

View File

@@ -1,17 +1,16 @@
<template>
<v-chart ref="vChartRef" :init-options="initOptions" :theme="themeColor" :option="option" :manual-update="isPreview()" autoresize></v-chart>
<v-chart ref="vChartRef" :theme="themeColor" :option="option" :manual-update="isPreview()" autoresize></v-chart>
</template>
<script setup lang="ts">
import { ref, watch, computed, PropType } from 'vue'
import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import dataJson from './data.json'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { HeatmapChart } from 'echarts/charts'
import { includes } from './config'
import { mergeTheme, setOption } from '@/packages/public/chart'
import { mergeTheme } from '@/packages/public/chart'
import { useChartDataFetch } from '@/hooks'
import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
@@ -39,8 +38,6 @@ const props = defineProps({
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
use([
DatasetComponent,
CanvasRenderer,
@@ -71,7 +68,7 @@ const dataSetHandle = (dataset: typeof dataJson) => {
props.chartConfig.option.series[0].data = seriesData
}
if (vChartRef.value && isPreview()) {
setOption(vChartRef.value, props.chartConfig.option)
vChartRef.value.setOption(props.chartConfig.option)
}
}

View File

@@ -1,3 +1,5 @@
// 展示图片
import image from '@/assets/images/chart/charts/process.png'
// 公共类型声明
import { ConfigType, PackagesCategoryEnum } from '@/packages/index.d'
// 当前[信息模块]分类声明
@@ -19,5 +21,5 @@ export const ProcessConfig: ConfigType = {
// 包分类
package: PackagesCategoryEnum.CHARTS,
// 图片
image: 'process.png'
image: image
}

View File

@@ -1,3 +1,4 @@
import image from '@/assets/images/chart/charts/radar.png'
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
@@ -10,5 +11,5 @@ export const RadarConfig: ConfigType = {
categoryName: ChatCategoryEnumName.MORE,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.COMMON,
image: 'radar.png'
image
}

View File

@@ -1,17 +1,16 @@
<template>
<v-chart ref="vChartRef" :init-options="initOptions" :theme="themeColor" :option="option" :manual-update="isPreview()" autoresize></v-chart>
<v-chart ref="vChartRef" :theme="themeColor" :option="option" :manual-update="isPreview()" autoresize></v-chart>
</template>
<script setup lang="ts">
import { ref, computed, PropType, watch } from 'vue'
import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import dataJson from './data.json'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { RadarChart } from 'echarts/charts'
import { includes } from './config'
import { mergeTheme, setOption } from '@/packages/public/chart'
import { mergeTheme } from '@/packages/public/chart'
import { useChartDataFetch } from '@/hooks'
import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
@@ -33,8 +32,6 @@ const props = defineProps({
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
use([DatasetComponent, CanvasRenderer, RadarChart, GridComponent, TooltipComponent, LegendComponent])
const vChartRef = ref<typeof VChart>()
@@ -53,7 +50,7 @@ const dataSetHandle = (dataset: typeof dataJson) => {
props.chartConfig.option.radar.indicator = dataset.radarIndicator
}
if (vChartRef.value && isPreview()) {
setOption(vChartRef.value, props.chartConfig.option)
vChartRef.value.setOption(props.chartConfig.option)
}
}

View File

@@ -1,43 +0,0 @@
import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
import { SankeyConfig } from './index'
import { CreateComponentType } from '@/packages/index.d'
import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json'
export const includes = ['legend']
// 图表方向
export const orientList = [
{ label: '水平', value: 'horizontal' },
{ label: '垂直', value: 'vertical' }
]
// 标签展示
export const toolTipSwitch = [
{ label: '开启', value: 1 },
{ label: '关闭', value: 0 }
]
export const option = {
dataset: { ...dataJson },
tooltip: {
show: 1,
trigger: 'item',
triggerOn: 'mousemove'
},
series: {
type: 'sankey',
layout: 'none',
orient:'horizontal',
data: dataJson.label,
links: dataJson.links,
levels: dataJson.levels
}
};
export default class Config extends PublicConfigClass implements CreateComponentType {
public key = SankeyConfig.key
public chartConfig = cloneDeep(SankeyConfig)
// 图表配置项
public option = echartOptionProfixHandle(option, includes)
}

View File

@@ -1,43 +0,0 @@
<template>
<div>
<CollapseItem name="桑基图" :expanded="true">
<SettingItemBox name="样式">
<SettingItem name="方向">
<n-select
v-model:value="sankeyConfig.orient"
size="small"
:options="orientList"
placeholder="选择方向"
/>
</SettingItem>
<SettingItem name="提示标签">
<n-select
v-model:value="optionData.tooltip.show"
size="small"
:options="toolTipSwitch"
placeholder="是否开启"
/>
</SettingItem>
</SettingItemBox>
</CollapseItem>
</div>
</template>
<script setup lang="ts">
import { PropType, computed } from 'vue'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { option, orientList, toolTipSwitch } from './config'
import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
const props = defineProps({
optionData: {
type: Object as PropType<typeof option & GlobalThemeJsonType>,
required: true
}
})
const sankeyConfig = computed<typeof option.series>(() => {
return props.optionData.series
})
</script>

View File

@@ -1,86 +0,0 @@
{
"label": [
{
"name": "a"
},
{
"name": "b"
},
{
"name": "a1"
},
{
"name": "a2"
},
{
"name": "b1"
},
{
"name": "b2"
}
],
"links": [
{
"source": "a",
"target": "a1",
"value": 5
},
{
"source": "a",
"target": "a2",
"value": 3
},
{
"source": "b",
"target": "b1",
"value": 8
},
{
"source": "a",
"target": "b1",
"value": 3
},
{
"source": "b1",
"target": "a1",
"value": 1
},
{
"source": "b1",
"target": "b2",
"value": 2
}
],
"levels": [
{
"depth": 0,
"itemStyle": {
"color": "#decbe4"
},
"lineStyle": {
"color": "source",
"opacity": 0.9
}
},
{
"depth": 1,
"itemStyle": {
"color": "#b3cde3"
},
"lineStyle": {
"color": "source",
"opacity": 0.6
}
},
{
"depth": 2,
"itemStyle": {
"color": "#ccebc5"
},
"lineStyle": {
"color": "source",
"opacity": 0.6
}
}
]
}

View File

@@ -1,14 +0,0 @@
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
export const SankeyConfig: ConfigType = {
key: 'Sankey',
chartKey: 'VSankey',
conKey: 'VCSankey',
title: '桑基图',
category: ChatCategoryEnum.MORE,
categoryName: ChatCategoryEnumName.MORE,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.COMMON,
image: 'sankey.png'
}

View File

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

View File

@@ -1,3 +1,4 @@
import image from '@/assets/images/chart/charts/tree_map.png'
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
@@ -10,5 +11,5 @@ export const TreeMapConfig: ConfigType = {
categoryName: ChatCategoryEnumName.MORE,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.COMMON,
image: 'tree_map.png'
image
}

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