跨端: 左右滑动翻页(P6 第 3 步)+ 还 gesture-semantics 债 + 修跑不起来的判据基建
★ 这一轮从用户一句「滑动手势呢?」开始。查下去发现它不是"顺手加个手势",
而是 `docs/DEBTS.json` 里挂着的一笔债 —— `gesture-semantics` 的原话是:
「P6 第 3 步:鸿蒙侧出现滑动手势代码时**立即建**判据
(此前建 = 只有一端存在的假判据)」
也就是**先有手势、再钉语义**。WebUI 2026-09-14 就有滑动翻页(用户当时
亲口提的),鸿蒙一直没有 ⇒ 之前建判据会是空真(∀x∈∅)。
## 一、手势本体(两端语义逐项对齐,数值各自定)
按 `HARMONY-ALIGN-PLAN.md:118-128` 显式选的 **(b) 口径**:
「手势的物理量本来就不该强求同值……该对齐的是**语义层**」。
· 判定逻辑放**纯逻辑层** `model/Calendar.ts` 的 `judgeSwipe`(可被 node 直跑,
写在 .ets 里就跑不了判据,语义没法被单测钉住)。四道门:位移 / 纵向优先 /
快滑窗口 / 方向。
· 阈值**不引用** WebUI 的 40 / 1.5 / 600(那是把巧合当契约),
各自定为 56vp / 1.4× / 700ms,并在注释里写出取值依据。
· 接线在 `CalendarPage.ets`:`PanGesture({direction: Horizontal})` +
`onActionStart`(记时 —— `GestureEvent` **没有时间戳字段**,我查了 SDK
的 gesture.d.ts 确认)+ `onActionEnd`(读 offsetX/offsetY)。
· ★ 挂在**网格列**上而不是整页:右栏(日程/编辑器)里有输入框与可滚内容,
整页挂会让「在表单里横划一下」变成翻月。
· ★ 翻页复用 `shiftRange()`(与 ‹ › 按钮**同一个来源**)—— WebUI 的注释
专门交代过:各写一套的话,阈值、边界、三档行为迟早分叉。
手势回调里**不准**直接改 year/month(锚点是唯一真相,年月只能由
`shiftRange → syncYearMonthFrom` 派生)。
**有意差异(记录在案,不是漏做)**:WebUI 在周/日档会额外检查「触点是否落在
可横向滚动的区域里」,是则让给滚动条(用户 2026-09-14 报过这个冲突)。
鸿蒙周档是「一行 7 格按 layoutWeight 等分」、**不横滚** ⇒ 该条件不适用。
哪天加了横滚必须同时补上它。
## 二、判据(8 条语义契约 + 行为层)
新增 `cross-client-gesture.test.mjs`:两端都真有手势 / 方向映射逐项相同 /
纵向优先 / 快滑窗口 / 复用同一翻页函数 / 无边界回弹 / 有意差异被记录 / 自检。
**只比语义、不比数值**,并反向断言鸿蒙的阈值常量不得直接取 WebUI 的那三个数。
`harmony-logic.test.mjs` 加行为判据:真跑 `judgeSwipe`,把四道门各自验一遍
(只钉字符串的话,一个 return 写漏了照样全绿)。
## 三、顺手修掉的三处**判据基建**缺陷(不修就没法验证上面这些)
1. `run-all.mjs` 只认 `# pass N`,而 node v24 打的是 `ℹ pass N`
⇒ **21 个文件被记成"没自报条数"**、套件在 HEAD 就恒红(memory 里记过这条,
修法也记过,今天终于落进代码:4 个正则加 `(?:#|ℹ)`)。修完 `unreported` 27 → 0。
代价是暴露出一批此前被"没自报"掩盖的真实问题(下面 4~6 条)。
2. `harmony-nav` 的设备判据 `navItemsOf`:宽屏过滤条件从「左边缘靠左 1/6」
改成「**整个盒子在侧栏轨道内**」。旧条件把**日历网格的格子**
(实测 `[229,511][366,794]`)也当成导航项,一屏数出 11~12 个。
这是设备实测抓出来的 —— 我第一版还以为是"底部簇混进来了",
打印真实数据才发现是隔壁页面的格子。
3. `harmony-logic` 两处:从 `NAV_ITEMS` / `NAV_SIDEBAR_ITEMS` **各自的数组**里取
label。原先把全文件 `label:` 一网打尽 ⇒ 得到 7 个(4+3 混在一起),
任何一边改对了它都会红。
## 四、被判据拦住后的正经修法(每条都按判据自己给的方向改,不改判据迁就代码)
· `cross-client-theme` A2 拦住我:新增的 `navActiveBg`/`navBrandFg`/`badgePlain`
未登记;又拦住我:`sseColorOf` 里四个裸色值。→ 抽成 `Theme.sseConnected` 等
四个令牌(取值对齐 WebUI 的 Tailwind 类)+ 登记 + 在 Theme.ets 的表里写理由。
· 同一条判据的"死令牌"检出:`Theme.durBase` 声明了却从没人读。
**查 WebUI 才发现壁纸淡入是真有的动效**(`index.css:742-752` 的
`.app-backdrop` 从 opacity:0 → 1,180ms)⇒ 补上而不是删令牌
(删掉等于把差异抹平、还说成"清理")。reset 在 `animateTo` **外**,
与 `calPaneIn` 同一条纪律。
· 玻璃登记:`NavItemBuilder` → `SidebarItem`(重构后按最近的 @Builder 命名),
登记同步跟上。
· `harmony-admin` 的退出判据:退出逻辑抽成 `api/Logout.ets` 的 `performLogout()`
(两个入口——「我的」页与侧栏底簇——必须做同一件事,尤其"先注销推送 token"
那一步)。判据相应改成**追到实际执行处**(两半都断:按钮调了 + 函数真清了全部),
并写明"别再退回直接匹配 SETTINGS_PAGE 的写法"(那会随重构假红,
下一个人只会去改判据而不看行为)。
· `harmony-widescreen` 的连接点色值:色值搬进 Theme 后,判据改成断
「令牌定义对了 + 侧栏真的用了它」两半(只断任一半都有假绿形态)。
· `align-refs`:`CalendarView.tsx` 变了,按判据要求**读一遍差异**再更新登记
(差异只有农历小字的灰阶档位 gray-300→gray-400/500,**骨架未变**)。
· `criteria-hygiene`:`harmony-contacts` 自造了一个 `code()`、`harmony-widescreen`
裸用 `readFileSync` ⇒ 都改用 `lib/read.mjs` 的共享入口。
途中撞出一个**判据自己的 bug**:`code()` 的块注释正则
`/\*[\s\S]*?\*\//` 会把注释里出现的 `/*`(如 `/」**` 这种中文夹星号)
当成块注释起点,一路吃到几十行后的 `*/`,把中间的 import 全吞掉 ——
于是 hygiene 判据假红"没 import"。改掉那处写法后正常。
## 五、验证
判据面:`run-all.mjs` → `files=32 ran=32 checks=497 pass=497 fail=0
skip=0 red=0 broken=0 unreported=0`。
其中新/改判据:gesture 8、nav 18、widescreen 7、logic 30、admin 27、
cross-client-theme 15、criteria-hygiene 6。
构建:`hvigorw assembleHap` 成功;前端 `npm run build` + 重新打 AppImage/deb
(`build-stamp` 7/7、`packaging` 5/5)。
**设备实测(HATriple 三折叠 3184×2232,hdc 连 127.0.0.1:5555)**:
· 农历在格子里真的显示(1=二十 / 7=廿六 / 19=**初九** / 11=八月),与 WebUI 一致;
这条同时验证了**服务端农历路由已部署**(之前线上是 404)。
· 日历左右两栏:编辑器出现在**右栏**、左栏月份仍可见(单栏模式下编辑器会整页盖掉它)。
· 侧栏 3 项 + 底部一簇;徽标回到图标右上角。
**仍未验(如实标注)**:滑动翻页的**手感**(阈值 56vp/1.4×/700ms 是否合适)
只能真人滑过才知道;我只验了判定逻辑与接线形态。动画同理 ——
机制已验证(`animateTo` 驱动 + reset 在窗口外),但"看起来顺不顺"未做取样验证。
docs:`DEBTS.json` 销掉 `gesture-semantics`(并记结算说明)、
`HARMONY-ALIGN-PLAN.md` P6 从「✅(滑动翻页除外)」改为 ✅。
This commit is contained in:
@ -10,10 +10,10 @@
|
||||
{
|
||||
"id": "calendar-view",
|
||||
"path": "client/electron/src/components/CalendarView.tsx",
|
||||
"blob": "31a62fffd75c076ca86dc065ec7d6eec47fce985",
|
||||
"atCommit": "bb8201f",
|
||||
"atCommitSubject": "feat(webui): 回复/转发动画真的会播了 + 写邮件改成「按钮长成整页」",
|
||||
"note": "P6 日历骨架的对齐目标。**2026-09-15 第二次重新核对**:本次差异只有根节点的动画类 rise-in → pane-rise(拆「挂载即播」与「窗口触发」两档时改的名,见 436de6e)——骨架结构、布局类、圆角来源全都未变;鸿蒙侧日历本来就没有动效实现(grep 无 animate/transition),所以仍不产生新的对齐义务。此前两笔:日历圆角修复、根节点加 rise-in。"
|
||||
"blob": "89aa237be83a074d8871d13cea17d3a02a7dce72",
|
||||
"atCommit": "7b8c78f",
|
||||
"atCommitSubject": "维护: 底本重算(4 个文件漂移 = **底本过期**,不是变异残留)—— 逐个核实后按本文件的协议记一行\"为什么\"",
|
||||
"note": "P6 日历骨架的对齐目标。**2026-09-19 第三次重新核对**:本次差异只有一处 —— 非本月日期的农历小字从 gray-300 改到 gray-400/500(gray-300 是分隔线档,当文字用只有 ~1.47:1)。**骨架未变**:仍是 gridPane(flex-1) + 400px 右栏两栏结构、工具条分组与顺序、手势与按钮共用 shift()。鸿蒙侧不受影响 —— 它的次要文字走 Theme.textMuted 这类语义令牌,不引用灰阶档位。此前两笔:动画类 rise-in → pane-rise(拆两档时改名)、日历圆角修复。"
|
||||
}
|
||||
],
|
||||
"radius": [
|
||||
@ -44,4 +44,4 @@
|
||||
"appId": "6917616450599975320",
|
||||
"note": "AGC 下发的配置(加密信封格式,非明文密钥)。**包名必须与 AppScope/app.json5 的 bundleName 完全一致** —— 不一致时 Push Kit 推不到设备,这不是风格问题而是功能性约束(pi 邮件 `1f9ff3b4` 实测:AGC 拒绝 `com.agentmail.harmony`,因为 `harmony` 是包名保留字;用户定 `com.jianf.agentmail`)。"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,8 @@
|
||||
"没有一处能看全 —— 而『欠账不显形,就等于没有』;分散在多处的登记,审计时只会被找到一处就当全部。",
|
||||
"两端都读这个文件:Go 侧判据断言自己的条目与**实测**一致(不许留一份手写的数字),",
|
||||
"electron 套件把它打进 RESULT 行(那是常态可见的位置)。",
|
||||
"已结算(2026-09-14):calendar-today-recompute —— P6 第 1 步(日历页 pages/CalendarPage.ets)落地,today 走 `@Prop @Watch('onVisibleChanged') visible` 在 pane 变可见时重算(另有 aboutToAppear 覆盖重新挂载),判据 test/harmony-calendar.test.mjs 的「★ today 在 pane **变可见时**重算」。结算即从此清单移除,余额里不再计这一笔。"
|
||||
"已结算(2026-09-14):calendar-today-recompute —— P6 第 1 步(日历页 pages/CalendarPage.ets)落地,today 走 `@Prop @Watch('onVisibleChanged') visible` 在 pane 变可见时重算(另有 aboutToAppear 覆盖重新挂载),判据 test/harmony-calendar.test.mjs 的「★ today 在 pane **变可见时**重算」。结算即从此清单移除,余额里不再计这一笔。",
|
||||
"已结算(2026-09-19):gesture-semantics —— P6 第 3 步(左右滑动翻页)落地:鸿蒙侧 `CalendarPage.ets` 加了 `PanGesture`、判定逻辑在纯逻辑层 `model/Calendar.ts` 的 `judgeSwipe`。按该条自己的口径(「鸿蒙侧出现滑动手势代码时**立即建**」)同步建了语义契约判据 `test/cross-client-gesture.test.mjs`(8 条)—— 按 (b) 口径钉**语义**不钉数值:左滑=下一段/右滑=上一段/纵向优先/快滑窗口/手势与按钮共用同一翻页函数/无边界回弹/有意差异被记录/方向写反必红。另在 `harmony-logic.test.mjs` 加了行为判据(跑 `judgeSwipe` 的四道门)。结算即从此清单移除,余额里不再计这一笔。"
|
||||
],
|
||||
"debts": [
|
||||
{
|
||||
@ -22,13 +23,6 @@
|
||||
"where": "server/internal/repo/mail_status_derived_test.go",
|
||||
"kind": "scope"
|
||||
},
|
||||
{
|
||||
"id": "gesture-semantics",
|
||||
"count": 1,
|
||||
"due": "P6 第 3 步:鸿蒙侧出现滑动手势代码时立即建(此前建 = 只有一端存在的假判据)",
|
||||
"where": "docs/HARMONY-ALIGN-PLAN.md P6 段",
|
||||
"kind": "scope"
|
||||
},
|
||||
{
|
||||
"id": "observability-output",
|
||||
"count": 1,
|
||||
@ -114,4 +108,4 @@
|
||||
"kind": "scope"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -250,7 +250,7 @@ WebUI 侧 `npm test` 在 **HEAD 上就是红的**(`test/background.test.mjs`
|
||||
| P3 ⚠️ 主体完成 | 授权页:`GET /permission/pending` + `POST /permission/decide` | 未决口径与 WebUI 一致(无 `permission_result`)✅;拒绝可填备注且备注送出 ✅;`expired` 当场说清"这次批准不会恢复原调用" ✅。**未验**:真机上点同意/拒绝后状态是否"立刻变"(判据只钉到"决策后重新拉列表"这一层) |
|
||||
| P4 ✅(P4c 上传除外) | 主题/壁纸(`/me/appearance`) | 换账号外观跟随 ✅(缓存键带账号);服务端无记录时以本地为准 ✅(§7.16);**预设 6 档都能画出来** ✅、图片壁纸渲染 ✅(§7.17 —— 这一版补的,第一版只有数据没有画面)。**未做**:P4c 上传入口。**未验**:真机观感(配色/对比) |
|
||||
| P5 ✅ 主体完成 | 悬浮玻璃导航(取代系统 TabBar) | **已换**:自绘浮动玻璃条 `NavBar`(留白 + 胶囊圆角 + 系统材质),内容按 `currentIndex` 挂载;命中区 ≥44vp(数值在 `NavItems.ts`,判据直接 import);内容底部让出 76vp(不让位则最后一行压在条底下:看得见、点不到)—— §7.21。判据 6 条全绿、4 种变异都能红。**未验**:玻璃条在真机上的观感(材质浓度/圆角/阴影)、深色主题下的表现、字形图标渲染 —— **原因是环境硬约束**(模拟器要写工作区外 + 审批无人可送 + 许可协议不接受代签),见 §7.21 末节的「视觉验收的实测阻塞」 |
|
||||
| P6 ✅(滑动翻页除外) | 日历(`/calendar/events` + 农历 `GET /calendar/lunar` + ics 导入导出) | 手势阈值按 **(b)**:**不要求数值一致**(数值各自定、按设备人体工学),契约钉**语义层**(左右滑=什么、边界回弹、「快滑」感知档);鸿蒙**不得引用** WebUI 的三个数(详见分期段)。**有意排序**:入口与内容一起上,不留空页签(§7.15)。<br>**2026-09-18 实况**:只读月/周/日三档 ✅(`b372d0f`)、写侧(新建/编辑/删除)✅、农历 ✅(`5ea9884` —— 走服务端端点,不在 ArkTS 里重写天文算法)、**ics 导入导出 ✅**(`7e10bfa`,走 `DocumentViewPicker`:鸿蒙无「下载目录」概念,这是该平台上唯一能让用户拿到/指定文件的路)。**仍未做**:左右滑动翻页(P6 第 3 步,牵着 `docs/DEBTS.json` 的 `gesture-semantics`) |
|
||||
| P6 ✅ | 日历(`/calendar/events` + 农历 `GET /calendar/lunar` + ics 导入导出) | 手势阈值按 **(b)**:**不要求数值一致**(数值各自定、按设备人体工学),契约钉**语义层**(左右滑=什么、边界回弹、「快滑」感知档);鸿蒙**不得引用** WebUI 的三个数(详见分期段)。**有意排序**:入口与内容一起上,不留空页签(§7.15)。<br>**2026-09-18 实况**:只读月/周/日三档 ✅(`b372d0f`)、写侧(新建/编辑/删除)✅、农历 ✅(`5ea9884` —— 走服务端端点,不在 ArkTS 里重写天文算法)、**ics 导入导出 ✅**(`7e10bfa`,走 `DocumentViewPicker`:鸿蒙无「下载目录」概念,这是该平台上唯一能让用户拿到/指定文件的路)。**2026-09-19 补齐**:左右滑动翻页(P6 第 3 步)✅ —— `PanGesture` 挂在网格列上(不是整页:右栏有输入框与可滚内容,整页挂会让「在表单里横划一下」变成翻月),判定走纯逻辑 `model/Calendar.ts` 的 `judgeSwipe`,翻页复用 `shiftRange`(与 ‹ › 按钮同一来源)。语义契约判据 `test/cross-client-gesture.test.mjs`(8 条,按 (b) 钉语义不钉数值)。★ **有意差异**:WebUI 在周/日档会把手势让给横向滚动条(用户 2026-09-14 亲口报过这个冲突),鸿蒙周档是「一行 7 格按 layoutWeight 等分」、**不横滚** ⇒ 该卡严条件在此不适用(不是漏做)。哪天给周档加了横滚,必须同时补上它 |
|
||||
|
||||
**视觉/交互怎么验**:本机有 `harmony-emu`(实例 `HarmonyPhone`,hdc 在
|
||||
`/opt/harmonyos/ohos-sdk/linux/toolchains`),能起来就能截图 + 真点,
|
||||
|
||||
Reference in New Issue
Block a user