Files
test/README.md
2026-04-08 21:26:18 +08:00

464 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 — 内部项目