文件内容
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.