# EchoChat 第一阶段：基础设施与用户体系 - 实施计划

> **状态：✅ Phase 1 全部完成**（2026-03-02）
> 11 个 Task 全部通过端到端验证和代码审查。
> 分支：`feature/phase1-foundation-and-auth`
> **补充：角色等级体系与权限管控已实施**（2026-03-02）— `auth_roles.level` 字段 + 层级权限 + 多选角色分配

> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

**目标：** 搭建项目完整骨架（Go 后端、uniapp 前端、Vue3 管理端），实现用户注册登录体系，建立 Docker 开发环境，为后续 IM/会议等功能奠定基础。

**架构：** Go 单体模块化服务 + uniapp 前台 + Vue3 管理端 + PostgreSQL + Redis，Docker Compose 编排。

**技术栈：** Go 1.23+ (Gin + GORM + Wire + zap) / uniapp 3.0 (Vue 3.4 + Pinia 2.x) / Vue 3.5+ 管理端 (Pinia 3.x + Element Plus) / PostgreSQL 17 / Redis 7 / Docker Compose

**设计文档：** `docs/plans/2026-02-27-echochat-system-design.md`

**日志系统设计：** `docs/architecture/system-architecture.md` 第八节

---

## 全局规范（贯穿所有 Task）

### 代码注释规范

以下规范适用于所有 Task 中编写的代码，必须严格遵守：

**Go 后端注释规范：**
1. **包注释**：每个 package 必须有注释，以包名开头，说明包的用途
2. **公开函数/方法**：所有大写字母开头的函数/方法必须有注释，格式：`// FuncName 描述功能`
3. **结构体注释**：每个 struct 需要注释说明用途，关键字段需要行内注释
4. **枚举/常量**：每个常量值必须有注释说明含义
5. **复杂逻辑**：非显而易见的逻辑段落需要注释说明意图和设计考虑
6. **DAO 层**：每个数据库操作函数需说明 SQL 查询逻辑和性能考虑
7. **中间件**：说明中间件的作用、执行顺序依赖和副作用

**前端注释规范（Vue/uniapp）：**
1. **组件注释**：每个 `.vue` 文件顶部 `<!-- -->` 说明组件用途、功能清单、对应 API 和文档引用
2. **API 函数**：每个 API 调用函数说明对应后端接口路径和参数
3. **Store**：state 字段、action 方法需要注释说明
4. **工具函数**：参数和返回值类型、用途说明
5. **复杂模板逻辑**：`v-if`/`v-for` 等复杂条件需要注释说明
6. **CSS 注释**：`<style>` 顶部声明设计系统来源和色板引用

### 前端目录结构与编码规范

**目录结构（uni-app 前台）：**

```
frontend/src/
├── api/              # API 接口模块，每个后端模块一个文件
│   └── auth.js       # 对应 /api/v1/auth/*
├── pages/            # 页面组件（uni-app 页面路由）
│   ├── auth/         # 认证页面（login/register）
│   ├── index/        # 启动页（登录状态判断 + 路由重定向）
│   ├── chat/         # 消息列表（TabBar 页）
│   ├── contact/      # 联系人（TabBar 页）
│   ├── meeting/      # 会议（TabBar 页）
│   └── profile/      # 个人中心（TabBar 页）
├── store/            # Pinia 状态管理
│   └── user.js       # 用户认证状态
├── utils/            # 工具函数
│   ├── request.js    # HTTP 请求封装（基于 uni.request）
│   └── storage.js    # 本地存储封装
├── services/         # 业务服务（WebSocket 等）
│   └── websocket.js  # WebSocket 管理（占位）
├── static/           # 静态资源（图片、图标）
├── main.js           # 应用入口（Pinia 初始化）
├── App.vue           # 根组件
├── pages.json        # 页面路由 + TabBar 配置
└── manifest.json     # 应用配置
```

**编码规范：**
1. **模块化导入**：使用 `@/` 别名引用 `src/` 下的模块（如 `@/api/auth`、`@/store/user`）
2. **命名规范**：文件名使用 kebab-case 或小写，Vue 组件 name 使用 PascalCase
3. **导出方式**：统一使用 ES Module（`export` / `export default`）。禁止使用 CommonJS `module.exports`/`require`，Vite 构建环境不兼容 CJS
4. **状态管理**：所有全局状态通过 Pinia Store 管理，组件内部状态使用 `data()`
5. **API 调用**：页面组件不直接调用 `request.js`，必须通过 `api/` 层或 Store action
6. **表单校验**：使用 label + error feedback 模式（禁止 placeholder-only），参照 ui-ux-pro-max UX 规则
7. **设计系统**：所有页面 UI 必须基于 `design-system/echochat/MASTER.md` 设计规范实现
8. **响应式单位**：使用 `rpx` 替代 `px`（750rpx = 屏幕宽度），确保多端适配
9. **npm 配置**：`frontend/.npmrc` 设置 `legacy-peer-deps=true`（uni-app 生态需要）

### 日志规范

