|
|
# 广播系统软件架构文档
|
|
|
|
|
|
## 1. 架构目标
|
|
|
|
|
|
构建一个基于 Tauri v2 的桌面广播显示系统,满足以下架构目标:
|
|
|
- 支持固定窗口行为(无边框、左上角定位、启动即开)
|
|
|
- 支持 5000px 标尺在任意屏宽下的稳定分段显示
|
|
|
- 支持子元素跨段连续渲染
|
|
|
- 保持模块边界清晰,便于后续扩展(动态数据、渲染升级)
|
|
|
|
|
|
## 2. 总体架构
|
|
|
|
|
|
采用“宿主层 + 前端应用层 + 渲染域层”的分层结构:
|
|
|
|
|
|
- 宿主层(Tauri Runtime)
|
|
|
- 负责窗口生命周期、屏幕信息读取、系统能力接入
|
|
|
- 前端应用层(Vue Application)
|
|
|
- 负责状态管理、分段计算、组件编排
|
|
|
- 渲染域层(Ruler Rendering Domain)
|
|
|
- 负责刻度绘制、切片映射、子元素裁剪与连续性
|
|
|
|
|
|
架构原则:
|
|
|
- 计算与渲染分离:算法在 `composables/services`,界面在 `components/views`
|
|
|
- 数据驱动:通过状态变化触发渲染,不在组件中写复杂业务判断
|
|
|
- 可替换渲染:先 DOM,后续可平滑迁移到 Canvas
|
|
|
|
|
|
## 3. 逻辑视图(模块划分)
|
|
|
|
|
|
建议目录结构:
|
|
|
|
|
|
```text
|
|
|
broadcast-client/
|
|
|
src/
|
|
|
main.ts
|
|
|
App.vue
|
|
|
views/
|
|
|
BroadcastView.vue
|
|
|
components/
|
|
|
RulerCanvas.vue
|
|
|
RulerSegment.vue
|
|
|
RulerTicks.vue
|
|
|
SegmentChildren.vue
|
|
|
composables/
|
|
|
useScreenInfo.ts
|
|
|
useSegmentLayout.ts
|
|
|
useRulerTicks.ts
|
|
|
services/
|
|
|
segmentService.ts
|
|
|
childSliceService.ts
|
|
|
models/
|
|
|
ruler.ts
|
|
|
segment.ts
|
|
|
child.ts
|
|
|
utils/
|
|
|
math.ts
|
|
|
src-tauri/
|
|
|
tauri.conf.json
|
|
|
src/
|
|
|
lib.rs
|
|
|
```
|
|
|
|
|
|
模块职责:
|
|
|
- `useScreenInfo`:读取并维护当前主屏宽度、DPI 信息
|
|
|
- `segmentService`:计算段数量、每段映射关系
|
|
|
- `useRulerTicks`:生成 10/100 刻度数据
|
|
|
- `childSliceService`:计算子元素在每段的可见切片
|
|
|
- `RulerSegment`:单段渲染容器(裁剪窗口)
|
|
|
- `SegmentChildren`:渲染跨段子元素切片
|
|
|
|
|
|
## 4. 关键数据模型
|
|
|
|
|
|
```ts
|
|
|
type TickType = "minor" | "major";
|
|
|
|
|
|
interface Tick {
|
|
|
x: number;
|
|
|
type: TickType;
|
|
|
label?: string;
|
|
|
}
|
|
|
|
|
|
interface Segment {
|
|
|
index: number;
|
|
|
sourceX: number;
|
|
|
sliceWidth: number;
|
|
|
top: number;
|
|
|
height: number; // 固定 64
|
|
|
}
|
|
|
|
|
|
interface ChildElement {
|
|
|
id: string;
|
|
|
left: number;
|
|
|
width: number;
|
|
|
top: number;
|
|
|
height: number;
|
|
|
zIndex?: number;
|
|
|
className?: string;
|
|
|
}
|
|
|
|
|
|
interface ChildSlice {
|
|
|
childId: string;
|
|
|
segmentIndex: number;
|
|
|
renderLeft: number;
|
|
|
renderTop: number;
|
|
|
renderWidth: number;
|
|
|
renderHeight: number;
|
|
|
clipOffset: number;
|
|
|
}
|
|
|
```
|
|
|
|
|
|
设计说明:
|
|
|
- `Segment` 只描述“段映射”,不关心具体 UI。
|
|
|
- `ChildSlice` 是“子元素在某段中的投影结果”,用于直接渲染。
|
|
|
- 所有坐标统一使用同一逻辑坐标系(以 5000px 主轴为基准)。
|
|
|
|
|
|
## 5. 运行时流程(时序)
|
|
|
|
|
|
启动流程:
|
|
|
1. Tauri 启动并创建窗口(无边框,位置 `(0,0)`)。
|
|
|
2. 前端初始化,读取屏幕宽度 `screenWidth`。
|
|
|
3. 计算 `segments = ceil(5000 / screenWidth)`。
|
|
|
4. 生成刻度数据 `ticks`,构建段列表 `segmentList`。
|
|
|
5. 渲染每段:段容器裁剪 + 虚拟标尺偏移显示。
|
|
|
6. 若存在子元素,计算 `ChildSlice[]` 并叠加渲染。
|
|
|
|
|
|
更新流程(屏宽变化):
|
|
|
1. 监听窗口尺寸/屏幕变化事件。
|
|
|
2. 重新计算 `segmentList` 与 `ChildSlice[]`。
|
|
|
3. 增量更新视图(避免全量销毁重建)。
|
|
|
|
|
|
## 6. 关键算法设计
|
|
|
|
|
|
### 6.1 分段算法
|
|
|
|
|
|
- 输入:`TOTAL_WIDTH=5000`, `screenWidth`, `SEGMENT_HEIGHT=64`
|
|
|
- 输出:`Segment[]`
|
|
|
- 复杂度:`O(n)`,`n = segmentCount`
|
|
|
|
|
|
核心规则:
|
|
|
- `segmentCount = ceil(5000 / screenWidth)`
|
|
|
- 每段 `sourceX = i * screenWidth`
|
|
|
- `sliceWidth = min(screenWidth, 5000 - sourceX)`
|
|
|
|
|
|
### 6.2 子元素切片算法
|
|
|
|
|
|
- 输入:`ChildElement[]`, `Segment[]`
|
|
|
- 输出:`ChildSlice[]`
|
|
|
- 复杂度:`O(m * n)`(可按区间优化)
|
|
|
|
|
|
相交判定:
|
|
|
- 仅当子元素区间与段区间重叠时生成切片
|
|
|
- 切片宽度为区间交集长度
|
|
|
- 渲染左偏移为交集起点相对段起点
|
|
|
|
|
|
## 7. 部署视图
|
|
|
|
|
|
单机本地部署:
|
|
|
- 可执行文件(Tauri 打包产物)
|
|
|
- 前端静态资源内嵌
|
|
|
- 无外部服务依赖
|
|
|
|
|
|
跨平台建议:
|
|
|
- Windows 为主目标平台
|
|
|
- 后续可扩展到 Linux/macOS(保持 API 使用跨平台)
|
|
|
|
|
|
## 8. 非功能架构设计
|
|
|
|
|
|
### 8.1 性能
|
|
|
- 预计算与缓存刻度数据
|
|
|
- 分段与切片计算函数纯函数化,便于 memoization
|
|
|
- 控制组件重渲染范围(按段粒度更新)
|
|
|
|
|
|
### 8.2 可维护性
|
|
|
- 算法层独立文件,配套单元测试
|
|
|
- 组件职责单一,避免“巨型组件”
|
|
|
- 使用 TypeScript 类型约束输入输出
|
|
|
|
|
|
### 8.3 兼容性
|
|
|
- 适配不同分辨率,屏宽变化自动重算
|
|
|
- 高 DPI 场景下进行像素对齐优化
|
|
|
|
|
|
## 9. 异常与容错架构
|
|
|
|
|
|
- 屏幕宽度读取失败:降级默认值(如 1920)
|
|
|
- 输入数据异常(负宽度、越界坐标):统一在 service 层校正/裁剪
|
|
|
- 渲染失败保护:关键计算异常时记录日志并回退最小可用视图
|
|
|
|
|
|
## 10. 安全与边界
|
|
|
|
|
|
当前系统以本地渲染为主,安全关注点较轻,建议:
|
|
|
- 最小化 Tauri 权限配置
|
|
|
- 不暴露不必要的系统 API
|
|
|
- 对未来外部输入(若接入)进行 schema 校验
|
|
|
|
|
|
## 11. 测试架构
|
|
|
|
|
|
测试分层:
|
|
|
- 单元测试:`segmentService`、`childSliceService`
|
|
|
- 组件测试:`RulerSegment`、`SegmentChildren`
|
|
|
- 集成测试:启动后窗口行为与全链路渲染
|
|
|
|
|
|
关键断言:
|
|
|
- 分段数量与位置正确
|
|
|
- 末段宽度裁剪正确
|
|
|
- 子元素跨段连续且无视觉跳变
|
|
|
- 大小刻度在每段中对齐正确
|
|
|
|
|
|
## 12. 可扩展路线
|
|
|
|
|
|
- 渲染升级:DOM -> Canvas/WebGL
|
|
|
- 数据升级:静态子元素 -> 实时广播内容流
|
|
|
- 交互升级:缩放、定位、标记线、主题切换
|
|
|
- 多屏支持:副屏渲染与窗口同步控制
|
|
|
|
|
|
## 13. 架构决策记录(ADR 简版)
|
|
|
|
|
|
- ADR-001:采用 Tauri v2 作为宿主框架(轻量、跨平台)
|
|
|
- ADR-002:采用 Vue3 + TS 作为前端基础(可维护、类型安全)
|
|
|
- ADR-003:先采用 DOM 裁剪方案(交付快、调试友好),保留 Canvas 替换能力
|
|
|
- ADR-004:分段按屏宽计算并纵向堆叠(严格满足需求中的显示规则)
|
|
|
|