` 内联): * TripLog 的节点表单有十几组字段(类型/时间/出行方式/交通细节/起终点/内容/ * 参与人/照片/状态),内联在主页面里会把整个详情页撑得极长; * 更要命的是**编辑**时每个行程内联一份表单 → 页面上 N 份表单互相干扰 * (元素 id 撞车、密码管理器逐个扫描变卡)。这正是用户说的"把页面撑破"。 * * 字段顺序照 TripLog 的 nodes/form.php(第 17 批又砍掉了两处冗余): * 类型 → 标题 → 起止时间 → 出行方式(自驾才有车辆)→ 线路/车次/承运方 * → 出发地 → 到达地 → 内容 → 参与人 → 照片 →(编辑时)状态与花销。 * * 变量(require 前设好): * $ev 所属旅程(events 行,带 title) * $n 被编辑的行程;null = 新增 * $stage 'plan'|'actual'(新增时由按钮决定;编辑时取行程自己的) * $people 名册(**只用于弹框组件**,不再平铺成一长串勾选框) * $types 节点类型(NodeType::all) * $vehicles 可挑的车(Vehicle::pickable —— 第 17 批起**只有自家车辆库**) * $expenses 已有花销(编辑时) * $errors 校验错误 */ $isEdit = !empty($n); $canWrite = \App\Auth::canWrite(); $fid = (int)\App\Auth::familyId(); $people = $people ?? []; $types = $types ?? []; $vehicles = $vehicles ?? []; $expenses = $expenses ?? []; $errors = $errors ?? []; $stage = (string)($stage ?? ($n['stage'] ?? 'plan')); if (!isset(\App\Trip::NODE_STAGES[$stage])) { $stage = 'plan'; } $curType = (string)($n['node_type'] ?? ''); $curMode = (string)($n['travel_mode'] ?? ''); $picked = array_map('intval', array_column((array)($n['members'] ?? []), 'id')); /* 🔴 v41(用户 2026-10-10 第 7 条):「参与的人那里默认带上自己。」 ⚠️ 只对**新建**生效:编辑时必须如实反映已存的那批人 (硬塞自己进去会让"我把自己取消了"这个操作永远无效)。 与观影"同行的人默认带上自己"(v38)同一口径。 */ if (!$isEdit && !$picked) { $mine = (int)\App\Auth::personId(); if ($mine > 0) { $picked = [$mine]; } } $back = url('trips/show', ['id' => (int)$ev['id']]); // 车辆下拉:只有**自驾**才显示(用户第 3 条)。服务端先按已存值决定初始显隐, // 之后由 app.js 里的 data-mode-select 跟着下拉变。 $needsVehicle = \App\Trip::modeNeedsVehicle($curMode); // 车次/航班号:只有火车与飞机才显示(用户第 3 条) $needsTicket = in_array($curMode, \App\Trip::TICKET_MODES, true); // 起终点(编辑时从库里回填;老数据列是 varchar,坐标是 decimal) $fromRow = [ 'name' => (string)($n['from_place'] ?? ''), 'address' => (string)($n['from_addr'] ?? ''), 'lng' => (string)($n['from_lng'] ?? ''), 'lat' => (string)($n['from_lat'] ?? ''), 'city' => (string)($n['from_city'] ?? ''), ]; $toRow = [ 'name' => (string)($n['to_place'] ?? ''), 'address' => (string)($n['to_addr'] ?? ''), 'lng' => (string)($n['to_lng'] ?? ''), 'lat' => (string)($n['to_lat'] ?? ''), 'city' => (string)($n['to_city'] ?? ''), ]; /* 🔴🔴 v41(用户 2026-10-10 第 5/6 条): 「编辑行程、加计划行程、加实际行程,全部都采用弹窗的形式。其排版的方式和添加电影 是一样的,前面是标题冒号,后面是输入框,和观影模块一样,注意排版。」 「行程部分的编辑也是采用弹窗的形式。」 ⇒ 这份表单现在**既能当整页、也能当弹框**(`$nfModal` 控制),三种入口共用它。 ⚠️🔴 关键设计:**详情页里只放一个弹框容器**,表单内容按需(点击时)由服务端 AJAX 取回。**不要**为每段行程内嵌一份表单 —— 一段行程十几组字段、 详情页可能有十几段,内嵌 N 份会把页面撑到几屏长,而且元素 id 会互相撞车。 **那正是用户当年说"编辑行程把页面撑破"的成因**(见本文件头部注释)。 做法与观影详情页的编辑弹框一致:容器 + fetch 片段 + 事件委托。 */ $nfModal = !isset($nfModal) ? false : (bool)$nfModal; $nfModalOnly = !empty($nfModalOnly); $nfOpen = !empty($nfOpen); $nfReload = (string)($nfReload ?? ''); // 成功后要刷新的容器 id(弹框场景用) /* 🔴🔴 `$nfShell`(v41 关键): · 整页 `trips/node_new` 直达、且要显示成弹框 → **要壳**(`.cal-modal` 包住自己); · 详情页弹框里 **fetch 片段**(`?embed=1`)→ **不要壳**! 因为详情页已经有一个 `#nodeFormHost` 弹框容器(含遮罩 + 标题栏), 片段只需吐"表单本身",再由容器把它塞进 `#nodeFormBody`。 片段再自带一层 `.cal-modal` 会变成"弹框里再套一个弹框" (遮罩叠遮罩、标题栏双份、高度算错)—— 这是最容易犯的错。 ⇒ 由路由传 `$nfShell` 明确区分,**不靠猜**。 */ $nfShell = !isset($nfShell) ? $nfModal : (bool)$nfShell; /* `$nfEmbed`:是否"只吐表单片段"(详情页弹框 fetch 用)。 ⇒ 片段形态既不输出页头、也不输出弹框壳(壳由详情页容器提供)。 */ $nfEmbed = !empty($nfEmbed); ?>

·
返回旅程

花销( 笔) 这一段花了多少钱;旅程页的"总花销"是各段之和

还没记花销。

合计

)。 裸下拉的判据在部署断言里,写完空跑会直接红。 */ ?>