Files
laoyang daf5ca904e v94 必填项改成「标签红色加粗」,去掉红色星号 (#3)
需求(用户 2026-10-25):必填项原来在标题后面加一个红色星号,排版经常不齐。
改成「标题本身红色 + 加粗」——用户习惯后,看到红色加粗的标题就知道是必填。

CSS(assets/css/app.css):
- :root 新增 --req:#B03A2E、--req-w:700。
  · 不用 --red(#C0533F):那是动作红(删除按钮底色),当文字色放在暖纸底
    #F7F3EA 上对比度只有 ≈3.4:1,13-14px 标签偏浅;#B03A2E 约 4.6:1。
  · --req-w 必须 700 不能 650/600:本站标签基线字重本来就是 600
    (.form-grid > .field > label / .card .field > label / .mv-row > .mv-lb /
    .dt-range-label 四处都是 600),650 会被取整回 600 = 完全没加粗。
- 文件末尾新增「必填项统一标记」段,覆盖四种标签形态:
  label.is-req / .mv-lb.is-req / .dt-inline-lab.is-req / .dt-range-label.is-req,
  用 !important 打穿各宿主选择器的特异性(颜色与字重是语义标记,不该被面板样式盖掉)。
- 冒号跟着变红:.mv-lb::after / .dt-inline-lab::after 原本是灰色 400,
  只改标签本体会剩「红字 + 灰冒号」的半截效果。
- 包裹层兜底(.field.is-req > label 等),只作用直接子级 ——
  不写 .field.is-req label,那会把「提醒」那排 checkbox 的小标签一起染红。
- 深色主题给备用色 #F08A78。
- 保留 .mv-row > .mv-lb > i(万一有没清干净的星号不至于露灰星花,且静态断言会报出来)。

模板(16 个文件 / 30 处):
- _event_fields.php / _datetime.php 的标签闭包第三参数 $star → $req,
  $dtLabelStar → $dtLabelReq,删掉死引用 $evLabelStar。
- 其余 14 个模板把 `<i>*</i>` 换成给标签加 is-req 类。
- 用显式 .is-req 而不靠 required 属性反推:CSS 无父选择器,:has() 旧 WebView
  不可用,且影院名称/板块名本来就靠 JS 校验没有 required。

验证:
- 静态 _fb_v94_static.py 22/0,反向 9/9(含「--req-w 必须严格大于从 CSS 解析出的
  标签基线字重」,不写死 700)。
- 真浏览器 _fb_v94_req.py 63/0,反向 5/5(加粗/必须红/!important 必要性/
  星号必须消失/每形态单独覆盖,五类注入各自精确命中预期断言)。
- 全量流水线(含 60+ 套件)通过并部署。
- 线上真实页面 _fb_v94_live.py 31/0:观影「片名」、旅程「旅程名」、
  成员「姓名」、导航「网址/所属板块」实测 color=rgb(176,58,46) weight=700,
  同页非必填 color=rgb(44,35,29) weight=600,冒号同色,无星号。
2026-10-26 06:45:38 +08:00

173 lines
9.0 KiB
PHP
Raw Permalink 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
/**
* 🔴 v43(用户 2026-10-11 第 6 条)—— 任务的「编辑」表单,**独立一份**。
*
* 为什么要独立出来:
* 原来它内联在 `tasks/show.php` 的 `<details>` 里。而条目详情浮层点「编辑」时,
* 需要**单独取这份表单**(`tasks/edit?embed=1`)—— 不可能去详情页里抠。
* 抽成一份后,详情页与浮层用的是**同一张表单**,不会出现"两处字段不一致"。
*
* ⚠️ 字段名 / 服务端契约与原来**一字未改**(tasks/update 收的就是这些)。
* ⚠️ 「状态」不在这里改:状态由专门的 `tasks/status` 路由管(它还要处理循环任务),
* 文案里也说明了这一点(与 v24 第 14 批的口径一致)。
*
* 🔴🔴 **本片段一律用带前缀的局部变量(`$tk*`),绝不碰入参的名字。**
* 第一版写的是 `$t = is_array($t ?? null) ? $t : [];` —— 看似无害,其实是在
* **覆盖宿主模板的 `$t`**(那是"这条任务"本身)。只读一次没问题,
* 但下一个人只要把某个 `$tk*` 改回 `$t`(很自然)就会让详情页后半段的
* `$t['children']` / 评论区全是 null —— **而且是静默的**。
* 项目的"片段体检"(`_fb_frag_guard`)当场抓到了这处裸赋值,是对的。
* ⇒ 入参先**收进 `$tkT`**,后面全用它。
*
* 用法(include 前设好):
* $t 任务(Task::find 的形状)
* $people 名册
* $parents 可选父任务候选
* $categories / $boards 分类与看板
* $tkEditEmbed 是否"浮层形态"(true = 不输出自己的「保存」,由浮层底栏给)
* $tkEditModal 🔴 v55:是否**套 `.cal-modal` 弹框壳**(用户 2026-10-17 第 3 条
* 「编辑任务,弹框处理」)。详情页传 true;条目浮层 / AJAX 片段不传
* (它自己已经在浮层里,再套一层弹框就是"框中框")。
* $tkEditOpen 弹框初始是否打开(默认 **关闭** —— 详情页要点「编辑」才开)。
* $tkEditTitle 弹框标题(默认「编辑任务」)
*/
$tkT = is_array($t ?? null) ? $t : [];
$tkPeople = (array)($people ?? []);
$tkParents = (array)($parents ?? []);
$tkCats = (array)($categories ?? []);
$tkBoards = (array)($boards ?? []);
$tkModal = !empty($tkEditModal);
$tkOpen = !empty($tkEditOpen);
$tkMdlTitle = (string)($tkEditTitle ?? '编辑任务');
$tkEmbed = !empty($tkEditEmbed);
?>
<?php
/* 🔴 v55(用户 2026-10-17 第 3 条):「编辑任务,弹框处理。」
弹框壳(`.cal-modal`,与「新建任务 / 新建日程 / 编辑观影记录」同一套类名)。
⚠️ **表单本体一个字未改** —— 只是外面多包一层;字段名 / action / 契约全不动。
⚠️ `$tkEditEmbed` 为 true 时(详情页与条目浮层都是)保存键由**底栏**给,
所以下面 `$tkEmbed` 那段的「保存」不输出,改在底栏放。 */
?>
<?php if ($tkModal): ?>
<div class="cal-modal" id="tkEditCard" role="dialog" aria-modal="true"
aria-label="<?= e($tkMdlTitle) ?>"<?= $tkOpen ? '' : ' hidden' ?>>
<div class="cal-modal-panel">
<div class="cal-modal-head">
<b><?= e($tkMdlTitle) ?></b>
<button type="button" class="cal-modal-x" id="tkEditX" aria-label="关闭">✕</button>
</div>
<div class="cal-modal-body">
<?php endif; ?>
<form method="post" action="<?= e(url('tasks/update')) ?>" class="node-form" id="tkEditForm">
<?= csrf_field() ?>
<input type="hidden" name="id" value="<?= (int)($tkT['id'] ?? 0) ?>">
<?php /* 🔴 v55:编辑完回详情页(服务端 `tasks/update` 本来就 `redirect('tasks/show')`)——
这里**不传** back,与原来一致。 */ ?>
<?php /* 🔴 v44(用户 2026-10-12 第 5 条):编辑表单也统一成观影式排版 +
最新时间控件 + 文案精简(与「新建任务」弹框一致)——
同一件事在两个入口长得不一样,用户会以为"进了别的页面"。 */ ?>
<div class="mv-grid">
<div class="mv-row">
<span class="mv-lb is-req">任务名称</span>
<input class="input" id="tk-title" name="title" required value="<?= e((string)($tkT['title'] ?? '')) ?>">
</div>
<div class="mv-row">
<span class="mv-lb">截止时间</span>
<?php /* 🔴 v44:截止时间用 AntD 单点控件(与新建同一套);括号去掉。 */ ?>
<?php $dtName = 'due_at'; $dtValue = $tkT['due_at'] ?? null;
$dtRequired = false; $dtPlugin = 'antd-single';
require __DIR__ . '/../_datetime.php'; ?>
</div>
<div class="mv-row">
<span class="mv-lb">负责人</span>
<?php /* 第 8 条同一诉求:负责人也是「选人」,人多时用弹窗 + 首字母更快。
保留原下拉的「不指定」(pp-item-none + value=0)。 */ ?>
<?php
$ppName = 'assignee_id';
$ppPeople = $tkPeople;
$ppSelected = [(int)($tkT['assignee_id'] ?? 0)];
$ppMode = 'single';
$ppOpenBtn = '更换负责人';
$ppTitle = '谁负责这件事';
$ppEmptyText = '不指定';
$ppAllowEmpty = true;
require __DIR__ . '/../_person_picker.php';
?>
</div>
<div class="mv-row">
<span class="mv-lb">循环</span>
<select class="select" name="repeat_rule">
<?php foreach (\App\Task::REPEAT as $rk => $rv): ?>
<option value="<?= e($rk) ?>"<?= (string)($tkT['repeat_rule'] ?? '') === (string)$rk ? ' selected' : '' ?>>
<?= e($rv) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="mv-row">
<span class="mv-lb">父任务</span>
<select class="select" name="parent_id">
<option value="0">(这是一项独立的任务)</option>
<?php foreach ($tkParents as $p): ?>
<option value="<?= (int)$p['id'] ?>"<?= (int)($tkT['parent_id'] ?? 0) === (int)$p['id'] ? ' selected' : '' ?>>
<?= e((string)$p['title']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<?php /* v24 第 9、10 条:分类与看板(看板把任务放到哪一块,分类是标签) */ ?>
<div class="mv-row">
<span class="mv-lb">分类</span>
<select class="select" name="category_id">
<option value="0">未分类</option>
<?php foreach ($tkCats as $c): ?>
<option value="<?= (int)$c['id'] ?>"<?= (int)($tkT['category_id'] ?? 0) === (int)$c['id'] ? ' selected' : '' ?>>
<?= e((string)$c['name']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="mv-row">
<span class="mv-lb">看板</span>
<select class="select" name="board_id">
<?php foreach ($tkBoards as $b): ?>
<option value="<?= (int)$b['id'] ?>"<?= (int)($tkT['board_id'] ?? 0) === (int)$b['id'] ? ' selected' : '' ?>>
<?= e((string)$b['name']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="mv-row">
<span class="mv-lb">备注</span>
<textarea class="input" id="tk-note" name="note" rows="3"><?= e((string)($tkT['note'] ?? '')) ?></textarea>
</div>
</div>
<?php /* ⚠️ 「状态」不在这里改(由 tasks/status 路由管,它还要处理循环任务)。 */ ?>
<?php if ($tkModal): ?>
<?php /* 🔴 v55:**弹框形态下不在这里放「保存」** —— 它归底栏(与新建任务一致:
主要动作在右下角)。`.btn-row` 那份是给"页面上的普通卡片形态"用的。 */ ?>
<?php elseif (!$tkEmbed): ?>
<div class="btn-row"><button class="btn btn-sm" type="submit">保存</button></div>
<?php endif; ?>
</form>
<?php if ($tkModal): ?>
</div><?php /* /.cal-modal-body */ ?>
<div class="cal-modal-foot">
<button class="btn btn-sm" type="submit" form="tkEditForm" id="tkEditSubmit">保存</button>
<button class="btn btn-ghost btn-sm" type="button" id="tkEditCancel">取消</button>
</div>
</div><?php /* /.cal-modal-panel */ ?>
</div><?php /* /.cal-modal */ ?>
<?php endif; ?>
<?php /* 🔴🔴 —— **千万不要 unset 入参变量**!
这几种是宿主模板的"大局变量"(`$t` = 这条任务、`$people` = 名册…),
include 之后宿主还要继续用它们(`$t['children']`、评论、子任务…)。
我第一版照抄了 `_datetime.php` 那种"用完即清"的写法,把 `$t` 一并 unset ——
结果 `tasks/show.php` 后半段全部拿不到 `$t`,**子任务列表与评论区静默消失**
(e2e 当场抓到 2 条:子任务没了、@高亮没了)。
⇒ 这里只清**本片段自己造的**临时变量(`$tk*` 与 `$dt*` / `$pp*` 那几组)。 */
unset($tkT, $tkPeople, $tkParents, $tkCats, $tkBoards, $tkEmbed,
$tkModal, $tkOpen, $tkMdlTitle, // 🔴 v55:弹框壳那三个
$dtName, $dtValue, $dtRequired,
$ppName, $ppPeople, $ppSelected, $ppMode, $ppOpenBtn, $ppTitle,
$ppEmptyText, $ppAllowEmpty); ?>