## 1. 接口概述

袋牌模块提供了一系列RESTful API接口，用于袋牌的生成、打开、关闭以及与尾程运单号的关联操作。本文档详细描述了这些接口的使用方法、请求参数和响应格式。

### 1.1 接口基础信息

- 基础URL：`http://{服务器地址}:{端口}/api/bagtag`
- 测试环境请求地址：`http://172.232.21.79:5002`
- 正式环境请求地址：`https://lr.tooexp.com`
- 请求方式：POST/GET
- 数据格式：JSON
- 响应格式：JSON

### 1.2 状态码说明

状态码 | 描述
--- | ---
200 | 操作成功
400 | 请求参数错误或操作失败
404 | 资源不存在
500 | 服务器内部错误

## 2. 接口详细说明

### 2.1 生成袋牌号

POST /generate

根据渠道商名称和数量生成袋牌号

#### 请求参数

参数名 | 类型 | 必填 | 描述 | 示例值
--- | --- | --- | --- | ---
ChannelName | string | 是 | 渠道商名称 | "USPS"
Count | int | 否 | 生成数量，默认1 | 5
Creator | string | 是 | 创建人 | "test_user"

#### 请求示例

{ "ChannelName": "USPS", "Count": 3, "Creator": "test_user" }

#### 响应格式

成功响应：

{ "code": 0, "data": [ "USPS202601271200000001", "USPS202601271200000002", "USPS202601271200000003" ], "message": "Bag tags generated successfully" }

失败响应：

{ "code": 9999, "message": "错误信息" }

### 2.2 打开袋牌

POST /open

将袋牌状态设置为"打开"

#### 请求参数

参数名 | 类型 | 必填 | 描述 | 示例值
--- | --- | --- | --- | ---
TagNumber | string | 是 | 袋牌号 | "USPS202601271200000001"

#### 请求示例

{ "TagNumber": "USPS202601271200000001" }

#### 响应格式

成功响应：

{ "code": 0, "message": "Bag tag opened successfully", "data": { "waybillCount": 10 } }

失败响应：

{ "code": 1001, "message": "Failed to open bag tag. It may not exist or closed.", "data": {} }

### 2.3 关闭袋牌

POST /close

将袋牌状态设置为"关闭"

#### 请求参数

参数名 | 类型 | 必填 | 描述 | 示例值
--- | --- | --- | --- | ---
TagNumber | string | 是 | 袋牌号 | "USPS202601271200000001"

#### 请求示例

{ "TagNumber": "USPS202601271200000001" }

#### 响应格式

成功响应：

{ "code": 0, "message": "Bag tag closed successfully", "data": { "waybillCount": 10 } }

失败响应：

{ "code": 1002, "message": "Failed to close bag tag. It may not exist or already closed.", "data": {} }

### 2.4 关联尾程运单号

POST /associate-waybill

将尾程运单号与袋牌建立关联

#### 请求参数

参数名 | 类型 | 必填 | 描述 | 示例值
--- | --- | --- | --- | ---
TagNumber | string | 是 | 袋牌号 | "USPS202601271200000001"
FinalMileTrackingNumber | string | 是 | 尾程运单号 | "1Z999AA10123456789"
Creator | string | 是 | 创建人 | "test_user"

#### 请求示例

{ "TagNumber": "USPS202601271200000001", "FinalMileTrackingNumber": "1Z999AA10123456789", "Creator": "test_user" }

#### 响应格式

成功响应：

{ "code": 0, "message": "Final mile tracking number associated successfully", "data": { "waybillCount": 10 } }

失败响应：

{ "code": 10031, "message": "Bag tag not found", "data": {} }
{ "code": 10032, "message": "Bag tag is not in opened status", "data": {} }
{ "code": 10033, "message": "Channel does not match between bag tag and tracking number", "data": {} }
{ "code": 10035, "message": "Waybill is already associated with another bag tag", "data": {} }

### 2.5 获取袋牌信息

GET /{tagNumber}

根据袋牌号获取袋牌详细信息，包含关联的小包数量

#### 请求参数

参数名 | 类型 | 必填 | 描述 | 示例值
--- | --- | --- | --- | ---
tagNumber | string | 是 | 袋牌号（路径参数） | "TESTBAG001"

#### 请求示例

GET /api/bagtag/TESTBAG001

#### 响应格式

成功响应：

{ "code": 0, "message": "success", "data": { "Id": 1, "TagNumber": "TESTBAG001", "ChannelName": "USPS", "Status": "Opened", "Creator": "system", "CreatedAt": "2026-01-27T12:00:00Z", "OpenedAt": "2026-01-27T12:05:00Z", "ClosedAt": null, "waybillCount": 10 } }

失败响应：

{ "code": 1004, "message": "Bag tag not found" }

### 2.6 获取袋牌关联的尾程运单号

GET /{tagNumber}/waybills

获取指定袋牌关联的所有尾程运单号

#### 请求参数

