# LicenseManager Platform - 开发环境搭建指南

| 项目 | 内容 |
| --- | --- |
| 文档版本 | v1.0 |
| 文档类型 | 开发环境搭建指南 (Development Setup Guide) |
| 关联文档 | [RDP v1.0.1](./LicenseManager-Platform-RDP-v1.0.1.md) · [TAD v1.0](./LicenseManager-Platform-TAD-v1.0.md) · [DB Design](./LicenseManager-Platform-Database-Design-v1.0.md) · [API Spec](./LicenseManager-Platform-API-Spec-v1.0.md) · [Deployment Guide](./LicenseManager-Platform-Deployment-Guide-v1.0.md) · [Core Dev Guide](./LicenseManager.Core-Development-Guide-v1.0.md) |
| 目标读者 | 平台开发工程师、前端工程师、QA、新入职成员、社区贡献者 |
| 文档日期 | 2026-07-25 |

---

## 0. 修订历史

| 版本 | 日期 | 修订内容 |
| --- | --- | --- |
| v1.0 | 2026-07-25 | 初稿 |
| v1.1 | 2026-10-08 | 商业化裁剪：移除订单/支付/发票/PSP/优惠券等资金流相关章节，资金流移交外部销售系统 |
| v1.2 | 2026-10-14 | 默认种子管理员凭据同步为 `admin@licensemanager.cn` / `Admin@123456`（与演示环境一致，同步 `SeedService.cs` 常量与测试） |

---

## 1. 概述

### 1.1 文档目的

本指南面向需要在本地工作站搭建 LicenseManager Platform 开发环境的工程师，覆盖后端（.NET 8 ASP.NET Core）、前端（Vue 3 + Vite 管理后台）以及测试（xUnit 单元测试 + Playwright E2E 测试）三类环境的完整搭建流程。

通过本指南，开发者可以：

- 在 30 分钟内完成本地环境就绪；
- 启动后端 API（默认端口 `8080`）并访问 Swagger；
- 启动前端管理后台（默认端口 `5173`）并通过 Vite 代理访问 API；
- 运行单元测试与端到端测试；
- 掌握常见启动故障的排查方法。

### 1.2 适用范围

| 范围 | 说明 |
| --- | --- |
| 适用 | 本地开发、调试、单元测试、E2E 测试、代码贡献前自测 |
| 不适用 | 生产部署（参考 [Deployment Guide](./LicenseManager-Platform-Deployment-Guide-v1.0.md)）、CI/CD 流水线配置、气隙安装 |

### 1.3 项目结构速览

解决方案 `LicenseManager.sln` 包含以下工程：

| 工程 | 类型 | 路径 | 说明 |
| --- | --- | --- | --- |
| `LicenseManager.Core.Abstractions` | src | `src/LicenseManager.Core.Abstractions` | 核心库抽象（接口、DTO） |
| `LicenseManager.Core` | src | `src/LicenseManager.Core` | 授权核心库（许可证生成/激活/验证） |
| `LicenseManager.Platform` | src | `src/LicenseManager.Platform` | 平台应用服务与限界上下文 |
| `LicenseManager.Infrastructure` | src | `src/LicenseManager.Infrastructure` | EF Core / Redis / 支付适配器 |
| `LicenseManager.Api` | src | `src/LicenseManager.Api` | ASP.NET Core Web API 入口 |
| `LicenseManager.Server` | src | `src/LicenseManager.Server` | 浮动许可证（Floating License）服务器 |
| `LicenseManager.Tools` | src | `src/LicenseManager.Tools` | 命令行工具 |
| `LicenseManager.Sample.Basic` | samples | `samples/LicenseManager.Sample.Basic` | 基础集成示例 |
| `LicenseManager.Core.Tests` | tests | `tests/LicenseManager.Core.Tests` | 核心库单元测试 |
| `LicenseManager.Platform.Tests` | tests | `tests/LicenseManager.Platform.Tests` | 平台层单元测试 |
| `LicenseManager.Infrastructure.Tests` | tests | `tests/LicenseManager.Infrastructure.Tests` | 基础设施层单元测试 |
| `LicenseManager.Api.Tests` | tests | `tests/LicenseManager.Api.Tests` | API 集成测试（WebApplicationFactory） |
| `licensemanager-admin` | web | `web/admin` | Vue 3 + Vite 管理后台前端 |

---

## 2. 系统要求

