fear: 升级合并go-view主分支版本及新功能
优化画布功能, 优化编辑功能, 新转增组件联动功能, 新增输入框,下拉框,选择框,标签选择,时间选择,分页联动控件 新增全局联动配置, 新增带分页数据列表, 新增地图高德地图配置项与区域地图配置项, 新增图标分类组件, 新增图片分类组件, 新增字节系列图表 新增部分装饰组件 新增磨砂玻璃滤镜组件 完善OAUTH2令牌无感刷新等
3
.gitignore
vendored
@@ -4,3 +4,6 @@ dist
|
|||||||
dist-ssr
|
dist-ssr
|
||||||
*.local
|
*.local
|
||||||
.vscode
|
.vscode
|
||||||
|
.idea
|
||||||
|
.workflow
|
||||||
|
.husky
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||||
<meta name="renderer" content="webkit" />
|
<meta name="renderer" content="webkit" />
|
||||||
<meta name="description" content="GoView 是高效、高性能的拖拽式低代码数据可视化开发平台,将页面元素封装为基础组件,无需编写代码即可完成业务需求。">
|
<meta name="description" content="GoView 是高效、高性能的拖拽式低代码数据可视化开发平台,将页面元素封装为基础组件,无需编写代码即可完成业务需求。 ">
|
||||||
<meta name="keywords" content="GoView,goview,低代码,可视化">
|
<meta name="keywords" content="GoView,goview,低代码,可视化">
|
||||||
<meta name="author" content="奔跑的面条,面条">
|
<meta name="author" content="奔跑的面条,面条">
|
||||||
<meta
|
<meta
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
<link rel="icon" href="./favicon.ico" />
|
<link rel="icon" href="./favicon.ico" />
|
||||||
<title>GoView</title>
|
<title>GoView</title>
|
||||||
<link rel="stylesheet" href="./index.css" />
|
<link rel="stylesheet" href="./index.css" />
|
||||||
|
<script src="js/esobjs-xe2-plugin/dist-web/xe2-assets/js/load-common.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="appProvider" style="display: none;"></div>
|
<div id="appProvider" style="display: none;"></div>
|
||||||
|
|||||||
20213
package-lock.json
generated
Normal file
32
package.json
@@ -1,8 +1,9 @@
|
|||||||
{
|
{
|
||||||
|
"type": "module",
|
||||||
"name": "go-view",
|
"name": "go-view",
|
||||||
"version": "2.1.6",
|
"version": "2.1.6",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.14 <18.0.0"
|
"node": ">=12.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --host",
|
"dev": "vite --host",
|
||||||
@@ -16,34 +17,48 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@amap/amap-jsapi-loader": "^1.0.1",
|
"@amap/amap-jsapi-loader": "^1.0.1",
|
||||||
"@amap/amap-jsapi-types": "^0.0.8",
|
"@amap/amap-jsapi-types": "^0.0.8",
|
||||||
|
"@iconify/json": "^2.2.158",
|
||||||
"@types/color": "^3.0.3",
|
"@types/color": "^3.0.3",
|
||||||
"@types/crypto-js": "^4.1.1",
|
"@types/crypto-js": "^4.1.1",
|
||||||
"@types/keymaster": "^1.6.30",
|
"@types/keymaster": "^1.6.30",
|
||||||
"@types/lodash": "^4.14.184",
|
"@types/lodash": "^4.14.184",
|
||||||
|
"@visactor/vchart": "^1.12.3",
|
||||||
|
"@visactor/vchart-theme": "^1.12.1",
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"axios": "^0.27.2",
|
"axios": "^1.4.0",
|
||||||
|
"cesium": "1.99",
|
||||||
"color": "^4.2.3",
|
"color": "^4.2.3",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
|
"dayjs": "^1.11.7",
|
||||||
"dom-helpers": "^5.2.1",
|
"dom-helpers": "^5.2.1",
|
||||||
"echarts-liquidfill": "^3.1.0",
|
"echarts-liquidfill": "^3.1.0",
|
||||||
"echarts-stat": "^1.2.0",
|
"echarts-stat": "^1.2.0",
|
||||||
"echarts-wordcloud": "^2.0.0",
|
"echarts-wordcloud": "^2.0.0",
|
||||||
|
"esobjs-xe2-plugin": "^0.1.126-beta-0.3",
|
||||||
"gsap": "^3.11.3",
|
"gsap": "^3.11.3",
|
||||||
"highlight.js": "^11.5.0",
|
"highlight.js": "^11.5.0",
|
||||||
"html2canvas": "^1.4.1",
|
"html2canvas": "^1.4.1",
|
||||||
|
"iconify-icon": "^1.0.8",
|
||||||
"keymaster": "^1.6.2",
|
"keymaster": "^1.6.2",
|
||||||
|
"mitt": "^3.0.0",
|
||||||
"monaco-editor": "^0.33.0",
|
"monaco-editor": "^0.33.0",
|
||||||
"naive-ui": "2.34.3",
|
"naive-ui": "2.34.3",
|
||||||
"pinia": "^2.0.13",
|
"pinia": "^2.0.13",
|
||||||
|
"pnpm": "^8.7.0",
|
||||||
"screenfull": "^6.0.1",
|
"screenfull": "^6.0.1",
|
||||||
"three": "^0.145.0",
|
"three": "^0.145.0",
|
||||||
|
"vite-plugin-cesium": "^1.2.23",
|
||||||
"vue": "^3.2.31",
|
"vue": "^3.2.31",
|
||||||
"vue-demi": "^0.13.1",
|
"vue-demi": "^0.13.1",
|
||||||
"vue-i18n": "^9.2.2",
|
"vue-i18n": "9.2.2",
|
||||||
"vue-router": "4.0.12",
|
"vue-router": "4.0.12",
|
||||||
|
"vue-xe2-plugin": "^0.1.3",
|
||||||
"vue3-lazyload": "^0.2.5-beta",
|
"vue3-lazyload": "^0.2.5-beta",
|
||||||
"vue3-sketch-ruler": "^1.3.3",
|
"vue3-sketch-ruler": "^1.3.3",
|
||||||
"vuedraggable": "^4.1.0"
|
"vuedraggable": "^4.1.0",
|
||||||
|
"xbsj-xe2": "^0.1.16",
|
||||||
|
"xbsj-xe2-assets": "^0.1.16",
|
||||||
|
"smplotting-xe2-plugin": "^0.1.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^17.0.2",
|
"@commitlint/cli": "^17.0.2",
|
||||||
@@ -54,8 +69,8 @@
|
|||||||
"@typescript-eslint/parser": "^5.18.0",
|
"@typescript-eslint/parser": "^5.18.0",
|
||||||
"@vicons/carbon": "^0.12.0",
|
"@vicons/carbon": "^0.12.0",
|
||||||
"@vicons/ionicons5": "~0.11.0",
|
"@vicons/ionicons5": "~0.11.0",
|
||||||
"@vitejs/plugin-vue": "^1.10.2",
|
"@vitejs/plugin-vue": "^4.2.3",
|
||||||
"@vitejs/plugin-vue-jsx": "^1.3.9",
|
"@vitejs/plugin-vue-jsx": "^3.0.1",
|
||||||
"@vue/compiler-sfc": "^3.2.31",
|
"@vue/compiler-sfc": "^3.2.31",
|
||||||
"@vueuse/core": "^7.7.1",
|
"@vueuse/core": "^7.7.1",
|
||||||
"commitlint": "^17.0.2",
|
"commitlint": "^17.0.2",
|
||||||
@@ -66,6 +81,7 @@
|
|||||||
"eslint-plugin-import": "^2.26.0",
|
"eslint-plugin-import": "^2.26.0",
|
||||||
"eslint-plugin-prettier": "^4.0.0",
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
"eslint-plugin-vue": "^8.5.0",
|
"eslint-plugin-vue": "^8.5.0",
|
||||||
|
"esobjs-xe2-plugin-assets": "^0.1.14",
|
||||||
"husky": "^8.0.1",
|
"husky": "^8.0.1",
|
||||||
"lodash": "~4.17.21",
|
"lodash": "~4.17.21",
|
||||||
"mockjs": "^1.1.0",
|
"mockjs": "^1.1.0",
|
||||||
@@ -74,11 +90,13 @@
|
|||||||
"sass": "^1.49.11",
|
"sass": "^1.49.11",
|
||||||
"sass-loader": "^12.6.0",
|
"sass-loader": "^12.6.0",
|
||||||
"typescript": "4.6.3",
|
"typescript": "4.6.3",
|
||||||
"vite": "2.9.9",
|
"vite": "4.3.6",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
|
"vite-plugin-externals": "^0.6.2",
|
||||||
"vite-plugin-importer": "^0.2.5",
|
"vite-plugin-importer": "^0.2.5",
|
||||||
"vite-plugin-mock": "^2.9.6",
|
"vite-plugin-mock": "^2.9.6",
|
||||||
"vite-plugin-monaco-editor": "^1.1.0",
|
"vite-plugin-monaco-editor": "^1.1.0",
|
||||||
|
"vite-plugin-static-copy": "^1.0.6",
|
||||||
"vue-echarts": "^6.0.2",
|
"vue-echarts": "^6.0.2",
|
||||||
"vue-tsc": "^0.28.10"
|
"vue-tsc": "^0.28.10"
|
||||||
}
|
}
|
||||||
|
|||||||
6419
pnpm-lock.yaml
generated
10
preview.yml
Normal 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)
|
||||||
28
src/App.vue
@@ -19,6 +19,34 @@ import { GoAppProvider } from '@/components/GoAppProvider'
|
|||||||
import { I18n } from '@/components/I18n'
|
import { I18n } from '@/components/I18n'
|
||||||
import { useSystemInit, useDarkThemeHook, useThemeOverridesHook, useCode, useLang } from '@/hooks'
|
import { useSystemInit, useDarkThemeHook, useThemeOverridesHook, useCode, useLang } from '@/hooks'
|
||||||
|
|
||||||
|
//字节图表全局配置部分
|
||||||
|
import vScreenVolcanoBlue from '@visactor/vchart-theme/public/vScreenVolcanoBlue.json';
|
||||||
|
import VChart from '@visactor/vchart';
|
||||||
|
import {IGlobalMarkThemeByName, IGlobalMarkThemeByType, ITheme} from "@visactor/vchart/esm/theme/interface";
|
||||||
|
import {languages} from "monaco-editor";
|
||||||
|
import type {IColorKey} from "@visactor/vchart/esm/theme/color-scheme/interface";
|
||||||
|
import type {ITokenKey} from "@visactor/vchart/esm/theme/token";
|
||||||
|
import type {ISeriesTheme} from "@visactor/vchart/esm/series/interface";
|
||||||
|
import type {IComponentTheme} from "@visactor/vchart/esm/component/interface";
|
||||||
|
const myVScreenVolcanoBlue: Partial<ITheme> = {
|
||||||
|
...vScreenVolcanoBlue,
|
||||||
|
type:"dark",
|
||||||
|
background:vScreenVolcanoBlue.background as IColorKey,
|
||||||
|
fontFamily:vScreenVolcanoBlue.fontFamily as ITokenKey,
|
||||||
|
mark:vScreenVolcanoBlue.mark as IGlobalMarkThemeByType,
|
||||||
|
markByName:vScreenVolcanoBlue.markByName as IGlobalMarkThemeByName,
|
||||||
|
series:vScreenVolcanoBlue.series as ISeriesTheme,
|
||||||
|
component: vScreenVolcanoBlue.component as unknown as IComponentTheme
|
||||||
|
// 其他字段逐个检查和断言
|
||||||
|
};
|
||||||
|
|
||||||
|
VChart.ThemeManager.registerTheme('vScreenVolcanoBlue',myVScreenVolcanoBlue);
|
||||||
|
// apply the theme
|
||||||
|
VChart.ThemeManager.setCurrentTheme('vScreenVolcanoBlue');
|
||||||
|
//字节图标配置部分END
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 暗黑主题
|
// 暗黑主题
|
||||||
const darkTheme = useDarkThemeHook()
|
const darkTheme = useDarkThemeHook()
|
||||||
|
|
||||||
|
|||||||
142
src/api/axios.ts
@@ -1,12 +1,32 @@
|
|||||||
import axios, { AxiosResponse, AxiosRequestConfig, Axios } from 'axios'
|
import axios, { AxiosResponse, AxiosRequestConfig, Axios } from 'axios'
|
||||||
import { ResultEnum, ModuleTypeEnum } from "@/enums/httpEnum"
|
import { ResultEnum, ModuleTypeEnum } from "@/enums/httpEnum"
|
||||||
import { PageEnum, ErrorPageNameMap } from "@/enums/pageEnum"
|
import {PageEnum, ErrorPageNameMap, PreviewEnum} from "@/enums/pageEnum"
|
||||||
import { StorageEnum } from '@/enums/storageEnum'
|
import { StorageEnum } from '@/enums/storageEnum'
|
||||||
import { axiosPre } from '@/settings/httpSetting'
|
import { axiosPre } from '@/settings/httpSetting'
|
||||||
import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'
|
import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'
|
||||||
import { redirectErrorPage, getLocalStorage, routerTurnByName, isPreview } from '@/utils'
|
import {
|
||||||
|
redirectErrorPage,
|
||||||
|
getLocalStorage,
|
||||||
|
routerTurnByName,
|
||||||
|
isPreview,
|
||||||
|
clearAllSessio,
|
||||||
|
clearAllStorage,
|
||||||
|
setLocalStorage,
|
||||||
|
setSessionStorage, fetchRouteParamsLocation, fetchRouteName, logout, fetchRoutePath
|
||||||
|
} from '@/utils'
|
||||||
import { fetchAllowList } from './axios.config'
|
import { fetchAllowList } from './axios.config'
|
||||||
import includes from 'lodash/includes'
|
import includes from 'lodash/includes'
|
||||||
|
import {useSystemStore} from "@/store/modules/systemStore/systemStore";
|
||||||
|
import { useDialog } from 'naive-ui'
|
||||||
|
// Axios 无感知刷新令牌,参考 https://www.dashingdog.cn/article/11 与 https://segmentfault.com/a/1190000020210980 实现
|
||||||
|
// 请求队列
|
||||||
|
let requestList: any[] = []
|
||||||
|
// 是否正在刷新中
|
||||||
|
let isRefreshToken = false
|
||||||
|
// 请求路径
|
||||||
|
let base_url=`${import.meta.env.PROD ? import.meta.env.VITE_PRO_PATH : ''}${axiosPre}`
|
||||||
|
|
||||||
|
const dialog = useDialog()
|
||||||
|
|
||||||
export interface MyResponseType<T> {
|
export interface MyResponseType<T> {
|
||||||
code: ResultEnum
|
code: ResultEnum
|
||||||
@@ -19,7 +39,7 @@ export interface MyRequestInstance extends Axios {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const axiosInstance = axios.create({
|
const axiosInstance = axios.create({
|
||||||
baseURL: `${import.meta.env.PROD ? import.meta.env.VITE_PRO_PATH : ''}${axiosPre}`,
|
baseURL: base_url,
|
||||||
timeout: ResultEnum.TIMEOUT,
|
timeout: ResultEnum.TIMEOUT,
|
||||||
}) as unknown as MyRequestInstance
|
}) as unknown as MyRequestInstance
|
||||||
|
|
||||||
@@ -27,6 +47,7 @@ axiosInstance.interceptors.request.use(
|
|||||||
(config: AxiosRequestConfig) => {
|
(config: AxiosRequestConfig) => {
|
||||||
// 获取 tenantId
|
// 获取 tenantId
|
||||||
const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
|
const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
|
||||||
|
// console.log(window.location)
|
||||||
const tenantId = info ? info[SystemStoreEnum.TENANT_INFO]['tenantId'] : undefined
|
const tenantId = info ? info[SystemStoreEnum.TENANT_INFO]['tenantId'] : undefined
|
||||||
if (tenantId) {
|
if (tenantId) {
|
||||||
config.headers = {
|
config.headers = {
|
||||||
@@ -57,15 +78,18 @@ axiosInstance.interceptors.request.use(
|
|||||||
|
|
||||||
// 响应拦截器
|
// 响应拦截器
|
||||||
axiosInstance.interceptors.response.use(
|
axiosInstance.interceptors.response.use(
|
||||||
(res: AxiosResponse) => {
|
async (res: AxiosResponse<any>) => {
|
||||||
|
const config = res.config
|
||||||
|
|
||||||
|
const { code,msg } = res.data as { code: number,msg:string }
|
||||||
|
|
||||||
|
if (code === undefined || code === null) return Promise.resolve(res)
|
||||||
// 预览页面错误不进行处理
|
// 预览页面错误不进行处理
|
||||||
if (isPreview()) {
|
if (isPreview()&&code!==ResultEnum.TOKEN_OVERDUE) {
|
||||||
return Promise.resolve(res.data)
|
return Promise.resolve(res.data)
|
||||||
}
|
}
|
||||||
// 如果是验证码的返回,直接返回数据
|
// 如果是验证码的返回,直接返回数据
|
||||||
const { code } = res.data as { code: number }
|
|
||||||
|
|
||||||
if (code === undefined || code === null) return Promise.resolve(res)
|
|
||||||
|
|
||||||
// 成功
|
// 成功
|
||||||
if (code === ResultEnum.SUCCESS) {
|
if (code === ResultEnum.SUCCESS) {
|
||||||
@@ -74,9 +98,68 @@ axiosInstance.interceptors.response.use(
|
|||||||
|
|
||||||
// 登录过期
|
// 登录过期
|
||||||
if (code === ResultEnum.TOKEN_OVERDUE) {
|
if (code === ResultEnum.TOKEN_OVERDUE) {
|
||||||
window['$message'].error(window['$t']('http.token_overdue_message'))
|
// 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了
|
||||||
routerTurnByName(PageEnum.BASE_LOGIN_NAME)
|
console.log('Auth2:-------------------准备刷新令牌-----------------')
|
||||||
return Promise.resolve(res.data)
|
if (!isRefreshToken) {
|
||||||
|
isRefreshToken = true
|
||||||
|
const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
|
||||||
|
// console.log(window.location)
|
||||||
|
const refreshToken = info ? info[SystemStoreEnum.USER_INFO][SystemStoreUserInfoEnum.USER_REFRESH_TOKEN] : undefined
|
||||||
|
// 1. 如果获取不到刷新令牌,则只能执行登出操作
|
||||||
|
|
||||||
|
if (!refreshToken) {
|
||||||
|
console.log('无刷新令牌,即将返回。')
|
||||||
|
return handleAuthorized()
|
||||||
|
}
|
||||||
|
// 2. 进行刷新访问令牌
|
||||||
|
try {
|
||||||
|
const systemStore = useSystemStore()
|
||||||
|
const refreshTokenRes = await getTefreshToken()
|
||||||
|
// 2.1 刷新成功,则回放队列的请求 + 当前请求
|
||||||
|
systemStore.setItem(SystemStoreEnum.USER_INFO, {
|
||||||
|
[SystemStoreUserInfoEnum.USER_TOKEN]: (await refreshTokenRes).data.data.accessToken,
|
||||||
|
[SystemStoreUserInfoEnum.USER_REFRESH_TOKEN]: (await refreshTokenRes).data.data.refreshToken,
|
||||||
|
[SystemStoreUserInfoEnum.TOKEN_NAME]: 'Authorization'
|
||||||
|
})
|
||||||
|
//修改当前访问令牌
|
||||||
|
// config.headers!.Authorization = 'Bearer ' + (await refreshTokenRes).data.data.accessToken
|
||||||
|
const userInfo = info[SystemStoreEnum.USER_INFO]
|
||||||
|
config.headers = {
|
||||||
|
...config.headers,
|
||||||
|
[userInfo[SystemStoreUserInfoEnum.TOKEN_NAME] || 'token']: 'Bearer ' + userInfo[SystemStoreUserInfoEnum.USER_TOKEN] || ''
|
||||||
|
}
|
||||||
|
|
||||||
|
requestList.forEach((cb: any) => {
|
||||||
|
cb()
|
||||||
|
})
|
||||||
|
requestList = []
|
||||||
|
console.log('Auth2:-------------------令牌刷新成功-----------------')
|
||||||
|
return axiosInstance(config)
|
||||||
|
} catch (e) {
|
||||||
|
// 为什么需要 catch 异常呢?刷新失败时,请求因为 Promise.reject 触发异常。
|
||||||
|
// 2.2 刷新失败,只回放队列的请求
|
||||||
|
requestList.forEach((cb: any) => {
|
||||||
|
cb()
|
||||||
|
})
|
||||||
|
// 提示是否要登出。即不回放当前请求!不然会形成递归
|
||||||
|
return handleAuthorized()
|
||||||
|
} finally {
|
||||||
|
requestList = []
|
||||||
|
isRefreshToken = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Auth2:-------------------已添加刷新队列-----------------')
|
||||||
|
const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
|
||||||
|
// 添加到队列,等待刷新获取到新的令牌
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
requestList.push(() => {
|
||||||
|
const userInfo = info[SystemStoreEnum.USER_INFO]
|
||||||
|
config.headers!.Authorization = 'Bearer ' + userInfo[SystemStoreUserInfoEnum.USER_TOKEN] // 让每个请求携带自定义token 请根据实际情况自行修改
|
||||||
|
resolve(axiosInstance(config))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 固定错误码重定向
|
// 固定错误码重定向
|
||||||
@@ -85,6 +168,17 @@ axiosInstance.interceptors.response.use(
|
|||||||
return Promise.resolve(res.data)
|
return Promise.resolve(res.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (code !== 200) {
|
||||||
|
if (msg === '无效的刷新令牌') {
|
||||||
|
// hard coding:忽略这个提示,直接登出
|
||||||
|
console.log(msg)
|
||||||
|
return handleAuthorized()
|
||||||
|
} else {
|
||||||
|
window['$message'].error(msg)
|
||||||
|
}
|
||||||
|
return Promise.reject('error')
|
||||||
|
}
|
||||||
|
|
||||||
// 提示错误
|
// 提示错误
|
||||||
window['$message'].error(window['$t']((res.data as any).msg))
|
window['$message'].error(window['$t']((res.data as any).msg))
|
||||||
return Promise.resolve(res.data)
|
return Promise.resolve(res.data)
|
||||||
@@ -94,4 +188,32 @@ axiosInstance.interceptors.response.use(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
const getTefreshToken = async () => {
|
||||||
|
let tenantData = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
|
||||||
|
axios.defaults.headers.common['tenant-id'] = tenantData[SystemStoreEnum.TENANT_INFO]['tenantId'] ?? undefined;
|
||||||
|
return await axios.post(base_url + '/system/auth/refresh-token?refreshToken=' + tenantData[SystemStoreEnum.USER_INFO][SystemStoreUserInfoEnum.USER_REFRESH_TOKEN] ?? undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const handleAuthorized = () =>{
|
||||||
|
// window['$message'].error(window['$t']('http.token_overdue_message'))
|
||||||
|
console.log(useDialog())
|
||||||
|
window['$dialog'].warning( {title: '登录已超时',
|
||||||
|
content: '登录超时,请重新登录。',
|
||||||
|
positiveText: '确定',
|
||||||
|
negativeText: '取消',
|
||||||
|
onPositiveClick: () => {
|
||||||
|
// session 不需要清除 clearAllSessio() //清除所有Session缓存
|
||||||
|
clearAllStorage() //清除所有Storage缓存
|
||||||
|
//临时缓存跳回目录进行登录重新跳回
|
||||||
|
if('/chart/preview' === fetchRoutePath()){
|
||||||
|
setSessionStorage('setRedirectPath','/chart/preview')
|
||||||
|
setSessionStorage('setRedirectPathId', fetchRouteParamsLocation())
|
||||||
|
}
|
||||||
|
logout()
|
||||||
|
return Promise.resolve(window['$t']('http.token_overdue_message'))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
export default axiosInstance
|
export default axiosInstance
|
||||||
|
|||||||
100
src/api/mock/graph.json
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -19,6 +19,8 @@ export const capsuleUrl = '/mock/capsule'
|
|||||||
export const wordCloudUrl = '/mock/wordCloud'
|
export const wordCloudUrl = '/mock/wordCloud'
|
||||||
export const treemapUrl = '/mock/treemap'
|
export const treemapUrl = '/mock/treemap'
|
||||||
export const threeEarth01Url = '/mock/threeEarth01Data'
|
export const threeEarth01Url = '/mock/threeEarth01Data'
|
||||||
|
export const sankeyUrl = '/mock/sankey'
|
||||||
|
export const graphUrl = '/mock/graphData'
|
||||||
|
|
||||||
const mockObject: MockMethod[] = [
|
const mockObject: MockMethod[] = [
|
||||||
{
|
{
|
||||||
@@ -103,6 +105,16 @@ const mockObject: MockMethod[] = [
|
|||||||
method: RequestHttpEnum.GET,
|
method: RequestHttpEnum.GET,
|
||||||
response: () => test.threeEarth01Data
|
response: () => test.threeEarth01Data
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
url: sankeyUrl,
|
||||||
|
method: RequestHttpEnum.GET,
|
||||||
|
response: () => test.fetchSankey
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: graphUrl,
|
||||||
|
method: RequestHttpEnum.GET,
|
||||||
|
response: () => test.graphData
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
export default mockObject
|
export default mockObject
|
||||||
|
|||||||
86
src/api/mock/sankey.json
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ import heatmapJson from './heatMapData.json'
|
|||||||
import scatterJson from './scatter.json'
|
import scatterJson from './scatter.json'
|
||||||
import mapJson from './map.json'
|
import mapJson from './map.json'
|
||||||
import tTreemapJson from './treemap.json'
|
import tTreemapJson from './treemap.json'
|
||||||
|
import sankeyJson from './sankey.json'
|
||||||
|
import graphDataJson from './graph.json'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
// 单图表
|
// 单图表
|
||||||
@@ -219,5 +221,19 @@ export default {
|
|||||||
'endArray|10': [{ name: '@name', N: '@integer(10, 100)', E: '@integer(10, 100)' }]
|
'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
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
src/assets/images/chart/charts/bar_line.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
src/assets/images/chart/charts/dial.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
src/assets/images/chart/charts/graph.png
Normal file
|
After Width: | Height: | Size: 377 KiB |
BIN
src/assets/images/chart/charts/ground_glass.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
src/assets/images/chart/charts/grouped_stacked_rose_chart.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
src/assets/images/chart/charts/map_cesium.png
Normal file
|
After Width: | Height: | Size: 162 KiB |
BIN
src/assets/images/chart/charts/polar_coordinate_axis.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
src/assets/images/chart/charts/sankey.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
src/assets/images/chart/charts/visactor_bar_line.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
src/assets/images/chart/charts/visactor_biax_line.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
src/assets/images/chart/charts/visactor_instrument.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/images/chart/charts/visactor_line.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
src/assets/images/chart/charts/weather.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
src/assets/images/chart/decorates/Pipeline_H.png
Normal file
|
After Width: | Height: | Size: 999 B |
BIN
src/assets/images/chart/decorates/Pipeline_V.png
Normal file
|
After Width: | Height: | Size: 983 B |
BIN
src/assets/images/chart/decorates/bottom_decorate_1.png
Normal file
|
After Width: | Height: | Size: 386 KiB |
BIN
src/assets/images/chart/decorates/decorates08.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
src/assets/images/chart/decorates/flow-circle.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
src/assets/images/chart/decorates/flow-zhexian.png
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
BIN
src/assets/images/chart/decorates/fullScreen.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
src/assets/images/chart/decorates/right_decorate_1.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
src/assets/images/chart/decorates/round_dot.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
src/assets/images/chart/decorates/status_lamp.png
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
BIN
src/assets/images/chart/decorates/technologycircle.png
Normal file
|
After Width: | Height: | Size: 177 KiB |
BIN
src/assets/images/chart/icons/icon.png
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
BIN
src/assets/images/chart/informations/inputs_date.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
src/assets/images/chart/informations/inputs_input.png
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
BIN
src/assets/images/chart/informations/inputs_pagination.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/images/chart/informations/inputs_select.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
src/assets/images/chart/informations/inputs_tab.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
src/assets/images/chart/informations/photo_carousel.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
src/assets/images/chart/informations/text_card.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
src/assets/images/chart/photos/upload.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
src/assets/images/chart/tables/tables_basic.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
src/assets/images/chart_background.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
src/assets/images/decoration/background_image_1.jpg
Normal file
|
After Width: | Height: | Size: 476 KiB |
BIN
src/assets/images/decoration/background_image_2.jpg
Normal file
|
After Width: | Height: | Size: 425 KiB |
BIN
src/assets/images/decoration/background_image_3.jpg
Normal file
|
After Width: | Height: | Size: 2.3 MiB |
BIN
src/assets/images/decoration/background_image_4.png
Normal file
|
After Width: | Height: | Size: 3.3 MiB |
BIN
src/assets/images/decoration/background_image_5.png
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
BIN
src/assets/images/decoration/big_title_base_image_0.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
src/assets/images/decoration/big_title_base_image_2.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
src/assets/images/decoration/big_title_base_image_3.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
src/assets/images/decoration/big_title_base_image_4.png
Normal file
|
After Width: | Height: | Size: 121 KiB |
BIN
src/assets/images/decoration/big_title_base_image_5.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
src/assets/images/decoration/big_title_base_image_6.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
src/assets/images/decoration/big_title_base_image_7.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
src/assets/images/decoration/bottom_decorate_1.png
Normal file
|
After Width: | Height: | Size: 386 KiB |
BIN
src/assets/images/decoration/charts-img-db_id_17bwi76fzta800.mp4
Normal file
BIN
src/assets/images/decoration/charts-img-db_id_cqlw0qmjt4o00.mp4
Normal file
BIN
src/assets/images/decoration/right_decorate_1.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
src/assets/images/decoration/title_base_image_0.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
src/assets/images/decoration/title_base_image_11.png
Normal file
|
After Width: | Height: | Size: 92 KiB |
BIN
src/assets/images/decoration/title_base_image_12.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
src/assets/images/decoration/title_base_image_13.png
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
BIN
src/assets/images/decoration/title_base_image_14.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
src/assets/images/decoration/title_base_image_15.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
src/assets/images/decoration/title_base_image_16.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
src/assets/images/decoration/title_base_image_3.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
src/assets/images/decoration/title_base_image_4.png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
BIN
src/assets/images/decoration/title_base_image_5.png
Normal file
|
After Width: | Height: | Size: 270 B |
BIN
src/assets/images/decoration/title_base_image_6.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
src/assets/images/decoration/title_base_image_7.png
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
src/assets/images/decoration/title_base_image_8.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/assets/images/decoration/title_base_image_9.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
src/assets/images/decoration/xm56fRJH.jpg
Normal file
|
After Width: | Height: | Size: 416 KiB |
BIN
src/assets/images/decoration/上边框.png
Normal file
|
After Width: | Height: | Size: 686 KiB |
BIN
src/assets/images/decoration/干净小标题底图.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
src/assets/images/decoration/底座.png
Normal file
|
After Width: | Height: | Size: 483 KiB |
BIN
src/assets/images/decoration/微信图片_20240912103559.jpg
Normal file
|
After Width: | Height: | Size: 209 KiB |
BIN
src/assets/images/decoration/模块外框.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
src/assets/images/decoration/模块边框2.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
src/assets/images/decoration/点位.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
src/assets/images/decoration/科技圈圈.png
Normal file
|
After Width: | Height: | Size: 177 KiB |
BIN
src/assets/images/decoration/科技圈圈2.png
Normal file
|
After Width: | Height: | Size: 188 KiB |
BIN
src/assets/images/decoration/装饰绿点点.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
src/assets/images/decoration/边框.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
src/assets/images/decoration/边框流线.webm
Normal file
BIN
src/assets/videos/charts-img-db_id_17bwi76fzta800.mp4
Normal file
BIN
src/assets/videos/charts-img-db_id_cqlw0qmjt4o00.mp4
Normal file
BIN
src/assets/videos/dynamic_circle.mp4
Normal file
3
src/components/GoIconify/index.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import GoIconify from './index.vue';
|
||||||
|
|
||||||
|
export { GoIconify };
|
||||||
34
src/components/GoIconify/index.vue
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<template>
|
||||||
|
<iconify-icon
|
||||||
|
:icon="icon"
|
||||||
|
:rotate="`${rotate}deg`"
|
||||||
|
:width="width"
|
||||||
|
:style="{
|
||||||
|
color: color
|
||||||
|
}"
|
||||||
|
></iconify-icon>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
defineProps({
|
||||||
|
icon: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: '#999999',
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: '20',
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
rotate: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: '0',
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<img class="list-img" v-lazy="imageInfo" alt="图表图片" />
|
<img class="list-img" v-lazy="imageInfo" :alt="imageInfo" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<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>
|
||||||
@@ -1,4 +1,34 @@
|
|||||||
<template>
|
<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="标题">
|
<collapse-item v-if="title" name="标题">
|
||||||
<template #header>
|
<template #header>
|
||||||
<n-switch v-model:value="title.show" size="small"></n-switch>
|
<n-switch v-model:value="title.show" size="small"></n-switch>
|
||||||
@@ -227,9 +257,36 @@
|
|||||||
<n-switch v-model:value="legend.show" size="small"></n-switch>
|
<n-switch v-model:value="legend.show" size="small"></n-switch>
|
||||||
</template>
|
</template>
|
||||||
<setting-item-box name="图例文字">
|
<setting-item-box name="图例文字">
|
||||||
<setting-item>
|
<setting-item name="颜色">
|
||||||
<n-color-picker size="small" v-model:value="legend.textStyle.color"></n-color-picker>
|
<n-color-picker size="small" v-model:value="legend.textStyle.color"></n-color-picker>
|
||||||
</setting-item>
|
</setting-item>
|
||||||
|
<setting-item name="大小">
|
||||||
|
<n-input-number v-model:value="legend.textStyle.fontSize" :min="1" size="small"></n-input-number>
|
||||||
|
</setting-item>
|
||||||
|
</setting-item-box>
|
||||||
|
<setting-item-box name="图例位置">
|
||||||
|
<setting-item name="x轴">
|
||||||
|
<n-select v-model:value="legend.x" size="small" :options="legendConfig.lengendX" />
|
||||||
|
</setting-item>
|
||||||
|
<setting-item name="y轴">
|
||||||
|
<n-select v-model:value="legend.y" size="small" :options="legendConfig.lengendY" />
|
||||||
|
</setting-item>
|
||||||
|
</setting-item-box>
|
||||||
|
<setting-item-box name="图例信息">
|
||||||
|
<setting-item name="方向">
|
||||||
|
<n-select v-model:value="legend.orient" size="small" :options="legendConfig.orient" />
|
||||||
|
</setting-item>
|
||||||
|
<setting-item name="形状">
|
||||||
|
<n-select v-model:value="legend.icon" size="small" :options="legendConfig.shape" />
|
||||||
|
</setting-item>
|
||||||
|
</setting-item-box>
|
||||||
|
<setting-item-box name="图例大小">
|
||||||
|
<setting-item name="宽">
|
||||||
|
<n-input-number v-model:value="legend.itemWidth" :min="1" size="small"></n-input-number>
|
||||||
|
</setting-item>
|
||||||
|
<setting-item name="高">
|
||||||
|
<n-input-number v-model:value="legend.itemHeight" :min="1" size="small"></n-input-number>
|
||||||
|
</setting-item>
|
||||||
</setting-item-box>
|
</setting-item-box>
|
||||||
</collapse-item>
|
</collapse-item>
|
||||||
|
|
||||||
@@ -279,10 +336,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { PropType, computed } from 'vue'
|
import { PropType, computed, watch } from 'vue'
|
||||||
import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
|
import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
|
||||||
import { axisConfig } from '@/packages/chartConfiguration/echarts/index'
|
import { axisConfig, legendConfig } from '@/packages/chartConfiguration/echarts/index'
|
||||||
import { CollapseItem, SettingItemBox, SettingItem, GlobalSettingPosition } from '@/components/Pages/ChartItemSetting'
|
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({
|
const props = defineProps({
|
||||||
optionData: {
|
optionData: {
|
||||||
@@ -296,6 +358,12 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const chartEditStore = useChartEditStore()
|
||||||
|
const themeSetting = computed(() => {
|
||||||
|
const chartThemeSetting = chartEditStore.getEditCanvasConfig.chartThemeSetting
|
||||||
|
return chartThemeSetting
|
||||||
|
})
|
||||||
|
|
||||||
const title = computed(() => {
|
const title = computed(() => {
|
||||||
return props.optionData.title
|
return props.optionData.title
|
||||||
})
|
})
|
||||||
@@ -319,4 +387,18 @@ const grid = computed(() => {
|
|||||||
const visualMap = computed(() => {
|
const visualMap = computed(() => {
|
||||||
return props.optionData.visualMap
|
return props.optionData.visualMap
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 监听legend color颜色改变type = scroll的颜色
|
||||||
|
watch(() => legend.value && legend.value.textStyle.color, (newVal) => {
|
||||||
|
if (legend.value && newVal) {
|
||||||
|
if (!legend.value.pageTextStyle) {
|
||||||
|
legend.value.pageTextStyle = { color: newVal }
|
||||||
|
} else {
|
||||||
|
legend.value.pageTextStyle.color = newVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
immediate: true,
|
||||||
|
deep: true,
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -69,6 +69,22 @@
|
|||||||
</setting-item>
|
</setting-item>
|
||||||
</setting-item-box>
|
</setting-item-box>
|
||||||
|
|
||||||
|
<!-- 预设滤镜 -->
|
||||||
|
<div v-if="presetImageList.length" class="preset-filter">
|
||||||
|
<n-image
|
||||||
|
class="preset-img"
|
||||||
|
width="46"
|
||||||
|
preview-disabled
|
||||||
|
object-fit="scale-down"
|
||||||
|
v-for="(item, index) in presetImageList"
|
||||||
|
:key="index"
|
||||||
|
:class="{ 'active-preset': item.hueRotate === chartStyles.hueRotate }"
|
||||||
|
:style="{ filter: `hue-rotate(${item.hueRotate}deg)` }"
|
||||||
|
:src="item.src"
|
||||||
|
@click="() => (chartStyles.hueRotate = item.hueRotate)"
|
||||||
|
></n-image>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 混合模式 -->
|
<!-- 混合模式 -->
|
||||||
<setting-item-box v-if="!isCanvas" :alone="true">
|
<setting-item-box v-if="!isCanvas" :alone="true">
|
||||||
<template #name>
|
<template #name>
|
||||||
@@ -149,10 +165,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { PropType } from 'vue'
|
import { ref, PropType } from 'vue'
|
||||||
import { PickCreateComponentType, BlendModeEnumList } from '@/packages/index.d'
|
import { PickCreateComponentType, BlendModeEnumList } from '@/packages/index.d'
|
||||||
import { SettingItemBox, SettingItem, CollapseItem } from '@/components/Pages/ChartItemSetting'
|
import { SettingItemBox, SettingItem, CollapseItem } from '@/components/Pages/ChartItemSetting'
|
||||||
import { icon } from '@/plugins'
|
import { icon } from '@/plugins'
|
||||||
|
import logoImg from '@/assets/logo.png'
|
||||||
|
import { useDesignStore } from '@/store/modules/designStore/designStore'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
isGroup: {
|
isGroup: {
|
||||||
@@ -175,10 +193,48 @@ const { HelpOutlineIcon } = icon.ionicons5
|
|||||||
const sliderFormatTooltip = (v: string) => {
|
const sliderFormatTooltip = (v: string) => {
|
||||||
return `${(parseFloat(v) * 100).toFixed(0)}%`
|
return `${(parseFloat(v) * 100).toFixed(0)}%`
|
||||||
}
|
}
|
||||||
|
|
||||||
// 角度格式化
|
// 角度格式化
|
||||||
const degFormatTooltip = (v: string) => {
|
const degFormatTooltip = (v: string) => {
|
||||||
return `${v}deg`
|
return `${v}deg`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 预设滤镜
|
||||||
|
interface presetImageData {
|
||||||
|
index: number
|
||||||
|
src: string
|
||||||
|
hueRotate: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const presetImageList = ref([] as presetImageData[])
|
||||||
|
for (let i = 1; i <= 12; i++) {
|
||||||
|
presetImageList.value.push({
|
||||||
|
index: i,
|
||||||
|
src: logoImg,
|
||||||
|
hueRotate: i * 30
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped>
|
||||||
|
// 预设滤镜
|
||||||
|
.preset-filter {
|
||||||
|
margin: 20px 0 10px 0;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
.preset-img {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 2px;
|
||||||
|
border-radius: 6px;
|
||||||
|
transition: 0.2s all;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0 0 0 2px #66a9c9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.active-preset {
|
||||||
|
box-shadow: 0 0 0 2px #66a9c9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="go-Flipper" :class="[flipType, { go: isFlipping }]">
|
<div class="go-flipper" :class="[flipType, { go: isFlipping }]">
|
||||||
<div class="digital front" :data-front="frontTextFromData"></div>
|
<div class="digital front" :data-front="frontTextFromData"></div>
|
||||||
<div class="digital back" :data-back="backTextFromData"></div>
|
<div class="digital back" :data-back="backTextFromData"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, PropType, watch } from 'vue'
|
import { ref, PropType, watch, nextTick } from 'vue'
|
||||||
import { FlipType } from './index'
|
import { FlipType } from './index'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
flipType: {
|
flipType: {
|
||||||
@@ -43,6 +43,10 @@ const props = defineProps({
|
|||||||
backColor: {
|
backColor: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '#000000'
|
default: '#000000'
|
||||||
|
},
|
||||||
|
borderWidth: {
|
||||||
|
type: Number,
|
||||||
|
default: 2
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -50,19 +54,27 @@ const isFlipping = ref(false)
|
|||||||
const frontTextFromData = ref(props.count || 0)
|
const frontTextFromData = ref(props.count || 0)
|
||||||
const backTextFromData = ref(props.count || 0)
|
const backTextFromData = ref(props.count || 0)
|
||||||
|
|
||||||
|
let timeoutID: any = 0
|
||||||
|
|
||||||
// 翻牌
|
// 翻牌
|
||||||
const flip = (front: string | number, back: string | number) => {
|
const flip = async (front: string | number, back: string | number) => {
|
||||||
// 如果处于翻转中,则不执行
|
// 如果处于翻转中,则不执行
|
||||||
if (isFlipping.value) return
|
if (isFlipping.value) {
|
||||||
|
isFlipping.value = false // 立即结束此次动画
|
||||||
|
clearTimeout(timeoutID) // 清除上一个计时器任务
|
||||||
|
await nextTick()
|
||||||
|
await flip(front, back) // 开始最后一次翻牌任务
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 设置翻盘前后数据
|
// 设置翻盘前后数据
|
||||||
backTextFromData.value = back
|
backTextFromData.value = back
|
||||||
frontTextFromData.value = front
|
frontTextFromData.value = front
|
||||||
|
|
||||||
// 设置翻转状态为true
|
// 设置翻转状态为true
|
||||||
isFlipping.value = true
|
isFlipping.value = true
|
||||||
|
|
||||||
// 翻牌结束的行为
|
// 翻牌结束的行为
|
||||||
setTimeout(() => {
|
timeoutID = setTimeout(() => {
|
||||||
isFlipping.value = false // 设置翻转状态为false
|
isFlipping.value = false // 设置翻转状态为false
|
||||||
frontTextFromData.value = back
|
frontTextFromData.value = back
|
||||||
}, props.duration)
|
}, props.duration)
|
||||||
@@ -86,6 +98,7 @@ $radius: v-bind('`${props.radius}px`');
|
|||||||
$width: v-bind('`${props.width}px`');
|
$width: v-bind('`${props.width}px`');
|
||||||
$height: v-bind('`${props.height}px`');
|
$height: v-bind('`${props.height}px`');
|
||||||
$perspective: v-bind('`${props.height * 2}px`');
|
$perspective: v-bind('`${props.height * 2}px`');
|
||||||
|
$borderWidth: v-bind('`${props.borderWidth * 2}px`');
|
||||||
$speed: v-bind('`${props.duration / 1000}s`');
|
$speed: v-bind('`${props.duration / 1000}s`');
|
||||||
$shadowColor: #000000;
|
$shadowColor: #000000;
|
||||||
$lineColor: #4a9ef8;
|
$lineColor: #4a9ef8;
|
||||||
@@ -125,13 +138,12 @@ $lineColor: #4a9ef8;
|
|||||||
}
|
}
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
.go-Flipper {
|
.go-flipper {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: $width;
|
width: $width;
|
||||||
height: $height;
|
height: $height;
|
||||||
line-height: $height;
|
line-height: $height;
|
||||||
border: solid 1px $backColor;
|
|
||||||
border-radius: $radius;
|
border-radius: $radius;
|
||||||
background: $frontColor;
|
background: $frontColor;
|
||||||
font-size: $width;
|
font-size: $width;
|
||||||
@@ -139,6 +151,17 @@ $lineColor: #4a9ef8;
|
|||||||
box-shadow: 0 0 6px rgba($color: $shadowColor, $alpha: 0.5); // 阴影部分
|
box-shadow: 0 0 6px rgba($color: $shadowColor, $alpha: 0.5); // 阴影部分
|
||||||
text-align: center;
|
text-align: center;
|
||||||
// font-family: 'Helvetica Neue';
|
// font-family: 'Helvetica Neue';
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
z-index: 10;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
box-shadow: inset 0 0 $borderWidth 0 $frontColor; // 内测阴影部分
|
||||||
|
border-radius: $radius;
|
||||||
|
}
|
||||||
|
|
||||||
.digital:before,
|
.digital:before,
|
||||||
.digital:after {
|
.digital:after {
|
||||||
@@ -186,11 +209,13 @@ $lineColor: #4a9ef8;
|
|||||||
&.down.go .front:before {
|
&.down.go .front:before {
|
||||||
transform-origin: 50% 100%;
|
transform-origin: 50% 100%;
|
||||||
animation: frontFlipDown $speed ease-in-out both;
|
animation: frontFlipDown $speed ease-in-out both;
|
||||||
box-shadow: 0 -2px 6px rgba($color: $lineColor, $alpha: 0.3);
|
box-shadow: 0 -2px $borderWidth 0 $frontColor;
|
||||||
backface-visibility: hidden;
|
backface-visibility: hidden;
|
||||||
}
|
}
|
||||||
&.down.go .back:after {
|
&.down.go .back:after {
|
||||||
animation: backFlipDown $speed ease-in-out both;
|
animation: backFlipDown $speed ease-in-out both;
|
||||||
|
box-shadow: 0 2px $borderWidth 0 $frontColor;
|
||||||
|
backface-visibility: hidden;
|
||||||
}
|
}
|
||||||
/*向上翻*/
|
/*向上翻*/
|
||||||
&.up .front:after {
|
&.up .front:after {
|
||||||
@@ -208,11 +233,13 @@ $lineColor: #4a9ef8;
|
|||||||
&.up.go .front:after {
|
&.up.go .front:after {
|
||||||
transform-origin: 50% 0;
|
transform-origin: 50% 0;
|
||||||
animation: frontFlipUp $speed ease-in-out both;
|
animation: frontFlipUp $speed ease-in-out both;
|
||||||
box-shadow: 0 2px 6px rgba($color: $lineColor, $alpha: 0.3);
|
box-shadow: 0 2px $borderWidth 0 $frontColor;
|
||||||
backface-visibility: hidden;
|
backface-visibility: hidden;
|
||||||
}
|
}
|
||||||
&.up.go .back:before {
|
&.up.go .back:before {
|
||||||
animation: backFlipUp $speed ease-in-out both;
|
animation: backFlipUp $speed ease-in-out both;
|
||||||
|
box-shadow: 0 -2px $borderWidth 0 $frontColor;
|
||||||
|
backface-visibility: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||