参数名 | 类型 | 必填 | 描述 | 示例值
--- | --- | --- | --- | ---
tagNumber | string | 是 | 袋牌号（路径参数） | "USPS202601271200000001"

#### 请求示例

GET /api/bagtag/USPS202601271200000001/waybills

#### 响应格式

成功响应：

{ "status": "success", "data": [ { "Id": 1, "TagNumber": "USPS202601271200000001", "FinalMileTrackingNumber": "1Z999AA10123456789", "CreatedAt": "2026-01-27T12:10:00Z" }, { "Id": 2, "TagNumber": "USPS202601271200000001", "FinalMileTrackingNumber": "1Z999AA10123456790", "CreatedAt": "2026-01-27T12:15:00Z" } ] }

失败响应：

{ "status": "error", "message": "错误信息" }

### 2.7 查询袋牌关联小包数量

GET /{tagNumber}/waybill-count

查询指定袋牌关联的小包数量

#### 请求参数

参数名 | 类型 | 必填 | 描述 | 示例值
--- | --- | --- | --- | ---
tagNumber | string | 是 | 袋牌号（路径参数） | "TESTBAG001"

#### Mock数据

袋牌号 | 返回数量
--- | ---
TESTBAG001 | 10
TESTBAG002 | 5
TESTBAG003 | 0

#### 请求示例

GET /api/bagtag/TESTBAG001/waybill-count

#### 响应格式

成功响应：

{ "code": 0, "message": "success", "data": { "tagNumber": "USPS202601271200000001", "waybillCount": 5 } }

失败响应：

{ "code": 9999, "message": "错误信息" }

### 2.8 移除袋牌和小包关联

POST /remove-waybill

移除袋牌和小包的关联关系

#### 请求参数

参数名 | 类型 | 必填 | 描述 | 示例值
--- | --- | --- | --- | ---
TagNumber | string | 是 | 袋牌号 | "TESTBAG001"
FinalMileTrackingNumber | string | 是 | 尾程运单号 | "TESTWAYBILL001"

#### Mock数据

袋牌号 | 尾程运单号 | 返回结果
--- | --- | ---
TESTBAG001 | TESTWAYBILL001 | 成功
TESTBAG001 | TESTWAYBILL999 | 失败（运单未关联）
TESTBAG999 | 任意 | 失败（袋牌不存在）

#### 请求示例

{ "TagNumber": "TESTBAG001", "FinalMileTrackingNumber": "TESTWAYBILL001" }

#### 响应格式

成功响应：

{ "code": 0, "message": "Waybill removed from bag tag successfully" }

失败响应：

{ "code": 10031, "message": "Bag tag not found" }
{ "code": 10032, "message": "Bag tag is not in opened status" }
{ "code": 10034, "message": "Waybill is not associated with this bag tag" }

### 2.9 根据扫描单号查询袋牌与小包关联信息

GET /waybill/{finalMileTrackingNumber}

根据尾程运单号查询袋牌与小包的关联信息

#### 请求参数

参数名 | 类型 | 必填 | 描述 | 示例值
--- | --- | --- | --- | ---
finalMileTrackingNumber | string | 是 | 尾程运单号（路径参数） | "1Z999AA10123456789"

#### 请求示例

GET /api/bagtag/waybill/1Z999AA10123456789

#### 响应格式

成功响应：

{ "code": 0, "message": "success", "data": { "Id": 1, "TagNumber": "USPS202601271200000001", "FinalMileTrackingNumber": "1Z999AA10123456789", "Creator": "system", "CreatedAt": "2026-01-27T12:10:00Z", "Remark": null, "bagTag": { "ChannelName": "USPS", "Status": "Opened", "OpenedAt": "2026-01-27T12:05:00Z", "ClosedAt": null } } }

失败响应：

{ "code": 10036, "message": "Waybill not associated with any bag tag" }

### 2.10 袋牌标签打印

GET /{tagNumber}/print

打印袋牌标签，返回PDF格式的袋牌字节流

#### 请求参数

参数名 | 类型 | 必填 | 描述 | 示例值
--- | --- | --- | --- | ---
tagNumber | string | 是 | 袋牌号（路径参数） | "USPS202601271200000001"

#### 请求示例

GET /api/bagtag/USPS202601271200000001/print

#### 响应格式

成功响应：

- 响应类型：`application/pdf`
- 响应内容：袋牌标签的PDF字节流
- 文件名：`bag_tag_{tagNumber}.pdf`

失败响应：

- 响应类型：`application/pdf`
- 响应内容：空字节流

### 2.11 查询可用袋牌

GET /available

查询指定渠道的可用袋牌（已关闭且未绑定到出库交接单的袋牌）

#### 请求参数

参数名 | 类型 | 必填 | 描述 | 示例值
--- | --- | --- | --- | ---
channel | string | 是 | 渠道商名称 | "USPS"

#### 请求示例

GET /api/bagtag/available?channel=USPS

#### 响应格式

成功响应：

