首页任务面板:可直接改截止时间 (#74)
用户 2026-11-05:「点开之后,就可以修改任务的所有信息,包括:
1. 上传附件;2. 添加评论;3. 添加子任务;4. 修改截止时间
(已有值要带进来);5. 改状态、挪看板。这些操作全部都在这一个页面完成。」
盘点发现:附件 / 评论 / 子任务 / 状态 / 看板 **本来就有**(_panel.php 里
早就实现了),只有「截止时间」是只读的一行 dd。所以只补这一项。
四处改动:
① Task::setDue()(新增)
不复用 update():那是全字段覆盖(title/note/status/assignee/repeat/
parent/board/category 一起写)。表单只交 due_at 的话,其余字段会被
默认值抹成空 ——「只想改个日期,结果标题和备注没了」,不可恢复。
⇒ 单独一条只写 due_at 的 UPDATE。
② tasks/due 路由(新增,紧跟 tasks/status)
与 status/move 同一套约定:ajax_panel=1 回整块新面板,否则 flash+302。
空串 = 清掉截止时间。
③ _panel.php:只读「截止」行 → AntD 单点控件
原来:
<?php if ($tpDue !== ): ?>…<dd>截止 …</dd>…<?php endif; ?>
**没有截止时间时整行都不显示** —— 用户根本不知道该去哪填。
现在不管有没有值都画控件,$dtValue = $tpDue 自动带出已有值。
有值且在逾期时,右侧补一行「还剩 N 天」小字(.tk-due-word)。
④ task_panel.js
· paint() 后调 fbBootAntd():面板是 AJAX 换进来的,bootAntd 首屏
扫过一次 [data-dt-antd-single],那时面板还不存在 ⇒ 必须补挂。
· bindDue():监听 .dt-input 的 change 立即保存。
不用按钮式 data-tk-act(面板里其它动作都是"点一下/选完就生效",
再让用户点一次保存会与其它处不一致)。
监听隐藏字段的 change 而不是 AntD 回调 ⇒ 覆盖 AntD 与原生下拉两种形态。
data-fb-due-bound 幂等标记防止重复绑监听(否则改一次发好几条请求)。
⑤ CSS:.tk-sec-inline > .dt-input 加 flex/min-width/max-width ——
.dt-input 是 flex-wrap,放进也是 flex-wrap 的 .tk-sec-inline 里
会被当弹性项按内容撑,窄屏上可能把标签挤走或控件溢出。
实测:
setDue 设值 => [2026-12-25 18:30:00] ✅
标题仍为原值 ✅ 没被清空(证明没用 update())
setDue 清空 => NULL ✅
面板渲染:data-tk-url-due / data-dt-antd-single / due_at_date 全在,
带出的日期值 = [2026-10-22] ✅
状态/附件/子任务/评论 均仍在
This commit is contained in:
@@ -7277,6 +7277,55 @@ $want = array_keys($want);
|
||||
redirect('tasks');
|
||||
break;
|
||||
|
||||
/* 🔴 #74(用户 2026-11-05):「点开之后,就可以修改任务的所有信息,
|
||||
包括…修改截止时间。当然,如果现在已经有截止时间,就把它带进来。」
|
||||
|
||||
⇒ 首页任务面板里**直接改截止时间**,不再需要点「编辑」进那张整页表单。
|
||||
与 status / move 同一套约定:`ajax_panel=1` 就回**整块新面板**,
|
||||
否则按老规矩 flash + 302(无 JS 的兜底)。
|
||||
|
||||
⚠️ 用 `Task::setDue()` 而**不是** `Task::update()`:后者是全字段覆盖,
|
||||
只交 due_at 会把 title/note/assignee 等全部抹空(详见那个方法的注释)。
|
||||
⚠️ 字段名沿用 `due_at`(与 `_edit_form.php` 一致),
|
||||
空串 = 清掉截止时间。 */
|
||||
case 'tasks/due':
|
||||
$familyId = (int)Auth::familyId();
|
||||
$me = (int)Auth::personId();
|
||||
Auth::requireWrite();
|
||||
csrf_check();
|
||||
$id = (int)($_POST['id'] ?? 0);
|
||||
$dueAt = trim((string)($_POST['due_at'] ?? ''));
|
||||
$t = Task::find($familyId, $id, $me);
|
||||
if (!$t || !Task::canWrite($t, $me)) {
|
||||
if (($_SERVER['HTTP_X_REQUESTED_WITH'] ?? '') === 'XMLHttpRequest') {
|
||||
header('Content-Type: application/json; charset=utf-8', true, 403);
|
||||
echo json_encode(['ok' => false, 'msg' => '这项任务不能改。'], JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
}
|
||||
flash('err', '这项任务不能改。');
|
||||
redirect('tasks');
|
||||
}
|
||||
Task::setDue($familyId, $id, $dueAt);
|
||||
$msg = $dueAt !== ''
|
||||
? '截止时间改成 ' . substr($dueAt, 0, 16) . '。'
|
||||
: '已清掉截止时间。';
|
||||
if (task_panel_wanted()) {
|
||||
task_panel_json($id, $msg);
|
||||
}
|
||||
if (($_SERVER['HTTP_X_REQUESTED_WITH'] ?? '') === 'XMLHttpRequest') {
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
echo json_encode(['ok' => true, 'msg' => $msg], JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
}
|
||||
flash('ok', $msg);
|
||||
$back = (string)($_POST['back'] ?? '');
|
||||
if ($back === 'show') {
|
||||
redirect('tasks/show', ['id' => $id]);
|
||||
} elseif ($back === 'home') {
|
||||
redirect('home');
|
||||
}
|
||||
redirect('tasks');
|
||||
|
||||
case 'tasks/comment_add':
|
||||
$familyId = (int)Auth::familyId();
|
||||
$me = (int)Auth::personId();
|
||||
|
||||
Reference in New Issue
Block a user