fix(home): 从浮层把任务标成完成时该行不消失(只修了复选框那条路)(#20)
用户第二次提同一条需求。核了线上代码:4 文件 md5 与本地一致、mtime 18:14, 部署没问题;复跑原判据仍 20/0 全绿。判据绿 + 用户能复现 ⇒ 判据有盲区。 盲区:首页把任务标成完成有**两个入口** ① 每行前面那颗复选框 —— home.php 末尾的脚本(上一版已修) ② 点整行弹浮层 → 面板里「状态」三段按钮 → assets/js/task_panel.js 的 syncRow() 上一版只改了 ①。syncRow() 只改徽章与复选框的 aria 状态,**从不删行**, 所以从面板点「已完成」后行留在原地,只把徽标换成「已完成」。 用户点的就是 ②,而原判据 grep 全文没有 panel / 浮层 / data-fb-entry —— 完全没测这条路。 改法: - 把删行逻辑抽成 window.fbHomeTaskDrop(row, wasStatus) 放 assets/js/app.js, 两个入口共用一份。作用域限定 [data-tk-home-host]:任务**看板**页的行也带 data-task-row,那里勾完成只改状态、**必须保留该行**(看板按状态分栏,删了就没处看)。 - task_panel.js 的 syncRow() 在 d.status === 'done' 时调它; wasStatus 必须在改写 data-tk-status **之前**读,否则概述卡不知道该减「在做」还是「待办」。 - home.php 原来那份本地实现改成薄转发,避免两份实现改一处忘一处。 - 顺带修掉一条说谎的注释:原注释写"补偿了一个可撤回的提示",但代码里从来没有 撤回按钮,只有一句 3.2 秒自动消失的 say()。 - _card_tasks.php 补记"两个入口"这件事。 子任务安全:task_panel_json() 用 panel_of 找**父任务**,回的 status 是父任务的, 所以面板里勾子任务不会把父任务那一行删掉(判据 ⑱ 专门守这条)。 判据: - 新增 _b38_panel_done_drop.py(21 条,走真实浮层点击): 修复前 **16 通过 / 5 失败**(⑥⑦⑧⑬⑭)→ 修复后 **21 / 0** - 注入反证 _b38_falsify.py:把删行那两行用 if(false) 挡掉,锚点断言 count==1, 立刻红回同样的 5 条、关键条目 ⑥⑧⑬⑭ 命中 4/4,副本自动还原 - 原 _b37_home_task_drop.py(复选框路径)仍 **20 / 0** - _b37_regress.py **11 / 0**:看板仍改状态且**不删行**、详情页子任务复选框正常、 空态 display 真的是 none - home.php 内联 JS 0 块坏;app.js / task_panel.js node --check 全过
This commit is contained in:
@@ -2580,3 +2580,68 @@
|
||||
if (!document.hidden) { place(); }
|
||||
});
|
||||
})();
|
||||
|
||||
/* ============================================================================
|
||||
首页「近期任务」:把一条已完成的任务行从卡片里摘掉(工单 #20)
|
||||
----------------------------------------------------------------------------
|
||||
用户原话(2026-10-28,两次强调):「首页,近期任务,如果勾选了完成,
|
||||
应该刷新一下这个列表,把完成的删掉。」
|
||||
|
||||
🔴🔴 为什么这段放在 app.js 而不是留在 home.php 里:
|
||||
"把这条标成完成"在首页有**两个入口**——
|
||||
① 行首那颗复选框(脚本在 home.php 末尾)
|
||||
② 点整行弹浮层 → 面板里的「状态」三段按钮(脚本是 task_panel.js)
|
||||
第一版只改了 ①,于是同一个用户动作(都是"标完成")两条路径两种结果:
|
||||
从复选框勾 → 行消失;从面板点「已完成」→ 行留着,徽标变成「已完成」。
|
||||
用户复现的就是第二条(我先前的判据完全没测浮层,所以 20/0 全绿也是假绿,
|
||||
→ pitfalls「需求横跨几个入口就每个入口都要判据」)。
|
||||
|
||||
⚠️ 作用域必须限定 `[data-tk-home-host]`(首页任务卡片的外层):
|
||||
任务**看板**页的行也带 `data-task-row`,那里勾完成是**只改状态、不删行**
|
||||
(看板是按状态分栏的,"行"就是那个任务本身,删了就没处看了)。
|
||||
所以这段绝不能按 `[data-task-row]` 全局找。
|
||||
|
||||
⚠️ 只在"变更后确实是 done"时删(判据用服务端回的 `d.status`,不是我算出来的 next):
|
||||
`tasks/status` 是幂等接口,传 done 再来一次还是 done;拿返回值判断才不会
|
||||
"手快连点两下,第二下把行删了"。
|
||||
|
||||
@param {Element} row 要摘掉的那一行 `li[data-task-row]`
|
||||
@param {string} wasStatus 改**之前**的状态('doing' / 'todo')——
|
||||
决定概述卡该减「件在做」还是「件待办」。
|
||||
⚠️ 不能在这里读 `data-tk-status`:调用方通常已经把它改成 done 了。
|
||||
@return {boolean} 真的删了才 true(行不在首页卡片里就 false,什么也不做)
|
||||
============================================================================ */
|
||||
window.fbHomeTaskDrop = function (row, wasStatus) {
|
||||
if (!row) { return false; }
|
||||
var host = row.closest ? row.closest('[data-tk-home-host]') : null;
|
||||
/* 不在首页卡片里(任务看板 / 详情页子任务列表)→ 一律不删。
|
||||
⚠️ 这条判断是这段代码能被两个入口共用的**前提**,别为了"通用"去掉它。 */
|
||||
if (!host || !host.contains(row)) { return false; }
|
||||
|
||||
var ul = row.parentNode;
|
||||
if (row.parentNode) { row.parentNode.removeChild(row); }
|
||||
|
||||
/* 概述卡的「N 件在做 / N 件待办」同步减 1。
|
||||
⚠️ 用 `[data-hbs]` 定位(模板里专门加的钩子),**不靠中文文案** ——
|
||||
"件在做"改一个字就失效,而这是 JS 要读的东西。 */
|
||||
if (wasStatus === 'doing' || wasStatus === 'todo') {
|
||||
var a = document.querySelector('.hb-stats a.hbs[data-hbs="' + wasStatus + '"]');
|
||||
var b = a ? a.querySelector('b') : null;
|
||||
if (b) {
|
||||
var n = Math.max(0, (parseInt(b.textContent, 10) || 0) - 1);
|
||||
b.textContent = String(n);
|
||||
/* 减到 0 就把整条藏起来:服务端是 `if ($nTodo > 0)` 才渲染待办那一条,
|
||||
前端不藏会出现「0 件待办」——服务端永远不会画出来的状态。 */
|
||||
if (n === 0) { a.hidden = true; }
|
||||
}
|
||||
}
|
||||
|
||||
/* 删到一条不剩:摘掉空 ul,把服务端渲染的空态提示露出来
|
||||
—— 否则卡片变成一片空白,用户以为加载坏了。 */
|
||||
if (ul && ul.querySelectorAll && ul.querySelectorAll('[data-task-row]').length === 0) {
|
||||
if (ul.parentNode) { ul.parentNode.removeChild(ul); }
|
||||
var empty = host.querySelector('[data-tk-empty]');
|
||||
if (empty) { empty.hidden = false; }
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user