{ "code": 0, "message": "success", "data": [ { "id": 1, "tagNumber": "USPS202601271200000001", "channelName": "USPS", "status": "Closed", "creator": "system", "createdAt": "2026-01-27T12:00:00Z", "openedAt": "2026-01-27T12:05:00Z", "closedAt": "2026-01-27T12:30:00Z", "waybillCount": 10 } ] }

失败响应：

{ "code": 400, "message": "Channel parameter is required" }
{ "code": 9999, "message": "错误信息" }

## 3. 接口调用示例

### 3.1 使用cURL调用

#### 生成袋牌号

curl -X POST "http://localhost:5003/api/bagtag/generate" \ -H "Content-Type: application/json" \ -d '{"ChannelName": "USPS", "Count": 2}'

#### 打开袋牌

curl -X POST "http://localhost:5003/api/bagtag/open" \ -H "Content-Type: application/json" \ -d '{"TagNumber": "USPS202601271200000001"}'

#### 关联尾程运单号

curl -X POST "http://localhost:5003/api/bagtag/associate-waybill" \ -H "Content-Type: application/json" \ -d '{"TagNumber": "USPS202601271200000001", "FinalMileTrackingNumber": "1Z999AA10123456789"}'

### 3.2 使用PowerShell调用

#### 生成袋牌号

Invoke-RestMethod -Uri "http://localhost:5003/api/bagtag/generate" ` -Method POST ` -ContentType "application/json" ` -Body '{"ChannelName": "USPS", "Count": 2}'

#### 打开袋牌

Invoke-RestMethod -Uri "http://localhost:5003/api/bagtag/open" ` -Method POST ` -ContentType "application/json" ` -Body '{"TagNumber": "USPS202601271200000001"}'

#### 关联尾程运单号

Invoke-RestMethod -Uri "http://localhost:5003/api/bagtag/associate-waybill" ` -Method POST ` -ContentType "application/json" ` -Body '{"TagNumber": "USPS202601271200000001", "FinalMileTrackingNumber": "1Z999AA10123456789"}'

## 4. 业务流程示例

### 4.1 完整业务流程

1. 生成袋牌：根据渠道商生成袋牌号
2. 打开袋牌：将袋牌状态设置为"打开"
3. 关联尾程运单号：将尾程运单号与袋牌建立关联
4. 关闭袋牌：当袋牌使用完毕后，将其状态设置为"关闭"

### 4.2 流程示例

# 1. 生成袋牌 POST /api/bagtag/generate {"ChannelName": "UPS", "Count": 1} # 2. 打开袋牌 POST /api/bagtag/open {"TagNumber": "UPS202601271200000001"} # 3. 关联尾程运单号 POST /api/bagtag/associate-waybill {"TagNumber": "UPS202601271200000001", "FinalMileTrackingNumber": "1Z888BB20234567890"} # 4. 关闭袋牌 POST /api/bagtag/close {"TagNumber": "UPS202601271200000001"}

## 5. 注意事项

### 5.1 袋牌状态管理

- 只有状态为"Generated"的袋牌才能被打开
- 只有状态为"Opened"的袋牌才能关联尾程运单号
- 只有状态为"Opened"的袋牌才能被关闭
- 已关闭的袋牌不能再次打开或关联尾程运单号

### 5.2 袋牌号唯一性

- 系统确保生成的袋牌号唯一
- 袋牌号格式：`{渠道商名称}{时间戳}{序号}`
- 时间戳精确到秒，序号为4位数字

### 5.3 数据验证

- 渠道商名称不能为空
- 袋牌号不能为空且必须存在
- 尾程运单号不能为空
- 生成数量必须为正整数

### 5.4 性能考虑

- 批量生成袋牌时，建议单次生成数量不超过100个
- 频繁的袋牌操作可能会影响系统性能，建议合理控制调用频率

## 6. 常见问题

### 6.1 生成袋牌失败

可能原因：

- 渠道商名称为空
- 生成数量为负数或零

解决方案：

- 确保渠道商名称不为空
- 确保生成数量为正整数

### 6.2 打开袋牌失败

可能原因：

- 袋牌不存在
- 袋牌已被打开
- 袋牌已被关闭

解决方案：

- 检查袋牌号是否正确
- 检查袋牌当前状态

### 6.3 关联尾程运单号失败

可能原因：

- 袋牌不存在
- 袋牌未被打开
- 袋牌已被关闭

解决方案：

- 检查袋牌号是否正确
- 确保袋牌状态为"Opened"

### 6.4 关闭袋牌失败

可能原因：

- 袋牌不存在
- 袋牌未被打开
- 袋牌已被关闭

解决方案：

- 检查袋牌号是否正确
- 确保袋牌状态为"Opened"

## 7. 接口版本管理

版本 | 变更内容 | 发布日期
--- | --- | ---
v1.0 | 初始版本，包含所有基础接口 | 2026-01-27

## 8. 联系信息

如有接口使用问题，请联系系统管理员或开发团队。