所有 Task 中的 Go 后端代码必须遵守日志规范（详见架构文档第八节）：
1. 每个 Service/DAO 函数使用入口/出口日志模式
2. 所有日志从 context 提取 trace_id
3. 错误必须记录 ERROR 级别日志，包含上下文信息
4. 敏感信息必须脱敏

### Wire 依赖注入

从初期就使用 Wire 管理依赖注入：
1. 每个模块在 `provider.go` 中声明 Provider Set
2. 根目录 `app/provider/` 下维护全局 Wire 配置
3. 新增模块时同步更新 Wire Provider

---

## Task 1: Docker Compose 开发环境搭建

**Files:**
- Create: `deploy/docker-compose.dev.yml`
- Create: `deploy/docker/postgres/init.sql`
- Create: `deploy/docker/redis/redis.conf`
- Create: `scripts/dev-setup.sh`

**Step 1: 创建 Docker Compose 开发环境配置**

创建 `deploy/docker-compose.dev.yml`，包含 PostgreSQL 17 和 Redis 7 两个服务：

```yaml
version: '3.8'

services:
  postgres:
    image: postgres:17
    container_name: echochat-postgres
    environment:
      POSTGRES_DB: echochat
      POSTGRES_USER: echochat
      POSTGRES_PASSWORD: echochat_dev_2026
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
      - ./docker/postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U echochat"]
      interval: 5s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7
    container_name: echochat-redis
    ports:
      - "6379:6379"
    volumes:
      - redisdata:/data
      - ./docker/redis/redis.conf:/usr/local/etc/redis/redis.conf
    command: redis-server /usr/local/etc/redis/redis.conf
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 5s
      retries: 5

volumes:
  pgdata:
  redisdata:
```

**Step 2: 创建 PostgreSQL 初始化 SQL**

创建 `deploy/docker/postgres/init.sql`，包含 auth 模块相关的所有表：

```sql
-- auth_users, auth_roles, auth_user_roles 表
-- 参考设计文档第四节数据库设计
-- 同时插入默认角色: user, admin, super_admin
-- 插入默认超级管理员账号
```

**Step 3: 创建 Redis 配置文件**

创建 `deploy/docker/redis/redis.conf`，基础开发环境配置。

**Step 4: 创建开发环境搭建脚本**

创建 `scripts/dev-setup.sh`，一键启动开发环境。

**Step 5: 启动并验证开发环境**

Run: `cd deploy && docker compose -f docker-compose.dev.yml up -d`
Expected: PostgreSQL 和 Redis 正常启动，可以连接

**Step 6: Commit**

```bash
git add deploy/ scripts/
git commit -m "infra: Docker Compose 开发环境（PostgreSQL + Redis）"
```

---

## Task 2: Go 服务骨架搭建

**Files:**
- Create: `backend/go-service/cmd/server/main.go`
- Create: `backend/go-service/go.mod`
- Create: `backend/go-service/config/config.go`
- Create: `backend/go-service/config/config.dev.yaml`
- Create: `backend/go-service/pkg/db/postgres.go`
- Create: `backend/go-service/pkg/db/redis.go`
- Create: `backend/go-service/pkg/logs/logger.go`
- Create: `backend/go-service/pkg/logs/trace.go`
- Create: `backend/go-service/pkg/utils/response.go`
- Create: `backend/go-service/pkg/middleware/cors.go`
- Create: `backend/go-service/pkg/middleware/recovery.go`
- Create: `backend/go-service/pkg/middleware/logger.go`
- Create: `backend/go-service/pkg/middleware/trace.go`
- Create: `backend/go-service/app/provider/provider.go`
- Create: `backend/go-service/app/provider/wire.go`

> **日志系统详细设计见** `docs/architecture/system-architecture.md` 第八节

**Step 1: 初始化 Go Module**

Run: `cd backend/go-service && go mod init github.com/echochat/backend`

**Step 2: 创建配置管理**

创建 `config/config.go` 使用 viper 读取 YAML 配置 + 环境变量覆盖。
创建 `config/config.dev.yaml` 包含开发环境默认配置（数据库连接、Redis 连接、JWT 密钥、服务端口、日志级别等）。

```go
// config/config.go
type Config struct {
    Server   ServerConfig   `mapstructure:"server"`
    Database DatabaseConfig `mapstructure:"database"`
    Redis    RedisConfig    `mapstructure:"redis"`
    JWT      JWTConfig      `mapstructure:"jwt"`
    Log      LogConfig      `mapstructure:"log"`
}

type LogConfig struct {
    Level      string        `mapstructure:"level"`       // debug/info/warn/error
    Format     string        `mapstructure:"format"`      // text(开发)/json(生产)
    OutputPath string        `mapstructure:"output_path"` // stdout 或文件路径
    File       LogFileConfig `mapstructure:"file"`        // 日志文件轮转配置
}

type LogFileConfig struct {
    Enable     bool   `mapstructure:"enable"`      // 是否启用文件日志
    Dir        string `mapstructure:"dir"`          // 日志文件目录
    MaxSize    int    `mapstructure:"max_size"`     // 单文件最大大小（MB）
    MaxBackups int    `mapstructure:"max_backups"`  // 保留旧日志文件数量
    MaxAge     int    `mapstructure:"max_age"`      // 旧日志保留天数
    Compress   bool   `mapstructure:"compress"`     // 是否压缩归档文件
}
```

