# 云印享 - 前端 API 使用指南 本文档面向前端开发者,详细说明如何调用云印享后端 API 接口。后端基于 gRPC 构建,前端通过 HTTP RESTful 风格接口进行通信。 ## 目录 - [基础配置](#基础配置) - [认证服务 (Auth)](#认证服务-auth) - [文件管理服务 (File)](#文件管理服务-file) - [订单服务 (Order)](#订单服务-order) - [打印服务 (Print)](#打印服务-print) - [支付服务 (Pay)](#支付服务-pay) - [价目表服务 (Price)](#价目表服务-price) - [错误处理](#错误处理) - [注意事项](#注意事项) --- ## 基础配置 ### API 基础地址 API 地址配置在 [`src/config/api.ts`](src/config/api.ts:1) 中: ```typescript 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`](src/utils/request.ts:1),自动处理: - Token 注入(Bearer 认证) - 401 未授权处理(自动登出) - 错误捕获 ```typescript // 使用示例 import { request } from "../utils/request"; const response = await request({ url: "/auth/userinfo", method: "GET", }); ``` ### 统一响应格式 所有 API 返回遵循统一格式: ```typescript interface ApiResponse { code: number; // 状态码,0 表示成功 message: string; // 响应消息 data: T; // 实际数据 } ``` --- ## 认证服务 (Auth) **基础路径**: `/auth` ### 1. 微信登录 获取用户访问令牌。 | 项目 | 说明 | | ------------ | ------------------------------------------------------------------- | | **接口地址** | `POST /auth/login` | | **请求参数** | `{ code: string }` - 微信登录凭证 code | | **返回数据** | `{ accessToken: string; refreshToken: string; userInfo: UserInfo }` | **代码示例**: ```typescript import { authApi } from "./api/auth"; // 调用登录接口 const response = await authApi.login(wxCode); // response.accessToken // 访问令牌 // response.refreshToken // 刷新令牌 // response.userInfo // 用户信息 ``` **响应示例**: ```json { "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 }` | **代码示例**: ```typescript const { accessToken } = await authApi.refreshToken(refreshToken); ``` ### 3. 获取用户信息 获取当前登录用户的详细信息。 | 项目 | 说明 | | ------------ | --------------------------------- | | **接口地址** | `GET /auth/userinfo` | | **请求参数** | 无 | | **返回数据** | [`UserInfo`](src/types/user.ts:1) | **代码示例**: ```typescript const userInfo = await authApi.getUserInfo(); console.log(userInfo.nickname, userInfo.balance); ``` ### 4. 更新用户信息 更新用户昵称和头像。 | 项目 | 说明 | | ------------ | ---------------------------------------- | | **接口地址** | `POST /auth/update` | | **请求参数** | `{ nickname?: string; avatar?: string }` | | **返回数据** | [`UserInfo`](src/types/user.ts:1) | **代码示例**: ```typescript 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 }` | **代码示例**: ```typescript import { authApi } from "./api/auth"; // 调用手机号登录接口 const response = await authApi.phoneLogin({ phone: "13800138000", code: "123456", }); ``` ### 6. 发送短信验证码 发送短信验证码到指定手机号。 | 项目 | 说明 | | ------------ | --------------------- | | **接口地址** | `POST /auth/sms/code` | | **请求参数** | `{ phone: string }` | | **返回数据** | `void` | **代码示例**: ```typescript import { authApi } from "./api/auth"; // 发送短信验证码 await authApi.sendSmsCode({ phone: "13800138000" }); ``` --- ## 文件管理服务 (File) **基础路径**: `/file` ### 1. 上传文件 支持分片上传,使用 Taro 原生上传能力。 | 项目 | 说明 | | ------------ | ------------------------------------- | | **接口地址** | `POST /file/upload` | | **请求参数** | `filePath: string` - 本地文件路径 | | **返回数据** | `{ fileId: number; fileUrl: string }` | **代码示例**: ```typescript 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 }` | **代码示例**: ```typescript const { files, total } = await fileApi.getFileList(1, 20); ``` ### 3. 获取文件详情 | 项目 | 说明 | | ------------ | --------------------------------- | | **接口地址** | `GET /file/:fileId` | | **请求参数** | `fileId: number` | | **返回数据** | [`FileInfo`](src/types/file.ts:1) | **代码示例**: ```typescript const fileInfo = await fileApi.getFile(123); ``` ### 4. 删除文件 | 项目 | 说明 | | ------------ | ---------------------- | | **接口地址** | `DELETE /file/:fileId` | | **请求参数** | `fileId: number` | | **返回数据** | `void` | **代码示例**: ```typescript await fileApi.deleteFile(123); ``` ### 5. 添加水印 | 项目 | 说明 | | ------------ | ----------------------------------------- | | **接口地址** | `POST /file/:fileId/watermark` | | **请求参数** | `fileId: number`, `{ watermark: string }` | | **返回数据** | `{ watermarkUrl: string }` | **代码示例**: ```typescript const { watermarkUrl } = await fileApi.addWatermark(123, "仅供打印使用"); ``` --- ## 订单服务 (Order) **基础路径**: `/order` ### 1. 创建订单 | 项目 | 说明 | | ------------ | --------------------------------------------- | | **接口地址** | `POST /order/create` | | **请求参数** | [`CreateOrderRequest`](src/types/order.ts:22) | | **返回数据** | [`Order`](src/types/order.ts:4) | **请求参数结构**: ```typescript { fileId: number; // 文件ID printerId: number; // 打印机ID printType: "A4" | "A3" | "照片"; // 打印类型 colorType: "黑白" | "彩色"; // 颜色类型 copies: number; // 份数 } ``` **代码示例**: ```typescript 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`](src/types/order.ts:4) | **代码示例**: ```typescript const order = await orderApi.getOrder(456); ``` ### 3. 获取订单列表 | 项目 | 说明 | | ------------ | -------------------------------------- | | **接口地址** | `GET /order/list` | | **请求参数** | `{ page?: number; pageSize?: number }` | | **返回数据** | `{ orders: Order[]; total: number }` | **代码示例**: ```typescript const { orders, total } = await orderApi.getOrderList(1, 10); ``` ### 4. 更新订单状态 | 项目 | 说明 | | ------------ | --------------------------------------- | | **接口地址** | `PUT /order/:orderId/status` | | **请求参数** | `orderId: number`, `{ status: number }` | | **返回数据** | [`Order`](src/types/order.ts:4) | **订单状态枚举**: | 值 | 状态 | |----|------| | 0 | 待支付 | | 1 | 已支付 | | 2 | 打印中 | | 3 | 已完成 | | 4 | 已取消 | **代码示例**: ```typescript await orderApi.updateOrderStatus(456, 1); // 标记为已支付 ``` ### 5. 取消订单 | 项目 | 说明 | | ------------ | ------------------------------- | | **接口地址** | `PUT /order/:orderId/cancel` | | **请求参数** | `orderId: number` | | **返回数据** | [`Order`](src/types/order.ts:4) | **代码示例**: ```typescript await orderApi.cancelOrder(456); ``` --- ## 打印服务 (Print) **基础路径**: `/print` ### 1. 获取打印机列表 | 项目 | 说明 | | ------------ | ------------------------------------- | | **接口地址** | `GET /print/printers` | | **请求参数** | 无 | | **返回数据** | [`Printer[]`](src/types/printer.ts:3) | **代码示例**: ```typescript import { printerApi } from "./api/printer"; const printers = await printerApi.getPrinters(); ``` ### 2. 获取打印机状态 | 项目 | 说明 | | ------------ | -------------------------------------- | | **接口地址** | `GET /print/printer/:printerId/status` | | **请求参数** | `printerId: number` | | **返回数据** | [`Printer`](src/types/printer.ts:3) | **打印机状态枚举**: | 值 | 状态 | |----|------| | 0 | 空闲 | | 1 | 打印中 | | 2 | 离线 | **代码示例**: ```typescript const printer = await printerApi.getPrinterStatus(1); ``` ### 3. 注册打印机 | 项目 | 说明 | | ------------ | ------------------------------------ | | **接口地址** | `POST /print/printer/register` | | **请求参数** | `{ name: string; location: string }` | | **返回数据** | [`Printer`](src/types/printer.ts:3) | **代码示例**: ```typescript const printer = await printerApi.registerPrinter("打印机1", "一楼大厅"); ``` ### 4. 提交打印任务 | 项目 | 说明 | | ------------ | ---------------------------------------- | | **接口地址** | `POST /print/job/submit` | | **请求参数** | `{ orderId: number; printerId: number }` | | **返回数据** | `{ jobId: number }` | **代码示例**: ```typescript const { jobId } = await printerApi.submitPrintJob(456, 1); ``` ### 5. 取消打印任务 | 项目 | 说明 | | ------------ | ------------------------------ | | **接口地址** | `PUT /print/job/:jobId/cancel` | | **请求参数** | `jobId: number` | | **返回数据** | `void` | **代码示例**: ```typescript await printerApi.cancelPrintJob(789); ``` --- ## 支付服务 (Pay) **基础路径**: `/pay` ### 1. 创建微信支付订单 | 项目 | 说明 | | ------------ | ---------------------------------------------------------------------------------------------- | | **接口地址** | `POST /pay/create` | | **请求参数** | `{ orderId: number }` | | **返回数据** | `{ prepayId: string; paySign: string; timeStamp: string; nonceStr: string; signType: string }` | **代码示例**: ```typescript import { payApi } from "./api/pay"; const payParams = await payApi.createWxPayOrder(456); // 使用返回参数调起微信支付 ``` ### 2. 查询支付状态 | 项目 | 说明 | | ------------ | ------------------------- | | **接口地址** | `GET /pay/query/:orderId` | | **请求参数** | `orderId: number` | | **返回数据** | `{ status: number }` | **支付状态枚举**: | 值 | 状态 | |----|------| | 0 | 待支付 | | 1 | 支付中 | | 2 | 成功 | | 3 | 失败 | **代码示例**: ```typescript const { status } = await payApi.queryPayStatus(456); ``` ### 3. 余额支付 | 项目 | 说明 | | ------------ | ---------------------- | | **接口地址** | `POST /pay/balance` | | **请求参数** | `{ orderId: number }` | | **返回数据** | `{ success: boolean }` | **代码示例**: ```typescript const { success } = await payApi.payByBalance(456); ``` --- ## 价目表服务 (Price) **基础路径**: `/price` ### 1. 获取价目表 | 项目 | 说明 | | ------------ | ------------------------------------- | | **接口地址** | `GET /price/list` | | **请求参数** | 无 | | **返回数据** | [`PriceItem[]`](src/types/price.ts:3) | **代码示例**: ```typescript import { priceApi } from "./api/price"; const priceList = await priceApi.getPriceList(); ``` **价目表示例**: ```json [ { "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`](src/utils/request.ts:1) 已封装错误处理逻辑: ```typescript 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 由 [`request.ts`](src/utils/request.ts:16) 自动注入,无需手动处理 - Token 过期时,服务器返回 401,前端自动触发登出 ### 2. 文件上传 - 使用 Taro 原生 `uploadFile` API,支持断点续传 - 上传成功后返回 `fileId` 和 `fileUrl`,用于后续订单创建 ### 3. 分页查询 - 文件列表和订单列表接口支持分页 - 默认 `page=1`, `pageSize=20` - 响应中包含 `total` 字段表示总记录数 ### 4. 状态枚举 - 订单状态、支付状态、打印机状态均使用数字枚举 - 类型定义文件(如 [`order.ts`](src/types/order.ts:1))中提供了状态映射表,便于显示 ### 5. 数据格式 - 所有时间字段使用 ISO 8601 格式字符串(如 `"2024-01-01T12:00:00Z"`) - 价格字段使用数字类型,单位为元(如 `0.10` 表示 0.1 元) ### 6. 开发环境配置 - 开发环境 API 地址:`http://localhost:8080` - 确保后端服务已启动且端口正确 - 如需修改地址,编辑 [`src/config/api.ts`](src/config/api.ts:1) ### 7. 类型安全 - 所有 API 接口都有完整的 TypeScript 类型定义 - 导入对应的类型文件(如 `import type { Order } from '../types'`) - 使用类型提示可以减少运行时错误 --- ## 快速开始示例 以下是一个完整的打印流程示例: ```typescript 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