# 安徽运八需求（以API文档为准重构）

> **重构原则**: API接口文档(网货企业端接口文档 V1.0.2) 为权威数据源，HTML原型为UI参考，原始需求文档为业务背景补充。
> **重构时间**: 2026-07-13
> **原始需求**: `source_docs/requirements_raw/安徽运八需求.docx`
> **API文档**: `E:\Downloads\网货企业端接口文档（最新）.pdf` V1.0.2 (2023-04)
> **原型**: `anhuibaba_index.html`

---

## 一、系统边界

本需求涉及两套系统的对接：

| 系统 | 职责 | 本文档覆盖 |
|:---|:---|:---|
| **运八平台（我方）** | 自动触发三阶段上报、ETC上传；查询核验结果；发起/跟踪申诉；查看上报日志 | 全量 |
| **安徽省级网络货运监测系统（省平台）** | 接收上报数据；执行核验；受理申诉并反馈 | 仅接口交互 |

API文档覆盖的是**运八平台→省平台**的查询和申诉接口。上报触发逻辑（装货完成/打款完成/开票完成自动触发）属于运八平台内部业务逻辑，API文档中未定义上报提交接口。

---

## 二、API接口清单（权威来源：接口文档 V1.0.2）

### 2.1 通用规范

| 项目 | 规范 |
|:---|:---|
| 基地址 | `http://*******/api/` |
| 协议 | HTTP POST |
| 请求格式 | JSON（除上传文件接口外） |
| 响应格式 | `{"code":200, "message":"操作成功", "data":{}}` |
| 认证 | JWT Token，调用 `/sys/login` 获取，除登录接口外均需在请求头携带 |
| 时间格式 | `yyyy-MM-dd HH:mm:ss` |
| 成功码 | `code=200` |
| 失败码 | `code=500` |

### 2.2 接口一览（共9个）

| # | 接口 | URL | 说明 |
|:---:|:---|:---|:---|
| 1 | 获取token | `POST /sys/login` | JWT认证，参数: loginName, loginPassword |
| 2 | 上传申诉附件 | `POST /appeal/uploadFile` | 文件上传，参数: file (File) |
| 3 | 提交申诉运单 | `POST /appeal/insert` | 发起申诉，参数: freightSheetNumber, complaintNumber, attachmentUrl, content, verificationAbnormalItems |
| 4 | 查询异常运单信息 | `POST /verificationSummary/page` | 分页查询，支持多维度筛选 |
| 5 | 查询申诉进度 | `POST /appeal/page` | 分页查询申诉记录及审核结果 |
| 6 | 查询运单核验详情 | `POST /verificationSummary/verificationDetail` | 单运单全部核验项明细 |
| 7 | 查询发票是否合规 | `POST /verificationSummary/cargoOwnerInvoiceInfo` | 判断托运人发票系统核验是否合规 |
| 8 | 运单里程核验查询 | `POST /verificationSummary/mileageVerificationInfo` | 批量查询运单里程核验状态 |
| 9 | 运单里程申诉 | `POST /mileageAppeal/insert` | 对里程核验结果发起申诉 |

### 2.3 接口详细定义

#### 接口1: 获取token
```
POST /sys/login
请求: { "loginName": "xxx", "loginPassword": "xxx" }
响应: { "code": 200, "data": { "token": "...", "expireTime": 1681219619843, "loginName": "ceshi", "name": "测试" } }
```

#### 接口2: 上传申诉附件
```
POST /appeal/uploadFile
请求: multipart/form-data, 字段 file (File)
```

#### 接口3: 提交申诉运单
```
POST /appeal/insert
请求:
  freightSheetNumber    String  运单号           必填
  complaintNumber       String  申诉编号          必填
  attachmentUrl         String  申诉附件URL       必填
  content               String  申诉内容          必填
  verificationAbnormalItems String 核验异常项ID   必填  (逗号分隔，如"120,160")
```

