用户 2026-10-30:
网页端,跨天日程显示还是有问题…如果一个日程跨了三天,应该在日历本上怎么显示呢? 在周视图和日视图,应该怎么显示?现在显示的有问题。
用真实数据跑 build_time_grid:一个「11/10 20:00 → 11/12 02:00」的跨三天日程, 服务端 Calendar::month() 展开成三条(第一天带 time、中间天两者皆空、末天带 end_time), 输入 build_time_grid 后得到:
build_time_grid
Calendar::month()
time
end_time
=== 全天行 === 第1列 (2026-11-11): 跨天日程 第2列 (2026-11-12): 跨天日程 === 时间网格 === 第0列 (2026-11-10): top=83.33% height=2.08%
即:
三个问题叠加:
$endMin
build_time_grid()(index.php:517)只做单天定位:
build_time_grid()
index.php:517
$ci = $dayIndex[(string)$e['date']] ?? null; if ($ci === null) { continue; } // 只认起始日那一列 ... if ($t === '' || !preg_match(...)) { $allDay[$ci][] = $e; continue; } // 无时刻 ⇒ 全天
它不知道某条是"跨天日程的延续",也没有跨越天数的信息。 服务端展开时只给了 date/time/end_time,没有 是第几天/共几天。
date
是第几天/共几天
服务端(build_time_grid)
把同一日程的逐天条目合并回一条,并算清跨越了哪几列:
ref_id
occ
cols => [起始列, 结束列]
seg
data-fb-entry
模板(calendar/index.php)
calendar/index.php
left = 列起点%
width = 跨列数 / 总列数
overflow: hidden
.tg-body
conflictLanes
网页端跨天日程在周/日视图的渲染问题(build_time_grid 合并与跨列定位);#34 是鸿蒙端日程编辑时间选择器参数写反,#32 是地址联想下拉,#33 是端上地址联想,都是不同端、不同文件。
01d5bc2
线上已部署,4 个文件 sha256 与仓库一致,站点无 PHP 错误 (/ 302、/api/v1/calendar/books 401,均符合预期)。
/
/api/v1/calendar/books
一个「11/10 20:00 → 11/12 02:00」的跨三天日程,喂给 build_time_grid 后:
全天行:11/11、11/12 各一条 ← 中间两天变成"全天日程" 时间网格:11/10 一个小块,高度仅 2.08%(≈30 分钟)
↳
app/Calendar.php —— 补 span_days(跨几天)/ seg(start/mid/end/only)。 同时修掉一个真 bug:原来 $first 是"窗口内遍历的第一个", 日视图只查一天时,中间天会变成 $first 被当成开始日处理。 ⇒ 改用真实日期跟 $base/$base+span 比较,不看遍历顺序。
app/Calendar.php
span_days
$first
$base
$base+span
index.php::build_time_grid —— 先按 kind:ref_id:occ 归堆合并, 再按列切段。
index.php::build_time_grid
kind:ref_id:occ
归堆键必须带 occ:重复日程不同次发生的 ref_id 相同, 不带它会把 11/10 和 12/01 两次发生揉成一条(画成横跨三周的怪东西)。 也必须带 kind:观影/旅程的 ref_id 是各自表里的 id, custom:5 和 movie:5 是两回事。
kind
custom:5
movie:5
templates/calendar/index.php —— is-seg-* 类 + ↳ 延续标记; 跨天段用 left:0; width:100%,单天块保持原样。
templates/calendar/index.php
is-seg-*
left:0; width:100%
assets/css/app.css —— 段与段之间:起始段下圆角归零 + 下边框透明, 中间段上下都平,结束段上圆角归零 + 上边框透明。
assets/css/app.css
缝隙从 10.9px 降到 1.0px 的关键不只是圆角, 还有「跨天段要贴满整列」——单天块原本的 calc(2px + 1%) / calc(98% - 4px) 内缩在跨天段上会累积成明显的断口。
calc(2px + 1%)
calc(98% - 4px)
.tg-body 左边有 56px 固定 gutter,窄屏还会横向滚动 (.cal-tg-card{overflow:auto} + 每列 min-width:92px),.tg-col 又是 overflow:hidden。跨列层要自己算 gutter 偏移、跟着横向滚动跑、还不能被裁, 每个都是新坑。在列内画段天然对齐,代价只是段间 1px 列边框缝,用 CSS 糊掉即可。
.cal-tg-card{overflow:auto}
min-width:92px
.tg-col
overflow:hidden
逻辑层(PHP,跑真实 build_time_grid)
timed=1 all_day=2
视觉层(Playwright + 真实 CSS + include 真实模板)32 项全过
反向验证 4/4 全部抓到 故意做坏四个变体(段留单天内缩 / 保留圆角 / 中间段只画 30% / 下边框不透明), 判据全部转红 —— 说明"32 项全过"不是因为判据恒真。
跨天段占满整列,同一天的普通日程会与它在视觉上重叠。 这是日历的固有取舍(Google 日历同样如此)。
/home/btops/deploy-backups/multiday-20261030-234323/
app.css
is-seg-start
cp -a
用户 2026-11-01 明确回复「#35,可以关单了」。
commit 01d5bc2,已部署 family.yangyq.net 线上。
关键改动 4 个文件:app/Calendar.php(补 span_days/seg,并修掉日视图 $first 判据 bug)、 index.php::build_time_grid(按 kind:ref_id:occ 归堆后按列切段)、 templates/calendar/index.php(is-seg-* 类 + 延续标记)、assets/css/app.css(分段圆角/边框)。
验证:PHP 逻辑层 + Playwright 视觉层 32 项全过 + 反向验证 4/4 抓到。
跨天段占满整列,同一天的普通日程会与它在视觉上重叠 —— 与 Google 日历同样的固有取舍。
No dependencies set.
The note is not visible to the blocked user.
现象
用户 2026-10-30:
实测复现(不是靠猜)
用真实数据跑
build_time_grid:一个「11/10 20:00 → 11/12 02:00」的跨三天日程,服务端
Calendar::month()展开成三条(第一天带time、中间天两者皆空、末天带end_time),输入
build_time_grid后得到:即:
三个问题叠加:
$endMin被判无效 ⇒ 退化成 30 分钟的最短块。build_time_grid里"没有time又不是全天 ⇒ 按全天处理"这条兜底把跨天的延续日当成了全天日程。
根因
build_time_grid()(index.php:517)只做单天定位:它不知道某条是"跨天日程的延续",也没有跨越天数的信息。
服务端展开时只给了
date/time/end_time,没有是第几天/共几天。方案(用户 2026-10-30 已确认三条)
视觉上连成一条(同 Google/Apple 日历的做法)。
顶部标「← 接昨日」之类的提示。
实现要点
服务端(
build_time_grid)把同一日程的逐天条目合并回一条,并算清跨越了哪几列:
ref_id+occ(重复日程的不同次发生不能混)cols => [起始列, 结束列],以及seg(本段在该列的形态:起始/延续/结束/整天)
time;末段结束时刻 = 最后一条的end_timeend_time)data-fb-entry)仍取原条目,保证"点开能编辑"模板(
calendar/index.php)用
left = 列起点%、width = 跨列数 / 总列数定位overflow: hidden?—— 跨列色块不放在列里,放在.tg-body之上的一层,避免被裁切
验收标准
time画到当日 24:00(不再退化成 30 分钟)end_timeconflictLanes)对单天日程仍生效为什么单独建单
网页端跨天日程在周/日视图的渲染问题(build_time_grid 合并与跨列定位);#34 是鸿蒙端日程编辑时间选择器参数写反,#32 是地址联想下拉,#33 是端上地址联想,都是不同端、不同文件。
已修复并上线(commit
01d5bc2)线上已部署,4 个文件 sha256 与仓库一致,站点无 PHP 错误
(
/302、/api/v1/calendar/books401,均符合预期)。修复前实测到的样子
一个「11/10 20:00 → 11/12 02:00」的跨三天日程,喂给
build_time_grid后:三个问题叠加:
time又不是全天 ⇒ 被"按全天处理"的兜底收走按你确认的三条方案实现
↳表示接续关键改动
app/Calendar.php—— 补span_days(跨几天)/seg(start/mid/end/only)。同时修掉一个真 bug:原来
$first是"窗口内遍历的第一个",日视图只查一天时,中间天会变成
$first被当成开始日处理。⇒ 改用真实日期跟
$base/$base+span比较,不看遍历顺序。index.php::build_time_grid—— 先按kind:ref_id:occ归堆合并,再按列切段。
templates/calendar/index.php——is-seg-*类 +↳延续标记;跨天段用
left:0; width:100%,单天块保持原样。assets/css/app.css—— 段与段之间:起始段下圆角归零 + 下边框透明,中间段上下都平,结束段上圆角归零 + 上边框透明。
为什么不做跨列绝对定位层
.tg-body左边有 56px 固定 gutter,窄屏还会横向滚动(
.cal-tg-card{overflow:auto}+ 每列min-width:92px),.tg-col又是overflow:hidden。跨列层要自己算 gutter 偏移、跟着横向滚动跑、还不能被裁,每个都是新坑。在列内画段天然对齐,代价只是段间 1px 列边框缝,用 CSS 糊掉即可。
验证
逻辑层(PHP,跑真实
build_time_grid)(旧版
timed=1 all_day=2,高度 2.08%)✓视觉层(Playwright + 真实 CSS + include 真实模板)32 项全过
反向验证 4/4 全部抓到
故意做坏四个变体(段留单天内缩 / 保留圆角 / 中间段只画 30% / 下边框不透明),
判据全部转红 —— 说明"32 项全过"不是因为判据恒真。
已知取舍
跨天段占满整列,同一天的普通日程会与它在视觉上重叠。
这是日历的固有取舍(Google 日历同样如此)。
部署记录
/home/btops/deploy-backups/multiday-20261030-234323/(按目录结构保存 4 个文件)app.css已含is-seg-start,ETag 已更新cp -a回去即可用户验收通过,关单(2026-11-01)
用户 2026-11-01 明确回复「#35,可以关单了」。
交付回顾
commit
01d5bc2,已部署 family.yangyq.net 线上。↳标记、结束天 00:00→02:00关键改动 4 个文件:
app/Calendar.php(补 span_days/seg,并修掉日视图 $first 判据 bug)、index.php::build_time_grid(按 kind:ref_id:occ 归堆后按列切段)、templates/calendar/index.php(is-seg-* 类 + 延续标记)、assets/css/app.css(分段圆角/边框)。验证:PHP 逻辑层 + Playwright 视觉层 32 项全过 + 反向验证 4/4 抓到。
已知取舍(用户已知悉)
跨天段占满整列,同一天的普通日程会与它在视觉上重叠 —— 与 Google 日历同样的固有取舍。