feat: 完成v1.3.0架构对齐与Web端根路径托管全量开发
- 重构架构:抽离AddCloudSyncServer到扩展类,补全中间层文档对齐 - 修复根路径404与鉴权跳转:新增中间件处理浏览器请求302跳转 - 实现种子数据初始化:添加默认管理员账号自动创建逻辑 - 优化前端代理与构建:新增Vite代理配置与自动构建Target - 补全测试与文档:新增集成测试,更新开发与部署文档
This commit is contained in:
@@ -10,6 +10,22 @@
|
||||
- v1.2.0:Linux 支持与增强功能
|
||||
- v1.3.0(开发中):MCP 服务与语音控制
|
||||
|
||||
### v1.3.0 (2026-08-08,Host 双角色+路由+鉴权流修补)
|
||||
|
||||
- **修复:根路径 404 / 前端缺失引导**:`Hua.Todo.Host/Program.cs` 新增 `MinimalBootstrapPageMiddleware`(位于 Swagger 之后、UseDefaultFiles/UseStaticFiles 之前)。当前端 `wwwroot/index.html` 缺失时,访问 `/` 或 SPA 路由(如 `/settings`)不再返回 404,而是返回**中文最小引导页**(含期望路径、WebRoot、环境版本、三种修复方式:`dotnet build Host` / 手动 npm build / CI skip build;同时列出 `/swagger`、`/api/auth/bootstrap` 等仍可用的入口),解决了"根路径 404 看起来像后端挂了"的误判问题。
|
||||
- **修复:没权限应该跳登录页**:`DynamicApiMiddleware` 新增 `WriteUnauthorizedResponse` / `WriteForbiddenResponse` / `IsBrowserHtmlRequest` 三个方法。判定规则:请求是 `GET`/`HEAD` 且 `Accept: text/html` 且 **非** `X-Requested-With: XMLHttpRequest` → 视为「用户在地址栏直访问接口页面」→ 返回 `302 Location: "/"`,回到 Host 前端 SPA,SPA 判断未登录 → 弹出登录/云同步设置 `CloudSyncSettingsDialog` 完成鉴权。**不破坏** axios/fetch:Accept 为 JSON 或非 GET/HEAD 时,继续返回原有的 401/403 JSON(`success=false + message`)。403 同样走 302 跳转。
|
||||
- **架构文档对齐(Host 不区分模式 = 双角色统一部署)**:更新 `01-项目架构.md` 模式 B 章节:Host 部署时**同时承担 (1) Web 端前端/后端同源部署和 (2) 云同步权威服务端**两种职责,不区分"模式";端点列表扩展为 4 项(`/`、`/api/*`、`/mcp`、`/swagger + /admin/*`);明确 401/403 在浏览器页面时 302 跳 `/` 由 SPA 接管登录;新增中间件顺序硬约束链接。
|
||||
- **验收测试补齐(ATDD)**:新增 `test/Hua.Todo.Host.Tests/CloudSync/HostBootstrapAndAuthRedirectTests.cs`,覆盖 6 场景:① 无 index.html 时 GET `/` + AcceptHtml → 200 + 引导页含「前端尚未构建」构建命令;② `/settings`(SPA 路由)同样 200 引导页;③ 未登录浏览器 GET `/api/security/policy`(PolicyRead 权限)+ AcceptHtml → 302 `/`;④ 未登录 AcceptJson 同一接口 → 401 JSON `success=false`;⑤ PUT `/api/security/policy`(非 GET)+ AcceptHtml → 仍 401 JSON 不跳转;⑥ 匿名 `POST /api/cloud-sync/probe` 不被 redirect 或 401 影响。6 个新测试 + 原 `WebRootStaticFileTests` 4 个场景 = 10 个全部通过。
|
||||
|
||||
### v1.3.0 (2026-06-17)
|
||||
|
||||
- **架构对齐(v1.3.0 工单 05)**:新增「Hua.Todo.HttpApi.AspNetCore」中间层到项目清单和依赖图(Core → Application → HttpApi.AspNetCore → {Host,Maui,Avalonia});抽离 `AddCloudSyncServer` 到 `CloudSyncServiceCollectionExtensions.cs`;清理 `01-项目架构.md` §5 过时的扩展点路径;`00-工单总览.md` 明确模式 B 中间件顺序硬约束,`MapCloudSyncProxySettings` 已废弃(接口改由 DynamicApi 自动暴露)。
|
||||
- **Web 端根路径托管前端(v1.3.0 工单 06)**:模式 B 下 Host 同时承担「动态 API + 前端静态站点 + MCP」三大职责;`Program.cs` 新增 `UseDefaultFiles`/`UseStaticFiles`/`MapFallbackToFile("index.html")` 并对齐中间件顺序;`Host.csproj` 新增 `BuildHuaTodoWebWebRoot` Target(增量 npm build + 双份 wwwroot 拷贝 + Node 缺失 Warning);开发文档新增「模式 B 双开」与「BuildHuaTodoWebWebRoot 自动构建」指南;新增 `WebRootStaticFileTests.cs` 覆盖根路径 / SPA fallback / API 不覆盖 / Swagger 不覆盖 4 场景。
|
||||
- **CloudSync Swagger + 路由修复**:CloudSync 接口改查 `IsMetadataEnabled`,移除 `IsEnabled=false`,Swagger 中 `/auth/* /tasks/* /security/* /admin/* /cloud-sync/*` 可见;MCP 工具改用命名空间过滤 `Hua.Todo.Application.CloudSync.*`,避免云同步接口暴露为 MCP。
|
||||
- **CloudSync 端点 DynamicApi 化**:移除 16 个手动 `MapCloudSyncEndpoints()`,新增 5 个 `IDynamicApiService` 接口 + `DynamicApiRouteAttribute` + `RequirePermissionAttribute`,中间件支持自定义前缀与权限检查;错误响应统一 401/403。
|
||||
- **测试项目重构**:`src/test/` → `test/`;Host.Tests 161 个测试全部通过。
|
||||
- **Host 云同步端点补齐修复**:Program.cs 新增 `AddCloudSyncServer()` + `MapCloudSyncEndpoints()`(后已改为 DynamicApi) + `app.UseAuthentication()` 顺序;前端云同步默认账号 `admin`/`123456` + 默认地址 `http://localhost:5173`;`TaskList.vue` 新增登录/登出/同步按钮。
|
||||
|
||||
### v1.3.0 (2026-06-16)
|
||||
|
||||
- **MCP 服务**:新增 MCP 协议端点(`/mcp`),DynamicMcpToolExtensions 自动扫描 IDynamicApiService 接口生成 MCP 工具;当前覆盖 ITaskService(9 个)+ IVoiceService(4 个)= 13 个 MCP 工具
|
||||
|
||||
@@ -27,19 +27,60 @@ npm install
|
||||
|
||||
### 1.3 启动开发环境
|
||||
|
||||
**方式一:Windows 三件套(推荐)**
|
||||
#### 方式一:模式 B「Web 端双开」(推荐,调试 Host API + 前端)
|
||||
|
||||
> 模式 B = Hua.Todo.Host 同时承担「动态 API + 前端静态站点 + MCP」三大职责,
|
||||
> 访问 `http://localhost:5173/` 即可看到完整 Todo 前端,HTTP 同源无需再配 Vite proxy。
|
||||
|
||||
开发调试时分两个终端(修改前端能 HMR 热更新,不会每次都触发 npm build):
|
||||
|
||||
```powershell
|
||||
# 终端 1:启动 Host(API 服务端)
|
||||
.\start-host.ps1
|
||||
|
||||
# 终端 2:启动前端开发服务器
|
||||
.\start-dev.ps1
|
||||
# 终端 1:启动 Host(监听 :5173 HTTP + :7055 HTTPS,未登录时 HTTP 即可)
|
||||
# ⚠️ 若尚未构建过前端,Host 直接启动后 GET / 返回 404。首次需要先 build 一次:
|
||||
# cd src/Hua.Todo.Web && npm ci && npm run build
|
||||
# 后续 build 会被 MSBuild Target 自动触发,见 1.4 节。
|
||||
cd src/Hua.Todo.Host
|
||||
dotnet run # 或 Visual Studio F5 调试 Hua.Todo.Host
|
||||
```
|
||||
|
||||
**方式二:MAUI 嵌入模式**
|
||||
```powershell
|
||||
# 终端 2:Vite 开发服务器(:5174,负责前端 HMR;通过 .env.development 把 API 打回 :5173 Host)
|
||||
cd src/Hua.Todo.Web
|
||||
npm run dev
|
||||
# 浏览器访问 http://localhost:5174 → 代码保存后浏览器立即刷新
|
||||
```
|
||||
|
||||
在 Visual Studio 中直接调试运行 `Hua.Todo.Maui` 项目,MAUI 会自动启动内嵌 WebServer 并加载前端。
|
||||
> 关闭 Vite 后直接访问 `http://localhost:5173/` 也能看到上次构建的前端静态页(非 HMR)。
|
||||
|
||||
#### 方式二:模式 A「MAUI 嵌入模式」
|
||||
|
||||
在 Visual Studio 中直接调试运行 `Hua.Todo.Maui` 项目,MAUI 会自动启动内嵌 WebServer(`localhost:5057`)并加载前端。
|
||||
云同步链路:前端同源调用 `:5057` → CloudSyncProxy → 用户配置的 Web 端地址(默认 `http://localhost:5173`)。
|
||||
|
||||
#### 方式三:纯 Host 发布模式(快速验证部署产物)
|
||||
|
||||
```powershell
|
||||
# 单次构建(前端 dist + Host 二进制 + wwwroot 复制)
|
||||
dotnet build src/Hua.Todo.Host -c Release
|
||||
dotnet run -c Release --project src/Hua.Todo.Host
|
||||
# 浏览器访问 http://localhost:5173/ → 与部署后的体验一致
|
||||
```
|
||||
|
||||
### 1.4 BuildHuaTodoWebWebRoot 自动构建说明
|
||||
|
||||
`src/Hua.Todo.Host/Hua.Todo.Host.csproj` 内置 `BuildHuaTodoWebWebRoot` MSBuild Target(触发时机:`BeforeBuild`),每次 `dotnet build/publish Hua.Todo.Host` 时执行:
|
||||
|
||||
| 行为 | 说明 |
|
||||
|---|---|
|
||||
| 增量构建 | 仅当 `src/Hua.Todo.Web/package.json` 或 `src/**/*.{ts,vue,css,html}` 变化时才 npm build,否则跳过 |
|
||||
| Node 缺失保护 | 未安装 Node/npm 时仅输出 Warning,不阻塞 Host C# API 层编译(CI 可在外层单独 build 前端) |
|
||||
| 跳过开关 | `dotnet build /p:SkipBuildHuaTodoWebWebRoot=true` 禁用整个 Target |
|
||||
| 双份拷贝 | 产物同时写入 `src/Hua.Todo.Host/wwwroot/`(本地 `dotnet run`)和 `bin/Release/net10.0/wwwroot/`(`dotnet publish` 打包) |
|
||||
|
||||
常见提示排查:
|
||||
|
||||
- **`[BuildHuaTodoWebWebRoot] 未检测到 Node/npm`**:安装 Node.js 18+ 并重启终端;或 CI 先 `cd src/Hua.Todo.Web && npm ci && npm run build`。
|
||||
- **`[BuildHuaTodoWebWebRoot] npm run build 退出码 != 0`**:去 `src/Hua.Todo.Web` 手动 `npm run build` 看 TypeScript/Vite 报错,修复后再 build Host。
|
||||
|
||||
## 2. 版本构建 (Release Build)
|
||||
|
||||
@@ -68,6 +109,15 @@ npm install
|
||||
|
||||
## 3. 服务端部署
|
||||
|
||||
### 3.0 构建流程(新增:前端 dist 自动进 wwwroot)
|
||||
|
||||
v1.3.0 起 `dotnet publish src/Hua.Todo.Host` 会自动执行:
|
||||
1. `npm install`(仅 node_modules 不存在时)
|
||||
2. `npm run build` → `src/Hua.Todo.Web/dist`
|
||||
3. `dist/**/*` → `publish_output/wwwroot/`(保留目录结构)
|
||||
|
||||
因此部署前**不再需要**单独 build 前端,直接一条命令即可。CI 若在容器内无 Node,设置 `-p:SkipBuildHuaTodoWebWebRoot=true` 并在外层先 `npm ci && npm run build`。
|
||||
|
||||
### 3.1 Docker 部署(推荐)
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user