v81:首页卡片「新增电影」「新建纪念日」弹框(不离开首页就把事办了)

用户 2026-10-22:
「首页上的其他卡片也应该有这些基本功能。比如电影观影,它有一个"新增电影"的功能;
  如果是纪念日,就有一个"新增纪念日"。实际上,就是把原来模块里弹的那个框,现在拿到
  这边来。目的就是为了在首页上就能快速完成一定工作,而不用进到模块里面。」

做法:复用模块页**同一份**表单,不另写。
- app/HomeCards.php:TYPES 每张卡多登记 add(按钮文案)/ add_modal(弹框容器 id)。
- templates/home.php:按登记表挂 data-fb-add-open="#<id>"(没登记的仍用 v78 的
  data-tk-add-open,两种写法并存但各有唯一来源);页尾 require 模块的表单模板。
- assets/js/add_modal.js(新):通用开关,只认 [data-fb-add-modal] /
  data-fb-add-open / data-fb-add-close;幂等闸门;Esc 先让 antd 收面板;
  打开那一刻才 boot 日期控件(hidden 时尺寸为 0,antd 会定位到屏幕左上角)。
- templates/{movies,days}/form.php:只在首页内嵌时($fbAddModalAttr)挂通用属性
  并输出 back=home,模块页行为一字不变。
- index.php:days/save 与 movies/create 加 back=home 白名单(取 POST 再比字面量,
  不把 POST 当跳转地址)。

过程中修掉两个真问题:
- 登记表第一版写 anAddCard,而 days/form.php 实际是 anNewCard ⇒ 按钮属性写对了、
  DOM 也不报错,点下去毫无反应。已加「按钮指向的容器真的存在」判据与部署静态
  断言里的交叉校验(拿登记表 id 去 templates/ 里逐个找 id="...")。
- 探针判「提交后回首页」原本读 pg.url,而 wait_for_load_state(networkidle) 在
  点击那一刻本就 idle 时立刻返回 ⇒ 读到提交前的地址,恒绿。改成拦那次 POST 的
  响应看 (状态码, Location),拆成 ⑭a 提交真发生 / ⑭b 302 指向 home / ⑭c 浏览器停在 home。

验证:正向探针 23/0 · 反向验证 14/0(七注入各自变红)· e2e 1572/0 · 几何 428/0。
This commit is contained in:
2026-10-22 22:05:17 +08:00
parent b1d4502148
commit fd90e33d94
7 changed files with 288 additions and 13 deletions
+17 -3
View File
@@ -91,8 +91,14 @@ $mvModalOnly = !empty($mvModalOnly);
$mvModalForce = !empty($mvModalForce);
$mvModal = $mvModalForce || !$isEdit;
$mvOpen = isset($mvOpen) ? !empty($mvOpen) : ($mvModal && !$mvModalOnly);
/* 🔴 v81:首页内嵌时挂通用开关属性(`assets/js/add_modal.js`)。
⚠️ **只在首页设**(`$fbAddModalAttr` 由 `templates/home.php` 传):
模块页(观影列表页)自己有内联开关脚本,再挂通用属性会变成两套一起绑,
Esc / 点遮罩各关一次 —— 当前虽无害,但那是"两份实现同时生效",迟早出事。
所以这里按需挂,模块页行为一个字不变。 */
$fbAdd = !empty($fbAddModalAttr);
?>
<div class="<?= $mvModal ? 'cal-modal' : 'mv-form-wrap' ?>"<?= $mvModal ? ' id="mvAddCard" role="dialog" aria-modal="true" aria-label="' . ($isEdit ? '编辑观影记录' : '记一场电影') . '"' . ($mvOpen ? '' : ' hidden') : '' ?>>
<div class="<?= $mvModal ? 'cal-modal' : 'mv-form-wrap' ?>"<?= $mvModal ? ' id="mvAddCard" role="dialog" aria-modal="true" aria-label="' . ($isEdit ? '编辑观影记录' : '记一场电影') . '"' . ($mvOpen ? '' : ' hidden') . ($fbAdd ? ' data-fb-add-modal' : '') : '' ?>>
<?php if ($mvModal): ?>
<?php /* 🔴 v40:弹框的标题 / 主按钮文案**随用途变** —— 详情页点「编辑」时进来的是
同一份模板,标题得写「编辑观影记录」、按钮写「保存」,不能还叫"记下这场电影"。
@@ -101,7 +107,7 @@ $mvOpen = isset($mvOpen) ? !empty($mvOpen) : ($mvModal && !$mvModalOnly);
<div class="cal-modal-panel mv-panel">
<div class="cal-modal-head">
<b><?= $isEdit ? '编辑观影记录' : '记一场电影' ?></b>
<button type="button" class="cal-modal-x" id="mvAddX" aria-label="关闭">✕</button>
<button type="button" class="cal-modal-x" id="mvAddX" aria-label="关闭"<?= $fbAdd ? ' data-fb-add-close' : '' ?>>✕</button>
</div>
<?php endif; ?>
<form method="post" enctype="multipart/form-data"
@@ -111,6 +117,14 @@ $mvOpen = isset($mvOpen) ? !empty($mvOpen) : ($mvModal && !$mvModalOnly);
<?php if ($isEdit): ?>
<input type="hidden" name="id" value="<?= (int)$m['id'] ?>">
<?php endif; ?>
<?php /* 🔴 v81:首页内嵌时提交完回**首页**(不是跳去观影列表/详情 ——
用户要的是"不离开首页就把事办了",跳走就等于把他从首页赶出去)。
取值走服务端白名单(见 index.php 的 movies/create 分支),
**不把 POST 的字符串直接当跳转地址**(开放重定向)。
⚠️ 只在新建时给(编辑没有"回首页"的语义)。 */ ?>
<?php if (!$isEdit && $fbAdd): ?>
<input type="hidden" name="back" value="home">
<?php endif; ?>
<?php /* ⚠️ 弹框模式下"主要动作在右下角"(与日程 / 任务弹框一致):
body 滚、foot 固定。编辑态仍是页面上的普通卡片。 */ ?>
<?php if ($mvModal): ?><div class="cal-modal-body"><?php endif; ?>
@@ -394,7 +408,7 @@ $mDelForms = []; // 收集起来,在表单**外面**统一渲染
<div class="cal-modal-foot">
<span class="cal-modal-tip" id="mvAddTip"></span>
<button class="btn btn-sm" type="submit" form="mvForm" id="mvAddSubmit">确定</button>
<button class="btn btn-ghost btn-sm" type="button" id="mvAddCancel">取消</button>
<button class="btn btn-ghost btn-sm" type="button" id="mvAddCancel"<?= $fbAdd ? ' data-fb-add-close' : '' ?>>取消</button>
</div>
</div><?php /* /.cal-modal-panel(仅弹框形态) */ ?>
<?php else: ?>