**Step 3: 创建日志系统（核心）**

创建 `pkg/logs/logger.go`：
- 基于 zap 的结构化日志封装
- 支持从 context 中提取 trace_id 自动附加到每条日志
- 提供分级日志方法：`Debug(ctx, func, msg, fields...)` / `Info(...)` / `Warn(...)` / `Error(...)`
- 敏感信息脱敏工具函数（邮箱、手机号、Token）
- 控制台输出（始终启用）：开发环境彩色可读文本，生产环境 JSON 结构化
- 文件输出（可配置启用）：基于 lumberjack 自动轮转
  - `logs/app.log` — 全量日志（JSON 格式），便于接入 ELK/Loki
  - `logs/error.log` — 仅 WARN 及以上级别，便于快速定位问题
  - 支持按文件大小切割、保留数量、过期天数、压缩归档

创建 `pkg/logs/trace.go`：
- `GenerateTraceID()` — 生成唯一 trace ID（UUID v4 或雪花算法）
- `WithTraceID(ctx, traceID)` — 将 trace_id 注入 context
- `GetTraceID(ctx)` — 从 context 提取 trace_id

**日志输出格式示例（开发环境）：**
```
2026-02-27 10:30:00 INFO  [abc-123] auth | service.Login | 用户登录成功 | account=zhangsan | latency=25ms
```

**日志输出格式示例（生产环境 JSON）：**
```json
{"level":"info","ts":"2026-02-27 10:30:00","trace_id":"abc-123","module":"auth","func":"service.Login","msg":"用户登录成功","account":"zhangsan","latency_ms":25}
```

**Step 4: 创建数据库连接**

创建 `pkg/db/postgres.go` — GORM + PostgreSQL 连接池。GORM 日志适配 zap，SQL 查询日志携带 trace_id。
创建 `pkg/db/redis.go` — go-redis 客户端。Redis 操作日志携带 trace_id。

**Step 5: 创建统一响应工具**

创建 `pkg/utils/response.go` 包含 ResponseOK、ResponseBadRequest、ResponseUnauthorized、ResponseForbidden、ResponseError 等统一响应函数。响应中包含 trace_id 便于前端反馈问题时定位。

```go
type Response struct {
    Code      int         `json:"code"`
    Message   string      `json:"message"`
    Data    interface{} `json:"data,omitempty"`
    TraceID string      `json:"trace_id,omitempty"`
    Time    string      `json:"time"`
}
```

**Step 6: 创建中间件**

创建 `pkg/middleware/trace.go` — **链路追踪中间件**：
  - 从请求头提取 `X-Request-ID`，不存在则自动生成
  - 注入 context，后续所有日志自动携带 trace_id
  - 在响应头中返回 `X-Request-ID`

创建 `pkg/middleware/logger.go` — **请求日志中间件（Access Log 层）**：
  - 采用社区标准「分层不重复」策略，只记录 HTTP 请求级元信息
  - 记录字段：method / path / handler / status / latency / ip / user_agent / query
  - **不记录 Request Body**（由 Controller 层在 ShouldBindJSON 后以结构化参数形式记录，caller 可精确指向业务代码行号）
  - 错误响应(4xx/5xx)额外记录 Response Body（最大 2KB），便于排查接口返回内容
  - handler 字段通过 `c.HandlerName()` 获取，显示实际处理请求的函数名
  - 自动携带 trace_id，通过 trace_id 串联同一请求的各层日志
  - 状态码分级：5xx→ERROR / 4xx→WARN / 慢请求(>500ms)→WARN / 正常→INFO

创建 `pkg/middleware/cors.go` — CORS 跨域中间件。
创建 `pkg/middleware/recovery.go` — Panic 恢复中间件（捕获 panic 后记录 ERROR 日志含堆栈信息）。

**Step 7: 初始化 Wire 依赖注入**

创建 `app/provider/provider.go` — 定义基础设施层的 Provider Set：

```go
// provider.go — 基础设施 Provider Set
package provider

import "github.com/google/wire"

// InfraSet 提供所有基础设施组件
var InfraSet = wire.NewSet(
    db.NewPostgres,
    db.NewRedis,
    logs.NewLogger,
)
```

创建 `app/provider/wire.go` — Wire 注入入口：

```go
//go:build wireinject

package provider

// InitializeApp 初始化整个应用（Wire 自动生成实现）
func InitializeApp(cfg *config.Config) (*App, error) {
    wire.Build(
        InfraSet,
        // 后续每增加一个模块，在这里添加对应的 ProviderSet
    )
    return nil, nil
}
```

安装 Wire 工具：`go install github.com/google/wire/cmd/wire@latest`
生成注入代码：`cd app/provider && wire`

