# 用户表 Schema (users)

---
DDS-Section: 9. 数据模型 - 9.2 用户表 DDL
DDS-Lines: L695-L764
---

## 表定义

```go
type User struct {
    ID                  int64      `gorm:"primaryKey;autoIncrement" json:"id"`
    Username            string     `gorm:"uniqueIndex;not null;size:50" json:"username"`      // 中文真实姓名
    EnglishUsername     string     `gorm:"size:100" json:"english_username"`                  // 英文用户名(昵称)
    PasswordHash        string     `gorm:"not null;size:255" json:"-"`                        // 加密后的密码
    AvatarID            string     `gorm:"size:50;default:'default_1'" json:"avatar_id"`      // 头像ID
    AvatarFrameID       string     `gorm:"size:50;default:'default'" json:"avatar_frame_id"`  // 头像框ID
    Gender              string     `gorm:"size:10;default:'male'" json:"gender"`              // 性别
    Email               string     `gorm:"uniqueIndex;size:100" json:"email"`                 // 邮箱
    Phone               string     `gorm:"size:20" json:"phone"`                              // 手机号
    ShortNumber         string     `gorm:"size:10" json:"short_number"`                       // 短号
    WorkID              string     `gorm:"size:50" json:"work_id"`                            // 工号
    GroupName           string     `gorm:"size:100" json:"group_name"`                        // 所属小组
    Company             string     `gorm:"size:100" json:"company"`                           // 公司名称
    DevRole             string     `gorm:"size:50;default:'unknown'" json:"dev_role"`         // 开发角色
    
    // 注册关系
    RegisteredByID      int64      `json:"registered_by_id"`                                  // 注册人ID
    RegisteredByName    string     `gorm:"size:64" json:"registered_by_name"`                 // 注册人姓名
    
    // 角色与状态
    Role                string     `gorm:"not null;size:20;default:'normal'" json:"role"`     // 系统角色
    Status              string     `gorm:"not null;size:20;default:'disabled'" json:"status"` // 状态
    
    // 密码策略
    PasswordExpiresAt   *time.Time `json:"password_expires_at"`                               // 密码过期时间
    MustChangePassword  bool       `gorm:"default:true" json:"must_change_password"`          // 是否需强制改密
    
    // 账户有效期
    AccountExpiresAt    *time.Time `json:"account_expires_at"`                                // 账户有效期
    
    // 登录锁定
    FailedLoginAttempts int        `gorm:"default:0" json:"failed_login_attempts"`
    LockedUntil         *time.Time `json:"locked_until"`
    
    // MFA
    MFASecret           string     `gorm:"size:100" json:"-"`
    
    // 审计字段
    CreatedAt           time.Time  `gorm:"autoCreateTime" json:"created_at"`
    UpdatedAt           time.Time  `gorm:"autoUpdateTime" json:"updated_at"`
    DeletedAt           *time.Time `gorm:"index" json:"deleted_at,omitempty"`
    LastLoginAt         *time.Time `json:"last_login_at"`
}
```

## 字段说明

| 字段 | 类型 | 约束 | 默认值 | 说明 |
|:---|:---|:---|:---|:---|
| `id` | int64 | PK, AUTO | - | 主键 |
| `username` | varchar(50) | UNIQUE, NOT NULL | - | 中文真实姓名 |
| `english_username` | varchar(100) | - | - | 英文昵称 |
| `password_hash` | varchar(255) | NOT NULL | - | bcrypt 哈希 |
| `email` | varchar(100) | UNIQUE | - | 邮箱 |
| `role` | varchar(20) | NOT NULL | 'normal' | superadmin/admin/normal/third |
| `status` | varchar(20) | NOT NULL | 'disabled' | active/locked/disabled |
| `registered_by_id` | int64 | - | - | 注册人 ID |
| `registered_by_name` | varchar(64) | - | - | 注册人姓名（冗余） |
| `password_expires_at` | datetime | - | - | 密码过期时间 |
| `must_change_password` | bool | - | true | 首次登录强制改密标识 |
| `account_expires_at` | datetime | - | NULL | 账户有效期，NULL=永久 |
| `failed_login_attempts` | int | - | 0 | 登录失败次数 |
| `locked_until` | datetime | - | - | 锁定截止时间 |

## 索引设计

| 索引 | 类型 | 字段 |
|:---|:---|:---|
| PRIMARY | PK | id |
| idx_users_username | UNIQUE | username |
| idx_users_email | UNIQUE | email |
| idx_users_deleted_at | INDEX | deleted_at |

## v2.0 新增字段

| 字段 | 类型 | 说明 | 默认值 |
|:---|:---|:---|:---|
| `registered_by_name` | varchar(64) | 注册人姓名（冗余存储） | NULL |
| `must_change_password` | bool | 是否需要强制改密 | true |
| `account_expires_at` | datetime | 账户有效期 | NULL |
