文件预览

SKILL.md

查看 12306 Train Booking 技能包中的文件内容。

文件内容

SKILL.md

---
name: 12306-android-adb
description: 12306-specific knowledge for booking train tickets. Covers app UI structure, station search behavior, booking flow, and common pitfalls. Uses the appium-android-adb bridge for all screen interaction — NEVER use raw ADB commands on 12306.
---

# 12306 Train Booking

12306-specific knowledge, workflows, and pitfalls. For screen interaction, use the `appium-android-adb` skill (`bridge_daemon.py`).

## 🚨 Before Any 12306 Action

Start the Appium bridge (once per session):

```bash
bash ~/.openclaw/workspace/skills/appium-android-adb/start_bridge.sh
```

All screen interactions use `python3 ~/.openclaw/workspace/skills/appium-android-adb/bridge_daemon.py <command>`.

## ⚠ Never Use Raw ADB on 12306

The 12306 app uses UC WebView for the train list and booking pages. **ADB `input tap` is IGNORED.** Always use `bridge_daemon.py` from `appium-android-adb`.

## 12306 App Structure

| Page | Package/Activity | How to Detect |
|------|-----------------|---------------|
| Home | `com.MobileTicket` / `MainActivity` | `ticket_home_btn_search` button exists |
| Train list | `com.MobileTicket` / `H5Activity` | `title` contains `<>` (e.g. "上海 <> 苏州") |
| Booking | same H5Activity | "预订" buttons exist |
| Confirmation | same H5Activity | "提交订单" button exists |
| Payment | same H5Activity | "立即支付" or "去支付" button |

### Key Element IDs (Home Page)

| Element | Resource ID |
|---------|------------|
| Search button | `ticket_home_btn_search` |
| Departure station | `home_page_train_dep1` |
| Arrival station | `home_page_train_arr1` |
| Date container | `home_page_depart_date_view_container` |

## ⚠ Station Search Behavior

**Any station in a city searches ALL stations in that city.** Example:
- "上海虹桥→苏州" also shows trains from 上海站, 上海南站, 上海松江 etc.
- "上海→苏州北" also shows trains to 苏州站, 苏州园区, 苏州新区 etc.

**Once you have ANY valid city-to-city search result, NEVER go back to change stations.** If the target train isn't immediately visible, just scroll — it's in the list.

## Booking Flow

### Step 1: Home page — ensure valid city pair + date
```
dump → check current stations and date
If stations show any valid city pair (e.g. "上海虹桥→苏州" or "上海→苏州北"):
  → SKIP station changes. All trains from both cities will appear.
If stations are completely wrong:
  → tap departure, pick ANY station in correct city
  → tap arrival, pick ANY station in correct city
tap date container → pick target date
tap "查询车票"
```

### Step 2: Find and select train
```
dump → check trains[] for target train number
scroll down → dump → repeat until target appears
tap train by text (e.g. '{"text": "G7004"}')
→ train detail / booking page appears
```

### Step 3: Book seat
```
dump → see seat options, look for "预订" buttons
tap '{"text": "预订", "index": 0}'  → first is usually 二等座
```

### Step 4: Fingerprint (manual — tell user)
```
If alert with "指纹" appears: tell user to authenticate on phone. Wait, then dump to verify.
```

### Step 5: Confirm and submit
```
dump → verify train, passenger, seat, price
If passenger not selected: tap "选择乘车人" → tap passenger name
tap "提交订单"
```

### Step 6: Payment (user handles Alipay/WeChat)
```
dump → tap "立即支付" or "去支付"
→ User handles Alipay/WeChat login manually
```

## Decision Tree

```
dump the screen:
  ├─ package != "com.MobileTicket" → app not in foreground, tap app icon or adb shell monkey
  ├─ "ticket_home_btn_search" in buttons → HOME PAGE
  │   → ensure valid city pair (any station!) + date → tap 查询车票
  ├─ title contains "<>" → TRAIN LIST
  │   → scroll + dump to find target train → tap it
  │   → NEVER go back to change stations — scroll instead
  ├─ "预订" in buttons → BOOKING PAGE
  │   → tap 预订 for seat type
  ├─ "提交订单" in buttons → CONFIRMATION
  │   → verify details → select passenger → submit
  ├─ "立即支付" in buttons → PAYMENT
  │   → tap to pay, user handles auth
  └─ alerts not empty → dismiss first, re-dump
```

## Common Pitfalls

- **Going back to change stations**: Don't. Any station in a city shows all trains. Just scroll.
- **Train at viewport edge (h=6)**: Scroll slightly to bring it into view, then tap.
- **Fingerprint dialog**: Cannot automate. Tell user to authenticate.
- **Session timeout**: The bridge daemon holds a persistent session — no timeout issues.
- **Wrong date on train list**: The results page has date tabs at the top. Tap the correct date there directly.

## Files

- `adb_helper.py` — Low-level ADB helper (native element dump/find/tap/swipe). Use for pre-Appium checks or native-only pages.
- `SKILL.md` — This file. 12306-specific knowledge.
- `README.md` — Reference docs.