feat: AI 辅助修改行程(自然语言调整 + 单活动替代推荐)
- 新增 refinePlan / suggestAlternativeItems 到 ai.ts - 新增 POST /api/blindbox/plan/refine(整体行程调整) - 新增 POST /api/blindbox/plan/suggest-item(单活动 AI 替代 + POI 搜索) - BlindboxPlan 底部新增自然语言输入框(方案 A) - 编辑 modal 内新增 AI 推荐替代方案卡片(方案 B) - export searchPois 供 suggest-item 路由复用
This commit is contained in:
@@ -627,6 +627,24 @@ export default function BlindboxRoomPage() {
|
||||
}
|
||||
}, [planId, profile, planDays, planAccepted, toast]);
|
||||
|
||||
const handleRefine = useCallback(async (instruction: string) => {
|
||||
if (!profile || !planDays.length) return;
|
||||
const prevDays = planDays;
|
||||
try {
|
||||
const res = await fetch("/api/blindbox/plan/refine", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ userId: profile.id, instruction, days: planDays }),
|
||||
});
|
||||
if (!res.ok) throw new Error((await res.json().catch(() => ({}))).error || "AI 调整失败");
|
||||
const data = await res.json();
|
||||
await handlePlanDaysChange(data.days);
|
||||
} catch (e) {
|
||||
setPlanDays(prevDays);
|
||||
toast.show(e instanceof Error ? e.message : "AI 调整失败");
|
||||
}
|
||||
}, [profile, planDays, handlePlanDaysChange, toast]);
|
||||
|
||||
/** Non-creator: leave room (remove membership). Creator: delete room (after confirm). */
|
||||
const handleLeaveOrDelete = async () => {
|
||||
if (!confirmLeave) {
|
||||
@@ -1112,6 +1130,7 @@ export default function BlindboxRoomPage() {
|
||||
accepted={planAccepted}
|
||||
regenerating={generating}
|
||||
onDaysChange={handlePlanDaysChange}
|
||||
onRefine={handleRefine}
|
||||
location={room.lng != null && room.lat != null ? `${room.lng},${room.lat}` : undefined}
|
||||
onAccept={async () => {
|
||||
setPlanAccepted(true);
|
||||
|
||||
Reference in New Issue
Block a user