Compare commits

..

7 Commits

Author SHA1 Message Date
奔跑的面条
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
290 changed files with 35574 additions and 7144 deletions

12
.env
View File

@@ -1,8 +1,14 @@
# port
VITE_DEV_PORT = '8080'
VITE_DEV_PORT = '8001'
# development path
VITE_DEV_PATH = 'http://1.117.240.165:8080'
VITE_DEV_PATH = '/'
# production path
VITE_PRO_PATH = 'http://1.117.240.165:8080'
VITE_PRO_PATH = '/'
# spa-title
VITE_GLOB_APP_TITLE = GoView
# spa shortname
VITE_GLOB_APP_SHORT_NAME = GoView

View File

@@ -20,11 +20,6 @@ module.exports = {
extends: ['plugin:vue/vue3-essential', 'eslint:recommended'],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-unused-vars': 'off',
'vue/no-unused-vars': 'off',
'vue/multi-word-component-names': 'off',
'vue/valid-template-root': 'off',
'vue/no-mutating-props': 'off'
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
}
}

View File

@@ -0,0 +1,51 @@
version: '1.0'
name: branch-pipeline
displayName: BranchPipeline
stages:
- stage:
name: compile
displayName: 编译
steps:
- step: build@nodejs
name: build_nodejs
displayName: Nodejs 构建
# 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
nodeVersion: 14.16.0
# 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
commands:
- npm install && rm -rf ./dist && npm run build
# 非必填字段开启后表示将构建产物暂存但不会上传到制品库中7天后自动清除
artifacts:
# 构建产物名字作为产物的唯一标识可向下传递支持自定义默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
- name: BUILD_ARTIFACT
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
path:
- ./dist
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
# 上游构建任务定义的产物名默认BUILD_ARTIFACT
dependArtifact: BUILD_ARTIFACT
# 上传到制品库时的制品命名默认output
artifactName: output
dependsOn: build_nodejs
- stage:
name: release
displayName: 发布
steps:
- step: publish@release_artifacts
name: publish_release_artifacts
displayName: '发布'
# 上游上传制品任务的产出
dependArtifact: output
# 发布制品版本号
version: '1.0.0.0'
# 是否开启版本号自增,默认开启
autoIncrement: true
triggers:
push:
branches:
exclude:
- master
include:
- .*

View File

@@ -0,0 +1,49 @@
version: '1.0'
name: master-pipeline
displayName: MasterPipeline
stages:
- stage:
name: compile
displayName: 编译
steps:
- step: build@nodejs
name: build_nodejs
displayName: Nodejs 构建
# 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
nodeVersion: 14.16.0
# 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
commands:
- npm install && rm -rf ./dist && npm run build
# 非必填字段开启后表示将构建产物暂存但不会上传到制品库中7天后自动清除
artifacts:
# 构建产物名字作为产物的唯一标识可向下传递支持自定义默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
- name: BUILD_ARTIFACT
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
path:
- ./dist
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
# 上游构建任务定义的产物名默认BUILD_ARTIFACT
dependArtifact: BUILD_ARTIFACT
# 上传到制品库时的制品命名默认output
artifactName: output
dependsOn: build_nodejs
- stage:
name: release
displayName: 发布
steps:
- step: publish@release_artifacts
name: publish_release_artifacts
displayName: '发布'
# 上游上传制品任务的产出
dependArtifact: output
# 发布制品版本号
version: '1.0.0.0'
# 是否开启版本号自增,默认开启
autoIncrement: true
triggers:
push:
branches:
include:
- master

36
.workflow/pr-pipeline.yml Normal file
View File

@@ -0,0 +1,36 @@
version: '1.0'
name: pr-pipeline
displayName: PRPipeline
stages:
- stage:
name: compile
displayName: 编译
steps:
- step: build@nodejs
name: build_nodejs
displayName: Nodejs 构建
# 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
nodeVersion: 14.16.0
# 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
commands:
- npm install && rm -rf ./dist && npm run build
# 非必填字段开启后表示将构建产物暂存但不会上传到制品库中7天后自动清除
artifacts:
# 构建产物名字作为产物的唯一标识可向下传递支持自定义默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
- name: BUILD_ARTIFACT
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
path:
- ./dist
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
# 上游构建任务定义的产物名默认BUILD_ARTIFACT
dependArtifact: BUILD_ARTIFACT
# 上传到制品库时的制品命名默认output
artifactName: output
dependsOn: build_nodejs
triggers:
pr:
branches:
include:
- master

189
README.md
View File

