diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..43de1ba --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule ".claude/skills/zero-skills"] + path = .claude/skills/zero-skills + url = https://github.com/zeromicro/zero-skills.git diff --git a/docs/plans/2026-02-14-hot-reload-login-redesign.md b/docs/plans/2026-02-14-hot-reload-login-redesign.md new file mode 100644 index 0000000..68d7b37 --- /dev/null +++ b/docs/plans/2026-02-14-hot-reload-login-redesign.md @@ -0,0 +1,125 @@ +# 后端热重载 + 登录方式改造 设计文档 + +**日期**: 2026-02-14 +**状态**: 已批准 + +## 概述 + +两项改造: +1. 后端引入 Air 热重载,保存文件自动重启 +2. 登录从邮箱改为手机号/用户名,注册移除邮箱必填,JWT Claims 移除 email + +--- + +## 设计一:Air 热重载 + +### 方案 + +使用 [Air](https://github.com/air-verse/air) 监听 `.go` 和 `.yaml` 文件变化,自动编译重启。 + +### 新增文件 + +`backend/.air.toml`: +- 监听 `.go`, `.yaml` 文件 +- 排除 `tmp/`, `vendor/`, `tests/` +- 编译到 `tmp/base.exe` +- 延迟 1000ms 防抖 + +### 启动方式 + +```bash +# 安装(一次性) +go install github.com/air-verse/air@latest + +# 开发启动 +cd backend && air +``` + +### 影响范围 + +- 新增 `backend/.air.toml` +- `backend/.gitignore` 加 `tmp/` +- 零侵入现有代码 + +--- + +## 设计二:登录方式改造 + +### API 变更 + +**LoginRequest**: +``` +Account string `json:"account" validate:"required"` // 手机号或用户名 +Password string `json:"password" validate:"required,min=6,max=32"` +``` + +**RegisterRequest**: +``` +Username string `json:"username" validate:"required,min=3,max=32"` +Password string `json:"password" validate:"required,min=6,max=32"` +Phone string `json:"phone" validate:"required"` // 必填 +Email string `json:"email,optional"` // 可选 +``` + +### 后端 Login 逻辑 + +单一输入框,后端正则自动识别: +- `^\d{11}$` → 手机号 → `FindOneByPhone` +- 否则 → 用户名 → `FindOneByUsername` + +### Model 层 + +新增: +- `FindOneByPhone(ctx, db, phone) (*User, error)` +- `FindOneByUsername(ctx, db, username) (*User, error)` + +### JWT Claims 变更 + +移除 `Email` 字段: +```go +type Claims struct { + UserID int64 `json:"userId"` + Username string `json:"username"` + Role string `json:"role"` + jwt.RegisteredClaims +} + +func GenerateToken(userId int64, username, role string) (string, error) +``` + +影响调用点:loginlogic, registerlogic, refreshtokenlogic, ssologic, authmiddleware + +### Register 逻辑 + +- 检查 username 唯一性(FindOneByUsername) +- 检查 phone 唯一性(FindOneByPhone) +- email 可选,不做唯一性检查 + +### 种子超级管理员 + +```go +admin := &model.User{ + Username: "admin", + Phone: "13800000000", + Email: "", + Password: md5("admin123"), + Role: "super_admin", + Source: "system", +} +// 查找改为 FindOneByUsername(ctx, db, "admin") +``` + +### 前端变更 + +| 文件 | 变更 | +|------|------| +| `types/index.ts` | `LoginRequest.email` → `.account`; `RegisterRequest.email` 可选, `.phone` 必填 | +| `services/api.ts` | `login()` 传 `account` | +| `contexts/AuthContext.tsx` | `login(email, password)` → `login(account, password)`; JWT 解析移除 email | +| `pages/LoginPage.tsx` | 输入框: Mail 图标 → User 图标, placeholder "手机号 / 用户名", `type="text"` | + +### 不变的部分 + +- SSO 登录流程(Casdoor 自有账号体系) +- 用户管理 CRUD、Profile 接口 +- `user_entity.go` 的 email 字段保留,仅改为非必填