3.1 KiB
3.1 KiB
设备与在线时长接口
概述
- 基础地址:
http://localhost:8000 - 版本前缀:
/api/v1 - 说明:同一账号仅允许一个设备同时在线(依据
device_id);后端会记录登录登出并可统计在线时长。
登录(含单设备限制)
- 方法与路径:
POST /api/v1/auth/login - 请求体:
{
"username": "alice",
"password": "secret123",
"device_id": "devA"
}
- 成功响应:
{
"access_token": "<JWT>",
"token_type": "bearer",
"username": "alice"
}
- 失败响应:
- 401:
用户名或密码错误 - 403:
该账号已在其他设备在线
- 401:
- 说明:
- 必须传入稳定的
device_id(前端生成并持久化),用于限制并发登录与统计时长 - 登录成功会记录会话的
login_at,并将设备会话标记为活跃
- 必须传入稳定的
登出(记录在线时长)
- 方法与路径:
POST /api/v1/auth/logout - 请求体:
{
"username": "alice",
"device_id": "devA"
}
- 成功响应:
{ "detail": "已退出登录" }
- 行为:
- 将对应设备的会话置为非活跃,并记录
logout_at - 若存在
login_at,会计算本次会话的在线时长duration_seconds(单位:秒)
- 将对应设备的会话置为非活跃,并记录
在线时长统计
- 方法与路径:
GET /api/v1/auth/online-time/{username} - 成功响应:
{
"username": "alice",
"total_seconds": 1234,
"active_seconds": 56
}
- 字段说明:
total_seconds:历史所有已登出会话的累计在线时长(秒)active_seconds:当前活跃会话的实时在线时长(秒),若无活跃会话则为 0;实时时长基于最近心跳时间last_seen_at与login_at的差值
- 统计逻辑:
- 登录时写入
login_at(UTC) - 登出时写入
logout_at并计算duration_seconds - 查询时将已登出会话的
duration_seconds累加为total_seconds,并以当前时间与活跃会话的login_at计算active_seconds
- 登录时写入
心跳接口(保持在线时长统计)
- 方法与路径:
POST /api/v1/auth/heartbeat - 请求体:
{
"username": "alice",
"device_id": "devA"
}
- 成功响应:
{ "detail": "心跳已更新" }
- 说明:
- 前端应在用户在线期间定期调用心跳(例如每 30~60 秒),以更新会话的
last_seen_at - 若未调用登出而直接关闭应用,在线时长将以最近一次心跳为准,不会无限累计
- 前端应在用户在线期间定期调用心跳(例如每 30~60 秒),以更新会话的
错误信息(统一中文)
- 401:
用户名或密码错误 - 403:
该账号已在其他设备在线 - 404:
用户不存在
前端调用示例(Axios)
import axios from 'axios';
const API = 'http://localhost:8000/api/v1/auth';
export async function login(username: string, password: string, deviceId: string) {
return axios.post(`${API}/login`, { username, password, device_id: deviceId });
}
export async function logout(username: string, deviceId: string) {
return axios.post(`${API}/logout`, { username, device_id: deviceId });
}
export async function getOnlineTime(username: string) {
return axios.get(`${API}/online-time/${encodeURIComponent(username)}`);
}