
TREK 创建行程完整指南对话框字段、权限、封面与数据模型全解析【免费下载链接】TREKA self-hosted travel/trip planner with real-time collaboration, interactive maps, PWA support, SSO, budgets, packing lists, and more.项目地址: https://gitcode.com/GitHub_Trending/nomad22/TREK本指南围绕 TREK自托管实时协作旅行规划器的行程创建流程展开系统讲解 Create Trip 对话框的打开方式、每个表单字段的语义与校验规则、封面图片的四种添加途径、行程提醒的服务端开关以及创建请求在前后端的数据流。读完本文你将掌握如何通过界面、深度链接或 API 三种方式创建行程并能理解day_count、reminder_days、currency等字段在 shared 契约 与 后端服务 中的真实约束。打开创建对话框创建行程的入口集中在仪表盘Dashboard页面上共有三种途径工具栏按钮点击仪表盘工具栏中的New Trip按钮空状态按钮当实例上还没有任何行程时页面会显示Create First Trip按钮点击同样打开对话框深度链接直接导航到/dashboard?create1。这是系统通知system notice提示创建行程时使用的 URL。深度链接的实现在 useDashboard.ts页面挂载时读取 URL 查询参数若create等于1则置showForm为true并立即用setSearchParams({}, { replace: true })清掉该参数避免刷新页面时对话框被意外再次弹出。此外移动端底部导航BottomNav.tsx和系统通知操作noticeActions.ts也都是通过navigate(/dashboard?create1)这种方式打开创建框的因此你在任何系统提示上点击创建行程最终都会落到同一个表单组件 TripFormModal.tsx。同一个表单组件同时承担创建与编辑两种职责trip属性为null时是创建模式非空时是编辑模式。两种模式下部分字段的可见性和权限要求不同下文会逐一说明。字段详解Title必填行程名称。空标题会阻塞保存——前端在校验失败时提示标题必填tripCreateRequestSchema在契约层也通过z.string().min(1)强制非空见 trip.schema.ts。提交时前端还会对标题做一次trim()处理去掉首尾空白。Description可选一段自由文本描述显示在行程卡片上。保存时空字符串会被规范化为null存入数据库。Dates日期使用日期选择器设置Start date与End date。两个日期都填好时**Day count天数**会自动计算。关键交互规则对应 TripFormModal.tsx 中的update函数两个日期都留空表单会切换到显示独立的Day count字段允许你输入1 到 365之间的整数创建一个无日期但有固定天数的行程。前端用NumericInput将输入钳制在1..365第 501-515 行提交校验同样要求为整数且处于该区间。只填一个日期正常交互下不可能出现有开始没结束的状态。设置开始日期时如果结束日期为空或早于开始日期结束日期会被自动补成同一天如果原本已有完整的起止区间则保持原有时长把结束日期整体后移。日期字段的提交逻辑位于 第 141-149 行只有当日历日期全部为空时payload 里才会携带day_count只要存在任一日期就以日期为准。在编辑模式下移动开始日期还有一个额外步骤由于行程的每日日程day grid跟随日期TREK 会弹出date shift确认框让你选择预订内容如何跟随新日期——keep_bookings默认日程随天移动、有明确日期的预订留在绝对日期上或shift_all整个行程含预订整体平移。该行为对应 tripUpdateRequestSchema 中的date_shift_mode枚举。Currency货币行程的记账本位币Costs费用标签页中的每一笔支出都会折算成该货币所有余额与结清建议也用它计算。默认值为EUR可选 165 种货币前端通过 BudgetPanel.constants.ts 的currenciesWith与SYMBOLS生成带符号的下拉选项。两点重要提示货币不是装饰性标签但也不是一锤子买卖。之后可以随时从同一对话框更改需trip_edit权限TREK 会重新折算既有费用账上金额不变。详见 Currencies → 更改行程货币。它不等于Settings → General 里的显示货币——后者只改变你自己阅读时的币种展示。详见 Currencies。后端在写入时同样做了兜底createTrip中data.currency || EURtripService.ts。Cover Image封面图封面图展示在行程卡片上同时也是 Spotlight 卡片的背景。添加方式有四种拖放把图片文件拖到虚线上传区域剪贴板粘贴对话框任意位置直接粘贴剪贴板中的图片由handlePaste监听onPaste事件实现第 305-317 行文件选择器点击上传区域浏览本地文件搜索 Unsplash输入关键词搜索图库照片。如果返回Unsplash search unavailable常见于 VPS / 机房 IP需要配置一个免费的 Unsplash Access Key——详见 Environment-Variables → Image Search (Unsplash) 一节服务端读取的正是UNSPLASH_ACCESS_KEY环境变量README.md 环境变量参考表中亦有说明。权限与时机差异创建新行程时封面字段始终可见图片不会立即上传而是先暂存在本地pendingCoverFile或pendingUnsplashUrl等行程创建成功拿到trip.id后再上传或保存第 179-196 行。编辑已有行程时仅当当前用户拥有trip_cover_upload权限才显示该字段此时选择图片会立即上传uploadCoverNow第 225-239 行。值得一提的实现细节iOS 上的 HEIC/HEIF 图片无法被浏览器直接渲染和存储因此所有封面文件在提交前都会经过normalizeImageFileutils/convertHeic.ts转成 JPEG。Unsplash 搜索还带有一个序号护栏coverSearchSeq只有最新一次请求的结果才会被应用慢返回的旧请求不会覆盖新结果。Reminder出发提醒出发前发送的推送通知。预设选项如下选项距出发天数None01 day13 days39 days9Custom1–30自行输入数字可见性规则创建时始终可见编辑时仅行程所有者或admin用户可见第 529 行 的权限判断。自定义输入同样被钳制在 1–30 之间。提醒由服务端特性开关trip_reminders_enabled控制若实例上该开关为false提醒区块会以半透明opacity-50显示并用一段说明文字替代预设按钮第 534-537 行。前端在对话框打开时通过authApi.getAppConfig()拉取该开关状态第 109-113 行创建新行程时若开关关闭默认reminder_days为0。管理员注意若需开启提醒功能请在服务端配置trip_reminders_enabled并让用户重新打开对话框开关状态是打开时拉取的。后端对提醒值还有一道服务端校验createTrip中reminder_days若不在 0–30 范围内则回退为 3tripService.ts更新时同理回退到旧值。Members成员通过成员选择器添加初始成员。新建行程时选中的成员先缓存在本地selectedMembers数组行程保存成功后才逐个调用tripsApi.addMember加入第 168-177 行即使某个成员添加失败行程本身也已创建成功仅弹出错误提示不会阻塞整个流程。选择器展示的是实例上除自己以外的全部注册用户支持搜索过滤。编辑模式下同一选择器用于管理现有成员点击成员标签可移除选择新用户则立即调用 API 添加。保存流程与数据模型点击Create Trip后前端在 useDashboard.ts 的handleCreate中调用tripsApi.create(tripData)成功后把新行程插入列表顶部并给出成功提示然后跳转到新行程的 Trip-Planner-Overview 概览页。创建请求的完整字段契约定义在 shared/src/trip/trip.schema.ts前后端共享的唯一事实来源export const tripCreateRequestSchema z.object({ title: z.string().min(1), description: z.string().nullable().optional(), start_date: z.string().nullable().optional(), end_date: z.string().nullable().optional(), currency: z.string().optional(), reminder_days: z.number().optional(), day_count: z.number().optional(), });服务端 createTrip 的写入逻辑校验并归一化reminder_days0–30非法回退 3向trips表插入一行currency缺省时写EUR日期缺省写null调用generateDays(...)根据start_date/end_date或day_count生成每日日程day 行——这就是有日期行程天数自动计算和无日期行程按固定天数生成的底层实现返回行程对象含day_count等计算字段与tripId。行程实体的响应结构见 tripSchema除表字段外还通过TRIP_SELECT计算day_count、place_count、is_owner、owner_username、shared_count等派生字段。相关阅读Trip-Members-and-Sharing — 成员角色、邀请链接与协作权限Trip-Planner-Overview — 创建后的行程规划主界面My-Trips-Dashboard — 仪表盘视图、归档与卡片交互Currencies — 行程货币与显示货币的关系及更换流程Environment-Variables —UNSPLASH_ACCESS_KEY等封面图相关配置【免费下载链接】TREKA self-hosted travel/trip planner with real-time collaboration, interactive maps, PWA support, SSO, budgets, packing lists, and more.项目地址: https://gitcode.com/GitHub_Trending/nomad22/TREK创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考