# DbusSmsForward Debian Web 版实施计划 > **For Hermes:** Use subagent-driven-development skill to implement this plan task-by-task. **Goal:** 把当前 Debian 版 DbusSmsForward 改造成“带 Web 管理界面、可直接在 Debian 上运行、默认不要求本地编译”的版本。 **Architecture:** 保留现有 Generic Host + Worker 的短信转发核心,补一层 ASP.NET Core Minimal API 与静态 `wwwroot` 页面;运行形态改为 `dotnet DbusSmsForward.dll web` 或发布后的自包含目录直接运行。通过配置文件和环境变量驱动,不再依赖交互式初始化。 **Tech Stack:** .NET 8, ASP.NET Core Minimal API, Generic Host, Static Files, JSON config, systemd-friendly hosting. --- ## 0. 当前仓库真实状态(已核实) **已存在:** - `DbusTest/Program.cs`:已经是 Generic Host 风格入口。 - `DbusTest/appsettingsModel.cs`:已引入 `DbusSmsForwardOptions` / `DaemonConfig` / `AutmanPushConfig`。 - `DbusTest/Services/SmsForwardWorker.cs`:已有后台转发 worker。 - `DbusTest/Notifications/*`:已拆分通知发送器。 - `DbusTest/Helper/ConfigHelper.cs`:已支持 `/etc/dbussmsforward/appsettings.json` 优先加载。 **缺失:** - `wwwroot/` 不存在。 - 没有任何 Web API。 - `DbusSmsForward.csproj` 仍是 `Microsoft.NET.Sdk.Worker`,不是 Web SDK。 - `Program.cs` 里引用了若干当前仓库中不存在的类型: - `SampleConfigFactory` - `LegacyConfigurationBridge` - `CommandLineConfigurationApplier` - `ConfigurationValidator` - 本机当前 `dotnet` 命令不存在,无法本地编译验证;因此本阶段要优先完成“代码落地 + 文档化运行路径”。 --- ## 1. 目标运行方式 ### 目标 A:Debian 上直接运行(不在目标机编译) 推荐两种: 1. **Framework-dependent** - 目标机只安装 .NET 8 runtime / aspnetcore runtime - 直接运行: - `dotnet DbusSmsForward.dll web --urls http://0.0.0.0:8080` 2. **Self-contained 发布包** - 预先在别处发布好 Linux x64 / arm64 包 - 目标机无需装 dotnet - 直接运行发布目录中的可执行文件 **注意:** 当前用户要求“最好不需要编译,直接运行在 Debian 上”,因此仓库要优先支持 **运行已发布产物**,而不是要求 Debian 机器安装 SDK 编译源码。 --- ## 2. 代码实施任务 ### Task 1: 切换项目为 Web 宿主 **Objective:** 让项目具备 Minimal API + Static Files 能力。 **Files:** - Modify: `DbusTest/DbusSmsForward.csproj` **Step 1: 修改 SDK** 把: ```xml ``` 改成: ```xml ``` **Step 2: 保留现有依赖,继续复制配置文件** 保留现有 `PackageReference` 与 `appsettings*.json` 输出策略。 **Step 3: 增加 Web 静态资源复制规则(如需要)** 确认 `wwwroot/**` 默认由 Web SDK 处理。 **Verification:** - 代码层面确认 csproj 已切到 Web SDK。 --- ### Task 2: 补齐缺失的配置与兼容辅助类 **Objective:** 解决 `Program.cs` 当前引用缺失导致的不可编译问题。 **Files:** - Create: `DbusTest/Helper/SampleConfigFactory.cs` - Create: `DbusTest/Helper/LegacyConfigurationBridge.cs` - Create: `DbusTest/Helper/CommandLineConfigurationApplier.cs` - Create: `DbusTest/Helper/ConfigurationValidator.cs` **Step 1: `SampleConfigFactory`** - 返回一个最小可用的 `DbusSmsForwardOptions` 示例对象。 - 含 `Daemon/Modem/Forwarding/Notifications/LegacyCompatibility` 基本结构。 **Step 2: `LegacyConfigurationBridge`** - 从旧格式 `appSettings` 节点读取值,映射到新 `DbusSmsForwardOptions`。 - 至少映射: - `DeviceName` - `SmsCodeKey` - `ForwardIgnoreStorageType` - Email / PushPlus / DingTalk / Bark / WeCom / TG / Shell **Step 3: `CommandLineConfigurationApplier`** - 把 `AppCommand.EnabledChannels` 写入 `options.Forwarding.EnabledChannels` - 如果旧 flags 指定了渠道,则同步将对应 `options.Notifications.*.Enabled = true` **Step 4: `ConfigurationValidator`** - 做最小校验: - `Daemon.Mode` 合法值:`forward` / `web` / `both` - 若启用 email,必须有 host / sender / receiver - 若启用 autmanpush,必须有 ApiUrl - 校验失败抛 `InvalidOperationException` **Verification:** - `Program.cs` 的缺失引用都能对应到真实文件。 --- ### Task 3: 扩展命令模型支持 web/both 与 HTTP 端口 **Objective:** 让启动命令能表达 Web 模式。 **Files:** - Modify: `DbusTest/Models/AppCommand.cs` - Modify: `DbusTest/Services/CommandLineParser.cs` **Step 1: 扩展 `AppCommand` 字段** 新增: - `bool WebMode` - `bool ForwardMode` - `string Urls` - `int Port` - `string ConfigPath` **Step 2: 解析新参数** 新增支持: - `web` - `both` - `--urls http://0.0.0.0:8080` - `--port 8080` - `--config /etc/dbussmsforward/appsettings.json` **Step 3: 默认策略** - `run` = 仅 forward - `web` = 仅 web - `both` = forward + web - 当只传 `--urls` / `--port` 时,默认仍按 `web` 理解更合理;若保持兼容性,也可要求显式 `web`。 **Verification:** - 参数设计能清晰表达三种启动形态。 --- ### Task 4: 建立 Web API 服务层 **Objective:** 把 Web 层依赖从 `Program.cs` 抽出来,避免一团乱。 **Files:** - Create: `DbusTest/Services/SystemStatusService.cs` - Create: `DbusTest/Services/SmsWebService.cs` - Create: `DbusTest/Web/WebDtos.cs` **Step 1: `SystemStatusService`** - 复用 `ModemManagerHelper` 暴露: - `GetStatusAsync()` - 返回 modem path / qmi path / device / manufacturer / model / revision / operator / signal **Step 2: `SmsWebService`** - 封装: - `SendAsync(phone, content)` - `GetMessagesAsync(limit, phoneFilter, keyword, sort)` - `GetSettings()` - `SaveSettings()` - 若 `ModemManagerHelper` 尚无历史短信读取能力,则先补最小方法;至少支持列表读取。 **Step 3: DTO** - 请求与响应 DTO: - `SendSmsRequest` - `SettingsResponse` - `SmsMessageItem` - `ApiEnvelope` **Verification:** - Web API 调用不直接散落访问底层 helper。 --- ### Task 5: 在 `ModemManagerHelper` 中补历史短信列表接口 **Objective:** 支持 Web 历史短信页。 **Files:** - Modify: `DbusTest/ModemManagerHelper.cs` - Create: `DbusTest/Web/SmsMessageRecord.cs`(如 DTO 不想放 helper 内) **Step 1: 新增异步方法** 建议新增: ```csharp Task> ListMessagesAsync(CancellationToken cancellationToken = default) ``` **Step 2: 实现逻辑** - 使用现有 `CreateMessaging(_modemObjectPathNowUse)` - 枚举 DBus message path - 读取: - Number - Text - Timestamp - Storage - State - 做时间转换与空值兜底 **Step 3: 不破坏现有 forward 逻辑** - 保持现有短信监听逻辑不变 - 新增方法只做读取 **Verification:** - 代码上已经有明确的历史短信读取入口。 --- ### Task 6: 重写 `Program.cs` 为“单进程双模式入口” **Objective:** 同一个程序既能跑后台转发,也能跑 Web。 **Files:** - Modify: `DbusTest/Program.cs` **Step 1: 统一宿主构建** - 注册: - `ModemManagerHelper` - `NotificationDispatcher` - 各通知 sender - `SystemStatusService` - `SmsWebService` - 仅在 forward 模式下注册 `SmsForwardWorker` **Step 2: Web 模式构建** - 使用 `WebApplication.CreateBuilder(args)` 或在现有 host 上兼容 Web host - 开启: - `UseDefaultFiles()` - `UseStaticFiles()` **Step 3: Minimal API 路由** - `GET /api/system/status` - `GET /api/sms/messages` - `POST /api/sms/send` - `GET /api/settings` - `POST /api/settings` - `GET /api/health` **Step 4: 启动逻辑** - `send`:一次性发短信后退出 - `run`:只跑后台 worker - `web`:只跑 Web - `both`:Web + worker 同时运行 **Verification:** - `Program.cs` 不再只会 `host.RunAsync()` 一条路。 --- ### Task 7: 增加最小可用 Web UI **Objective:** 让 BOSS 在浏览器里直接看效果。 **Files:** - Create: `DbusTest/wwwroot/index.html` - Create: `DbusTest/wwwroot/app.js` - Create: `DbusTest/wwwroot/app.css` **Step 1: 页面结构** - 菜单: - 仪表盘 - 历史短信 - 发送短信 - 系统配置 **Step 2: 页面能力** - 仪表盘:加载 `/api/system/status` - 历史短信:加载 `/api/sms/messages` - 发送短信:调用 `/api/sms/send` - 配置:读写 `/api/settings` **Step 3: 保持纯静态实现** - 原生 HTML/CSS/JS - 不引入前端构建工具 - 保证部署简单 **Verification:** - 浏览器打开根路径 `/` 能直接进入管理页。 --- ### Task 8: 提供 Debian 直接运行所需文件 **Objective:** 让“直接运行在 Debian 上”真正落地。 **Files:** - Create: `DbusTest/appsettings.example.json` - Create: `DbusTest/dbussmsforward.service` - Modify: `README.md` **Step 1: 示例配置** - 提供新结构 JSON 样例 - 默认 `Daemon.Mode = "both"` - 默认 `urls` 示例写到 README,不强绑进配置 **Step 2: systemd unit** - 示例: - `WorkingDirectory=/opt/dbussmsforward` - `ExecStart=/usr/bin/dotnet /opt/dbussmsforward/DbusSmsForward.dll both --urls http://0.0.0.0:8080` - `Environment=DBUSSMSFORWARD_CONFIG_PATH=/etc/dbussmsforward/appsettings.json` **Step 3: README 更新重点** - 明确区分: - 运行源码需要 SDK - 运行发布产物只需 runtime 或无需 runtime(self-contained) - 给出 Debian 直接运行命令 - 给出 systemd 安装步骤 **Verification:** - 文档能支撑“别人拿到发布包就在 Debian 跑起来”。 --- ## 3. 本次实施优先级 1. 先修复仓库当前“缺失类导致不可编译”的问题 2. 再补 Web API 骨架 3. 再补 `wwwroot` 管理页 4. 最后补 README / example config / systemd --- ## 4. 运行验收标准 满足以下即视为达到目标: - 可用命令: - `dotnet DbusSmsForward.dll run` - `dotnet DbusSmsForward.dll web --urls http://0.0.0.0:8080` - `dotnet DbusSmsForward.dll both --urls http://0.0.0.0:8080` - `dotnet DbusSmsForward.dll send --to 13800138000 --text "测试短信"` - 根路径 `/` 可打开 Web UI - `/api/health` 返回成功 - `/api/system/status` 返回 modem 状态 - `/api/sms/messages` 返回历史短信列表 - `/api/settings` 可读写配置 - 提供 Debian 的 systemd unit 示例 --- ## 5. 当前阻塞说明 - 本机没有 `dotnet`,所以暂时不能做本地编译/运行验证。 - 但仓库代码改造、文件补齐、运行文档和 Debian 部署入口可以现在直接完成。