v60:范围时间控件只改一端(点「确定」不再跳回开始)

用户反馈:范围控件里前面的时间不用改,直接点后面的结束时间,选完之后它还是
跳回开始时间、要重新选开始 —— 没必要。

真根因(不是接线错,一个回调都不挂的裸 RangePicker 也一样):
 ① rc-picker 点「确定」会把活动端复位到「开始」(那是为下一次选择准备的,
    正常情况面板同时也该关掉,用户看不见);
 ② 这个版本关完面板又把焦点送回开始输入框,而 Trigger 「聚焦即展开」,
    于是面板又开了、还停在「开始」端。

修法:接管 open —— 点「确定」就关(onOk),开合由 onOpenChange 同步。
只给成对的范围控件(观影/日程/行程的起止)加;单点控件(任务截止时间)
不动 —— 它点确定本来就能正常关闭。

编号说明:v56/v57/v58/v59 已被「设备会话 / 增量同步」那批用掉,本批顺延 v60。

验证:
- _fb_v60_ui.py 真机 28 条(只改结束日期/时刻不动开始、确定后关闭、
  关掉后能重开、点面板外能关、日历点格子带入时间仍同步、单点控件不受影响)
- _b60_falsify.py 3 处注入全部变红(不接管 open / 确定不关 / 连张开都吞掉)
- 回归:v55 套件 30/30、v45 重复到 10/10 仍全绿
This commit is contained in:
2026-10-18 09:56:00 +08:00
parent ebaed21920
commit 54ab9f825b
+24
View File
@@ -2017,6 +2017,20 @@
⚠️ 状态用 `v0/v1` 两个字符串('YYYY-MM-DD HH:mm'):与 writeBack 的入参同一 ⚠️ 状态用 `v0/v1` 两个字符串('YYYY-MM-DD HH:mm'):与 writeBack 的入参同一
口径(antd 的 `strs` 就是这个格式),不用在两条路之间换算。 */ 口径(antd 的 `strs` 就是这个格式),不用在两条路之间换算。 */
var st0 = v0, st1 = v1; var st0 = v0, st1 = v1;
/* 🔴🔴 v60(用户 2026-10-18):**范围控件只改一端,选完不该被赶回起点**。
现象:「前面的时间不用改,我直接点后面的结束时间;选完之后它还是跳回到
开始时间、让我重新选开始 —— 没必要。」
链路(**不是我们接线接错了** —— 一个回调都不挂的裸 RangePicker 也一样):
① 点「确定」→ rc-picker 把**活动端复位到「开始」**(那是为"下一次选择"
准备的,正常情况下面板同时也该关掉,用户看不见);
② 但这个版本关完面板又把焦点**送回开始输入框**,Trigger 是"聚焦即展开"
⇒ 面板又开了、还停在「开始」端 ⇒ 用户看到的就是"让我重选开始"。
⇒ 这里**接管 open**:面板开合由我们说了算,点「确定」就关(`onOk`)。
⚠️ 别把 `open` 的接管抄到 `mountAntdSingleDT`:单点控件(任务截止时间)
实测点确定能正常关闭 —— 没有"复位活动端"这回事,多接管一层反而挡开合。
⚠️ 反向验证(_b60_falsify 三处注入)证明:去掉 `open` 接管 / 去掉
`onOk` 里的关闭 / 让 `onOpenChange` 连张开都吞掉 —— 对应断言都会变红。 */
var openState = false;
var root = null; var root = null;
function renderPicker() { function renderPicker() {
@@ -2027,6 +2041,16 @@
placeholder: ['开始时间', '结束时间'], placeholder: ['开始时间', '结束时间'],
// ⚠️ 受控:空串要给 null,否则 dayjs('') 会变成 Invalid Date → 控件显示 NaN // ⚠️ 受控:空串要给 null,否则 dayjs('') 会变成 Invalid Date → 控件显示 NaN
value: [st0 ? toDayjs(st0) : null, st1 ? toDayjs(st1) : null], value: [st0 ? toDayjs(st0) : null, st1 ? toDayjs(st1) : null],
// 🔴 v60:面板开合由我们说了算(见上面那段)。
open: openState,
onOpenChange: function (o) {
openState = !!o;
renderPicker();
},
onOk: function () {
openState = false;
renderPicker();
},
// ⚠️ onCalendarChange 是**单端也算**的那个(实测:只点开始它就响); // ⚠️ onCalendarChange 是**单端也算**的那个(实测:只点开始它就响);
// onChange 只在两端齐了才响。两个都挂才不会丢值。 // onChange 只在两端齐了才响。两个都挂才不会丢值。
onCalendarChange: function (vals, strs) { onCalendarChange: function (vals, strs) {