统一数据字典
修改记录
日期 |
变更 |
|---|---|
2026-07-18 |
从引擎内部 5 种类型扩展为全链路数据字典(API → 引擎 → 前端) |
单位约定
量 |
单位 |
说明 |
|---|---|---|
距离 |
km |
行驶距离 |
时间 |
min |
旅行耗时、时间窗、停留时长 |
速度 |
km/h |
旅行速度(默认 1.0——仅测试实验集使用,真实数据由高德驾车 API 提供,不依赖此值) |
经纬度 |
GCJ-02 |
高德坐标系,x=经度,y=纬度 |
索引 |
0=depot |
0 索引始终为酒店,景点从 1 开始 |
时间窗 |
(start, end) |
距午夜分钟数,0=00:00,1440=24:00 |
一、POI 与地图数据
POIItem(API 请求)
前端传给后端的单个景点参数。定义见 backend/api/schemas.py:6。
字段 |
类型 |
默认值 |
说明 |
|---|---|---|---|
|
|
— |
景点名称 |
|
|
— |
GCJ-02 经度 |
|
|
— |
GCJ-02 纬度 |
|
|
480 |
营业开始(8:00) |
|
|
1020 |
营业结束(17:00) |
|
|
0 |
建议停留时长 |
|
|
None |
用户期望到达时间 |
POILookupResponse(API 响应)
POI 查询结果。定义见 backend/api/schemas.py:54。
{
items: POILookupItem[], // 查询成功列表
failed: string[] // 未找到的名称
}
POILookupItem:
name, lon, lat, address
tw_start: int | None // LLM 解析结果,None 表示解析失败
tw_end: int | None
tw_start/tw_end为int | None:若 LLM 无法从高德opentime2解析出营业时间,返回 None。前端暂未处理此情况。
PoiCache / PoiCacheItem(引擎内存缓存)
后端内部映射,见 backend/typedefs.py:27。
PoiCache:
hotel: PoiCacheItem
spots: PoiCacheItem[]
PoiCacheItem:
name, lon, lat
tw: (float, float) // 与 API 不同,这里为元组 (start, end)
stay: float
SpotDict(引擎求解器核心类型)
引擎内部景点类型,求解器和聚类算法直接使用。定义见 backend/typedefs.py:11。
字段 |
类型 |
必填 |
说明 |
|---|---|---|---|
|
|
✅ |
景点名称 |
|
|
✅ |
GCJ-02 经度 |
|
|
✅ |
GCJ-02 纬度 |
|
|
✅ |
有效时间窗 |
|
|
✅ |
停留时长(分钟) |
|
|
✅ |
原始营业时间窗,来自 POI 查询结果,用于对照 |
|
|
❌ |
与 x 重复的兼容字段 |
|
|
❌ |
与 y 重复的兼容字段 |
|
|
❌ |
期望到达时间,影响 |
tw的收缩规则在pipeline.py:97-117:effective_start = max(tw_start, expected_arrival, day_start)effective_end = tw_end - stay
二、规划请求
PlanRequest(统一请求体)
适用于 /api/suggest 和 /api/plan 两个端点。定义见 backend/api/schemas.py:67。
{
city: string // 城市名
hotel_name, hotel_lon, hotel_lat, hotel_tw_start: 0, hotel_tw_end: 1440
spots: POIItem[] // 至少 1 个
n_days: int | null // null → 建议模式,有值 → 规划模式
mode: "fast" | "deep" // fast=CA求解器,deep=VNS求解器
day_start: float // 启程时间,默认 0=午夜
min_days: int | null // 建议模式的最小天数,null 时引擎自动推断
// 矩阵复用(来自 suggest 响应):
cost_matrix: number[][] | null
dist_matrix: number[][] | null
// 惩罚权重:
penalty_weight: 100 // 迟到惩罚
early_wait_weight: 0.1 // 早到等待
late_return_weight: 50 // 晚归
}
PlanAdjustRequest(规划调整)
重新规划请求,见 backend/api/schemas.py:130。
{
spots: dict // 当前景点字典
cost_matrix: number[][]
dist_matrix: number[][]
routes: list
adjustments: { // 调整指令
balance?: true, // 均衡天数
change_days?: 3, // 改天数
remove_poi?: "故宫", // 移除景点
add_poi?: {...} // 添加景点
}
}
三、规划结果
RouteResult(求解器原始输出)
solve_groups 的返回,定义见 backend/typedefs.py:44。
字段 |
类型 |
说明 |
|---|---|---|
|
|
每组 |
|
|
收敛历史(可选) |
|
|
总成本 min, |
|
|
总行驶距离 km |
|
|
总等待时间 min |
|
|
总迟到时间 min |
|
|
是否覆盖全部景点 |
ScheduleItem(每日行程单条)
重建行程的产物,定义见 backend/typedefs.py:63 和 frontend/src/types.ts。
{
name: string // 景点名称
arrival: int // 到达时间(距午夜分钟数)
departure: int // 离开时间(距午夜分钟数)
tw: string // 营业时间窗 "HH:MM - HH:MM"
stay: string // 停留时长 "X min"
arrival_status: string // "正常到达" / "早到 X 分钟" / "迟到 X 分钟"
departure_status: string // "正常离开" / "迟到 X 分钟离开"
}
后端
stay为str(含单位),前端types.ts中为number(纯数值)。
PlanResult(完整规划结果)
run_planning 的最终返回,定义见 backend/typedefs.py:74 和 frontend/src/types.ts。
{
type: string // "suggestion" 或 "solution"
solution?: {
routes, total_cost, total_dist, wait, late, valid
}
best_days: int // 建议天数
best_m: string // 最优方法名称
spots: { // 景点字典,key=索引
"1": { name, x, y, tw, stay, original_tw, ... }
}
daily_schedules: [ // 每日行程
[ScheduleItem, ...], // Day 1(首尾为酒店出发/返回)
[ScheduleItem, ...], // Day 2
]
commentary: string // AI 评语(仅 solution 模式有)
cost_matrix: number[][] // N+1 × N+1 成本矩阵(分钟)
dist_matrix: number[][] // N+1 × N+1 距离矩阵(km)
polylines: { // 真实路径坐标
"0_3": "116.39,39.91;116.40,39.92;..."
}
amap_api_key: string
amap_security_code: string
algo_time: float // 算法耗时(秒)
}
suggestion模式会为每条建议调用_rebuild_schedule,返回daily_schedules。type="solution"时额外包含commentary。
SuggestionItem(建议列表条目)
POST /api/suggest 响应中 suggestions[] 的元素类型,见 frontend/src/types.ts。
{
n_days: int
method: string
cost: number, total_dist: number, wait: number, late: number
routes: number[][]
daily_schedules?: ScheduleItem[][]
}
四、历史记录
HistoryCreate(创建请求)
保存方案到分享站,定义见 backend/api/schemas.py:147。
{
device_id: string | null // 匿名设备标识,用于删除时鉴权
note: string | null // 用户备注
city: string
hotel: string | null
n_days: int
cost: float | null
spot_count: int | null
plan_result: dict // 完整 PlanResult(JSONB 存储)
request_params: dict|null // 原始请求参数(buildRequest 产物)
}
HistorySummary(列表项)
分页列表的每条摘要,见 backend/api/schemas.py:165。
{
id: string, city: string, hotel: string|null, n_days: int
cost: float|null, spot_count: int|null, note: string|null
created_at: string // ISO 8601
}
HistoryDetail(完整详情)
单条历史完整数据,见 backend/api/schemas.py:177。
{
id, city, hotel, n_days, cost, spot_count, note, created_at
plan_result: dict // 全量 PlanResult
request_params: dict|null
}
五、数据流映射
前后端类型对应
逻辑概念 |
API(schemas.py) |
后端引擎(typedefs.py) |
前端(types.ts) |
|---|---|---|---|
景点参数 |
|
|
|
POI 查询 |
|
|
|
规划请求 |
|
— |
|
求解结果 |
— |
|
|
行程项 |
— |
|
|
完整结果 |
— |
|
|
建议项 |
— |
— |
|
历史摘要 |
|
ORM 行 |
|
历史详情 |
|
ORM 行 |
|
索引约定
所有数组和字典的 0 索引固定为酒店(depot)
routes序列:[0, 3, 1, 0]意为酒店 → 景点3 → 景点1 → 酒店前端构建 PlanResult 时,
best_days与daily_schedules.length一致polylines的 key 格式为"{fromIdx}_{toIdx}",如"0_3":depot 到景点3
边界与约束
约束 |
值 |
来源 |
|---|---|---|
景点数下限 |
1 |
|
天数范围 |
[min_days, n_spots] |
|
天数下界(默认) |
|
|
聚类方法数 |
6 |
|
成本矩阵形状 |
(N+1, N+1) |
N=景点数 |
VNS 精英池容量 |
3 |
|