laoyang
|
0f22aef689
|
弹框动画丝滑化:入场加位移+弹簧曲线,修加载态打断动画 (#82)
用户:首页,弹出所有弹框,动画,都要改一下,改的跟丝滑流畅,
尤其是观影,基本上没动画,都需要修改。
先核实:把时长临时放大到 3s 后连拍,遮罩 246→210→170→153→148 逐帧压暗,
说明**动画确实在播**。所以不是没接上,而是动效本身太弱:
220ms 太短、只有 0.94→1 缩放(差 6%,且无方向感)、FastOutSlowIn 落定硬停、
进出同长。
四处改动:
① 入场加纵向位移 SHEET_RISE_VP=22 —— 竖向是人眼最敏感的方向,
纯缩放读不出从哪来;22vp 是看得出从下面来但不觉得它飞了的量。
② 时长分离:卡片 320/200、遮罩 240/160(出场必须比入场快,
用户已决定关闭,等待就是拦他);缩放起点 0.94→0.90。
③ 曲线换物理弹簧 curves.springCurve(0, 1, 228, 26)(末段自然收敛)。
⚠️ 先写的 Curve.springMotion 编译失败——本工程 SDK 6.1.1 里没这个 API,
技能包速查表也把它列在高频臆造 API里,是我没照表走。
④ 观影/日程详情卡加载态:**这是观影没动画的真凶** ——
卡片高度按内容定,加载态只有一行字(~100px),详情回来瞬间撑到 72% 屏高,
320ms 的入场动画只播了前 1/3 就被高度突变打断。
改法:加载态放固定 460vp 骨架屏(FbEventSheet 同样问题,一并修 300vp)。
用固定 vp 而非 %:builder 在 Scroll 里,百分比拿不到基准。
验证(真机):放大时长连拍 N2 卡片顶边 y=1073 → N3 y=1011,
上移 62px≈20vp,证实位移生效;临时给接口加 1.5s 延迟后抓图,
骨架屏(海报位+4 条文字条)正确撑住卡片高度;临时代码已撤除(grep 0 处)。
连开合 3 轮均正常、无 JS 崩溃、进程存活。
hvigorw assembleHap BUILD SUCCESSFUL。
FbAnim 是全站唯一动画入口,98 处引用 / 14 个页面,全部同时生效。
|
2026-11-06 10:18:22 +08:00 |
|
laoyang
|
5fba8c4eda
|
修导航目的地前面多出问号 (#69)
用户 2026-11-05:「导航的,点进去导航之后,为什么目的地地址前面有个问号」
根因:我上一轮拼的是 `lat,lng?地名` —— 那个 `?` 是照抄 `geo:` URI 的写法,
但这个字符串**不是 URI**,是交给 fbOpenNavigation() 的普通文本。
FbNav.parseGeoOf() 的动作:
① 正则抓 `数字,数字` 当坐标
② clean = 把坐标从原文剪掉后剩下的文字,用作地名
传 `36.168977,120.375693?青岛北站` 剪掉坐标后剩 `?青岛北站`
⇒ 问号跟着进了高德 dname,目的地标题显示成「?青岛北站」。
改成「地名 + 空格 + lat,lng」:
`青岛北站 36.168977,120.375693`
剪掉坐标后剩「青岛北站」,正是要显示的名字。
实测(复刻 parseGeoOf 跑):
旧 lat,lng?地名 → clean=[?青岛北站] ❌
新 地名 lat,lng → clean=[青岛北站] ✅
只有地名 → ok=false 走地理编码 ✅
两处都改了:
- FbEventSheet.navTargetOf()(#69 新增的)
- FbDayEventPanel 行程卡片的 onClick(#67 里同一个错误)
|
2026-11-05 17:22:36 +08:00 |
|
laoyang
|
ad9b934760
|
日程详情卡:补齐行程的出发地/目的地 (#69)
用户 2026-11-05:「点击行程里旅行日历本里的信息时,弹出来的那个框是在首页上
弹出的,还是没有出发地和目的地。」
根因链(三段,缺一段都不显示):
1. FbCalEventFull 没有那四个字段
#67 只给了 FbCalEvent(列表用),详情卡消费的是 FbCalEventFull。
2. shellOf() 只塞了 location: b.place
行程节点的 place 是空串 —— 它的位置概念是"从哪到哪",没有单一地点。
3. 最关键:行程条目**永远走 shell,压根不请求详情接口**
openEvent() 里 `if (!isEditableEvent(e)) { shellOf(e); return; }`,
行程的 kind 是 trip 不是 custom ⇒ 直接短路。
而且即使去请求也没意义:Calendar::event($id) 查的是 calendar_events,
行程节点在 trip_nodes 表,那个 id 查不到东西。
⇒ 位置信息**只能**靠 shell 带过去。
改动:
- FbCalEventFull 加 fromPlace/toPlace/fromLng/fromLat/toLng/toLat
- FbCalRepo.toFull() 从接口读(接口给就填,普通日程取到空串)
- 首页 FbHomePage.shellOf()、日程页 FbCalendarPage.shellOf() 两处传递
(两处是独立实现,只改一处会漏)
- FbEventSheet:
· navRow 改 navRowRaw(label, place, navTarget) —— 标签不再硬编码「地点」
· onNavigate 从无参改成 onNavigate(navTarget)
原来宿主只能读 event.location 猜导航目标,无法区分出发地/目的地
· 渲染三分支:有 fromPlace 画「出发地」、有 toPlace 画「目的地」、
有 location 画「地点」(三者互斥:行程条目只有前两个,普通日程只有第三个)
· 新增 navTargetOf(place, lng, lat):有坐标返回 `lat,lng?地名`
(同名地点不会搜错城市),没有就只给地名让 FbNav 地理编码
- 首页 navigateEvent / 日程页 navigateDetail 改成接受 navTarget,
非空直接用,为空退回原来那套推导(底部那颗「导航」按钮传空串)
|
2026-11-05 16:21:16 +08:00 |
|
laoyang
|
48a0507455
|
v73:桌面卡片刷新修复 + 首页日程/任务就地弹详情卡 + 一键导航
用户 2026-10-21 三条:
「卡片里面的数据并不刷新……应用里面的日程已经有了,但卡片上的日程却并不刷新」
「首页上的那个日程和任务,点击之后都应该像日程和任务里面的卡片一样弹出来,
不要进入到日程里面……有地址的还可以直接一键导航」
「任务也是一样,点击任务之后弹出来详情,可以标记它是不是完成了」
① 卡片不刷新(根因)
卡片进程(FormExtensionAbility)与应用进程靠 preferences 传 formIds / 翻页偏移。
SDK 明文禁止跨进程用 preferences,且 getPreferences() 在**进程内**缓存实例、
同名再取不读盘 ⇒ 应用进程可能永久持有空注册表 ⇒ pushAll() 首行
`if (list.length === 0) return` 直接返回 ⇒ 卡片只靠系统 30 分钟自刷。
修:store() 每次先 removePreferencesFromCacheSync 再取;并写死单写者纪律
(register/unregister/setOffset/clearOffset 只由卡片进程调,应用进程只读)。
② 首页点日程 → 弹 FbEventSheet(canEdit: false,首页不给编辑入口)
有地址的行整行可点 + 右侧「➤ 导航」胶囊;「编辑日程」才跳日历模块
(编辑是日历页的职责,不在首页复制第二份表单)。
③ 首页点任务 → 新的 FbTaskDetailSheet
状态圆可点(勾完成)、标题带删除线、底部「标记为已完成/未完成」+「改一改」。
状态**必须走 POST /tasks/<id>/status**(PATCH 会忽略 status)。
④ 一键导航 FbNav.ets:startAbility 隐式 Want(不是 openLink,那是 App Linking);
canOpenLink 需 module.json5 声明 querySchemes(未声明恒 false 且不抛错);
高德/百度/花瓣/腾讯按序探测,一个地图都没装则复制地点到剪贴板 + Toast。
⑤ 首页登记 FB_BACK(与其余 10 个模块一致),根容器 Stack(浮层是兄弟节点,
不能当 Column 子项排,否则卡片被挤出屏幕)。
静态守卫 905/0、v73 反向验证 17/0、assembleHap 通过、已装机启动。
|
2026-10-21 20:01:37 +08:00 |
|
laoyang
|
4a063114c5
|
v62:修 P0 登录被踢 / 关闭按钮统一右上角 / 观影三处 / 影院管理补齐 / 名册三处
用户 2026-10-19 第二批八条(原话逐条对应):
═══ ⑨ P0:「现在还是不稳定,会退出,提示:这台设备已经被退出登录,请重新登录。」
真因**是我 v61 自己埋的**:「个人设置」页(`FbAccountPage`)里两处 `fbApi`
调用**取了 `token` 变量却没传进请求选项** ⇒ 没有 Authorization 头 ⇒ 服务端 401
⇒ `FbHttp` 的全局回调 `unauthorizedCb` **清掉本地令牌 + 踢回登录页**。
而本页在 `aboutToAppear` 里就调它 ⇒ **点一下右上角头像,App 就退出登录**。
⚠️ 我上一轮把同一现象归因成"残留旧令牌 / 设备会话被顶掉"(还去线上查了
`api_tokens` 表,一切正常)—— **那个结论是错的**,等于把 bug 归给了环境。
修法(两处调用 + **两道架构防线**,缺一不可):
① 修两处调用,把 token 传进去;
② `fbApi` 内部:**本地有令牌、调用方又没传时自动补上**
(大部分接口本来就要鉴权,补上是"纠正";`/login`、`/ping` 带了也无害);
③ **401 只在"确实带了令牌"时才算被踢** —— 否则"没带令牌"也会触发全局清令牌,
那正是这次事故的机制。
═══ ④「你这个按钮到底是在弹框的右上角关闭,还是在下面关闭……全放在右上角。」
选**右上角 ✕**(底部已被 编辑/保存/删除 占满,再塞关闭会堆三四个按钮,分不清主操作)。
新增 `components/FbSheetClose.ets`:
· `FbSheetClose` —— 32vp 圆形 ✕(热区 40+,小图标在手机上点不中);
· `FbSheetTitleBar` —— 左标题 + 右收尾(设置类给 `confirmText` 显示「完成」)。
9 个浮层全接;名册详情 / 日程详情 / 简要卡**底部不再有「关闭」**。
⚠️ 浅色底走 `fbAlpha`,**不能拼 `+ '14'`** —— ArkUI 八位色是 `#AARRGGBB`
(本项目曾因写 `#00000066` 导致遮罩**从来没显示过**)。
═══ ①「观影……弹出的框左上角有一条灰色的线,不知道是什么。」
那是浮层顶部的**抽屉把手**(36×4 的 `line2` 浅灰短线)。本意是"可下拉关掉"的提示,
但 ① 它落在左上角、旁边没有文字;② 这个浮层的关闭本来就不靠下拉。
⇒ 用户认不出它 = 它没起作用,**删掉**(不改成居中 —— 那只是把灰线挪个位置)。
═══ ②「然后这个观影人的头像并没有带进来。」
同看人的 `FbAvatar` **漏传 `imageUrl`** —— 服务端 `Movie::attendees()` 本来就
`SELECT p.avatar`、端上 `parseAttendees` 也解析进了 `a.avatar`,
纯粹是**渲染时忘了用它** ⇒ 有头像的人也退化成色块。
⚠️ 与名册详情 2026-10-15 那个是同一个 bug(当时是 `FbPersonSheet` 漏传)。
═══ ③「点击这个图片呢,不能左右滑动看所有的这个图片。」
全屏查看器原来**只有底部「上一张/下一张」文字按钮**。现在整张大图左右滑翻页。
⚠️ 用 `.gesture(PanGesture(Horizontal))` 而不是 `SwipeGesture`:
`SwipeGesture` 要"快速划动"才识别,在有滚动容器的页面容易被先吃掉
(日程页实测:`gesture`/`priorityGesture` 都不触发)。`PanGesture` 看**累计位移**。
⚠️ 判定要求 `|dx| >= 40 && |dx| > |dy|`,否则竖划会被误判成翻页。
═══ ⑤「影院管理……增加影院呢、修改影院呢、高级搜索、统计、年度报告,这些全部都应该补充进去。」
端上原来**只有一个只读列表**(连"新增"都没有)。补成四个页签:
· **影院**:新增 / 修改 / 删除(服务端 CRUD 早就有,端上一直没接)+ 删除二次确认;
· **统计**:总览(看过/影院/人数/人次)+ 按影院/按年/按月的条形图;
· **搜索**:片名 / 影院 / 起止日期(条件全空时不查,与网页 `hasCond` 同行为);
· **年报**:按年切换(第一场/最后一场、最常去的影院、一起看最多的人、每月分布)。
⚠️ **统计/年报必须联网**(`/movies/stats|report`):口径要与网页**完全一致**
(同一份 `MovieStats`)。本地库算出来的是"已同步的那部分",
少同步一次就少一部 ⇒ 用户会发现"网页 124 部、App 121 部"。
⇒ 断网时明说"需要联网",而不是给一个偏低的数字。
⚠️ 影院写操作后**立刻回写本地库**(`refreshCinemas`),否则刚建的那家要等下次同步
才出现,看着像失败;并用 `INSERT OR REPLACE` 而非"清空再插"
(中途失败会留下一个空表 = 用户的影院列表整个消失)。
═══ ⑥「名册搜索,搜索后,下面有一个白色的框,什么内容都没有,删除。」
那是列表**末尾给悬浮栏留高度的占位块**(`height(FB_DOCK_RESERVE)`),
底色是 `FbColors.surface`(**白**)而列表容器是 `paper`(**米**)——
列表内容一短(搜索只剩一两条)它就露出来,看着像"什么都没有的白框"。
⇒ 改底色与列表同色。**不能删**:删了最后一张卡片会被悬浮栏压住。
═══ ⑦「如果一个人没头像,在列表是有一个文字的头像的,那么点击后弹框,也应该有。」
`FbAvatar` 原来是 `if/else`:有 `imageUrl` 就**只画 Image**,
而图片**加载失败时 `Image` 什么都不显示**(只露出纯色底)⇒ 看着是个光板。
(`alt()` 只在**加载中**起作用,失败后是空白。)
⇒ 改成**叠加**:底色 + 文字头像**常驻**,图片有就叠在上面
(加载成功即盖住文字,失败则自动露出文字头像)。
⚠️ 之前注释说"图层叠会错位"——那是因为当时想靠 Image 的 intrinsic size 撑尺寸;
现在两层都显式给 `dia`,尺寸来源唯一,不存在错位。
═══ ⑧「现在名册的列表太空了,应该显示更多内容,例如工作单位、职务。」
列表卡片加一行「单位|职务」(独立成行,避免与标签/生日挤)。
⚠️ 用 `persons.org` / `persons.title` 而**不是** `person_jobs`:
列表读的是**本地库**,而本地库只存 `persons` 那一行
(`person_jobs` 是一对多,端上没同步那张表)⇒ 服务端加了字段也到不了列表。
线上实测 801 人里 192 人有单位、48 人有职务,列表立刻有内容。
验证:
· 编译 BUILD SUCCESSFUL
· ArkTS 守卫 536/0(新增整组 groupV62,含 P0 两道防线)
· 反向验证 51/0(新增 13 条注入,逐条确认能变红)
· Schema 列守卫 12/0
· **真机 22/0**(6 组,含照片横滑 `1/5 → 2/5`、四个页签、点头像不被踢)
|
2026-10-19 15:27:31 +08:00 |
|
laoyang
|
853b0e0b20
|
v61:顶栏标题=模块名 / 抽屉瘦身 + 头像进个人设置 / 删除按钮红底 / 浮层动画 / 日程卡片与手势
用户这一批九条,逐条对应:
1)「页面上左上角的标题,不再是家书了,而是切换到那个模块,就显示哪个模块的标题。
这样在页面内容部,就不再出现模块的名字标题了。」
→ TopBar 主标题改读 moduleName()(通知/设置/个人设置三个非模块路由也有名字);
观影/纪念日/读书/笔记/通知五处页内大标题删掉。
2)「按钮,也需要和主题色保持一致,出现文字的时候,例如观影模块,
在左上角出现的时候,颜色也需要和主题色保持一致。」
→ 标题色走 fbModuleColor(app.activeModule)(一处算,11 个页面不用各写)。
3)「弹框的外圈颜色,跟模块的主题色保持一致。」
→ 日程详情原来传 bookColor(日历本色)⇒ 改 accentColor();
7 个模块设置浮层补传 accent: this.accent。
4)「删除按钮全部用红色背景。」
→ 日程编辑/人员编辑从红描边改红底白字;详情「删除联系人」从浅红底改红底白字;
两处确认框统一 FbColors.red。
5)「做几个动画,例如,点击名册列表,应该有一个过渡动画出现弹框,
点击详情,框变大了,也应该有一个过渡动画,点编辑,也有动画。」
→ 新建 common/FbAnim.ets(fbMaskTransition / fbSheetTransition /
fbSheetGrowTransition / fbViewTransition),9 个页面共 17 遮罩 + 16 浮层挂上;
简要卡→详情用 0.96→1 的"继续长大"(0.94 会先缩一下)。
6)「左侧抽屉,把通知消息、个人设置、修改密码、系统设置,都去掉,
放在个人设置页,就是在点击右侧头像那里。消息通知不用放进去,
直接在头像旁边那里就可以了。」
→ 抽屉底部那四行整块删除(抽屉只剩品牌区 + 模块列表);
新建 pages/account/FbAccountPage.ets(整页,__account 分发),
点头像 switchModule('__account');改密码真打服务端新接口。
7)「日程……日期下面:12本日历可见,本月124条,这句话去掉。
点击日程弹出的框,编辑按钮也颜色也要修改。
全天日程,例如农历,上面显示无标题,读不到这条日程,这个有问题。」
→ 删统计行;编辑按钮从写死名册青 #4A7C82 改模块主题色;
真根因:衍生条目(农历/节气)的 detailFull **一直是 null**
(它们没有 /events/<id> 可拉,原来直接 return)⇒ 垫 shellOf(),
并把"整卡报错"改成"照常画内容 + 一行小字";
空标题兜底从「(无标题)」改成日历本名。
8)「再做几个卡片,先做日程的,这个参考 synccalendar。」
→ FbDayEventPanel.eventRow 照 SyncCalendar:左侧 4vp 圆头色条 + 标题 +
时间/全天 + 「↻ 重复」徽标 + 右端日历本名(限宽 30%、同色);
一行一张独立圆角卡(12)+ 描边,卡间 space 8,不再用 Divider 连成一片。
9)「日程,有很多手势,你参考 synccalendar。」
→ 月历上滑→周视图、周条下划→月视图、周条左右滑→换周。
真机实测两次踩空后定下写法:**竖向必须 parallelGesture(PanGesture)**
(外层是 Scroll,SwipeGesture 的"快速划动"会被它的内置滚动先吃掉,
gesture/priorityGesture 都不行);**横滑用 gesture(PanGesture)**
(同一节点两条方向不同的 parallelGesture 会互相压制);
方向按累计位移判、并要求 |dy| > |dx|。切视图走 animateTo + fbViewTransition。
验证:
· 编译 BUILD SUCCESSFUL
· ArkTS 守卫 493/0;Schema 列守卫 12/0;反向验证 39/0(新增 22 条注入逐条确认能变红)
· 服务端接口 e2e 20/0(独立副本 + 真 MariaDB,5 种错误路径 + 原令牌仍有效)
· 真机 _fb_v61_verify.py 21/0(6 组全过);像素采样确认浮层主题色环实测存在
|
2026-10-19 12:19:54 +08:00 |
|
laoyang
|
1a67247407
|
v60b:所有弹框统一主题色描边环 + 编辑改居中弹框 + 修名册下拉回弹吃掉悬浮栏
1)9 个浮层统一描边环(抽组件,不复制 8 遍)
新增 components/FbSheetRing.ets:环宽 FB_RING_W=2 全工程唯一一处;
实现是"外层 Column 铺色 + padding",不是 border(border 画在盒子内侧);
外圆角 = 内圆角 + 环宽。简要卡/详情/编辑/日程详情/日程编辑/观影详情/影院/
日程设置/模块设置全部改用;各浮层的环色 = 所属模块的主题色。
2)编辑从"贴底满宽 + 只有上圆角"改成居中弹框
人员编辑与日程编辑:Stack 对齐改 Center,卡片 92% 宽 + 四角圆 + 环;
constraintSize 留在卡片自己身上(挪到外层会让内层 Scroll().layoutWeight
拿到 0 高度,资料区塌成一条线)。日程的日期时间选择弹层、两个删除确认框
一并套环,避免同一次交互里出现两种形态。
3)修名册下拉到头回弹后悬浮按钮消失
EdgeEffect.Spring 在越界松手后把内容弹回,每帧 offset>0 被当成"用户在往上滑"
⇒ 收起悬浮栏。判据 = 手指已抬起 + 最后一次方向是下滑 + 抬手不到 500ms;
拦截必须排在 offset >= HIDE_AT 快路径之前(回弹第一帧位移常 >= 12vp)。
4)真机截图暴露的两个观感问题(静态检查全绿也照错)
- Scroll().layoutWeight(1) 让短内容也撑满 maxHeight ⇒ 卡片空半屏
(日程详情/模块设置),改为 flexShrink(1);内容本来就长的浮层不动。
- 人员编辑"虚拟人物(还没弄清真实身份)"被卡片裁掉半句:两个小开关从
并排 Row 改为 Flex(wrap) 换行,间距改走 margin。
验证:ArkTS 守卫 444/0;反向验证 17/17;真机 _fb_v60b_verify.py 11/0,
且关掉回弹拦截重编重装后该用例确实变红(证明测试不是假绿);
9 个浮层逐个真机截图确认。
|
2026-10-19 08:29:44 +08:00 |
|
laoyang
|
776c95ba0b
|
v0.7.0 接上真实服务器:登录 / 设备会话 / 全量同步与各模块真实数据
从「演示数据壳子」走到「真的能连家里的服务器用」。
登录(用户 2026-10-17「完整的登录功能」)
· 首次启动先填服务器地址 → /api/v1/ping 自报门户(认得出"这地址上真是家书")
· 手机号或用户名 + 密码 → 拿令牌;失败提示统一,不泄露账号是否存在
· FbDeviceStore:首次启动生成并持久化设备 UUID(三方应用拿不到 UDID),
设备名取机型(marketName),并上报 platform / app_version
设备会话(v57,用户 2026-10-17)
· 一把令牌 = 一台设备的一条会话;每次启动打一次 /me(有网就验)
· 两种锁分开:need_login(401/被踢 → 清令牌)与 offline_expired
(离线超 24h → 只锁界面、不清数据、联网自动恢复)——
混成一种就会违背用户要的"一直联网就不用每天输密码"
· 运行期任何请求 401 → 网络层全局回调立刻锁定跳登录页(FbHttp 的 authProbe
让登录/校验类请求跳过,避免"两个地方同时跳登录页")
· 退出登录:先清本地令牌(主防线),再尽力通知服务端
· 设置页显示版本号与「这台设备」
数据层
· FbDb / FbSchema / FbParse / 各 Repo(日程 / 名册 / 观影 / 模块)+ FbSyncAll
· 首页改为服务端 /home(农历/节气/纪念日/生日/天气/统计/往年的今天)
· 日程页用 FbDayEventPanel,与网页端显示方式/红线/并排三处一致
验证:ArkTS 静态守卫 231/0;hvigor 编译 BUILD SUCCESSFUL(entry-default-signed.hap)。
|
2026-10-18 03:36:04 +08:00 |
|