修复登录,修改ICON。权限过滤

main
LX 2023-12-12 11:16:38 +08:00
parent 0e275477ce
commit 559cd0929e
74 changed files with 82 additions and 1419 deletions

2
.env
View File

@ -1,5 +1,5 @@
# 网站标题
VITE_APP_TITLE='OpenDataV'
VITE_APP_TITLE='DataView'
# 端口
VITE_APP_PORT=8890

View File

@ -1,5 +1,5 @@
# 网站标题
VITE_APP_TITLE='OpenDataV'
VITE_APP_TITLE='DataView'
# 端口
VITE_APP_PORT=8890
@ -20,7 +20,7 @@ VITE_AUTH_TOKEN='Token'
VITE_TOKEN_STORAGE='localStorage'
# 网站是否不需要权限认证: NoAuth Auth
VITE_APP_NO_AUTH='NoAuth'
VITE_APP_NO_AUTH='Auth'
VITE_BACKIMAGE=''

View File

@ -1,5 +1,5 @@
# 网站标题
VITE_APP_TITLE='OpenDataV'
VITE_APP_TITLE='DataView'
# 端口
VITE_APP_PORT=8890
@ -20,7 +20,7 @@ VITE_AUTH_TOKEN='Token'
VITE_TOKEN_STORAGE='localStorage'
# 网站是否不需要权限认证: NoAuth Auth
VITE_APP_NO_AUTH='NoAuth'
VITE_APP_NO_AUTH='Auth'
VITE_BACKGROUND=''

View File

