Files
FamilyBook/templates/trips/_node_form.php
T
laoyang b2ca4f336e v24 第 10 批:名册真性能(根因是每卡内联表单)等九条
- #6 名册线上真实数据(1184 人)卡顿:根因是**每张卡片内联一整份分组弹层**——
  全页 2369 个 form / 27234 个 input / 22496 个 radio / 98100 DOM 节点,
  密码管理器(Bitwarden 等)逐个扫描 form 把主线程占死(用户报的就是这个冲突)。
  改为卡片只带 data 属性 + 全页**唯一一份**共享浮层 #rosterMenus。
  实测:form 2369→3、input 27234→25、DOM 98100→17659、解压 7694→2306 KB、
  长任务 1/52ms → 0。新增哨兵 _fb_formbloat_check.py(含反向验证)。
- #5 日视图翻页失效:day_columns() 无条件吸到周一,天视图只有 1 列 → 永远显示那周周一。
  改为仅 span>1 时吸附(周视图行为不变)。
- #2 财务「欠款」类别(负债);并修一个真 bug:负债填负数会让净资产**反向变大**。
  写入口 normalizeAmount 归一化 + summary/timeline 侧 abs 防御 + Schema v17 纠正老数据。
- #3 账目行「盘点」「修改」两个并列按钮(各自就地弹面板);图移到账目上方,
  总金额图跨整行 + 每个账目一条线 + 类别筛选条;charts() 改为覆盖全部账目。
- #4 日程新增「农历」「节假日」两本不可删除只读日历(app/Holiday.php):
  两级自动更新 —— 内置规则(公历固定 + 清明节气 + 农历节日)保证断网也有;
  官方 JSON 镜像自动抓取补齐调休。抓取**不在渲染路径联网**(响应后 fastcgi_finish_request
  + 频率闸门),缓存落 storage/cache。仅派生本不可写日程。
- #6 日程页设置按钮前加「跳到某一天」(选中即跳)。
- #7 起止范围改用一个 Semi dateTimeRange 控件(观影/旅程/节点/日程共 4 处);
  新增 window.fbSetDT / fbUpgradeRange;修范围重挂(React 非受控组件须 unmount 再 createRoot)
  与范围里 required 未摘除导致表单无法提交两个真实问题。

验证:e2e 786/0、batch10 44/0、batch9 38/0、batch_e 91/0、upgrade 126/0、picker 28/0、
semi_integrate 27/0、formbloat 5/0(+反向 3 红)、mobile 688/0、interact 97/0、drag 5/0、geom 5/5;
线上自检 19/19 + 线上真实账号巡检 28/0(含 Firefox 实测)。
2026-10-04 10:46:50 +08:00

92 lines
4.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 行程节点表单(新增 / 编辑共用;被 show.php 循环 require)。
*
* 计划与执行是**双轨**:同一段行程可以先在 plan 里排一遍,走完再在 reality 里记一遍。
* 所以表单里带一个隐藏的 category —— 加在哪一轨就进哪一轨。
*
* 变量(require 前设好):
* $nfNode 被编辑的节点数组,或 null(新增)
* $nfTripId 旅程 id(events.id)
* $nfCategory 'plan' | 'reality'
* $nfPeople 可选人名册(选参与人用),为空就不显示成员多选
* $nfMembers 已选成员 id 列表
*/
$nfIsEdit = !empty($nfNode);
$nfPrefix = $nfIsEdit ? 'ne' . (int)$nfNode['id'] : ('n' . ($nfCategory === 'reality' ? 'r' : 'p'));
?>
<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 if ($nfIsEdit): ?>
<input type="hidden" name="id" value="<?= (int)$nfNode['id'] ?>">
<?php endif; ?>
<div class="nf-grid">
<div class="field">
<label for="<?= e($nfPrefix) ?>-title">这一段 *</label>
<input class="input" id="<?= e($nfPrefix) ?>-title" name="title" required
value="<?= e($nfNode['title'] ?? '') ?>" placeholder="如:栈桥看海">
</div>
<div class="field">
<label for="<?= e($nfPrefix) ?>-type">类型</label>
<select class="select" id="<?= e($nfPrefix) ?>-type" name="node_type">
<?php foreach (\App\Trip::NODE_TYPES as $tk => $tv): ?>
<option value="<?= e($tk) ?>"<?= ($nfNode['node_type'] ?? 'other') === $tk ? ' selected' : '' ?>>
<?= e($tv[1] . ' ' . $tv[0]) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="field">
<label for="<?= e($nfPrefix) ?>-place">地点</label>
<input class="input" id="<?= e($nfPrefix) ?>-place" name="place"
value="<?= e($nfNode['place'] ?? '') ?>" placeholder="选填">
</div>
<div class="field">
<label for="<?= e($nfPrefix) ?>-status">状态</label>
<select class="select" id="<?= e($nfPrefix) ?>-status" name="status">
<?php foreach (\App\Trip::NODE_STATUS as $sk => $sv): ?>
<option value="<?= e($sk) ?>"<?= ($nfNode['status'] ?? 'planned') === $sk ? ' selected' : '' ?>>
<?= e($sv) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<?php /* 用户 2026-10-04 第 7 条:节点的起止也是**一个范围**,一次选完 */ ?>
<div class="field dt-range">
<label>开始 / 结束</label>
<?php $dtName = 'starts_at'; $dtValue = $nfNode['starts_at'] ?? '';
$dtId = $nfPrefix . '-s'; $dtSeconds = true; $dtRange = 'start';
require __DIR__ . '/../_datetime.php'; ?>
<?php $dtName = 'ends_at'; $dtValue = $nfNode['ends_at'] ?? '';
$dtId = $nfPrefix . '-e'; $dtSeconds = true; $dtRange = 'end';
require __DIR__ . '/../_datetime.php'; ?>
<span class="tip">结束时间可不填。</span>
</div>
<div class="field full">
<label for="<?= e($nfPrefix) ?>-detail">记录</label>
<textarea class="input" id="<?= e($nfPrefix) ?>-detail" name="detail" rows="2"
placeholder="这一段发生了什么"><?= e($nfNode['detail'] ?? '') ?></textarea>
</div>
<?php if (!empty($nfPeople)): ?>
<div class="field full">
<label>这一段里有谁(不勾 = 全趟同行的人)</label>
<div class="nf-members">
<?php foreach ($nfPeople as $p): ?>
<label class="check-item">
<input type="checkbox" name="members[]" value="<?= (int)$p['id'] ?>"
<?= in_array((int)$p['id'], $nfMembers, 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"><?= $nfIsEdit ? '保存' : '加一段' ?></button>
</div>
</form>