# 订单核销结果页面重构说明
## 问题分析
### 原始问题
在执行次卡核销(order_type=1)时出现错误:
```
Expected BEGIN_OBJECT but was STRING at line 1 column 345 path $.data.result.info
```
### 根本原因
服务端对于不同订单类型返回的 `info` 字段数据结构不一致:
- **次卡核销 (order_type=1)**: `info` 字段为字符串类型
```json
"info": "平时"
```
- **年月卡核销 (order_type=3)**: `info` 字段为对象类型
```json
"info": {
"card_no": "2509085314",
"rest_number": 5,
"status": 1,
"verify_desc": "人脸验证...",
"verify_time": "2025-09-10 11:26:36",
"verify_type": 2
}
```
原有代码没有根据 `order_type` 正确处理这种数据结构差异。
## 解决方案
### 1. 修复 PadApiService.VerifyOrderResult 数据模型
**核心问题修复**:将 [VerifyOrderResult](file://c:\Users\mate1\Desktop\CODE\Android\oxFaceAndroid\app\src\main\java\com\ouxuan\oxface\network\api\PadApiService.java#L1287-L1322) 类中的 [info](file://c:\Users\mate1\Desktop\CODE\Android\oxFaceAndroid\app\src\main\java\com\ouxuan\oxface\network\api\PadApiService.java#L1311-L1312) 字段从固定的 `VerifyOrderInfo` 对象类型改为灵活的 `JsonElement` 类型。
```java
// 修复前(有问题的代码)
@SerializedName("info")
private VerifyOrderInfo info; // 只能处理对象类型
// 修复后(正确的代码)
@SerializedName("info")
private com.google.gson.JsonElement info; // 支持字符串和对象类型
```
**添加辅助方法**:
```java
// 获取字符串类型的info(次卡核销)
public String getInfoAsString() {
if (info != null && info.isJsonPrimitive()) {
return info.getAsString();
}
return "";
}
// 获取对象类型的info(年月卡核销)
public JsonObject getInfoAsJsonObject() {
if (info != null && info.isJsonObject()) {
return info.getAsJsonObject();
}
return null;
}
```
### 2. 重构 OrderVerificationResultActivity
#### 1.1 数据结构优化
```java
// 原始字段
private TextView tvTitle, tvOrderNo, tvVerificationCode, tvOrderType, tvCardNo, tvStatus, tvMessage, tvProject;
private String orderNo, verificationCode, orderType, cardNo, status, message, project;
// 重构后字段
private TextView tvTitle, tvStatus, tvMessage;
private ScrollView scrollContent;
private LinearLayout layoutContent;
private int orderType; // 改为int类型
private JsonElement orderInfo; // 支持多种数据类型
private PadApiService.VerifyOrderResult verifyResult; // 完整核销结果
```
#### 1.2 布局文件重构
```xml
```
#### 1.3 动态内容生成
根据订单类型动态生成不同的显示内容:
```java
private void buildOrderTypeSpecificContent() {
switch (orderType) {
case 0: // 场次核销
buildSiteContent();
break;
case 1: // 人次核销
buildPeopleContent();
break;
case 3: // 年月卡
buildCardContent();
break;
case 5: // 课程
buildCourseContent();
break;
}
}
```
### 2. 根据 uni 端逻辑实现不同订单类型展示
#### 2.1 场次核销 (order_type=0)
显示场次信息列表:
- 场馆名称
- 开始时间
#### 2.2 人次核销 (order_type=1)
显示人次相关信息:
- 验证码
- 订单编号
- 有效时间
- 预订信息(info 字符串)
#### 2.3 年月卡 (order_type=3)
显示年月卡信息:
- 验证码
- 名称(项目)
- 卡号(NO.xxx)
- 核销方式
- 核销时间
#### 2.4 课程 (order_type=5)
显示课程信息:
- 上课时间
- 上课教练
- 上课地点
- 课程名称
- 订单编号
- 签到方式
- 签到时间
### 3. 数据传递优化
#### 3.1 传递完整核销结果
```java
// 在 OrderSelectionActivity 中
if (data != null) {
intent.putExtra("verify_result", new Gson().toJson(data));
}
```
#### 3.2 解析完整数据结构
```java
// 在 OrderVerificationResultActivity 中
String verifyResultJson = intent.getStringExtra("verify_result");
if (verifyResultJson != null) {
verifyResult = gson.fromJson(verifyResultJson, PadApiService.VerifyOrderResponse.class).getResult();
orderInfo = JsonParser.parseString(gson.toJson(verifyResult.getInfo()));
}
```
### 4. 兼容性处理
#### 4.1 JsonElement 处理
```java
private String getJsonString(JsonObject jsonObject, String key, String defaultValue) {
if (jsonObject.has(key) && !jsonObject.get(key).isJsonNull()) {
return jsonObject.get(key).getAsString();
}
return defaultValue;
}
```
#### 4.2 不同数据类型检查
```java
// 字符串类型处理
if (orderInfo != null && orderInfo.isJsonPrimitive()) {
String bookingInfo = orderInfo.getAsString();
}
// 对象类型处理
if (orderInfo != null && orderInfo.isJsonObject()) {
JsonObject cardInfo = orderInfo.getAsJsonObject();
}
```
## 优势分析
### 1. 数据结构兼容性
- ✅ 支持 info 字段的字符串和对象两种类型
- ✅ 根据 order_type 智能选择处理方式
- ✅ 避免 JSON 解析异常
### 2. 界面显示灵活性
- ✅ 动态生成内容,支持不同订单类型
- ✅ 滚动视图支持长内容显示
- ✅ 统一的界面风格和交互
### 3. 代码可维护性
- ✅ 模块化的内容构建方法
- ✅ 清晰的数据传递流程
- ✅ 完善的错误处理机制
### 4. 用户体验
- ✅ 针对不同订单类型优化信息展示
- ✅ 保持与 uni 端一致的信息结构
- ✅ 友好的错误提示和状态显示
## 测试验证
创建了完整的单元测试来验证:
- 次卡核销数据解析
- 年月卡核销数据解析
- 订单类型名称转换
- 验证码格式化
- 使用时长格式化
## 使用说明
### 1. 次卡核销场景
系统会自动检测 order_type=1,将 info 字段作为字符串处理,显示预订信息。
### 2. 年月卡核销场景
系统会自动检测 order_type=3,将 info 字段作为对象处理,提取卡号、核销方式等详细信息。
### 3. 其他订单类型
支持场次(order_type=0)和课程(order_type=5)核销,根据相应的数据结构显示内容。
## 注意事项
1. **数据完整性**: 确保从上级页面传递完整的 verify_result 数据
2. **错误处理**: 当数据解析失败时,会降级显示基本订单信息
3. **向后兼容**: 保持与现有调用方式的兼容性
4. **性能优化**: 使用动态布局生成,避免冗余的视图创建
通过这次重构,彻底解决了不同订单类型核销时的数据结构不兼容问题,提升了用户体验和系统稳定性。