laoyang
|
ea6e42c27f
|
fix(home): 近期任务勾选完成后该行不消失(连概述卡计数也不减)(#20)
用户原话:「首页,近期任务,如果勾选了完成,应该刷新一下这个列表,把完成的删掉。」
## 原来的行为
首页那段复选框脚本 AJAX 成功后只改徽章文字(`kb-st` → 「已完成」),
**没有任何"移除这一行"的逻辑**。而且 templates/home.php:160 那条注释还写着
这是**当年的刻意设计**:
> ⚠️ 改完**不摘掉这一行**:用户点完正想看自己刚完成什么,立刻消失会让人怀疑
> "是不是点到删除了"。刷新时由服务端决定它还在不在。
用户现在明确推翻这条:完成的就该从列表里删掉。
## 服务端本身是对的
首页路由只取 `doing` + `todo`(index.php:839),`done` 本来就不在列表里
⇒ 手动刷新这一行确实会消失,问题纯粹在"AJAX 完成后前端没同步"。
所以这次一行服务端代码都不用改。
## 改法
新增 `dropTaskRow(row, wasStatus)`,AJAX 成功后(**按服务端返回的 `d.status` 判断**,
不是拿点击前的 `next`)做三件事:
1. **删掉这一行**;
2. **同步「概述」卡右下的「N 件在做 / N 件待办」** —— 那两个数字与这份列表
**同源**(同一个 `$tasks`,见 _card_brief.php:53),只删行不减去数字
⇒ 列表 2 条、概述说 3 件在做,自相矛盾;
3. **一条不剩时把空态提示露出来**(服务端渲染的 `[data-tk-empty]` 原来一直 hidden)
—— 否则卡片变成一片空白,用户以为加载坏了。
配套的小改动:
- `_card_tasks.php`:空态提示改成**一直渲染、靠 `hidden` 切换**,加 `data-tk-empty`
钩子(不靠匹配文案 —— 文案改一个字就失效)。外层加 `data-tk-home-host`。
- `_card_brief.php`:两个统计 `<a>` 加 `data-hbs="doing|todo"` 钩子,
同样**不靠中文文案定位**(这是 JS 要读的东西,不能把展示文案变成接口)。
- `app.css`:补 `.empty-hint[hidden] { display: none !important; }` ——
浏览器默认的 `[hidden]{display:none}` 优先级最低,哪天有人给它加 `display:flex`
这句提示就会在"有任务时"也冒出来(与 app.css:601 那条注释是同一约定)。
## 几个判据上的讲究
- **按 `d.status` 判断而不是 `next`**:`tasks/status` 是幂等接口,
拿服务端返回的状态才不会"手快连点两下,第二下把行删了"。
- **`wasStatus` 要在改 `data-tk-status` 之前存**:删行时要靠它决定减「在做」还是「待办」。
第一版直接在删行时读 `data-tk-status`,读到的已经是 `done` —— 自己写的时候就踩了。
- **提示文案补一句"已从近期任务移出,去「全部」里能看到"**:
删行的原罪是"用户以为点到删除了",所以必须**明说它去哪了**,
而不是沿用服务端那句「已标成「已完成」」(那会让人以为行还在,下一眼发现没了更慌)。
## 验证
**主判据 `_tooling/_b37_home_task_drop.py` —— 20 通过 / 0 失败**
夹具:把库里历史 doing/todo 任务临时改状态腾空卡片(**不能靠 `deleted_at`** ——
`Task::byStatus()` 的 SQL 里根本没有 `deleted_at IS NULL`,软删对首页无效,实测过),
造 2 条 doing + 1 条 todo,跑完逐个恢复。
覆盖:勾「进行中」→ 行移除 + 「件在做」2→1 + 「件待办」不误减;
勾「待办」→ 行移除 + 「件待办」1→0 且链接藏起;
删到最后一条 → 0 行 + 空态露出;刷新后与服务端事实一致;库里状态真的是 done。
**注入反证 `_tooling/_b37_falsify.py` —— 三次独立注入,各自红在对应处**
| 注入 | 结果 | 命中的判据 |
|---|---|---|
| ① 不删行(原始 bug) | 通过 12 / **失败 8** | ③④⑤⑪⑭⑮ |
| ② 删行但不减概述卡计数 | 通过 17 / **失败 3** | ⑤⑫⑯ |
| ③ 不限空态(删完一片空白) | 通过 19 / **失败 1** | ⑮ |
每次注入前断言锚点唯一(#474),恢复后回到 20/0。
**回归 `_tooling/_b37_regress.py` —— 11 通过 / 0 失败**
看板勾选仍能改状态且**不删行**(与首页行为不同是有意的)、
详情页子任务复选框仍能改状态、`[hidden]` 的 `display` 真的是 `none`、
`data-hbs` 钩子在、卡片「全部」入口仍指向 tasks。
⚠️ 回归里踩了一个判据假设错:我一开始按"详情页也该有父任务复选框"写,
直接 FAIL。真实情况是详情页的复选框**只给子任务**(show.php:181 在子任务循环里),
父任务没有 —— 是判据错了不是产品坏了(#429 同族)。
**内联 JS 校验 `_tooling/_b37_inline_js_check.py`**:把渲染后 HTML 的 `<script>`
抽出来逐个 `node --check`(`php -l` 不看 HTML 里的 JS)。
并做了反证:喂一段坏 JS,它确实报 1 块坏,不是恒绿。
工单 #20
|
2026-10-28 18:13:49 +08:00 |
|
laoyang
|
a7b3d8cfd8
|
v85: 首页日程刻度按结束时间定范围 / Markdown 标题真正有层级
用户报了两处(网页版):
① 「今天的日程,有一个日程到下午五点半,首页日程刻度只有九点。」
真根因:掐头去尾只按 `time`(开始时间)算范围,`end_time` 压根没参与
⇒ 08:30-17:30 被当成"8 点半结束",endH = 8 + 2 = 10,
刻度只画到 09:00;色块高 540 分钟硬塞进 3 小时格子,被 min(96, …) 夹住糊成一片。
修法:收集「开始 + 结束」两组分钟数,endH 由 max(结束) 向上取整到小时;
保留"区间必须包含此刻"的原逻辑与下限保护。
② 「日记 markdown 代码都没解析,## 后面的是标题,现在显示的还是和正文一样。」
真根因:渲染一直是对的(`## x` → `<h4 class="md-h">`),问题全在视觉 ——
`h4.md-h` 是 15px,而阅读态正文 `.note-read-block` 也是 15px,字号完全同号;
标题只有 font-weight:500,肉眼看不出层级。
修法:h3/h4/h5/h6 分别 18/17/15.5/14.5px,父级 .md-h 字重 600、行高 1.45,
h6 用 muted 色;`:first-child` 去掉多余的顶部外边距。
反向验证:
_fb_v85_agenda_range.py 13/0(钉死 08:00 做 A/B + 真实 now 复核 5 条)
_fb_v85_md_heading.py 9/0(真实 Markdown::render + 真实 CSS + 计算值)
_fb_v85_static_falsify.py 7/0(部署静态断言 6 处注入各自都能变红)
线上真值复核(family.yangyq.net,真实库 #1853 工程管理硕士开题 08:30~17:30):
旧模板 刻度 07~09(3 行)下沿 10:00,色块 top=50%/h=50% —— 复现用户所见
新模板 刻度 07~17(11 行)下沿 18:00,色块 top=13.64%/h=81.82% = 95.46% 完整在车道内
CSS h4.md-h 17px / 正文 15px / .md-h font-weight 600
|
2026-10-24 09:31:08 +08:00 |
|
laoyang
|
b1d4502148
|
v80 首页日程:修「右侧缺一块」——色块百分比按含刻度的整宽算了
用户:「网页端,首页,日程好像显示不全,右侧是缺一块的,是不是左侧有刻度,
导致你算宽度的时候,没算对?」—— 猜对了,而且比想的严重。
原因:色块内联 `left: calc(46px + L%)` 是**绝对**让位(46px 给刻度),
`width: calc(W% - 4px)` 的百分比却相对**含刻度的整宽**(.ag-grid 481px)。
于是 100% 时色块宽 477、左端 48,右端落到 744,而卡片右边界只有 700
⇒ 多出 44px 被 .hc-agenda 的 overflow:hidden 裁掉,日历本名正好在那截里。
日历页 .tg-block 没这个病:它左边刻度是独立的一列(.tg-col),百分比天然相对列宽。
修法(换参照系,不是调数字):新增 .ag-lanes 定位层,左让刻度、右留 2px,
色块与红线都挪进去,百分比就相对真正可用的宽度算;刻度宽度收成单一变量
--ag-gutter(50px),以后改刻度只改它。内联删掉 46px。
验证四层:
- _fb_agenda_geom.py 27/0:不越界 / 左右留白 2&4px / 宽度自洽 / 与日历页同公式
- _fb_agenda_pixel.py 8/0:截图数着色列,右沿留白 5px(修前 0px)
- _fb_agenda_falsify.py 11/0:退回旧写法与车道超宽都变红,合法微调仍绿
- e2e 1558/0 · 几何 428/0 · b37 5/0
同时修两处失效探针:
- _fb_b37_ui.py 点 #taskAddBtn(v78 已改成 [data-tk-add-open])导致基线超时全红
- _fb_b37_falsify.py 注入锚点写死 calc(46px + ...),改到会重现该 bug 的 width 上
部署脚本加 v80 三条静态断言(已逐条注入确认会红)。
|
2026-10-22 20:22:54 +08:00 |
|
laoyang
|
40fd6c501c
|
v78 服务端:首页任务改成「就地处理」面板 + 新建任务搬到首页
用户原话:
「网页端,首页点击一个任务后,除了展示信息,应该有相应的功能,可以修改状态:
待办、进行中,可以挪动分组,可以拖动上传附件,可以添加评论,添加子任务等。
其目地,是为了让用户不离开首页,就能对任务进行简单的处理。」
「另外,在全部任务旁边,放一个新建任务的功能,其实就是把任务中的新建和编辑功能,
搬过来,用弹出框来处理。」
一、首页任务浮层由「只读信息」改成「可操作面板」
- 新增 templates/tasks/_panel.php:状态三段 / 看板 chips(带看板色)/
子任务(复用 _task_check.php)/ 附件拖放框(复用 _attachments.php)/ 讨论
- 新增路由 tasks/panel:只吐一块 HTML(找不到 404)
- 既有七个动作路由各加一条 ajax_panel 回包分支(状态 / 挪分组 / 新建子任务 /
评论增删 / 附件增删),没有新开写接口
- helpers.php 新增 task_panel_wanted() / task_panel_json();
fb_entry_json() 的 payload 增加 panel 字段(只有任务会给)
- 每次动作回**整块新面板**:一次动作会牵动子任务计数、附件张数、看板选中态,
逐处同步 DOM 必然漏一处
- 拖进来的附件**立刻上传**(任务已存在,不该再让用户点一次保存),
不复用 _stage_drop.php 那套「暂存 + 认领」
二、新建任务搬到首页
- 从 templates/tasks/index.php 抽出公共片段 templates/tasks/_add_modal.php
(字段与原来一字未改),首页与任务页共用同一份
- 新增 assets/js/task_add.js 管开关(两页共用,幂等绑定);
打开那一刻才 fbUpgradeRange() + fbBootAntd()(hidden 时宽高为 0,antd 会定位错乱)
- App\HomeCards 登记表里加 add => 新建任务,首页卡头与「全部任务」并排
- tasks/create 支持 back=home(白名单),新建完回首页
三、其它
- assets/js/task_panel.js:事件委托;动作后整块换面板;
顺手同步首页那张卡的状态徽标与复选框(关掉浮层不能还是旧状态);
传附件时保住用户写了一半的留言与子任务标题;取不到面板时退回只读信息
- app.css 追加面板样式(含 color-mix 的 @supports 兜底)与卡片窄到宽 2 时允许折行
验证:本地 e2e 1558/0、几何 428/0 + 660/0、v78 反向验证 11/0、
片段作用域体检 35/0、php -l 与 node --check 全过
|
2026-10-22 12:40:14 +08:00 |
|
laoyang
|
b45cf671d1
|
v71c:首页「通知消息」改成正规卡片,样式直接复用通知页
用户 2026-10-21:
「先把web端的首页修一下,通知消息这个,也是首页的卡片,可以调整顺序和大小。
另外,这个样式也不好看,我看个人头像点击后,通知消息那个页面的样式就不错,
直接复用就可以了。」
① 卡片化(HomeCards 注册表 + 默认布局 + 取数)
· TYPES 新增 'notif'(w4/h4,route=notifications,more=全部通知)
· DEFAULT_LAYOUT 钉在 brief 之后,与 days 并一行(宽 4)——
若插在 brief 与 agenda 之间,agenda/tasks 会被挤成一上一下(实测 C13 顶边 407 vs 751)
· data() 加 case 'notif' → 新增 notifData():最新 10 条 + 未读数,
与原来的取数口径一字不差;关掉卡片就不查这两条 SQL
· templates/home.php 删掉网格前那块写死区块(v30 第 5 条「必须在往年的今天前面」
这条约束作废 —— 那时还没有卡片体系);index.php 不再单独传 notifs/notifUnread
② 样式复用 templates/notifications/index.php
· 结构与通知页完全一致:头像在前 → 正文 → kind 图标在右(带 ntf-kind-{kind})
(旧首页那块是"图标在前、头像第二",正是用户说不好看的那一版)
· 新增 .hc-ntf 作用域只补"卡片比整页小"的三条差异:正文允许折两行(宽 2 时
单行省略会把正文全吃掉)、时间挪到正文下一行、未读数做小注脚
· 不带每条右侧「删除」按钮(4×4 的卡里塞两个按钮会把正文挤成两三个字),
删除在通知页做,卡片右上角有「全部通知」
③ 顺带修掉 v63 A1 抓住的一处:'notif' 的 mod 给 'home' 而不是空串
(通知不在 Module::LIST,但它是首页自己的卡片;空串会让「全部通知」成为
一排同色模块按钮里唯一白底 ghost 的那个)
⇒ TYPES docstring 立规矩:route 非空就必须有 mod,认不出归哪个模块就归 home
验证(familybook_push.sh 第 6 轮全绿,PUSH_RC=0,2h11m)
v62 首页卡片 56/0 · v62 反向验证 14/0(新增 M8–M12 五条注入)
b30 通知 16/0 · b30 反向验证 18/0
v63 40/0 · v63 反向验证 51/0 · e2e 1523/0 · 部署静态断言空跑 RC=0
同批带上上一轮 v70/v71 的日历修复(已单独验过,本轮流水线一并回归):
· v70 日历导入后条目不显示:+N 条从纯文本 span 改成真按钮,点开是当天全部
条目浮层;AJAX 新建后就地插入与服务端同形(回 entry,不让前端自己拼)
· v71 ICS 导入顺序:主事件 → 覆盖行 → EXDATE 由 Calendar::importIcs() 统一保证
|
2026-10-21 13:22:37 +08:00 |
|
laoyang
|
2f7dc6ca23
|
v63:卡片配色 / 日历本靠右 / 地图题图 / 设置页清理 / 公共标签颜色 / 令牌下线
- 卡片右上角按钮改用「来自哪个模块」的主题色:HomeCards 登记表新增 mod 字段
与 module(),首页从登记表取色(原来是模板里硬编码 in_array(['agenda','tasks'])
白名单,新加带按钮的卡片会默默变灰)
- 首页日程把日历本放到色块右侧:.ag-ev 改弹性行,「时间+标题」包进
.ag-ev-main(flex:1 1 auto; min-width:0),日历本作右侧兄弟。
原来 display:block 会把日历本顶到第二行,色块一矮就完全看不见
- 旅程地图显示题图:服务端把 media_url(cover_key) 塞进地图数据,
地图卡片左侧 40x40 题图(object-fit:cover),没有题图不留灰框
- 系统设置第一块改叫「系统标语」;删掉「首页上那一行小字」提示、
「不是全家的统一口号」说明、「上次结构升级有步骤失败了」整框;
运行环境删「排错时看这一块」与「亲属连线」那一行(功能与数据未动)
- 公共标签:说明文字全删;列表与编辑合并成一行(色块+名字+N人+箭头+编辑);
person_groups 加 color 列(Schema addColumn,老库可升);点「编辑」弹框
改名字与颜色、点「完成」提交;下面那个独立编辑列表撤掉。删除挪进弹框
- 个人设置删掉「手动签发接口令牌」整块;settings/api_token 路由保留但挡下提交
(只删界面会留下知道地址就能用的后门);令牌只由登录后自动签发,
设备管理卡保留。apiTokens/apiPlain/apiLabel/apiBase 四个变量一并撤掉
|
2026-10-19 17:27:37 +08:00 |
|
laoyang
|
9a66068c33
|
v62:纪念日列表修正 / 分类图标与设置菜单 / 首页卡片体系
- 纪念日列表:display:flex 从 td 移到内层 div(写在 td 上会破坏表格列算法,
表现为关联人列与其它列高度不一致);行内列序按表头对齐;
改完再点「新建」不再带出上次修改的数据;文案改为「与我相关」「来自名册」;
别人记的、把我挂成关联人的条目一并显示(split() 返回 hiddenIds,
路由层据此过滤「接下来的日子」,与两张表同一套可见性)
- 分类图标:新增 app/AnnivIcon.php(17 个行内 SVG 图标 + 同 key 的 emoji
供日历纯文本处使用,内网无 CDN 不用 FontAwesome);去掉「看日历」按钮;
设置按钮改为菜单,第一项进 days/settings 独立页;分类可自选图标,
列表徽标与日历条目都按分类显示
- 首页卡片:新增 app/HomeCards.php 与 templates/home_cards.php;
8 格宽 × 高 2/4/6/8;首页拆成 templates/home/_card_*.php 共 8 个片段;
home/cards 可改尺寸、调顺序、开关
|
2026-10-19 12:51:17 +08:00 |
|