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