前端对接参考
通用规范
请求头
所有需认证的接口:
Authorization: Bearer <token>
Content-Type: application/json
响应格式
{
"code": 200,
"message": "错误信息(仅失败时存在)",
"data": {}
}
code与 HTTP 状态码一致:200/400/401/403/404/500- 成功时
data为业务数据,写操作成功时data为 null - 失败时
message为可展示的错误描述
分页响应格式
所有列表接口统一返回:
{
"code": 200,
"data": {
"data": [],
"total": 100,
"page": 1,
"page_size": 10,
"total_pages": 10
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
| data | array | 当前页数据 |
| total | int64 | 总记录数 |
| page | int | 当前页码(从 1 开始) |
| page_size | int | 每页数量 |
| total_pages | int | 总页数 |
分页请求参数
所有列表接口通用:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| page | int | 1 | 页码,最小 1 |
| page_size | int | 10 | 每页数量,范围 1-100 |
| keyword | string | - | 模糊搜索关键词 |
| sort_by | string | id | 排序字段(各接口不同,见下方) |
| sort_desc | string | false | 是否降序,传 "true" |
认证
注册
POST /auth/register
{
"username": "admin",
"password": "123456",
"role_ids": [1]
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| username | string | Y | 用户名,唯一 |
| password | string | Y | 密码,最少 6 位 |
| role_ids | uint[] | N | 角色 ID 列表,不传默认 staff;第一个用户自动 admin |
成功响应 data 为 User 对象。
登录
POST /auth/login
{
"username": "admin",
"password": "123456"
}
响应:
{
"code": 200,
"data": { "token": "eyJhbGciOi..." }
}
| HTTP | code | message | 场景 |
|---|---|---|---|
| 200 | 200 | - | 成功 |
| 401 | 401 | invalid username or password | 用户名或密码错误 |
| 403 | 403 | user is disabled | 账号被禁用 |
Token 过期时间 24 小时。前端应在 401 时跳转登录页。
获取当前用户
GET /auth/me
响应:
{
"code": 200,
"data": { "id": 1, "username": "admin" }
}
注销
POST /auth/logout
用户管理
所有用户接口需 admin 角色。
用户列表
GET /users
查询参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| keyword | string | - | 按 username 模糊搜索 |
| sort_by | string | id | 可选:id, username, status, created_at |
| sort_desc | string | false | 传 "true" 降序 |
| page | int | 1 | 页码 |
| page_size | int | 10 | 每页数量 |
响应示例:
{
"code": 200,
"data": {
"data": [
{
"id": 1,
"username": "admin",
"status": "active",
"roles": [{"id": 1, "name": "admin", "description": "系统管理员"}],
"created_at": "2026-04-29T12:00:00Z",
"updated_at": "2026-04-29T12:00:00Z"
}
],
"total": 10,
"page": 1,
"page_size": 10,
"total_pages": 1
}
}
User 对象字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | uint | 用户 ID |
| username | string | 用户名 |
| status | string | 状态:active / disabled |
| roles | Role[] | 角色列表 |
| created_at | string | 创建时间 RFC3339 |
| updated_at | string | 更新时间 RFC3339 |
注意:password 字段不会在 JSON 中返回。
获取单个用户
GET /users/:id
| HTTP | code | message |
|---|---|---|
| 200 | 200 | - |
| 400 | 400 | invalid id |
| 404 | 404 | user not found |
修改用户状态
PUT /users/:id/status
{ "status": "disabled" }
status 取值:active / disabled
| HTTP | code | message |
|---|---|---|
| 200 | 200 | - |
| 400 | 400 | invalid id |
| 400 | 400 | invalid request body |
| 400 | 400 | invalid status |
分配角色
PUT /users/:id/roles
{ "role_ids": [1, 2] }
role_ids 为完整的角色 ID 列表,会替换现有角色(不是增量追加)。
| HTTP | code | message |
|---|---|---|
| 200 | 200 | - |
| 400 | 400 | invalid id |
| 400 | 400 | invalid request body |
角色 ID 参考:
| ID | name | 说明 |
|---|---|---|
| 1 | admin | 系统管理员 |
| 2 | manager | 部门经理 |
| 3 | staff | 普通员工 |
可通过 GET /roles 获取完整角色列表。
修改/重置密码
PUT /users/:id/password
admin 操作(重置他人密码):
{ "new_password": "654321" }
仅需 new_password,最少 6 位。
非 admin 操作(修改自己密码):
{
"old_password": "123456",
"new_password": "654321"
}
需同时提供 old_password 和 new_password。
| HTTP | code | message |
|---|---|---|
| 200 | 200 | - |
| 400 | 400 | invalid id |
| 400 | 400 | invalid request body |
| 400 | 400 | wrong old password |
| 403 | 403 | forbidden |
删除用户
DELETE /users/:id
| HTTP | code | message |
|---|---|---|
| 200 | 200 | - |
| 400 | 400 | invalid id |
| 400 | 400 | cannot delete yourself |
前端应在删除前判断是否为当前登录用户,给出禁用/提示。
部门管理
部门列表
GET /depts
查询参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| keyword | string | - | 按 name 模糊搜索 |
| sort_by | string | id | 可选:id, name |
| sort_desc | string | false | 传 "true" 降序 |
| page | int | 1 | 页码 |
| page_size | int | 10 | 每页数量 |
部门树
GET /depts/tree
返回完整树结构,一次性加载。适合侧边栏/下拉框等场景。
{
"code": 200,
"data": [
{
"id": 1,
"name": "研发部",
"description": "...",
"parent_id": null,
"children": [...]
}
]
}
创建部门
POST /depts
需要 admin 或 manager(部门负责人)角色。
{
"name": "研发部",
"description": "负责产品研发",
"leader_id": 3,
"parent_id": null
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | Y | 名称,唯一 |
| description | string | N | 描述 |
| leader_id | uint | N | 负责人 Employee ID |
| parent_id | uint | N | 父部门 ID,null 为顶级 |
更新部门
PUT /depts/:id
只传需要更新的字段。更新 parent_id 时校验循环引用。
删除部门
DELETE /depts/:id
仅 admin。有子部门或有员工时不可删除(code 400)。
员工管理
员工列表
GET /employees
查询参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| keyword | string | - | 按 name/email/phone/id_number 模糊搜索 |
| sort_by | string | id | 可选:id, name, email, phone, status, created_at |
| sort_desc | string | false | 传 "true" 降序 |
| page | int | 1 | 页码 |
| page_size | int | 10 | 每页数量 |
admin 可看全部,manager 看本部门+子部门,staff 无权限(403)。
获取自己的员工档案
GET /employees/me
所有角色可访问。未关联员工档案时返回 404。
创建员工
POST /employees
需要 admin 或 manager(部门负责人)角色。
{
"name": "张伟",
"email": "zhangwei@pms.com",
"phone": "13800000001",
"id_number": "110101199001011234",
"dept_id": 1,
"user_id": 2,
"status": "active"
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | Y | 姓名 |
| string | Y | 邮箱,唯一 | |
| phone | string | N | 手机号 |
| id_number | string | N | 身份证号 |
| dept_id | uint | Y | 部门 ID |
| user_id | uint | N | 关联登录账号 ID,一个 User 最多关联一个 Employee |
| status | string | N | 默认 active |
Employee 对象包含 department 关联字段(Preload),可直接取部门名称。
更新员工
PUT /employees/:id
只传需要更新的字段。更新 dept_id 和 email 时有存在性校验。
删除员工
DELETE /employees/:id
仅 admin。
薪资管理
所有薪资接口需 admin 角色。
薪资结构列表
GET /salaries/structures
查询参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| keyword | string | - | 按员工姓名/邮箱搜索 |
| sort_by | string | id | 可选:id, base_salary, position_allowance, performance_factor, created_at |
| sort_desc | string | false | 降序 |
| page | int | 1 | 页码 |
| page_size | int | 10 | 每页数量 |
创建薪资结构
POST /salaries/structures
{
"employee_id": 1,
"base_salary": 10000,
"position_allowance": 2000,
"performance_factor": 1.0
}
每个员工只能有一个薪资结构。
查询员工薪资结构
GET /salaries/structures/employees/:emp_id
更新/删除薪资结构
PUT /salaries/structures/:id
DELETE /salaries/structures/:id
薪资记录列表
GET /salaries/records
新增筛选参数(在通用分页基础上):
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| employee_id | int | - | 按员工 ID |
| year | int | - | 按年份 |
| month | int | - | 按月份 |
| status | string | - | draft/pending/approved/rejected/paid |
| sort_by | string | id | 可选:id, year, month, actual_salary, status, created_at |
生成薪资记录
POST /salaries/records
{
"employee_id": 1,
"year": 2026,
"month": 4,
"performance_factor": 1.0
}
批量生成
POST /salaries/records/batch
{
"year": 2026,
"month": 4,
"employee_ids": [1, 2, 3]
}
employee_ids 和 dept_id 可选,优先级:employee_ids > dept_id > 全部。
修改薪资记录
PUT /salaries/records/:id
仅 draft 或 rejected 状态可修改。修改 performance_factor 时自动重算 actual_salary。
{ "performance_factor": 1.3 }
| HTTP | code | message |
|---|---|---|
| 200 | 200 | - |
| 400 | 400 | invalid id |
| 400 | 400 | salary record is not in draft/rejected status |
| 404 | 404 | salary record not found |
查询单条薪资记录
GET /salaries/records/:id
| HTTP | code | message |
|---|---|---|
| 200 | 200 | - |
| 400 | 400 | invalid id |
| 404 | 404 | salary record not found |
薪资记录状态流转
PUT /salaries/records/:id/submit draft/rejected → pending
PUT /salaries/records/:id/approve pending → approved
PUT /salaries/records/:id/reject pending → rejected
PUT /salaries/records/:id/pay approved → paid
状态流转图:
draft → pending → approved → paid
↑ ↓
└── rejected
考勤管理
打卡
POST /attendance/clock-in 上班打卡
PUT /attendance/clock-out 下班打卡
{ "employee_id": 1 }
staff 只能为自己打卡(后端校验 JWT employee_id),admin/manager 可为任意员工打卡。
打卡记录列表
GET /attendance/records
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| employee_id | int | - | 按员工 |
| start_date | string | - | 起始日期 YYYY-MM-DD |
| end_date | string | - | 结束日期 YYYY-MM-DD |
| keyword | string | - | 按员工姓名/邮箱搜索 |
| sort_by | string | date | 可选:id, date, created_at |
| sort_desc | string | false | 降序 |
| page | int | 1 | 页码 |
| page_size | int | 10 | 每页数量 |
查询单条打卡记录
GET /attendance/records/:id
| HTTP | code | message |
|---|---|---|
| 200 | 200 | - |
| 404 | 404 | attendance record not found |
生成考勤统计
POST /attendance/summaries/generate
{ "employee_id": 1, "year": 2026, "month": 4 }
需要 admin/manager 角色。重复生成会覆盖。
考勤统计列表
GET /attendance/summaries
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| employee_id | int | - | 按员工 |
| year | int | - | 按年份 |
| month | int | - | 按月份 |
| sort_by | string | id | 可选:id, year, month, created_at |
| sort_desc | string | false | 降序 |
| page | int | 1 | 页码 |
| page_size | int | 10 | 每页数量 |
请假管理
提交请假
POST /leaves
{
"employee_id": 1,
"type": "annual",
"start_date": "2026-05-01",
"end_date": "2026-05-03",
"reason": "年假"
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| employee_id | uint | Y | 员工 ID |
| type | string | Y | annual/sick/personal |
| start_date | string | Y | 开始日期 YYYY-MM-DD |
| end_date | string | Y | 结束日期 YYYY-MM-DD,需 >= start_date |
| reason | string | N | 请假原因 |
staff 只能为本人申请。
请假列表
GET /leaves
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| employee_id | int | - | 按员工 |
| status | string | - | pending/approved/rejected |
| keyword | string | - | 按员工姓名/邮箱搜索 |
| sort_by | string | id | 可选:id, type, status, start_date, created_at |
| sort_desc | string | false | 降序 |
| page | int | 1 | 页码 |
| page_size | int | 10 | 每页数量 |
查询单条请假申请
GET /leaves/:id
| HTTP | code | message |
|---|---|---|
| 200 | 200 | - |
| 404 | 404 | leave request not found |
审批
PUT /leaves/:id/approve
PUT /leaves/:id/reject
需 admin/manager(部门负责人)角色。manager 只能审批本部门范围。
角色列表
GET /roles
所有认证用户可访问。返回固定三种角色:
{
"code": 200,
"data": [
{"id": 1, "name": "admin", "description": "系统管理员"},
{"id": 2, "name": "manager", "description": "部门经理"},
{"id": 3, "name": "staff", "description": "普通员工"}
]
}
审计日志
需 admin 角色。
GET /audit-logs
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| operator | string | - | 按操作人 |
| entity_type | string | - | 按实体类型 |
| start_time | string | - | 起始时间 RFC3339 |
| end_time | string | - | 结束时间 RFC3339 |
| sort_by | string | id | 可选:id, created_at, action, entity_type |
| sort_desc | string | false | 降序 |
| page | int | 1 | 页码 |
| page_size | int | 10 | 每页数量 |
entity_type 取值:user, department, employee, salary_structure, salary_record, attendance_record, attendance_summary, leave_request
权限概览
| 操作 | admin | manager(部门负责人) | staff |
|---|---|---|---|
| 查看部门/部门树 | Y | Y | Y |
| 创建/编辑部门 | Y | Y(本部门范围) | - |
| 删除部门 | Y | - | - |
| 查看员工列表 | Y(全部) | Y(本部门+子部门) | - |
| /employees/me | Y | Y | Y |
| 创建/编辑员工 | Y | Y(本部门范围) | - |
| 删除员工 | Y | - | - |
| 用户管理(含删除) | Y | - | - |
| 查看角色列表 | Y | Y | Y |
| 薪资管理(全部) | Y | - | - |
| 打卡 | Y | Y | 仅自己 |
| 查看考勤记录/统计 | Y | Y | 仅自己 |
| 生成考勤统计 | Y | Y | - |
| 提交请假 | Y | Y | 仅自己 |
| 查看请假列表 | Y | Y | 仅自己 |
| 审批请假 | Y | Y(本部门范围) | - |
| 查看审计日志 | Y | - | - |
- "本部门范围" 指 manager 作为 leader_id 所属部门及其子部门
- "仅自己" 指后端强制使用 JWT 中的 employee_id,忽略请求中的 employee_id
前端权限控制建议
- 登录后从 JWT 解析
role,存储到全局状态 - 根据角色控制菜单/按钮显隐
- admin:全部功能可见
- manager:部门/员工管理(本部门范围)、考勤统计、请假审批可见;用户管理、薪资管理、审计日志不可见
- staff:仅 /employees/me、打卡(自己)、请假(自己)可见
- 所有角色:部门/部门树、角色列表只读可见
JWT Token Payload
{
"user_id": 1,
"username": "admin",
"role": "admin",
"employee_id": 3,
"jti": "xxx",
"exp": 1746000000
}
| 字段 | 类型 | 说明 |
|---|---|---|
| user_id | uint | 用户 ID |
| username | string | 用户名 |
| role | string | 角色名:admin / manager / staff |
| employee_id | *uint | 关联的员工 ID,未关联时不出现 |
| exp | int64 | 过期时间戳 |
前端可用 jwt-decode 库解析 token 获取 role 和 employee_id。