@ -1,64 +1,4 @@
## 简介
🎃这是一个纯前端的`拖拽式`、`可视化`、`低代码`数据可视化🌈开发平台,你可以用它自由的拼接成各种✨炫酷的大屏,同时支持用户方便的开发自己的组件并接入平台。
目前该项目在不断的完善中,
## 👁️预览
### 🤿 页面编辑
1. 组件添加
![screenshots2.gif](https://s2.loli.net/2022/10/31/nApiFm7PogI1dHS.gif)
2. 组件操作
![screenshots1.gif](https://s2.loli.net/2022/10/31/9lkiR15sVMLapIe.gif)
3. 组件数据配置
![screenshots.gif](https://s2.loli.net/2022/10/31/28lf6NK35EaY9wJ.gif)
### 🖇️ 接口管理
![API.png](https://s2.loli.net/2022/10/31/f1GuMTIp2rzEPQF.png)
## 💒功能
- 🎊 编辑器页面基本功能完成,包括编辑、预览、导入、导出、保存
- 🪄 图层的置顶、置底、上下移动、显示、隐藏、复制、剪切、粘贴
- 🖼️ 组件的缩放、旋转、拖动、复制、粘贴、组合、拆分、移除、自动对齐
- 🔮 支持用户操作记录的恢复、撤销功能
- 🧶 支持用户自定义组件
- 📔 支持组件的用户自定组件配置项
- 🏪 支持明暗主题切换
- 🧬 使用Monorepo模式进行组件和依赖管理
- 🧶 组件数据自定义接入
- 🔌 数据动态处理JS已完成
- 🖇️ 接口管理(示例数据、静态数据、HTTP接口数据已完成适配)
## 🎢技术点
本项目采用`Vue3` + `vite` + `TypeScript`开发,界面库使用`NaiveUI`使用面向对象方式封装了路由、请求、存储组件采用自动扫描注册、异步加载提升渲染速度使用IndexDB存储快照数据减少快照数据内存占用加快访问速度组件独立依赖解耦了组件和基础框架的依赖库方便后续独立开发组件。
目前仅开发了部分组件,后续还会继续完善。
## ⌛计划功能
- [ ] 组件管理
- [ ] 脚本管理Python待支持
- [ ] GraphQL、GRPC、WebScoket、MQTT、SocketIO多种数据接口适配
- [ ] 代码生成
- [ ] 动态文档
- [ ] 全局数据接入
## 💂开发
### 🧊开发环境
| 名称 | 版本 |
| ---- | ------- |
| node | 16.14.x |
| pnpm | 7.9.3 |
| vue | 3.2.37 |
🚥目前仅在 `Chrome``Microsoft Edge` 最新版浏览器测试过,其他浏览器未测试
### 🎮启动项目

View File

@ -2,7 +2,7 @@
<n-result
status="404"
title="文档正在编写中..."
description="star一下来为OpenDataV加速吧"
description="star一下来为DataView加速吧"
style="height: 100%"
>
<template #icon>

View File

@ -5,7 +5,7 @@
<RouterView />
<n-layout-footer position="absolute"
><div class="copyleft">
<div>OpenDataV · Made by AnsGoo</div>
<div>DataView · Made by AnsGoo</div>
</div></n-layout-footer
>
</n-layout>

View File

@ -50,14 +50,6 @@ const toolBars: ToolBarItemType[] = [
location: 'left'
},
...leftBars,
{
label: 'GitHub',
action: () => {
window.open('https://github.com/AnsGoo/openDataV', '_blank')
},
icon: 'github',
location: 'right'
},
{
label: '主题',
action: toggleTheme,

View File

@ -1,4 +1,4 @@
<template><LogoView width="65px" /><span class="title">OpenDataV</span></template>
<template><LogoView width="65px" /><span class="title">DataView</span></template>
<script lang="ts" setup>
import LogoView from '@/components/LogoView'
</script>

View File

@ -1,41 +0,0 @@
[toc]
# 为什么我不能保存我的页面?
openDataV 是一款基于Vue3的纯前端拖拽式低代码平台默认所有的接口都是Mock接口因此你不能进行任何写操作,因此保存更新之类的操作是无效果的;因为时间和精力不足,我们开发了一个简易的后台服务[https://gitee.com/small_bud_star/open-data-backend](https://gitee.com/small_bud_star/open-data-backend),便于大家使用,但是并不适合在生产环境中使用
我们也打算开发一个高性能的后台服务计划采用Spring套装或者Go语言感兴趣的大佬可以加入我们一起开发
# 为什么没有XXXX组件
我们对OpenDataV的定位更多是一个平台性质或者框架性质所以自带的组件更多是示例功能。
我们在实际应用中发现,组件的通用性和复杂度成反比,如果一个组件通用性很强,那么它的复杂度就很高,用户的的学习成本就会很大,这样就失去了低代码的意义;既然做不到通用性强,我们的工作重点也不会放在组件开发上;当然我们也会去开发一些有较大通用性的组件,但是站在个人经验来说,组件的开发本身应该是结合业务,根据具体业务有侧重点的开发,既能满足业务需求的变化,又简单易上手。
后期不排除我们会针对某个行业去开发一成套的组件,同时如果各位老板有定制组件的开发需求,我们也不排除去接一些定制组件开发的兼职。
# 怎么去开发一个新组件?
1. 学习开发文档
2. 学习官方组件例子
3. 关注公众号,查看往期文章
4. 和社区同伴交流
同时希望大家向本项目贡献自己的组件,被官方收录的组件请保证组件有较大的通用性、完善的示例文档,且和本项目保持一致的开源许可证, 如果未上传开源许可证,默认采用本项目的许可证。
# 我的组件依赖和其他组件公用一个`NPM`包,但是版本不一样怎么办?
整个OpenDataV是采用`Monorepo`方式管理组件以及依赖,严格意义上来说,每个组件都是独立的,每个组件有自己的`类型文件`、`依赖包`和`许可证`,删除任何一个组件不影响其他组件的使用。所以对于同一个包的不同版本,只要在各自的依赖中添加对应的版本即可,也可以像官方组件一样,多个组件共享同一个依赖。
同时对于官方组件你也可以按需引入,对于自己用不到的可以删除,不会有任何问题
# 想自己开发后台,如何知道本项目的接口?
可以查看项目 `src\api`接口文件和类型文件,当然你可以随意更改这些接口定义

View File

@ -1,102 +0,0 @@
[toc]
平台集成了`通用数据`管理功能,目前已完成`静态数据`和`Rest数据`功能开发
# 静态数据
静态数据是指平台提供了一个统一接口用来读取或者存储的数据
![](./img/015.png)
用户可以在静态页面对平台存储的静态数据进行`修改`、`删除`和`新增`
## 新增与修改
点击静态数据的`原始数据`页签,在代码编辑器里面可以对静态数据进行`修改`和`新增`,点击<x-icon name="save"/>按钮,即可将在`处理数据`页签看到,此静态数据被脚本处理完成之后的效果,点击右上角的保存按钮,即可将此静态书进行更新和保存
## 删除
在右侧静态数据列表中,鼠标右击即可删除对应的静态数据
## 设计思路
> 很多低代码平台的静态数据保存在页面中配置文件中,但是我们无法预测用户配置的静态数据大小,如果将静态数据存储在页面配置文件中,将会导致页面配置文件数据体积增大,进而影响页面渲染速度。
> 静态数据保存在平台后台的话又会带来另一个问题,静态数据在多个组件中被复用时,在某个组件中更改了静态数据内容时所带来的影响是不是可预见的,答案是否定的。
> 我们不建议在组件使用过程中更改静态数据内容,我们可以通过在每个组件中写不同的脚本来适配同一数据源在不同组件复用时数据差异。
> 静态数据的修改应该考虑数据被复用时,对使用的组件效果影响,因此我们将静态数据设计为存储在平台后端,在使用组件使用过程中不可更改,但是在静态数据页面可修改!
# Rest数据
`Rest 数据`是通过`HTTP`接口获取数据,应该是平台最主要的获取数据的方式,一个类似`PostMan`的接口调试
![](./img/16.png)
## 跨域拦截
因为浏览器的安全策略,一旦你的接口服务未配置跨域相关安全策略,那么是无法在本平台进行接口调试的,可以跟接口服务开发人员协调,支持跨域访问
## 设计思路
> `Rest数据`页面设计是类似于`PostMan`的作用,但是很遗憾,我们尚未达到`Postman`的效果,目前仅支持`application/json`数据的请求和响应,但是对于`FormData`、`Blob`和`ArrayBuffer`等数据尚未支持
> `Rest数据`的定义数据是可控的,主要是 `url`、`method`、`headers`、`params`、`data`,因此整个 `Rest数据`定义我们是保存在页面配置文件中的,我们支持在`Rest数据`页面增加或者修改接口定义,同时我们也支持在单个组件中添加接口,也就是说你修改任意一接口也不会影响已经在其他组件中被使用的该接口
# 脚本
为了提高组件的`复用性`和接口的`兼容性`,我们提供了脚本功能。
![](./img/17.png)
通过脚本你可以将`接口返回的数据`处理成`组件所需要的数据`,这样就你就无需担心你的组件和接口之间的无法兼容的问题。
目前我们的脚本只支持`javascript`,后续将支持`python`,因为`Python`在数据处理方面的先天优势十分的吸引我们,我们希望可以将`Python`的引入,可以和平台碰撞出耀眼的火光。
## Javascript脚本
`Javascript脚本` 我们使用的是js的 `new Function()`特性,因此`Javascript脚本`,你只需要书写函数体本身即可
例如
```javascript
const filterFunc = (respoptions) => {
return resp.filter(el => el.value > 30)
}
```
你只需要写
```javascript
return resp.filter(el => el.value > 30)
```
`Javascript脚本` 生成函数默认有两个位置参数`resp`和`options`
- `resp`: 需要处理的数据
- `options`: 在组件中使用,默认返回的组件的`propValue`属性
## Python脚本
待实现

View File

@ -1,536 +0,0 @@
[toc]
# 基础知识
## 入门须知
1. 本项目是基于`Vue3`开发,所有的组件都符合`Vue3`知识,对于`Vue3`知识不熟悉的同学建议,先学习`Vue3`相关知识
2. 本项目是采用`TypeScript`开发,若对于`TypeScript`知识欠缺的,可先熟悉一下`TypeScript`
3. 本项目中所有的组件只能在本项目中使用,无法保证在别的平台同样适用
# 编辑器
编辑器承载与渲染组件的容器,编辑提供了组件`拉伸`、`旋转`、`置顶`、`置底`、`组合`、`拆分`的能力,编辑器如下图:
![create](./img/006.png)
编辑器主要由以下功能分区组成:
> - 顶部的`工具栏` 常用工具按钮
> - 左侧的`资源栏` 组件和图层
> - 右侧的`属性栏` 属性分为组件属性和画布属性
> - 底部的`状态栏` 创建页面的状态
> - 中间的`画布` 承载组件的最顶层容器
# 组件
一个完整的组件又以下属性构成
> - `componentName`:组件名
> - `component` 组件对象渲染模板
> - `config`:组件配置项对象
> - `docs`:组件说明文档
## 组件名
组件名必须保证全局唯一,因为组件会被挂载到`Vue3`实例对象上
## 组件配置项对象
配置项对象是继承了 `CustomComponent` 抽象类的子类,在这里我们以静态文本为例
```typescript
/**
* {component}: 组件名
* {group}: 组件分类
* {name}: 组件label
* {id}: 组件ID
* {width}: 组件初始化长度
* {height}: 组件初始化高度
* {icon? }: 组件图标
* {DataMode? }: 数据接入模式
*/
class StaticTextComponent extends CustomComponent {
constructor(id?: string, name?: string, icon?: string) {
super({
component: componentName,
group: ComponentGroup.TEXT,
name: name ? name : '静态文本',
id,
width: 150,
height: 20,
icon,
dataMode: DataMode.SELF
})
}
}
```
各个属性含义
> - `component`: 组件名
> - `group`: 组件分类
> - `name`: 组件label
> - `id`: 组件ID
> - `width`: 组件初始化长度
> - `height`: 组件初始化高度
> - `icon? `: 组件图标
> - `DataMode? `: 数据接入模式
除过需要继承`CustomComponent` 抽象类外,还需要重新定义`_prop`和`_style`属性,
> - `_prop属性`:定义了组件可以更改的属性
> - `_style`: 定义了组件的外在的CSS样式
## 组件渲染模板对象
组件渲染模板对象是一个特殊的`Vue3`组件对象, 这个组件对象有一个`component`配置项对象,这里我展示Vue3 `setup script` 写法
```typescript
const props = defineProps<{
component: StaticTextComponent
}>()
```
## 组件分类
目前组件分为 16类分别是
- `BASIC`: 基础组件
- `BORDER`: 边框组件
- `DECORATION`: 装饰组件
- `LINE`: 线状图组件
- `BAR`: 柱状图组件
- `PIE`: 饼状图组件
- `MAP`: 地图组件
- `GAUGE`: 仪表盘组件
- `CUSTOM`: 自定义组件
- `TEXT`: 文本组件
- `TABLE`: 表格组件
- `NAVIFATION`: 导航组件
- `PROGERSS`: 进度条组件
- `THERMOMETER`: 温度计组件
- `OTHER`: 其他组件
用户按照组件特性选择对应的组件类型即可
## 组件属性
组件属性是定义了组件在编辑器右侧`属性栏`中的`属性`的可配置项
组件属性的由属性配置项对象`MetaContainerItem`和组件属性值对象构成
```typescript
[
{
label: '基础配置',
prop: 'base',
children: [
{
prop: 'type',
label: '文本类型',
type: FormType.SELECT,
props: {
defaultValue: 'text',
options: [
{ value: 'text', label: '文本' },
{ value: 'symbol', label: '符号' }
]
}
},
{
prop: 'text',
label: '自定义文本',
type: FormType.TEXT,
props: {
defaultValue: 'OpenDataV'
}
}
]
}
]
```
该配置项对应的组件属性分别是
```typescript
StaticTextType {
base: {
text: string
type: 'text' | 'symbol'
}
}
```
属性配置项对象`MetaContainerItem`
- `label`: 分类标签
- `prop`: 分类值
- `children`: `AttrType`子属性配置项集合
`AttrType`子属性配置项
- `label`: 值标签
- `prop`: 属性值
- `type`: 属性值的Form类型
- `showLabel`: 是否显示标签
- `props`: Form组件配置
- `help`: Form帮助信息
## 组件样式
### 公共样式
所有的组件都有`位置大小`这个公共样式,公共样式主要是组件在画布中的`坐标`、`尺寸`和`旋转度`三个类属性
### 其他样式
其他样式组件属性的定义类似只不过组件属性需要你在组件中根据业务将属性值渲染出来但是组件样式是里面的子属性值要求必须是CSS属性本平台已经实现了常见的CSS样式渲染
## 组件可用Form类型
本平台已经实现了常用的Form类型例如
> - `TEXT`: Input框
> - `TEXTAREA`: 文本域
> - `NUMBER`: 数字输入框
> - `SELECT`: 选择器
> - `COLOR`: 色盘
> - `RADIO`: 单选框
> - `SWITCH`: 开关
以及平台定制的Form类型 例如:
> - `FONT_STYLE`: 字体选择
> - `FONT_WEIGHT`: 字重选择
> - `ARRAY`: 动态列表Form
> - `BACKGROUND`: 背景选择
> - `LINEAR_GRADIENT`: 渐变色
还有支持用户自定义`Form`
> -`CUSTOM`: 自定义Form
**Form公共属性**
所有的Form 都有如下属性其次每一种Form类型可能拥有自己独有的属性
|属性名|含义|说明|
|----|---|---|
|editable|是否可编辑| bool型|
|disabled|是否禁用| bool型|
|required|是否必须| bool型|
|defaultValue|默认值| 任意类型|
|options|自有配置项| 任意类型|
1. TEXT Form属性
无专有属性
2. NUMBER Form属性
|属性名|含义|说明|
|----|---|---|
|min|最小值| 数字型|
|max|最大值| 数字型|
|step|步长| 数字型|
3. SELECT Form属性
|属性名|含义|说明|
|----|---|---|
|options|选项列表| `Array<{value:any, label:string}>`|
4. SWITCH Form属性
|属性名|含义|说明|
|----|---|---|
|options|选项列表| `Array<{value:any, label:string}>`|
5. RADIO Form属性
|属性名|含义|说明|
|----|---|---|
|options|选项列表| `Array<{value:any, label:string}>`|
6. ARRAY Form 属性
|属性名|含义|说明|
|----|---|---|
|count|数量| 数字型|
|type|类型| `static`长度不可变,`dynamic`长度可变|
|maxItem|最大数量| 数字型|
|minItem|最小数量| 数字型|
7. CUSTOM Form 属性
|属性名|含义|说明|
|----|---|---|
|componentType|组件| Form组件|
|args|组件参数|任何类型|
8. 自定义Form类型
我们自定义Form类型自定义Form组件需要实现属性`value`和`update:value`的`emit`方法,具体详见本平台`FONT_STYLE`或者`BACKGROUND`等平台定制Form组件
```typescript
const props = withDefaults(
defineProps<{
value?: number
}>(),
{
value: 400
}
)
const emits = defineEmits<{
(e: 'update:value', weight: number): void
(e: 'change', weight: number): void
}>()
```
## 监听组件属性
当用户通过`属性栏`的`属性`更改组件属性时,画布中的组件需要根据用户更改来,对组件进行重新渲染。
监听组件属性变化有三种方式
### watch 观测
可以通过深度监听,监听组件 `component`属性对象的`propValue`属性或者子属性来监听组件属性更改
```typescript
const customeText = ref<string>(props.propValue.base.text)
watch(
() => props.propValue.base.text,
(value: string) => {
customeText.value = value
}
)
```
### computed 计算属性
也可以通过computed计算组件 `component`属性对象的`propValue`属性或者子属性来监听组件属性更改
```typescript
const customeText = computed<string>(() => {
return props.propValue.base.text
})
```
### hooks
还可以通过平台提供的`useProp`hook来监听属性变化
```typescript
const customeText = ref<string>(props.propValue.base.text)
const propValueChange = (type:string, key:string, value:any) {
if(type === 'base' && key === 'text'){
customeText.value = value
}
}
const { propValue } = useProp<StaticTextType>(props.component, propValueChange)
```
### 注意事项
需要注意的事,只有在编辑模式下才需要监听组件属性变化,在预览模式下不需要监听组件属性变化,因此可以在组件中判断编辑器模式(`什么是编辑器模式,详见编辑器模式`),来决定是不是要对属性进行监听依次可以提升组件性能
## 数据
组件配置项对象在有一个`DataMode` 数据接入模式的属性,他定义了组件可以从那里接入数据
接入模式分为三类:
> - `SELF`: 组件自己内部自行接入数据
> - `UNIVERSAL`: 组件采用通用的方式接入数据
> - `GLOBAL`: 组件从订阅全局数据
### SELF
组件自己在内部通过不管通过`HTTP`或者`WebSocket` 自己处理数据的请求和响应,这时候组件的`属性栏`没有`数据`配置项
```typescript
const activeCount = ref<string>(props.propValue.base.count)
const getData = async () => {
const resp = await http.get({url: '/getdata'})
activeCount.value = resp.data
}
const intervalId:number = 0
onMounted( () => {
clearInterval(intervalId)
intervalId = setInterval( getData, 30000)
})
onUnmounted( () => {
clearInterval(intervalId)
})
```
### UNIVERSAL
组件采用`useData`hook来统一处理数据通用数据处理方式目前提供了三种数据接入方式分别是`示例数据`、`静态数据`、`Rest数据`
> - `示例数据`: 示例数据无法更改,主要 用来组件的展示,不建议在生产环境下使用
> - `静态数据`: 静态数据从后台数据库中存储的静态数据中加载
> - `Rest数据`: 根据用户提供的`REST`接口发起HTTP请求获取数据
```typescript
import { useData } from 'open-data-v/base/hooks'
let chartData:
| Array<{ label: string; value: number }>
| RequestResponse<Array<{ label: string; value: number }>>['afterData'] = []
const dataChange = (resp: any, _: DataType) => {
if (resp.status >= 0) {
chartData = resp.afterData
doSomething(chartData)
}
}
useData(props.component, dataChange)
```
`useData`钩子的第二个参数是一个数据处理回调,入参是获取到的数据,用户可以在回调中根据数据处理组件的渲染
### GLOBAL
待实现
# 监听组件尺寸
不管是在`画布`中`拉伸`组件还是通过`属性栏`的`样式`里面的`位置大小`属性进行配置,都会引起组件大小变动,可以通过`v-resize`指令来监听组件大小的更改,具体详见`常见指令`章节
# 编辑器模式
1. 模式分类
编辑器分为`编辑模式(EDIT)`、`预览模式(PREVIEW)`、`视图模式(VIEW)`
2. 模式作用
在组件中可以根据编辑器的模式来切换不同的表现形式,例如:
>
> - 在`编辑模式`下我们需要监听组件属性或者样式的变化,但是在`预览模式`和`视图模式`下我们不需要监听组件属性的变化,这时候我们可以获取编辑器模式,来在不同模式下采用不同的逻辑。
>
> - 在`编辑模式`下我们采用示例数据来渲染组件,但是在`预览模式`和`视图模式`下我们采用生产数据渲染组件。
3. 获取组件模式
我们可以通过`canvasState`来获取编辑器模式,例如
```typescript
import useCanvasState from 'open-data-v/designer/state/canvas'
const canvasState = useCanvasState()
// editoMode 即为编辑器模式
canvasState.editMode
// isEditMode 可以判断编辑器是否处于编辑模式
canvasState.isEditMode
```
# 常用指令
`v-resize` 组件缩放
组件编辑器中经常需要被拉伸进行放大或者缩小,可以采用我们封装的`v-resize`指令,来监听组件的大小变化,以便做出对应的响应
```html
<div v-size="resizeHander">我是组件</div>
```
```TypeScript
const resizeHandler = (entry: ResizeObserverEntry) => {
const {width, height}: DOMRectReadOnly = entry.contentRect
doSomething()
}
```
# 组件文档
本项目主体文档采用`Markdown`编写支持在Markdown中渲染Vue组件为了方便文档书写我们提供了一个工具组件`RenderComponent`,支持渲染任意组件,并提供`palyground`
```vue
<RenderComponent
:config="StaticTextComponent"
:component="StaticText"
:prop-value="{
base: {
text: '我们一起建设OpenDataV吧',
type: 'text'
}
}"
:style="{
color: '#d03050',
fontSize: 40,
fontWeight: 800,
width: 550,
height: 100
}
"
title="静态文本"
mode="debug"
/>
```
> - `mode`: 模式,可选项`debug`|`view`, 在`debug`下提供了`playground`功能
> - `component`: 组件模板
> - `config`:组件配置项类
> - `propValue`:组件属性初始化配置项
> - `style`:组件样式初始化配置项
大家在撰写组件文档时需要有如下内容
**1. 属性或者样式的解释**
**2. 效果示例**
**3. 可交互的`playground`**

View File

@ -1,155 +0,0 @@
[toc]
![](@/assets/logo.png)
<div class="badge">
![](https://img.shields.io/github/license/AnsGoo/openDataV)
![](https://img.shields.io/github/stars/AnsGoo/openDataV)
![](https://img.shields.io/github/issues/AnsGoo/openDataV)
![](https://img.shields.io/github/forks/AnsGoo/openDataV)
</div>
## 简介
🎃OpenDataV 是一个纯前端的`拖拽式`、`可视化`、`低代码`数据可视化 🌈 开发平台,你可以用它自由的拼接成各种 ✨ 炫酷的大屏,同时支持用户方便的开发自己的组件并接入平台。
## 体验
🧙国外:[http://datav.byteportrait.com/](http://datav.byteportrait.com/)
🧙国内:[http://small_bud_star.gitee.io/opendatav](http://small_bud_star.gitee.io/opendatav)
🧙国内:[http://opendatav.xingxingzaixian.fun/](http://opendatav.xingxingzaixian.fun/) (已对接后端)
## 源码地址:
🍨github:[https://github.com/AnsGoo/openDataV](https://github.com/AnsGoo/openDataV)
🍨gitee:[https://gitee.com/small_bud_star/DataV](https://gitee.com/small_bud_star/DataV)
gitee 仅做代码同步issues 或者 PR 请在 github 提交。
目前该项目在不断的完善中,🎉 欢迎 issuer,🌹 欢迎 start, 🎨 欢迎 commit, 🚀 欢迎 use...,💪 欢迎一切技术交流活动
## 👁️ 预览
### 🤿 页面编辑
1. 组件添加
![screenshots2.gif](https://s2.loli.net/2022/10/31/nApiFm7PogI1dHS.gif)
2. 组件操作
![screenshots1.gif](https://s2.loli.net/2022/10/31/9lkiR15sVMLapIe.gif)
3. 组件数据配置
![screenshots.gif](https://s2.loli.net/2022/10/31/28lf6NK35EaY9wJ.gif)
### 🖇️ 接口管理
![API.png](https://s2.loli.net/2022/10/31/f1GuMTIp2rzEPQF.png)
## 💒 功能
- 🎊 编辑器页面基本功能完成,包括编辑、预览、导入、导出、保存
- 🪄 图层的置顶、置底、上下移动、显示、隐藏、复制、剪切、粘贴
- 🖼️ 组件的缩放、旋转、拖动、复制、粘贴、组合、拆分、移除、自动对齐
- 🔮 支持用户操作记录的恢复、撤销功能
- 🧶 支持用户自定义组件
- 📔 支持组件的用户自定组件配置项
- 🏪 支持明暗主题切换
- 🧬 使用 Monorepo 模式进行组件和依赖管理
- 🧶 组件数据自定义接入
- 🔌 数据动态处理JS 已完成)
- 🖇️ 接口管理(示例数据、静态数据、HTTP 接口数据已完成适配)
## 🎢 技术点
本项目采用`Vue3` + `vite` + `TypeScript`开发,界面库使用`NaiveUI`,使用面向对象方式封装了路由、请求、存储,组件采用自动扫描注册、异步加载,提升渲染速度;使用 IndexDB 存储快照数据,减少快照数据内存占用,加快访问速度;组件独立依赖,解耦了组件和基础框架的依赖库,方便后续独立开发组件。
目前仅开发了部分组件,后续还会继续完善。
## ⌛ 计划功能
- [ ] 组件管理
- [ ] 脚本管理Python 待支持)
- [ ] GraphQL、GRPC、WebScoket、MQTT、SocketIO 多种数据接口适配
- [ ] 代码生成
- [ ] 动态文档
- [ ] 全局数据接入
## 💂 开发
### 🧊 开发环境
| 名称 | 版本 |
| ---- | ------- |
| node | 16.14.x |
| pnpm | 7.9.3 |
| vue | 3.2.37 |
🚥 目前仅在`Chrome`和`Microsoft Edge`最新版浏览器测试过,其他浏览器未测试
### 🎮 启动项目
```Bash
# 安装依赖
pnpm install
pnpm bootstrap
# 运行项目
pnpm dev
# 打包项目
pnpm build
```
## 🧑‍💻 代码提交
git commit 信息请按照如下规范进行书写
- feat: 新功能
- fix: 修复 Bug
- docs: 文档修改
- perf: 性能优化
- revert: 版本回退
- ci: CICD 集成相关
- test: 添加测试代码
- refactor: 代码重构
- build: 影响项目构建或依赖修改
- style: 不影响程序逻辑的代码修改
- other: 不属于以上类型的其他类型(日常事务)
## ☎️联系方式
**技术交流,请加微信群**
<img src="/wechat.png" style="width:430px">
**更新动态请关注公众号**
![wechat](/OfficialAccounts.jpg)
<script setup >
</script>
<style scoped>
.badge {
display: flex;
align-items: center;
align-content: center;
flex-wrap: nowrap;
flex-direction: row;
justify-content: center;
}
</style>

View File

@ -1,224 +0,0 @@
[toc]
## 开源合作
本项目使用`Apache-2.0`开源协议,二次开发及其商用请遵守开源协议即可,若想采用商用授权请联系`OpenDataV`的作者,可邮件 **haiven_123@163.com**
## 免责声明
任何企业或者个人使用`OpenDataV`原始项目或者二次开发,对自己或者他人造成的任何形式的损失或者危害,`OpenDataV`开发者不承担任何法律风险
## 权益声明
本项目使用`Apache-2.0`开源协议,二次开发及其商用请遵守开源协议即可,如若擅自违反开源协议产生的法律纠纷,`OpenDataV`将会追究到底
```license
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2022 AnsGoo
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```

View File

@ -1,220 +0,0 @@
[toc](目录)
快速创建一个属于自己的页面并发布
# 快速开始
接下来我们将带领大家创建一个页面,来熟悉该低代码平台的使用
## 安装
```Bash
git clone https://github.com/AnsGoo/openDataV.git
npm install pnpm -g
pnpm install
```
## 启动
```Bash
pnpm dev
```
## 编译
```Bash
pnpm build
```
# 访问布局管理
```Bash
/Pages
```
![管理页面](./img/005.png)
当前会展示出项目已有的页面,你可以点击页面卡片进行查看,也可以对已有页面进行二次编辑,还可以自己新创建一个页面
## 打开创建页面
点击`新建按钮`号会自动进入`创建`页面
![create](./img/006.png)
整个页面被分为:
- 顶部的`工具栏` 常用工具按钮
- 左侧的`资源栏` 组件和图层
- 右侧的`属性栏` 属性分为组件属性和画布属性
- 底部的`状态栏` 创建页面的状态
- 中间的`画布` 承载组件的最顶层容器
接下来我们将开始创建一个页面
# 添加第一组件
我们设计一个`HelloWord`文本页面
## 拖动组件
我们在左侧`资源栏`的组件中找到`柱状图`->`基础柱状图`组件,并将其拖动到画布中央,并单击鼠标左键选中组件
![text](./img/007.png)
## 修改组件属性
修改组件下列属性
- 数据配置的大值为`70`
- 坐标轴配置的X网格线`不显示`
- 坐标轴配置的轴线颜色为 `#18A058`
![text](./img/008.png)
同时我们可以对组件进行`拖动`、`旋转`、`拉伸`
<video muted autoplay="true" loop="true">
<source src="./img/010.mp4" type="video/mp4" />
</video>
## 配置组件数据
将组件的示例数据改为静态数据,切换组件数据类型,这里我们选择静态数据,并选择具体的静态数据
<video muted autoplay="true" loop="true">
<source src="./img/011.mp4" type="video/mp4" />
</video>
## 修改组件样式
所有的组件都有`位置大小`的公共样式,主要是用来设置组件的`坐标`、`尺寸`和`旋转`情况,你除过可以通过`拉伸`、`拖动`、`旋转`组件本身来改变这些值以外,还可以通过公共样式`位置大小`来精确更改。
这里我让将组件旋转状态改为0
<video muted autoplay="true" loop="true">
<source src="./img/012.mp4" type="video/mp4" />
</video>
# 组件间的操作
我们向画布中追加一个边框组件
![imag](./img/014.png)
## 选中
这里我们通过框选,选中`边框`和`柱状图`
- 框选
<video muted autoplay="true" loop="true">
<source src="./img/020.mp4" type="video/mp4" />
</video>
- ctr + '鼠标单击'
<video muted autoplay="true" loop="true">
<source src="./img/021.mp4" type="video/mp4" />
</video>
- 通过图层选中
<video muted autoplay="true" loop="true">
<source src="./img/022.mp4" type="video/mp4" />
</video>
## 组合
在选中框上右击组合进行组件的组合,这时候两个或者多个组件就被变成一个`分组`组件
<video muted autoplay="true" loop="true">
<source src="./img/023.mp4" type="video/mp4" />
</video>
## 拆分
我们也可以通过选中分组组件,然后鼠标右击对`分组`组件进行`拆分`
<video muted autoplay="true" loop="true">
<source src="./img/024.mp4" type="video/mp4" />
</video>
# 图层编辑
图层是组件的层级关系,越是靠近顶层的组件图层级别越高,组件图层级别高的可以遮盖图层级别低的组件,图层级别高低关系着组件的渲染顺序,从而影响用户页面的`视觉效果`(比如一张图片覆盖了另一张图片)和`交互效果`(点击效果无法触发)等;点击左侧`资源栏`一列的图层即可看到我们画图中所有组件之间的图层关系,默认组件的名称就是图层的名称。
## 更名
选中组件之后,每一个组件的都有属性一栏都有一个`公共属性`,可以通过更改`公共属性`的`名称`一栏来修改图层名称
## 移动
可以通过选中组件来,然后鼠标右击菜单栏里面的`置顶`、`上移一层`、`置底`、`下移一层`来更改组件的图层顺序
<video muted autoplay="true" loop="true">
<source src="./img/025.mp4" type="video/mp4" />
</video>
也可以通过`图层`一栏,鼠标右击的菜单栏里面的`置顶`、`上移一层`、`置底`、`下移一层`来更改组件的图层顺序
<video muted autoplay="true" loop="true">
<source src="./img/026.mp4" type="video/mp4" />
</video>
还可以通过拖动组件到对应的位置来修改图层顺序
<video muted autoplay="true" loop="true">
<source src="./img/027.mp4" type="video/mp4" />
</video>
## 隐藏、显示
在`图层`一栏,通过在图层上鼠标右击菜单栏里面的`显示`\\`隐藏`来显示或者隐藏组件,需要注意的是显示或者隐藏组件只是在画图中组件较多时,通过隐藏组件来减少画布中组件数量,便于用户编辑组件,在非编辑模式下无任何效果,只对编辑模式有效
# 修改画布
## 分辨率
我们支持针对不同的分辨率的设备,当设备分辨率比差异较大的情况下,可以通过指定分辨率使设计出来的页面达到最好的效果
## 页面背景
默认页面使背景色,我们支持页面修改为`背景色`、`渐变色`、`背景图`
<video muted autoplay="true" loop="true">
<source src="./img/028.mp4" type="video/mp4" />
</video>
# 预览并发布
当我们完成页面的设计,我们可以通过`工具栏`里面的预览按钮去预览一下页面效果效果,也可以通过`保存`按钮来保存我们的页面,还可以通过`导出`按钮将我们页面设计在本地进行保存。
<video muted autoplay="true" loop="true">
<source src="./img/029.mp4" type="video/mp4" />
</video>
至此一个简单的页面就设计完成了!

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

View File

@ -10,7 +10,7 @@ import { apiHttp as http } from '@/utils/http'
*/
export const loginApi = async (data: LoginData): Promise<AxiosResponse<string>> => {
return http.post<string>({
url: '/user/login',
url: '/api/auth/login2',
data: data
})
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 96 KiB

View File

@ -69,14 +69,7 @@
</div>
</n-dropdown>
</div>
<div class="layout-header-trigger layout-header-trigger-min">
<n-tooltip placement="bottom">
<template #trigger>
<x-icon name="github" :color="iconColor" @click="toGithub" />
</template>
<span>Github</span>
</n-tooltip>
</div>
<!--设置-->
<div class="layout-header-trigger layout-header-trigger-min" @click="openSetting">
<n-tooltip placement="bottom-end">
@ -186,9 +179,6 @@ const toggleFullscreenIcon = () => {
fullscreenIcon.value = document.fullscreenElement ? 'off-screen-one' : 'full-screen-one'
}
const toGithub = () => {
window.open('https://github.com/AnsGoo/openDataV', '_blank')
}
//
const toggleTheme = () => {

View File

@ -30,14 +30,6 @@ const toolBars: ToolBarItemType[] = [
divider: true,
location: 'left'
},
{
label: 'GitHub',
action: () => {
window.open('https://github.com/AnsGoo/openDataV', '_blank')
},
icon: 'github',
location: 'right'
},
{
label: '主题',
action: toggleTheme,

View File

@ -93,14 +93,6 @@ export default function useToolBars(
action: toggleTheme,
icon: () => h(ThemeIcon),
location: 'right'
},
{
label: 'GitHub',
action: () => {
window.open('https://github.com/AnsGoo/openDataV', '_blank')
},
icon: 'github',
location: 'right'
}
]
}

View File

@ -3,7 +3,7 @@
<div class="left">
<div class="name">
<span><img class="logo" src="/favicon.ico" alt="" /></span>
<span> OPenDataV</span>
<span> DataView</span>
</div>
<img class="home" src="/home.png" alt="" />
<div class="desc">
@ -92,9 +92,11 @@ const loginAction = async () => {
})
} else {
message.error('登录失败')
}
} catch (e: any) {
message.error(`登录失败,请输入正确的账号密码`)
}
} catch (e: unknown) {
Logger.log(e)

View File

@ -4,17 +4,25 @@
<script setup lang="ts">
/* eslint-disable-next-line @typescript-eslint/consistent-type-imports */
import { Previewer } from 'open-data-v/designer'
import { Previewer, useDataState, useScriptState } from 'open-data-v/designer'
import { onMounted, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { getPageApi } from '@/api/pages'
import { Logger } from '@/utils/utils'
import QuickDataPlugin from '@/data/Quick'
import RestDataPlugin from '@/data/Rest'
import { CustomScriptPlugin, SystemScriptPlugin } from 'open-data-v/scripts'
const viewer = ref<InstanceType<typeof Previewer> | null>(null)
const route = useRoute()
const router = useRouter()
const dataState = useDataState()
dataState.loadPlugins([QuickDataPlugin, RestDataPlugin])
const scriptState = useScriptState()
scriptState.loadPlugins([CustomScriptPlugin, SystemScriptPlugin])
const initComponents = async (index: string): Promise<void> => {
Logger.log('加载通用组件')

View File

@ -69,6 +69,7 @@ class RouteView {
curRouter.beforeEach((to, _, next) => {
NProgress.start()
// 如果网站不需要登录认证,所有路由直接切换
if (to.meta.ignoreAuth) {
next()

View File

@ -24,12 +24,22 @@ export const REDIRECT_ROUTE = {
const basicRoutes = [
{
path: '/',
name: 'Home',
name: 'Login2',
component: () => Layout,
redirect: 'Pages',
redirect: 'Login',
meta: {
title: '首页',
ignoreAuth: true,
title: '登录',
ignoreAuth: false,
hideInMenu: true
}
},
{
path: '/login',
name: 'Login',
component: () => import('@/pages/Login.vue'),
meta: {
title: '登录',
ignoreAuth: false,
hideInMenu: true
}
},
@ -49,6 +59,7 @@ const basicRoutes = [
component: () => import('@/pages/DesignerView/View.vue'),
meta: {
title: '创建页面',
ignoreAuth: false,
permission: 'CreatePage',
hideInMenu: true
}
@ -59,6 +70,7 @@ const basicRoutes = [
component: () => import('@/pages/DesignerView/View.vue'),
meta: {
title: '编辑页面',
ignoreAuth: false,
permission: 'EditePage',
hideInMenu: true
}
@ -69,6 +81,7 @@ const basicRoutes = [
component: () => import('@/pages/Preview.vue'),
meta: {
title: '预览界面',
ignoreAuth: false,
permission: 'PreviewPage',
hideInMenu: true
}
@ -88,6 +101,7 @@ const basicRoutes = [
component: () => import('@/pages/Pages.vue'),
meta: {
title: '页面管理',
ignoreAuth: false,
icon: 'page'
}
}

View File

@ -57,7 +57,7 @@
<div class="app-loading-svg">
<img src="/loading.svg" alt="loading" />
</div>
<div class="app-loading-title">OpenDataV</div>
<div class="app-loading-title">DataView</div>
</div>
</div>
</div>

View File

@ -2,7 +2,7 @@
"id": "1b0acf36-d309-43fe-9e0a-7b6942e2f953",
"name": "大宋疫情分布图",
"thumbnail": "https://s2.loli.net/2022/10/31/5j9iF1NI7YCQWhV.png",
"author": "OpenDataV",
"author": "DataView",
"isHome": false,
"dataIntegrationMode": "UNIVERSAL",
"canvasData": [
@ -710,4 +710,4 @@
"backgroundColor": "#272e3b"
}
}
}
}

View File

@ -2,7 +2,7 @@
"id": "1b0acf36-d309-43fe-9e0a-7b6942e2f953",
"name": "大汉疫情分布图",
"thumbnail": "https://s2.loli.net/2022/10/31/XWS4MnRTiLDwIKN.png",
"author": "OpenDataV",
"author": "DataView",
"isHome": false,
"dataIntegrationMode": "UNIVERSAL",
"canvasData": [
@ -710,4 +710,4 @@
"backgroundColor": "#272e3b"
}
}
}
}

View File

@ -2,7 +2,7 @@
"id": "1b0acf36-d309-43fe-9e0a-7b6942e2f953",
"name": "大唐疫情分布图",
"thumbnail": "https://s2.loli.net/2022/10/31/2W3ofP7aH4tmTBG.png",
"author": "OpenDataV",
"author": "DataView",
"isHome": false,
"dataIntegrationMode": "UNIVERSAL",
"canvasData": [
@ -710,4 +710,4 @@
"backgroundColor": "#272e3b"
}
}
}
}

View File

@ -4,7 +4,7 @@
"scripts": {
"bootstrap": "pnpm install",
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"build": "vite build",
"serve": "pnpm build && vite preview",
"lint": "eslint --ext .js,.ts,.vue,.tsx src/ examples/ docs/ resource/",
"lint:fromat": "prettier -c --parser typescript \"{src,__tests__,e2e}/**/*.[jt]s?(x)\"",
@ -13,6 +13,9 @@
"reinstall": "rimraf pnpm-lock.yaml && rimraf src/**/node_modules && rimraf node_modules && pnpm bootstrap"
},
"license": "Apache-2.0",
"eslintIgnore": [
"*"
],
"dependencies": {
"@codemirror/commands": "^6.2.4",
"@codemirror/lang-javascript": "^6.1.9",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

View File

@ -5,7 +5,7 @@
"main": "index.ts",
"scripts": {},
"keywords": [
"OpenDataV"
"DataView"
],
"author": "chenghaiwen",
"license": "Apache-2.0",

View File

@ -7,11 +7,11 @@
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"OpenDataV"
"DataView"
],
"author": "chenghaiwen",
"license": "Apache-2.0",
"dependencies": {
"flv.js": "^1.6.2"
}
}
}

View File

@ -4,7 +4,7 @@
"description": "边框",
"scripts": {},
"keywords": [
"OpenDataV"
"DataView"
],
"author": "qwecxzpoi",
"license": "Apache-2.0",

View File

@ -6,7 +6,7 @@
"scripts": {
},
"keywords": [
"OpenDataV"
"DataView"
],
"author": "chenghaiwen",
"license": "Apache-2.0"

View File

@ -41,7 +41,7 @@ class DecorationComponent extends CustomComponent {
label: '文本',
type: FormType.TEXT,
props: {
defaultValue: 'OpenDataV'
defaultValue: 'DataView'
}
}
]

View File

@ -5,7 +5,7 @@
"main": "index.ts",
"scripts": {},
"keywords": [
"OpenDataV"
"DataView"
],
"author": "chenghaiwen",
"license": "Apache-2.0",

View File

@ -5,7 +5,7 @@
"main": "index.ts",
"scripts": {},
"keywords": [
"OpenDataV"
"DataView"
],
"author": "chenghaiwen",
"license": "Apache-2.0",

View File

@ -5,10 +5,10 @@
"main": "index.ts",
"scripts": {},
"keywords": [
"OpenDataV"
"DataView"
],
"author": "chenghaiwen",
"license": "Apache-2.0",
"dependencies": {},
"devDependencies": {}
}
}

View File

@ -1,11 +1,11 @@
{
"name": "scrolltable",
"version": "1.0.0",
"description": "OpenDataV滚动表格",
"description": "DataView滚动表格",
"main": "ScrollTable/index.ts",
"scripts": {},
"keywords": [
"OpenDataV"
"DataView"
],
"author": "xingxingzaixian",
"license": "Apache-2.0"

View File

@ -9,7 +9,7 @@
:component="StaticText"
:prop-value="{
base: {
text: '我们一起建设OpenDataV吧',
text: '我们一起建设DataView吧',
type: 'text'
}
}"
@ -80,7 +80,7 @@ import StaticText from './StaticText.vue'
import type { StaticTextType } from './type'
const propValue: StaticTextType = {
base: {
text: 'OpenDataV',
text: 'DataView',
type: 'text'
}
}

View File

@ -38,7 +38,7 @@ class StaticTextComponent extends CustomComponent {
label: '自定义文本',
type: FormType.TEXT,
props: {
defaultValue: 'OpenDataV'
defaultValue: 'DataView'
}
}
]

View File

@ -30,14 +30,23 @@ const resizeHandler = (entry: ResizeObserverEntry) => {
const dataHandler = (event) => {
console.log(event)
customeText.value=event
customeText.value = event
}
onMounted(async () => {
try {
const queryParems = { tag: propValue.base.tag }
const res = await http.get({ url: propValue.base.url, params: queryParems })
if (res.status === 200 && Object.keys(res.data).includes(propValue.base.tag)) {
dataHandler(res.data)
}
} catch (error: any) {
console.log(error?.message)
}
})
const dataChange = (resp: any, _?: string) => {
console.log(resp)
if (!resp || !resp.data) {
if (!resp || !resp.data.data) {
console.log("数据失败-----")
return
}
@ -49,7 +58,6 @@ const dataChange = (resp: any, _?: string) => {
}
useData(props.component, dataChange)
useEventBus('globalData', dataHandler)
</script>
<style lang="less" scoped>

View File

@ -5,7 +5,7 @@
"main": "index.ts",
"scripts": {},
"keywords": [
"OpenDataV"
"DataView"
],
"author": "chenghaiwen",
"license": "Apache-2.0",

View File

@ -191,7 +191,6 @@ const dataChange = (resp: any, _?: string) => {
}
useData(props.component, dataChange)
useEventBus('globalData', dataHandler)
</script>
<style lang="less" scoped>

View File

@ -8,7 +8,7 @@ class SubTextComponent extends CustomComponent {
super({
component: componentName,
group: ComponentGroup.OTHER,
name: name ? name : '库位图',
name: name ? '库位图' : '库位图',
id,
width: 100,
height: 30,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 KiB

View File

@ -38,7 +38,7 @@ const setShowEm = () => {
}
const exportCanvas = (id: string) => {
const name: string = `${canvasState.name}` || 'OpenDataV'
const name: string = `${canvasState.name}` || 'DataView'
exportRaw(
`${name}.json`,
JSON.stringify({