Files
Axi_Omron/AGENTS.md
yunxiao.zhu 49f113dcf3 feat: 初始化 PCB 检测 WPF 应用程序
* 创建 AxiOmron.PcbCheck 项目主框架及解决方案
* 添加 Dashboard 和系统设置页面
* 实现 Modbus TCP PLC、扫码枪、SFTP 查询等核心服务
* 集成 Andon 报警、工作流托管服务与日志配置
* 补充项目文档和 UI 设计规范
2026-04-17 10:43:51 +08:00

249 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# AGENTS C# WPF 上位机项目初始化规范
本文件为在本仓库中创建和维护 **新的 C# WPF 上位机项目** 的智能体提供统一操作规范,作用域覆盖整个仓库。
若某个子目录存在更深层级的 `AGENTS.md`,则以更具体的规则为准。
## 适用说明
- 本仓库中的历史项目、样例项目、参考项目仅用于借鉴工程结构与协作方式,不视为新项目的默认业务实现。
- 新项目初始化时,优先采用 **.NET 8 + WPF + MVVM Toolkit + Generic Host/DI + NLog** 这一默认技术基线。
- 不要直接复制参考项目中的业务命名、设备协议、数据库模型、接口定义、配置项或目录命名,除非用户明确要求。
- 若用户仅要求“初始化项目”或“生成上位机骨架”,默认理解为生成一个结构清晰、可扩展、适合工业桌面应用的 WPF 工程,而不是复制旧项目的业务代码。
## 推荐技术基线
- 平台Windows
- SDK.NET 8 SDK
- UIWPF
- 项目文件SDK-style `.csproj`
- 目标框架:`net8.0-windows`
- 语言特性:`<Nullable>enable</Nullable>``<ImplicitUsings>enable</ImplicitUsings>`
- MVVM`CommunityToolkit.Mvvm`
- 宿主与依赖注入:`Microsoft.Extensions.Hosting`
- 日志:`NLog` + `NLog.Extensions.Logging`
- 配置:`appConfig.json` + `appConfig.{Environment}.json`
- 开发期敏感配置:`UserSecrets` 或环境变量
- 测试:优先单独测试项目,推荐 xUnitUI 难测逻辑应下沉到 ViewModel 或 Service
## 新项目初始化骨架
若无额外约束,推荐使用如下仓库结构:
```text
src/
<ProjectName>/
<ProjectName>.csproj
App.xaml
App.xaml.cs
MainWindow.xaml
MainWindow.xaml.cs
appConfig.json
appConfig.Development.json
NLog.config
Assets/
Models/
ViewModels/
Views/
Pages/
UserControls/
Services/
Interfaces/
Implementations/
Modules/
Utils/
tests/
<ProjectName>.Tests/
```
约束如下:
- `App.xaml` / `App.xaml.cs` 负责应用启动、Host 创建、全局异常处理、配置与日志装配。
- `MainWindow.xaml` / `.cs` 只负责主窗口装配,不承载核心业务逻辑。
- `ViewModels/` 保存可绑定状态、命令和页面协调逻辑。
- `Views/Pages/``Views/UserControls/` 保存页面和可复用视图组件。
- `Services/Interfaces/``Services/Implementations/` 用于硬件通信、文件处理、MES/PLC/条码/图像处理等业务服务。
- `Modules/` 用于较独立的能力模块,例如数据库、设备协议封装、审计上传、报表导出等。
- `Utils/` 仅保留轻量、通用、无业务语义的辅助工具;不要把主要业务逻辑塞入工具类。
- `tests/` 必须与应用项目分离,避免把测试代码混入正式程序集。
若仓库当前只有单个应用项目,也可暂时不建 `src/` 目录,直接在仓库根下放置 `<ProjectName>/`;但若无明确要求,优先采用 `src/ + tests/` 结构。
## 项目初始化最低要求
新建项目时,至少保证以下内容一次到位:
- WPF 应用可以成功还原、编译、启动。
- `App.xaml.cs` 中建立统一的 Host/DI 启动入口。
- 主窗口与主要 ViewModel 通过依赖注入创建。
- 日志系统已接入,且启动阶段异常可落日志。
- 配置文件支持环境分层加载。
- 输出目录包含 `appConfig.json``appConfig.Development.json``NLog.config`
- 为未来扩展预留 `Services``ViewModels``Views``Utils``Modules` 目录。
- 若涉及设备通信、轮询、文件监控、批处理等后台任务,必须预先考虑取消、限流、异常记录与 UI 线程切换。
## 构建 / 还原 / 运行 / 发布
以下命令中的 `<ProjectName>` 代表新建 WPF 项目名:
- 创建解决方案:`dotnet new sln -n <SolutionName>`
- 创建 WPF 项目:`dotnet new wpf -n <ProjectName> --framework net8.0`
- 还原:`dotnet restore src/<ProjectName>/<ProjectName>.csproj`
- 调试构建:`dotnet build src/<ProjectName>/<ProjectName>.csproj -c Debug`
- 发布构建:`dotnet build src/<ProjectName>/<ProjectName>.csproj -c Release`
- 运行UI`dotnet run --project src/<ProjectName>/<ProjectName>.csproj -c Debug`
- 发布示例:`dotnet publish src/<ProjectName>/<ProjectName>.csproj -c Release -r win-x64 --self-contained false`
初始化或修改 `.csproj` 时,至少保持以下属性:
- `<UseWPF>true</UseWPF>`
- `<TargetFramework>net8.0-windows</TargetFramework>`
- `<Nullable>enable</Nullable>`
- `<ImplicitUsings>enable</ImplicitUsings>`
若项目包含配置、日志、资源或字典文件,需要同步设置 `CopyToOutputDirectory`,确保运行目录完整。
## 测试 / 验证
- 新项目默认应预留独立测试项目:`tests/<ProjectName>.Tests/`
- 优先测试 ViewModel、Service、配置装配、解析逻辑、队列/调度逻辑,不要把核心逻辑压在难以测试的 code-behind 中。
- 若功能与 UI 强绑定,应先抽离为接口或服务,再进行单元测试或集成测试。
- 若暂未建立测试项目,至少执行一次构建验证,并手动完成关键 UI 流程检查。
- 单元测试示例:`dotnet test --filter FullyQualifiedName~命名空间.类名.方法名`
- 提交前最低要求:`dotnet build` 成功;涉及关键逻辑时应补充对应测试。
## Lint / 格式
- 若仓库尚未提供统一格式化工具或 `.editorconfig`,保持现有风格一致,不擅自引入新的格式化方案。
- 保持 using 简洁,移除未使用引用。
- 使用文件作用域命名空间,除非现有项目明确不采用。
- 避免只为“看起来更优雅”而大范围重排代码格式。
## XML 文档注释规则
- 所有 `public` / `internal` / `protected` 类、接口、记录、方法、属性必须有 **中文 XML 文档注释**
- 私有成员若逻辑不简单,或方法体超过 10 行,也应补充 XML 注释。
- 方法注释必须包含:
- `<summary>`
- 每个参数的 `<param>`
- 有返回值时的 `<returns>`
- 可能抛出异常时的 `<exception>`
- 异步方法名必须以 `Async` 结尾。
- 若方法接收 `CancellationToken`,需要在注释中写明取消行为及影响。
- 涉及命令、绑定、Dispatcher、后台线程、Task.Run、定时器、轮询、文件监控时注释必须明确线程模型和触发行为。
- 已有 XML 注释不得删除;修改实现后必须同步更新注释内容。
## 代码风格(通用 C#
- 命名空间使用文件作用域写法。
- 可读性优先:类型不明显时使用显式类型,明显时可使用 `var`
- 字段优先使用 `private readonly`,字段命名采用 `_camelCase`
- 常量使用 `const PascalCase`
- 参数校验只放在系统边界:用户输入、外部接口、文件内容、网络返回、硬件返回等位置。
- 不要为当前需求之外的场景做预留抽象。
- 不要新增只被调用一次的帮助类、工具类或接口。
- 不要为了兼容历史命名而保留无意义的中间层,确认无用即可删除。
## MVVM / WPF 实践
- 业务逻辑放在 ViewModel 或 Servicecode-behind 仅做视图装配、事件桥接、生命周期对接。
- 命令优先使用 `RelayCommand` / `AsyncRelayCommand`
- 可绑定属性优先使用 `[ObservableProperty]` 生成,不手写重复样板代码。
- 长耗时操作必须使用 `async/await`,不得阻塞 UI 线程。
- 后台线程不得直接更新绑定到 UI 的对象;涉及 UI 更新时必须切回 Dispatcher。
- 不要在 View 中直接 `new` 业务服务。
- 不要在 code-behind 中直接访问数据库、文件系统、MES、PLC、串口、相机或网络接口。
- 页面切换、对话框协调、状态共享应优先通过 ViewModel 或应用级服务完成。
- 若项目包含托盘、单实例、后台常驻、自动重连、设备轮询等能力,应将其建模为显式服务并通过 DI 管理生命周期。
## 宿主 / DI / 启动约定
-`App.xaml.cs` 中集中创建 `HostApplicationBuilder` 或等价 Host 对象。
- 所有服务、ViewModel、Window、Page 的注册集中管理,不要分散在多个随机文件中。
- 优先使用构造函数注入,不使用服务定位器模式。
- 应用启动顺序应清晰:配置加载 → 日志初始化 → Host 构建 → 服务注册 → 主窗口创建与显示。
- 若涉及全局异常捕获、未观察任务异常、UI 线程异常,应在启动阶段完成统一挂接。
- 若项目需要单实例约束,应采用明确、可维护的单实例方案,并保证启动顺序可追踪。
## 日志 / 异常 / 用户提示
- 注入 `ILogger<T>` 进行日志记录,优先使用结构化日志。
- 记录错误时使用包含异常对象的重载,例如:`_logger.LogError(ex, "消息 {上下文}", value)`
- 不要静默吞异常;至少按 Debug / Warning / Error 级别记录。
- 对用户可感知的失败,要同时提供用户友好提示与详细日志。
- 对启动失败、配置错误、设备离线、文件访问失败、网络错误等场景,应明确记录上下文。
- 对于可恢复错误,应在日志中记录恢复动作;对于不可恢复错误,应阻止继续执行并给出清晰提示。
## 配置与环境管理
- 配置文件默认采用:
- `appConfig.json`
- `appConfig.Development.json`
- 如有必要再增加 `appConfig.Production.json``appConfig.Local.json`
- 运行环境通过 `DOTNET_ENVIRONMENT``ASPNETCORE_ENVIRONMENT` 识别,默认 `Production`
- 不要硬编码密钥、口令、连接串、IP、账号。
- 开发期敏感配置优先使用 `UserSecrets` 或环境变量。
- 新增配置文件、资源文件、字典文件时,必须同步 `.csproj` 的输出复制规则。
- 读取配置时优先建立强类型 Options 或清晰的数据模型,不散落魔法字符串。
## 集合、并发与 I/O
- 文件处理优先使用流式 API`Directory.EnumerateFiles`,避免一次性加载大量文件。
- 批处理、轮询、文件监控、设备通信等后台任务需具备可取消性。
- 对共享状态使用明确的并发策略:`SemaphoreSlim``ConcurrentQueue``ConcurrentDictionary`、Channel 或串行队列。
- 不要锁住 UI 线程等待后台结果。
- 对缓冲区、日志列表、待处理队列要设置上限,避免内存无限增长。
- 所有后台任务都必须定义“谁创建、谁取消、谁记录异常、谁负责收尾”。
## 命名约定
- 类 / 结构 / 记录 / 枚举:`PascalCase`
- 接口:`I` 前缀 + `PascalCase`
- 方法 / 属性 / 事件:`PascalCase`
- 私有字段:`_camelCase`
- 局部变量 / 参数:`camelCase`
- 命令:`*Command`
- 异步方法:`*Async`
- 配置类型名应与配置节含义一致,不使用模糊命名如 `ConfigHelper``DataManager``CommonUtil`
## 新项目初始化完成的判定标准
一个新建 WPF 上位机项目,至少达到以下状态才可认为“初始化完成”:
- 可以成功 `restore``build``run`
- 主窗口可以正常显示
- Host / DI 已接入,主窗口和主 ViewModel 不依赖手工拼装
- 配置文件可被读取,环境分层生效
- 日志文件或日志输出可验证
- 核心目录结构已建立
- 至少保留一个可扩展的 Service、一个可扩展的 ViewModel、一个基础页面或主窗口示例
- 若已经接入设备/文件监听/后台任务,则具备最基本的取消与异常记录机制
## 贡献检查清单
- 是否遵循本文件规定的初始化骨架与技术基线。
- 是否保持业务逻辑不进入 code-behind。
- 是否为公开成员补齐中文 XML 注释。
- 是否已接入 Host/DI、配置和日志。
- 是否移除未使用 using、无意义抽象和一次性工具层。
- 是否避免硬编码敏感信息。
- 是否在涉及后台任务时明确线程切换、取消与异常处理。
- 是否为新增配置/资源设置输出复制规则。
- 是否在提交前至少执行一次 `dotnet build`
## 快速命令速查
- 新建解决方案:`dotnet new sln -n <SolutionName>`
- 新建 WPF 项目:`dotnet new wpf -n <ProjectName> --framework net8.0`
- 添加到解决方案:`dotnet sln add src/<ProjectName>/<ProjectName>.csproj`
- 还原:`dotnet restore src/<ProjectName>/<ProjectName>.csproj`
- 调试构建:`dotnet build src/<ProjectName>/<ProjectName>.csproj -c Debug`
- 发布构建:`dotnet build src/<ProjectName>/<ProjectName>.csproj -c Release`
- 运行调试:`dotnet run --project src/<ProjectName>/<ProjectName>.csproj -c Debug`
- 发布示例:`dotnet publish src/<ProjectName>/<ProjectName>.csproj -c Release -r win-x64 --self-contained false`
- 单测示例:`dotnet test --filter FullyQualifiedName~命名空间.类名.方法名`
## 额外说明
- 如果后续在某个新项目目录下生成了更具体的 `AGENTS.md`,应把该项目特有的设备协议、数据库约束、部署方式、配置项和 UI 行为写入子级文档,而不是污染仓库级规则。
- 仓库级 `AGENTS.md` 应保持“可复用、可初始化、不过度绑定具体业务”的定位。