SeatFlow 架构分层、技术栈、关键设计决策和策略管道概念
本页目录
全部文档
架构总览
项目目标
SeatFlow 是一个 .NET 10 跨平台座位编排系统,面向学校、培训机构和企业等需要批量座位安排的场景。系统同时提供桌面与浏览器双壳,核心能力包括:
- 多策略排座管道(固定座位、前排轮换、同桌分组、性别限制、历史防重复等)
- 多种教室布局支持(网格、极坐标、自由点)
- 多数据源导入(CSV、XLSX、JSON)
- 排座结果导出(Excel、CSV、PDF、图片;PDF/图片导出仅桌面可用)
- 历史快照与回滚
- 桌面与浏览器双壳,共享同一套 UI 与业务逻辑
- 完整的国际化支持(zh-CN/en-US等)
分层架构
采用经典三层架构 + 双平台启动壳,遵循严格的分层依赖原则:
┌────────────────────────────┐ ┌────────────────────────────┐
│ SeatFlow.Desktop │ │ SeatFlow.Browser │
│ 桌面 EXE (SeatFlow) │ │ WASM 静态站 (wwwroot) │
│ Velopack / Watchdog / 单实例│ │ IndexedDB / 控制台日志 │
└──────────────┬─────────────┘ └─────────────┬──────────────┘
└───────────┬───────────────────┘
▼
┌─────────────────────────────────────────────┐
│ Presentation.Avalonia │
│ Avalonia UI 12 + CommunityToolkit MVVM │
│ MainView 共享外壳, 编译绑定, i18n │
│ net10.0;net10.0-browser │
└──────────────────────┬──────────────────────┘
│
┌──────────────────────▼──────────────────────┐
│ Application │
│ IApplicationFacade (外观) │
│ StrategyExecutionPipeline │
│ CommandHistory + DI 容器 │
└──────────────────────┬──────────────────────┘
│
┌─────────────────────┴─────────────────────┐
│ │
┌────────▼──────┐ ┌─────────▼──────┐
│ Core │ │ Infrastructure │
│ │ │ │
│ ┌───────────┐ │ │ Csv/Xlsx/Json │
│ │ Entities │ │ │ Providers │
│ │ Student │ │ │ Exporters │
│ │ Seat │ │ │ Repositories │
│ │ Layout │ │ │ LayoutBuilders │
│ ├───────────┤ │ │ MigrationSys │
│ │ Strategies│ │ │ FileSystem / │
│ │ 7 Builtin │ │ │ IndexedDb 存储 │
│ ├───────────┤ │ └────────────────┘
│ │ Domain │ │
│ │ Services │ │
│ ├───────────┤ │
│ │ILocalData │ │
│ │ Store │ │
│ └───────────┘ │
└───────────────┘
各层职责
| 层 | 项目 | 核心职责 |
|---|---|---|
| Core | SeatFlow.Core |
领域实体、策略接口和实现、领域服务、工作区、数据提供者接口、存储抽象 ILocalDataStore |
| Infrastructure | SeatFlow.Infrastructure |
数据提供者实现、导出器、布局构建器、仓库、文件迁移系统、序列化、平台存储实现 |
| Application | SeatFlow.Application |
UI 单一入口(外观)、策略管道执行器、命令模式、DI 注册 |
| Presentation | SeatFlow.Presentation.Avalonia |
共享 UI 类库(桌面 + 浏览器),Avalonia 12 MVVM 架构 |
| Desktop | SeatFlow.Desktop |
桌面启动壳:自动更新、Watchdog、单实例、文件关联 |
| Browser | SeatFlow.Browser |
浏览器启动壳:WASM 静态站发布 |
依赖关系链
SeatFlow.Desktop SeatFlow.Browser
└───────┬───────────┘
Presentation.Avalonia
└── Application
├── Core
└── Infrastructure
技术栈
| 技术 | 版本 | 用途 |
|---|---|---|
| .NET SDK | 10 | 运行时和 SDK |
| Avalonia UI | 12 | 跨平台 UI 框架(桌面) |
| Avalonia WebAssembly | 12 | 浏览器端 UI(net10.0-browser,WebGL/CanvasKit 渲染) |
| CommunityToolkit.Mvvm | 8.4 | MVVM 源码生成器([ObservableProperty], [RelayCommand]) |
| Serilog | 4 | 结构化日志 |
| EPPlus | 8 | XLSX 读写 |
| QuestPDF | — | PDF 导出(仅桌面) |
| Microsoft.Extensions.DependencyInjection | — | DI 容器 |
| xUnit | 3 | 单元测试框架 |
| FluentAssertions | — | 测试断言 |
| NSubstitute | — | 模拟框架 |
关键设计决策
项目采用架构决策记录(ADR)系统文档化重大技术决策,位于 docs/adr/ 目录。
ADR 索引
| ADR | 主题 | 关键结论 |
|---|---|---|
| ADR-001 | 选择 Avalonia UI | 跨平台(Windows/macOS/Linux),原生 MVVM,WPF 开发者友好 |
| ADR-002 | MVVM 框架 | CommunityToolkit.Mvvm 源码生成器 |
| ADR-003 | 分层架构 | 经典三层结构 |
| ADR-004 | 策略模式 | ISeatingStrategy 作为排座算法通用接口 |
| ADR-005 | 命令模式 | IUndoableCommand + CommandHistory 实现撤销/重做 |
| ADR-006 | 策略管道 | Fill-in-Order 模型,依赖策略在 RandomFill 上下文中执行 |
| ADR-008 | 引导系统示例数据注入 | 纯内存注入,零磁盘痕迹,DispatcherPriority.Background 延迟 |
| ADR-013 | 移除插件系统 | 2.0.0 起移除插件/脚本/能力系统,新策略以内置方式加入 |
核心架构模式
- 外观模式:
IApplicationFacade是 UI 层的单一入口点,封装所有业务操作(40+ 方法) - 策略模式:
ISeatingStrategy和IDependentSeatingStrategy定义排座算法接口 - 命令模式:
IUndoableCommand+CommandHistory提供快照式撤销/重做 - 双壳共享:
SeatFlow.Presentation.Avalonia为共享类库,MainView同时由桌面与浏览器单视图承载,平台差异通过接口与条件编译注入 - 依赖注入: Microsoft.Extensions.DependencyInjection 管理组件生命周期
策略管道概念
SeatFlow 的策略管道采用 Fill-in-Order 模型,核心原则:
- 按 Priority 降序执行:Priority 数值越大越先执行,先执行的策略优先挑选空座
- 不存在覆盖语义:先占的座位不会被后执行的策略推翻
- IsFixed 保护:固定座位标记
IsFixed=true,后续GetEmptySeats()自动排除 - 依赖策略:某些策略(DeskMate、GenderRestrictedSeat、NoRepeatDeskMate)不在外部管道执行,而是在 RandomFill 的分配循环中按上下文内部优先级评估
管道执行顺序
独立策略 Priority 降序 →
FixedSeat(100) ← 最先执行:锁定固定座位
FrontRowRotation(50) ← 在非固定空座中填前排
RandomFill(1) ← 兜底填充:
└─ 依赖策略(优先级降序)→
DeskMate(50) ← 检查同桌关系
GenderRestrictedSeat(45) ← 检查性别限制
NoRepeatDeskMate(40) ← 检查历史同桌重复
Defrag(0) ← 碎片整理(默认禁用)
双壳架构
SeatFlow 的 UI 与业务逻辑集中在 SeatFlow.Presentation.Avalonia(共享类库,目标框架 net10.0;net10.0-browser),由两个启动壳承载:
| 壳 | 项目 | 说明 |
|---|---|---|
| 桌面壳 | SeatFlow.Desktop |
输出 EXE 名为 SeatFlow;提供 Velopack 自动更新、Watchdog 看门狗和单实例;PDF/图片导出仅在此可用 |
| 浏览器壳 | SeatFlow.Browser |
net10.0-browser WASM 应用,发布为 wwwroot/ 纯静态文件;数据存储于 IndexedDB,文件选择/下载经 JS 互操作 |
共享 UI 外壳 MainView : UserControl 由桌面 MainWindow : Window 与浏览器单视图(ISingleViewApplicationLifetime.MainView)共同承载。平台相关服务(对话框、文件、日志、存储)由各壳实现,共享层通过接口消费,并通过 BROWSER 条件编译区分浏览器专属代码路径。