#### 接口4: 查询异常运单信息
```
POST /verificationSummary/page
请求:
  pageIndex              int     页码            必填
  pageSize               int     每页条数         必填
  freightSheetNumber     String  运单号           可选
  verificationAbnormalItems String 异常项ID       可选 (多个逗号拼接)
  driverName             String  驾驶员姓名       可选
  driverIdCard           String  驾驶员身份证号   可选
  vehicleNumber          String  车牌号           可选
  appealStateId          int     申诉状态ID       可选
  verifyStateId          int     核验状态ID       可选
  beginTime ~ endTime            运单创建时间范围  可选
  beginFirstVerifyTime ~ endFirstVerifyTime  首次核验时间范围  可选
  beginLastVerifyTime ~ endLastVerifyTime    最新核验时间范围  可选
  beginInsertTime ~ endInsertTime            插入时间范围      可选

响应:
  pageRecords[]:
    freightSheetNumber       String  运单号
    appealStateId            int     申诉状态ID
    appealStateName          String  申诉状态名称
    verificationAbnormalItem String  核验异常项
    createTime               date    运单创建时间
    lastVerifyTime           date    最新核验时间
    firstVerifyTime          date    首次核验时间
    vehicleNumber            String  车牌号
    driverName               String  驾驶员姓名
    driverIdCard             String  驾驶员身份证号
    verifyStateId            int     核验状态ID
    verifyStateName          String  核验状态名称
    abnormalDetails[]:
      id        int     异常项ID
      name      String  异常项名称
      message   String  异常原因
      time      date    异常时间
      state     int     异常项处理状态 (100=未申诉, 110=申诉中)
```

#### 接口5: 查询申诉进度
```
POST /appeal/page
请求:
  pageIndex          int     页码              必填
  pageSize           int     每页条数           必填
  freightSheetNumber String  运单号             可选
  abnormalTypeId     String  核验异常项ID        可选
  auditStateId       String  审核状态ID         可选
  beginTime ~ endTime        申诉时间范围        可选
  auditBeginTime ~ auditEndTime 审核时间范围     可选
  complaintNumber    String  申诉编号           可选

响应:
  pageRecords[]:
    complaintNumber          String  申诉编号
    freightSheetNumber       String  运单号
    content                  String  申诉内容
    complainantName          String  申诉人
    auditStateId             int     审核状态ID
    auditStateName           String  审核状态名称
    auditorName              String  审核人
    auditRemark              String  审核备注
    auditTime                date    审核时间
    verificationAbnormalItem String  运单异常项
    cancelPerson             String  取消人
    cancelReason             String  取消原因
    cancelTime               date    取消时间
    revokeUserName           String  撤回人
    revokeTime               date    撤回时间
    createTime               date    创建时间
    appealAbnormalList[]:
      verificationTypeId     int     异常项ID
      verificationTypeName   String  异常项名称
```

#### 接口6: 查询运单核验详情
```
POST /verificationSummary/verificationDetail
请求:
  freightSheetNumber  String  运单号  必填
  beginInsertTime     String  插入时间-开始  可选
  endInsertTime       String  插入时间-结束  可选

响应:
  pageRecords[].details[]:
    verificationCode      int     核验项编码
    verificationName      String  核验项名称
    verificationState     String  核验状态
    verificationStateId   int     核验状态ID
    verificationTime      date    核验时间
    message               String  核验信息
```

#### 接口7: 查询发票是否合规
```
POST /verificationSummary/cargoOwnerInvoiceInfo
请求: { "freightSheetNumber": "55141359" }
响应: { "isSystemVerification": true }  // true=系统核验合规, false=人工判定合规
```

#### 接口8: 运单里程核验查询
```
POST /verificationSummary/mileageVerificationInfo
请求: { "freightSheetNumberList": ["22222222", "111111"] }
响应: [
  { "verificationStateId": 110, "freightSheetNumber": "22222222", "mileage": 350.263 },
  { "verificationStateId": null, "freightSheetNumber": "4658151", "mileage": null }
]
// 注: 运单未上报里程时 verificationStateId 和 mileage 为 null
```

#### 接口9: 运单里程申诉
```
POST /mileageAppeal/insert
请求:
  freightSheetNumber  String  运单号    必填
  content             String  申诉内容  必填
  complaintNumber     String  申诉编号  必填
  mileage             String  里程数    必填
```

---

## 三、数据字典（权威来源：接口文档 §4.1~§4.5）

### 3.1 异常项ID对照表（§4.1）— 共17项

