2026-10-02 09:28:07 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
/**
|
2026-10-05 13:26:49 +08:00
|
|
|
|
* 旅程详情(v24 第 16 批重做)。
|
2026-10-02 09:28:07 +08:00
|
|
|
|
*
|
2026-10-05 13:26:49 +08:00
|
|
|
|
* ⚠️ 术语(用户第 9 条:「活动都改名吧,改成旅程,新建旅程,旅程包含行程,
|
|
|
|
|
|
* 这个名字就固定下来」):
|
|
|
|
|
|
* · **旅程** = 这一页(原来叫"活动")
|
|
|
|
|
|
* · **行程** = 里面的一段一段(原来叫"旅程")
|
2026-10-05 10:58:17 +08:00
|
|
|
|
*
|
2026-10-05 13:26:49 +08:00
|
|
|
|
* 页面结构(用户第 1/2/3/6 条):
|
|
|
|
|
|
* ① 页头:标题 + 右上角按钮(计划行程 / 实际行程 / 设置 / 编辑 / 删除)
|
|
|
|
|
|
* —— 标题旁边**不放时间**(第 6 条:时间移到内容里、题图右侧)
|
|
|
|
|
|
* ② 封面行:左 16:9 题图 + 右侧信息区
|
|
|
|
|
|
* 信息区 = 参与人 / 城市数 / 天数 / 行程段数 / 总花销 + 简介那一段话
|
|
|
|
|
|
* ③ 行程分组:**只显示非空的分组**(第 4 条:"只要是没有就是 0 条,
|
|
|
|
|
|
* 那个类型就不显示了,现在显示的是 0 条,这样没意义")
|
|
|
|
|
|
* ④ **没有照片上传板块**(第 3 条:图片视频都针对一次具体行程)
|
2026-10-05 10:58:17 +08:00
|
|
|
|
*
|
2026-10-05 13:26:49 +08:00
|
|
|
|
* @param array $t 旅程(events + trip_details + 派生值)
|
|
|
|
|
|
* @param array $nodes 全部行程(已带上成员/附件/花销)
|
|
|
|
|
|
* @param array $sm 汇总信息(Trip::summary())
|
2026-10-02 09:28:07 +08:00
|
|
|
|
*/
|
|
|
|
|
|
$canWrite = \App\Auth::canWrite();
|
2026-10-05 13:26:49 +08:00
|
|
|
|
$fid = (int)\App\Auth::familyId();
|
|
|
|
|
|
$sm = $sm ?? [];
|
|
|
|
|
|
$people = $sm['people'] ?? [];
|
|
|
|
|
|
$cities = $sm['cities'] ?? [];
|
|
|
|
|
|
$days = (int)($sm['days'] ?? 0);
|
|
|
|
|
|
$nodeN = (int)($sm['nodes'] ?? 0);
|
|
|
|
|
|
$cents = (int)($sm['cents'] ?? 0);
|
|
|
|
|
|
|
|
|
|
|
|
// 三组:计划 / 实际 / 未成行
|
2026-10-04 20:57:40 +08:00
|
|
|
|
$bysStage = ['plan' => [], 'actual' => [], 'skipped' => []];
|
2026-10-02 09:28:07 +08:00
|
|
|
|
foreach ((array)($nodes ?? []) as $n) {
|
2026-10-05 13:26:49 +08:00
|
|
|
|
$sg = (string)($n['stage'] ?? 'plan');
|
2026-10-04 20:57:40 +08:00
|
|
|
|
if (!isset($bysStage[$sg])) { $sg = 'plan'; }
|
|
|
|
|
|
$bysStage[$sg][] = $n;
|
2026-10-02 09:28:07 +08:00
|
|
|
|
}
|
2026-10-05 13:26:49 +08:00
|
|
|
|
$groupMeta = [
|
|
|
|
|
|
'plan' => ['计划的行程', '还没走 —— 可以修正 / 完成 / 标记未成行'],
|
|
|
|
|
|
'actual' => ['实际行程', '已走过 —— 也出现在日历与首页「往年今日」'],
|
|
|
|
|
|
'skipped' => ['未成行', '这次没去成;不上日程,但在这里留着可查'],
|
|
|
|
|
|
];
|
2026-10-02 09:28:07 +08:00
|
|
|
|
?>
|
|
|
|
|
|
<div class="page-head">
|
|
|
|
|
|
<h1><?= e((string)$t['title']) ?></h1>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<?php /* ⚠️ 用户第 6 条:标题旁边**不放**时间。时间在下面题图右侧的信息区里。 */ ?>
|
2026-10-02 09:28:07 +08:00
|
|
|
|
<div class="actions">
|
|
|
|
|
|
<?php if ($canWrite): ?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<?php /* 用户第 6 条:添加计划行程 / 实际行程的按钮都放**右上角**,
|
|
|
|
|
|
点击打开**新页面**(第 5 条:不再内联,内联会把页面撑破)。 */ ?>
|
|
|
|
|
|
<a class="btn btn-ghost" href="<?= e(url('trips/node_new', ['id' => (int)$t['id'], 'stage' => 'plan'])) ?>">
|
|
|
|
|
|
+ 计划行程
|
|
|
|
|
|
</a>
|
|
|
|
|
|
<a class="btn" href="<?= e(url('trips/node_new', ['id' => (int)$t['id'], 'stage' => 'actual'])) ?>">
|
|
|
|
|
|
+ 实际行程
|
|
|
|
|
|
</a>
|
2026-10-02 09:28:07 +08:00
|
|
|
|
<a class="btn btn-ghost" href="<?= e(url('trips/edit', ['id' => (int)$t['id']])) ?>">编辑</a>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<?php /* 用户第 8 条:右上角增加一个**设置**按钮(车辆管理 / 出行方式 / 节点类型)。
|
|
|
|
|
|
按全站规矩:设置按钮只有图标(三条横线)、无文字、贴最右。 */ ?>
|
|
|
|
|
|
<?php $trSetCurrent = ''; require __DIR__ . '/_settings_menu.php'; ?>
|
|
|
|
|
|
<form method="post" action="<?= e(url('trips/destroy')) ?>" class="res-inline"
|
|
|
|
|
|
onsubmit="return confirm('确定删除「<?= e((string)$t['title']) ?>」吗?里面的行程、照片会一起删掉,不可恢复。')">
|
2026-10-02 09:28:07 +08:00
|
|
|
|
<?= csrf_field() ?>
|
|
|
|
|
|
<input type="hidden" name="id" value="<?= (int)$t['id'] ?>">
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<button class="btn btn-ghost btn-icon" type="submit" title="删除这个旅程" aria-label="删除">🗑</button>
|
2026-10-02 09:28:07 +08:00
|
|
|
|
</form>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<?php else: ?>
|
|
|
|
|
|
<span class="link-quiet">只读账号</span>
|
2026-10-02 09:28:07 +08:00
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<?php /* ==================== 封面行:题图 + 信息区 ====================
|
|
|
|
|
|
⚠️ 第 1 条:「题图应该按照 16:9 显示,因为添加的时候,是按照这个比例裁剪的,
|
|
|
|
|
|
现在的显示比例不对」—— 之前 CSS 写的是 4:3,把 16:9 的图裁掉两边。
|
|
|
|
|
|
16:9 这个数字与 ImageSlot 里 cover 槽位的比例**必须一致**,
|
2026-10-05 16:45:10 +08:00
|
|
|
|
部署断言里有一条专门比对它。
|
|
|
|
|
|
⚠️ 第 17 批 第 4 条:「旅程详情页面,图片右侧显示的是**聚合的城市**,
|
|
|
|
|
|
而不是终点地址。」—— 城市来自 `Trip::cities()`(出发地 ∪ 到达地,去重),
|
|
|
|
|
|
见 summary() → cities()。 */ ?>
|
2026-10-02 09:28:07 +08:00
|
|
|
|
<div class="card card-pad trip-hero">
|
|
|
|
|
|
<div class="trip-hero-cover">
|
|
|
|
|
|
<?php if (!empty($t['cover_key'])): ?>
|
|
|
|
|
|
<img src="<?= e(media_url((string)$t['cover_key'])) ?>" alt="">
|
|
|
|
|
|
<?php else: ?>
|
|
|
|
|
|
<span class="trip-cover-empty">🧳</span>
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
</div>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
|
2026-10-02 09:28:07 +08:00
|
|
|
|
<div class="trip-hero-body">
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<?php /* ---- 时间与城市:从行程算出来的(第 15 批第 2 条);
|
|
|
|
|
|
第 6 条要求放在这里(题图右侧)而不是标题旁 ---- */ ?>
|
|
|
|
|
|
<div class="trip-when">
|
|
|
|
|
|
<span class="trip-when-date"><?= e(\App\Trip::activitySpan($t['starts_at'] ?? null, $t['ends_at'] ?? null)) ?></span>
|
|
|
|
|
|
<?php if ($cities): ?>
|
|
|
|
|
|
<span class="trip-when-cities">
|
|
|
|
|
|
<?php foreach ($cities as $i => $c): ?>
|
|
|
|
|
|
<?= $i > 0 ? '<span class="city-sep">·</span>' : '' ?><span class="city-chip"><?= e((string)$c) ?></span>
|
|
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<?php /* ---- 五项统计(用户第 2 条):参与人 / 城市 / 天数 / 段数 / 花销 ---- */ ?>
|
|
|
|
|
|
<div class="trip-stats">
|
|
|
|
|
|
<div class="ts-item">
|
|
|
|
|
|
<span class="ts-n"><?= count($people) ?></span>
|
|
|
|
|
|
<span class="ts-l">参与人</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="ts-item">
|
|
|
|
|
|
<span class="ts-n"><?= count($cities) ?></span>
|
|
|
|
|
|
<span class="ts-l">个城市</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="ts-item">
|
|
|
|
|
|
<span class="ts-n"><?= $days > 0 ? $days : '—' ?></span>
|
|
|
|
|
|
<span class="ts-l">天</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="ts-item">
|
|
|
|
|
|
<span class="ts-n"><?= $nodeN ?></span>
|
|
|
|
|
|
<span class="ts-l">段行程</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="ts-item">
|
|
|
|
|
|
<span class="ts-n"><?= e(\App\Expense::money($cents)) ?></span>
|
|
|
|
|
|
<span class="ts-l">总花销</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<?php /* 参与人是谁:用户点名要("显示的是参与人都有谁") */ ?>
|
|
|
|
|
|
<?php if ($people): ?>
|
2026-10-05 10:58:17 +08:00
|
|
|
|
<div class="trip-people-block">
|
|
|
|
|
|
<span class="small muted">参与的人(各段行程的合集)</span>
|
|
|
|
|
|
<div class="viewers-list">
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<?php foreach ($people as $a): ?>
|
2026-10-05 10:58:17 +08:00
|
|
|
|
<?= person_chip($a, url('people/show', ['id' => (int)$a['id']])) ?>
|
|
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
|
</div>
|
2026-10-02 09:28:07 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<?php endif; ?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
|
|
|
|
|
|
<?php /* ---- 简介:用户第 2 条明确"简介那一段话保留" ---- */ ?>
|
|
|
|
|
|
<?php if (!empty($t['summary'])): ?>
|
|
|
|
|
|
<p class="info-text trip-sum"><?= nl2br(e((string)$t['summary'])) ?></p>
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
|
2026-10-02 09:28:07 +08:00
|
|
|
|
<?php if (!empty($t['note'])): ?>
|
|
|
|
|
|
<p class="remark-text"><?= nl2br(e((string)$t['note'])) ?></p>
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<?php /* ==================== 行程分组 ====================
|
|
|
|
|
|
用户第 4 条:「只要是没有就是 0 条,那个类型就不显示了,现在显示的是 0 条,这样没意义。」
|
|
|
|
|
|
⚠️ 所以这里**跳过空分组**。但要给"一段都还没有"的情况一句引导 ——
|
|
|
|
|
|
否则新建的旅程页面上会一片空白,人不知道该干什么。 */ ?>
|
2026-10-04 20:57:40 +08:00
|
|
|
|
<?php
|
2026-10-05 13:26:49 +08:00
|
|
|
|
$shown = 0;
|
|
|
|
|
|
foreach ($bysStage as $lst) { $shown += count($lst); }
|
2026-10-04 20:57:40 +08:00
|
|
|
|
?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<?php if ($shown === 0): ?>
|
|
|
|
|
|
<div class="card card-pad empty">
|
|
|
|
|
|
<b>还没有行程</b>
|
|
|
|
|
|
<?php if ($canWrite): ?>
|
|
|
|
|
|
点右上角「+ 计划行程」把打算走的地方排进来,或者「+ 实际行程」直接记已经走过的。
|
|
|
|
|
|
参与人、城市、天数、花销都会从行程里自动汇总到这里。
|
2026-10-02 09:28:07 +08:00
|
|
|
|
<?php else: ?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
家人还没有记录行程。
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<?php else: ?>
|
|
|
|
|
|
<?php foreach (['plan', 'actual', 'skipped'] as $sg): ?>
|
|
|
|
|
|
<?php $list = $bysStage[$sg]; if (!$list) { continue; } /* 空分组不显示 */ ?>
|
|
|
|
|
|
<div class="card card-pad trip-stage-card stage-<?= e($sg) ?>">
|
|
|
|
|
|
<h2 class="cinema-h2">
|
|
|
|
|
|
<?= e($groupMeta[$sg][0]) ?>
|
|
|
|
|
|
<span class="group-n"><?= count($list) ?> 段</span>
|
|
|
|
|
|
</h2>
|
|
|
|
|
|
<p class="stage-hint"><?= e($groupMeta[$sg][1]) ?></p>
|
|
|
|
|
|
|
2026-10-02 09:28:07 +08:00
|
|
|
|
<ol class="node-list">
|
|
|
|
|
|
<?php foreach ($list as $n): ?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
$nid = (int)$n['id'];
|
2026-10-05 16:45:10 +08:00
|
|
|
|
// ⚠️ 第 17 批 第 4 条末:「行程中,时间明明具体到了时分秒,怎么不显示?」
|
|
|
|
|
|
// → 行程行改用 nodeSpan()(精确到时分),**不再**用只到日期的 formatSpan()。
|
|
|
|
|
|
// formatSpan 那个精度是给"旅程"(容器)用的。
|
|
|
|
|
|
$span = \App\Trip::nodeSpan($n['starts_at'] ?? null, $n['ends_at'] ?? null);
|
2026-10-05 13:26:49 +08:00
|
|
|
|
$mode = (string)($n['travel_mode'] ?? '');
|
|
|
|
|
|
$spent = (int)($n['spent_cents'] ?? 0);
|
|
|
|
|
|
?>
|
2026-10-04 20:57:40 +08:00
|
|
|
|
<li class="node-row status-<?= e((string)$n['status']) ?> stage-<?= e($sg) ?>"
|
2026-10-05 13:26:49 +08:00
|
|
|
|
id="node-<?= $nid ?>">
|
|
|
|
|
|
<span class="node-ico" title="<?= e(\App\Trip::typeWord((string)$n['node_type'], $fid)) ?>">
|
|
|
|
|
|
<?= e(\App\Trip::typeIcon((string)$n['node_type'], $fid)) ?>
|
2026-10-02 09:28:07 +08:00
|
|
|
|
</span>
|
|
|
|
|
|
<div class="node-body">
|
|
|
|
|
|
<div class="node-head">
|
|
|
|
|
|
<b><?= e((string)$n['title']) ?></b>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<span class="node-badge nb-<?= e($sg) ?>"><?= e(\App\Trip::typeWord((string)$n['node_type'], $fid)) ?></span>
|
2026-10-04 20:57:40 +08:00
|
|
|
|
<?php if ((int)($n['revision_n'] ?? 0) > 0): ?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<span class="rev-badge" title="已修正过多次">已修正 <?= (int)$n['revision_n'] ?> 次</span>
|
2026-10-04 20:57:40 +08:00
|
|
|
|
<?php endif; ?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<?php if ($mode !== ''): ?>
|
|
|
|
|
|
<span class="node-mode"><?= e(\App\Trip::modeIcon($mode)) ?> <?= e(\App\Trip::modeWord($mode)) ?></span>
|
|
|
|
|
|
<?php endif; ?>
|
2026-10-02 09:28:07 +08:00
|
|
|
|
</div>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
|
2026-10-02 09:28:07 +08:00
|
|
|
|
<?php if ($span !== '日期待补'): ?>
|
2026-10-04 20:57:40 +08:00
|
|
|
|
<div class="node-time">
|
|
|
|
|
|
<?= e($span) ?>
|
|
|
|
|
|
<?php if ($sg === 'actual'): ?><span class="actual-tag">实际</span><?php endif; ?>
|
|
|
|
|
|
</div>
|
2026-10-02 09:28:07 +08:00
|
|
|
|
<?php endif; ?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
|
2026-10-05 16:45:10 +08:00
|
|
|
|
<?php /* 交通细节:**只保留**「线路名 / 车次航班号 / 承运方」。
|
|
|
|
|
|
⚠️ 第 17 批 第 3 条明确「座位什么的不记录了」→
|
|
|
|
|
|
座位 / 车厢、登机口 / 站台**不再出现在这里**
|
|
|
|
|
|
(数据库那两列还留着老数据,只是不再展示)。 */ ?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
$traffic = [];
|
|
|
|
|
|
if (!empty($n['line_name'])) { $traffic[] = (string)$n['line_name']; }
|
|
|
|
|
|
if (!empty($n['trip_no'])) { $traffic[] = (string)$n['trip_no']; }
|
|
|
|
|
|
if (!empty($n['carrier'])) { $traffic[] = (string)$n['carrier']; }
|
|
|
|
|
|
?>
|
|
|
|
|
|
<?php if ($traffic): ?>
|
|
|
|
|
|
<div class="node-traffic">
|
|
|
|
|
|
<?php foreach ($traffic as $tf): ?><span class="ntag"><?= e($tf) ?></span><?php endforeach; ?>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
|
2026-10-05 16:45:10 +08:00
|
|
|
|
<?php /* 出发地 → 到达地(第 17 批 第 3 条要记详细地址;
|
|
|
|
|
|
这里显示地点名,详细地址放 title 里悬停可见 + 带导航链接)。 */ ?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<?php if (!empty($n['from_place']) || !empty($n['to_place'])): ?>
|
|
|
|
|
|
<div class="node-route-line">
|
2026-10-05 16:45:10 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
$navFrom = \App\Geo::navUrl($n['from_lng'] ?? null, $n['from_lat'] ?? null, (string)($n['from_place'] ?? ''));
|
|
|
|
|
|
$navTo = \App\Geo::navUrl($n['to_lng'] ?? null, $n['to_lat'] ?? null, (string)($n['to_place'] ?? ''));
|
|
|
|
|
|
?>
|
|
|
|
|
|
<?php if ($navFrom !== ''): ?>
|
|
|
|
|
|
<a href="<?= e($navFrom) ?>" target="_blank" rel="noopener"
|
|
|
|
|
|
title="<?= e((string)($n['from_addr'] ?? '')) ?>"><?= e((string)$n['from_place']) ?></a>
|
|
|
|
|
|
<?php else: ?>
|
|
|
|
|
|
<?= e((string)($n['from_place'] ?? '—')) ?>
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
<span class="arrow">→</span>
|
|
|
|
|
|
<?php if ($navTo !== ''): ?>
|
|
|
|
|
|
<a href="<?= e($navTo) ?>" target="_blank" rel="noopener"
|
|
|
|
|
|
title="<?= e((string)($n['to_addr'] ?? '')) ?>"><?= e((string)$n['to_place']) ?></a>
|
|
|
|
|
|
<?php else: ?>
|
|
|
|
|
|
<?= e((string)($n['to_place'] ?? '—')) ?>
|
|
|
|
|
|
<?php endif; ?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
|
2026-10-02 09:28:07 +08:00
|
|
|
|
<?php if (!empty($n['detail'])): ?>
|
|
|
|
|
|
<p class="node-detail"><?= nl2br(e((string)$n['detail'])) ?></p>
|
|
|
|
|
|
<?php endif; ?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
|
|
|
|
|
|
<?php if ($spent !== 0): ?>
|
|
|
|
|
|
<div class="node-spent">💰 这一段花了 <?= e(\App\Expense::money($spent)) ?></div>
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
|
2026-10-05 16:45:10 +08:00
|
|
|
|
<?php /* ⚠️ 第 17 批 第 3 条:「给参与人标注角色这个功能去掉,不要了。」
|
|
|
|
|
|
所以这里**不再渲染** role_tag(数据库里老数据的角色还在,只是不显示)。 */ ?>
|
2026-10-02 09:28:07 +08:00
|
|
|
|
<?php if (!empty($n['members'])): ?>
|
|
|
|
|
|
<div class="trip-people">
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<?php foreach ($n['members'] as $mm): ?>
|
2026-10-05 16:45:10 +08:00
|
|
|
|
<?= person_chip($mm) ?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<?php endforeach; ?>
|
2026-10-02 09:28:07 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<?php endif; ?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
|
2026-10-02 09:28:07 +08:00
|
|
|
|
<?php if (!empty($n['attachs'])): ?>
|
2026-10-03 08:18:05 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
$attRows = $n['attachs'];
|
2026-10-04 20:57:40 +08:00
|
|
|
|
$attCanEdit = false;
|
2026-10-03 08:18:05 +08:00
|
|
|
|
$attDelUrl = '';
|
|
|
|
|
|
require __DIR__ . '/../_attachments.php';
|
|
|
|
|
|
?>
|
2026-10-02 09:28:07 +08:00
|
|
|
|
<?php endif; ?>
|
2026-10-04 20:57:40 +08:00
|
|
|
|
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<?php /* ---- 修正记录对比(第 13 批) ---- */ ?>
|
2026-10-04 20:57:40 +08:00
|
|
|
|
<?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>
|
2026-10-05 16:45:10 +08:00
|
|
|
|
<td class="small"><?= e(\App\Trip::nodeSpan($rv['starts_at'] ?? null, $rv['ends_at'] ?? null)) ?></td>
|
2026-10-04 20:57:40 +08:00
|
|
|
|
<td><?= e((string)($rv['place'] ?? '')) ?></td>
|
|
|
|
|
|
<td class="small"><?= e((string)($rv['detail'] ?? '')) ?></td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
|
</tbody>
|
|
|
|
|
|
</table>
|
|
|
|
|
|
</details>
|
|
|
|
|
|
<?php endif; ?>
|
2026-10-02 09:28:07 +08:00
|
|
|
|
</div>
|
2026-10-04 20:57:40 +08:00
|
|
|
|
|
2026-10-02 09:28:07 +08:00
|
|
|
|
<?php if ($canWrite): ?>
|
|
|
|
|
|
<div class="node-ops">
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<?php /* 用户第 5 条:**编辑行程打开新页面**(内联的编辑面板会把页面撑破) */ ?>
|
|
|
|
|
|
<a class="btn btn-ghost btn-sm"
|
|
|
|
|
|
href="<?= e(url('trips/node_edit', ['id' => $nid])) ?>">编辑</a>
|
|
|
|
|
|
|
2026-10-04 20:57:40 +08:00
|
|
|
|
<?php if ($sg === 'plan'): ?>
|
|
|
|
|
|
<details class="rev-open">
|
|
|
|
|
|
<summary class="btn btn-ghost btn-sm">修正</summary>
|
|
|
|
|
|
<div class="rev-panel">
|
|
|
|
|
|
<p class="rev-tip">
|
2026-10-05 10:58:17 +08:00
|
|
|
|
记录实际执行情况。这仍与上面那条计划是<b>同一条记录</b>,
|
2026-10-04 20:57:40 +08:00
|
|
|
|
原来的计划数据会保留在「修正记录」里,方便日后对比。
|
2026-10-05 13:26:49 +08:00
|
|
|
|
点完这里<b>这段行程仍是计划</b>;确认无误后再点「标记为实际」。
|
2026-10-04 20:57:40 +08:00
|
|
|
|
</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>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<form method="post" action="<?= e(url('trips/node_done')) ?>" class="res-inline"
|
2026-10-05 10:58:17 +08:00
|
|
|
|
onsubmit="return confirm('实际执行与计划完全相同,直接转为实际?')">
|
2026-10-04 20:57:40 +08:00
|
|
|
|
<?= csrf_field() ?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<input type="hidden" name="id" value="<?= $nid ?>">
|
2026-10-04 20:57:40 +08:00
|
|
|
|
<input type="hidden" name="trip_id" value="<?= (int)$t['id'] ?>">
|
|
|
|
|
|
<button class="btn btn-sm" type="submit">完成</button>
|
|
|
|
|
|
</form>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<form method="post" action="<?= e(url('trips/node_skip')) ?>" class="res-inline"
|
|
|
|
|
|
onsubmit="return confirm('标记为「未成行」?它不会再出现在日程与往年今日,但在这个旅程里仍然看得到。')">
|
2026-10-04 20:57:40 +08:00
|
|
|
|
<?= csrf_field() ?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<input type="hidden" name="id" value="<?= $nid ?>">
|
2026-10-04 20:57:40 +08:00
|
|
|
|
<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): ?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<form method="post" action="<?= e(url('trips/node_actual')) ?>" class="res-inline">
|
2026-10-04 20:57:40 +08:00
|
|
|
|
<?= csrf_field() ?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<input type="hidden" name="id" value="<?= $nid ?>">
|
2026-10-04 20:57:40 +08:00
|
|
|
|
<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'): ?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<form method="post" action="<?= e(url('trips/node_restore')) ?>" class="res-inline">
|
2026-10-04 20:57:40 +08:00
|
|
|
|
<?= csrf_field() ?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<input type="hidden" name="id" value="<?= $nid ?>">
|
2026-10-04 20:57:40 +08:00
|
|
|
|
<input type="hidden" name="trip_id" value="<?= (int)$t['id'] ?>">
|
|
|
|
|
|
<button class="btn btn-ghost btn-sm" type="submit">恢复为计划</button>
|
|
|
|
|
|
</form>
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<form method="post" action="<?= e(url('trips/node_del')) ?>" class="res-inline"
|
|
|
|
|
|
onsubmit="return confirm('彻底删除这段行程?连同它的修正记录一起消失,不可恢复。\n\n如果你只是想表达「这次没去成」,请用「标记未成行」。')">
|
2026-10-02 09:28:07 +08:00
|
|
|
|
<?= csrf_field() ?>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<input type="hidden" name="id" value="<?= $nid ?>">
|
2026-10-02 09:28:07 +08:00
|
|
|
|
<input type="hidden" name="trip_id" value="<?= (int)$t['id'] ?>">
|
2026-10-05 13:26:49 +08:00
|
|
|
|
<button class="btn btn-ghost btn-sm" type="submit">删除</button>
|
2026-10-02 09:28:07 +08:00
|
|
|
|
</form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
|
</ol>
|
2026-10-05 13:26:49 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
|
<?php endif; ?>
|