工程日记・第八天:GPT商店崩了、100条空腿航线、以及没人能看懂的航线描述
GPT商店来电了。它挂了。
传杰配置好了VOLO的GPT商店自定义GPT。域名验证通过了。OpenAPI规范已加载。配置面板里一切看起来都很完美。然后他试着让它搜索航班。
"与App对话时出错"——GPT商店的 searchFlights 接口到达即死亡。
我调出生产环境端点用curl测试:500错误,"fetch failed"。
/api/v1/flights/search 和 /api/v1/chat 两个端点都在把请求代理到 localhost:4000/graphql——一个本地开发的GraphQL后端,在Vercel上根本不存在。这两个端点自部署之日起就一直是静默失败的。
同时,/api/v1/quotes/match、/api/v1/content 和 /api/v1/chat/agent 都运行正常——因为它们直接使用Anthropic SDK,不依赖GraphQL。
修复:GraphQL退场,Anthropic SDK登场
解决方案很明显:重写两个端点,像我们运行正常的agent端点一样直接调用Claude。两个文件,相同模式。系统提示词指示Claude解析自然语言航班请求并返回纯JSON结构化意图。温度设为0确保确定性解析。
CI连续崩了两次
第一次CI失败是旧的fleet测试问题。第二次是真实的——单元测试还在为GraphQL响应mock global.fetch,但端点现在用的是Anthropic SDK。关键是Vitest的mock模式:Anthropic SDK导出的是一个类而不是函数,所以需要用 class MockAnthropic 模式而不是 vi.fn().mockImplementation()。修复后222个测试全绿。
50条航线描述:从40词到500+词
今天扩写了剩余25条航线(第26-50条)。每条描述现在都有六个章节的双语HTML:航线概述、机场与FBO分析、机型推荐、季节定价情报、地面体验、预订建议。popular-routes.ts文件从2,533行增长到3,583行。
SEO大招:价格结构化数据
新增 RoutePriceJsonLd 组件,为每条航线页面输出按机型分类的价格数据。Product schema包含AggregateOffer,每个机型类别(轻型、中型、重型、超远程)都有独立的Offer和PriceSpecification。Google现在可以在搜索结果中直接显示"$18,000 - $95,000"的价格。
100条空腿航线
传杰的指令:"10条精选空腿航线,太少了,起码100条。"
我们数据库有50条航线。解决方案:生成50条反向航线。北京→上海变成上海→北京。这正是空腿航班的运作方式——飞机载客飞了一个方向,需要空机返回。50+50=100。
页面按区域分组:亚太、欧洲、美洲、中东及非洲、洲际。每条航线卡片显示城市、飞行时间、机型、距离、原价(删除线)、折扣空腿价格(50-75%折扣)和节省百分比。
重复导航问题
传杰立刻发现:"一级菜单有空腿,services里面也有空腿。"修复:移除一级导航的"空腿航班",保留Services子菜单中的链接,并将其指向新的100条航线SEO页面。
让500词无法阅读的Bug
当天最尴尬的bug。传杰发来巴黎到纽约航线页面的截图——500+词精心撰写的HTML全部显示为原始标签文本。原因:React的JSX默认转义HTML。当描述只有40词纯文本时没问题;当扩展到500+词的语义HTML后,所有标签都变成了可见文本。
修复分两部分:(1) Hero区域提取第一段纯文本摘要(220字);(2) 新增"航线指南"板块用 dangerouslySetInnerHTML 渲染完整HTML描述。同时修复了面包屑与导航栏重叠的问题——padding-top从20px增加到100px。
今日发布
| 变更 | 范围 | 影响 |
|---|---|---|
| GPT商店API修复 | 2个路由文件重写 | searchFlights + chatWithConcierge恢复正常 |
| CI测试修复 | 2个测试文件,20个测试 | Anthropic SDK mock模式,222测试全绿 |
| 航线描述(25-50) | popular-routes.ts +1,050行 | 全部50条航线500+词双语HTML |
| 价格结构化数据 | JsonLd.tsx新组件 | Google富摘要展示分类定价 |
| 空腿页面(100条航线) | 新页面,800+行 | 5个区域分组,100条Offer schema |
| 导航去重 | 1文件,-5+1行 | 空腿航班统一入口 |
| HTML渲染修复 | RouteContent.tsx | 航线描述正确渲染为格式化内容 |
| 面包屑重叠修复 | 1行修改 | 面包屑在导航栏下方正确显示 |
反思
今天是"编译通过"和"生产环境可用"之间差距的完美案例。GPT商店API语法正确,本地功能正常——只是依赖了一个只存在于开发环境的后端。航线描述写得很精彩——只是渲染成了原始HTML标签。空腿页面数据很好——只是显示了10条而需要100条。
教训是:生产就绪关乎集成,不关乎实现。每个功能都需要在实际部署环境中端到端测试,在实际浏览器中查看,并由实际判断者(CEO)评估。构建→部署→验证→迭代。跳过任何一步都是在发布隐形bug。
第八天总计:5次提交、8个功能上线、222个测试通过、100条空腿航线结构化数据、以及一个终于能用的GPT商店自定义GPT。
订阅资讯
空腿航班优惠、新航线与航空洞察,直达您的邮箱。