| Code | 名称 | 说明 |
|:---:|:---|:---|
| 100 | 委托合同 | 托运人与承运人签订的委托运输合同核验 |
| 120 | 承运合同 | 承运人以自身名义签订的运输合同核验 |
| 130 | 实时定位 | 车辆实时定位数据核验 |
| 140 | 运单时间逻辑 | 运单各时间节点的逻辑合理性核验（如装货时间<卸货时间） |
| 150 | 车辆资质 | 车辆道路运输经营许可证有效性核验 |
| 160 | 道路运输证 | 车辆道路运输证有效期核验 |
| 170 | 驾驶证 | 驾驶员驾驶证有效性核验 |
| 180 | 从业资格证 | 驾驶员从业资格证有效期核验 |
| 190 | 车辆重复 | 同一车辆在同一时段是否存在多运单 |
| 200 | 司机重复 | 同一司机在同一时段是否存在多运单 |
| 210 | 车辆轨迹 | GPS轨迹真实性、与运单路线匹配度核验 |
| 220 | 运费收款 | 运单是否在运费收款方名下 |
| 230 | 公司统一收款 | 是否通过公司账户统一收款 |
| 240 | 集中支付 | 是否通过网络货运平台集中支付 |
| 250 | 资金流水 | 资金流水单号唯一性、金额匹配核验 |
| 260 | 发票信息 | 托运人发票信息核验（第三次上报相关） |
| 270 | 非通行车辆可开票 | 非通行车辆是否允许开具通行费发票 |

### 3.2 运单核验状态（§4.2）

| Code | 名称 | 说明 |
|:---:|:---|:---|
| 100 | 未核验 | 运单尚未被省平台核验 |
| 110 | 核验通过 | 全部核验项通过 |
| 120 | 全部异常 | 存在核验不通过的异常项 |

### 3.3 运单部分核验状态（§4.3）

| Code | 名称 | 说明 |
|:---:|:---|:---|
| 100 | 未核验 | 尚未核验 |
| 110 | 部分核验 | 部分核验项已通过，仍有待核验项 |
| 120 | 全部核验 | 全部核验项已出结果 |

### 3.4 运单申诉状态（§4.4）— 权威枚举

| Code | 名称 | 说明 |
|:---:|:---|:---|
| **100** | **未申诉** | 尚未发起申诉 |
| **110** | **审核通过** | 省平台审核通过 |
| **120** | **审核不通过** | 省平台审核驳回 |
| **130** | **已取消** | 申诉已取消（原始需求未提及此状态） |

> **与原始需求的差异**: 
> - 原始需求: 未申诉 / 申诉中 / 申诉通过 / 申诉驳回
> - API文档: 未申诉(100) / 审核通过(110) / 审核不通过(120) / 已取消(130)
> - **API文档为权威来源**。原始需求的"申诉中"在API中对应"未申诉(100)"状态下的一个进行中标记（接口4响应中 abnormalDetails[].state=110 表示申诉中）。
> - 原型中的"待省平台反馈"和"反馈处理中"为UI层面的展示状态，非后端枚举值。

### 3.5 附件状态（§4.5）

| Code | 名称 | 说明 |
|:---:|:---|:---|
| 100 | 未处理 | 申诉附件尚未被省平台处理 |
| 110 | 处理通过 | 附件核验通过 |
| 120 | 处理异常 | 附件核验异常 |

---

## 四、功能模块（综合API文档+原型+原始需求）

### 4.1 上报运单看板

**入口**: 侧边栏 → 上报运单看板

**统计卡片**（原型定义）:
- 异常运单数、待申诉数、申诉中数、已处理数

**查询条件**（综合原型+接口4请求参数）:

| 筛选项 | 类型 | 可选值 |
|:---|:---|:---|
| 运单号/托运单号/货源单号 | 文本输入 | 模糊搜索 |
| 上报阶段 | 下拉 | 全部 / 第一次上报 / 第二次上报 / 第三次上报 |
| 核验状态 | 下拉 | 全部 / 异常 / 通过 |
| 申诉状态 | 下拉 | 全部 / 未申诉(100) / 审核通过(110) / 审核不通过(120) / 已取消(130) |

**列表字段**（原型为准，15列含勾选）:
货源单号 / 运单号 / 托运单号 / 车牌号 / 司机姓名 / 上报阶段 / 托运方名称 / 核验状态 / 申诉状态 / 异常项 / 货物名称 / 合同金额 / 最新核验时间 / 操作

