Pre Merge pull request !273 from kakajun/master

This commit is contained in:
kakajun 2026-05-12 06:27:35 +00:00 committed by Gitee
commit 7c3ce463dc
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
31 changed files with 288 additions and 324 deletions

231
README.md
View File

@ -1,30 +1,122 @@
## 总览 </p>
<p align="center">
<a
href="https://ai.goviewlink.com/saas/"
target="_blank"
style="
padding: 10px 20px;
display: inline-block;
border-radius: 10px;
">
<img src="readme/GoViewPro.png" alt="go-view" />
</a>
</p>
![logo](readme/logo-t-y.png) <p align="center">
<img src="readme/logo-t-y.png" alt="go-view" />
</p>
GoView 是一个高效的拖拽式低代码数据可视化开发平台,将图表或页面元素封装为基础组件,无需编写代码即可制作数据大屏,减少心智负担。 <h4 align="center">
开源、精美、便捷的「数据可视化」低代码开发平台
</h4>
### 😶 纯 **前端** 分支: **`master`** <h4 align="center">
<img src="https://gitee.com/dromara/go-view/badge/star.svg?theme=gvp" style="position: relative; display: inline-block; top: 6px; border-radius: 0px;" />
<img src="https://gitcode.com/GoView/go-view/star/badge.svg" style="display: inline-block; position: relative; top: 4px;">
</h4>
### 👻 携带 **后端** 请求分支: **`master-fetch`** #### 长期赞助商
### 📚 GoView **文档** 地址:[http://www.mtruning.club:81/](http://www.mtruning.club:81/) <div>
<div align="center" style="column-gap: 20px;">
<a
href="http://www.ccflow.org/?from=goviewGitee"
target="_blank"
style="
padding: 10px 20px;
display: inline-block;
border-radius: 10px;
background: #f9f9f9;
">
<img src="readme/sponsors/ccflow-banner.png" alt="go-view" style="width: 250px;" width="250px" />
</a>
<span> &nbsp;</span>
<a
href="https://fastbee.cn/"
target="_blank"
style="
padding: 10px 20px;
display: inline-block;
border-radius: 10px;
background: #f9f9f9;
">
<img src="readme/sponsors/fb-banner.gif" alt="go-view" style="width: 250px;" width="250px"/>
</a>
<br/>
<br/>
<a
href="https://www.mingdao.com?s=utm_88&utm_source=Goview&utm_medium=banner&utm_campaign=gitee&utm_content=IT%E8%B5%8B%E8%83%BD%E4%B8%9A%E5%8A%A1"
target="_blank"
style="
padding: 10px 20px;
display: inline-block;
border-radius: 10px;
background: #f9f9f9;
">
<img src="readme/sponsors/mdy-banner.png" alt="go-view" style="width: 270px;" width="270px"/>
</a>
<a
href="https://doc.hummingbird.winc-link.com?from=Goview"
target="_blank"
style="
padding: 10px 20px;
display: inline-block;
border-radius: 10px;
background: #f9f9f9;
">
<img src="readme/sponsors/yingchuang-banner.png" alt="go-view" style="width: 270px;" width="270px"/>
</a>
<br/>
<br/>
<a
href="https://www.mtruning.club/chengDan/index.html"
target="_blank"
style="
padding: 10px 20px;
display: inline-block;
border-radius: 10px;
background: #f9f9f9;
">
<img src="readme/sponsors/chengdan-banner.png" alt="go-view" style="width: 270px;" width="270px"/>
</a>
</div>
</div>
项目纯前端-Demo 地址:[https://www.mtruning.club](https://www.mtruning.club) #### 😶 **纯前端** 分支: **`master`**
项目带后端-Demo 地址:[后端 Demo 地址](http://1.117.240.165:8080/goview/#/login) #### 👻 携带 **后端** 请求分支: **`master-fetch`**
文档-在线地址:[http://www.mtruning.club:81/](http://www.mtruning.club:81/) #### 📚 GoView **文档** 地址:[https://www.mtruning.club/](https://www.mtruning.club/)
文档-源码地址:[https://gitee.com/MTrun/go-view-doc](https://gitee.com/MTrun/go-view-doc) 项目纯前端-Demo 地址:[https://vue.mtruning.club/](https://vue.mtruning.club/)
### 🤯 后端项目 项目带后端-Demo 地址:[https://demo.mtruning.club/](https://demo.mtruning.club/)
后端项目 gitee 地址:[https://gitee.com/MTrun/go-view-serve](https://gitee.com/MTrun/go-view-serve) Cloud IDE 代码在线预览地址:[https://idegitee.com/dromara/go-view](https://idegitee.com/dromara/go-view)
接口说明地址:[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) #### 🤯 后端项目看这里!
技术点: 后端地址(社区实现,仅供参考):
- `JAVA` [https://gitee.com/MTrun/go-view-serve](https://gitee.com/MTrun/go-view-serve) (当前使用)
- `.NET` [https://gitee.com/sun_xiang_yu/go-view-dotnet](https://gitee.com/sun_xiang_yu/go-view-dotnet)
- `NODE` [https://gitee.com/qwdingyu/led](https://gitee.com/qwdingyu/led)
- `Docker 镜像` [https://gitee.com/AHEAD4/go-view-docker](https://gitee.com/AHEAD4/go-view-docker)
- `GO-goframe` [https://gitee.com/bufanyun/go-view-server](https://gitee.com/bufanyun/go-view-server)
- `GO-gin` [https://gitee.com/ls1990/go-view-serve](https://gitee.com/ls1990/go-view-serve)
- `接口文档` [https://docs.apipost.cn](https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3) (不是最新, 以前端代码为准)
#### 整体介绍
- 框架:基于 `Vue3` 框架编写,使用 `hooks` 写法抽离部分逻辑,使代码结构更加清晰; - 框架:基于 `Vue3` 框架编写,使用 `hooks` 写法抽离部分逻辑,使代码结构更加清晰;
@ -44,16 +136,31 @@ GoView 是一个高效的拖拽式低代码数据可视化开发平台,将图
![说明文档](readme/go-view-doc.png) ![说明文档](readme/go-view-doc.png)
工作台: 工作台:
![项目截图](readme/go-view-canvas.png) ![工作台](readme/go-view-canvas.png)
请求配置: 请求配置:
![项目截图](readme/go-view-fetch.png) ![请求配置](readme/go-view-fetch.png)
数据过滤: 数据过滤:
![项目截图](readme/go-view-filter.png) ![数据过滤](readme/go-view-filter.png)
高级事件编辑:
![高级事件编辑](readme/go-view-event.png)
自定义组件颜色:
![高级事件编辑](readme/go-view-echarts-color.png)
快捷主页:
![快捷主页](readme/go-view-indexpage.png)
主题色: 主题色:
![项目截图](readme/go-view-color.png) ![主题色](readme/go-view-color.png)
亮白主题:
![亮白主题](readme/go-view-theme.png)
最新动态: 整合字节图表框架 VChart[https://visactor.io/vchart](https://visactor.io/vchart)
![图表框架 VChart](readme/go-view-vcharts.png)
主要技术栈为: 主要技术栈为:
@ -66,21 +173,24 @@ GoView 是一个高效的拖拽式低代码数据可视化开发平台,将图
开发环境: 开发环境:
| 名称 | 版本 | 名称 | 版本 | | 名称 | 版本 | 名称 | 版本 |
| ---- | ------- | ------- | ----- | | ---- | ------- | ------- | ------ |
| node | 16.16.x | npm | 8.5.x | | node | 18.20.x | npm | 10.7.x |
| pnpm | 7.1.x | windows | 11 | | pnpm | 8.6.7 | windows | 11 |
已完成图表: 已完成图表:
| 分类 | 名称 | 名称 | 名称 | | 分类 | 名称 | 名称 | 名称 | 名称 |
| ------ | ---------------- | ---------------- | -------- | | ------ | ---------------- | ---------- | -------------- | ------------------------ |
| 图表 | 柱状图 | 横向柱状图 | 折线图 | | 图表 | 柱状图 | 横向柱状图 | 折线图 | 单/多 折线面积图(渐变色) |
| \* | 单/多 折线面积图 | 饼图 | 水球图 | | \* | 饼图 | 环形图 | 水球图 | 雷达图 |
| \* | 环形图 | NaiveUI 多种进度 | 🤠 | | \* | NaiveUI 多种进度 | 散点图 | 对数回归散点图 | 热力图 |
| 信息 | 文字 | 图片 | 😶 | | \* | 漏斗图 | 中国地图 | 高德地图 | 🦊 |
| 列表 | 滚动排名列表 | 滚动表格 | 🤓 | | 信息 | 文字 | 渐变文字 | 词云 | 嵌套网页 |
| 小组件 | 边框-01~13 | 装饰-01~05 | 数字翻牌 | | \* | 图片 | 视频 | 😺 | 🐯 |
| 列表 | 滚动排名列表 | 滚动表格 | 🐮 | 🐐 |
| 小组件 | 边框-01~13 | 装饰-01~05 | 数字翻牌 | 通用时间 |
| \* | 数字计数 | 倒计时 | 时钟 | 🦁 |
## 浏览器支持 ## 浏览器支持
@ -88,52 +198,7 @@ GoView 是一个高效的拖拽式低代码数据可视化开发平台,将图
## 安装 ## 安装
本项目采用` pnpm` 进行包管理 请查看文档:[https://www.mtruning.club/](https://www.mtruning.club/)
```shell
#建议使用 nrm 切换到淘宝源 https://registry.npmmirror.com/
#pnpm
pnpm install
#yarn
yarn install
#npm
npm install
```
## 启动
```shell
#pnpm
pnpm dev
# npm
npm run dev
#yarn
yarn dev
#Makefile
make dev
```
## 编译
```shell
#pnpm
pnpm run build
# npm
npm run build
#yarn
yarn run build
#Makefile
make dist
```
## 代码提交 ## 代码提交
@ -149,10 +214,18 @@ make dist
- style: 不影响程序逻辑的代码修改 - style: 不影响程序逻辑的代码修改
- chore: 不属于以上类型的其他类型(日常事务) - chore: 不属于以上类型的其他类型(日常事务)
## 交流 ## 交流
QQ 群:1030129384 QQ 群:687586375
![QQ群](readme/go-view-qq.png) <img width="260px" src="readme/go-view-qq.jpg" alt="QQ群" style="border-radius: 20px" />
## Pro 部分功能展示
体验地址: <a href="https://ai.goviewlink.com/saas/" target="_blank">https://ai.goviewlink.com/saas/</a>
<p align="center">
<img width="100%" src="readme/go-view-pro-ai.png" alt="GoViewProAI" style="border-radius: 4px" />
</p>
![渲染海报](readme/logo-poster.png) ![渲染海报](readme/logo-poster.png)

View File

@ -1,6 +1,6 @@
{ {
"name": "go-view", "name": "go-view",
"version": "1.1.11", "version": "1.3.2",
"engines": { "engines": {
"node": ">=16.14" "node": ">=16.14"
}, },
@ -48,7 +48,7 @@
"vue-i18n": "9.2.2", "vue-i18n": "9.2.2",
"vue-router": "4.0.12", "vue-router": "4.0.12",
"vue3-lazyload": "^0.2.5-beta", "vue3-lazyload": "^0.2.5-beta",
"vue3-sketch-ruler": "^1.3.3", "vue3-sketch-ruler": "^2.4.1",
"vuedraggable": "^4.1.0" "vuedraggable": "^4.1.0"
}, },
"devDependencies": { "devDependencies": {

26
pnpm-lock.yaml generated
View File

@ -111,8 +111,8 @@ importers:
specifier: ^0.2.5-beta specifier: ^0.2.5-beta
version: 0.2.5-beta(@vue/compiler-sfc@3.5.16)(vue@3.5.16(typescript@4.6.3)) version: 0.2.5-beta(@vue/compiler-sfc@3.5.16)(vue@3.5.16(typescript@4.6.3))
vue3-sketch-ruler: vue3-sketch-ruler:
specifier: ^1.3.3 specifier: ^2.4.1
version: 1.3.16(vue@3.5.16(typescript@4.6.3)) version: 2.4.1
vuedraggable: vuedraggable:
specifier: ^4.1.0 specifier: ^4.1.0
version: 4.1.0(vue@3.5.16(typescript@4.6.3)) version: 4.1.0(vue@3.5.16(typescript@4.6.3))
@ -3946,18 +3946,8 @@ packages:
'@vue/compiler-sfc': '>=3.0.0' '@vue/compiler-sfc': '>=3.0.0'
vue: '>=3.0.0' vue: '>=3.0.0'
vue3-sketch-ruler@1.3.16: vue3-sketch-ruler@2.4.1:
resolution: {integrity: sha512-k/TBOwbueU9eWOF7k/emsZMwtEqFk/FxG+h//TlaZ2B8RWbxhIe6hPFgggO4Jng10ARsuH4cMGAR+ZOuN4ozgg==} resolution: {integrity: sha512-TMMJ5v3cqDA94DPUa1iFHBx4D+FqEqpNXwzGU310aaMDllqyvyFfZigBFryeCRO7Q7EuOD5J5Zwc++LOCHB7Jw==}
deprecated: This version is deprecated. Please upgrade to version 2X for better features and performance.See https://github.com/kakajun/vue3-sketch-ruler
hasBin: true
peerDependencies:
'@vue/composition-api': ^1.1.0
vue: ^2.6.0 || ^3.2.0
peerDependenciesMeta:
'@vue/composition-api':
optional: true
vue:
optional: true
vue@3.5.16: vue@3.5.16:
resolution: {integrity: sha512-rjOV2ecxMd5SiAmof2xzh2WxntRcigkX/He4YFJ6WdRvVUrbt6DxC1Iujh10XLl8xCDRDtGKMeO3D+pRQ1PP9w==} resolution: {integrity: sha512-rjOV2ecxMd5SiAmof2xzh2WxntRcigkX/He4YFJ6WdRvVUrbt6DxC1Iujh10XLl8xCDRDtGKMeO3D+pRQ1PP9w==}
@ -4323,7 +4313,7 @@ snapshots:
'@types/node': 20.5.1 '@types/node': 20.5.1
chalk: 4.1.2 chalk: 4.1.2
cosmiconfig: 8.3.6(typescript@5.8.3) cosmiconfig: 8.3.6(typescript@5.8.3)
cosmiconfig-typescript-loader: 4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@5.8.3))(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.8.3))(typescript@5.8.3) cosmiconfig-typescript-loader: 4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@4.6.3))(ts-node@10.9.2(@types/node@16.18.126)(typescript@4.6.3))(typescript@5.8.3)
lodash.isplainobject: 4.0.6 lodash.isplainobject: 4.0.6
lodash.merge: 4.6.2 lodash.merge: 4.6.2
lodash.uniq: 4.5.0 lodash.uniq: 4.5.0
@ -5556,7 +5546,7 @@ snapshots:
core-util-is@1.0.3: {} core-util-is@1.0.3: {}
cosmiconfig-typescript-loader@4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@5.8.3))(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.8.3))(typescript@5.8.3): cosmiconfig-typescript-loader@4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@4.6.3))(ts-node@10.9.2(@types/node@16.18.126)(typescript@4.6.3))(typescript@5.8.3):
dependencies: dependencies:
'@types/node': 20.5.1 '@types/node': 20.5.1
cosmiconfig: 8.3.6(typescript@5.8.3) cosmiconfig: 8.3.6(typescript@5.8.3)
@ -8186,9 +8176,7 @@ snapshots:
'@vue/compiler-sfc': 3.5.16 '@vue/compiler-sfc': 3.5.16
vue: 3.5.16(typescript@4.6.3) vue: 3.5.16(typescript@4.6.3)
vue3-sketch-ruler@1.3.16(vue@3.5.16(typescript@4.6.3)): vue3-sketch-ruler@2.4.1: {}
optionalDependencies:
vue: 3.5.16(typescript@4.6.3)
vue@3.5.16(typescript@4.6.3): vue@3.5.16(typescript@4.6.3):
dependencies: dependencies:

10
preview.yml Normal file
View File

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

BIN
readme/GoViewPro.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

BIN
readme/go-view-pro-ai.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 773 KiB

BIN
readme/go-view-qq.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 475 KiB

View File

@ -12,7 +12,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, PropType, onMounted, watch, ref } from 'vue' import { computed, PropType, onMounted, watch } from 'vue'
import VChart from 'vue-echarts' import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook' import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use } from 'echarts/core' import { use } from 'echarts/core'

View File

@ -1,7 +1,7 @@
import type { App } from 'vue' import type { App } from 'vue'
import { GoSkeleton } from '@/components/GoSkeleton' import { GoSkeleton } from '@/components/GoSkeleton'
import { GoLoading } from '@/components/GoLoading' import { GoLoading } from '@/components/GoLoading'
import { SketchRule } from 'vue3-sketch-ruler' import SketchRule from 'vue3-sketch-ruler'
/** /**
* *

View File

@ -31,6 +31,4 @@ export interface ChartLayoutType {
[ChartLayoutStoreEnum.LAYER_TYPE]: LayerModeEnum [ChartLayoutStoreEnum.LAYER_TYPE]: LayerModeEnum
// 当前正在加载的数量 // 当前正在加载的数量
[ChartLayoutStoreEnum.PERCENTAGE]: number [ChartLayoutStoreEnum.PERCENTAGE]: number
// 是否重置当前画布位置
[ChartLayoutStoreEnum.RE_POSITION_CANVAS]: boolean
} }

View File

@ -49,9 +49,6 @@ export const useChartLayoutStore = defineStore({
}, },
getPercentage(): number { getPercentage(): number {
return this.percentage return this.percentage
},
getRePositionCanvas(): boolean {
return this.rePositionCanvas
} }
}, },
actions: { actions: {
@ -65,8 +62,6 @@ export const useChartLayoutStore = defineStore({
}) })
// 存储本地 // 存储本地
setLocalStorage(GO_CHART_LAYOUT_STORE, this.$state) setLocalStorage(GO_CHART_LAYOUT_STORE, this.$state)
// 这里需要标记重置画布位置
this.rePositionCanvas = true;
// 重新计算拖拽区域缩放比例 // 重新计算拖拽区域缩放比例
if (computedScale) { if (computedScale) {
setTimeout(() => { setTimeout(() => {

View File

@ -62,10 +62,15 @@ import { useDesignStore } from '@/store/modules/designStore/designStore'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d' import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore' import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore'
import { ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d'
const { LockClosedOutlineIcon, LockOpenOutlineIcon } = icon.ionicons5 const { LockClosedOutlineIcon, LockOpenOutlineIcon } = icon.ionicons5
const props = defineProps<{
reset?: () => void
zoomIn?: () => void
zoomOut?: () => void
}>()
// //
const designStore = useDesignStore() const designStore = useDesignStore()
const themeColor = ref(designStore.getAppTheme) const themeColor = ref(designStore.getAppTheme)
@ -105,8 +110,7 @@ const filterValue = ref('')
const selectHandle = (v: number) => { const selectHandle = (v: number) => {
selectInstRef.value?.blur() selectInstRef.value?.blur()
if (v === 0) { if (v === 0) {
chartLayoutStore.setItemUnHandle(ChartLayoutStoreEnum.RE_POSITION_CANVAS, true) props.reset?.()
chartEditStore.computedScale()
return return
} }
chartEditStore.setScale(v / 100) chartEditStore.setScale(v / 100)

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="go-edit-range go-transition" :style="rangeStyle" @mousedown="mousedownBoxSelect($event, undefined)"> <div class="go-edit-range go-transition" @mousedown="mousedownBoxSelect($event, undefined)">
<slot></slot> <slot></slot>
<!-- 水印 --> <!-- 水印 -->
<edit-watermark></edit-watermark> <edit-watermark></edit-watermark>
@ -33,15 +33,6 @@ const size = computed(() => {
} }
}) })
const rangeStyle = computed(() => {
//
const scale = {
transform: `scale(${getEditCanvas.value.scale})`
}
// @ts-ignore
return { ...useSizeStyle(size.value), ...scale }
})
// //
const rangeModelStyle = computed(() => { const rangeModelStyle = computed(() => {
const dragStyle = getEditCanvas.value.isCreate && { 'z-index': 99999 } const dragStyle = getEditCanvas.value.isCreate && { 'z-index': 99999 }
@ -52,6 +43,7 @@ const rangeModelStyle = computed(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
@include go(edit-range) { @include go(edit-range) {
height: 100%;
position: relative; position: relative;
transform-origin: left top; transform-origin: left top;
background-size: cover; background-size: cover;

View File

@ -2,82 +2,72 @@
<div class="go-sketch-rule"> <div class="go-sketch-rule">
<sketch-rule <sketch-rule
v-if="sketchRuleReDraw" v-if="sketchRuleReDraw"
ref="sketchRuleRef"
:thick="thick" :thick="thick"
:scale="scale" :scale="scale"
:width="canvasBox().width" :width="canvasBox().width"
:height="canvasBox().height" :height="canvasBox().height"
:startX="startX" :canvasWidth="width"
:startY="startY" :canvasHeight="height"
:lines="lines" :lines="lines"
:palette="paletteStyle" :palette="paletteStyle"
:isShowReferLine="true"
:shadow="shadow"
@zoomchange="handleZoomChange"
> >
</sketch-rule> <template #default>
<div ref="$app" class="edit-screens" @scroll="handleScroll"> <div ref="refSketchRuleBox" class="abc" :style="canvasStyle" @mousedown="dragCanvas">
<div ref="$container" class="edit-screen-container" :style="{ width: containerWidth }"> <slot></slot>
<div
ref="refSketchRuleBox"
class="canvas"
@mousedown="dragCanvas"
:style="{ marginLeft: '-' + (canvasBox().width / 2 - 25) + 'px' }"
>
<div :style="{ pointerEvents: isPressSpace ? 'none' : 'auto' }">
<slot></slot>
</div>
</div> </div>
</div> </template>
</div> </sketch-rule>
<!-- 修复右下角白点用的 -->
<!-- <div v-if="designStore.getDarkTheme" class="fix-edit-screens-block"></div> -->
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, onMounted, toRefs, watch, onUnmounted, computed } from 'vue' import { ref, reactive, onMounted, toRefs, watch, onUnmounted, computed } from 'vue'
import type { CSSProperties } from 'vue'
import { listen } from 'dom-helpers' import { listen } from 'dom-helpers'
import { useDesignStore } from '@/store/modules/designStore/designStore' import { useDesignStore } from '@/store/modules/designStore/designStore'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore'
import { ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d'
import throttle from 'lodash/throttle' import throttle from 'lodash/throttle'
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
const chartLayoutStore = useChartLayoutStore()
const designStore = useDesignStore() const designStore = useDesignStore()
const thick = 20 const thick = 20
let prevMoveXValue = [0, 0]
let prevMoveYValue = [0, 0]
const $app = ref() const sketchRuleRef = ref()
const sketchRuleReDraw = ref(true) const sketchRuleReDraw = ref(false)
const refSketchRuleBox = ref()
const $container = ref()
const isPressSpace = ref(false) const isPressSpace = ref(false)
const cursorStyle = ref('auto') const cursorStyle = ref('auto')
const { width, height } = toRefs(chartEditStore.getEditCanvasConfig) const { width, height } = toRefs(chartEditStore.getEditCanvasConfig)
const startX = ref(0)
const startY = ref(0)
const lines = reactive({ h: [], v: [] }) const lines = reactive({ h: [], v: [] })
const scale = computed(() => { const scale = computed(() => chartEditStore.getEditCanvas.scale)
return chartEditStore.getEditCanvas.scale
})
// // panzoom store
const containerWidth = computed(() => { let isUpdatingFromPanzoom = false
return `${window.innerWidth * 2}px` watch(
}) () => chartEditStore.getEditCanvas.scale,
newScale => {
// if (isUpdatingFromPanzoom) {
const containerHeight = computed(() => { isUpdatingFromPanzoom = false
return `${height.value * 2}px` return
}) }
const panzoom = sketchRuleRef.value?.panzoomInstance
if (panzoom && Math.abs(panzoom.getScale() - newScale) > 0.001) {
panzoom.zoom(newScale)
}
}
)
// //
const paletteStyle = computed(() => { const paletteStyle = computed(() => {
const isDarkTheme = designStore.getDarkTheme const isDarkTheme = designStore.getDarkTheme
return isDarkTheme return isDarkTheme
? { ? {
bgColor: '#18181c', bgColor: 'transparent',
longfgColor: '#4d4d4d', longfgColor: '#4d4d4d',
shortfgColor: '#4d4d4d', shortfgColor: '#4d4d4d',
fontColor: '#4d4d4d', fontColor: '#4d4d4d',
@ -85,42 +75,29 @@ const paletteStyle = computed(() => {
borderColor: '#18181c', borderColor: '#18181c',
cornerActiveColor: '#18181c' cornerActiveColor: '#18181c'
} }
: {} : { bgColor: 'transparent' }
}) })
// //
const themeColor = computed(() => { const themeColor = computed(() => {
return designStore.getAppTheme return designStore.getAppTheme
}) })
const canvasStyle = computed((): CSSProperties => {
// return {
const handleWheel = (e: any) => { pointerEvents: isPressSpace.value ? ('none' as const) : ('auto' as const),
if (e.ctrlKey || e.metaKey) { width: `${width.value}px`,
e.preventDefault() height: `${height.value}px`
let resScale = scale.value
// (200%)
if (e.wheelDelta >= 0 && scale.value < 2) {
resScale = scale.value + 0.05
chartEditStore.setScale(resScale)
return
}
// (10%)
if (e.wheelDelta < 0 && scale.value > 0.1) {
resScale = scale.value - 0.05
chartEditStore.setScale(resScale)
}
} }
} })
// thick
// const shadow = computed(() => {
const handleScroll = () => { return {
if (!$app.value) return x: 0,
const screensRect = $app.value.getBoundingClientRect() y: 0,
const canvasRect = refSketchRuleBox.value.getBoundingClientRect() width: 200,
// height: 200
startX.value = (screensRect.left + thick - canvasRect.left) / scale.value }
startY.value = (screensRect.top + thick - canvasRect.top) / scale.value })
}
// //
const dragCanvas = (e: any) => { const dragCanvas = (e: any) => {
@ -132,30 +109,8 @@ const dragCanvas = (e: any) => {
// @ts-ignore // @ts-ignore
document.activeElement?.blur() document.activeElement?.blur()
const startX = e.pageX
const startY = e.pageY
const listenMousemove = listen(window, 'mousemove', (e: any) => {
const nx = e.pageX - startX
const ny = e.pageY - startY
const [prevMoveX1, prevMoveX2] = prevMoveXValue
const [prevMoveY1, prevMoveY2] = prevMoveYValue
prevMoveXValue = [prevMoveX2, nx]
prevMoveYValue = [prevMoveY2, ny]
$app.value.scrollLeft -=
prevMoveX2 > prevMoveX1 ? Math.abs(prevMoveX2 - prevMoveX1) : -Math.abs(prevMoveX2 - prevMoveX1)
$app.value.scrollTop -=
prevMoveY2 > prevMoveY1 ? Math.abs(prevMoveY2 - prevMoveY1) : -Math.abs(prevMoveY2 - prevMoveY1)
})
const listenMouseup = listen(window, 'mouseup', () => { const listenMouseup = listen(window, 'mouseup', () => {
listenMousemove()
listenMouseup() listenMouseup()
prevMoveXValue = [0, 0]
prevMoveYValue = [0, 0]
isPressSpace.value = false isPressSpace.value = false
}) })
} }
@ -183,16 +138,7 @@ const reDraw = throttle(() => {
setTimeout(() => { setTimeout(() => {
sketchRuleReDraw.value = true sketchRuleReDraw.value = true
}, 10) }, 10)
},20) }, 20)
//
const canvasPosCenter = () => {
const { width: containerWidth, height: containerHeight } = $container.value.getBoundingClientRect()
const { width, height } = canvasBox()
$app.value.scrollLeft = containerWidth / 2 - width / 2
$app.value.scrollTop = containerHeight / 2 - height / 2
}
// //
watch( watch(
@ -202,21 +148,6 @@ watch(
} }
) )
// //
watch(
() => scale.value,
(newValue, oldValue) => {
if (oldValue !== newValue && chartLayoutStore.getRePositionCanvas) {
chartLayoutStore.setItemUnHandle(ChartLayoutStoreEnum.RE_POSITION_CANVAS, false)
}
handleScroll()
setTimeout(() => {
canvasPosCenter()
reDraw()
}, 400)
}
)
// //
watch( watch(
() => isPressSpace.value, () => isPressSpace.value,
@ -225,68 +156,71 @@ watch(
} }
) )
const handleZoomChange = (detail: any) => {
isUpdatingFromPanzoom = true
chartEditStore.setScale(detail.scale)
}
onMounted(() => { onMounted(() => {
if ($app.value) { // canvasBox()
$app.value.addEventListener('wheel', handleWheel, { passive: false }) sketchRuleReDraw.value = true
canvasPosCenter() window.onKeySpacePressHold = (isHold: boolean) => {
isPressSpace.value = isHold
} }
}) })
onUnmounted(() => { onUnmounted(() => {
if ($app.value) { window.onKeySpacePressHold = undefined
$app.value.removeEventListener('wheel', handleWheel)
}
}) })
window.onKeySpacePressHold = (isHold: boolean) => { const reset = () => sketchRuleRef.value?.reset?.()
isPressSpace.value = isHold const zoomIn = () => sketchRuleRef.value?.zoomIn?.()
} const zoomOut = () => sketchRuleRef.value?.zoomOut?.()
defineExpose({
reset,
zoomIn,
zoomOut
})
</script> </script>
<style> <style>
/* 使 SCSS 使 CSS
此库有计划 Vue3 版本但是开发的时候还没发布 */
#mb-ruler {
top: 0;
left: 0;
}
/* 横线 */ /* 横线 */
#mb-ruler .v-container .lines .line { .sketch-ruler .v-container .lines .line {
/* 最大缩放 200% */ /* 最大缩放 200% */
width: 200vw !important; width: 200vw !important;
border-top: 1px dashed v-bind('themeColor') !important; border-top: 1px dashed v-bind('themeColor') !important;
} }
#mb-ruler .v-container .indicator { .sketch-ruler .v-container .indicator {
border-bottom: 1px dashed v-bind('themeColor') !important; border-bottom: 1px dashed v-bind('themeColor') !important;
} }
/* 竖线 */ /* 竖线 */
#mb-ruler .h-container .lines .line { .sketch-ruler .h-container .lines .line {
/* 最大缩放 200% */ /* 最大缩放 200% */
height: 200vh !important; height: 200vh !important;
border-left: 1px dashed v-bind('themeColor') !important; border-left: 1px dashed v-bind('themeColor') !important;
} }
#mb-ruler .h-container .indicator { .sketch-ruler .h-container .indicator {
border-left: 1px dashed v-bind('themeColor') !important; border-left: 1px dashed v-bind('themeColor') !important;
} }
/* 坐标数值背景颜色 */ /* 坐标数值背景颜色 */
#mb-ruler .indicator .value { .sketch-ruler .indicator .value {
background-color: rgba(0, 0, 0, 0); background-color: rgba(0, 0, 0, 0);
} }
/* 删除按钮 */ /* 删除按钮 */
#mb-ruler .line .del { .sketch-ruler .line .del {
padding: 0; padding: 0;
color: v-bind('themeColor'); color: v-bind('themeColor');
font-size: 26px; font-size: 26px;
font-weight: bolder; font-weight: bolder;
} }
#mb-ruler .corner { .sketch-ruler .corner {
border-width: 0 !important; border-width: 0 !important;
} }
</style> </style>
@ -297,60 +231,10 @@ window.onKeySpacePressHold = (isHold: boolean) => {
width: 100%; width: 100%;
height: 100%; height: 100%;
.edit-screens {
position: absolute;
width: 100%;
height: 100%;
overflow: auto;
user-select: none;
padding-bottom: 0px;
/* firefox */
scrollbar-color: rgba(144, 146, 152, 0.3) transparent;
scrollbar-width: thin;
/* chrome */
&::-webkit-scrollbar,
&::-webkit-scrollbar-track-piece {
background-color: transparent;
}
&::-webkit-scrollbar {
width: 7px;
}
&::-webkit-scrollbar-thumb {
border-radius: 5px;
background-color: rgba(144, 146, 152, 0.3);
}
//
&::-webkit-scrollbar-corner {
background-color: transparent;
}
}
.fix-edit-screens-block {
position: absolute;
bottom: 0;
right: 0;
width: 10px;
height: 10px;
background-color: $--color-dark-bg-1;
}
.edit-screen-container {
position: absolute;
height: v-bind('containerHeight');
top: 0;
left: 0;
}
.canvas { .canvas {
position: absolute; position: absolute;
top:50%; top: 0;
left: 50%; left: 0;
transform-origin: 50% 0;
transform: translateY(-50%);
&:hover { &:hover {
cursor: v-bind('cursorStyle'); cursor: v-bind('cursorStyle');

View File

@ -1,5 +1,4 @@
<template> <template>
<!-- <edit-rule></edit-rule> -->
<content-box <content-box
id="go-chart-edit-layout" id="go-chart-edit-layout"
:flex="true" :flex="true"
@ -13,7 +12,7 @@
@dragover="dragoverHandle" @dragover="dragoverHandle"
@dragenter="dragoverHandle" @dragenter="dragoverHandle"
> >
<edit-rule> <edit-rule ref="editRuleRef">
<!-- 画布主体 --> <!-- 画布主体 -->
<div id="go-chart-edit-content" @contextmenu="handleContextMenu"> <div id="go-chart-edit-content" @contextmenu="handleContextMenu">
<!-- 展示 --> <!-- 展示 -->
@ -30,7 +29,7 @@
<!-- 分组 --> <!-- 分组 -->
<edit-group <edit-group
v-if="item.isGroup" v-if="item.isGroup"
:groupData="(item as CreateComponentGroupType)" :groupData="item as CreateComponentGroupType"
:groupIndex="index" :groupIndex="index"
></edit-group> ></edit-group>
@ -40,9 +39,9 @@
:data-id="item.id" :data-id="item.id"
:index="index" :index="index"
:style="{ :style="{
...useComponentStyle(item.attr, index), ...useComponentStyle(item.attr, index),
...getBlendModeStyle(item.styles) as any ...(getBlendModeStyle(item.styles) as any),
}" }"
:item="item" :item="item"
@click="mouseClickHandle($event, item)" @click="mouseClickHandle($event, item)"
@mousedown="mousedownHandle($event, item)" @mousedown="mousedownHandle($event, item)"
@ -77,13 +76,17 @@
<!-- 底部控制 --> <!-- 底部控制 -->
<template #bottom> <template #bottom>
<EditBottom></EditBottom> <EditBottom
:reset="editRuleMethods.reset"
:zoom-in="editRuleMethods.zoomIn"
:zoom-out="editRuleMethods.zoomOut"
></EditBottom>
</template> </template>
</content-box> </content-box>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, computed, provide, watch } from 'vue' import { onMounted, computed, provide, watch, ref } from 'vue'
import { chartColors } from '@/settings/chartThemes/index' import { chartColors } from '@/settings/chartThemes/index'
import { MenuEnum } from '@/enums/editPageEnum' import { MenuEnum } from '@/enums/editPageEnum'
import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d' import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
@ -181,6 +184,13 @@ const rangeStyle = computed(() => {
// vChart // vChart
useInitVChartsTheme(chartEditStore) useInitVChartsTheme(chartEditStore)
const editRuleRef = ref()
const editRuleMethods = {
reset: () => editRuleRef.value?.reset?.(),
zoomIn: () => editRuleRef.value?.zoomIn?.(),
zoomOut: () => editRuleRef.value?.zoomOut?.()
}
// //
onMounted(() => { onMounted(() => {
useAddKeyboard() useAddKeyboard()
@ -197,6 +207,7 @@ onMounted(() => {
@include goId('chart-edit-content') { @include goId('chart-edit-content') {
overflow: hidden; overflow: hidden;
height: 100%;
@extend .go-transition; @extend .go-transition;
@include fetch-theme('box-shadow'); @include fetch-theme('box-shadow');

View File

@ -7,3 +7,7 @@ declare module '*.vue' {
declare module 'lodash/*' declare module 'lodash/*'
declare module 'dom-helpers' declare module 'dom-helpers'
declare module 'vue3-sketch-ruler'; declare module 'vue3-sketch-ruler';
declare module 'lodash/*'
declare module 'dom-helpers'
declare module 'vue3-sketch-ruler';

View File

@ -12,6 +12,11 @@ function pathResolve(dir: string) {
export default defineConfig({ export default defineConfig({
base: '/', base: '/',
// 修改端口
server: {
port: 3020,
open: true,
},
// 路径重定向 // 路径重定向
resolve: { resolve: {
alias: [ alias: [