@@ -2,17 +2,21 @@
![logo](readme/logo-t-y.png)
**`master-fetch` 分支是带有后端接口请求的分支**
GoView 是一个高效的拖拽式低代码数据可视化开发平台,将图表或页面元素封装为基础组件,无需编写代码即可制作数据大屏,减少心智负担。
**后端项目地址:[https://gitee.com/MTrun/go-view-serve](https://gitee.com/MTrun/go-view-serve)**
### 😶 纯 **前端** 分支: **`master`**
**接口说明地址:[https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb](https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb)**
### 👻 携带 **后端** 请求分支: **`master-fetch`**
## 使用
### 📚 GoView **文档** 地址:[http://www.mtruning.club:81/](http://www.mtruning.club:81/)
所有的接口地址位置:`src\api\path\*`
项目纯前端-Demo 地址:[https://www.mtruning.club](https://www.mtruning.club)
接口地址修改:`.env`
项目带后端-Demo 地址:[后端 Demo 地址](http://1.117.240.165:8080/goview/#/login)
文档-在线地址:[http://www.mtruning.club:81/](http://www.mtruning.club:81/)
文档-源码地址:[https://gitee.com/MTrun/go-view-doc](https://gitee.com/MTrun/go-view-doc)
### 🤯 后端项目
@@ -20,103 +24,124 @@
接口说明地址:[https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb](https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb)
```shell
# port
VITE_DEV_PORT = '8080'
技术点:
# development path
VITE_DEV_PATH = 'http://127.0.0.1:8080'
- 框架:基于 `Vue3` 框架编写,使用 `hooks` 写法抽离部分逻辑,使代码结构更加清晰;
# production path
VITE_PRO_PATH = 'http://127.0.0.1:8080'
```
- 类型:使用 `TypeScript` 进行类型约束,减少未知错误发生概率,可以大胆修改逻辑内容;
公共前缀修改:`src\settings\httpSetting.ts`
- 性能:多处性能优化,使用页面懒加载、组件动态注册、数据滚动加载等方式,提升页面渲染速度;
- 存储:拥有本地记忆,部分配置项采用 `storage` 存储本地,提升使用体验;
- 封装:项目进行了详细的工具类封装如:路由、存储、加/解密、文件处理、主题、NaiveUI 全局方法、组件等
工作台:
![项目截图](readme/go-view-canvas.png)
请求配置:
![项目截图](readme/go-view-fetch.png)
数据过滤:
![项目截图](readme/go-view-filter.png)
主题色:
![项目截图](readme/go-view-color.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
// 请求前缀
export const axiosPre = '/api/goview'
#建议使用 nrm 切换到淘宝源 https://registry.npmmirror.com/
#pnpm
pnpm install
#yarn
yarn install
#npm
npm install
```
接口封装:`src\api\http.ts`
## 启动
```ts
import axiosInstance from './axios'
import { RequestHttpEnum, ContentTypeEnum } from '@/enums/httpEnum'
```shell
#pnpm
pnpm dev
export const get = (url: string, params?: object) => {
return axiosInstance({
url: url,
method: RequestHttpEnum.GET,
params: params,
})
}
# npm
npm run dev
export const post = (url: string, data?: object, headersType?: string) => {
return axiosInstance({
url: url,
method: RequestHttpEnum.POST,
data: data,
headers: {
'Content-Type': headersType || ContentTypeEnum.JSON
}
})
}
#yarn
yarn dev
export const put = (url: string, data?: object, headersType?: string) => {
return axiosInstance({
url: url,
method: RequestHttpEnum.PUT,
data: data,
headers: {
'Content-Type': headersType || ContentTypeEnum.JSON
}
})
}
#Makefile
make dev
```
export const del = (url: string, params?: object) => {
return axiosInstance({
url: url,
method: RequestHttpEnum.DELETE,
params
})
}
## 编译
// 获取请求函数默认get
export const http = (type?: RequestHttpEnum) => {
switch (type) {
case RequestHttpEnum.GET:
return get
```shell
#pnpm
pnpm run build
case RequestHttpEnum.POST:
return post
# npm
npm run build
case RequestHttpEnum.PUT:
return put
#yarn
yarn run build
case RequestHttpEnum.DELETE:
return del
default:
return get
}
}
#Makefile
make dist
```
## 代码提交
* feat: 新功能
* fix: 修复 Bug
* docs: 文档修改
* perf: 性能优化
* revert: 版本回退
* ci: CICD集成相关
* test: 添加测试代码
* refactor: 代码重构
* build: 影响项目构建或依赖修改
* style: 不影响程序逻辑的代码修改
* chore: 不属于以上类型的其他类型(日常事务)
- feat: 新功能
- fix: 修复 Bug
- docs: 文档修改
- perf: 性能优化
- revert: 版本回退
- ci: CICD 集成相关
- test: 添加测试代码
- refactor: 代码重构
- build: 影响项目构建或依赖修改
- style: 不影响程序逻辑的代码修改
- chore: 不属于以上类型的其他类型(日常事务)
## 交流

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

@@ -82,4 +82,25 @@
to {
opacity: 1;
}
}
/* 小屏处理 0~1000*/
.mobile-terminal {
display: none;
}
@media (max-width: 1000px) {
#app {
display: none;
}
.mobile-terminal {
display: flex;
align-items: center;
justify-content: center;
width: 100vw;
height: 100vh;
text-align: center;
font-size: 24px;
font-weight: 200;
background-image: linear-gradient(to top, #fff1eb 0%, #ace0f9 100%);
}
}

View File

@@ -24,6 +24,9 @@
</div>
</div>
</div>
<div class="mobile-terminal">
<p>请使用 Web 端进行查看</p>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@@ -1,14 +1,12 @@
{
"name": "go-view",
"version": "2.0.91",
"version": "1.1.0",
"scripts": {
"dev": "vite --host",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview",
"new": "plop --plopfile ./plop/plopfile.js",
"postinstall": "husky install",
"lint": "eslint --ext .js,.jsx,.ts,.tsx,.vue src",
"lint:fix": "eslint --ext .js,.jsx,.ts,.tsx,.vue src --fix"
"postinstall": "husky install"
},
"dependencies": {
"@types/color": "^3.0.3",
@@ -21,17 +19,16 @@
"crypto-js": "^4.1.1",
"echarts-liquidfill": "^3.1.0",
"echarts-stat": "^1.2.0",
"echarts-wordcloud": "^2.0.0",
"highlight.js": "^11.5.0",
"html2canvas": "^1.4.1",
"keymaster": "^1.6.2",
"monaco-editor": "^0.33.0",
"naive-ui": "2.33.4",
"naive-ui": "2.30.3",
"pinia": "^2.0.13",
"screenfull": "^6.0.1",
"vue": "^3.2.31",
"vue-demi": "^0.13.1",
"vue-i18n": "9.1.10",
"vue-i18n": "9.1.9",
"vue-router": "4.0.12",
"vue3-lazyload": "^0.2.5-beta",
"vue3-sketch-ruler": "^1.3.3",

728
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,7 @@ import { zhCN, dateZhCN, NConfigProvider } from 'naive-ui'
import { GoAppProvider } from '@/components/GoAppProvider'
import { I18n } from '@/components/I18n'
import { useSystemInit, useDarkThemeHook, useThemeOverridesHook, useCode } from '@/hooks'
import { useDarkThemeHook, useThemeOverridesHook, useCode } from '@/hooks'
// 暗黑主题
const darkTheme = useDarkThemeHook()
@@ -28,7 +28,4 @@ const overridesTheme = useThemeOverridesHook()
// 代码主题
const hljsTheme = useCode()
// 系统全局数据初始化
useSystemInit()
</script>

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,38 +1,19 @@
import axios, { AxiosResponse, AxiosRequestConfig } from 'axios'
import { ResultEnum } from "@/enums/httpEnum"
import { PageEnum, ErrorPageNameMap } from "@/enums/pageEnum"
import { StorageEnum } from '@/enums/storageEnum'
import { axiosPre } from '@/settings/httpSetting'
import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'
import { redirectErrorPage, getLocalStorage, routerTurnByName, httpErrorHandle } from '@/utils'
import { fetchAllowList } from './axios.config'
import includes from 'lodash/includes'
import { ErrorPageNameMap } from "@/enums/pageEnum"
import { redirectErrorPage } from '@/utils'
const axiosInstance = axios.create({
baseURL: `${import.meta.env.PROD ? import.meta.env.VITE_PRO_PATH : ''}${axiosPre}`,
baseURL: import.meta.env.DEV ? import.meta.env.VITE_DEV_PATH : import.meta.env.VITE_PRO_PATH,
timeout: ResultEnum.TIMEOUT,
})
axiosInstance.interceptors.request.use(
(config: AxiosRequestConfig) => {
// 白名单校验
if (includes(fetchAllowList, config.url)) return config
// 获取 token
const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
// 重新登录
if (!info) {
routerTurnByName(PageEnum.BASE_LOGIN_NAME)
return config
}
const userInfo = info[SystemStoreEnum.USER_INFO]
config.headers = {
...config.headers,
[userInfo[SystemStoreUserInfoEnum.TOKEN_NAME] || 'token']: userInfo[SystemStoreUserInfoEnum.USER_TOKEN] || ''
}
return config
},
(err: AxiosRequestConfig) => {
Promise.reject(err)
(error: AxiosRequestConfig) => {
Promise.reject(error)
}
)
@@ -40,30 +21,13 @@ axiosInstance.interceptors.request.use(
axiosInstance.interceptors.response.use(
(res: AxiosResponse) => {
const { code } = res.data as { code: number }
// 成功
if (code === ResultEnum.SUCCESS) {
return Promise.resolve(res.data)
}
// 登录过期
if (code === ResultEnum.TOKEN_OVERDUE) {
window['$message'].error(window['$t']('http.token_overdue_message'))
routerTurnByName(PageEnum.BASE_LOGIN_NAME)
return Promise.resolve(res.data)
}
// 固定错误码重定向
if (ErrorPageNameMap.get(code)) {
redirectErrorPage(code)
return Promise.resolve(res.data)
}
// 提示错误
window['$message'].error(window['$t']((res.data as any).msg))
if (code === ResultEnum.DATA_SUCCESS) return Promise.resolve(res.data)
// 重定向
if (ErrorPageNameMap.get(code)) redirectErrorPage(code)
return Promise.resolve(res.data)
},
(err: AxiosResponse) => {
window['$message'].error('接口异常,请检查!')
Promise.reject(err)
}
)

View File

@@ -13,7 +13,7 @@ export const get = (url: string, params?: object) => {
return axiosInstance({
url: url,
method: RequestHttpEnum.GET,
params: params,
params: params
})
}
@@ -80,32 +80,6 @@ export const http = (type?: RequestHttpEnum) => {
return get
}
}
const prefix = 'javascript:'
// 对输入字符进行转义处理
export const translateStr = (target: string | object) => {
if (typeof target === 'string') {
if (target.startsWith(prefix)) {
const funcStr = target.split(prefix)[1]
let result;
try {
result = new Function(`${funcStr}`)()
} catch (error) {
console.log(error)
window['$message'].error('js内容解析有误')
}
return result
} else {
return target
}
}
for (const key in target) {
if (Object.prototype.hasOwnProperty.call(target, key)) {
const subTarget = (target as any)[key];
(target as any)[key] = translateStr(subTarget)
}
}
return target
}
/**
* * 自定义请求
@@ -113,7 +87,7 @@ export const translateStr = (target: string | object) => {
* @param globalParams 全局参数
*/
export const customizeHttp = (targetParams: RequestConfigType, globalParams: RequestGlobalConfigType) => {
if (!targetParams || !globalParams) {
if(!targetParams || !globalParams) {
return
}
@@ -151,17 +125,15 @@ export const customizeHttp = (targetParams: RequestConfigType, globalParams: Req
}
// 处理头部
let headers: RequestParamsObjType = {
const headers: RequestParamsObjType = {
...globalRequestParams.Header,
...targetRequestParams.Header
...targetRequestParams.Header,
}
headers = translateStr(headers)
// data 参数
let data: RequestParamsObjType | FormData | string = {}
// params 参数
let params: RequestParamsObjType = { ...targetRequestParams.Params }
params = translateStr(params)
let params: RequestParamsObjType = targetRequestParams.Params
// form 类型处理
let formData: FormData = new FormData()
formData.set('default', 'defaultData')
@@ -173,35 +145,33 @@ export const customizeHttp = (targetParams: RequestConfigType, globalParams: Req
case RequestBodyEnum.JSON:
headers['Content-Type'] = ContentTypeEnum.JSON
data = translateStr(JSON.parse(targetRequestParams.Body['json']))
data = JSON.parse(targetRequestParams.Body['json'])
// json 赋值给 data
break
case RequestBodyEnum.XML:
headers['Content-Type'] = ContentTypeEnum.XML
// xml 字符串赋值给 data
data = translateStr(targetRequestParams.Body['xml'])
data = targetRequestParams.Body['xml']
break
case RequestBodyEnum.X_WWW_FORM_URLENCODED: {
case RequestBodyEnum.X_WWW_FORM_URLENCODED:
headers['Content-Type'] = ContentTypeEnum.FORM_URLENCODED
const bodyFormData = targetRequestParams.Body['x-www-form-urlencoded']
for (const i in bodyFormData) formData.set(i, translateStr(bodyFormData[i]))
for (const i in bodyFormData) formData.set(i, bodyFormData[i])
// FormData 赋值给 data
data = formData
break
}
case RequestBodyEnum.FORM_DATA: {
case RequestBodyEnum.FORM_DATA:
headers['Content-Type'] = ContentTypeEnum.FORM_DATA
const bodyFormUrlencoded = targetRequestParams.Body['form-data']
for (const i in bodyFormUrlencoded) {
formData.set(i, translateStr(bodyFormUrlencoded[i]))
formData.set(i, bodyFormUrlencoded[i])
}
// FormData 赋值给 data
data = formData
break
}
}
// sql 处理
@@ -210,17 +180,11 @@ export const customizeHttp = (targetParams: RequestConfigType, globalParams: Req
data = requestSQLContent
}
try {
const url = (new Function("return `" + `${requestOriginUrl}${requestUrl}`.trim() + "`"))();
return axiosInstance({
url,
method: requestHttpType,
data,
params,
headers
})
} catch (error) {
console.log(error)
window['$message'].error('URL地址格式有误')
}
return axiosInstance({
url: `${requestOriginUrl}${requestUrl}`,
method: requestHttpType,
data,
params,
headers
})
}

View File

@@ -14,9 +14,6 @@ export const scrollBoardUrl = '/mock/scrollBoard'
export const radarUrl = '/mock/radarData'
export const heatMapUrl = '/mock/heatMapData'
export const scatterBasicUrl = '/mock/scatterBasic'
export const mapUrl = '/mock/map'
export const wordCloudUrl = '/mock/wordCloud'
export const treemapUrl = '/mock/treemap'
const mockObject: MockMethod[] = [
{
@@ -76,21 +73,6 @@ const mockObject: MockMethod[] = [
method: RequestHttpEnum.GET,
response: () => test.fetchScatterBasic
},
{
url: mapUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchMap
},
{
url: wordCloudUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchWordCloud
},
{
url: treemapUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchTreemap
},
]
export default mockObject

View File

@@ -1,79 +0,0 @@
{
"point": [
{
"name": "北京",
"value": [116.405285, 39.904989, 200]
},
{
"name": "郑州",
"value": [113.665412, 34.757975, 888]
},
{
"name": "青海",
"value": [101.778916, 36.623178, 666]
},
{
"name": "宁夏回族自治区",
"value": [106.278179, 38.46637, 66]
},
{
"name": "哈尔滨市",
"value": [126.642464, 45.756967, 101]
}
],
"map": [
{
"name": "北京市",
"value": "@integer(0, 1000)"
},
{
"name": "河北省",
"value": "@integer(0, 1000)"
},
{
"name": "江苏省",
"value": "@integer(0, 1000)"
},
{
"name": "福建省",
"value": "@integer(0, 1000)"
},
{
"name": "山东省",
"value": "@integer(0, 1000)"
},
{
"name": "河南省",
"value": "@integer(0, 1000)"
},
{
"name": "湖北省",
"value": "@integer(0, 1000)"
},
{
"name": "广西壮族自治区",
"value": "@integer(0, 1000)"
},
{
"name": "海南省",
"value": "@integer(0, 1000)"
},
{
"name": "青海省",
"value": "@integer(0, 1000)"
},
{
"name": "新疆维吾尔自治区",
"value": "@integer(0, 1000)"
}
],
"pieces": [
{ "gte": 1000, "label": ">1000" },
{ "gte": 600, "lte": 999, "label": "600-999" },
{ "gte": 200, "lte": 599, "label": "200-599" },
{ "gte": 50, "lte": 199, "label": "49-199" },
{ "gte": 10, "lte": 49, "label": "10-49" },
{ "lte": 9, "label": "<9" }
]
}

View File

@@ -1,7 +1,5 @@
import heatmapJson from './heatMapData.json'
import scatterJson from './scatter.json'
import mapJson from './map.json'
import tTreemapJson from './treemap.json'
export default {
// 单图表
@@ -200,58 +198,5 @@ export default {
status: 200,
msg: '请求成功',
data: scatterJson
},
// 中国地图
fetchMap: {
code: 0,
status: 200,
msg: '请求成功',
data: mapJson
},
// 词云
fetchWordCloud: {
code: 0,
status: 200,
msg: '请求成功',
data: [
{
name: '@name',
value: 8000,
textStyle: {
color: '#78fbb2'
},
emphasis: {
textStyle: {
color: 'red'
}
}
},
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' }
]
},
// 树图
fetchTreemap: {
code: 0,
status: 200,
msg: '请求成功',
data: tTreemapJson
},
}
}

View File

@@ -1,50 +0,0 @@
[
{
"name": "@name",
"value": "@integer(0, 1000)",
"children": [
{
"name": "@name",
"value": "@integer(0, 500)"
},
{
"name": "@name",
"value": "@integer(0, 500)"
}
]
},
{
"name": "@name",
"value": "@integer(0, 1000)",
"children": [
{
"name": "@name",
"value": "@integer(0, 00)"
},
{
"name": "@name",
"value": "@integer(0, 500)"
}
]
},
{
"name": "@name",
"value": "@integer(0, 1000)",
"children": [
{
"name": "@name",
"value": "@integer(0, 1000)"
}
]
},
{
"name": "@name",
"value": "@integer(0, 1000)",
"children": [
{
"name": "@name",
"value": "@integer(0, 1000)"
}
]
}
]

View File

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

View File

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

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@@ -1,4 +0,0 @@
import Flipper from './index.vue'
type FlipType = 'up' | 'down'
export { Flipper, FlipType }

View File

@@ -1,224 +0,0 @@
<template>
<div class="M-Flipper" :class="[flipType, { go: isFlipping }]">
<div class="digital front" :data-front="frontTextFromData"></div>
<div class="digital back" :data-back="backTextFromData"></div>
</div>
</template>
<script lang="ts">
export default {
name: 'Flipper'
}
</script>
<script lang="ts" setup>
import { ref, PropType, watch } from 'vue'
import { FlipType } from '.'
const props = defineProps({
flipType: {
type: String as PropType<FlipType>,
default: () => {
return 'down'
}
},
count: {
type: [Number, String],
default: 0
},
duration: {
type: Number,
default: 600
},
width: {
type: Number,
default: 60
},
height: {
type: Number,
default: 100
},
radius: {
type: Number,
default: 10
},
frontColor: {
type: String,
default: '#ffffff'
},
backColor: {
type: String,
default: '#000000'
}
})
const isFlipping = ref(false)
const frontTextFromData = ref(props.count || 0)
const backTextFromData = ref(props.count || 0)
// 翻牌
const flip = (front: string | number, back: string | number) => {
// 如果处于翻转中,则不执行
if (isFlipping.value) return
// 设置翻盘前后数据
backTextFromData.value = back
frontTextFromData.value = front
// 设置翻转状态为true
isFlipping.value = true
// 翻牌结束的行为
setTimeout(() => {
isFlipping.value = false // 设置翻转状态为false
frontTextFromData.value = back
}, props.duration)
}
watch(
() => props.count,
(newVal, oldVal) => {
flip(oldVal as string | number, newVal as string | number)
},
{
immediate: true
}
)
</script>
<style lang="scss" scoped>
$frontColor: v-bind('props.frontColor');
$backColor: v-bind('props.backColor');
$radius: v-bind('`${props.radius}px`');
$width: v-bind('`${props.width}px`');
$height: v-bind('`${props.height}px`');
$perspective: v-bind('`${props.height * 2}px`');
$speed: v-bind('`${props.duration / 1000}s`');
$shadowColor: #000000;
$lineColor: #4a9ef8;
// #region 动画效果
@keyframes frontFlipDown {
0% {
transform: perspective($perspective) rotateX(0deg);
}
100% {
transform: perspective($perspective) rotateX(-180deg);
}
}
@keyframes backFlipDown {
0% {
transform: perspective($perspective) rotateX(180deg);
}
100% {
transform: perspective($perspective) rotateX(0deg);
}
}
@keyframes frontFlipUp {
0% {
transform: perspective($perspective) rotateX(0deg);
}
100% {
transform: perspective($perspective) rotateX(180deg);
}
}
@keyframes backFlipUp {
0% {
transform: perspective($perspective) rotateX(-180deg);
}
100% {
transform: perspective($perspective) rotateX(0deg);
}
}
// #endregion
.M-Flipper {
display: inline-block;
position: relative;
width: $width;
height: $height;
line-height: $height;
border: solid 1px $backColor;
border-radius: $radius;
background: $frontColor;
font-size: $width;
color: $frontColor;
box-shadow: 0 0 6px rgba($color: $shadowColor, $alpha: 0.5); // 阴影部分
text-align: center;
// font-family: 'Helvetica Neue';
.digital:before,
.digital:after {
content: '';
position: absolute;
left: 0;
right: 0;
background: $backColor;
overflow: hidden;
box-sizing: border-box;
}
.digital.front:before,
.digital.front:after {
content: attr(data-front) !important;
}
.digital.back:before,
.digital.back:after {
content: attr(data-back) !important;
}
.digital:before {
top: 0;
bottom: 50%;
border-radius: $radius $radius 0 0;
border-bottom: solid 1px rgba($color: $lineColor, $alpha: 0.3); // 中间线颜色
}
.digital:after {
top: 50%;
bottom: 0;
border-radius: 0 0 $radius $radius;
line-height: 0;
}
/*向下翻*/
&.down .front:before {
z-index: 3;
}
&.down .back:after {
z-index: 2;
transform-origin: 50% 0%;
transform: perspective($perspective) rotateX(180deg);
}
&.down .front:after,
&.down .back:before {
z-index: 1;
}
&.down.go .front:before {
transform-origin: 50% 100%;
animation: frontFlipDown $speed ease-in-out both;
box-shadow: 0 -2px 6px rgba($color: $lineColor, $alpha: 0.3);
backface-visibility: hidden;
}
&.down.go .back:after {
animation: backFlipDown $speed ease-in-out both;
}
/*向上翻*/
&.up .front:after {
z-index: 3;
}
&.up .back:before {
z-index: 2;
transform-origin: 50% 100%;
transform: perspective($perspective) rotateX(-180deg);
}
&.up .front:before,
&.up .back:after {
z-index: 1;
}
&.up.go .front:after {
transform-origin: 50% 0;
animation: frontFlipUp $speed ease-in-out both;
box-shadow: 0 2px 6px rgba($color: $lineColor, $alpha: 0.3);
backface-visibility: hidden;
}
&.up.go .back:before {
animation: backFlipUp $speed ease-in-out both;
}
}
</style>

View File

@@ -190,14 +190,11 @@ const handleChange = (e: MouseEvent, item: ListType) => {
width: 100px;
}
.select-min-width {
width: 115px;
width: 110px;
}
@include deep() {
.n-list-item {
border-bottom: 0!important;
}
.n-list-item__divider {
display: none!important;
.n-list-item:not(:last-child) {
border-bottom: 0;
}
}
}

View File

@@ -1,4 +1,3 @@
<!-- eslint-disable vue/valid-template-root -->
<template></template>
<script lang="ts" setup>

View File

@@ -230,15 +230,15 @@
</setting-item>
</setting-item-box>
<setting-item-box name="控制块">
<setting-item-box name="视觉映射">
<setting-item name="放置方向">
<n-select v-model:value="visualMap.orient" size="small" :options="axisConfig.visualMap.orient"></n-select>
</setting-item>
<setting-item name="宽度">
<n-input-number v-model:value="visualMap.itemWidth" :min="5" size="small"></n-input-number>
<n-input-number v-model:value="visualMap.temWidth" size="small"></n-input-number>
</setting-item>
<setting-item name="高度">
<n-input-number v-model:value="visualMap.itemHeight" :min="5" size="small"></n-input-number>
<n-input-number v-model:value="visualMap.itemHeight" size="small"></n-input-number>
</setting-item>
<setting-item name="反转">
<n-space>
@@ -252,6 +252,14 @@
</setting-item>
</setting-item-box>
<global-setting-position :targetData="visualMap"></global-setting-position>
<!-- <setting-item-box name="位置">
<setting-item name="距离底部">
<n-input-number v-model:value="visualMap.bottom" size="small"></n-input-number>
</setting-item>
<setting-item name="距离左侧">
<n-input-number v-model:value="visualMap.left" size="small"></n-input-number>
</setting-item>
</setting-item-box> -->
</collapse-item>
</template>

View File

@@ -1,12 +1,12 @@
<template>
<div v-show="isGroup">
<n-divider n-divider style="margin: 10px 0"></n-divider>
<n-tag type="warning"> 解散分组 {{ isCanvas ? '滤镜' : '滤镜 / 变换' }} 也将消失!</n-tag>
<n-tag type="warning"> 解散分组 {{ isCanvas ? '滤镜' : '滤镜 / 变换' }} 也将消失!</n-tag>
</div>
<collapse-item :name="isCanvas ? '滤镜' : '滤镜 / 变换'">
<template #header>
<n-switch v-model:value="chartStyles.filterShow" size="small"></n-switch>
<n-switch v-if="isCanvas" v-model:value="chartStyles.filterShow" size="small"></n-switch>
</template>
<setting-item-box name="色相" :alone="true">
<setting-item :name="`值:${chartStyles.hueRotate}deg`">
@@ -69,24 +69,6 @@
</setting-item>
</setting-item-box>
<!-- 混合模式 -->
<setting-item-box v-if="!isCanvas" :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>
<setting-item>
<n-select v-model:value="chartStyles.blendMode" size="small" filterable :options="BlendModeEnumList"></n-select>
</setting-item>
</setting-item-box>
<!-- 变换 -->
<setting-item-box v-if="!isCanvas" name="旋转°">
<setting-item name="Z轴(平面) - 旋转">
@@ -144,15 +126,14 @@
</setting-item-box>
<!-- 提示 -->
<n-tag type="warning"> 若预览时大屏模糊可以尝试关闭滤镜进行修复 </n-tag>
<n-tag v-show="isCanvas" type="warning"> 若预览时大屏模糊可以尝试关闭滤镜进行修复 </n-tag>
</collapse-item>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { PickCreateComponentType, BlendModeEnumList } from '@/packages/index.d'
import { PickCreateComponentType } from '@/packages/index.d'
import { SettingItemBox, SettingItem, CollapseItem } from '@/components/Pages/ChartItemSetting'
import { icon } from '@/plugins'
const props = defineProps({
isGroup: {
@@ -169,14 +150,14 @@ const props = defineProps({
}
})
const { HelpOutlineIcon } = icon.ionicons5
// 百分比格式化 person
// 百分比格式化persen
const sliderFormatTooltip = (v: string) => {
// @ts-ignore
return `${(parseFloat(v) * 100).toFixed(0)}%`
}
// 角度格式化
const degFormatTooltip = (v: string) => {
// @ts-ignore
return `${v}deg`
}
</script>

View File

@@ -1,7 +1,6 @@
<!-- eslint-disable vue/valid-template-root -->
<template></template>
<script lang="ts" setup>
import { useDialog } from 'naive-ui'
import { useDialog } from 'naive-ui';
//挂载在 window 方便与在js中使用
window['$dialog'] = useDialog()
window['$dialog'] = useDialog();
</script>

View File

@@ -1,4 +1,3 @@
<!-- eslint-disable vue/valid-template-root -->
<template></template>
<script lang="ts" setup>

View File

@@ -1,8 +1,7 @@
<!-- eslint-disable vue/valid-template-root -->
<template></template>
<script lang="ts" setup>
import { useMessage } from 'naive-ui'
import { useMessage } from 'naive-ui';
//挂载在 window 方便与在js中使用
window['$message'] = useMessage()
window['$message'] = useMessage();
</script>

View File

@@ -1,7 +1,7 @@
// 鼠标点击左右键
export enum MouseEventButton {
LEFT = 1,
RIGHT = 2
RIGHT = 2,
}
// 页面拖拽键名
@@ -40,17 +40,8 @@ export enum MenuEnum {
UN_GROUP = 'unGroup',
// 后退
BACK = 'back',
FORWORD = 'forward',
// 保存
SAVE = 'save',
// 锁定
LOCK = 'lock',
// 解除锁定
UNLOCK = 'unLock',
// 隐藏
HIDE = 'hide',
// 显示
SHOW = 'show'
// 前进
FORWORD = 'forward'
}
// Win 键盘枚举
@@ -58,9 +49,9 @@ export enum WinKeyboard {
CTRL = 'ctrl',
SHIFT = 'shift',
ALT = ' alt',
CTRL_SOURCE_KEY = 'control',
SHIFT_SOURCE_KEY = 'shift',
ALT_SOURCE_KEY = 'alt'
CTRL_SOURCE_KEY = "control",
SHIFT_SOURCE_KEY = "shift",
ALT_SOURCE_KEY = "alt"
}
// Mac 键盘枚举
@@ -69,19 +60,7 @@ export enum MacKeyboard {
CTRL = '⌘',
SHIFT = '⇧',
ALT = '⌥',
CTRL_SOURCE_KEY = '⌘',
SHIFT_SOURCE_KEY = '⇧',
ALT_SOURCE_KEY = '⌥'
}
// 同步状态枚举
export enum SyncEnum {
// 等待
PENDING,
// 开始
START,
// 成功
SUCCESS,
// 失败
FAILURE
CTRL_SOURCE_KEY = "⌘",
SHIFT_SOURCE_KEY = "⇧",
ALT_SOURCE_KEY = "⌥"
}

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

View File

@@ -20,15 +20,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

@@ -1,5 +1,4 @@
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/useChartDataFetch.hook'

View File

@@ -25,7 +25,7 @@ export const useChartDataFetch = (
const requestIntervalFn = () => {
const chartEditStore = useChartEditStore()
// 全局数据
const {
requestOriginUrl,
@@ -88,10 +88,7 @@ export const useChartDataFetch = (
// 开启轮询
if (time) fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit))
}
// eslint-disable-next-line no-empty
} catch (error) {
console.log(error);
}
} catch (error) {}
}
isPreview() && requestIntervalFn()

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 信息
const getOssUrl = async () => {
const res = await ossUrlApi({}) as unknown as MyResponseType
if (res.code === ResultEnum.SUCCESS) {
systemStore.setItem(SystemStoreEnum.FETCH_INFO, {
OSSUrl: res.data?.bucketURL
})
}
}
// 执行
getOssUrl()
}

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

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

@@ -24,7 +24,6 @@ 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'
import isObject from 'lodash/isObject'
const props = defineProps({
themeSetting: {
@@ -52,9 +51,8 @@ const option = computed(() => {
// dataset 无法变更条数的补丁
watch(
() => props.chartConfig.option.dataset,
(newData: { dimensions: any }, oldData) => {
if (!isObject(newData) || !('dimensions' in newData)) return
if (newData?.dimensions.length !== oldData?.dimensions.length) {
(newData, oldData) => {
if (newData.dimensions.length !== oldData.dimensions.length) {
const seriesArr = []
for (let i = 0; i < newData.dimensions.length - 1; i++) {
seriesArr.push(seriesItem)

View File

@@ -23,7 +23,6 @@ import { useChartDataFetch } from '@/hooks'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { isPreview } from '@/utils'
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import isObject from 'lodash/isObject'
const props = defineProps({
themeSetting: {
@@ -51,8 +50,7 @@ const option = computed(() => {
// dataset 无法变更条数的补丁
watch(
() => props.chartConfig.option.dataset,
(newData: { dimensions: any }, oldData) => {
if (!isObject(newData) || !('dimensions' in newData)) return
(newData, oldData) => {
if (newData?.dimensions.length !== oldData?.dimensions.length) {
const seriesArr = []
for (let i = 0; i < newData.dimensions.length - 1; i++) {

View File

@@ -24,7 +24,6 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore
import { useChartDataFetch } from '@/hooks'
import { isPreview } from '@/utils'
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import isObject from 'lodash/isObject'
const props = defineProps({
themeSetting: {
@@ -52,8 +51,7 @@ const option = computed(() => {
// dataset 无法变更条数的补丁
watch(
() => props.chartConfig.option.dataset,
(newData: { dimensions: any }, oldData) => {
if (!isObject(newData) || !('dimensions' in newData)) return
(newData, oldData) => {
if (newData?.dimensions.length !== oldData?.dimensions.length) {
const seriesArr = []
for (let i = 0; i < newData.dimensions.length - 1; i++) {

View File

@@ -1,156 +0,0 @@
import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
import { MapBaseConfig } from './index'
import { chartInitConfig } from '@/settings/designSetting'
import { CreateComponentType } from '@/packages/index.d'
import dataJson from './data.json'
export const includes = []
export const option = {
dataset: dataJson,
mapRegion: {
adcode: 'china',
showHainanIsLands: true
},
tooltip: {
show: true,
trigger: 'item'
},
visualMap: {
show: true,
orient: 'vertical',
pieces: [
{ gte: 1000, label: '>1000' }, // 不指定 max表示 max 为无限大Infinity
{ gte: 600, lte: 999, label: '600-999' },
{ gte: 200, lte: 599, label: '200-599' },
{ gte: 50, lte: 199, label: '49-199' },
{ gte: 10, lte: 49, label: '10-49' },
{ lte: 9, label: '<9' } // 不指定 min表示 min 为无限大(-Infinity
],
inRange: {
// 渐变颜色,从小到大
color: ['#c3d7df', '#5cb3cc', '#8abcd1', '#66a9c9', '#2f90b9', '#1781b5']
},
textStyle: {
color: '#fff'
}
},
geo: {
show: false,
type: 'map',
roam: false,
map: 'china',
selectedMode: false, //是否允许选中多个区域
zoom: 1
},
series: [
{
name: '',
type: 'effectScatter',
coordinateSystem: 'geo',
symbolSize: 4,
legendHoverLink: true,
showEffectOn: 'render',
rippleEffect: {
scale: 6,
color: '#FFFFFF',
brushType: 'fill'
},
tooltip: {
show: true,
backgroundColor: 'rgba(0,0,0,.6)',
borderColor: 'rgba(147, 235, 248, .8)',
textStyle: {
color: '#FFF'
}
},
label: {
formatter: '{b}',
fontSize: 11,
offset: [0, 2],
position: 'bottom',
textBorderColor: '#fff',
textShadowColor: '#000',
textShadowBlur: 10,
textBorderWidth: 0,
color: '#FFFFFF',
show: true
},
itemStyle: {
color: '#FFFFFF',
borderColor: 'rgba(225,255,255,2)',
borderWidth: 4,
shadowColor: '#E1FFFF',
shadowBlur: 10
},
data: []
},
{
name: '区域',
type: 'map',
map: 'china',
data: [],
selectedMode: false,
zoom: 1,
geoIndex: 1,
tooltip: {
show: true,
backgroundColor: '#00000060',
borderColor: 'rgba(147, 235, 248, 0.8)',
textStyle: {
color: '#FFFFFF',
fontSize: 12,
}
},
label: {
show: false,
color: '#FFFFFF',
fontSize: 12,
},
emphasis: {
disabled: false,
label: {
color: '#FFFFFF',
fontSize: 12,
},
itemStyle: {
areaColor: '#389BB7',
shadowColor: '#389BB7',
borderWidth: 1
}
},
itemStyle: {
borderColor: '#93EBF8',
borderWidth: 1,
areaColor: {
type: 'radial',
x: 0.5,
y: 0.5,
r: 0.8,
colorStops: [
{
offset: 0,
color: '#93ebf800' // 0% 处的颜色
},
{
offset: 1,
color: '#93ebf820' // 100% 处的颜色
}
],
globalCoord: false
},
shadowColor: '#80D9F842',
shadowOffsetX: -2,
shadowOffsetY: 2,
shadowBlur: 10
}
}
]
}
export const MapDefaultConfig = { ...option }
export default class Config extends PublicConfigClass implements CreateComponentType {
public key: string = MapBaseConfig.key
public attr = { ...chartInitConfig, w: 750, h: 800, zIndex: -1 }
public chartConfig = MapBaseConfig
public option = echartOptionProfixHandle(option, includes)
}

View File

@@ -1,277 +0,0 @@
<template>
<!-- Echarts 全局设置 -->
<global-setting :optionData="optionData"></global-setting>
<CollapseItem name="地图" :expanded="true">
<SettingItemBox name="地图区域">
<SettingItem name="默认中国">
<n-select
size="small"
v-model:value="mapRegion.adcode"
:options="mapRegionOptions"
value-field="adcode"
label-field="name"
/>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="区域颜色">
<SettingItem name="0%处颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].itemStyle.areaColor.colorStops[0].color"
></n-color-picker>
</SettingItem>
<SettingItem name="100%处颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].itemStyle.areaColor.colorStops[1].color"
></n-color-picker>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="阴影">
<SettingItem name="颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].itemStyle.shadowColor"
></n-color-picker>
</SettingItem>
<SettingItem name="模糊程度">
<n-input-number
v-model:value="seriesList[1].itemStyle.shadowBlur"
:min="0"
size="small"
placeholder="请输入模糊程度"
></n-input-number>
</SettingItem>
<SettingItem name="水平偏移">
<n-input-number
v-model:value="seriesList[1].itemStyle.shadowOffsetX"
size="small"
placeholder="请输入水平偏移大小"
></n-input-number>
</SettingItem>
<SettingItem name="垂直偏移">
<n-input-number
v-model:value="seriesList[1].itemStyle.shadowOffsetY"
size="small"
placeholder="请输入垂直偏移大小"
></n-input-number>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="地理信息名称">
<SettingItem name="显示">
<n-space>
<n-switch v-model:value="seriesList[1].label.show" size="small"></n-switch>
</n-space>
</SettingItem>
<SettingItem name="字体颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].label.color"
></n-color-picker>
</SettingItem>
<SettingItem name="字体大小">
<n-input-number
v-model:value="seriesList[1].label.fontSize"
:min="1"
size="small"
placeholder="请输入字体大小"
></n-input-number>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="悬浮 (预览可见)">
<SettingItem name="禁用">
<n-space>
<n-switch v-model:value="seriesList[1].emphasis.disabled" size="small"></n-switch>
</n-space>
</SettingItem>
<SettingItem name="颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].emphasis.itemStyle.areaColor"
></n-color-picker>
</SettingItem>
<SettingItem name="字体大小">
<n-input-number
v-model:value="seriesList[1].emphasis.label.fontSize"
:min="1"
size="small"
placeholder="请输入字体大小"
></n-input-number>
</SettingItem>
<SettingItem name="阴影">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].emphasis.itemStyle.shadowColor"
></n-color-picker>
</SettingItem>
<SettingItem name="边框大小">
<n-input-number
v-model:value="seriesList[1].emphasis.itemStyle.borderWidth"
:min="1"
size="small"
placeholder="请输入边框大小"
></n-input-number>
</SettingItem>
<SettingItem name="文字颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].emphasis.label.color"
></n-color-picker>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="悬浮弹窗">
<SettingItem name="显示">
<n-space>
<n-switch v-model:value="seriesList[1].tooltip.show" size="small"></n-switch>
</n-space>
</SettingItem>
<SettingItem name="字体大小">
<n-input-number
v-model:value="seriesList[1].tooltip.textStyle.fontSize"
:min="1"
size="small"
placeholder="请输入字体大小"
></n-input-number>
</SettingItem>
<SettingItem name="字体颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].tooltip.textStyle.color"
></n-color-picker>
</SettingItem>
<SettingItem name="背景颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].tooltip.backgroundColor"
></n-color-picker>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="区域边框">
<SettingItem name="颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="seriesList[1].itemStyle.borderColor"
></n-color-picker>
</SettingItem>
<SettingItem name="宽度大小">
<n-input-number
v-model:value="seriesList[1].itemStyle.borderWidth"
:min="1"
size="small"
placeholder="请输入边框大小"
></n-input-number>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="其他" v-if="mapRegion.adcode === 'china'">
<SettingItem>
<n-checkbox v-model:checked="mapRegion.showHainanIsLands" size="small">显示南海群岛</n-checkbox>
</SettingItem>
</SettingItemBox>
</CollapseItem>
<CollapseItem name="标记" :expanded="true">
<SettingItemBox name="样式">
<SettingItem name="大小">
<n-input-number v-model:value="seriesList[0].symbolSize" size="small" :min="0"></n-input-number>
</SettingItem>
<SettingItem name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="seriesList[0].itemStyle.color"></n-color-picker>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="文本">
<SettingItem name="显示">
<n-space>
<n-switch v-model:value="seriesList[0].label.show" size="small"></n-switch>
</n-space>
</SettingItem>
<SettingItem name="字体大小">
<n-input-number v-model:value="seriesList[0].label.fontSize" size="small" :min="0"></n-input-number>
</SettingItem>
<SettingItem name="字体颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="seriesList[0].label.color"></n-color-picker>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="涟漪">
<SettingItem name="涟漪大小">
<n-input-number
v-model:value="seriesList[0].rippleEffect.scale"
:min="1"
size="small"
placeholder="请输入涟漪大小"
></n-input-number>
</SettingItem>
<SettingItem name="涟漪颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="seriesList[0].rippleEffect.color"></n-color-picker>
</SettingItem>
<SettingItem name="涟漪的绘制方式">
<n-select size="small" v-model:value="seriesList[0].rippleEffect.brushType" :options="rippleEffectOptions" />
</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/index'
import { GlobalSetting } from '@/components/Pages/ChartItemSetting'
import { ref } from 'vue'
import mapChinaJson from './mapGeojson/china.json'
const mapRegionOptions = ref([
{
adcode: 'china',
name: '中国'
}
])
const rippleEffectOptions = ref([
{
value: 'fill',
label: '实心'
},
{
value: 'stroke',
label: '空心'
}
])
const props = defineProps({
optionData: {
type: Object as PropType<GlobalThemeJsonType>,
required: true
}
})
const initMapRegionOptions = () => {
mapChinaJson.features.forEach((element: any) => {
if (element.properties.name) {
mapRegionOptions.value.push({ ...element.properties })
}
})
}
initMapRegionOptions()
const seriesList = computed(() => {
return props.optionData.series
})
const mapRegion = computed(() => {
return props.optionData.mapRegion
})
</script>

View File

@@ -1,79 +0,0 @@
{
"point": [
{
"name": "北京",
"value": [116.405285, 39.904989, 200]
},
{
"name": "郑州",
"value": [113.665412, 34.757975, 888]
},
{
"name": "青海",
"value": [101.778916, 36.623178, 666]
},
{
"name": "宁夏回族自治区",
"value": [106.278179, 38.46637, 66]
},
{
"name": "哈尔滨市",
"value": [126.642464, 45.756967, 101]
}
],
"map": [
{
"name": "北京市",
"value": 666
},
{
"name": "河北省",
"value": 98
},
{
"name": "江苏省",
"value": 300
},
{
"name": "福建省",
"value": 1199
},
{
"name": "山东省",
"value": 86
},
{
"name": "河南省",
"value": 850
},
{
"name": "湖北省",
"value": 84
},
{
"name": "广西壮族自治区",
"value": 81
},
{
"name": "海南省",
"value": 900
},
{
"name": "青海省",
"value": 800
},
{
"name": "新疆维吾尔自治区",
"value": 7
}
],
"pieces": [
{ "gte": 1000, "label": ">1000" },
{ "gte": 600, "lte": 999, "label": "600-999" },
{ "gte": 200, "lte": 599, "label": "200-599" },
{ "gte": 50, "lte": 199, "label": "49-199" },
{ "gte": 10, "lte": 49, "label": "10-49" },
{ "lte": 9, "label": "<9" }
]
}

View File

@@ -1,15 +0,0 @@
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 = {
key: 'MapBase',
chartKey: 'VMapBase',
conKey: 'VCMapBase',
title: '地图(可选省份)',
category: ChatCategoryEnum.MAP,
categoryName: ChatCategoryEnumName.MAP,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.COMMON,
image
}

View File

@@ -1,144 +0,0 @@
<template>
<v-chart ref="vChartRef" :theme="themeColor" :option="option.value" :manual-update="isPreview()" autoresize>
</v-chart>
</template>
<script setup lang="ts">
import { PropType, reactive, watch, ref, nextTick } from 'vue'
import config, { includes } from './config'
import VChart from 'vue-echarts'
import { use, registerMap } from 'echarts/core'
import { EffectScatterChart, MapChart } from 'echarts/charts'
import { CanvasRenderer } from 'echarts/renderers'
import { useChartDataFetch } from '@/hooks'
import { mergeTheme } from '@/packages/public/chart'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { isPreview } from '@/utils'
import mapJsonWithoutHainanIsLands from './mapWithoutHainanIsLands.json'
import { DatasetComponent, GridComponent, TooltipComponent, GeoComponent, VisualMapComponent } from 'echarts/components'
const props = defineProps({
themeSetting: {
type: Object,
required: true
},
themeColor: {
type: Object,
required: true
},
chartConfig: {
type: Object as PropType<config>,
required: true
}
})
use([
MapChart,
DatasetComponent,
CanvasRenderer,
GridComponent,
TooltipComponent,
GeoComponent,
EffectScatterChart,
VisualMapComponent
])
const option = reactive({
value: mergeTheme(props.chartConfig.option, props.themeSetting, includes)
})
const vChartRef = ref<typeof VChart>()
//动态获取json注册地图
const getGeojson = (regionId: string) => {
return new Promise<boolean>(resolve => {
import(`./mapGeojson/${regionId}.json`).then(data => {
registerMap(regionId, { geoJSON: data.default as any, specialAreas: {} })
resolve(true)
})
})
}
//异步时先注册空的 保证初始化不报错
registerMap(props.chartConfig.option.mapRegion.adcode, { geoJSON: {} as any, specialAreas: {} })
// 进行更换初始化地图 如果为china 单独处理
const registerMapInitAsync = async () => {
await nextTick()
if (props.chartConfig.option.mapRegion.adcode!="china") {
await getGeojson(props.chartConfig.option.mapRegion.adcode)
}else{
await hainanLandsHandle(props.chartConfig.option.mapRegion.showHainanIsLands)
}
vEchartsSetOption()
}
registerMapInitAsync()
// 手动触发渲染
const vEchartsSetOption = () => {
option.value = props.chartConfig.option
vChartRef.value?.setOption(props.chartConfig.option)
}
// 更新数据处理
const dataSetHandle = async (dataset: any) => {
props.chartConfig.option.series.forEach((item: any) => {
if (item.type === 'effectScatter' && dataset.point) item.data = dataset.point
else if (item.type === 'map' && dataset.map) item.data = dataset.map
})
if (dataset.pieces) props.chartConfig.option.visualMap.pieces = dataset.pieces
isPreview() && vEchartsSetOption()
}
// 处理海南群岛
const hainanLandsHandle=async(newData:boolean)=>{
if (newData) {
await getGeojson('china')
} else {
registerMap('china', { geoJSON: mapJsonWithoutHainanIsLands as any, specialAreas: {} })
}
}
//监听 dataset 数据发生变化
watch(
() => props.chartConfig.option.dataset,
newData => {
dataSetHandle(newData)
},
{
immediate: true,
deep: false
}
)
//监听是否显示南海群岛
watch(
() => props.chartConfig.option.mapRegion.showHainanIsLands,
async newData => {
await hainanLandsHandle(newData)
vEchartsSetOption()
},
{
deep: false
}
)
//监听地图展示区域发生变化
watch(
() => props.chartConfig.option.mapRegion.adcode,
async newData => {
await getGeojson(newData)
props.chartConfig.option.geo.map = newData
props.chartConfig.option.series.forEach((item: any) => {
if (item.type === 'map') item.map = newData
})
vEchartsSetOption()
},
{
deep: false
}
)
// 预览
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
dataSetHandle(newData)
})
</script>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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