**操作按钮**:
- 异常运单: [申诉] [详情]
- 申诉中运单: [进度] [详情]
- 正常运单: [详情]

**标签颜色**（原型CSS定义）:
- 蓝色 `.tag-blue`: 上传中、申诉中
- 绿色 `.tag-green`: 已上传、通过、已完成、申诉通过、对公账户
- 红色 `.tag-red`: 上传失败、异常、申诉驳回
- 橙色 `.tag-orange`: 异常项标签、待上报
- 灰色 `.tag-gray`: 未申诉
- 紫色 `.tag-purple`: (预留)

### 4.2 第一次上报（装货完成）

**触发条件**: 运单装货完成 AND 货源税源地=安徽

**上报数据子对象**（以接口文档字段定义为准）:

| 子对象 | 必选/可选 | 核心字段 |
|:---|:---|:---|
| waybillInfo（建单信息） | 必选 | originalDocumentNumber, shippingNoteNumber, documentCreateTime, carrier, unifiedSocialCreditIdentifier, permitNumber, businessTypeCode, goodsArrangementTypeCode, orderReceivingTime, departureTime, commercialContractNumber, contractNumber(可选), mileage(可选) |
| consignorInfo（托运人信息） | 必选 | consignor, consignorId, frameContractNumber(可选), placeOfLoading, loadingLongitude, loadingLatitude, loadingCountrySubdivisionCode |
| consigneeInfo（收货方信息） | 必选 | consignee, consigneeId, goodsReceiptPlace, unLoadingLongitude, unLoadingLatitude |
| driverInfo（司机信息） | 必选 | driverName, drivingIdNumber, drivingLicense, issuingOrganizations, qualificationCertificate, qualificationCertificateFrom, qualificationCertificateTo, taxRegistrationCertificate, telephone, validPeriodFrom, validPeriodTo, vehicleClass, provinceCode |
| carInfo（车辆信息） | 必选 | vehicleNumber, vehiclePlateColorCode, LicensePlateTypeCode, vin, owner, ownerId, useCharacter, vehicleType, vehicleEnergyType, registerDate, issueDate, issuingOrganizations, vehicleTonnage, grossMass, roadTransportCertificateNumber, trailerVehiclePlateNumber(可选), vehicleLicenseNumbe(可选), roadTransportSocialCreditFrom(可选), roadTransportSocialCreditTo(可选) |
| goodsInfos（货物信息） | 必选，可多条 | descriptionOfGoods, cargoTypeClassificationCode, quantity, unit |
| insuranceInformation（保险信息） | 可选 | policyNumber, insuranceCompany |

**业务规则**:
- 仅安徽税源地(省份代码=34，非28)运单触发
- 上报成功后自动调用"修改第一次上报部分字段"接口更新变化字段
- 失败自动重试最多3次，全部失败后站内信通知运营
- 第一次上报是后续上报的前置条件（后端校验）

**列表页**（原型为准，14列+勾选）:
货源单号 / 运单号 / 托运单号 / 车牌号 / 司机姓名 / 托运方名称 / 业务类型 / 货物名称 / 装货地址 / 卸货地址 / 运输里程 / 合同编号 / 上报状态 / 操作

**上报状态**（内部系统状态，非API枚举）:
- 上传中（蓝色）
- 已上传（绿色）
- 上传失败（红色）— 显示"手动上传"按钮
- 异常（橙色）

### 4.3 第二次上报（打款完成）

**触发条件**: 财务打款完成 AND 第一次上报已完成

**核验项**: 省平台自动核验，共17项（见§3.1）。每项独立产生核验结果，核验异常项可通过申诉机制逐项申诉。

**上报数据子对象**:
| 子对象 | 必选/可选 | 核心字段 |
|:---|:---|:---|
| waybillInfo | 必选 | （同第一次上报） |
| consignorInfo | 必选 | （同第一次上报） |
| consigneeInfo | 必选 | （同第一次上报） |
| 资金流水信息 | 必选 | 支付金额、支付方式、支付时间、付款方名称、收款方名称、收款人、收款账号、收款账号类型、流水号、支付状态 |
| 车辆轨迹信息 | 必选，2~2000点 | 定位类型、定位时间、定位地点、经度、纬度、轨迹类型 |