### 2.1 操作系统

| 操作系统 | 版本 | 备注 |
| --- | --- | --- |
| Windows | 10 / 11 / Server 2022 | 推荐使用 PowerShell 5+ |
| macOS | 12 Monterey 及以上 | Apple Silicon 需 .NET 8 原生支持 |
| Linux | Ubuntu 22.04 LTS / CentOS Stream / Debian 12 | 适用于容器化开发 |

### 2.2 运行时与 SDK 版本

| 组件 | 最低版本 | 推荐版本 | 验证命令 |
| --- | --- | --- | --- |
| .NET SDK | 8.0.100 | 8.0.x（最新补丁） | `dotnet --version` |
| Node.js | 18.19（LTS） | 20.x LTS | `node --version` |
| npm | 9.x | 10.x | `npm --version` |
| MySQL | 8.0.30 | 8.0.36+ | `mysql --version` |
| Redis | 6.2 | 7.x | `redis-server --version` |
| Git | 2.30 | 2.40+ | `git --version` |

> 提示：项目目标框架为 `net8.0`，所有 src/tests 工程统一使用 .NET 8。请勿使用 .NET 9 SDK 还原，避免间接包版本漂移。

### 2.3 端口要求

| 端口 | 用途 | 占用方 |
| --- | --- | --- |
| 8080 | 后端 API（HTTP，`launchSettings.json` 已固定） | `LicenseManager.Api` |
| 5173 | 前端 Vite 开发服务器（代理 `/v1` → 8080） | `web/admin` (`npm run dev`) |
| 3306 | MySQL（默认数据库） | 数据库服务 |
| 6379 | Redis（可选组件） | 缓存服务 |

确保上述端口在本机未被其他应用占用。

---

## 3. 开发工具推荐

### 3.1 IDE / 编辑器

| 工具 | 用途 | 备注 |
| --- | --- | --- |
| Visual Studio 2022 (17.8+) | 后端主力 IDE | 推荐 Windows 用户；Community 版免费 |
| JetBrains Rider | 后端跨平台 IDE | macOS / Linux 推荐 |
| Visual Studio Code | 前端 / 通用编辑器 | 安装 Volar、ESLint、C# Dev Kit 扩展 |
| WebStorm | 前端 IDE | 可选 |

### 3.2 数据库与缓存工具

| 工具 | 用途 |
| --- | --- |
| DBeaver Community | MySQL 连接、查询、表结构浏览 |
| MySQL Workbench | MySQL 官方客户端 |
| Redis Insight | Redis 可视化客户端 |
| redis-cli | Redis 命令行（调试缓存键） |

### 3.3 API 测试工具

| 工具 | 用途 |
| --- | --- |
| Swagger UI（内置） | 启动后端后访问 `http://localhost:8080/swagger` |
| Postman / Insomnia | 复杂接口联调、环境变量管理 |
| curl | 命令行快速验证 |

### 3.4 其他辅助工具

| 工具 | 用途 |
| --- | --- |
| git | 版本控制 |
| .NET EF Tools | 数据库迁移（`dotnet ef`） |
| Playwright CLI | 浏览器自动化（`npx playwright install`） |

---

## 4. 获取源码

### 4.1 克隆仓库

```bash
git clone <仓库地址> LicenseManager
cd LicenseManager
```

> 若使用内部 Git 服务器，请替换为对应 URL。社区贡献者请先 Fork 仓库后再克隆自己的副本。

### 4.2 切换分支

```bash
# 主干分支
git checkout main

# 或切换到功能分支
git checkout feature/your-feature
```

### 4.3 目录概览

克隆完成后，根目录应包含：

```
LicenseManager/
├── LicenseManager.sln
├── src/                     # 后端源码
├── tests/                   # 后端测试
├── samples/                 # 示例
├── web/                     # 前端子项目（admin / portal / partner / marketing / status / docs 等）
├── docs/                    # 文档（本文件所在目录）
└── .gitignore
```

---

## 5. 后端开发环境搭建

### 5.1 安装 .NET SDK

