459 lines
10 KiB
Markdown
459 lines
10 KiB
Markdown
# 用户资料完整度 API 文档
|
||
|
||
## 接口概述
|
||
|
||
**接口名称**:获取用户资料完整度
|
||
**接口路径**:`/api/account/profile-completeness`
|
||
**请求方法**:`GET`
|
||
**接口描述**:获取当前登录用户的资料完整度信息,包括各项必填信息的完成状态、完整度百分比、缺失项列表等。
|
||
**业务场景**:用于在用户登录后提醒用户完善个人资料,提升平台服务质量。
|
||
|
||
---
|
||
|
||
## 请求参数
|
||
|
||
### Headers
|
||
|
||
| 参数名 | 类型 | 必填 | 描述 |
|
||
|--------|------|------|------|
|
||
| `Cookie` | string | 是 | 包含用户会话信息(session cookie),用于身份认证 |
|
||
|
||
### Query Parameters
|
||
|
||
无
|
||
|
||
### Body Parameters
|
||
|
||
无(GET 请求无 Body)
|
||
|
||
---
|
||
|
||
## 响应格式
|
||
|
||
### 成功响应 (200 OK)
|
||
|
||
**Content-Type**: `application/json`
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": {
|
||
"completeness": {
|
||
"hasPassword": true,
|
||
"hasPhone": true,
|
||
"hasEmail": false,
|
||
"isWechatUser": false
|
||
},
|
||
"completenessPercentage": 66,
|
||
"needsAttention": false,
|
||
"missingItems": ["邮箱"],
|
||
"isComplete": false,
|
||
"showReminder": false
|
||
}
|
||
}
|
||
```
|
||
|
||
### 响应字段说明
|
||
|
||
#### 顶层字段
|
||
|
||
| 字段名 | 类型 | 描述 |
|
||
|--------|------|------|
|
||
| `success` | boolean | 请求是否成功,`true` 表示成功 |
|
||
| `data` | object | 资料完整度数据对象 |
|
||
|
||
#### `data` 对象字段
|
||
|
||
| 字段名 | 类型 | 描述 |
|
||
|--------|------|------|
|
||
| `completeness` | object | 各项资料的完成状态详情 |
|
||
| `completenessPercentage` | number | 资料完整度百分比(0-100) |
|
||
| `needsAttention` | boolean | 是否需要用户注意(提醒用户完善) |
|
||
| `missingItems` | array[string] | 缺失项的中文描述列表 |
|
||
| `isComplete` | boolean | 资料是否完全完整(100%) |
|
||
| `showReminder` | boolean | 是否显示提醒横幅(同 `needsAttention`) |
|
||
|
||
#### `completeness` 对象字段
|
||
|
||
| 字段名 | 类型 | 描述 |
|
||
|--------|------|------|
|
||
| `hasPassword` | boolean | 是否已设置登录密码 |
|
||
| `hasPhone` | boolean | 是否已绑定手机号 |
|
||
| `hasEmail` | boolean | 是否已设置有效邮箱(排除临时邮箱) |
|
||
| `isWechatUser` | boolean | 是否为微信登录用户 |
|
||
|
||
---
|
||
|
||
## 业务逻辑说明
|
||
|
||
### 资料完整度计算规则
|
||
|
||
1. **必填项**(共 3 项):
|
||
- 登录密码(`hasPassword`)
|
||
- 手机号(`hasPhone`)
|
||
- 邮箱(`hasEmail`)
|
||
|
||
2. **完整度计算公式**:
|
||
```
|
||
completenessPercentage = (已完成项数 / 3) × 100
|
||
```
|
||
示例:
|
||
- 已完成 2 项 → 66%
|
||
- 已完成 3 项 → 100%
|
||
|
||
3. **邮箱有效性判断**:
|
||
- 必须包含 `@` 符号
|
||
- 不能是临时邮箱(如 `*@valuefrontier.temp`)
|
||
|
||
### 提醒逻辑(`needsAttention`)
|
||
|
||
**仅对微信登录用户进行提醒**,需同时满足以下条件:
|
||
|
||
1. `isWechatUser === true`(微信登录用户)
|
||
2. `completenessPercentage < 100`(资料不完整)
|
||
|
||
**后端额外的智能提醒策略**(Mock 模式未实现):
|
||
|
||
- 新用户(注册 7 天内):更容易触发提醒
|
||
- 每 7 天最多提醒一次(通过 session 记录)
|
||
- 完整度低于 50% 时优先提醒
|
||
|
||
### 缺失项列表(`missingItems`)
|
||
|
||
根据 `completeness` 对象生成中文描述:
|
||
|
||
| 条件 | 添加到 `missingItems` |
|
||
|------|----------------------|
|
||
| `!hasPassword` | `"登录密码"` |
|
||
| `!hasPhone` | `"手机号"` |
|
||
| `!hasEmail` | `"邮箱"` |
|
||
|
||
---
|
||
|
||
## 响应示例
|
||
|
||
### 示例 1:手机号登录用户,资料完整
|
||
|
||
**场景**:手机号登录,已设置密码和邮箱
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": {
|
||
"completeness": {
|
||
"hasPassword": true,
|
||
"hasPhone": true,
|
||
"hasEmail": true,
|
||
"isWechatUser": false
|
||
},
|
||
"completenessPercentage": 100,
|
||
"needsAttention": false,
|
||
"missingItems": [],
|
||
"isComplete": true,
|
||
"showReminder": false
|
||
}
|
||
}
|
||
```
|
||
|
||
### 示例 2:微信登录用户,未绑定手机号
|
||
|
||
**场景**:微信登录,未设置密码和手机号,触发提醒
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": {
|
||
"completeness": {
|
||
"hasPassword": false,
|
||
"hasPhone": false,
|
||
"hasEmail": true,
|
||
"isWechatUser": true
|
||
},
|
||
"completenessPercentage": 33,
|
||
"needsAttention": true,
|
||
"missingItems": ["登录密码", "手机号"],
|
||
"isComplete": false,
|
||
"showReminder": true
|
||
}
|
||
}
|
||
```
|
||
|
||
### 示例 3:微信登录用户,只缺邮箱
|
||
|
||
**场景**:微信登录,已设置密码和手机号,只缺邮箱
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": {
|
||
"completeness": {
|
||
"hasPassword": true,
|
||
"hasPhone": true,
|
||
"hasEmail": false,
|
||
"isWechatUser": true
|
||
},
|
||
"completenessPercentage": 66,
|
||
"needsAttention": true,
|
||
"missingItems": ["邮箱"],
|
||
"isComplete": false,
|
||
"showReminder": true
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 错误响应
|
||
|
||
### 401 Unauthorized - 未登录
|
||
|
||
**场景**:用户未登录或 Session 已过期
|
||
|
||
```json
|
||
{
|
||
"success": false,
|
||
"error": "用户未登录"
|
||
}
|
||
```
|
||
|
||
**HTTP 状态码**:`401`
|
||
|
||
### 500 Internal Server Error - 服务器错误
|
||
|
||
**场景**:服务器内部错误(如数据库连接失败)
|
||
|
||
```json
|
||
{
|
||
"success": false,
|
||
"error": "获取资料完整性错误: [错误详情]"
|
||
}
|
||
```
|
||
|
||
**HTTP 状态码**:`500`
|
||
|
||
---
|
||
|
||
## 调用示例
|
||
|
||
### JavaScript (Fetch API)
|
||
|
||
```javascript
|
||
async function checkProfileCompleteness() {
|
||
try {
|
||
const response = await fetch('/api/account/profile-completeness', {
|
||
method: 'GET',
|
||
credentials: 'include', // 重要:携带 Cookie
|
||
headers: {
|
||
'Content-Type': 'application/json'
|
||
}
|
||
});
|
||
|
||
if (!response.ok) {
|
||
throw new Error(`HTTP error! status: ${response.status}`);
|
||
}
|
||
|
||
const data = await response.json();
|
||
|
||
if (data.success) {
|
||
console.log('资料完整度:', data.data.completenessPercentage + '%');
|
||
console.log('是否需要提醒:', data.data.needsAttention);
|
||
|
||
if (data.data.needsAttention) {
|
||
console.log('缺失项:', data.data.missingItems.join('、'));
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('检查资料完整性失败:', error);
|
||
}
|
||
}
|
||
```
|
||
|
||
### cURL
|
||
|
||
```bash
|
||
curl -X GET 'http://localhost:5001/api/account/profile-completeness' \
|
||
-H 'Cookie: session=your_session_cookie_here' \
|
||
-H 'Content-Type: application/json'
|
||
```
|
||
|
||
### Axios
|
||
|
||
```javascript
|
||
import axios from 'axios';
|
||
|
||
async function checkProfileCompleteness() {
|
||
try {
|
||
const { data } = await axios.get('/api/account/profile-completeness', {
|
||
withCredentials: true // 携带 Cookie
|
||
});
|
||
|
||
if (data.success) {
|
||
return data.data;
|
||
}
|
||
} catch (error) {
|
||
if (error.response?.status === 401) {
|
||
console.error('用户未登录');
|
||
} else {
|
||
console.error('检查失败:', error.message);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 调用时机建议
|
||
|
||
### ✅ 推荐调用场景
|
||
|
||
1. **用户登录后**:首次登录或刷新页面后检查一次
|
||
2. **资料更新后**:用户修改个人资料后重新检查
|
||
3. **手动触发**:用户点击"检查资料完整度"按钮
|
||
|
||
### ❌ 避免的场景
|
||
|
||
1. **导航栏每次 render 时**:会导致频繁请求
|
||
2. **组件重新渲染时**:应使用缓存或标志位避免重复
|
||
3. **轮询调用**:此接口不需要轮询,用户资料变化频率低
|
||
|
||
### 最佳实践
|
||
|
||
```javascript
|
||
// 使用 React Hooks 的最佳实践
|
||
function useProfileCompleteness() {
|
||
const [completeness, setCompleteness] = useState(null);
|
||
const hasChecked = useRef(false);
|
||
const { isAuthenticated, user } = useAuth();
|
||
|
||
const check = useCallback(async () => {
|
||
// 避免重复检查
|
||
if (hasChecked.current) return;
|
||
|
||
try {
|
||
const response = await fetch('/api/account/profile-completeness', {
|
||
credentials: 'include'
|
||
});
|
||
|
||
if (response.ok) {
|
||
const data = await response.json();
|
||
if (data.success) {
|
||
setCompleteness(data.data);
|
||
hasChecked.current = true; // 标记已检查
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.warn('检查失败:', error);
|
||
}
|
||
}, []);
|
||
|
||
// 仅在登录后检查一次
|
||
useEffect(() => {
|
||
if (isAuthenticated && user && !hasChecked.current) {
|
||
check();
|
||
}
|
||
}, [isAuthenticated, user, check]);
|
||
|
||
// 提供手动刷新方法
|
||
const refresh = useCallback(() => {
|
||
hasChecked.current = false;
|
||
check();
|
||
}, [check]);
|
||
|
||
return { completeness, refresh };
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Mock 模式说明
|
||
|
||
在 Mock 模式下(`REACT_APP_ENABLE_MOCK=true`),此接口由 MSW (Mock Service Worker) 拦截:
|
||
|
||
### Mock 实现位置
|
||
|
||
- **Handler**: `src/mocks/handlers/account.js`
|
||
- **数据源**: `src/mocks/data/users.js` (getCurrentUser)
|
||
|
||
### Mock 特点
|
||
|
||
1. **真实计算**:基于当前登录用户的实际数据计算完整度
|
||
2. **状态同步**:与登录状态同步,登录后才返回真实用户数据
|
||
3. **未登录返回 401**:模拟真实后端行为
|
||
4. **延迟模拟**:300ms 网络延迟,模拟真实请求
|
||
|
||
### Mock 测试数据
|
||
|
||
| 测试账号 | 手机号 | 密码 | 邮箱 | 微信 | 完整度 |
|
||
|---------|--------|------|------|------|--------|
|
||
| 测试用户 | 13800138000 | ✅ | ❌ | ❌ | 66% |
|
||
| 投资达人 | 13900139000 | ✅ | ✅ | ✅ | 100% |
|
||
|
||
---
|
||
|
||
## 前端集成示例
|
||
|
||
### 显示资料完整度横幅
|
||
|
||
```jsx
|
||
import { useProfileCompleteness } from './hooks/useProfileCompleteness';
|
||
|
||
function App() {
|
||
const { completeness } = useProfileCompleteness();
|
||
|
||
return (
|
||
<>
|
||
{/* 资料完整度提醒横幅 */}
|
||
{completeness?.showReminder && (
|
||
<Alert status="info" variant="subtle">
|
||
<AlertIcon />
|
||
<Box flex="1">
|
||
<AlertTitle>完善资料,享受更好服务</AlertTitle>
|
||
<AlertDescription>
|
||
您还需要设置:{completeness.missingItems.join('、')}
|
||
({completeness.completenessPercentage}% 完成)
|
||
</AlertDescription>
|
||
</Box>
|
||
<Button size="sm" onClick={() => navigate('/settings')}>
|
||
立即完善
|
||
</Button>
|
||
</Alert>
|
||
)}
|
||
|
||
{/* 主要内容 */}
|
||
<MainContent />
|
||
</>
|
||
);
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 版本历史
|
||
|
||
| 版本 | 日期 | 变更说明 |
|
||
|------|------|----------|
|
||
| v1.0 | 2024-10-17 | 初始版本,支持资料完整度检查和智能提醒 |
|
||
|
||
---
|
||
|
||
## 相关接口
|
||
|
||
- `GET /api/auth/session` - 检查登录状态
|
||
- `GET /api/account/profile` - 获取完整用户资料
|
||
- `PUT /api/account/profile` - 更新用户资料
|
||
- `POST /api/auth/logout` - 退出登录
|
||
|
||
---
|
||
|
||
## 技术支持
|
||
|
||
如有问题,请联系开发团队或查看:
|
||
- **Mock 配置指南**: [MOCK_GUIDE.md](./MOCK_GUIDE.md)
|
||
- **项目文档**: [CLAUDE.md](./CLAUDE.md)
|
||
|
||
---
|
||
|
||
**文档生成日期**:2024-10-17
|
||
**API 版本**:v1.0
|
||
**Mock 支持**:✅ 已实现
|