**列表页**（原型为准，17列+勾选）:
货源单号 / 运单号 / 托运单号 / 车牌号 / 司机姓名 / 托运方名称 / 承运运费 / 总金额 / 付款方式 / 付款时间 / 收款人 / 收款账号 / 收款账号类型 / 核验状态 / 异常项 / 上报状态 / 操作

**收款账号类型标签**: 个人账户=蓝色, 对公账户=绿色

### 4.4 第三次上报（开票完成）

**触发条件**: 发票开具完成 AND 第二次上报已完成

**前置条件**: 第二次上报必须完成（后端校验）

**API关联接口**: 
- `POST /verificationSummary/cargoOwnerInvoiceInfo` — 查询托运人发票系统核验是否合规
- 响应: `isSystemVerification`: true=系统核验合规, false=人工判定合规

**列表页**（原型为准，15列+勾选）:
货源单号 / 运单号 / 托运单号 / 发票号码 / 发票金额 / 税率 / 销售方名称 / 受票方名称 / 开票日期 / 油气票张数 / 核验状态 / 异常原因 / 上报状态 / 操作

### 4.5 ETC发票上传

**触发条件**: 税务抵扣完成

**列表页**（原型为准，10列+勾选）:
货源单号 / 运单号 / 托运单号 / ETC发票号 / 交易金额 / 入口收费站 / 出口收费站 / 交易时间 / 上传状态 / 操作

**详情弹窗字段**（原型为准）:
- 运单信息: 运单号、货源单号、托运单号、车牌号、司机姓名、托运方名称、收货方名称
- ETC发票信息: ETC发票号码、ETC发票代码、交易金额、税率(3%)、发票金额(不含税)、税额、入口收费站、出口收费站、交易时间、发票状态

### 4.6 异常申诉功能

**关联API接口**: 
- `POST /appeal/uploadFile` — 上传申诉附件
- `POST /appeal/insert` — 提交申诉
- `POST /appeal/page` — 查询申诉进度
- `POST /mileageAppeal/insert` — 里程申诉（独立接口）

**申诉流程**（闭环）:
```
异常运单查询(接口4) → 发起申诉(接口3) → 省平台复核 → 
查询申诉进度(接口5) → 审核通过(110) | 审核不通过(120) → 
重新申诉(接口3) | 取消(130)
```

**申诉状态流转**（以API §4.4为准）:
```
未申诉(100) → 审核通过(110) [终态]
未申诉(100) → 审核不通过(120) → 重新申诉 → 未申诉(100) [新申诉单]
未申诉(100) → 已取消(130) [终态]
```

**列表页**（原型为准，14列+勾选）:
运单号 / 托运单号 / 车牌号 / 司机姓名 / 托运方名称 / 上报阶段 / 核验状态 / 异常项 / 申诉状态 / 申诉时间 / 申诉人 / 省平台反馈结果 / 省平台反馈时间 / 操作

**详情弹窗分组**（原型为准）:
- 申诉信息: 申诉单号、上报阶段、异常项、申诉原因、申诉状态、申诉时间、申诉人、申诉附件
- 运单信息: 运单号、托运单号、车牌号、司机姓名、托运方名称
- 异常信息: 核验状态、异常原因、异常时间
- 省平台反馈信息: 反馈状态、反馈时间、反馈结果、反馈意见
- 处理记录（时间线）: 操作人、操作时间、操作类型、操作内容

### 4.7 上报日志

**查询条件**（原型为准）:
- 运单号/托运单号/货源单号: 模糊搜索
- 上报阶段: 全部 / 第一次上报 / 第二次上报 / 第三次上报 / ETC上传
- 上报结果: 全部 / 成功 / 失败
- 时间范围: 开始时间 ~ 结束时间

**列表字段**（原型为准，11列）:
序号 / 货源单号 / 运单号 / 托运单号 / 上报阶段 / 上报结果 / 接口URL / HTTP状态码 / 响应时间 / 上报时间 / 操作

**日志详情弹窗**: 展示完整请求报文（URL/Method/Headers/Body）和响应报文（StatusCode/Headers/Body），JSON格式化展示，支持一键复制。

---

## 五、状态枚举汇总（以API文档为权威）

### 5.1 申诉状态（API §4.4 权威）

