news 2026/10/14 18:42:48

一份旅行文档统治一切:palantir-for-family-trips的9类实体trip document数据模型设计

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
一份旅行文档统治一切:palantir-for-family-trips的9类实体trip document数据模型设计

【免费下载链接】palantir-for-family-trips

A Palantir-ish dashboard for family trip planning.

项目地址:https://gitcode.com/gh_mirrors/pa/palantir-for-family-trips
点击查看免费下载

palantir-for-family-trips 是一个把家庭旅行做成"作战指挥中心"的开源规划看板。它的核心不是数据库,而是一份完整的trip document(旅行文档):家庭、地点、路线、餐饮等 9 类实体全部装在这份 JSON 文档里,靠linkedEntityKeys互相引用,整体持久化在浏览器 localStorage 中。读懂这份文档的结构,就读懂了整个应用。

为什么用"一份旅行文档"管理整个行程?🧭

多家庭同游本质上是个小型系统问题:三个家庭从不同城市错峰出发、共享一处营地、轮流订餐、还要分摊费用。传统做法是多张表格加群聊记录,而 palantir-for-family-trips 选择把所有信息收敛成单一事实来源:

  • 没有后端、没有数据库,整份 trip document 存进 localStorage,存储键为trip-command-center/v4-public(见 tripModel.js)
  • Itinerary、Meals、Activities 等页面只是同一份文档的不同"投影"
  • 修改任何实体(比如勾掉一个任务),整份文档重新渲染,数据天然一致

持久化逻辑薄到不能再薄:usePersistedTripState.js 就是一个"读 JSON → 存 JSON"的 React Hook,真正的复杂度全部集中在 tripModel.js 的文档模型里。

trip document 的 9 类实体全景 📐

初始化函数 createInitialTripDocument 返回的文档结构一目了然——9 个实体集合加少量 UI 状态:

实体类型文档字段对应页面负责什么
familyfamiliesFamilies家庭单位:出发城市、ETA、车辆、准备度
locationlocationsStay / Meals 等地点:营地、餐厅、补给点、公园入口
routeroutesItinerary路线:起终点、途经点、回放窗口
itineraryItemitineraryItemsItinerary时间轴上的行程段(startSlot+span)
mealmealsMeals每一餐:时间、地点、状态、负责人
activityactivitiesActivities每日主题:风险、天气敏感度、降级方案
stayItemstayItemsStay住宿事务:门禁、分房、停车、退房
expenseexpensesExpenses费用:付款人、金额、分摊模式
tasktasksItinerary / Families待办任务:归属家庭、完成状态

类型到集合字段的映射写死在 COLLECTION_BY_TYPE,实体到页面的映射在 ENTITY_PAGE。注意location是特例——它被多个页面共享,isEntityOnPage 里专门放宽了归属规则,因为餐厅、营地、湖滩天然跨场景使用。

9 类实体逐个拆解 🔍

人:family 与 task

family实体记录出发地、ETA、车辆和readiness准备度,并用taskIds直接挂着自家待办。每个task有ownerFamilyId和status,getFamilyReadiness 直接用"已完成任务 ÷ 总任务"实时算出准备度——派生指标不落库,永远新鲜。

地:location

location用category细分为stay(营地)、meal(餐厅)、activity(活动区)、logistics(补给点)、park(公园入口)。营地实体还带入住/退房时间、Wi-Fi、照片等完整字段,是所有路线的目的地锚点。

动:route 与 itineraryItem

这是最有"指挥中心味道"的一对:itineraryItem是时间轴上的色块,route是地图上的线与点。

  • route 有originCoordinates、destinationLocationId、stopLocationIds,路径由 synchronizeRoutePaths 从 locations 的坐标自动拼装——坐标只存一份,永不漂移
  • route 用simulationStartSlot / simulationEndSlot定义回放窗口,simulationMilestones甚至能模拟中途停车
  • 路线与行程段通过linkedEntityKey双向绑定

事:meal、activity 与 stayItem

meal记录每餐的timeLabel、locationId和reservationType(Cook-in / Pack-out / Walk-in);activity是每日"主题任务",带status(Go/Watch)、riskLevel、weatherSensitivity和backup降级方案;stayItem则把住宿拆成门禁、分房、停车、退房四个可独立追踪的事务。

钱:expense

expense除了金额和付款人,还有allocationMode(equal / individual / manual)和allocations明细字典——分摊规则与分摊数据分离,改规则不动数据。

linkedEntityKeys:用字符串键把实体串成一张图 🕸️