**Step 8: 创建 main.go 入口**

创建 `cmd/server/main.go`：
1. 加载配置
2. 初始化日志系统（根据配置设置级别和输出格式）
3. 通过 Wire 生成的 InitializeApp 初始化所有组件
4. 创建 Gin Engine
5. 注册中间件（顺序：Trace → Logger → CORS → Recovery）
6. 注册路由（暂时只有健康检查 GET /health）
7. 启动 HTTP 服务

**Step 9: 安装依赖**

Run: `cd backend/go-service && go mod tidy`

**Step 10: 运行验证**

Run: `cd backend/go-service && go run cmd/server/main.go`
Expected: 服务启动在 :8085，访问 /health 返回 200

**Step 11: Commit**

```bash
git add backend/go-service/
git commit -m "feat(backend): Go 服务骨架（配置、日志、数据库、中间件、路由）"
```

---

## Task 3: Auth 模块 — 用户模型与数据层

**Files:**
- Create: `backend/go-service/app/auth/model/user.go`
- Create: `backend/go-service/app/auth/model/role.go`
- Create: `backend/go-service/app/auth/dao/user_dao.go`
- Create: `backend/go-service/app/auth/dao/role_dao.go`
- Create: `backend/go-service/app/auth/provider.go`
- Create: `backend/go-service/app/constants/user_status.go`
- Create: `backend/go-service/app/constants/role_code.go`

**Step 1: 创建用户状态和角色常量**

```go
// app/constants/user_status.go — 驼峰命名，符合 Go 社区规范
const (
    UserStatusActive   = 1  // 正常
    UserStatusDisabled = 2  // 禁用
    UserStatusDeleted  = 3  // 注销
)

// app/constants/role_code.go
const (
    RoleUser       = "user"
    RoleAdmin      = "admin"
    RoleSuperAdmin = "super_admin"
)
```

**Step 2: 创建用户模型**

创建 `app/auth/model/user.go`，定义 User 结构体，JSON tag 使用下划线命名，GORM tag 指定表名 `auth_users`。

**Step 3: 创建角色模型**

创建 `app/auth/model/role.go`，定义 Role 和 UserRole 结构体。

**Step 4: 创建用户 DAO**

创建 `app/auth/dao/user_dao.go`，包含：
- `Create(ctx, user)` — 创建用户
- `FindByEmail(ctx, email)` — 按邮箱查询
- `FindByUsername(ctx, username)` — 按用户名查询
- `FindByID(ctx, id)` — 按 ID 查询
- `Update(ctx, user)` — 更新用户
- `UpdateLastLogin(ctx, userID, ip)` — 更新最后登录信息

包含标准的日志入口/出口记录。

**Step 5: 创建角色 DAO**

创建 `app/auth/dao/role_dao.go`，包含：
- `FindByCode(ctx, code)` — 按角色代码查询
- `AssignRole(ctx, userID, roleID)` — 分配角色
- `GetUserRoles(ctx, userID)` — 获取用户角色列表
- `HasRole(ctx, userID, roleCode)` — 检查用户是否拥有指定角色

**Step 6: 创建 Auth 模块 Wire Provider**

创建 `app/auth/provider.go`：

```go
// provider.go — Auth 模块依赖注入 Provider Set
package auth

import "github.com/google/wire"

// AuthSet 提供 Auth 模块的所有组件
var AuthSet = wire.NewSet(
    dao.NewUserDAO,
    dao.NewRoleDAO,
)
```

同步更新 `app/provider/wire.go`，在 `wire.Build` 中添加 `auth.AuthSet`。

**Step 7: Commit**

```bash
git add backend/go-service/app/
git commit -m "feat(auth): 用户/角色模型与数据访问层"
```

---

## Task 4: Auth 模块 — 认证服务层

**Files:**
- Create: `backend/go-service/app/auth/service/auth_service.go`
- Create: `backend/go-service/app/auth/service/token_store.go`
- Create: `backend/go-service/app/dto/auth_dto.go`
- Create: `backend/go-service/pkg/utils/jwt.go`
- Create: `backend/go-service/pkg/utils/password.go`
- Create: `backend/go-service/pkg/middleware/auth.go`

**Step 1: 创建密码工具**

创建 `pkg/utils/password.go`：
- `HashPassword(password)` — bcrypt 加密（`golang.org/x/crypto/bcrypt`，复用 go.mod 已有的兼容版本）
- `CheckPassword(password, hash)` — 密码校验

**Step 2: 创建 JWT 工具**

创建 `pkg/utils/jwt.go`（使用 `github.com/golang-jwt/jwt/v5@v5.2.1`，兼容 Go 1.23）：
- `GenerateToken(cfg, userID, username, roles)` — 生成 Access Token
- `GenerateRefreshToken(cfg, userID)` — 生成 Refresh Token
- `ParseToken(cfg, tokenStr)` — 解析验证 Token
- Claims 结构体包含 UserID, Username, Roles

