19 KiB
19 KiB
云印享 - 前端 API 使用指南
本文档面向前端开发者,详细说明如何调用云印享后端 API 接口。后端基于 gRPC 构建,前端通过 HTTP RESTful 风格接口进行通信。
目录
基础配置
API 基础地址
API 地址配置在 src/config/api.ts 中:
const DEV_API_URL = "http://localhost:8080";
const PROD_API_URL = "http://localhost:8080";
export const API_BASE_URL =
process.env.NODE_ENV === "development" ? DEV_API_URL : PROD_API_URL;
请求封装
项目已封装统一的请求工具 src/utils/request.ts,自动处理:
- Token 注入(Bearer 认证)
- 401 未授权处理(自动登出)
- 错误捕获
// 使用示例
import { request } from "../utils/request";
const response = await request({
url: "/auth/userinfo",
method: "GET",
});
统一响应格式
所有 API 返回遵循统一格式:
interface ApiResponse<T = any> {
code: number; // 状态码,0 表示成功
message: string; // 响应消息
data: T; // 实际数据
}
认证服务 (Auth)
基础路径: /auth
1. 微信登录
获取用户访问令牌。
| 项目 | 说明 |
|---|---|
| 接口地址 | POST /auth/login |
| 请求参数 | { code: string } - 微信登录凭证 code |
| 返回数据 | { accessToken: string; refreshToken: string; userInfo: UserInfo } |
代码示例:
import { authApi } from "./api/auth";
// 调用登录接口
const response = await authApi.login(wxCode);
// response.accessToken // 访问令牌
// response.refreshToken // 刷新令牌
// response.userInfo // 用户信息
响应示例:
{
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "dGhpcyBpcyBhIHJlZnJl...",
"userInfo": {
"id": 1,
"openid": "oXXXX-xxxxx",
"nickname": "用户昵称",
"avatar": "https://xxx.com/avatar.jpg",
"balance": 10.5,
"createdAt": "2024-01-01T00:00:00Z"
}
}
2. 刷新 Token
使用刷新令牌获取新的访问令牌。
| 项目 | 说明 |
|---|---|
| 接口地址 | POST /auth/refresh |
| 请求参数 | { refreshToken: string } |
| 返回数据 | { accessToken: string } |
代码示例:
const { accessToken } = await authApi.refreshToken(refreshToken);
3. 获取用户信息
获取当前登录用户的详细信息。
| 项目 | 说明 |
|---|---|
| 接口地址 | GET /auth/userinfo |
| 请求参数 | 无 |
| 返回数据 | UserInfo |
代码示例:
const userInfo = await authApi.getUserInfo();
console.log(userInfo.nickname, userInfo.balance);
4. 更新用户信息
更新用户昵称和头像。
| 项目 | 说明 |
|---|---|
| 接口地址 | POST /auth/update |
| 请求参数 | { nickname?: string; avatar?: string } |
| 返回数据 | UserInfo |
代码示例:
const updatedUser = await authApi.updateUser({
nickname: "新昵称",
avatar: "https://new-avatar.jpg",
});
5. 手机号登录
使用手机号和短信验证码登录。
| 项目 | 说明 |
|---|---|
| 接口地址 | POST /auth/phone/login |
| 请求参数 | { phone: string; code: string } |
| 返回数据 | { accessToken: string; refreshToken: string; userInfo: UserInfo } |
代码示例:
import { authApi } from "./api/auth";
// 调用手机号登录接口
const response = await authApi.phoneLogin({
phone: "13800138000",
code: "123456",
});
6. 发送短信验证码
发送短信验证码到指定手机号。
| 项目 | 说明 |
|---|---|
| 接口地址 | POST /auth/sms/code |
| 请求参数 | { phone: string } |
| 返回数据 | void |
代码示例:
import { authApi } from "./api/auth";
// 发送短信验证码
await authApi.sendSmsCode({ phone: "13800138000" });
文件管理服务 (File)
基础路径: /file
1. 上传文件
支持分片上传,使用 Taro 原生上传能力。
| 项目 | 说明 |
|---|---|
| 接口地址 | POST /file/upload |
| 请求参数 | filePath: string - 本地文件路径 |
| 返回数据 | { fileId: number; fileUrl: string } |
代码示例:
import { fileApi } from "./api/file";
// 上传文件
const result = await fileApi.upload(tempFilePath);
console.log(result.fileId, result.fileUrl);
2. 获取文件列表
分页获取用户上传的文件列表。
| 项目 | 说明 |
|---|---|
| 接口地址 | GET /file/list |
| 请求参数 | { page?: number; pageSize?: number } - 默认 page=1, pageSize=20 |
| 返回数据 | { files: FileInfo[]; total: number } |
代码示例:
const { files, total } = await fileApi.getFileList(1, 20);
3. 获取文件详情
| 项目 | 说明 |
|---|---|
| 接口地址 | GET /file/:fileId |
| 请求参数 | fileId: number |
| 返回数据 | FileInfo |
代码示例:
const fileInfo = await fileApi.getFile(123);
4. 删除文件
| 项目 | 说明 |
|---|---|
| 接口地址 | DELETE /file/:fileId |
| 请求参数 | fileId: number |
| 返回数据 | void |
代码示例:
await fileApi.deleteFile(123);
5. 添加水印
| 项目 | 说明 |
|---|---|
| 接口地址 | POST /file/:fileId/watermark |
| 请求参数 | fileId: number, { watermark: string } |
| 返回数据 | { watermarkUrl: string } |
代码示例:
const { watermarkUrl } = await fileApi.addWatermark(123, "仅供打印使用");
订单服务 (Order)
基础路径: /order
1. 创建订单
| 项目 | 说明 |
|---|---|
| 接口地址 | POST /order/create |
| 请求参数 | CreateOrderRequest |
| 返回数据 | Order |
请求参数结构:
{
fileId: number; // 文件ID
printerId: number; // 打印机ID
printType: "A4" | "A3" | "照片"; // 打印类型
colorType: "黑白" | "彩色"; // 颜色类型
copies: number; // 份数
}
代码示例:
import { orderApi } from "./api/order";
const order = await orderApi.createOrder({
fileId: 123,
printerId: 1,
printType: "A4",
colorType: "黑白",
copies: 2,
});
2. 获取订单详情
| 项目 | 说明 |
|---|---|
| 接口地址 | GET /order/:orderId |
| 请求参数 | orderId: number |
| 返回数据 | Order |
代码示例:
const order = await orderApi.getOrder(456);
3. 获取订单列表
| 项目 | 说明 |
|---|---|
| 接口地址 | GET /order/list |
| 请求参数 | { page?: number; pageSize?: number } |
| 返回数据 | { orders: Order[]; total: number } |
代码示例:
const { orders, total } = await orderApi.getOrderList(1, 10);
4. 更新订单状态
| 项目 | 说明 |
|---|---|
| 接口地址 | PUT /order/:orderId/status |
| 请求参数 | orderId: number, { status: number } |
| 返回数据 | Order |
订单状态枚举:
| 值 | 状态 |
|---|---|
| 0 | 待支付 |
| 1 | 已支付 |
| 2 | 打印中 |
| 3 | 已完成 |
| 4 | 已取消 |
代码示例:
await orderApi.updateOrderStatus(456, 1); // 标记为已支付
5. 取消订单
| 项目 | 说明 |
|---|---|
| 接口地址 | PUT /order/:orderId/cancel |
| 请求参数 | orderId: number |
| 返回数据 | Order |
代码示例:
await orderApi.cancelOrder(456);
打印服务 (Print)
基础路径: /print
1. 获取打印机列表
| 项目 | 说明 |
|---|---|
| 接口地址 | GET /print/printers |
| 请求参数 | 无 |
| 返回数据 | Printer[] |
代码示例:
import { printerApi } from "./api/printer";
const printers = await printerApi.getPrinters();
2. 获取打印机状态
| 项目 | 说明 |
|---|---|
| 接口地址 | GET /print/printer/:printerId/status |
| 请求参数 | printerId: number |
| 返回数据 | Printer |
打印机状态枚举:
| 值 | 状态 |
|---|---|
| 0 | 空闲 |
| 1 | 打印中 |
| 2 | 离线 |
代码示例:
const printer = await printerApi.getPrinterStatus(1);
3. 注册打印机
| 项目 | 说明 |
|---|---|
| 接口地址 | POST /print/printer/register |
| 请求参数 | { name: string; location: string } |
| 返回数据 | Printer |
代码示例:
const printer = await printerApi.registerPrinter("打印机1", "一楼大厅");
4. 提交打印任务
| 项目 | 说明 |
|---|---|
| 接口地址 | POST /print/job/submit |
| 请求参数 | { orderId: number; printerId: number } |
| 返回数据 | { jobId: number } |
代码示例:
const { jobId } = await printerApi.submitPrintJob(456, 1);
5. 取消打印任务
| 项目 | 说明 |
|---|---|
| 接口地址 | PUT /print/job/:jobId/cancel |
| 请求参数 | jobId: number |
| 返回数据 | void |
代码示例:
await printerApi.cancelPrintJob(789);
支付服务 (Pay)
基础路径: /pay
1. 创建微信支付订单
| 项目 | 说明 |
|---|---|
| 接口地址 | POST /pay/create |
| 请求参数 | { orderId: number } |
| 返回数据 | { prepayId: string; paySign: string; timeStamp: string; nonceStr: string; signType: string } |
代码示例:
import { payApi } from "./api/pay";
const payParams = await payApi.createWxPayOrder(456);
// 使用返回参数调起微信支付
2. 查询支付状态
| 项目 | 说明 |
|---|---|
| 接口地址 | GET /pay/query/:orderId |
| 请求参数 | orderId: number |
| 返回数据 | { status: number } |
支付状态枚举:
| 值 | 状态 |
|---|---|
| 0 | 待支付 |
| 1 | 支付中 |
| 2 | 成功 |
| 3 | 失败 |
代码示例:
const { status } = await payApi.queryPayStatus(456);
3. 余额支付
| 项目 | 说明 |
|---|---|
| 接口地址 | POST /pay/balance |
| 请求参数 | { orderId: number } |
| 返回数据 | { success: boolean } |
代码示例:
const { success } = await payApi.payByBalance(456);
价目表服务 (Price)
基础路径: /price
1. 获取价目表
| 项目 | 说明 |
|---|---|
| 接口地址 | GET /price/list |
| 请求参数 | 无 |
| 返回数据 | PriceItem[] |
代码示例:
import { priceApi } from "./api/price";
const priceList = await priceApi.getPriceList();
价目表示例:
[
{ "id": 1, "name": "A4黑白打印", "type": "A4", "price": 0.1, "unit": "页" },
{ "id": 2, "name": "A4彩色打印", "type": "A4", "price": 0.3, "unit": "页" },
{ "id": 3, "name": "A3黑白打印", "type": "A3", "price": 0.2, "unit": "页" },
{ "id": 4, "name": "A3彩色打印", "type": "A3", "price": 0.6, "unit": "页" },
{ "id": 5, "name": "照片打印", "type": "照片", "price": 2.0, "unit": "张" }
]
错误处理
HTTP 状态码
| 状态码 | 说明 | 处理建议 |
|---|---|---|
| 200 | 请求成功 | 正常处理响应数据 |
| 400 | 请求参数错误 | 检查请求参数格式 |
| 401 | 未授权 | Token 过期或无效,需重新登录 |
| 403 | 禁止访问 | 权限不足 |
| 404 | 资源不存在 | 检查请求的资源 ID |
| 500 | 服务器内部错误 | 联系后端排查 |
统一错误处理
request.ts 已封装错误处理逻辑:
try {
const result = await orderApi.createOrder(orderData);
} catch (error) {
if (error.message === "Unauthorized") {
// 处理未授权,跳转登录
Taro.redirectTo({ url: "/pages/login/index" });
} else {
// 显示错误提示
Taro.showToast({ title: error.message, icon: "none" });
}
}
注意事项
1. 认证机制
- 所有需要用户身份的接口都需要在请求头中携带
Authorization: Bearer <token> - Token 由
request.ts自动注入,无需手动处理 - Token 过期时,服务器返回 401,前端自动触发登出
2. 文件上传
- 使用 Taro 原生
uploadFileAPI,支持断点续传 - 上传成功后返回
fileId和fileUrl,用于后续订单创建
3. 分页查询
- 文件列表和订单列表接口支持分页
- 默认
page=1,pageSize=20 - 响应中包含
total字段表示总记录数
4. 状态枚举
- 订单状态、支付状态、打印机状态均使用数字枚举
- 类型定义文件(如
order.ts)中提供了状态映射表,便于显示
5. 数据格式
- 所有时间字段使用 ISO 8601 格式字符串(如
"2024-01-01T12:00:00Z") - 价格字段使用数字类型,单位为元(如
0.10表示 0.1 元)
6. 开发环境配置
- 开发环境 API 地址:
http://localhost:8080 - 确保后端服务已启动且端口正确
- 如需修改地址,编辑
src/config/api.ts
7. 类型安全
- 所有 API 接口都有完整的 TypeScript 类型定义
- 导入对应的类型文件(如
import type { Order } from '../types') - 使用类型提示可以减少运行时错误
快速开始示例
以下是一个完整的打印流程示例:
import { authApi } from "./api/auth";
import { fileApi } from "./api/file";
import { orderApi } from "./api/order";
import { printerApi } from "./api/printer";
import { payApi } from "./api/pay";
// 1. 登录
const { accessToken, userInfo } = await authApi.login(wxCode);
// 2. 上传文件
const { fileId } = await fileApi.upload(tempFilePath);
// 3. 获取打印机列表
const printers = await printerApi.getPrinters();
const availablePrinter = printers.find((p) => p.status === 0);
// 4. 创建订单
const order = await orderApi.createOrder({
fileId,
printerId: availablePrinter.id,
printType: "A4",
colorType: "黑白",
copies: 2,
});
// 5. 发起支付
const payParams = await payApi.createWxPayOrder(order.id);
// 调起微信支付...
// 6. 查询支付状态
const { status } = await payApi.queryPayStatus(order.id);
if (status === 2) {
// 支付成功,提交打印任务
await printerApi.submitPrintJob(order.id, availablePrinter.id);
}
更新日志
- 2024-01-01: 初始版本,基于后端 README 和前端现有实现整理
文档维护: 前端开发团队
最后更新: 2024-01-01