v24 第 13 批:旅程模块重构(双轨 → 一条记录 + 状态机)
用户原话:「旅程这个模块,我准备大改…如果按照计划行程和实际行程来分别管理,
会变的很复杂…根据我的想法,重构这个模块。」
—— 这不是加需求,是把「双轨」架构换成「一条记录 + 状态机」。
## 用户确认的三个决定
1. 两层:**活动**(顶层容器)→ **行程**(挂其下,字段沿用原节点)
2. **修正不立即转实际**:修正只是记录,行程仍标"计划(已修正 N 次)",
要再点一次「标记为实际」才转实际
3. 老数据**按现有轨道自动迁移**(category=reality → stage=actual)
## 状态机(本次重构的心脏)
trip_nodes.stage:
· plan 计划行程 —— 唯一以「计划时间」上日程的状态,三个动作都能用
· actual 实际行程 —— 上日程(实际时间)+ 进「往年今日」
· skipped 未成行 —— **不上日程、不进往年今日**,但旅程里仍显示并标注
(用户:"还是要显示,只不过要标记上")
旧的 category(plan/reality) 保留作兼容,业务一律看 stage(saveNode 同步维护两者)。
## 三个动作(Trip.php)
· reviseNode —— 记一次修正。🔴 **第一次修正前先把原计划存成 seq=1 快照**,
否则用户要的"之前的计划行程数据要保留,为了以后做对比"就落空。**不动 stage**。
可无限次(seq 递增)。
· completeNode —— 实际=计划,直接转 actual,**不产生修正历史**(没有变化就没有历史)。
· markActual —— 把(已修正过的)计划正式转 actual。
· skipNode —— **不是真删**,只置 stage='skipped'(用户明确"不要真的删除,只是做一个标记")。
· restoreNode —— 撤销未成行(点错了能改回来)。
界面上的「彻底删除」与「标记未成行」是两个并列动作,弹窗文案里写明区别。
## 修正历史(Schema v19,新表 trip_node_revisions)
每次修正一行:实际起止 / 实际地点 / 说明 / 参与人快照。
第 1 条 = 原计划快照,第 2..n 条 = 各次修正 —— 详情页用表格展示,可直接对比。
## 日历与往年今日(用户点名的联动)
· 日历:`n.stage IN ('plan','actual')` —— 去掉旧的 `status<>'cancelled'`
(那是双轨口径;现在"未成行"是 stage)。实际行程标题加 ✓ 前缀便于区分。
· **活动本身绝不上日程**(用户:"活动因为可能跨越的时间比较长")。
· 往年今日:旅程部分从「整趟 events」改成**实际行程**(stage='actual'),
标题带活动名前缀;未成行的不出现。
## 验证
新增 _trip_e2e12.py **30/0**:建活动 → 加行程(可选计划/实际)→ 修正(仍计划 /
历史保留原计划 09:00 / 可无限次)→ 标记为实际 → 完成(无历史)→ 标记未成行(未真删)
→ 日历四种情形(已转实际✓ 新建实际✓ 完成✓ 未成行✗ 活动✗)→ 往年今日只看实际。
回归:e2e 787/0、升级 129/0(含 v19 路径)、batch_e 91/0、batch10 46/0、batch9 38/0、
picker 28/0 + 11/0、crop 17/0、formbloat 9/0、semi 27/0、geom 5/5、mobile 688/0、
interact 92/0、drag 5/0。
e2e 两条旧断言("双轨两块/两轨各一条")按重构语义更新为"三组渲染 / stage 各一条
+ category 与 stage 同步"。
部署断言新增 1 大组,含**反退化防线**:skipNode 若被改成 DELETE 立即变红。
线上自检 19/19;线上真实账号验收 16/0。
线上老数据迁移实测:#222 计划3+实际1、#221 实际4、#220 实际13 —— 一条没丢。
This commit is contained in:
@@ -2,23 +2,33 @@
|
||||
/**
|
||||
* 行程节点表单(新增 / 编辑共用;被 show.php 循环 require)。
|
||||
*
|
||||
* 计划与执行是**双轨**:同一段行程可以先在 plan 里排一遍,走完再在 reality 里记一遍。
|
||||
* 所以表单里带一个隐藏的 category —— 加在哪一轨就进哪一轨。
|
||||
* v24 第 13 批:旅程重构后,**行程不再分两条轨**,而是**一条记录 + 状态机**。
|
||||
* 用户原话:「这个实际的行程和计划行程,是一条记录,不是两条」。
|
||||
* 所以这里加一个「这是哪一类」的下拉:计划行程 / 实际行程
|
||||
* (新建时由用户选;编辑时是当前状态)。
|
||||
* 「修正」「标记为实际」「完成」「标记未成行」是**另外三个按钮**(在 show.php 上),
|
||||
* 不走这张表单 —— 它们的语义是"对既有行程的操作",不是"填一遍字段"。
|
||||
*
|
||||
* 变量(require 前设好):
|
||||
* $nfNode 被编辑的节点数组,或 null(新增)
|
||||
* $nfTripId 旅程 id(events.id)
|
||||
* $nfCategory 'plan' | 'reality'
|
||||
* $nfCategory 【兼容保留】'plan' | 'reality'(新版只用来定默认值)
|
||||
* $nfPeople 可选人名册(选参与人用),为空就不显示成员多选
|
||||
* $nfMembers 已选成员 id 列表
|
||||
*/
|
||||
$nfIsEdit = !empty($nfNode);
|
||||
$nfPrefix = $nfIsEdit ? 'ne' . (int)$nfNode['id'] : ('n' . ($nfCategory === 'reality' ? 'r' : 'p'));
|
||||
$nfPrefix = $nfIsEdit ? 'ne' . (int)$nfNode['id'] : 'nn';
|
||||
// 默认状态:编辑时用它的 stage;新建时按调用方给的 $nfCategory 映射(兼容旧调用)
|
||||
$nfStage = $nfIsEdit
|
||||
? (string)($nfNode['stage'] ?? (($nfNode['category'] ?? 'plan') === 'reality' ? 'actual' : 'plan'))
|
||||
: ($nfCategory === 'reality' ? 'actual' : 'plan');
|
||||
?>
|
||||
<form class="node-form" method="post" action="<?= e(url($nfIsEdit ? 'trips/node_update' : 'trips/node_add')) ?>">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="trip_id" value="<?= (int)$nfTripId ?>">
|
||||
<input type="hidden" name="category" value="<?= e($nfCategory) ?>">
|
||||
<?php /* v24 第 13 批:新建时选「计划 / 实际」——用户原话第 2 条明确要求。
|
||||
一旦创建后要改,走行程上那三个按钮(修正/完成/标记未成行),不在这张表里。 */ ?>
|
||||
<input type="hidden" name="stage" value="<?= e($nfStage) ?>">
|
||||
<?php if ($nfIsEdit): ?>
|
||||
<input type="hidden" name="id" value="<?= (int)$nfNode['id'] ?>">
|
||||
<?php endif; ?>
|
||||
@@ -39,6 +49,21 @@ $nfPrefix = $nfIsEdit ? 'ne' . (int)$nfNode['id'] : ('n' . ($nfCategory === 'rea
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<?php if (!$nfIsEdit): ?>
|
||||
<div class="field">
|
||||
<label for="<?= e($nfPrefix) ?>-stage">这是哪一类 *</label>
|
||||
<select class="select" id="<?= e($nfPrefix) ?>-stage" name="stage_pick">
|
||||
<option value="plan"<?= $nfStage === 'plan' ? ' selected' : '' ?>>计划行程(还没走)</option>
|
||||
<option value="actual"<?= $nfStage === 'actual' ? ' selected' : '' ?>>实际行程(已经走过)</option>
|
||||
</select>
|
||||
<span class="tip">计划行程走完后可用「修正 / 完成」转成实际行程。</span>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="field">
|
||||
<label>当前状态</label>
|
||||
<div class="node-stage-ro"><?= e(\App\Trip::stageWord($nfStage)) ?></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="field">
|
||||
<label for="<?= e($nfPrefix) ?>-place">地点</label>
|
||||
<input class="input" id="<?= e($nfPrefix) ?>-place" name="place"
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* 「修正」表单(v24 第 13 批):记录一条计划行程的**实际**执行情况。
|
||||
*
|
||||
* 用户原话:「另外一个按钮,用来记录实际的情况,按钮名字就叫修正,但是记住,
|
||||
* 这个实际的行程和计划行程,是一条记录,不是两条,点击这个按钮,
|
||||
* 则让用户选择实际的执行时间,包括开始和结束时间,实际的参与人等信息,
|
||||
* 就相当于是修改了一下这个行程,只不过,之前的计划行程数据要保留,
|
||||
* 为了以后做对比。修正,是无限次数的。」
|
||||
*
|
||||
* ⚠️ 与「编辑」的区别:
|
||||
* · 编辑 = 改**计划**本身(排错了计划就改它);
|
||||
* · 修正 = 记**实际**发生了什么(计划不动,实际值进历史,供对比)。
|
||||
* 两者都作用在同一条 trip_nodes 记录上(用户明确"是一条记录,不是两条")。
|
||||
*
|
||||
* 变量(require 前设好):
|
||||
* $rvNode 被修正的行程
|
||||
* $rvTripId 旅程 id
|
||||
* $rvPeople 人名册(选实际参与人)
|
||||
* $rvMembers 当前参与人 id
|
||||
*/
|
||||
$rvPrefix = 'rv' . (int)$rvNode['id'];
|
||||
$rvN = (int)($rvNode['revision_n'] ?? 0);
|
||||
?>
|
||||
<form class="rev-form" method="post" action="<?= e(url('trips/node_revise')) ?>">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="trip_id" value="<?= (int)$rvTripId ?>">
|
||||
<input type="hidden" name="id" value="<?= (int)$rvNode['id'] ?>">
|
||||
|
||||
<div class="nf-grid">
|
||||
<?php /* 实际的起止时间:默认填计划值,方便"只改时间"这种最常见的情况 */ ?>
|
||||
<div class="field dt-range full">
|
||||
<label>实际的开始 / 结束</label>
|
||||
<?php $dtName = 'rev_starts_at'; $dtValue = $rvNode['starts_at'] ?? '';
|
||||
$dtId = $rvPrefix . '-s'; $dtSeconds = true; $dtRange = 'start';
|
||||
require __DIR__ . '/../_datetime.php'; ?>
|
||||
<?php $dtName = 'rev_ends_at'; $dtValue = $rvNode['ends_at'] ?? '';
|
||||
$dtId = $rvPrefix . '-e'; $dtSeconds = true; $dtRange = 'end';
|
||||
require __DIR__ . '/../_datetime.php'; ?>
|
||||
<span class="tip">默认是计划的时间,改成实际发生的即可。</span>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="<?= e($rvPrefix) ?>-place">实际地点</label>
|
||||
<input class="input" id="<?= e($rvPrefix) ?>-place" name="place"
|
||||
value="<?= e($rvNode['place'] ?? '') ?>" placeholder="没变就留空">
|
||||
</div>
|
||||
<div class="field full">
|
||||
<label for="<?= e($rvPrefix) ?>-detail">这次修正的说明</label>
|
||||
<input class="input" id="<?= e($rvPrefix) ?>-detail" name="detail"
|
||||
placeholder="如:航班延误,改到下午才到">
|
||||
</div>
|
||||
<?php if (!empty($rvPeople)): ?>
|
||||
<div class="field full">
|
||||
<label>实际参与的人</label>
|
||||
<div class="nf-members">
|
||||
<?php foreach ($rvPeople as $p): ?>
|
||||
<label class="check-item">
|
||||
<input type="checkbox" name="members[]" value="<?= (int)$p['id'] ?>"
|
||||
<?= in_array((int)$p['id'], $rvMembers, true) ? 'checked' : '' ?>>
|
||||
<span><?= e(person_name($p)) ?></span>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="btn-row">
|
||||
<button class="btn btn-sm" type="submit">
|
||||
<?= $rvN > 0 ? '再记一次修正' : '记录这次修正' ?>
|
||||
</button>
|
||||
<?php if ($rvN > 0): ?>
|
||||
<span class="tip" style="align-self:center">之前已记过 <?= $rvN ?> 次;原计划数据都留着。</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</form>
|
||||
<?php unset($rvPrefix, $rvN); ?>
|
||||
+130
-23
@@ -6,15 +6,22 @@
|
||||
* 两轨并存才能回看"本来想去哪、后来去了哪"—— 这是 TripLog 最有价值的一点,搬过来时保留了。
|
||||
*/
|
||||
$canWrite = \App\Auth::canWrite();
|
||||
$plan = [];
|
||||
$reality = [];
|
||||
// v24 第 13 批:不再按 category 双轨分,按**状态机 stage** 分三组展示。
|
||||
// 计划行程 / 实际行程 / 未成行(未成行的也要显示,用户明确要求"只不过要标记上")。
|
||||
$bysStage = ['plan' => [], 'actual' => [], 'skipped' => []];
|
||||
foreach ((array)($nodes ?? []) as $n) {
|
||||
if (($n['category'] ?? 'plan') === 'reality') {
|
||||
$reality[] = $n;
|
||||
} else {
|
||||
$plan[] = $n;
|
||||
}
|
||||
$sg = (string)($n['stage'] ?? (($n['category'] ?? 'plan') === 'reality' ? 'actual' : 'plan'));
|
||||
if (!isset($bysStage[$sg])) { $sg = 'plan'; }
|
||||
$bysStage[$sg][] = $n;
|
||||
}
|
||||
// 每条行程带上它的修正历史(模板里画"原计划 → 实际"的对比)
|
||||
foreach ($bysStage as $sg => &$lst) {
|
||||
foreach ($lst as &$nd) {
|
||||
$nd['revisions'] = \App\Trip::revisions((int)$nd['id']);
|
||||
}
|
||||
unset($nd);
|
||||
}
|
||||
unset($lst);
|
||||
$memberIds = array_map('intval', array_column((array)($t['attendees'] ?? []), 'id'));
|
||||
?>
|
||||
<div class="page-head">
|
||||
@@ -103,32 +110,59 @@ $memberIds = array_map('intval', array_column((array)($t['attendees'] ?? []), 'i
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php /* ---- 行程节点(双轨)---- */ ?>
|
||||
<?php foreach ([['plan', '计划行程', $plan], ['reality', '实际走过', $reality]] as [$cat, $catName, $list]): ?>
|
||||
<div class="card card-pad">
|
||||
<h2 class="cinema-h2"><?= e($catName) ?> <span class="group-n"><?= count($list) ?> 段</span></h2>
|
||||
<?php /* ==================== 行程(v24 第 13 批重构)====================
|
||||
用户 2026-10-05 原话要点:
|
||||
· 刚开始添加时选「计划行程 / 实际行程」
|
||||
· 计划行程有三个按钮:删除(**标记未成行,不真删**)、修正(记实际执行,可无限次)、
|
||||
完成(实际=计划,直接变实际)
|
||||
· 未成行的仍显示、但带标记;不上日程、不进往年今日
|
||||
· 实际行程上日程 + 往年今日
|
||||
分三组渲染:计划 / 实际 / 未成行(未成行放最后,用灰调)。 */ ?>
|
||||
<?php
|
||||
$stageMeta = [
|
||||
'plan' => ['计划行程', '还没走,下面的「修正 / 完成 / 标记未成行」都能用'],
|
||||
'actual' => ['实际行程', '已走过 —— 会出现在日历与首页「往年今日」'],
|
||||
'skipped' => ['未成行', '这次计划没成行;不再出现在日程与「往年今日」,但在这里保留可查'],
|
||||
];
|
||||
foreach (['plan', 'actual', 'skipped'] as $sg):
|
||||
$list = $bysStage[$sg];
|
||||
?>
|
||||
<div class="card card-pad trip-stage-card stage-<?= e($sg) ?>">
|
||||
<h2 class="cinema-h2">
|
||||
<?= e($stageMeta[$sg][0]) ?>
|
||||
<span class="group-n"><?= count($list) ?> 段</span>
|
||||
</h2>
|
||||
<p class="stage-hint"><?= e($stageMeta[$sg][1]) ?></p>
|
||||
|
||||
<?php if (!$list): ?>
|
||||
<p class="empty-hint"><?= $cat === 'plan' ? '还没有排计划。' : '还没有记录实际行程。' ?></p>
|
||||
<p class="empty-hint">
|
||||
<?= $sg === 'plan' ? '还没有排计划。' : ($sg === 'actual' ? '还没有走过的行程。' : '没有未成行的计划。') ?>
|
||||
</p>
|
||||
<?php else: ?>
|
||||
<ol class="node-list">
|
||||
<?php foreach ($list as $n): ?>
|
||||
<?php /* v24:日历里点「行程节点」是跳 #node-<id> 过来的,这里给个锚点好定位。 */ ?>
|
||||
<li class="node-row status-<?= e((string)$n['status']) ?>" id="node-<?= (int)$n['id'] ?>">
|
||||
<li class="node-row status-<?= e((string)$n['status']) ?> stage-<?= e($sg) ?>"
|
||||
id="node-<?= (int)$n['id'] ?>">
|
||||
<span class="node-ico" title="<?= e(\App\Trip::typeWord((string)$n['node_type'])) ?>">
|
||||
<?= e(\App\Trip::typeIcon((string)$n['node_type'])) ?>
|
||||
</span>
|
||||
<div class="node-body">
|
||||
<div class="node-head">
|
||||
<b><?= e((string)$n['title']) ?></b>
|
||||
<span class="node-badge"><?= e(\App\Trip::statusWord((string)$n['status'])) ?></span>
|
||||
<span class="node-badge nb-<?= e($sg) ?>"><?= e(\App\Trip::stageWord($sg)) ?></span>
|
||||
<?php if ((int)($n['revision_n'] ?? 0) > 0): ?>
|
||||
<span class="rev-badge" title="已修正过多次,点下方「看修正记录」查看">已修正 <?= (int)$n['revision_n'] ?> 次</span>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($n['place'])): ?>
|
||||
<span class="node-place">📍 <?= e((string)$n['place']) ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php $span = \App\Trip::formatSpan($n['starts_at'] ?? null, $n['ends_at'] ?? null); ?>
|
||||
<?php if ($span !== '日期待补'): ?>
|
||||
<div class="node-time"><?= e($span) ?></div>
|
||||
<div class="node-time">
|
||||
<?= e($span) ?>
|
||||
<?php if ($sg === 'actual'): ?><span class="actual-tag">实际</span><?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($n['detail'])): ?>
|
||||
<p class="node-detail"><?= nl2br(e((string)$n['detail'])) ?></p>
|
||||
@@ -141,29 +175,101 @@ $memberIds = array_map('intval', array_column((array)($t['attendees'] ?? []), 'i
|
||||
<?php if (!empty($n['attachs'])): ?>
|
||||
<?php
|
||||
$attRows = $n['attachs'];
|
||||
$attCanEdit = false; // 节点附件不单独给删除入口(防越权:得先判整趟旅程)
|
||||
$attCanEdit = false;
|
||||
$attDelUrl = '';
|
||||
require __DIR__ . '/../_attachments.php';
|
||||
?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php /* ---- 修正记录:原计划 → 每次修正的对比 ---- */ ?>
|
||||
<?php if (!empty($n['revisions'])): ?>
|
||||
<details class="rev-hist">
|
||||
<summary class="link-quiet">看修正记录(<?= count($n['revisions']) ?> 条)</summary>
|
||||
<table class="rev-table">
|
||||
<thead>
|
||||
<tr><th>#</th><th>时间</th><th>地点</th><th>说明</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($n['revisions'] as $rv): ?>
|
||||
<tr>
|
||||
<td><?= (int)$rv['seq'] === 1 ? '原计划' : '第 ' . ((int)$rv['seq'] - 1) . ' 次修正' ?></td>
|
||||
<td class="small"><?= e(\App\Trip::formatSpan($rv['starts_at'] ?? null, $rv['ends_at'] ?? null)) ?></td>
|
||||
<td><?= e((string)($rv['place'] ?? '')) ?></td>
|
||||
<td class="small"><?= e((string)($rv['detail'] ?? '')) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</details>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($canWrite): ?>
|
||||
<div class="node-ops">
|
||||
<?php /* ---- 计划行程:三个动作(用户点名的三个按钮)---- */ ?>
|
||||
<?php if ($sg === 'plan'): ?>
|
||||
<details class="rev-open">
|
||||
<summary class="btn btn-ghost btn-sm">修正</summary>
|
||||
<div class="rev-panel">
|
||||
<p class="rev-tip">
|
||||
记录**实际**执行情况。这仍与上面那条计划是<b>同一条记录</b>,
|
||||
原来的计划数据会保留在「修正记录」里,方便日后对比。
|
||||
点完这里<b>行程仍是计划</b>;确认无误后再点「标记为实际」。
|
||||
</p>
|
||||
<?php
|
||||
$rvNode = $n; $rvTripId = (int)$t['id'];
|
||||
$rvPeople = $people ?? [];
|
||||
$rvMembers = array_map('intval', array_column((array)($n['members'] ?? []), 'id'));
|
||||
require __DIR__ . '/_revise_form.php';
|
||||
?>
|
||||
</div>
|
||||
</details>
|
||||
<form method="post" action="<?= e(url('trips/node_done')) ?>"
|
||||
onsubmit="return confirm('实际执行与计划完全相同,直接转为实际行程?')">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="id" value="<?= (int)$n['id'] ?>">
|
||||
<input type="hidden" name="trip_id" value="<?= (int)$t['id'] ?>">
|
||||
<button class="btn btn-sm" type="submit">完成</button>
|
||||
</form>
|
||||
<form method="post" action="<?= e(url('trips/node_skip')) ?>"
|
||||
onsubmit="return confirm('标记为「未成行」?它不会再出现在日程与往年今日,但在这趟旅程里仍然看得到。')">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="id" value="<?= (int)$n['id'] ?>">
|
||||
<input type="hidden" name="trip_id" value="<?= (int)$t['id'] ?>">
|
||||
<button class="btn btn-ghost btn-sm" type="submit">标记未成行</button>
|
||||
</form>
|
||||
<?php if ((int)($n['revision_n'] ?? 0) > 0): ?>
|
||||
<form method="post" action="<?= e(url('trips/node_actual')) ?>">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="id" value="<?= (int)$n['id'] ?>">
|
||||
<input type="hidden" name="trip_id" value="<?= (int)$t['id'] ?>">
|
||||
<button class="btn btn-sm btn-primary" type="submit">标记为实际</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
<?php elseif ($sg === 'skipped'): ?>
|
||||
<form method="post" action="<?= e(url('trips/node_restore')) ?>">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="id" value="<?= (int)$n['id'] ?>">
|
||||
<input type="hidden" name="trip_id" value="<?= (int)$t['id'] ?>">
|
||||
<button class="btn btn-ghost btn-sm" type="submit">恢复为计划</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
|
||||
<details class="node-edit">
|
||||
<summary class="link-quiet">编辑</summary>
|
||||
<?php
|
||||
$nfNode = $n; $nfTripId = (int)$t['id']; $nfCategory = $cat;
|
||||
$nfNode = $n; $nfTripId = (int)$t['id']; $nfCategory = $sg;
|
||||
$nfPeople = $people ?? [];
|
||||
$nfMembers = array_map('intval', array_column((array)($n['members'] ?? []), 'id'));
|
||||
require __DIR__ . '/_node_form.php';
|
||||
?>
|
||||
</details>
|
||||
<form method="post" action="<?= e(url('trips/node_del')) ?>"
|
||||
onsubmit="return confirm('删掉这一段?')">
|
||||
onsubmit="return confirm('**彻底删除**这一段?连同它的修正记录一起消失,不可恢复。\n\n如果你只是想表达"这次没去成",请用「标记未成行」。')">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="id" value="<?= (int)$n['id'] ?>">
|
||||
<input type="hidden" name="trip_id" value="<?= (int)$t['id'] ?>">
|
||||
<button class="btn btn-ghost btn-sm" type="submit">删除</button>
|
||||
<button class="btn btn-ghost btn-sm" type="submit">彻底删除</button>
|
||||
</form>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
@@ -172,11 +278,11 @@ $memberIds = array_map('intval', array_column((array)($t['attendees'] ?? []), 'i
|
||||
</ol>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($canWrite): ?>
|
||||
<?php if ($canWrite && $sg !== 'skipped'): ?>
|
||||
<details class="node-add">
|
||||
<summary class="link-quiet">+ 加一段<?= e($catName) ?></summary>
|
||||
<summary class="link-quiet">+ 加一段<?= e($stageMeta[$sg][0]) ?></summary>
|
||||
<?php
|
||||
$nfNode = null; $nfTripId = (int)$t['id']; $nfCategory = $cat;
|
||||
$nfNode = null; $nfTripId = (int)$t['id']; $nfCategory = $sg;
|
||||
$nfPeople = $people ?? []; $nfMembers = $memberIds;
|
||||
require __DIR__ . '/_node_form.php';
|
||||
?>
|
||||
@@ -184,3 +290,4 @@ $memberIds = array_map('intval', array_column((array)($t['attendees'] ?? []), 'i
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user