| Code | 名称 | 原始需求对应 | 说明 |
|:---:|:---|:---|:---|
| 100 | 未申诉 | 未申诉 + 申诉中 | 含已提交但省平台尚未审核的情况 |
| 110 | 审核通过 | 申诉通过 | 终态 |
| 120 | 审核不通过 | 申诉驳回 | 可重新申诉 |
| 130 | 已取消 | （无） | API独有，原始需求未提及 |

### 5.2 核验状态（API §4.2 权威）

| Code | 名称 | 说明 |
|:---:|:---|:---|
| 100 | 未核验 | 运单尚未核验 |
| 110 | 核验通过 | 全部17项核验通过 |
| 120 | 全部异常 | 存在核验异常项 |

### 5.3 异常项处理状态（API §4.1 子字段）

| Code | 名称 | 说明 |
|:---:|:---|:---|
| 100 | 未申诉 | 该异常项尚未发起申诉 |
| 110 | 申诉中 | 该异常项已提交申诉，待审核 |

### 5.4 上报状态（内部系统状态，非API枚举）

| 状态 | 标签颜色 | 说明 |
|:---|:---|:---|
| 上传中 | 蓝色 | 数据正在上报中 |
| 已上传 | 绿色 | 上报成功 |
| 上传失败 | 红色 | 上报超时或错误，显示"手动上传"按钮 |
| 异常 | 橙色 | 数据校验不通过 |

---

## 六、与原始需求的关键差异

| # | 项目 | 原始需求 | API文档（权威） | 影响 |
|:---:|:---|:---|:---|:---|
| 1 | 核验项数量 | 7类 | **17项** (§4.1) | 测试覆盖需从14条扩展到34条 |
| 2 | 申诉状态 | 未申诉/申诉中/通过/驳回 | **未申诉(100)/审核通过(110)/审核不通过(120)/已取消(130)** | 申诉状态枚举全部更新 |
| 3 | 申诉"进行中" | 独立状态"申诉中" | 归属于"未申诉(100)"，由abnormalDetails[].state=110标识 | 状态机变更 |
| 4 | 已取消状态 | 无 | **130=已取消** | 新增状态，需补充测试 |
| 5 | 里程申诉 | 无 | **独立接口** `/mileageAppeal/insert` | 新增功能模块 |
| 6 | 发票合规查询 | 无 | **独立接口** `/verificationSummary/cargoOwnerInvoiceInfo` | 新增功能点 |
| 7 | 核验状态 | 通过/异常（二元） | 未核验(100)/通过(110)/全部异常(120) | 新增"未核验"初始状态 |
| 8 | 附件状态 | 无 | 未处理(100)/处理通过(110)/处理异常(120) | 新增枚举 |

---

## 七、上报接口文档参考

原始需求中提到的上报接口文档（上报数据字段定义）:
- URL: `https://www.showdoc.com.cn/2210641821476236/9919735893682511`
- 密码: `szjj@2023`

> ⚠️ 此文档定义了上报请求的字段结构（第一次上报7个子对象、第二次上报资金流水+轨迹、第三次上报发票信息），因受密码保护未直接读取。上报字段定义建议以此文档为准。

---

## 八、待确认项（累计14项）

### 阻塞级（影响测试覆盖）
1. **核验项分组映射**: API 17项核验如何映射到UI展示的异常项？是否所有17项均可独立申诉？
2. **上报接口字段定义**: showdoc文档中的字段是否与API文档§4一致？

### 重要级
3. 申诉状态"已取消(130)"的触发条件和权限
4. 原型中"待省平台反馈"和"反馈处理中"两个UI状态如何对应API的"未申诉(100)"
5. 第三次上报列表字段以原型(15列)还是原始需求(13列)为准
6. 里程申诉与通用申诉的关系——是否合并入口还是独立入口
7. 发票合规查询（接口7）的调用时机——第三次上报前校验还是独立查询

### 参考级
8. 自动重试间隔时间（当前参考值5s/15s/30s）
9. ETC税额四舍五入规则（0.01×3%=0.0003→?）
10. 申诉超时告警阈值（当前参考值7个工作日）
11. 原始需求与API文档省份代码一致性
12. 原型第二次上报详情弹窗缺失车辆轨迹——是原型bug还是设计如此
13. 原型详情弹窗字段分组与接口字段定义的完整映射
14. ETC上传触发条件"税务抵扣完成"由哪个系统事件触发
