Files
no-whatever/src/app/api/blindbox/room/[code]/route.ts
T
kurihada 99120a7042 feat: 交通信息与 AI 解耦,完善出发/回程路线显示
- 从 finalize_plan schema 和 agent 提示词中移除 transit 字段,AI 只负责活动/POI/坐标
- 新增 enrichTransitInfo:计划生成后查询高德 V3 公交 API,计算出发地→首活动、活动间、末活动→出发地三段交通
- parseTransitSegments 增加起终点站显示(去除线路名中的全程终点括号)
- WeekendPlanData 新增 transitFromStart/transitToEnd 字段
- BlindboxPlan 新增出发地和返回出发地交通连接器,传入 startLocationLabel 显示具体地址
- BlindBoxRoom schema 新增 address 字段存完整逆地理地址,city 保留供 API 使用
- 新增 /api/debug/transit 调试端点(仅开发环境)
- agent userPrompt 要求将出发/回程时间计入全天时间预算
2026-03-02 16:35:38 +08:00

93 lines
2.6 KiB
TypeScript

import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { getRoomByCode, requireMembership } from "@/lib/blindbox";
import { apiHandler, ApiError, requireUserId } from "@/lib/api";
export const GET = apiHandler(async (_req, { params }) => {
const { code } = await params;
const room = await getRoomByCode(code.toUpperCase());
if (!room) throw new ApiError("房间不存在", 404);
return NextResponse.json({
id: room.id,
code: room.code,
name: room.name,
creatorId: room.creatorId,
city: room.city,
address: room.address,
lat: room.lat,
lng: room.lng,
poolCount: room._count.ideas,
members: room.members.map((m) => ({
...m.user,
joinedAt: m.joinedAt,
})),
});
});
export const PATCH = apiHandler(async (req, { params }) => {
const { code } = await params;
const { userId, city, address, lat, lng } = await req.json();
requireUserId(userId);
const room = await prisma.blindBoxRoom.findUnique({
where: { code: code.toUpperCase() },
});
if (!room) throw new ApiError("房间不存在", 404);
await requireMembership(room.id, userId);
const numLat = Number(lat);
const numLng = Number(lng);
if (
!Number.isFinite(numLat) || !Number.isFinite(numLng) ||
numLat < -90 || numLat > 90 || numLng < -180 || numLng > 180
) {
throw new ApiError("位置坐标无效");
}
const updated = await prisma.blindBoxRoom.update({
where: { id: room.id },
data: {
city: typeof city === "string" ? city.trim() : null,
address: typeof address === "string" ? address.trim() : null,
lat: numLat,
lng: numLng,
},
});
return NextResponse.json({
city: updated.city,
address: updated.address,
lat: updated.lat,
lng: updated.lng,
});
});
export const DELETE = apiHandler(async (req, { params }) => {
const { code } = await params;
const { userId } = await req.json();
requireUserId(userId);
const room = await prisma.blindBoxRoom.findUnique({
where: { code: code.toUpperCase() },
});
if (!room) throw new ApiError("房间不存在", 404);
if (room.creatorId === userId) {
await prisma.blindBoxRoom.delete({ where: { id: room.id } });
return NextResponse.json({ action: "deleted" });
}
const membership = await prisma.blindBoxMember.findUnique({
where: { roomId_userId: { roomId: room.id, userId } },
});
if (!membership) throw new ApiError("你不是该房间成员", 403);
await prisma.blindBoxMember.delete({ where: { id: membership.id } });
return NextResponse.json({ action: "left" });
});