This commit is contained in:
2026-04-08 21:26:18 +08:00
commit 8fdc7ac0c3
401 changed files with 53093 additions and 0 deletions

463
README.md Normal file
View File

@@ -0,0 +1,463 @@
# CSLAB-DCS-Web
**DCS分布式控制系统跨平台可视化组态编辑器**
面向工业控制场景的画布组态设计、数据绑定、实时仿真与运行监控平台,支持 Web、Electron、Tauri 三端部署。
---
## 目录
- [项目简介](#项目简介)
- [技术栈](#技术栈)
- [项目结构](#项目结构)
- [环境要求](#环境要求)
- [快速开始](#快速开始)
- [开发命令](#开发命令)
- [构建与部署](#构建与部署)
- [核心架构](#核心架构)
- [功能模块](#功能模块)
- [数据模型](#数据模型)
- [API 层](#api-层)
- [测试](#测试)
- [CI/CD](#cicd)
---
## 项目简介
CSLAB-DCS-Web 是一个 **工业分布式控制系统可视化组态编辑器**,采用 pnpm monorepo 架构。用户可在画布上拖放、编排工业控制组件(如 PID 控制器、阀门控制器、仪表等),配置数据绑定与表达式,并通过 WebSocket 实现运行时的实时数据推送和仿真监控。
### 核心能力
- **画布组态设计**:基于可视化画布的工业控制界面设计,支持多图层、组件拖放、对齐辅助线、缩放漫游
- **丰富组件库**矩形、文本、数字显示、柱状图、按钮、PID 控制器、阀门控制器、画布切换器等
- **数据绑定与表达式**支持将组件属性绑定到运行时变量内置表达式引擎tokenizer → parser → evaluator
- **条件样式**:根据运行时条件动态切换组件样式
- **事件与动作**:组件支持 click/dblclick 事件触发,执行自定义动作
- **实时运行监控**:通过 WebSocket 连接运行时服务RAF 帧批处理数据更新
- **仿真执行**:对接 chemical-chaos 微服务,支持任务创建、启停、暂停/恢复
- **导入导出**:画布/项目的导入导出Zod schema 校验数据完整性
- **跨平台**Web 浏览器 / Electron 桌面 / Tauri 轻量桌面三端统一
---
## 技术栈
| 类别 | 技术 |
|------|------|
| **框架** | Vue 3 (Composition API + `<script setup>`) |
| **路由** | Vue Router 4Hash 模式,兼容桌面端) |
| **状态管理** | Pinia 3 |
| **UI 组件库** | Element Plus中文本地化 |
| **原子化 CSS** | UnoCSS |
| **组合式工具** | VueUse |
| **HTTP 客户端** | ofetch |
| **Schema 校验** | Zod |
| **构建工具** | Vite 6 / electron-vite |
| **桌面框架** | Electron 22 / Tauri 2 |
| **包管理器** | pnpmworkspace |
| **TypeScript** | 5.9+(严格模式) |
| **代码规范** | ESLint + @antfu/eslint-config |
| **单元测试** | Vitest + @vue/test-utils + happy-dom |
| **E2E 测试** | PlaywrightChromium |
| **样式预处理** | SCSS |
| **图标** | FontAwesome 7 |
---
## 项目结构
```
cslab-dcs-web/
├── apps/ # 应用入口层
│ ├── web/ # Web 浏览器版
│ ├── electron/ # Electron 桌面版
│ └── tauri/ # Tauri 桌面版
├── packages/ # 共享包层
│ ├── core/ # 核心业务逻辑与 UI
│ │ └── src/
│ │ ├── api/ # API 服务层
│ │ ├── assets/ # 静态资源(字体、图片、样式)
│ │ ├── bootstrap/ # 应用初始化Bridge、编辑器、路由状态同步
│ │ ├── components/ # 组件库
│ │ │ └── editor/ # 编辑器组件
│ │ │ ├── canvas/ # 画布引擎Stage、图层面板、属性面板、组件面板
│ │ │ ├── components/# 可渲染组件rect、text、number、bar、button、PID…
│ │ │ ├── controls/ # UI 控件(输入框、颜色选择器、开关…)
│ │ │ ├── header/ # 顶部工具栏
│ │ │ └── ... # 运行时控制台、状态栏等
│ │ ├── composables/ # 组合式函数
│ │ ├── config/ # 运行时配置
│ │ ├── constants/ # 常量定义
│ │ ├── layout/ # 布局组件
│ │ ├── request/ # 请求层HTTP / IndexedDB 双适配器)
│ │ ├── router/ # 路由配置
│ │ ├── stores/ # Pinia 状态管理
│ │ ├── utils/ # 工具函数
│ │ └── views/ # 页面视图
│ │
│ ├── bridge/ # 平台抽象桥接层
│ │ └── src/
│ │ ├── adapters/ # Web / Electron / Tauri 适配器
│ │ └── types.ts # IPlatformBridge 接口定义
│ │
│ └── schema/ # 数据模型与校验
│ └── src/
│ ├── dcs.ts # DCS 配置类型
│ ├── types.ts # 通用类型
│ └── validators.ts # Zod 校验器
├── tests/ # 测试
│ ├── e2e/ # Playwright E2E 测试
│ └── unit/ # Vitest 单元测试
├── references/ # 参考文档与竞品截图
├── eslint.config.js
├── vitest.config.ts
├── playwright.config.ts
├── tsconfig.base.json
├── pnpm-workspace.yaml
└── package.json
```
### 包职责说明
| 包名 | 描述 |
|------|------|
| `@cslab-dcs/core` | 核心业务层——路由、Store、API、视图、组件、组合式函数是应用的主体 |
| `@cslab-dcs/bridge` | 平台抽象层——定义 `IPlatformBridge` 接口,提供文件操作、对话框、系统信息的跨平台实现 |
| `@cslab-dcs/schema` | 数据模型层——Canvas、Layer、Component、Variable 的 Zod Schema 定义与校验 |
| `@cslab-dcs/web` | Web 入口——挂载 Vue 应用到浏览器 |
| `@cslab-dcs/electron` | Electron 入口——主进程 IPC、窗口管理、文件授权 |
| `@cslab-dcs/tauri` | Tauri 入口——Tauri Plugin API 绑定 |
---
## 环境要求
| 依赖 | 版本 |
|------|------|
| Node.js | >= 20.0.0 |
| pnpm | >= 9.0.0 |
| Rust仅 Tauri | latest stable |
---
## 快速开始
```bash
# 1. 安装依赖
pnpm install
# 2. 启动 Web 开发服务
pnpm dev:web
# 访问 http://localhost:5173/dcs-web#/
# 3. 或启动 Electron 桌面版
pnpm dev:electron
# 4. 或启动 Tauri 桌面版
pnpm dev:tauri
```
---
## 开发命令
### 开发
| 命令 | 说明 |
|------|------|
| `pnpm dev:web` | 启动 Web 版开发服务器(端口 5173 |
| `pnpm dev:electron` | 启动 Electron 桌面版 |
| `pnpm dev:tauri` | 启动 Tauri 桌面版 |
### 构建
| 命令 | 说明 |
|------|------|
| `pnpm build:web` | 构建 Web 生产包 |
| `pnpm build:electron:win` | 构建 Windows Electron 安装包 |
| `pnpm build:tauri` | 构建 Tauri 跨平台安装包 |
### 质量保障
| 命令 | 说明 |
|------|------|
| `pnpm format` | ESLint 自动修复 |
| `pnpm typecheck` | 全包 TypeScript 类型检查 |
| `pnpm test` | 运行单元测试 |
| `pnpm test:watch` | 监听模式单元测试 |
| `pnpm test:coverage` | 生成覆盖率报告 |
| `pnpm test:e2e` | 运行 E2E 测试 |
| `pnpm test:e2e:ui` | E2E 测试(带 UI |
---
## 构建与部署
### Web 构建产物
```bash
pnpm build:web
# 输出目录apps/web/dist/
```
构建产物为纯静态资源HTML/JS/CSS可直接部署到任意 Web 服务器或 CDN。
### 环境变量
| 变量 | 说明 |
|------|------|
| `VITE_API_BASE_URL` | 后端 API 地址 |
| `VITE_BASE_URL` | 前端部署路径 |
---
## 核心架构
### 分层架构
```
┌────────────────────────────────────────────┐
│ Views页面视图
├────────────────────────────────────────────┤
│ ComponentsUI 组件层) │
├────────────────────────────────────────────┤
│ Composables组合式函数层
├────────────────────────────────────────────┤
│ Pinia Stores状态管理层
├────────────────────────────────────────────┤
│ API Layer服务接口层
├────────────────────────────────────────────┤
│ Request AdaptersHTTP / IndexedDB 适配) │
├────────────────────────────────────────────┤
│ Platform BridgeWeb / Electron / Tauri
└────────────────────────────────────────────┘
```
### 路由
| 路由 | 页面 | 说明 |
|------|------|------|
| `/canvases` | 画布列表 | 项目下的画布管理 |
| `/editor` | 画布编辑器 | 核心组态编辑界面 |
| `/preview` | 预览模式 | 只读画布预览 |
| `/runtime` | 运行模式 | 实时仿真与监控 |
| `/settings` | 设置 | 桌面端专属 |
| `/welcome` | 欢迎页 | 桌面端专属 |
### 状态管理Pinia Stores
| Store | 职责 | 持久化 |
|-------|------|--------|
| `useAppStore` | 主题、平台信息、应用版本 | — |
| `useUserStore` | JWT Token、设备类型、用户信息 | localStorage |
| `useProjectStore` | 项目列表、当前项目、最近项目 | sessionStorage |
| `useCanvasStore` | 画布列表、缩放级别、视口状态 | sessionStorage |
| `useLayerStore` | 选中图层、图层列表、基础图层 | sessionStorage |
### 平台桥接Bridge
```typescript
interface IPlatformBridge {
platform: 'web' | 'electron' | 'tauri'
file: IFileService // 读写文件、打开/保存对话框
dialog: IDialogService // 消息弹窗、确认弹窗
system: ISystemService // 应用版本、平台信息、打开外部链接
}
```
三端适配器各自实现该接口,上层业务代码无需关心平台差异。
---
## 功能模块
### 画布编辑器
- **画布引擎**:支持缩放(最大 300%、平移、网格对齐10px
- **画布尺寸**:默认 1920×1080最小 360×240最大 20000×20000
- **图层管理**:多选、分组、排序、锁定
- **属性面板**:根据选中组件类型动态展示配置项
- **对齐辅助线**:智能吸附对齐
- **Minimap**:画布缩略图导航
- **撤销/重做**:完整的操作历史记录
- **自动保存**:编辑内容自动持久化
### 可渲染组件
| 组件 | 说明 |
|------|------|
| `rect` | 矩形/容器 |
| `text` | 文本标签 |
| `number` | 数字显示 |
| `bar` | 柱状图 |
| `button` | 可交互按钮 |
| `pidController` | PID 控制器面板 |
| `valveController` | 阀门控制器 |
| `canvasSwitcher` | 画布切换导航 |
| `custom` | 自定义组件 |
### 数据绑定与表达式引擎
组件属性支持绑定到运行时变量,内置完整的表达式解析引擎:
```
表达式字符串 → Tokenizer词法分析→ Parser语法分析→ Evaluator求值
```
支持条件样式:根据表达式结果动态切换组件外观,支持优先级配置。
### 运行时监控
- WebSocket 实时数据推送
- RequestAnimationFrame 帧批处理,保证渲染性能
- 运行时控制台输出
- 手动控制面板
- PID 参数调节面板
- 阀门开度控制面板
### 组合式函数Composables
| 函数 | 职责 |
|------|------|
| `useBridge()` | 获取平台桥接实例 |
| `useOperationLog()` | 操作日志记录(上限 500 条) |
| `useRuntimeSocket()` | WebSocket 运行时连接与帧批更新 |
| `useDataConnection()` | 数据连接管理与写入命令 |
| `useExportImport()` | 画布/项目导入导出 |
| `useRuntimeConsole()` | 运行时控制台日志 |
| `useComponentTemplates()` | 组件模板存取localStorage |
---
## 数据模型
### Canvas画布
```typescript
{
id: string
projectId: string
name: string
description?: string
width: number // 默认 1920
height: number // 默认 1080
type: CanvasType
version: string
components: Layer[] // 组件/图层列表
vars?: Variable[] // 运行时变量
config?: CanvasConfig
thumbnail?: string // 缩略图
updatedAt: string
}
```
### Layer图层/组件)
```typescript
{
id: string // UUID
type: ComponentType // rect | number | text | bar | button | ...
x: number // X 坐标
y: number // Y 坐标
width: number
height: number
config?: object // 组件特定配置
style?: object // CSS 样式
bindings?: Record<string, string | BindingExpression> // 数据绑定
tagNumber?: string // 设备标签号
events?: EventConfig[] // 事件处理器
conditionalStyles?: ConditionalStyle[] // 条件样式
}
```
所有数据模型均使用 Zod Schema 定义,提供运行时校验和 TypeScript 类型推导。
---
## API 层
### 请求架构
采用 **Repository 模式** + **双适配器**
- **HTTP 适配器** → 对接 `/cslab-server` 后端
- **IndexedDB 适配器** → 浏览器本地存储(离线模式)
HTTP 客户端基于 `ofetch`,支持 JWT Token 自动刷新、401 会话过期处理、错误提示。
### API 模块
| 模块 | 接口 |
|------|------|
| **Project** | `getProjectListApi()` / `createProjectApi()` / `updateProjectApi()` |
| **Canvas** | `listCanvasesApi()` / `getCanvasByIdApi()` / `createCanvasApi()` / `updateCanvasApi()` / `saveCanvasComponentsApi()` / `duplicateCanvasApi()` |
| **Runtime** | `addJobApi()` / `stopJobApi()` / `pauseJobApi()` / `resumeJobApi()` / `getProjectJobApi()` / `pushFullDataApi()` / `getExecSequenceApi()` |
| **Dynamic Project** | 动态项目更新 |
### 运行时 RPC
对接 `chemical-chaos` 微服务,通过 `/v1/rpc/common/``/v1/rpc/zero_rpc/` 端点进行仿真调度。
---
## 测试
### 单元测试
- **框架**Vitest + happy-dom + @vue/test-utils
- **位置**`tests/unit/`
- **覆盖范围**Composables、Stores、Schema 校验、表达式引擎
```bash
pnpm test # 运行全部单元测试
pnpm test:watch # 监听模式
pnpm test:coverage # 覆盖率报告
```
### E2E 测试
- **框架**PlaywrightChromium
- **位置**`tests/e2e/`
- **测试场景**:画布编辑器操作、图层交互、页面导航
```bash
pnpm test:e2e # 运行 E2E 测试
pnpm test:e2e:ui # 带 UI 的 E2E 测试
```
---
## CI/CD
项目配置了 Jenkins Pipeline支持两套部署环境
| 环境 | 配置文件 | 目标 |
|------|----------|------|
| 开发环境110 | `Jenkinsfile.dev110` | Windows 服务器部署 |
| 测试环境139 | `Jenkinsfile.dev139` | Linux 服务器部署 |
### Pipeline 流程
1. **环境检查** → 验证 Node 22 / pnpm 版本
2. **安装依赖**`pnpm install`
3. **构建**`pnpm build:web`
4. **部署** → SSH 拷贝静态资源到目标服务器
5. **通知** → 企业微信 Webhook 通知构建结果
### 部署要点
- 构建产物:`apps/web/dist/` 下的静态文件
- 构建超时15 分钟
- 跳过 Electron 二进制下载:`ELECTRON_SKIP_BINARY_DOWNLOAD=1`
- 测试环境支持旧版本自动清理(>7 天)
---
## License
Private — 内部项目