16 KiB
java-mock 接口文档 & 数据设计
Base URL:
http://localhost:8080认证方式: JWT Bearer Token(除登录/注册外,所有接口均需在请求头附加
Authorization: Bearer <token>)
目录
接口总览
| 方法 | 路径 | 是否需要 Token | 说明 |
|---|---|---|---|
| GET | /health |
否 | 健康检查 |
| POST | /api/auth/login |
否 | 登录 |
| POST | /api/auth/register |
否 | 注册 |
| GET | /api/auth/me |
✅ | 获取当前用户信息 |
| POST | /api/ai/getScenes |
✅ | 获取场景列表(转发 Python) |
| POST | /api/ai/proxy?Action=StartVoiceChat |
✅ | 开始语音对话(转发 Python) |
| POST | /api/ai/proxy?Action=StopVoiceChat |
✅ | 停止语音对话(转发 Python) |
| POST | /api/ai/session/history |
✅ | 写入历史上下文(转发 Python) |
| POST | /api/ai/conversations |
✅ | 保存对话记录 |
| GET | /api/ai/conversations |
✅ | 对话列表(分页) |
| GET | /api/ai/conversations/:id |
✅ | 对话详情 |
| POST | /api/ai/conversations/:id/append |
✅ | 追加消息到对话 |
| DELETE | /api/ai/conversations/:id |
✅ | 删除对话 |
一、认证接口
1.1 登录
POST /api/auth/login
请求体(JSON):
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| username | string | ✅ | 用户名 |
| password | string | ✅ | 密码(明文) |
请求示例:
{
"username": "admin",
"password": "admin123"
}
成功响应 200:
{
"code": 200,
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"name": "管理员",
"sex": "male",
"isDriver": false,
"deptId": 1,
"deptName": "办公室",
"roleList": ["admin", "user"]
}
}
失败响应:
| HTTP 状态码 | code | message |
|---|---|---|
| 400 | 400 | 用户名和密码不能为空 |
| 401 | 401 | 用户名或密码错误 |
1.2 注册
POST /api/auth/register
请求体(JSON):
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| username | string | ✅ | 用户名(唯一) |
| password | string | ✅ | 密码(明文) |
| nickname | string | ❌ | 昵称,不传时默认等于 username |
请求示例:
{
"username": "newuser",
"password": "pass123",
"nickname": "新用户"
}
成功响应 200:
{
"code": 200,
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"name": "新用户",
"sex": "unknown",
"isDriver": false,
"deptId": 0,
"deptName": "",
"roleList": ["user"]
}
}
失败响应:
| HTTP 状态码 | code | message |
|---|---|---|
| 400 | 400 | 用户名和密码不能为空 |
| 409 | 409 | 用户名已存在 |
注册成功后新用户默认属性:
sex=unknown、isDriver=false、deptId=0、roleList=["user"]
1.3 获取当前用户信息
GET /api/auth/me
成功响应 200:
{
"code": 200,
"data": {
"name": "管理员",
"sex": "male",
"isDriver": false,
"deptId": 1,
"deptName": "办公室",
"roleList": ["admin", "user"]
}
}
失败响应:
| HTTP 状态码 | code | message |
|---|---|---|
| 401 | 401 | 未提供 Authorization Token |
| 401 | 401 | Token 无效或已过期 |
| 404 | 404 | 用户不存在 |
二、AI 代理接口(转发 Python)
所有 AI 代理接口均带 HMAC-SHA256 内部签名后转发至 Python 后端(
PYTHON_BACKEND_URL),响应内容原样透传。详细签名规则见 内部转发签名协议。
2.1 获取场景列表
POST /api/ai/getScenes
请求体: {} 或空
成功响应(Python 原样返回):
{
"ResponseMetadata": {
"Action": "getScenes"
},
"Result": {
"scenes": [
{
"scene": {
"id": "Custom",
"botName": "BotUser001",
"isInterruptMode": true,
"isVision": false,
"isScreenMode": false,
"isAvatarScene": false,
"avatarBgUrl": null
},
"rtc": {
"AppId": "6xxxxxxx",
"RoomId": "room-abc123",
"UserId": "user-xyz",
"Token": "AQBhMGI3Zm...",
"TaskId": "task-001"
}
}
]
}
}
2.2 开始语音对话
POST /api/ai/proxy?Action=StartVoiceChat
请求体(JSON):
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| SceneID | string | ✅ | 场景 ID(从 getScenes 获取) |
请求示例:
{
"SceneID": "Custom"
}
成功响应(Python 原样返回):
{
"ResponseMetadata": {
"RequestId": "2024xxxxxxxxxx",
"Action": "StartVoiceChat",
"Version": "2024-12-01",
"Service": "rtc"
},
"Result": {
"Message": "success"
}
}
2.3 停止语音对话
POST /api/ai/proxy?Action=StopVoiceChat
请求体(JSON):
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| SceneID | string | ✅ | 场景 ID |
请求示例:
{
"SceneID": "Custom"
}
成功响应(Python 原样返回):
{
"ResponseMetadata": {
"RequestId": "2024xxxxxxxxxx",
"Action": "StopVoiceChat",
"Version": "2024-12-01",
"Service": "rtc"
},
"Result": {
"Message": "success"
}
}
2.4 写入历史上下文
在 StartVoiceChat 之前调用,将历史对话上下文注入 Python Session,以便 AI 延续上下文。
POST /api/ai/session/history
请求体(JSON):
转发到 Python /api/session/history,具体字段由 Python 接口定义,典型示例:
{
"roomId": "room-abc123",
"history": [
{ "role": "user", "content": "你好" },
{ "role": "assistant", "content": "你好!有什么可以帮你?" }
]
}
成功响应: Python 原样返回
三、对话记录接口
3.1 保存对话
POST /api/ai/conversations
请求体(JSON):
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| sceneId | string | ✅ | 场景 ID |
| roomId | string | ❌ | RTC 房间 ID |
| messages | array | ✅ | 消息数组(见下表) |
messages 数组每条消息字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| role | string | "user" 或 "assistant"(优先使用) |
| content | string | 消息文本 |
| time | string | ISO 时间戳,不传取服务器当前时间 |
| userId | string | 兼容旧格式。与当前登录用户 ID 相同则视为 user,否则视为 assistant |
| text | string | 兼容旧格式,与 content 二选一 |
请求示例:
{
"sceneId": "Custom",
"roomId": "room-abc123",
"messages": [
{ "role": "assistant", "content": "你好,我是小块", "time": "2026-04-02T10:00:00Z" },
{ "role": "user", "content": "今天出勤情况咋样", "time": "2026-04-02T10:00:05Z" },
{ "role": "assistant", "content": "今天出勤率 90%", "time": "2026-04-02T10:00:08Z" }
]
}
成功响应 200:
{
"code": 200,
"data": {
"sessionId": "9864c5ef-cdee-4c35-8f6a-81a9a4f6d323"
}
}
失败响应:
| HTTP 状态码 | code | message |
|---|---|---|
| 400 | 400 | sceneId 和 messages 不能为空 |
3.2 对话列表(分页)
GET /api/ai/conversations?page=1&size=20
Query 参数:
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| page | number | 1 | 页码(从 1 开始) |
| size | number | 20 | 每页条数(上限 100) |
成功响应 200:
{
"code": 200,
"data": {
"total": 5,
"page": 1,
"size": 20,
"list": [
{
"id": "9864c5ef-cdee-4c35-8f6a-81a9a4f6d323",
"sceneId": "Custom",
"roomId": "room-abc123",
"startedAt": "2026-04-02T10:00:00Z",
"endedAt": "2026-04-02T10:00:08Z",
"messageCount": 3,
"firstMessage": "今天出勤情况咋样"
}
]
}
}
- 列表按
createdAt倒序排列firstMessage取第一条role === "user"的消息内容,无用户消息时为空串- 仅返回当前登录用户的对话记录
3.3 对话详情
GET /api/ai/conversations/:id
Path 参数:
| 字段 | 说明 |
|---|---|
| id | 对话 UUID |
成功响应 200:
{
"code": 200,
"data": {
"id": "9864c5ef-cdee-4c35-8f6a-81a9a4f6d323",
"userId": "user-admin-001",
"sceneId": "Custom",
"roomId": "room-abc123",
"startedAt": "2026-04-02T10:00:00Z",
"endedAt": "2026-04-02T10:00:08Z",
"createdAt": "2026-04-02T10:00:10Z",
"messages": [
{ "role": "assistant", "content": "你好,我是小块", "createdAt": "2026-04-02T10:00:00Z" },
{ "role": "user", "content": "今天出勤情况咋样", "createdAt": "2026-04-02T10:00:05Z" },
{ "role": "assistant", "content": "今天出勤率 90%", "createdAt": "2026-04-02T10:00:08Z" }
]
}
}
失败响应:
| HTTP 状态码 | code | message |
|---|---|---|
| 404 | 404 | 对话记录不存在 |
| 403 | 403 | 无权访问该对话 |
3.4 追加消息
对话保存后如需继续追加消息(例如语音会话延续),调用此接口。
POST /api/ai/conversations/:id/append
Path 参数:
| 字段 | 说明 |
|---|---|
| id | 对话 UUID |
请求体(JSON):
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| messages | array | ✅ | 追加的消息数组,格式同 3.1 |
请求示例:
{
"messages": [
{ "role": "user", "content": "那明天呢", "time": "2026-04-02T10:01:00Z" },
{ "role": "assistant", "content": "明天是周末,无需考勤", "time": "2026-04-02T10:01:03Z" }
]
}
成功响应 200:
{
"code": 200,
"data": {
"sessionId": "9864c5ef-cdee-4c35-8f6a-81a9a4f6d323"
}
}
失败响应:
| HTTP 状态码 | code | message |
|---|---|---|
| 400 | 400 | messages 不能为空 |
| 404 | 404 | 对话记录不存在 |
| 403 | 403 | 无权操作该对话 |
3.5 删除对话
DELETE /api/ai/conversations/:id
Path 参数:
| 字段 | 说明 |
|---|---|
| id | 对话 UUID |
成功响应 200:
{
"code": 200,
"data": null
}
失败响应:
| HTTP 状态码 | code | message |
|---|---|---|
| 404 | 404 | 对话记录不存在 |
| 403 | 403 | 无权删除该对话 |
四、其他
4.1 健康检查
GET /health
响应(无需 Token):
{
"status": "ok",
"service": "java-mock",
"timestamp": "2026-04-02T10:00:00.000Z"
}
数据结构设计
User(用户表)
文件存储路径:
data/users.json(数组)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | string | ✅ | 唯一 ID,格式 user-<uuid> 或 user-admin-001(内置账号) |
| username | string | ✅ | 登录用户名,全局唯一 |
| password | string | ✅ | 明文密码(Mock 环境,生产请改用 bcrypt 哈希) |
| name | string | ✅ | 显示名 / 昵称 |
| sex | string | ✅ | 性别:"male" / "female" / "unknown" |
| isDriver | boolean | ✅ | 是否为司机角色 |
| deptId | number | ✅ | 部门 ID,0 表示无部门 |
| deptName | string | ✅ | 部门名称 |
| roleList | string[] | ✅ | 角色列表,如 ["admin","user"] / ["user"] |
| createdAt | string | ✅ | 创建时间 ISO8601 |
示例数据:
[
{
"id": "user-admin-001",
"username": "admin",
"password": "admin123",
"name": "管理员",
"sex": "male",
"isDriver": false,
"deptId": 1,
"deptName": "办公室",
"roleList": ["admin", "user"],
"createdAt": "2026-01-01T00:00:00.000Z"
},
{
"id": "user-001",
"username": "user1",
"password": "user123",
"name": "测试用户",
"sex": "female",
"isDriver": false,
"deptId": 2,
"deptName": "工程部",
"roleList": ["user"],
"createdAt": "2026-01-01T00:00:00.000Z"
}
]
Conversation(对话表)
文件存储路径:
data/conversations.json(数组)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | string | ✅ | UUID v4,全局唯一 |
| userId | string | ✅ | 所属用户 ID(关联 User.id) |
| sceneId | string | ✅ | 场景 ID,如 "Custom" |
| roomId | string | ✅ | RTC 房间 ID,无则为空串 |
| startedAt | string | ✅ | 对话开始时间(取第一条消息 createdAt) |
| endedAt | string | ✅ | 对话结束时间(取最后一条消息 createdAt) |
| createdAt | string | ✅ | 记录入库时间 |
| messages | Message[] | ✅ | 消息数组(见 Message 结构) |
示例数据:
{
"id": "85ce1273-7279-44fb-b018-3e49295c89f7",
"userId": "user-admin-001",
"sceneId": "Custom",
"roomId": "4fea87af-5b23-445d-9754-d4d878a1c705",
"startedAt": "2026-04-02T05:06:57.828Z",
"endedAt": "2026-04-02T05:07:18.750Z",
"createdAt": "2026-04-02T05:07:28.729Z",
"messages": [...]
}
Message(消息子文档)
嵌套在 Conversation.messages 数组中
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| role | string | ✅ | "user"(用户说)或 "assistant"(AI 说) |
| content | string | ✅ | 消息文本内容 |
| createdAt | string | ✅ | 消息时间 ISO8601 |
示例:
[
{ "role": "assistant", "content": "你好,我是小块,有什么需要帮忙的吗?", "createdAt": "2026-04-02T05:06:57.828Z" },
{ "role": "user", "content": "今天办公室出勤情况咋样", "createdAt": "2026-04-02T05:07:12.023Z" },
{ "role": "assistant", "content": "今天办公室一共九个人,出勤率 90%。", "createdAt": "2026-04-02T05:07:18.750Z" }
]
内部转发签名协议
转发到 Python 时,java-mock 会附加以下请求头,Python 侧需验证签名合法性。
| Header | 说明 |
|---|---|
X-Internal-Service |
固定值 java-gateway |
X-Internal-User-Id |
当前登录用户 ID |
X-Internal-Timestamp |
毫秒级 Unix 时间戳(字符串) |
X-Internal-Signature |
HMAC-SHA256 签名,见下方算法 |
X-User-Name |
URL 编码的用户显示名 |
X-User-Sex |
性别字符串 |
X-User-Is-Driver |
"true" 或 "false" |
X-User-Dept-Id |
部门 ID 字符串 |
X-User-Dept-Name |
URL 编码的部门名称 |
X-User-Role-List |
URL 编码的 JSON 数组字符串,如 %5B%22admin%22%5D |
签名算法:
message = "java-gateway:{userId}:{timestamp}"
signature = HMAC-SHA256(INTERNAL_SERVICE_SECRET, message) // hex 输出
通用错误响应
所有接口在出错时均返回如下结构:
{
"code": <HTTP状态码>,
"message": "错误描述"
}
| code | 含义 |
|---|---|
| 400 | 请求参数缺失或格式错误 |
| 401 | 未登录或 Token 无效 / 过期 |
| 403 | 无权限访问该资源 |
| 404 | 资源不存在 |
| 409 | 资源冲突(如用户名重复) |
| 502 | 无法连接 Python 后端 |
| 500 | 服务器内部错误 |
环境变量
| 变量名 | 默认值 | 说明 |
|---|---|---|
PORT |
8080 |
服务监听端口 |
JWT_SECRET |
— | JWT 签名密钥(必填) |
JWT_EXPIRES_IN |
7d |
JWT 过期时间 |
PYTHON_BACKEND_URL |
http://localhost:3001 |
Python 后端地址 |
INTERNAL_SERVICE_SECRET |
— | 内部签名密钥(必填) |