> **依赖版本选择原则：** 优先选择兼容当前 Go 版本的包版本，不盲目拉取最新版，避免触发工具链升级。

**Step 3: 创建认证 DTO**

创建 `app/dto/auth_dto.go`：

```go
type UserInfo struct {
    ID        int64    `json:"id"`
    Username  string   `json:"username"`
    Email     string   `json:"email"`
    Nickname  string   `json:"nickname"`
    Avatar    string   `json:"avatar"`
    Gender    int      `json:"gender"`
    Phone     string   `json:"phone,omitempty"`
    Roles     []string `json:"roles"`
    CreatedAt string   `json:"created_at,omitempty"`
}
```

**Step 4: 创建 Token Redis 存储管理**

创建 `app/auth/service/token_store.go`：
- Redis Key 按 clientType 隔离：`echo:auth:token:{client_type}:{user_id}` / `echo:auth:refresh:{client_type}:{user_id}`
- `SaveTokens(ctx, userID, clientType, accessToken, refreshToken)` — 存入 Redis（按 clientType 隔离）
- `ValidateAccessToken(ctx, userID, clientType, token)` — 校验 Access Token 与 Redis 一致
- `ValidateRefreshToken(ctx, userID, clientType, token)` — 校验 Refresh Token 与 Redis 一致
- `RemoveTokens(ctx, userID, clientType)` — 登出时删除指定 clientType 的 Token

**Step 5: 创建认证服务**

创建 `app/auth/service/auth_service.go`：
- `Register(ctx, req)` — 注册逻辑（检查重复、加密密码、创建用户、分配默认角色、生成 Token + 存 Redis）
- `Login(ctx, req, clientIP)` — 登录逻辑（查找用户、校验密码、检查状态、更新登录信息、生成 Token + 存 Redis）
- `AdminLogin(ctx, req, clientIP)` — 管理员登录（额外检查 admin/super_admin 角色）
- `RefreshToken(ctx, refreshToken)` — 刷新 Token（校验 Redis + 生成新 Token + 覆盖 Redis）
- `Logout(ctx, userID)` — 登出（从 Redis 删除 Token）
- `ValidateAccessToken(ctx, userID, token)` — 供中间件调用，校验 Redis
- `GetProfile(ctx, userID)` — 获取用户信息
- `UpdateProfile(ctx, userID, req)` — 更新用户信息
- `ChangePassword(ctx, userID, req)` — 修改密码

**Step 6: 创建认证中间件**

创建 `pkg/middleware/auth.go`：
- `TokenValidator` 接口 — 定义 Token 校验契约，由 AuthService 实现（解耦 pkg 与 app 层依赖）
- `JWTAuth(cfg, validator)` — 有状态 JWT 验证中间件（解析 Token + 校验 Redis 有效性）
- `RequireRole(roles ...string)` — 角色检查中间件
- 将 UserID、Username 和 Roles 注入 Gin Context

**Step 7: 更新 Wire Provider**

更新 `app/auth/provider.go`：

```go
var AuthSet = wire.NewSet(
    dao.NewUserDAO,
    dao.NewRoleDAO,
    service.NewTokenStore,
    service.NewAuthService,
    controller.NewAuthController,
    controller.NewAdminAuthController,
)
```

**Step 8: Commit**

```bash
git add backend/go-service/
git commit -m "feat(auth): 认证服务层（注册、登录、有状态JWT、密码加密、中间件）"
```

---

## Task 5: Auth 模块 — Controller 与路由注册

**Files:**
- Create: `backend/go-service/app/auth/controller/auth_controller.go`
- Create: `backend/go-service/app/auth/controller/admin_auth_controller.go`
- Create: `backend/go-service/app/auth/router.go` — auth 模块路由定义（模块自包含）
- Create: `backend/go-service/router/router.go` — 主路由汇总入口
- Modify: `backend/go-service/cmd/server/main.go` — 调用 router.Setup() 注册路由
- Modify: `backend/go-service/app/auth/provider.go` — 添加 Controller Provider

> **路由架构：** 采用"模块自包含 + 主路由汇总"模式。每个模块在自己目录内的 `router.go` 定义具体路由，`router/router.go` 主路由文件仅做汇总注册，不含具体路由定义。利于后期微服务拆分——整个模块目录搬走即可。

**Step 1: 创建前台认证 Controller**

创建 `app/auth/controller/auth_controller.go`：
- `Register(c *gin.Context)` — POST /api/v1/auth/register
- `Login(c *gin.Context)` — POST /api/v1/auth/login
- `Logout(c *gin.Context)` — POST /api/v1/auth/logout
- `RefreshToken(c *gin.Context)` — POST /api/v1/auth/refresh-token
- `GetProfile(c *gin.Context)` — GET /api/v1/auth/profile
- `UpdateProfile(c *gin.Context)` — PUT /api/v1/auth/profile
- `ChangePassword(c *gin.Context)` — PUT /api/v1/auth/password

每个方法：参数绑定 → 调用 Service → 统一响应返回。

**Step 2: 创建后台认证 Controller**

