Files
sundynix-micro-admin/API_DOCS.md
T
2026-04-30 22:53:46 +08:00

1051 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Sundynix 前端接入文档
> 网关地址:`http://{GATEWAY_HOST}:8888`
> 所有接口统一经过网关转发,前端只需对接网关地址
---
## 一、全局约定
### 1.1 统一响应格式
所有接口返回 **HTTP 200**,通过 `code` 区分业务状态:
```json
{
"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>
```
前端需要在响应拦截器中处理:
```ts
// 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
```
**响应**
```json
{
"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
```
**请求体**
```json
{
"account": "admin",
"password": "123456",
"captchaId": "abc123",
"captcha": "5xmn"
}
```
| 字段 | 必填 | 说明 |
|------|:----:|------|
| account | ✅ | 账号 |
| password | ✅ | 密码 |
| captchaId | ✅ | 验证码 ID(从 captcha 接口获取) |
| captcha | ✅ | 用户输入的验证码 |
**响应**
```json
{
"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
```
**请求体**
```json
{
"code": "wx_login_code_from_wx.login()",
"clientId": "mini-app"
}
```
**响应**:同 2.2 的响应格式
---
### 2.4 手机号登录
> 🔓 无需鉴权
```
POST /api/auth/loginByPhone
```
**请求体**
```json
{
"code": "phone_code_from_getPhoneNumber",
"openId": "用户openId",
"clientId": "mini-app"
}
```
**响应**:同 2.2 的响应格式
---
### 2.5 获取当前用户信息(含角色、菜单)
> 🔒 需要鉴权
```
GET /api/auth/info
```
**响应**
```json
{
"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
```
**请求体**(所有字段可选,只传需要修改的):
```json
{
"name": "李四",
"nickName": "小李",
"phone": "13900139000",
"avatarId": "new-file-id"
}
```
**响应**
```json
{ "code": 200, "msg": "success" }
```
---
## 三、System 服务(`/api/sys`
> [!IMPORTANT]
> 以下所有接口均需要鉴权(`Authorization: Bearer <token>`
---
### 3.1 客户端管理
#### 创建客户端
```
POST /api/sys/client/create
```
```json
{
"clientId": "sundynix-admin",
"name": "Web管理端",
"grantType": "password",
"additionalInfo": "",
"activeTimeout": 7200
}
```
| 字段 | 必填 | 说明 |
|------|:----:|------|
| clientId | ✅ | 客户端唯一标识 |
| name | ✅ | 客户端名称 |
| grantType | ❌ | 授权类型 |
| additionalInfo | ❌ | 附加信息 |
| activeTimeout | ❌ | Token 有效期(秒),默认 7200 |
#### 更新客户端
```
POST /api/sys/client/update
```
```json
{
"id": "客户端记录ID",
"name": "新名称",
"activeTimeout": 3600
}
```
#### 删除客户端
```
POST /api/sys/client/delete
```
```json
{ "ids": ["id1", "id2"] }
```
#### 客户端列表
```
POST /api/sys/client/list
```
```json
{
"current": 1,
"pageSize": 10,
"name": ""
}
```
**响应**
```json
{
"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
```
```json
{
"name": "管理员",
"code": "admin",
"sort": 1,
"menuIds": ["menu-id-1", "menu-id-2"]
}
```
#### 更新角色
```
POST /api/sys/role/update
```
```json
{
"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
```
```json
{ "ids": ["role-id-1"] }
```
#### 角色列表
```
POST /api/sys/role/list
```
```json
{
"current": 1,
"pageSize": 10,
"name": ""
}
```
**响应**
```json
{
"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
```
```json
{
"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
```
```json
{
"id": "菜单ID",
"title": "新标题",
"sort": 2
}
```
#### 删除菜单
```
POST /api/sys/menu/delete
```
```json
{ "ids": ["menu-id-1"] }
```
> [!WARNING]
> 删除菜单会同步清除该菜单与所有角色的关联关系
#### 菜单列表(树形)
```
GET /api/sys/menu/list
```
无参数。返回完整的树形菜单结构。
**响应**
```json
{
"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
```
```json
{ "id": "角色ID" }
```
**响应**:同菜单列表格式,但只包含该角色关联的菜单
---
### 3.4 用户管理(后台管理)
#### 用户列表
```
POST /api/sys/user/list
```
```json
{
"current": 1,
"pageSize": 10,
"name": "",
"account": ""
}
```
**响应**
```json
{
"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
```
```json
{
"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
```
```json
{
"id": "用户ID",
"name": "李四",
"phone": "13900139000",
"roleIds": ["role-id-1"]
}
```
#### 删除用户
```
POST /api/sys/user/delete
```
```json
{ "ids": ["user-id-1", "user-id-2"] }
```
#### 重置密码
```
POST /api/sys/user/resetPassword
```
```json
{
"id": "用户ID",
"password": "newpassword123"
}
```
---
### 3.5 字典管理
#### 创建字典
```
POST /api/sys/dict/create
```
```json
{
"type": "gender",
"label": "男",
"value": "1",
"sort": 1,
"desc": "性别-男"
}
```
#### 更新字典
```
POST /api/sys/dict/update
```
```json
{
"id": "字典ID",
"label": "女",
"value": "2"
}
```
#### 删除字典
```
POST /api/sys/dict/delete
```
```json
{ "ids": ["dict-id-1"] }
```
#### 字典列表
```
POST /api/sys/dict/list
```
```json
{
"current": 1,
"pageSize": 10,
"type": "gender"
}
```
**响应**
```json
{
"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
```
```json
{
"current": 1,
"pageSize": 20,
"method": "POST",
"path": "/api/auth/login",
"status": 200
}
```
**响应**
```json
{
"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
```
```json
{ "ids": ["log-id-1", "log-id-2"] }
```
---
## 四、前端接入参考
### 4.1 Axios 封装建议
```ts
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 分组
```ts
// 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 类型定义
```ts
// ========== 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` | ✅ | 删除日志 |