You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

221 lines
6.1 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 广播系统软件架构文档
## 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分段按屏宽计算并纵向堆叠严格满足需求中的显示规则