# API 文档 Base URL:`http://localhost:8080/api` ## 通用约定 所有接口均返回统一 JSON 结构: ```typescript class Response { "code": number; "message": string; "data": T | null; } ``` - `code === 200` 表示成功;**`code !== 200` 时 `data` 恒为 `null`** - 除特别标注(公开)外,接口需在请求头携带 `Authorization: Bearer ` - 下文路径均省略 `/api` 前缀,`data` 仅给出 `T` 的声明 - 部分 `/test` 接口的返回值不遵循上述格式 ## 接口总览 | 分组 | 路径前缀 | 说明 | |----------|-------------|-------------------------------------------| | 测试 | `/test` | 连通性测试 | | 认证 | `/v1/auth` | 登录 / 注册 / 验证码 / Token 管理 | | 物品管理 | `/v1/items` | 物品 / 类别 / 图片 CRUD、借还、上下架查询 | --- ## 分组:测试 `/test` ### GET /hello 公开接口。 **响应** ```typescript "Hello Kotlin WebFlux!" ``` --- ## 分组:认证 `/v1/auth` | 方法 | 路径 | 认证 | 说明 | |--------|---------------------------|------|--------------------------| | POST | `/login` | 公开 | 登录,获取 Token | | GET | `/logout` | 需要 | 注销,Token 加入黑名单 | | GET | `/ask-code` | 公开 | 发送邮箱验证码 | | POST | `/register` | 公开 | 邮箱注册 | | POST | `/reset` | 公开 | 重置密码 | | GET | `/relogin` | 需要 | 用旧 Token 换取新 Token | ### POST /login **请求参数** | 字段 | 类型 | 说明 | |----------|--------|----------| | username | string | 用户名 | | password | string | 密码 | **响应 data** ```typescript class data { "username": string; "role": string; "token": string; "expire": Date; } ``` ### GET /logout **请求参数**:无 **响应 data**:`null` ### GET /ask-code **请求参数** | 字段 | 类型 | 说明 | |-------|-----------------------------|------------------------------------| | email | string | 接收验证码的邮箱 | | type | `register` \| `reset` | 验证码用途(注册 / 重置密码) | **响应 data**:`null` ### POST /register **请求体字段**:`email`、`code`、`username`、`password` **响应 data**:`null` ### POST /reset **请求体字段**:`email`、`code`、`password` **响应 data**:`null` ### GET /relogin **请求参数**:无 **响应 data** ```typescript class data { "token": string; "expire": time; } ``` --- ## 分组:物品管理 `/v1/items` | 方法 | 路径 | 认证 | 说明 | |--------|---------------------------------|------|----------------------------------------| | GET | `/items` | 需要 | 分页查询物品 | | POST | `/items` | 需要 | 创建物品 | | PUT | `/items` | 需要 | 更新物品 | | DELETE | `/items` | 需要 | 删除物品(同时清理其图片) | | POST | `/items/{id}/upload_images` | 需要 | 上传物品图片(multipart) | | POST | `/items/{id}/set_primary_image` | 需要 | 设置物品主图 | | POST | `/items/{id}/borrow` | 需要 | 借用物品(扣减可用库存) | | POST | `/items/{id}/return_item` | 需要 | 归还物品(恢复可用库存) | | GET | `/items/available` | 需要 | 获取可用物品列表 | | GET | `/items/in_use` | 需要 | 获取使用中物品列表 | | GET | `/items/categories` | 需要 | 查询物品类别列表 | | POST | `/items/categories` | 需要 | 创建物品类别 | | PUT | `/items/categories` | 需要 | 更新物品类别 | | DELETE | `/items/categories` | 需要 | 删除物品类别 | | GET | `/items/images` | 需要 | 查询物品图片列表 | | POST | `/items/images` | 需要 | 创建物品图片 | | PUT | `/items/images` | 需要 | 更新物品图片 | | DELETE | `/items/images` | 需要 | 删除物品图片(同时删除物理文件) | ### 实体定义 ```typescript class Item { "id": number | null; "code": string; // 物品编号 / 资产编号 "name": string; "categoryId": number | null; "model": string | null; "brand": string | null; "location": string | null; "totalQuantity": number; "availableQuantity": number; "unit": string; // 默认 "件" "price": number | null; "purchaseDate": string | null; "supplier": string | null; "status": string; // normal / disabled / lost / repair "description": string | null; "imagePath": string | null; "createdBy": number | null; "createdAt": string | null; "updatedAt": string | null; } ``` ```typescript class Category { "id": number | null; "name": string; "parentId": number | null; "description": string | null; "createdAt": string | null; "updatedAt": string | null; } ``` ```typescript class Attachment { "id": number | null; "relatedTable": string | null; // 关联表名,如 "items" "relatedId": number | null; // 关联记录 ID "fileName": string | null; "filePath": string | null; "fileSize": number | null; "contentType": string | null; "uploadedBy": number | null; "uploadedAt": string | null; } ``` ```typescript class Page { "records": T[]; "total": number; "size": number; "current": number; "pages": number; } ``` ### GET /items **请求参数** | 字段 | 类型 | 说明 | |----------|---------|-----------------------------------| | pageNum | number | 页码,默认 `1` | | pageSize | number | 每页条数,默认 `10` | | keyword | string? | 按名称 / 编号模糊搜索 | | status | string? | 按状态过滤,如 `normal` | **响应 data**:`Page` ### POST /items **请求体**:`Item`(`id` / `createdAt` / `updatedAt` 由服务端填充) **响应 data**:`null` ### PUT /items **请求体**:`Item`(须包含 `id`) **响应 data**:`null` ### DELETE /items **请求参数** | 字段 | 类型 | 说明 | |------|--------|--------| | id | number | 物品 ID | **响应 data**:`null` ### POST /items/{id}/upload_images **请求**:`multipart/form-data`,字段名 `files`,可传多个图片文件 **响应 data**:`null` ### POST /items/{id}/set_primary_image **请求参数** | 字段 | 类型 | 说明 | |---------|--------|------------------------------------------| | imageId | number | 附件 ID,须属于该物品 | **响应 data**:`null` ### POST /items/{id}/borrow **请求参数** | 字段 | 类型 | 说明 | |----------|--------|-------------------| | quantity | number | 借用数量,默认 `1` | **响应 data**:`null` ### POST /items/{id}/return_item **请求参数** | 字段 | 类型 | 说明 | |----------|--------|-------------------| | quantity | number | 归还数量,默认 `1` | **响应 data**:`null` ### GET /items/available **请求参数**:无 **响应 data**:`Item[]` ### GET /items/in_use **请求参数**:无 **响应 data**:`Item[]` ### GET /items/categories **请求参数**:无 **响应 data**:`Category[]` ### POST /items/categories **请求体**:`Category`(`id` / `createdAt` / `updatedAt` 由服务端填充) **响应 data**:`null` ### PUT /items/categories **请求体**:`Category`(须包含 `id`) **响应 data**:`null` ### DELETE /items/categories **请求参数** | 字段 | 类型 | 说明 | |------|--------|----------| | id | number | 类别 ID | **响应 data**:`null` ### GET /items/images **请求参数**:无 **响应 data**:`Attachment[]`(`relatedTable` 为 `"items"` 的图片) ### POST /items/images **请求体**:`Attachment`(`id` / `uploadedAt` 由服务端填充) **响应 data**:`null` ### PUT /items/images **请求体**:`Attachment`(须包含 `id`) **响应 data**:`null` ### DELETE /items/images **请求参数** | 字段 | 类型 | 说明 | |------|--------|----------| | id | number | 图片 ID | **响应 data**:`null` --- ## 其他 ### WebSocket `ws://localhost:8080/ws` — 目前不支持