# Exchange Flow Type Display Specification

## Overview

Update the exchange display to show the new flow type and timestamp fields returned by the backend exchange APIs.

## API Response Changes

### GET /api/c/v1/exchange/pending

**New Response Fields:**

```json
{
  "code": 0,
  "msg": "success",
  "timestamp": "2026-06-03T10:00:00+08:00",
  "data": {
    "id": 1,
    "exchange_no": "EXC20260603001",
    "order_no": "EXC20260603001",
    "old_asset_type": "iot_card",
    "old_identifier": "8986012345678901234",
    "exchange_reason": "设备损坏",
    "status": 2,
    "status_text": "待发货",
    "flow_type": "shipping",
    "flow_type_name": "物流换货",
    "shipped_at": null,
    "completed_at": null,
    "created_at": "2026-06-03T10:00:00+08:00",
    "recipient_name": "张三",
    "recipient_phone": "13800138000",
    "recipient_address": "北京市朝阳区xxx路xxx号"
  }
}
```

**Field Descriptions:**

| Field | Type | Description |
|-------|------|-------------|
| `flow_type` | string | 流程类型: `shipping` (物流换货) or `direct` (直接换货)。历史数据为空时视为 `shipping` |
| `flow_type_name` | string | 流程类型名称: "物流换货" or "直接换货" |
| `shipped_at` | string\|null | 发货时间，仅 `shipping` 流程发货后有值 |
| `completed_at` | string\|null | 换货完成时间，换货完成后有值 |

**Backend Behavior:**

- Only returns exchanges where `flow_type = shipping` AND `status IN (1, 2, 3)`
- `direct` type exchanges are never returned (they complete immediately on creation)
- If no pending exchange exists, returns `data: null`

### POST /api/c/v1/exchange/{id}/shipping-info

**Response includes the same new fields as above**

**Backend Constraints:**

- Only accepts `flow_type = shipping` AND `status = 1`
- Returns 400 error if `flow_type = direct`: `{"code": 400, "message": "流程类型不支持该操作"}`
- Returns 400 error if status is not 1: `{"code": 400, "message": "当前状态不允许填写收货信息"}`

## UI Changes

### Exchange Detail Card

Add flow type display in the exchange info section:

**Before:**
```
换货原因: 设备损坏
申请时间: 2026-06-03 10:00:00
收件人: 张三
联系电话: 13800138000
收货地址: 北京市朝阳区xxx路xxx号
```

**After:**
```
换货类型: 物流换货
换货原因: 设备损坏
申请时间: 2026-06-03 10:00:00
发货时间: 2026-06-04 15:30:00 (仅已发货时显示)
完成时间: 2026-06-05 10:00:00 (仅已完成时显示)
收件人: 张三
联系电话: 13800138000
收货地址: 北京市朝阳区xxx路xxx号
```

**Display Rules:**

1. **换货类型**: Always display `flow_type_name` if present, fallback to "物流换货" if empty
2. **发货时间**: Only display if `shipped_at` is not null
3. **完成时间**: Only display if `completed_at` is not null and `status === 4`

### Error Handling

When submitting shipping info fails with flow type error:

```javascript
// Existing error handling should catch and display backend error message
catch (error) {
  console.error('提交换货信息失败', error);
  // Backend will return: {"code": 400, "message": "流程类型不支持该操作"}
  // Default error toast will show this message
}
```

## Implementation

### 1. Update API Module Types

No changes needed to `api/modules/exchange.js` - it already passes through all response fields.

### 2. Update Exchange Page Template

File: `pages/device-exchange/device-exchange.vue`

Add flow type and timestamp displays:

```vue
<view class="exchange-info">
  <view class="info-row flex-row-sb">
    <view class="info-label">换货类型</view>
    <view class="info-value">{{ exchangeData.flow_type_name || '物流换货' }}</view>
  </view>
  <view class="info-row flex-row-sb">
    <view class="info-label">换货原因</view>
    <view class="info-value">{{ exchangeData.exchange_reason }}</view>
  </view>
  <view class="info-row flex-row-sb">
    <view class="info-label">申请时间</view>
    <view class="info-value">{{ formatTime(exchangeData.created_at) }}</view>
  </view>
  <view class="info-row flex-row-sb" v-if="exchangeData.shipped_at">
    <view class="info-label">发货时间</view>
    <view class="info-value">{{ formatTime(exchangeData.shipped_at) }}</view>
  </view>
  <view class="info-row flex-row-sb" v-if="exchangeData.completed_at && exchangeData.status === 4">
    <view class="info-label">完成时间</view>
    <view class="info-value">{{ formatTime(exchangeData.completed_at) }}</view>
  </view>
  <!-- Existing recipient fields -->
</view>
```

### 3. No Button Logic Changes

Since `direct` type exchanges never appear in pending (they complete immediately), the existing button visibility logic remains valid:

```vue
<view class="exchange-actions" v-if="exchangeData.status === 1">
  <button class="btn-apple btn-primary" @tap="openPopup">填写信息</button>
</view>
```

Backend enforces that only `shipping` + status 1 can submit shipping info, so frontend doesn't need additional flow type checks.

## Testing Scenarios

### 1. Shipping Flow Exchange (Existing Behavior)

- Load pending exchange with `flow_type: "shipping"`, `status: 1`
- Verify "换货类型: 物流换货" displays
- Verify "填写信息" button shows
- Submit shipping info successfully
- Verify response includes new fields

### 2. Shipped Exchange

- Load exchange with `flow_type: "shipping"`, `status: 3`, `shipped_at: "2026-06-04T15:30:00+08:00"`
- Verify "发货时间" row displays
- Verify no action buttons show

### 3. Completed Exchange

- Load exchange with `flow_type: "shipping"`, `status: 4`, `completed_at: "2026-06-05T10:00:00+08:00"`
- Verify "完成时间" row displays
- Verify no action buttons show

### 4. No Pending Exchange

- Call API with no pending exchange
- Verify empty state shows: "暂无换货记录"

### 5. Error Handling (Edge Case)

If somehow a `direct` type exchange appeared and user tried to submit shipping info (should not happen), backend returns 400 error which existing error handler will toast.

## Backward Compatibility

- Historical data without `flow_type` will be treated as `shipping` (per backend spec)
- All new fields are optional in frontend display logic
- Existing shipping submission flow is unchanged
