SeatFlow 10 个项目目录结构、依赖关系、csproj 关键设置和 NuGet 管理
本页目录
全部文档
项目结构
解决方案文件
SeatFlow 使用新版 XML 格式的解决方案文件 SeatFlow.slnx(.slnx 格式,而非传统 .sln)。所有 10 个项目(6 个 src/ + 4 个 tests/)均在此解决方案中管理。
SeatFlow.slnx
├── src/SeatFlow.Core/ → 领域核心
├── src/SeatFlow.Application/ → 应用编排层
├── src/SeatFlow.Infrastructure/ → 基础设施实现
├── src/SeatFlow.Presentation.Avalonia/ → 共享 UI 类库(桌面 + 浏览器)
├── src/SeatFlow.Desktop/ → 桌面启动壳
├── src/SeatFlow.Browser/ → 浏览器 WASM 启动壳
├── tests/SeatFlow.Core.Tests/ → 核心测试
├── tests/SeatFlow.Application.Tests/ → 应用层测试
├── tests/SeatFlow.Infrastructure.Tests/ → 基础设施测试
└── tests/SeatFlow.Presentation.Tests/ → 共享 UI 无头测试(Avalonia.Headless.XUnit)
项目列表与用途
| 项目 | 类型 | 用途 |
|---|---|---|
SeatFlow.Core |
类库 | 领域实体、策略接口和 11 条内置策略、领域服务、工作区、数据提供者接口、存储抽象 ILocalDataStore、工具类 |
SeatFlow.Application |
类库 | 外观接口/实现、策略管道执行器、命令模式、DI 扩展方法 |
SeatFlow.Infrastructure |
类库 | CSV/XLSX/JSON 数据提供者、导出器、布局构建器、JSON 仓库、文件迁移系统、序列化、SeatSets 服务、平台存储实现 |
SeatFlow.Presentation.Avalonia |
类库 | 共享 UI 层(net10.0;net10.0-browser),双范式 MVVM、7 页导航、自绘 SeatingCanvas、令牌主题、平台服务接口 |
SeatFlow.Desktop |
桌面应用 | 桌面启动壳。输出 EXE 名为 SeatFlow.exe,含 Velopack 自动更新、Watchdog、单实例 |
SeatFlow.Browser |
浏览器应用 | 浏览器启动壳(net10.0-browser)。WASM 静态站,发布产物为 wwwroot/ |
SeatFlow.Core.Tests |
测试 (xUnit v3) | Core 层单元测试 |
SeatFlow.Application.Tests |
测试 (xUnit v3) | Application 层单元测试 |
SeatFlow.Infrastructure.Tests |
测试 (xUnit v3) | Infrastructure 层单元测试 |
SeatFlow.Presentation.Tests |
测试 (xUnit v3 3.2.2) | 共享 UI 无头测试:Headless VM/服务单测 + Avalonia.Skia 真实绘制 + 视觉基线/像素回归 |
项目依赖图
SeatFlow.Desktop ──┐ SeatFlow.Browser ──┐
▼ ▼
Presentation.Avalonia ───────────────┘
│
▼
Application
│
┌──────┴──────┐
▼ ▼
Core Infrastructure
严格的分层依赖:
SeatFlow.Desktop/SeatFlow.Browser→Presentation.AvaloniaPresentation.Avalonia→ApplicationApplication→Core、Infrastructure- 无循环依赖,下层不引用上层
关键目录和文件
每个项目内的典型目录结构
src/SeatFlow.Core/
├── Models/ ← 领域实体 (Student, Seat, ClassroomLayoutDefinition, LayoutMetadata 等)
├── Strategies/ ← 策略接口与 11 条内置策略
│ ├── ISeatingStrategy.cs / IDependentSeatingStrategy.cs / IRandomFillContext.cs
│ ├── SeatAdjacencyHelper.cs
│ ├── Manifests/ ← 策略 manifest JSON 文件(声明式配置)
│ └── FixedSeatStrategy.cs 等 11 条策略实现
├── DomainServices/ ← ObstacleProcessor, SeatGeometryHelper
├── Services/ ← StrategyManifestProvider
├── Providers/ ← 数据提供者/仓储接口(IStudentProvider, IVenueRepository 等)
├── Exporters/ ← ISeatingPlanExporter
├── Storage/ ← ILocalDataStore
├── Workspace/ ← SeatingWorkspace
├── Utilities/ ← CircularHistory<T>, AttributeBag, AppEnvironment
└── Enums/ / Logging/ / Telemetry/
src/SeatFlow.Application/
├── Interfaces/ ← IApplicationFacade, IConflictResolver
├── Services/ ← ApplicationFacade, StrategyExecutionPipeline, CommandHistory, ServiceCollectionExtensions(DI 注册)
└── Commands/ ← IUndoableCommand, AssignSeatCommand 等
src/SeatFlow.Infrastructure/
├── Providers/ ← Csv/Xlsx/Json/Composite/InMemory 数据提供者、写入器、FuzzyColumnMatcher、JSON 仓储
├── Exporters/ ← Excel/Csv/Pdf/Image 导出器
├── Layouts/ ← Grid/Polar/Freeform 布局构建器
├── Repositories/ ← SeatingSnapshotRepository
├── Storage/ ← FileSystemDataStore(桌面)/ IndexedDbDataStore.browser.cs(浏览器,条件编译)
├── Migration/ ← FileMigrationService, IFileMigrator
│ ├── file_versions.json ← 各文件类型当前版本号
│ └── Migrators/ ← VenueMigrators, SeatSetsMigrators
├── Serialization/ ← SeatJsonConverter, JsonOptions
├── Services/ ← SeatSetsService
└── Data/ / Utils/ ← field_mappings.json / ContentHashHelper
src/SeatFlow.Presentation.Avalonia/
├── App.axaml / App.axaml.cs ← 应用生命周期与启动序列(构造参数化:DI + 桌面启动参数)
├── MainView.axaml / MainView.axaml.cs ← 共享 UI 外壳(桌面与浏览器共用)
├── MainWindow.axaml / MainWindow.axaml.cs ← 桌面主窗口(由桌面壳解析,承载 MainView)
├── ViewLocator.cs ← VM→View 命名约定解析 + 弱引用视图缓存
├── ViewModels/ ← 7 个页面 VM + MainShellViewModel 等
├── Views/ ← 页面 View、对话框窗口与共享内容
├── Controls/ ← SeatingCanvas.cs(自绘画布), SeatVisual.cs(不可变座位快照), PhaseGuideIndicator.cs
├── Services/ ← 导航、对话框、文件 + 生命周期与横切服务(IPageLifecycle, DirtyTracker, IDialogGate, IBusyScope, IShellLayoutService, IGuideSeedTarget 等)
├── Resources/Tokens/ ← Colors.axaml / Spacing.axaml / Typography.axaml(方向 B 令牌)
├── Tokens/ ← MotionTokens.cs(动效时长,{x:Static} 供 Transitions)
├── Styles/ ← Components.axaml(sf-* 组件类)等
├── Behaviors/ ← ChineseInputNormalizer, KeyboardShortcutHandler, FileDropHandler
├── Converters/ / Lang/ / Data/ / Telemetry/
src/SeatFlow.Desktop/
├── Program.cs ← 进程入口、Velopack 更新钩子、单实例 + 命名管道转发
└── 平台服务注册 ← FileSystemDataStore、桌面文件/对话框服务、WatchdogService
src/SeatFlow.Browser/
├── Program.cs ← 入口(启动前异步预加载语言)、DI 注册
├── 平台服务 ← WebDialogService、WebFileService、BrowserConsoleLoggerProvider
└── wwwroot/js/ ← interop.js(sf.idb)、files.js(sf.files)
结构变更(2.1.0):
HomeView/HomeViewModel、FreeformManagementView/FreeformManagementViewModel、MainWindowViewModel已删除;Behaviors/CanvasZoomPan、Behaviors/ZoomOnScroll退役,缩放/平移/拖拽并入Controls/SeatingCanvas.cs。
NuGet 包管理
不使用 Directory.Build.props 或 Directory.Packages.props。包版本直接在每个 .csproj 中管理。这确保了每个项目的依赖版本显式可见。
主要 NuGet 包
| 包名 | 用于 |
|---|---|
Avalonia / Avalonia.Desktop / Avalonia.Browser |
跨平台 UI 框架(共享类库 / 桌面 / 浏览器),版本 12.1.3 |
CommunityToolkit.Mvvm 8.4.2 |
MVVM 源码生成器(ViewModelBase 与存量 VM) |
ReactiveUI.Avalonia 12.1.5 |
响应式 MVVM(新代码优先;与 CTK 双范式共存,ADR-014) |
FluentIcons.Avalonia |
Fluent 图标控件 |
Serilog / Serilog.Sinks.File |
结构化日志(仅桌面文件 sink) |
Microsoft.Extensions.DependencyInjection |
DI 容器 |
Microsoft.Extensions.Logging.ILogger<T> |
日志抽象 |
EPPlus |
XLSX 文件读写(桌面与浏览器) |
QuestPDF |
PDF 导出(仅桌面) |
Avalonia.Headless.XUnit / Avalonia.Skia 12.1.3 |
共享 UI 无头测试与真实绘制(仅 tests/SeatFlow.Presentation.Tests) |
xunit.v3 / FluentAssertions / NSubstitute |
测试栈(xunit.v3 4.0.1;Presentation.Tests 锁 3.2.2) |
csproj 关键设置
共享类库的多目标框架 (SeatFlow.Presentation.Avalonia.csproj)
共享 UI 类库同时面向桌面与浏览器:
<TargetFrameworks>net10.0;net10.0-browser</TargetFrameworks>
<!-- 编译绑定默认启用 -->
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<!-- Designer.cs 不存在时跳过编译(首次克隆时) -->
<Compile Remove="Lang\Resources.Designer.cs"
Condition="!Exists('Lang\Resources.Designer.cs')" />
浏览器专属资源(如内嵌 CJK 字体)通过 MSBuild 条件限定到 net10.0-browser 目标。
桌面壳项目设置 (SeatFlow.Desktop.csproj)
<!-- 输出 EXE 名称,而非项目名称 -->
<AssemblyName>SeatFlow</AssemblyName>
<!-- Windows DPI 感知 -->
<ApplicationManifest>app.manifest</ApplicationManifest>
<!-- 抑制 DI 构造函数注入警告 -->
<NoWarn>AVLN3001</NoWarn>
<!-- 确定性构建 -->
<Deterministic>true</Deterministic>
<PathMap>$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)'))=./</PathMap>
<!-- M6:显式对齐 Skia native 版本(修复 Linux 桌面渲染错配) -->
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="4.153.1" />
依赖清理(2.1.0):已移除死依赖
Svg.Controls.Skia.Avalonia;桌面壳与 Headless 测试项目显式对齐SkiaSharp.NativeAssets.Linux4.153.1,避免 Linux 桌面/无头绘制崩溃。浏览器/共享类库不受影响(对齐属桌面与测试壳层职责)。
Git 提交哈希注入
MSBuild 目标 GenerateGitCommit 在每次构建前运行 git rev-parse --short HEAD,生成 GitCommit.g.cs(位于 $(IntermediateOutputPath)Generated\),提供 GitCommit.Hash 常量。git 不可用时回退到 "unknown-commit-id"。该文件不提交到版本控制。
共享 UI 测试项目设置 (SeatFlow.Presentation.Tests.csproj)
<PackageReference Include="Avalonia.Headless" Version="12.1.3" />
<PackageReference Include="Avalonia.Headless.XUnit" Version="12.1.3" />
<PackageReference Include="Avalonia.Skia" Version="12.1.3" />
<!-- 锁定 Headless 包的编译基线(用 4.x 会 MissingMethodException) -->
<PackageReference Include="xunit.v3" Version="3.2.2" />
<!-- Linux 上无头真实绘制依赖的原生库,版本须与桌面壳一致 -->
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="4.153.1" />
dotnet 工具
仓库根目录的 dotnet-tools.json 安装了 avaloniaui.developertools(avdt,仅桌面可用)、vpk(Velopack)与 run-script(dotnet r 任务)。首次使用先执行 dotnet tool restore。
浏览器端构建需要 WASM 工作负载:dotnet workload install wasm-tools。
脚本工具
| 目录/脚本 | 用途 |
|---|---|
scripts/version.py |
统一管理 App/文件格式/策略清单/引导配置等 15+ 处版本号 |
scripts/i18n.py |
.resx 资源 CRUD 与 Resources.Designer.cs 生成 |
scripts/build/publish.* |
多平台发布;scripts/build/clean.* 清理 |
scripts/release/release.py |
发布编排(读取 RELEASE.md 作为 Release body) |
scripts/ui-inspect/ |
无头 WASM UI 工具链:CDP 可信输入、批量截图、trace 分析、像素定位、序列回放、演示数据注入 |
scripts/tests/ |
脚本自身测试(cd scripts && python3 -m pytest tests/ -v) |