6bb0e65d4c
Task 4: 统一 amap.ts 为完整 API 客户端 - 扩展 amap.ts 为统一客户端(amapFetch 8s 超时 + 错误处理) - 导出 searchPlaceText/searchPlaceAround/getInputTips/reverseGeocode/getTransitDirection - 精简 4 个 location route 为单行调用,blindboxPlanGen 删除 ~80 行内联 API 代码 Task 2: 抽取 ShareCardShell 消除三兄弟重复 - 新建 ShareCardShell.tsx 共享外框/背景/品牌头/QR 底部 - RestaurantShareCard 406→268 行,BlindboxShareCard 341→173 行,BlindboxPlanShareCard 277→159 行 Task 3: 拆分 BlindboxPlan.tsx (742→371 行) - 提取 planUtils.ts (guessCategory + formatDuration) - 提取 PoiSearchField / SortablePlanItem / PlanItemEditModal 三个独立组件 Task 1: 拆分 blindbox/[code]/page.tsx 上帝组件 (1300→509 行) - 提取 useBlindboxRoom / useBlindboxIdeas / useBlindboxPlan / useBlindboxDraw 四个 hooks - 提取 BlindboxPoolPhase / BlindboxRevealPhase 两个子组件 - 主页面仅保留 phase 协调 + hook 组装 + 子组件渲染 Task 5: 统一 SWR 数据获取层 - 新建 fetcher.ts (FetchError 携带 status,401 不重试) - 新建 useBlindboxRooms / useAchievements / useFavorites SWR hooks - useRoomPolling 改用共享 fetcher - blindbox 大厅/成就/个人中心页面删除手写 fetch 样板代码 - JWT 过期时自动弹出登录框而非反复重试
23 lines
1.0 KiB
TypeScript
23 lines
1.0 KiB
TypeScript
export function guessCategory(activity: string): string | null {
|
|
const lower = activity.toLowerCase();
|
|
if (/吃|餐|饭|火锅|烧烤|面|菜|厨|食/.test(lower)) return "dining";
|
|
if (/手作|工坊|烘焙|插花|陶艺|DIY|体验/.test(lower)) return "experience";
|
|
if (/露营|徒步|赶海|农场|自然|野|营地/.test(lower)) return "nature";
|
|
if (/公园|山|湖|海|户外|骑/.test(lower)) return "outdoor";
|
|
if (/电影|KTV|密室|游戏|桌游|剧/.test(lower)) return "entertainment";
|
|
if (/逛街|购物|商场|买/.test(lower)) return "shopping";
|
|
if (/运动|健身|球|跑|游泳|瑜伽/.test(lower)) return "sports";
|
|
if (/博物馆|展览|美术|书/.test(lower)) return "culture";
|
|
if (/咖啡|茶|SPA|按摩|下午茶/.test(lower)) return "relaxation";
|
|
return null;
|
|
}
|
|
|
|
export function formatDuration(minutes: number): string {
|
|
if (minutes >= 60) {
|
|
const h = Math.floor(minutes / 60);
|
|
const m = minutes % 60;
|
|
return m > 0 ? `${h}h${m}min` : `${h}h`;
|
|
}
|
|
return `${minutes}min`;
|
|
}
|