创建 `app/auth/controller/admin_auth_controller.go`：
- `AdminLogin(c *gin.Context)` — POST /api/v1/admin/auth/login
  - 与普通登录的区别：登录后检查用户是否拥有 admin 或 super_admin 角色

**Step 3: 创建路由注册函数**

创建 `app/auth/router.go`：

```go
func RegisterRoutes(r *gin.Engine, ctrl *AuthController, adminCtrl *AdminAuthController, authMiddleware gin.HandlerFunc) {
    // 前台公开路由
    public := r.Group("/api/v1/auth")
    {
        public.POST("/register", ctrl.Register)
        public.POST("/login", ctrl.Login)
        public.POST("/refresh-token", ctrl.RefreshToken)
    }

    // 前台需认证路由
    authed := r.Group("/api/v1/auth").Use(authMiddleware)
    {
        authed.POST("/logout", ctrl.Logout)
        authed.GET("/profile", ctrl.GetProfile)
        authed.PUT("/profile", ctrl.UpdateProfile)
        authed.PUT("/password", ctrl.ChangePassword)
    }

    // 后台认证路由
    admin := r.Group("/api/v1/admin/auth")
    {
        admin.POST("/login", adminCtrl.AdminLogin)
    }
}
```

**Step 4: 创建主路由汇总文件**

创建 `router/router.go`：
- `Setup(engine, app)` 函数，负责注册健康检查和调用各模块的 RegisterRoutes
- 不含任何具体路由定义，仅做汇总调度

**Step 5: 在 main.go 中调用 router.Setup()**

修改 `cmd/server/main.go`，将路由注册逻辑移到 `router.Setup()` 调用，main.go 不再直接定义路由。

**Step 5: 运行验证**

Run: `cd backend/go-service && go run cmd/server/main.go`
Expected: 服务启动在 :8085，可以通过 curl 测试注册和登录接口

```bash
# 测试注册
curl -X POST http://localhost:8085/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{"username":"testuser","email":"test@example.com","password":"123456","nickname":"测试用户"}'

# 测试登录
curl -X POST http://localhost:8085/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"account":"testuser","password":"123456"}'

# 测试登出后 Token 立即失效
TOKEN=$(curl -s ... | jq -r '.data.token')
curl -X POST http://localhost:8085/api/v1/auth/logout -H "Authorization: Bearer $TOKEN"
curl http://localhost:8085/api/v1/auth/profile -H "Authorization: Bearer $TOKEN"
# 预期返回 401 "认证已失效，请重新登录"
```

Expected: 注册返回 Token（同时存入 Redis），登录返回 Token + 用户信息，登出后 Token 立即失效

**Step 6: Commit**

```bash
git add backend/go-service/
git commit -m "feat(auth): 用户注册/登录 API（Controller + 路由注册）"
```

---

## Task 6: uniapp 前端骨架完善

**Files:**
- Create: `frontend/src/utils/request.js`
- Create: `frontend/src/utils/storage.js`
- Create: `frontend/src/api/auth.js`
- Create: `frontend/src/store/user.js`
- Create: `frontend/src/services/websocket.js`（占位）
- Modify: `frontend/src/pages.json`
- Modify: `frontend/src/main.js`
- Modify: `frontend/package.json`

**Step 1: 安装前端依赖**

> **版本策略：** uni-app 锁定 Vue 3.4.21，Pinia 3.x 需要 Vue >= 3.5.11，因此前台用户端必须使用 Pinia 2.x。后台管理端（Task 9）为独立 Vue 3 项目，不受此限制，可使用 Pinia 3.x。
> 
> **npm 兼容性：** uni-app 的 peer dependency 链与 npm 7+ 的严格解析存在冲突，需在 `frontend/.npmrc` 中设置 `legacy-peer-deps=true`。

```bash
# 创建 .npmrc 固化 npm 解析策略
echo "legacy-peer-deps=true" > frontend/.npmrc

# 安装 Pinia 及持久化插件
cd frontend && npm install pinia@2.1.7 pinia-plugin-persistedstate@3
```

uniapp 内置了请求 API（uni.request），不需要额外安装 axios。

**Step 2: 创建 HTTP 请求封装**

创建 `src/utils/request.js`：
- 封装 uni.request 为 Promise
- 请求拦截器：自动添加 Authorization Header
- 响应拦截器：统一处理错误码（401 跳转登录等）
- 基础 URL 配置

**Step 3: 创建存储工具**

创建 `src/utils/storage.js`：
- 封装 uni.setStorageSync / uni.getStorageSync
- Token 存取方法

**Step 4: 创建 Pinia Store**

修改 `src/main.js` 集成 Pinia。
创建 `src/store/user.js`：
- state: userInfo, token, isLoggedIn
- actions: login, register, logout, getProfile, setToken

**Step 5: 创建 Auth API**

创建 `src/api/auth.js`：
- register(data)
- login(data)
- logout()
- getProfile()
- updateProfile(data)
- changePassword(data)

**Step 6: 更新 pages.json**

