# 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 X-Client-Id: <客户端标识> ``` > [!IMPORTANT] > - `Authorization` 从登录接口获取 > - `X-Client-Id` 由后台管理端配置的客户端标识(如 `sundynix-admin`、`mini-app`) ### 1.3 Token 自动续期 网关内置**滑动窗口续期**机制。当 Token 剩余有效时间 < 1 小时时,响应头会携带新 Token: ``` X-Refresh-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 图片,直接赋给 `` | --- ### 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 `) --- ### 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 { 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` | ✅ | 删除日志 |