整套模型最精妙的设计在 makeEntityKey:它把"类型 + id"拼成family:north-star、meal:thu-dinner这样的字符串键。每个实体都可以携带linkedEntityKeys数组指向其他实体,不建外键表,一张轻量引用网就搭好了:

  • 选中一个 activity,getLinkedEntities 顺键找出它关联的行程段、餐饮和地点
  • getTimelineContext 用时间轴光标找出"正在发生"和"即将发生"的实体,再顺藤摸出关联的未完成待办
  • 界面里的"关联实体"、"规划任务"面板,都是同一张网的投影

slot 时间轴:让所有页面对齐同一把标尺 ⏱️

tripData.js 定义了 4 天(DAYS)和每天的 4 个时段(TIME_SLOTS = ['00', '06', '12', '18'],每格 6 小时)。全行程因此被拉成一条 0~16 的 slot 数轴:startSlot: 2.09表示第 1 天第 3 个时段后 0.09 格,约等于周四 12:32。getSlotLabel 能把 slot 反解成Thu 12:32 PM这样的人类可读时间。行程段、餐饮、路线回放全部共用这把标尺,这就是"一条时间线统领所有页面"的底气。

版本化持久化:老数据如何平滑升级 📦

存储键里的v4是版本号,历史键(v1~v3)列在 LEGACY_TRIP_DOCUMENT_STORAGE_KEYS。升级路径分三步:

  1. migrateLegacyState:把老结构(比如内嵌在家庭里的 checklist)映射成独立的 task 实体
  2. refreshSeededDoc:用种子数据刷新文档,同时保留用户改过的字段(准备度、任务状态、费用明细等)
  3. projectTripDocument:公开分享模式下把家庭住址、Wi-Fi 密码等隐私字段全部洗掉

一套"迁移 + 刷新 + 脱敏"流程,让浏览器里的单文档能像正经数据库一样平滑演进。

给初学者的 3 点设计启发 💡

  1. 单一事实来源比"小而全"更简单:一个 JSON 文档 + localStorage,没有 schema 迁移烦恼,却同时支撑了六个页面
  2. 用字符串键建引用图:type:id键比外键表轻得多,非常适配前端单文档模型
  3. 派生值不落库:准备度、时间标签、路线 path 全部实时计算,文档只存最小事实

palantir-for-family-trips 把一次普通家庭周末硬生生做成了"作战指挥",而全部秘密就在这份结构清晰、引用自洽、可迁移可脱敏的 trip document 里。想动手改造,从 tripModel.js 入手,配合 README.md 了解启动方式、DESIGN.md 了解界面设计即可上手。

【免费下载链接】palantir-for-family-trips

A Palantir-ish dashboard for family trip planning.

项目地址:https://gitcode.com/gh_mirrors/pa/palantir-for-family-trips
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 18:41:54

微信小程序案例 3.5 计时器(增加背景文字:时间如流水)

一、案例简介 本案例是微信小程序计时器实现,基础功能实现计时、暂停、重置。扩展需求:在时间显示界面底层添加背景文字 “时间如流水”,作为页面装饰文字。本案例学习定时器、时间戳、页面布局 z-index 层级控制。 二、实现思路 计时原理&am…

作者头像 李华
网站建设 2026/10/14 18:41:17

jdk1.8.0_231.zip 部署指南:环境变量、多版本共存与容器化实践

简介:JDK1.8.0_231是Oracle于2019年发布的Java开发工具包64位版本,面向需要在Windows平台搭建Java开发环境的程序员与运维人员,尤其适合希望免安装、快速部署JDK的开发者。压缩包共1473个文件,约172.9MB,以705个jar核心…

作者头像 李华
网站建设 2026/10/14 18:40:36

AutoJs无障碍服务从源码到初始化:原理、配置与保活避坑指南

简介:面向AutoJs初学者与自动化脚本开发者,这份源码演示了如何通过无障碍服务实现辅助功能自动开启,适合快速上手自动点击、控件读取、界面判断等常见应用场景。包体非常精简,仅包含1个js格式脚本文件,压缩包大小约581…

作者头像 李华
网站建设 2026/10/14 18:40:28

Java土耳其语词干分析器:低攻击性策略优化搜索召回与精度

简介:一份面向 Java 开发者的土耳其语自然语言处理工具包,提供基于词素 n-gram 统计语言模型与词典驱动的词干分析器,相比常规土耳其语词干器攻击性更低、准确率更高,适合信息检索、文本挖掘等预处理场景。压缩包共 11 个文件&…

作者头像 李华