添加 auth 页面路由、TabBar 配置。

**Step 7: Commit**

```bash
git add frontend/
git commit -m "feat(frontend): uniapp 前端骨架（请求封装、状态管理、Auth API）"
```

---

## Task 7: uniapp 登录/注册页面

**Files:**
- Create: `frontend/src/pages/auth/login.vue`
- Create: `frontend/src/pages/auth/register.vue`
- Modify: `frontend/src/pages.json`

> **Note:** 页面构建使用 ui-ux-pro-max skill 生成设计系统后实现。uniapp 使用 `<view>` `<text>` `<input>` 等组件而非 HTML 标签。

**Step 1: 使用 ui-ux-pro-max 生成设计系统**

```bash
python3 skills/ui-ux-pro-max/scripts/search.py "video conference meeting chat modern professional" --design-system -p "EchoChat" --persist
```

然后获取 Vue stack 的实现指南：
```bash
python3 skills/ui-ux-pro-max/scripts/search.py "login register form" --stack vue
```

**Step 2: 创建登录页面**

创建 `src/pages/auth/login.vue`：
- 输入框：账号（邮箱或用户名）+ 密码
- 登录按钮
- "没有账号？去注册" 链接
- 表单验证
- 调用 userStore.login()
- 登录成功跳转首页

**Step 3: 创建注册页面**

创建 `src/pages/auth/register.vue`：
- 输入框：用户名 + 邮箱 + 密码 + 确认密码 + 昵称（选填）
- 注册按钮
- "已有账号？去登录" 链接
- 表单验证
- 调用 userStore.register()
- 注册成功自动登录

**Step 4: 更新 pages.json 路由配置**

**Step 5: 运行验证**

Run: `cd frontend && npm run dev:h5`
Expected: H5 浏览器中可以看到登录/注册页面，输入信息后可以成功注册和登录

**Step 6: Commit**

```bash
git add frontend/
git commit -m "feat(frontend): 登录/注册页面"
```

---

## Task 8: uniapp 首页框架与 TabBar

**Files:**
- Create: `frontend/src/pages/chat/index.vue`（占位）
- Create: `frontend/src/pages/contact/index.vue`（占位）
- Create: `frontend/src/pages/meeting/index.vue`（占位）
- Create: `frontend/src/pages/profile/index.vue`
- Modify: `frontend/src/pages/index/index.vue`
- Modify: `frontend/src/pages.json`

**Step 1: 创建 TabBar 页面占位**

创建消息、联系人、会议三个 Tab 页面的占位版本（显示模块名称和"开发中"提示）。

**Step 2: 创建个人中心页面**

创建 `src/pages/profile/index.vue`：
- 显示用户头像、昵称、用户名
- 编辑资料入口
- 修改密码入口
- 退出登录按钮
- 使用 ui-ux-pro-max 设计系统

**Step 3: 配置 TabBar**

修改 `pages.json`，配置底部 TabBar：消息 | 联系人 | 会议 | 我的

**Step 4: 配置首页重定向**

修改 `src/pages/index/index.vue`，判断登录状态：
- 已登录 → 跳转消息列表页
- 未登录 → 跳转登录页

**Step 5: 运行验证**

Run: `cd frontend && npm run dev:h5`
Expected: 未登录时显示登录页，登录后显示 TabBar 页面，个人中心可以查看信息并退出

**Step 6: Commit**

```bash
git add frontend/
git commit -m "feat(frontend): TabBar 框架与个人中心页面"
```

---

## Task 9: Vue 3 管理端项目搭建

**Files:**
- Create: `admin/` 整个目录（通过 Vite 脚手架创建）
- 项目结构参考设计文档第三节

**Step 1: 创建 Vue 3 项目**

Run: `cd /path/to/EchoChat && npm create vite@latest admin -- --template vue`

**Step 2: 安装核心依赖**

> **版本策略：** 管理端为独立 Vue 3 项目（非 uni-app），可使用最新的 Vue 3.5+ 和 Pinia 3.x，不受 uni-app 版本限制。

Run: `cd admin && npm install element-plus vue-router@4 pinia axios @element-plus/icons-vue`

**Step 3: 创建布局框架**

创建 `src/views/layout/index.vue`：
- 左侧边栏导航
- 顶部栏（管理员信息、退出登录）
- 主内容区
- 使用 Element Plus 的 Container/Aside/Header/Main 布局

**Step 4: 创建路由配置**

创建 `src/router/index.js`：
- 登录页路由
- 后台布局路由（嵌套子路由）
- 路由守卫（未登录跳转登录页）

**Step 5: 创建请求封装**

创建 `src/api/request.js`：
- 基于 axios 的请求封装
- 请求/响应拦截器
- Token 自动附加

**Step 6: 创建管理员登录页**

创建 `src/views/login.vue`：
- 管理员账号 + 密码登录表单
- 使用 Element Plus 表单组件
- 使用 ui-ux-pro-max 设计系统

**Step 7: 创建仪表盘占位页**