1. 前往 [.NET 官方下载页](https://dotnet.microsoft.com/download/dotnet/8.0) 下载对应操作系统的 .NET 8 SDK 安装包。
2. 安装完成后，打开终端验证：

   ```bash
   dotnet --version
   # 期望输出形如：8.0.x
   ```

3. （可选）安装 EF Core 工具，用于手动执行迁移：

   ```bash
   dotnet tool install --global dotnet-ef
   dotnet ef --version
   ```

### 5.2 还原 NuGet 包

在仓库根目录执行：

```bash
dotnet restore LicenseManager.sln
```

或在 IDE 中右键解决方案 → 还原 NuGet 包。

### 5.3 数据库配置（MySQL）

#### 5.3.1 准备 MySQL 实例

- 本地安装 MySQL 8.0；
- 或使用 Docker：

  ```bash
  docker run -d --name lm-mysql -p 3306:3306 \
    -e MYSQL_ROOT_PASSWORD=root123 \
    -e MYSQL_DATABASE=licensemanager \
    -e MYSQL_CHARSET=utf8mb4 \
    -e MYSQL_COLLATION=utf8mb4_unicode_ci \
    mysql:8.0 \
    --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
  ```

#### 5.3.2 创建数据库

```sql
CREATE DATABASE licensemanager CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
```

> 字符集必须为 `utf8mb4`，迁移文件中所有字符串列均带 `MySql:CharSet` 注解，使用其他字符集将导致迁移失败。

#### 5.3.3 创建 `appsettings.Local.json`

`appsettings.Local.json` 已加入 `.gitignore`，用于存放本地开发凭据，不会被提交。

在 `src/LicenseManager.Api/` 目录下创建 `appsettings.Local.json`：

```json
{
  "Database": {
    "Provider": "MySql",
    "ConnectionString": "Server=localhost;Port=3306;Database=licensemanager;User=root;Password=root123;CharSet=utf8mb4;"
  },
  "ConnectionStrings": {
    "MySql": "Server=localhost;Port=3306;Database=licensemanager;User=root;Password=root123;CharSet=utf8mb4;",
    "Redis": "localhost:6379"
  },
  "Jwt": {
    "Secret": "本地开发用 JWT 密钥-至少32字符-请勿用于生产"
  },
  "Seed": {
    "AdminEmail": "admin@licensemanager.cn",
    "AdminPassword": "Admin@123456"
  }
}
```

> 程序启动时会通过 `builder.Configuration.AddJsonFile("appsettings.Local.json", optional: true, reloadOnChange: true)` 加载该文件，覆盖 `appsettings.json` 中的空值键。

#### 5.3.4 连接字符串说明

| 配置键 | 用途 |
| --- | --- |
| `Database:Provider` | EF Core 提供程序，本指南使用 `MySql`（默认值）。可选：`PostgreSQL`、`SqlServer`、`MySql`、`Sqlite`、`Oracle` |
| `Database:ConnectionString` | 主连接串，被 `LicenseManagerDbContext` 使用 |
| `Database:ServerVersion` | 可选。MySQL 显式版本号（如 `8.0.36-mysql`），未配置时使用 `ServerVersion.AutoDetect` 自动探测 |
| `ConnectionStrings:MySql` | 兼容旧版配置的回退键，当 `Database:ConnectionString` 为空时使用 |
| `ConnectionStrings:Redis` | Redis 连接串，留空则不启用分布式缓存 |

### 5.4 Redis 配置（可选）

开发环境 Redis 为可选项，未配置时后端仍可启动（不注册 `IDistributedCache`）。

- 本地安装或使用 Docker：

  ```bash
  docker run -d --name lm-redis -p 6379:6379 redis:7-alpine
  ```

- 在 `appsettings.Local.json` 的 `ConnectionStrings:Redis` 中填入 `localhost:6379`（或带认证的 `localhost:6379,password=xxx`）。

### 5.5 环境变量

#### 5.5.1 `ASPNETCORE_ENVIRONMENT`

必须设置为 `Development`，以便启用 Swagger、放宽 CORS、允许使用占位管理员密码。

**PowerShell（当前会话）：**

```powershell
$env:ASPNETCORE_ENVIRONMENT='Development'
```

**PowerShell（持久化用户变量）：**

```powershell
[Environment]::SetEnvironmentVariable('ASPNETCORE_ENVIRONMENT', 'Development', 'User')
```

**bash / zsh：**

```bash
export ASPNETCORE_ENVIRONMENT=Development
# 持久化：写入 ~/.bashrc 或 ~/.zshrc
```

#### 5.5.2 `LICENSEMANAGER_DATA_PROTECTION_KEY`

`SecretProtector` 使用 AES-GCM 加密凭据，密钥来源：

1. 优先：环境变量 `LICENSEMANAGER_DATA_PROTECTION_KEY`（base64 编码的 32 字节）；
2. 兼容：`IConfiguration` 同名键；
3. 开发环境兜底：进程级随机密钥（每次重启变化，旧加密数据将无法解密）；
4. 生产环境：未设置时抛出 `InvalidOperationException` 拒绝启动。

开发环境建议生成一个稳定密钥并写入用户环境变量，避免重启后无法解密本地保存的密文：

**生成密钥（PowerShell）：**

```powershell
# 生成 base64 编码的 32 字节随机密钥
[Convert]::ToBase64String((1..32 | ForEach-Object { Get-Random -Maximum 256 }))
```

**生成密钥（bash）：**

```bash
openssl rand -base64 32
```

**设置环境变量（PowerShell 持久化）：**

```powershell
[Environment]::SetEnvironmentVariable('LICENSEMANAGER_DATA_PROTECTION_KEY', '<上一步输出的字符串>', 'User')
```

> 设置后需重启终端或 IDE 生效。若不设置，开发环境仍可运行，但每次进程重启后无法解密上一进程写入的密文。

> 注：原 5.5.3 PSP 凭据环境变量小节（`STRIPE_SECRET_KEY` / `Stripe:SecretKey`、`STRIPE_WEBHOOK_SECRET` / `Stripe:WebhookSecret` 等）已随商业化裁剪删除，资金流移交外部销售系统。

### 5.6 数据库迁移

#### 5.6.1 自动迁移（推荐）

后端启动时 `Program.cs` 会按提供程序初始化 schema：

```csharp
if (db.Database.ProviderName == "Pomelo.EntityFrameworkCore.MySql")
{
    await db.Database.MigrateAsync();
}
else
{
    await WarnIfSchemaDriftRiskAsync(db, app.Logger);
    await db.Database.EnsureCreatedAsync();
}
```

仅 MySQL 走版本化 EF 迁移；PostgreSQL / SQL Server / SQLite / Oracle 走 `EnsureCreated`（无迁移历史，已有表时记录 schema 漂移告警）。

首次运行 `dotnet run` 即可完成建表，无需手动操作。

#### 5.6.2 手动迁移

若需在启动前手动应用迁移（便于观察 SQL 或排查错误）：

```bash
cd src/LicenseManager.Api
dotnet ef database update --project ../LicenseManager.Infrastructure --startup-project .
```

#### 5.6.3 重置数据库

开发环境需要清空数据时：

```bash
dotnet ef database drop --project src/LicenseManager.Infrastructure --startup-project src/LicenseManager.Api
dotnet ef database update --project src/LicenseManager.Infrastructure --startup-project src/LicenseManager.Api
```

### 5.7 启动后端

#### 5.7.1 命令行启动

```bash
cd src/LicenseManager.Api
dotnet run --urls http://localhost:8080
```

或从仓库根目录：

```bash
dotnet run --project src/LicenseManager.Api/LicenseManager.Api.csproj --urls http://localhost:8080
```

#### 5.7.2 IDE 启动

- Visual Studio：将 `LicenseManager.Api` 设为启动项目，按 F5（调试）或 Ctrl+F5（不调试）；
- Rider：选择 `LicenseManager.Api` 运行配置。

#### 5.7.3 验证启动成功

启动成功后，控制台将输出监听地址。访问以下端点进行验证：

| URL | 期望响应 |
| --- | --- |
| `http://localhost:8080/` | 返回 API 概览 JSON（包含 `name`、`version`、`endpoints` 等） |
| `http://localhost:8080/swagger` | Swagger UI 页面（仅 Development 环境可用） |
| `http://localhost:8080/v1/status` | 健康检查端点 |
| `http://localhost:8080/v1/readyz` | 就绪检查端点 |

### 5.8 默认管理员账号

后端首次启动时，`SeedService.InitializeAsync` 会幂等地创建默认管理员账号：

| 字段 | 默认值 | 覆盖配置键 |
| --- | --- | --- |
| 邮箱 | `admin@licensemanager.cn` | `Seed:AdminEmail` |
| 显示名 | `Default Admin` | （固定常量，不可配置） |
| 密码 | `Admin@123456` | `Seed:AdminPassword` |

> 重要：
> - `Admin@123456` 仅为开发环境占位密码，**生产环境未配置 `Seed:AdminPassword` 时将抛出异常拒绝启动**；
> - 该账号可通过 `appsettings.Local.json` 的 `Seed` 节点自定义；
> - 如已存在同邮箱账号，种子服务不会重复创建或覆盖密码。

使用默认账号登录前端管理后台或调用 `/v1/auth/login` 接口获取 JWT。

---

## 6. 前端开发环境搭建

### 6.1 安装 Node.js

前往 [Node.js 官网](https://nodejs.org/) 下载 20.x LTS 安装包，或使用版本管理工具：

```bash
# 使用 nvm（Windows: nvm-windows）
nvm install 20
nvm use 20

# 使用 fnm
fnm install 20
fnm use 20
```

验证：

```bash
node --version   # 期望 v20.x
npm --version    # 期望 10.x
```

### 6.2 安装依赖

```bash
cd web/admin
npm install
```

> 若 npm 速度较慢，可切换国内镜像：`npm config set registry https://registry.npmmirror.com`

### 6.3 启动 Vite 开发服务器

```bash
npm run dev
```

启动后控制台输出类似：

```
  VITE v5.2.x  ready in xxx ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
```

### 6.4 访问前端

浏览器打开 `http://localhost:5173`，使用默认管理员账号登录：

- 邮箱：`admin@licensemanager.cn`
- 密码：`Admin@123456`

### 6.5 Vite 代理配置

`web/admin/vite.config.ts` 已配置开发代理：

```ts
server: {
  port: 5173,
  proxy: {
    '/v1': {
      target: 'http://localhost:8080',
      changeOrigin: true,
    },
  },
}
```

前端所有 `/v1/*` 请求会被代理到后端 `http://localhost:8080`，因此**启动前端前请确保后端已在 8080 端口运行**。

### 6.6 前端技术栈

| 库 | 版本 | 用途 |
| --- | --- | --- |
| vue | ^3.4.0 | 视图框架 |
| vue-router | ^4.3.0 | 路由 |
| pinia | ^2.1.0 | 状态管理 |
| element-plus | ^2.7.0 | UI 组件库 |
| @element-plus/icons-vue | ^2.3.0 | 图标 |
| axios | ^1.7.0 | HTTP 客户端 |
| echarts / vue-echarts | ^5.5.0 / ^7.0.0 | 图表 |
| vue-i18n | ^9.13.0 | 国际化 |
| vite | ^5.2.0 | 构建工具 |
| typescript | ^5.4.0 | 类型系统 |
| vue-tsc | ^2.0.0 | Vue 类型检查 |
| @playwright/test | ^1.61.1 | E2E 测试 |

---

## 7. 测试环境搭建

### 7.1 后端单元测试与集成测试

#### 7.1.1 测试框架

| 工程 | 框架 | 说明 |
| --- | --- | --- |
| `LicenseManager.Core.Tests` | xUnit + FluentAssertions | 核心库单元测试 |
| `LicenseManager.Platform.Tests` | xUnit + FluentAssertions | 平台层单元测试 |
| `LicenseManager.Infrastructure.Tests` | xUnit + FluentAssertions | 基础设施层测试 |
| `LicenseManager.Api.Tests` | xUnit + FluentAssertions + `Microsoft.AspNetCore.Mvc.Testing` | API 集成测试（WebApplicationFactory） |
| `LicenseManager.Server.Tests` | xUnit + FluentAssertions | 浮动许可证服务器（LeaseService）测试 |

> API 集成测试默认使用 EF Core InMemory 提供程序，无需真实 MySQL/Redis 即可运行。

#### 7.1.2 运行所有测试

```bash
dotnet test LicenseManager.sln
```

#### 7.1.3 运行指定工程

```bash
dotnet test tests/LicenseManager.Core.Tests
dotnet test tests/LicenseManager.Api.Tests
```

#### 7.1.4 生成测试报告

```bash
dotnet test LicenseManager.sln --logger "trx;LogFileName=test-results.trx" --results-directory ./TestResults
```

结果文件为 TRX 格式，可由 VS / Rider / VS Code 测试资源管理器加载。

#### 7.1.5 启用代码覆盖率（可选）

```bash
dotnet test --collect:"XPlat Code Coverage"
```

报告输出于 `TestResults/<guid>/coverage.cobertura.xml`，可使用 `reportgenerator` 工具转 HTML。

### 7.2 前端 E2E 测试（Playwright）

#### 7.2.1 安装浏览器

首次运行前需安装 Playwright 浏览器二进制：

```bash
cd web/admin
npx playwright install
# 仅安装 chromium（与配置一致）
npx playwright install chromium
```

#### 7.2.2 前置依赖

E2E 测试**不会自动启动**前后端服务（`playwright.config.ts` 中故意未配置 `webServer`），需手动启动：

```bash
# 终端 1：启动后端
dotnet run --project src/LicenseManager.Api --urls http://localhost:8080

# 终端 2：启动前端
cd web/admin
npm run dev
```

#### 7.2.3 运行 E2E 测试

```bash
cd web/admin

# 默认（headless）
npm run test
# 或
npx playwright test

# 带界面（headed）
npm run test:headed

# UI 模式（交互式调试）
npm run test:ui
```

#### 7.2.4 测试配置要点

`playwright.config.ts` 关键配置：

| 配置项 | 值 | 说明 |
| --- | --- | --- |
| `testDir` | `./e2e` | 测试用例目录 |
| `baseURL` | `http://localhost:5173` | 前端地址 |
| `fullyParallel` | `true` | 并行执行 |
| `retries` (CI) | 2 | CI 环境重试次数 |
| `reporter` | `['list'], ['html', { open: 'never' }]` | 控制台列表 + HTML 报告 |
| `trace` | `on-first-retry` | 首次重试时记录 trace |
| `screenshot` | `only-on-failure` | 失败时截图 |
| `video` | `retain-on-failure` | 失败时保留视频 |
| `projects` | chromium | 当前仅配置 Chromium |

#### 7.2.5 查看测试报告

```bash
npm run test:report
# 或
npx playwright show-report
```

将自动在浏览器打开 HTML 报告，包含失败截图、视频、trace 等附件。

#### 7.2.6 现有 E2E 用例

`web/admin/e2e/` 目录包含以下测试文件：

| 文件 | 覆盖范围 |
| --- | --- |
| `auth.spec.ts` | 认证流程 |
| `login-flow.spec.ts` | 登录流程 |
| `dashboard.spec.ts` | 仪表盘 |
| `navigation.spec.ts` | 导航 |
| `routes.spec.ts` | 路由 |
| `crud-operations.spec.ts` | 增删改查 |
| `customers.spec.ts` | 客户管理 |
| `licenses.spec.ts` | 许可证管理 |
| `list-pages.spec.ts` | 列表分页 |
| `reports.spec.ts` | 报表 |
| `api-proxy.spec.ts` | API 代理 |
| `api-coverage.spec.ts` | API 覆盖率 |
| `multi-role.spec.ts` | 多角色权限验证 |
| `fixtures.ts` | 公共夹具 |

---

## 8. 常见问题

### 8.1 端口冲突

**现象**：启动后端报 `Failed to bind address http://localhost:8080: address already in use`。

**排查**：

```bash
# Windows
netstat -ano | findstr :8080
# 找到 PID 后终止
taskkill /PID <PID> /F

# Linux / macOS
lsof -i :8080
kill -9 <PID>
```

或更换端口：

```bash
dotnet run --project src/LicenseManager.Api --urls http://localhost:5000
```

> 更换后端端口后需同步修改 `web/admin/vite.config.ts` 中 `proxy['/v1'].target`，否则前端代理失效。

### 8.2 数据库连接失败

**现象**：启动时抛出 `MySqlConnector.MySqlException` 或 `Unable to connect to any of the specified MySQL hosts`。

**排查清单**：

1. 确认 MySQL 服务已启动：`mysqladmin -u root -p ping`；
2. 确认 `appsettings.Local.json` 中连接串的主机、端口、用户名、密码正确；
3. 确认 `licensemanager` 数据库存在且字符集为 `utf8mb4`；
4. 确认 `Database:Provider` 为 `MySql`（区分大小写）；
5. 若使用 Docker MySQL，确认端口已映射 `-p 3306:3306`；
6. 连接串包含 `CharSet=utf8mb4;` 以避免字符集不一致。

### 8.3 EF 迁移失败

**现象**：`dotnet ef database update` 报 `MySql:CharSet` 相关错误或表已存在。

**排查**：

- 确认 MySQL 版本 ≥ 8.0；
- 在连接串或 `Database:ServerVersion` 中显式指定版本：`"ServerVersion": "8.0.36-mysql"`；
- 若数据库已部分迁移，可 `dotnet ef database drop` 后重新 `update`（开发环境数据可丢弃）。

### 8.4 前端依赖安装失败

**现象**：`npm install` 报错或卡住。

**处理**：

```bash
# 清理缓存
npm cache clean --force

# 删除 node_modules 重装
rm -rf node_modules package-lock.json
npm install

# 切换镜像
npm config set registry https://registry.npmmirror.com
```

### 8.5 前端代理 502 / 请求无响应

**现象**：浏览器请求 `/v1/*` 返回 502 Bad Gateway。

**原因**：后端未启动，或未在 `8080` 端口启动。

**处理**：先启动后端（`dotnet run --urls http://localhost:8080`），再启动前端。

### 8.6 默认管理员登录失败

**现象**：使用 `admin@licensemanager.cn / Admin@123456` 登录返回 401。

**排查**：

1. 检查 `appsettings.Local.json` 是否覆盖了 `Seed:AdminEmail` / `Seed:AdminPassword`；
2. 查看后端启动日志，确认出现 `已创建默认管理员账号` 字样；
3. 若数据库已存在同邮箱账号但密码不同，种子服务不会覆盖密码。可手动清空 `users` 表后重启，或调用密码重置接口。

### 8.7 数据保护密钥错误

**现象**：解密凭据时抛出 `AuthenticationTagMismatchException` 或日志输出 `SecretProtector 在开发环境使用进程级随机密钥`。

**原因**：进程重启后随机密钥丢失，无法解密上一进程加密的数据。

**处理**：

1. 设置环境变量 `LICENSEMANAGER_DATA_PROTECTION_KEY`（参考 5.5.2）；
2. 重启后端；
3. 若本地数据库中已存在无法解密的密文，可清空对应字段或重置数据库。

### 8.8 Playwright 浏览器未安装

**现象**：`npx playwright test` 报 `Executable doesn't exist at .../chromium-.../chrome-win/chrome.exe`。

**处理**：

```bash
npx playwright install chromium
```

### 8.9 Swagger 无法访问

**现象**：访问 `http://localhost:8080/swagger` 返回 404。

**原因**：未设置 `ASPNETCORE_ENVIRONMENT=Development`，Swagger 仅在开发环境启用。

**处理**：参考 5.5.1 设置环境变量后重启。

---

## 9. 附录

### 9.1 常用命令速查表

#### 后端

| 操作 | 命令 |
| --- | --- |
| 还原 NuGet 包 | `dotnet restore LicenseManager.sln` |
| 构建解决方案 | `dotnet build LicenseManager.sln` |
| 启动 API（8080） | `dotnet run --project src/LicenseManager.Api --urls http://localhost:8080` |
| 启动 API（开发环境） | `$env:ASPNETCORE_ENVIRONMENT='Development'; dotnet run --project src/LicenseManager.Api --urls http://localhost:8080` |
| 运行全部单元测试 | `dotnet test LicenseManager.sln` |
| 运行指定测试工程 | `dotnet test tests/LicenseManager.Api.Tests` |
| 应用 EF 迁移 | `dotnet ef database update --project src/LicenseManager.Infrastructure --startup-project src/LicenseManager.Api` |
| 删除数据库 | `dotnet ef database drop --project src/LicenseManager.Infrastructure --startup-project src/LicenseManager.Api` |
| 添加新迁移 | `dotnet ef migrations add <Name> --project src/LicenseManager.Infrastructure --startup-project src/LicenseManager.Api` |
| 生成数据保护密钥（PowerShell） | `[Convert]::ToBase64String((1..32 \| ForEach-Object { Get-Random -Maximum 256 }))` |
| 生成数据保护密钥（bash） | `openssl rand -base64 32` |

#### 前端

| 操作 | 命令 |
| --- | --- |
| 安装依赖 | `cd web/admin; npm install` |
| 启动开发服务器 | `npm run dev` |
| 构建生产包 | `npm run build` |
| 预览生产包 | `npm run preview` |
| 安装 Playwright 浏览器 | `npx playwright install chromium` |
| 运行 E2E 测试 | `npm run test` |
| 运行 E2E（带界面） | `npm run test:headed` |
| 运行 E2E（UI 模式） | `npm run test:ui` |
| 查看 HTML 测试报告 | `npm run test:report` |

#### 数据库与缓存

| 操作 | 命令 |
| --- | --- |
| 启动 MySQL（Docker） | `docker run -d --name lm-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root123 -e MYSQL_DATABASE=licensemanager mysql:8.0` |
| 启动 Redis（Docker） | `docker run -d --name lm-redis -p 6379:6379 redis:7-alpine` |
| 连接 MySQL | `mysql -h localhost -P 3306 -u root -p licensemanager` |
| 连接 Redis | `redis-cli -h localhost -p 6379` |

#### Git

| 操作 | 命令 |
| --- | --- |
| 克隆仓库 | `git clone <仓库地址>` |
| 查看状态 | `git status` |
| 拉取最新 | `git pull` |
| 创建功能分支 | `git checkout -b feature/your-feature` |

### 9.2 端口与地址速查

| 服务 | 地址 | 说明 |
| --- | --- | --- |
| 后端 API 根 | `http://localhost:8080/` | 返回 API 概览 |
| Swagger UI | `http://localhost:8080/swagger` | 仅 Development |
| 健康检查 | `http://localhost:8080/v1/status` | - |
| 就绪检查 | `http://localhost:8080/v1/readyz` | - |
| 依赖检查 | `http://localhost:8080/v1/status/dependencies` | - |
| 前端管理后台 | `http://localhost:5173/` | Vite 开发服务器 |
| MySQL | `localhost:3306` | - |
| Redis | `localhost:6379` | - |

### 9.3 关键配置键速查

| 配置键 | 来源 | 说明 |
| --- | --- | --- |
| `Database:Provider` | `appsettings.json` / `appsettings.Local.json` | 数据库提供程序（`MySql` 等） |
| `Database:ConnectionString` | `appsettings.Local.json` | 主连接串 |
| `Database:ServerVersion` | `appsettings.Local.json` | MySQL 显式版本号（可选） |
| `ConnectionStrings:MySql` | `appsettings.Local.json` | 兼容回退连接串 |
| `ConnectionStrings:Redis` | `appsettings.Local.json` | Redis 连接串（留空则不启用） |
| `Jwt:Secret` | `appsettings.Local.json` | JWT 签名密钥 |
| `Seed:AdminEmail` | `appsettings.Local.json` | 种子管理员邮箱 |
| `Seed:AdminPassword` | `appsettings.Local.json` | 种子管理员密码 |
| `Auth:Enabled` | `appsettings.json` | 是否启用认证 |
| `RateLimit:PerMinute` | `appsettings.json` | 每分钟限流阈值 |
| `RateLimit:Distributed` | `appsettings.json` | 分布式全局计数开关（默认 `false`；开启后经 Redis `IDistributedCache` 跨实例计数，多实例部署必须开启，未配置 Redis 时回退进程内计数并告警） |
| `RateLimit:TrustXForwardedFor` | `appsettings.json` | 匿名限流是否信任 `X-Forwarded-For` 首段（默认 `false`，反向代理部署时开启） |
| `Cors:AllowedOrigins` | `appsettings.json` | 生产环境 CORS 白名单 |
| `Maintenance:Enabled` | `appsettings.json` | 维护模式开关 |
| `ASPNETCORE_ENVIRONMENT` | 环境变量 | 运行环境（`Development`） |
| `LICENSEMANAGER_DATA_PROTECTION_KEY` | 环境变量 | AES-GCM 加密密钥（base64 32 字节） |

### 9.4 默认账号

| 字段 | 值 |
| --- | --- |
| 邮箱 | `admin@licensemanager.cn` |
| 密码 | `Admin@123456`（仅开发环境占位） |
| 显示名 | `Default Admin` |

> 生产环境必须通过 `Seed:AdminPassword` 显式提供密码，否则启动失败。

### 9.5 进一步阅读

| 主题 | 文档 |
| --- | --- |
| 平台架构与设计 | [RDP v1.0.1](./LicenseManager-Platform-RDP-v1.0.1.md) |
| 技术选型 | [TAD v1.0](./LicenseManager-Platform-TAD-v1.0.md) |
| 数据库设计 | [DB Design v1.0](./LicenseManager-Platform-Database-Design-v1.0.md) |
| API 规范 | [API Spec v1.0](./LicenseManager-Platform-API-Spec-v1.0.md) |
| 部署运维 | [Deployment Guide v1.0](./LicenseManager-Platform-Deployment-Guide-v1.0.md) |
| 核心库开发 | [Core Dev Guide v1.0](./LicenseManager.Core-Development-Guide-v1.0.md) |
