19 KiB
19 KiB
Sundynix 前端接入文档
网关地址:
http://{GATEWAY_HOST}:8888所有接口统一经过网关转发,前端只需对接网关地址
一、全局约定
1.1 统一响应格式
所有接口返回 HTTP 200,通过 code 区分业务状态:
{
"code": 200,
"msg": "success",
"data": { ... }
}
| code | 含义 |
|---|---|
| 200 | 成功 |
| 400 | 业务错误(参数错误、逻辑异常等) |
| 401 | 未授权(Token 缺失/过期/无效) |
1.2 鉴权机制
需要鉴权的接口必须携带以下请求头:
Authorization: Bearer <token>
X-Client-Id: <客户端标识>
Important
Authorization从登录接口获取X-Client-Id由后台管理端配置的客户端标识(如sundynix-admin、mini-app)
1.3 Token 自动续期
网关内置滑动窗口续期机制。当 Token 剩余有效时间 < 1 小时时,响应头会携带新 Token:
X-Refresh-Token: <new_token>
前端需要在响应拦截器中处理:
// axios 响应拦截器
axios.interceptors.response.use((response) => {
const newToken = response.headers['x-refresh-token']
if (newToken) {
// 静默替换本地存储的 Token
useUserStore().setToken(newToken)
}
return response
})
1.4 CORS 说明
网关已配置跨域,前端无需额外处理。已暴露自定义响应头 X-Refresh-Token。
二、Auth 服务(/api/auth)
2.1 获取图形验证码
🔓 无需鉴权
GET /api/auth/captcha
响应:
{
"code": 200,
"msg": "success",
"data": {
"captchaId": "abc123",
"captchaImg": "data:image/png;base64,iVBOR..."
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
| captchaId | string | 验证码 ID,登录时回传 |
| captchaImg | string | Base64 图片,直接赋给 <img src> |
2.2 账号密码登录
🔓 无需鉴权
POST /api/auth/login
请求头:
X-Client-Id: sundynix-admin
请求体:
{
"account": "admin",
"password": "123456",
"captchaId": "abc123",
"captcha": "5xmn"
}
| 字段 | 必填 | 说明 |
|---|---|---|
| account | ✅ | 账号 |
| password | ✅ | 密码 |
| captchaId | ✅ | 验证码 ID(从 captcha 接口获取) |
| captcha | ✅ | 用户输入的验证码 |
响应:
{
"code": 200,
"msg": "success",
"data": {
"token": "eyJhbGciOiJIUzI1NiIs...",
"userInfo": {
"id": "1234567890",
"name": "张三",
"account": "admin",
"nickName": "管理员",
"phone": "13800138000",
"avatarId": "file-id-xxx",
"gender": 1
}
}
}
2.3 微信小程序登录
🔓 无需鉴权
POST /api/auth/miniLogin
请求体:
{
"code": "wx_login_code_from_wx.login()",
"clientId": "mini-app"
}
响应:同 2.2 的响应格式
2.4 手机号登录
🔓 无需鉴权
POST /api/auth/loginByPhone
请求体:
{
"code": "phone_code_from_getPhoneNumber",
"openId": "用户openId",
"clientId": "mini-app"
}
响应:同 2.2 的响应格式
2.5 获取当前用户信息(含角色、菜单)
🔒 需要鉴权
GET /api/auth/info
响应:
{
"code": 200,
"msg": "success",
"data": {
"id": "1234567890",
"name": "张三",
"account": "admin",
"nickName": "管理员",
"phone": "13800138000",
"avatarId": "file-id-xxx",
"gender": 1,
"roles": ["admin", "editor"],
"menus": [
{
"id": "m1",
"parentId": "0",
"category": 1,
"name": "Dashboard",
"title": "仪表盘",
"code": "dashboard",
"path": "/dashboard",
"permission": "",
"locale": "menu.dashboard",
"icon": "icon-dashboard",
"sort": 1,
"children": [
{
"id": "m2",
"parentId": "m1",
"name": "Workplace",
"title": "工作台",
"path": "/dashboard/workplace",
"sort": 1,
"children": []
}
]
}
],
"createdAt": 1714000000
}
}
Tip
roles是角色 code 数组,用于前端权限判断menus是树形结构,已按sort排序,前端直接渲染侧边栏createdAt是 Unix 时间戳(秒)
2.6 更新个人信息
🔒 需要鉴权
POST /api/auth/update
请求体(所有字段可选,只传需要修改的):
{
"name": "李四",
"nickName": "小李",
"phone": "13900139000",
"avatarId": "new-file-id"
}
响应:
{ "code": 200, "msg": "success" }
三、System 服务(/api/sys)
Important
以下所有接口均需要鉴权(
Authorization: Bearer <token>)
3.1 客户端管理
创建客户端
POST /api/sys/client/create
{
"clientId": "sundynix-admin",
"name": "Web管理端",
"grantType": "password",
"additionalInfo": "",
"activeTimeout": 7200
}
| 字段 | 必填 | 说明 |
|---|---|---|
| clientId | ✅ | 客户端唯一标识 |
| name | ✅ | 客户端名称 |
| grantType | ❌ | 授权类型 |
| additionalInfo | ❌ | 附加信息 |
| activeTimeout | ❌ | Token 有效期(秒),默认 7200 |
更新客户端
POST /api/sys/client/update
{
"id": "客户端记录ID",
"name": "新名称",
"activeTimeout": 3600
}
删除客户端
POST /api/sys/client/delete
{ "ids": ["id1", "id2"] }
客户端列表
POST /api/sys/client/list
{
"current": 1,
"pageSize": 10,
"name": ""
}
响应:
{
"code": 200,
"msg": "success",
"data": {
"list": [
{
"id": "xxx",
"clientId": "sundynix-admin",
"name": "Web管理端",
"grantType": "password",
"additionalInfo": "",
"activeTimeout": 7200
}
],
"total": 1,
"current": 1,
"size": 10
}
}
3.2 角色管理
创建角色
POST /api/sys/role/create
{
"name": "管理员",
"code": "admin",
"sort": 1,
"menuIds": ["menu-id-1", "menu-id-2"]
}
更新角色
POST /api/sys/role/update
{
"id": "角色ID",
"name": "超级管理员",
"code": "super-admin",
"sort": 0,
"menuIds": ["menu-id-1", "menu-id-2", "menu-id-3"]
}
Note
menuIds是全量替换,传什么就关联什么。不传或空数组则清除所有菜单关联。
删除角色
POST /api/sys/role/delete
{ "ids": ["role-id-1"] }
角色列表
POST /api/sys/role/list
{
"current": 1,
"pageSize": 10,
"name": ""
}
响应:
{
"code": 200,
"msg": "success",
"data": {
"list": [
{
"id": "xxx",
"name": "管理员",
"code": "admin",
"sort": 1,
"menuIds": ["m1", "m2"]
}
],
"total": 1
}
}
3.3 菜单管理
创建菜单
POST /api/sys/menu/create
{
"parentId": "0",
"category": 1,
"name": "Dashboard",
"title": "仪表盘",
"code": "dashboard",
"path": "/dashboard",
"permission": "",
"locale": "menu.dashboard",
"icon": "icon-dashboard",
"sort": 1
}
| 字段 | 说明 |
|---|---|
| parentId | 父级ID,顶级菜单传 "0" 或空字符串 |
| category | 类型:1=菜单 2=按钮/权限 |
| name | 路由 name(英文,如 Dashboard) |
| title | 显示标题(中文,如 仪表盘) |
| code | 权限标识(如 dashboard) |
| path | 路由路径(如 /dashboard) |
| permission | 操作权限标识 |
| locale | 国际化 key |
| icon | 图标名称 |
| sort | 排序值,越小越靠前 |
更新菜单
POST /api/sys/menu/update
{
"id": "菜单ID",
"title": "新标题",
"sort": 2
}
删除菜单
POST /api/sys/menu/delete
{ "ids": ["menu-id-1"] }
Warning
删除菜单会同步清除该菜单与所有角色的关联关系
菜单列表(树形)
GET /api/sys/menu/list
无参数。返回完整的树形菜单结构。
响应:
{
"code": 200,
"msg": "success",
"data": [
{
"id": "m1",
"parentId": "0",
"category": 1,
"name": "System",
"title": "系统管理",
"code": "system",
"path": "/system",
"icon": "icon-settings",
"sort": 99,
"children": [
{
"id": "m2",
"parentId": "m1",
"name": "User",
"title": "用户管理",
"path": "/system/user",
"sort": 1,
"children": []
}
]
}
]
}
根据角色获取菜单
POST /api/sys/menu/byRole
{ "id": "角色ID" }
响应:同菜单列表格式,但只包含该角色关联的菜单
3.4 用户管理(后台管理)
用户列表
POST /api/sys/user/list
{
"current": 1,
"pageSize": 10,
"name": "",
"account": ""
}
响应:
{
"code": 200,
"msg": "success",
"data": {
"list": [
{
"id": "xxx",
"name": "张三",
"account": "admin",
"nickName": "管理员",
"phone": "13800138000",
"gender": 1,
"createdAt": 1714000000
}
],
"total": 1
}
}
创建用户
POST /api/sys/user/create
{
"name": "张三",
"account": "zhangsan",
"password": "123456",
"phone": "13800138000",
"nickName": "小张",
"roleIds": ["role-id-1", "role-id-2"]
}
| 字段 | 必填 | 说明 |
|---|---|---|
| name | ✅ | 姓名 |
| account | ✅ | 账号(唯一) |
| password | ✅ | 密码 |
| phone | ❌ | 手机号 |
| nickName | ❌ | 昵称 |
| roleIds | ❌ | 关联角色ID数组 |
更新用户
POST /api/sys/user/update
{
"id": "用户ID",
"name": "李四",
"phone": "13900139000",
"roleIds": ["role-id-1"]
}
删除用户
POST /api/sys/user/delete
{ "ids": ["user-id-1", "user-id-2"] }
重置密码
POST /api/sys/user/resetPassword
{
"id": "用户ID",
"password": "newpassword123"
}
3.5 字典管理
创建字典
POST /api/sys/dict/create
{
"type": "gender",
"label": "男",
"value": "1",
"sort": 1,
"desc": "性别-男"
}
更新字典
POST /api/sys/dict/update
{
"id": "字典ID",
"label": "女",
"value": "2"
}
删除字典
POST /api/sys/dict/delete
{ "ids": ["dict-id-1"] }
字典列表
POST /api/sys/dict/list
{
"current": 1,
"pageSize": 10,
"type": "gender"
}
响应:
{
"code": 200,
"msg": "success",
"data": {
"list": [
{
"id": "xxx",
"type": "gender",
"label": "男",
"value": "1",
"sort": 1,
"desc": "性别-男"
}
],
"total": 2
}
}
3.6 操作日志
日志列表
POST /api/sys/log/list
{
"current": 1,
"pageSize": 20,
"method": "POST",
"path": "/api/auth/login",
"status": 200
}
响应:
{
"code": 200,
"msg": "success",
"data": {
"list": [
{
"id": "xxx",
"clientId": "sundynix-admin",
"ip": "192.168.1.100",
"method": "POST",
"path": "/api/auth/login",
"status": 200,
"latency": 52000000,
"agent": "Mozilla/5.0...",
"errorMessage": "",
"body": "{\"account\":\"admin\"...}",
"resp": "{\"code\":200...}",
"userId": "user-id-xxx",
"createdAt": 1714000000
}
],
"total": 100
}
}
Note
latency单位是纳秒,前端显示时需转换:(latency / 1000000).toFixed(0) + 'ms'
删除日志
POST /api/sys/log/delete
{ "ids": ["log-id-1", "log-id-2"] }
四、前端接入参考
4.1 Axios 封装建议
import axios from 'axios'
const request = axios.create({
baseURL: 'http://192.168.100.4:8888', // 网关地址
timeout: 10000,
})
// 请求拦截器
request.interceptors.request.use((config) => {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
config.headers['X-Client-Id'] = 'sundynix-admin' // 你的客户端标识
return config
})
// 响应拦截器
request.interceptors.response.use((response) => {
// Token 自动续期
const newToken = response.headers['x-refresh-token']
if (newToken) {
localStorage.setItem('token', newToken)
}
const { code, msg, data } = response.data
if (code === 401) {
// 跳转登录
window.location.href = '/login'
return Promise.reject(new Error(msg))
}
if (code !== 200) {
return Promise.reject(new Error(msg))
}
return data
})
export default request
4.2 API 分组
// api/auth.ts
export const authApi = {
captcha: () => request.get('/api/auth/captcha'),
login: (data: LoginReq) => request.post('/api/auth/login', data),
getUserInfo: () => request.get('/api/auth/info'),
updateUser: (data: UpdateUserReq) => request.post('/api/auth/update', data),
}
// api/system.ts
export const clientApi = {
list: (data: PageReq) => request.post('/api/sys/client/list', data),
create: (data: ClientReq) => request.post('/api/sys/client/create', data),
update: (data: ClientUpdateReq) => request.post('/api/sys/client/update', data),
delete: (ids: string[]) => request.post('/api/sys/client/delete', { ids }),
}
export const roleApi = {
list: (data: PageReq) => request.post('/api/sys/role/list', data),
create: (data: RoleReq) => request.post('/api/sys/role/create', data),
update: (data: RoleUpdateReq) => request.post('/api/sys/role/update', data),
delete: (ids: string[]) => request.post('/api/sys/role/delete', { ids }),
}
export const menuApi = {
list: () => request.get('/api/sys/menu/list'),
byRole: (id: string) => request.post('/api/sys/menu/byRole', { id }),
create: (data: MenuReq) => request.post('/api/sys/menu/create', data),
update: (data: MenuUpdateReq) => request.post('/api/sys/menu/update', data),
delete: (ids: string[]) => request.post('/api/sys/menu/delete', { ids }),
}
export const userApi = {
list: (data: UserListReq) => request.post('/api/sys/user/list', data),
create: (data: UserCreateReq) => request.post('/api/sys/user/create', data),
update: (data: UserUpdateReq) => request.post('/api/sys/user/update', data),
delete: (ids: string[]) => request.post('/api/sys/user/delete', { ids }),
resetPassword: (data: ResetPasswordReq) => request.post('/api/sys/user/resetPassword', data),
}
export const dictApi = {
list: (data: DictListReq) => request.post('/api/sys/dict/list', data),
create: (data: DictReq) => request.post('/api/sys/dict/create', data),
update: (data: DictUpdateReq) => request.post('/api/sys/dict/update', data),
delete: (ids: string[]) => request.post('/api/sys/dict/delete', { ids }),
}
export const logApi = {
list: (data: LogListReq) => request.post('/api/sys/log/list', data),
delete: (ids: string[]) => request.post('/api/sys/log/delete', { ids }),
}
4.3 TypeScript 类型定义
// ========== Auth ==========
interface LoginReq {
account: string
password: string
captchaId: string
captcha: string
}
interface LoginResp {
token: string
userInfo: UserInfo
}
interface UserInfo {
id: string
name: string
account: string
nickName: string
phone: string
avatarId: string
gender: number // 0=未知 1=男 2=女
roles?: string[] // 角色 code 列表(仅 /info 接口返回)
menus?: MenuItem[] // 菜单树(仅 /info 接口返回)
createdAt?: number // Unix 时间戳(秒)
}
interface MenuItem {
id: string
parentId: string
category: number // 1=菜单 2=按钮
name: string // 路由名(英文)
title: string // 显示标题(中文)
code: string
path: string
permission: string
locale: string
icon: string
sort: number
children: MenuItem[]
}
// ========== System ==========
interface ClientInfo {
id: string
clientId: string
name: string
grantType: string
additionalInfo: string
activeTimeout: number // Token有效期(秒)
}
interface RoleInfo {
id: string
name: string
code: string
sort: number
menuIds: string[]
}
interface DictInfo {
id: string
type: string
label: string
value: string
sort: number
desc: string
}
interface OperationRecordInfo {
id: string
clientId: string
ip: string
method: string
path: string
status: number
latency: number // 纳秒
agent: string
errorMessage: string
body: string
resp: string
userId: string
createdAt: number // Unix 时间戳(秒)
}
// ========== 通用 ==========
interface PageReq {
current?: number
pageSize?: number
}
interface PageResp<T> {
list: T[]
total: number
}
五、接口速查表
| 模块 | 方法 | 路径 | 鉴权 | 说明 |
|---|---|---|---|---|
| Auth | GET | /api/auth/captcha |
❌ | 获取验证码 |
| POST | /api/auth/login |
❌ | 账号密码登录 | |
| POST | /api/auth/miniLogin |
❌ | 小程序登录 | |
| POST | /api/auth/loginByPhone |
❌ | 手机号登录 | |
| GET | /api/auth/info |
✅ | 获取用户信息+角色+菜单 | |
| POST | /api/auth/update |
✅ | 更新个人信息 | |
| 客户端 | POST | /api/sys/client/create |
✅ | 创建客户端 |
| POST | /api/sys/client/update |
✅ | 更新客户端 | |
| POST | /api/sys/client/delete |
✅ | 删除客户端 | |
| POST | /api/sys/client/list |
✅ | 客户端列表 | |
| 角色 | POST | /api/sys/role/create |
✅ | 创建角色 |
| POST | /api/sys/role/update |
✅ | 更新角色 | |
| POST | /api/sys/role/delete |
✅ | 删除角色 | |
| POST | /api/sys/role/list |
✅ | 角色列表 | |
| 菜单 | POST | /api/sys/menu/create |
✅ | 创建菜单 |
| POST | /api/sys/menu/update |
✅ | 更新菜单 | |
| POST | /api/sys/menu/delete |
✅ | 删除菜单 | |
| GET | /api/sys/menu/list |
✅ | 菜单列表(树形) | |
| POST | /api/sys/menu/byRole |
✅ | 按角色查菜单 | |
| 用户 | POST | /api/sys/user/list |
✅ | 用户列表 |
| POST | /api/sys/user/create |
✅ | 创建用户 | |
| POST | /api/sys/user/update |
✅ | 更新用户 | |
| POST | /api/sys/user/delete |
✅ | 删除用户 | |
| POST | /api/sys/user/resetPassword |
✅ | 重置密码 | |
| 字典 | POST | /api/sys/dict/create |
✅ | 创建字典 |
| POST | /api/sys/dict/update |
✅ | 更新字典 | |
| POST | /api/sys/dict/delete |
✅ | 删除字典 | |
| POST | /api/sys/dict/list |
✅ | 字典列表 | |
| 日志 | POST | /api/sys/log/list |
✅ | 操作日志列表 |
| POST | /api/sys/log/delete |
✅ | 删除日志 |