创建 `src/views/dashboard/index.vue`：
- 显示统计卡片占位（总用户数、在线用户、今日会议等）

**Step 8: 运行验证**

Run: `cd admin && npm run dev`
Expected: 浏览器访问管理端，未登录跳转登录页，登录后进入仪表盘

**Step 9: Commit**

```bash
git add admin/
git commit -m "feat(admin): Vue 3 管理端项目搭建（布局、路由、登录页）"
```

---

## Task 10: 管理端用户管理模块

**Files:**
- Create: `backend/go-service/app/admin/controller/user_manage_controller.go`
- Create: `backend/go-service/app/admin/service/user_manage_service.go`
- Create: `backend/go-service/app/admin/dao/user_manage_dao.go`
- Create: `backend/go-service/app/admin/router.go`
- Create: `backend/go-service/app/dto/admin_dto.go`
- Create: `admin/src/api/user.js`
- Create: `admin/src/views/user/list.vue`
- Create: `admin/src/views/user/detail.vue`
- Modify: `backend/go-service/cmd/server/main.go`

**Step 1: 创建管理端 DTO**

创建 `app/dto/admin_dto.go`：
- UserListRequest（分页、搜索、状态筛选）
- UserListResponse（用户列表 + 总数）
- UserDetailResponse

**Step 2: 创建管理端用户 DAO**

创建 `app/admin/dao/user_manage_dao.go`：
- `ListUsers(ctx, req)` — 分页查询用户列表（支持搜索、状态筛选）
- `CountUsers(ctx)` — 统计用户总数
- `UpdateUserStatus(ctx, userID, status)` — 更新用户状态

**Step 3: 创建管理端用户 Service**

创建 `app/admin/service/user_manage_service.go`：
- `GetUserList(ctx, req)` — 获取用户列表
- `GetUserDetail(ctx, userID)` — 获取用户详情（含角色信息）
- `UpdateUserStatus(ctx, userID, status)` — 启用/禁用用户
- `AssignUserRole(ctx, userID, roleCode)` — 分配角色
- `CreateUser(ctx, req)` — 管理员手动创建用户

**Step 4: 创建管理端 Controller 和路由**

创建 Controller 和路由注册函数，所有管理端 API 需要 JWT + admin 角色双重中间件。

**Step 5: 创建管理端用户列表页面**

创建 `admin/src/views/user/list.vue`：
- 搜索框（用户名/邮箱搜索）
- 状态筛选下拉
- 用户数据表格（Element Plus Table）
- 分页组件
- 操作按钮（查看详情、启用/禁用）

**Step 6: 创建管理端用户详情页面**

创建 `admin/src/views/user/detail.vue`：
- 基本信息 Tab
- 角色管理
- 会议记录 Tab（占位，后续完善）

**Step 7: 运行验证**

Expected: 管理端可以查看用户列表、搜索筛选、查看详情、启用/禁用用户

**Step 8: Commit**

```bash
git add backend/go-service/app/admin/ admin/src/
git commit -m "feat(admin): 用户管理模块（列表、详情、状态管理、角色分配）"
```

---

## Task 11: 端到端集成测试与文档

**Files:**
- Create: `backend/go-service/Dockerfile`
- Modify: `deploy/docker-compose.dev.yml` — 添加 go-service
- Create: `README.md` — 项目说明文档

**Step 1: 创建 Go 服务 Dockerfile**

创建 `backend/go-service/Dockerfile`，多阶段构建：
- 第一阶段：Go 编译
- 第二阶段：alpine 运行镜像

**Step 2: 更新 Docker Compose**

在 `deploy/docker-compose.dev.yml` 中添加 go-service 服务。

**Step 3: 编写项目 README**

更新根目录 `README.md`：
- 项目简介
- 技术栈
- 项目结构
- 开发环境搭建步骤
- API 文档链接

**Step 4: 完整流程验证**

1. Docker Compose 启动所有服务
2. 访问前台 H5 → 注册 → 登录 → 查看个人中心 → 退出
3. 访问管理端 → 管理员登录 → 查看用户列表 → 查看用户详情

**Step 5: Commit**

```bash
git add .
git commit -m "feat: 第一阶段完成（基础设施 + 用户体系 + 管理端用户管理）"
```

---

## 阶段完成标准

- [x] Docker Compose 开发环境可一键启动（PostgreSQL + Redis）
- [x] Go 后端服务骨架完整（配置、日志、数据库、中间件）
- [x] 用户注册/登录 API 正常工作（邮箱+密码、用户名+密码）
- [x] JWT Token 认证机制正常（Access Token + Refresh Token）
- [x] RBAC 角色权限体系正常（user / admin / super_admin）
- [x] uniapp 前端骨架完整（请求封装、状态管理、路由）
- [x] 前台登录/注册页面可用
- [x] 前台 TabBar 框架和个人中心可用
- [x] Vue 3 管理端项目搭建完成（布局、路由、登录）
- [x] 管理端用户管理模块可用（列表、详情、状态管理）
- [x] 所有代码已提交 Git
