# 用户基本信息

<cite>
**本文引用的文件**
- [schema.prisma](file://server/prisma/schema.prisma)
- [auth.controller.ts](file://server/src/modules/auth/auth.controller.ts)
- [auth.service.ts](file://server/src/modules/auth/auth.service.ts)
- [user.ts](file://my-uniapp-vue3/src/store/user.ts)
- [index.ts](file://server/src/models/index.ts)
</cite>

## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)

## 简介
本文件面向AI有声书生成平台的“用户基本信息”模型，围绕User模型进行系统化说明，重点覆盖以下方面：
- 字段定义与数据类型、约束条件及业务含义
- 字段允许空值的原因与默认值设计考量
- 常见业务流程的实现路径，如手机号登录/注册、用户信息查询与更新、昵称与头像变更等
- 与前端状态管理与后端服务层的交互方式

## 项目结构
与用户基本信息模型直接相关的代码分布在如下位置：
- 数据库模型定义：Prisma Schema（包含User模型及其索引）
- 后端控制器与服务：认证模块的路由与业务逻辑
- 前端状态管理：Pinia Store对用户信息的读取与持久化
- 数据访问层：Prisma 客户端连接与查询

```mermaid
graph TB
subgraph "前端"
FE_Store["用户状态存储<br/>user.ts"]
end
subgraph "后端"
BE_Router["认证路由<br/>auth.controller.ts"]
BE_Service["认证服务<br/>auth.service.ts"]
BE_Models["数据访问层<br/>models/index.ts"]
end
subgraph "数据库"
DB_Schema["Prisma Schema<br/>schema.prisma"]
end
FE_Store --> BE_Router
BE_Router --> BE_Service
BE_Service --> BE_Models
BE_Models --> DB_Schema
```

图表来源
- [auth.controller.ts:1-94](file://server/src/modules/auth/auth.controller.ts#L1-L94)
- [auth.service.ts:1-115](file://server/src/modules/auth/auth.service.ts#L1-L115)
- [index.ts:1-15](file://server/src/models/index.ts#L1-L15)
- [schema.prisma:10-38](file://server/prisma/schema.prisma#L10-L38)

章节来源
- [auth.controller.ts:1-94](file://server/src/modules/auth/auth.controller.ts#L1-L94)
- [auth.service.ts:1-115](file://server/src/modules/auth/auth.service.ts#L1-L115)
- [index.ts:1-15](file://server/src/models/index.ts#L1-L15)
- [schema.prisma:10-38](file://server/prisma/schema.prisma#L10-L38)

## 核心组件
本节聚焦User模型的核心字段，逐项说明其数据类型、约束、默认值与业务含义，并解释为何某些字段允许为空。

- id 主键自增
  - 类型：整数
  - 约束：主键、自动递增
  - 业务含义：用户唯一标识，用于关联其他表（如订单、收藏、播放记录等）
  - 设计考量：保证全局唯一且无需外部生成

- phone 手机号（唯一索引）
  - 类型：字符串
  - 约束：唯一、可空
  - 业务含义：手机号登录/注册入口；可为空表示未绑定手机号
  - 设计考量：允许空值以支持非手机号登录渠道；唯一性确保登录入口一致性

- openid 第三方登录标识（唯一索引）
  - 类型：字符串
  - 约束：唯一、可空
  - 业务含义：微信等第三方登录的用户标识；可为空表示未绑定第三方
  - 设计考量：允许空值以支持多渠道登录；唯一性避免重复绑定

- nickname 昵称（默认值）
  - 类型：字符串
  - 约束：非空
  - 默认值："用户"
  - 业务含义：展示用名称；为空白时提供友好默认名
  - 设计考量：提升首次体验与兼容性

- avatar 头像URL（默认值）
  - 类型：字符串
  - 约束：非空
  - 默认值：空字符串
  - 业务含义：用户头像地址；为空时表示未设置头像
  - 设计考量：兼容未设置头像的场景

- memberLevel 会员等级（默认值）
  - 类型：整数
  - 约束：非空
  - 默认值：0（普通用户）
  - 业务含义：区分用户权益与功能限制
  - 设计考量：从0级起步，便于后续扩展

- memberExpireAt 会员到期时间（可空）
  - 类型：日期时间
  - 约束：可空
  - 业务含义：会员状态的有效截止时间
  - 设计考量：允许空值表示非会员或永久会员

- dailyUsage 每日用量（默认值）
  - 类型：整数
  - 约束：非空
  - 默认值：0
  - 业务含义：当日使用量统计，配合签到奖励与限额控制
  - 设计考量：从0开始，便于累计与重置

- lastUsageDate 最后使用日期（默认值）
  - 类型：字符串
  - 约束：非空
  - 默认值：空字符串
  - 业务含义：记录最近一次使用日期，用于连续签到与重置逻辑
  - 设计考量：字符串格式便于快速比较与存储

- usedAudioMinutes 已用音频时长（默认值）
  - 类型：整数
  - 约束：非空
  - 默认值：0
  - 业务含义：累计使用的音频生成时长（分钟），用于配额控制
  - 设计考量：与订阅/套餐结合，限制生成时长

- subscriptionResetDate 订阅重置日期（可空）
  - 类型：日期时间
  - 约束：可空
  - 业务含义：订阅周期重置的时间点
  - 设计考量：允许空值表示未订阅或未启用重置

- createdAt/updatedAt 时间戳（默认值）
  - 类型：日期时间
  - 约束：非空
  - 默认值：创建时自动写入当前时间；更新时自动刷新
  - 业务含义：审计与排序依据

索引与外键
- 对phone与openid分别建立唯一索引，确保登录入口与第三方绑定的唯一性
- User模型与其他业务实体存在一对多/一对一关系（如评论、收藏、播放记录、偏好等）

章节来源
- [schema.prisma:10-38](file://server/prisma/schema.prisma#L10-L38)

## 架构总览
用户基本信息在系统中的流转路径如下：
- 前端通过认证接口发起登录请求
- 后端服务根据手机号与验证码进行校验并创建/查询用户
- 返回JWT令牌与用户信息
- 前端Store保存令牌与用户信息，后续请求携带令牌访问受保护资源

```mermaid
sequenceDiagram
participant Client as "客户端"
participant Router as "认证路由<br/>auth.controller.ts"
participant Service as "认证服务<br/>auth.service.ts"
participant DB as "数据库<br/>schema.prisma"
Client->>Router : "POST /auth/login"
Router->>Service : "loginWithPhone(phone, code)"
Service->>DB : "查询手机号是否存在"
DB-->>Service : "返回用户或空"
Service->>DB : "不存在则创建用户含默认昵称/头像等"
Service-->>Router : "返回token与用户信息"
Router-->>Client : "登录成功响应"
```

图表来源
- [auth.controller.ts:32-52](file://server/src/modules/auth/auth.controller.ts#L32-L52)
- [auth.service.ts:43-97](file://server/src/modules/auth/auth.service.ts#L43-L97)
- [schema.prisma:10-38](file://server/prisma/schema.prisma#L10-L38)

## 详细组件分析

### 字段定义与约束详解
- 主键与自增
  - id为整型主键并自动递增，保证全局唯一性与高并发下的稳定性
- 唯一索引字段
  - phone与openid均为唯一索引，防止重复登录入口与重复绑定
- 可空字段
  - phone与openid允许空值，体现多渠道登录策略
  - memberExpireAt与subscriptionResetDate允许空值，表示非会员或未启用重置
- 默认值设计
  - nickname默认"用户"，avatar默认空字符串，memberLevel默认0，dailyUsage与lastUsageDate默认0/空字符串，usedAudioMinutes默认0
  - 设计目标：在无显式设置时提供合理初始值，降低前端与业务层的空值判断复杂度

章节来源
- [schema.prisma:10-38](file://server/prisma/schema.prisma#L10-L38)

### 登录与注册流程（手机号）
- 前端调用发送验证码接口，随后调用登录接口
- 后端服务在开发模式下可跳过验证码校验（code为空或特定值时）
- 若用户不存在，则创建新用户并填充默认昵称与头像
- 生成JWT令牌返回给前端

```mermaid
sequenceDiagram
participant FE as "前端<br/>user.ts"
participant API as "后端路由<br/>auth.controller.ts"
participant SVC as "后端服务<br/>auth.service.ts"
participant PRISMA as "Prisma<br/>schema.prisma"
FE->>API : "POST /auth/send-code"
FE->>API : "POST /auth/login"
API->>SVC : "loginWithPhone(phone, code)"
SVC->>PRISMA : "findUnique(phone)"
alt "用户不存在"
SVC->>PRISMA : "create(user with defaults)"
end
SVC-->>API : "token + user"
API-->>FE : "登录成功"
```

图表来源
- [auth.controller.ts:10-52](file://server/src/modules/auth/auth.controller.ts#L10-L52)
- [auth.service.ts:43-97](file://server/src/modules/auth/auth.service.ts#L43-L97)
- [user.ts:32-46](file://my-uniapp-vue3/src/store/user.ts#L32-L46)

章节来源
- [auth.controller.ts:10-52](file://server/src/modules/auth/auth.controller.ts#L10-L52)
- [auth.service.ts:43-97](file://server/src/modules/auth/auth.service.ts#L43-L97)
- [user.ts:32-46](file://my-uniapp-vue3/src/store/user.ts#L32-L46)

### 用户信息查询与更新
- 查询用户信息
  - 后端通过鉴权中间件获取当前用户ID，查询User表并返回必要字段
- 更新用户信息
  - 支持更新昵称与头像；后端仅对传入的字段进行更新，避免覆盖其他字段

```mermaid
sequenceDiagram
participant FE as "前端<br/>user.ts"
participant API as "后端路由<br/>auth.controller.ts"
participant SVC as "后端服务<br/>auth.service.ts"
participant PRISMA as "Prisma<br/>schema.prisma"
FE->>API : "GET /auth/user-info"
API->>SVC : "getUserInfo(userId)"
SVC->>PRISMA : "findUnique(id)"
SVC-->>API : "用户信息"
API-->>FE : "返回信息"
FE->>API : "PUT /auth/user-info {nickname, avatar}"
API->>PRISMA : "update(id, {nickname?, avatar?})"
API-->>FE : "更新成功"
```

图表来源
- [auth.controller.ts:54-92](file://server/src/modules/auth/auth.controller.ts#L54-L92)
- [auth.service.ts:99-115](file://server/src/modules/auth/auth.service.ts#L99-L115)
- [schema.prisma:10-38](file://server/prisma/schema.prisma#L10-L38)

章节来源
- [auth.controller.ts:54-92](file://server/src/modules/auth/auth.controller.ts#L54-L92)
- [auth.service.ts:99-115](file://server/src/modules/auth/auth.service.ts#L99-L115)

### 字段允许空值与默认值的设计考量
- phone与openid允许空值
  - 支持多种登录方式（手机号、第三方），避免强制绑定单一入口
- nickname与avatar默认值
  - 提升首次体验，减少空值处理分支
- memberExpireAt与subscriptionResetDate允许空值
  - 表示非会员或未启用订阅周期重置，简化业务判断
- dailyUsage与lastUsageDate默认0/空字符串
  - 便于连续签到与额度重置逻辑的统一处理

章节来源
- [schema.prisma:10-38](file://server/prisma/schema.prisma#L10-L38)

### 常见业务场景实现路径
- 手机号绑定
  - 当前登录流程以手机号作为登录入口；若用户已有phone字段，可视为已绑定
  - 若需绑定新手机号，可在现有登录流程基础上扩展“绑定手机号”接口（当前仓库未提供独立绑定接口）
- OpenID关联
  - 当前User模型包含openid字段，但认证流程未展示第三方登录入口
  - 若接入第三方登录，可在登录流程中补充对openid的写入与去重逻辑
- 昵称修改
  - 通过PUT /auth/user-info接口传入nickname字段即可更新
- 头像URL更新
  - 通过PUT /auth/user-info接口传入avatar字段即可更新

章节来源
- [auth.controller.ts:66-92](file://server/src/modules/auth/auth.controller.ts#L66-L92)
- [auth.service.ts:43-97](file://server/src/modules/auth/auth.service.ts#L43-L97)
- [schema.prisma:10-38](file://server/prisma/schema.prisma#L10-L38)

## 依赖关系分析
- 前端依赖
  - Pinia Store负责登录态与用户信息的本地持久化与状态计算
- 后端依赖
  - 认证路由依赖认证服务进行业务处理
  - 认证服务依赖Prisma进行数据库读写
  - 数据访问层封装Prisma客户端连接与生命周期管理

```mermaid
graph LR
FE["前端 Store<br/>user.ts"] --> API["后端路由<br/>auth.controller.ts"]
API --> SVC["后端服务<br/>auth.service.ts"]
SVC --> PRISMA["Prisma 客户端<br/>models/index.ts"]
PRISMA --> SCHEMA["Schema 定义<br/>schema.prisma"]
```

图表来源
- [user.ts:1-107](file://my-uniapp-vue3/src/store/user.ts#L1-L107)
- [auth.controller.ts:1-94](file://server/src/modules/auth/auth.controller.ts#L1-L94)
- [auth.service.ts:1-115](file://server/src/modules/auth/auth.service.ts#L1-L115)
- [index.ts:1-15](file://server/src/models/index.ts#L1-L15)
- [schema.prisma:10-38](file://server/prisma/schema.prisma#L10-L38)

章节来源
- [user.ts:1-107](file://my-uniapp-vue3/src/store/user.ts#L1-L107)
- [auth.controller.ts:1-94](file://server/src/modules/auth/auth.controller.ts#L1-L94)
- [auth.service.ts:1-115](file://server/src/modules/auth/auth.service.ts#L1-L115)
- [index.ts:1-15](file://server/src/models/index.ts#L1-L15)
- [schema.prisma:10-38](file://server/prisma/schema.prisma#L10-L38)

## 性能考量
- 索引策略
  - phone与openid建立唯一索引，确保登录与绑定查询高效
- 查询优化
  - 登录与查询用户信息均采用按主键或唯一键查询，避免全表扫描
- 缓存建议
  - 对高频读取的用户信息可在应用层做短期缓存（如Redis），降低数据库压力
- 令牌与会话
  - 使用JWT令牌承载用户标识，减少数据库会话存储开销

## 故障排查指南
- 登录失败或验证码错误
  - 检查验证码生成与校验逻辑，确认过期时间与匹配规则
  - 开发环境下可临时跳过验证码校验以定位问题
- 用户不存在
  - 确认用户是否已通过手机号登录并创建
  - 检查phone字段是否正确传入
- 更新用户信息失败
  - 确认传入的nickname与avatar字段是否符合预期
  - 检查鉴权中间件是否正确注入userId
- 数据库连接异常
  - 检查Prisma客户端连接状态与数据库URL配置

章节来源
- [auth.controller.ts:54-92](file://server/src/modules/auth/auth.controller.ts#L54-L92)
- [auth.service.ts:21-32](file://server/src/modules/auth/auth.service.ts#L21-L32)
- [index.ts:5-13](file://server/src/models/index.ts#L5-L13)

## 结论
User模型以简洁明确的字段与合理的默认值设计，支撑起平台的多渠道登录与基础用户管理能力。通过唯一索引保障登录入口的一致性，通过可空字段与默认值兼顾灵活性与易用性。结合前端Store与后端服务层的清晰职责划分，形成了稳定可靠的用户信息流转链路。后续可在现有基础上扩展第三方登录与手机号绑定接口，进一步完善用户身份体系。