Commit Graph
8 Commits
Author SHA1 Message Date
laoyang 7858de27e3 v0.8.4 简要卡观感 / 分享 / 名册搜索 / 全局返回手势(v59e)
八条需求的落地与真因:

1. 浮层与白底"糊在一起"、看不清 —— 根因不是配色,是**遮罩从来没画出来过**:
   ArkUI 的八位色值是 #AARRGGBB(alpha 在前),而全应用写的是 '#00000066'
   (本意"黑 40%")⇒ alpha = 0x00 ⇒ 全透明。同型还有 brand + '1A'(拼到了蓝通道)
   与 shadow('#00000033')。⇒ 17 个文件统一改走 fbAlpha() / FB_MASK / FB_SHADOW /
   FB_HAIRLINE;真机像素采样复验:遮罩 (148,146,140)、卡片白、浅底 (237,242,243)。
2. 简要卡外圈加**主题色描边环**(外层铺色 + padding,不是 border —— border 会被
   内层圆角切出白缝)。
3. 简要卡**去掉删除按钮**,删除挪到完整详情卡最下面(Divider + 红字块)。
   顺手修一处静默失败:confirmDelete() 原来只取 quickSource(),
   从家谱直接开详情时 quickPerson 为 null ⇒ 点删除毫无反应。
4. 信息行间距 10 → 16(每行再各加 3vp 上下内边距,实测行距 134/118px)。
5. 主电话整行可点**直接拨号**(call.makeCall,落到系统拨号盘)。
6. 按钮改为 详情 / 编辑 / 分享 / 关闭;分享走系统分享面板,
   内容为纯文本「姓名 / 电话 / 邮箱」三项(用户点名的就是这三项,
   不多带单位),面板拉不起来时兜底复制到剪贴板并提示。
7. 名册搜索"完全不能用"有两个独立真因:
   ① 搜索框是 List 的第一个 item,无结果时整个 List 被空态替换 ⇒ 输入框被卸载、
      焦点丢失 ⇒ 输不进第二个字。改:List 无条件渲染,空态自身做成 ListItem。
   ② rowToPerson 把 initials 写死成空串,服务端下发的拼音首字母从未落库 ⇒
      拼音搜索恒 0 结果。改:FB_DB_VERSION 6→7 + PRAGMA 探测补列 + 同步时落库;
      匹配同时遍历全部电话(原来只比主号)。
   另加搜索框「清空」(24×24 命中区)。
8. 全局返回手势:应用是单页 + 模块分发、没有路由栈 ⇒ 自建 FB_BACK 登记表
   (倒序询问)+ moduleHistory + applyModule()(不记历史,否则 A/B 两页来回弹)。
   9 个页面登记/注销;Index.onBackPress 先关浮层 → 回上一模块 → 才 return false
   交给系统退桌面(onBackPress 必须声明 boolean,返回 void 会被当成没接管)。

验证:
- 静态守卫 417 / 0(新增 ⑤阴影·描边·色环 ⑥透明度色 ⑦返回手势 ⑧搜索 ⑨分享)
- 反向验证 10 / 0(9 条注入全部能让守卫变红;其中"遮罩换纯黑"那条暴露了
  一条存在型假绿,已改成数个数 + 禁止 Color.Black)
- 建表/迁移列一致性守卫 12 / 0
- 真机全模块遍历 14 / 14;真机逐项复核 12 / 0 与 7 / 0

工具侧顺带修好两个过期的探针:
- 遍历探针仍用"应用内横滑"打开抽屉,而该手势早已按用户要求去掉、入口改为顶栏图标
  ⇒ 一次全量遍历里 12 个模块全报"抽屉里没找到"(像应用坏了,其实是探针过期)。
- 资源/笔记两页写死了早已不存在的条目(户口本/房产证/阳台改造清单)⇒ 改成
  结构性文案(副标题 + 常驻筛选胶囊),不随用户数据变化而恒红。
2026-10-18 23:12:57 +08:00
laoyang 2b0401052c v0.8.2 头像点进我的详情 / 未读数接真实数据 / 名册圆角卡(容器要换成页面底色)
用户 2026-10-18 夜三条:

①「右上角,显示的应该是登录者的头像,点击头像进入我的详情页面。」
   头像**本来就是登录者本人的**(v59 已接 session.me.avatarUrl);
   真正缺的是**点击** —— TopBar 里那个 FbAvatar **根本没有 onClick**,
   只有一句写着"点开账号菜单"的注释,而"账号菜单"这个东西在代码里并不存在。
   ⇒ 接 openMyDetail() → bindSheet 弹 FbPersonSheet(复用名册那个人详情组件)。
   🔴 数据必须走 repo.byId(meId)(本次为它新增 byId),不能从名册列表那批里找:
      **"我"常常不在自己的名册里**(名册是"我挑出来的那一小撮"),
      从列表里查会**静默落空**、点了没反应 —— 最难查的那种失败。
   ⚠️ 三种状态都说清楚:加载中 / 拿到了 / 拿不到,绝不留空白浮层。

②「提醒按钮,明明没提醒,怎么还显示个 2?」
   🔴 真根因:`@Trace unread: number = 2;` 是**写死的占位初值**,
      而全工程只有一处给它赋值(通知页「全部已读」清 0)。
      没进过通知页的人**永远看到 2**;进了通知页又"永远 0"(把真实未读也盖掉)
      —— 两个方向都错。
   ⇒ ① 初值改 0(拿到真值前必须是"没有未读",不能凭空多出 2);
     ② 首页把 /home 的真实 unread 写进全局状态。
        (服务端 Notification::unreadCount,与通知页同源;/home 本来就返回它、
          FbParse 也早就解析了 —— 只是**没人往全局状态里写**。)

③「名册页面,不好看,太丑了,应该是每个人都是圆角矩形,往中间收一点,
   距离左右都有点距离,每个人中间都有一点空隙。」
   🔴🔴 真凶**不是卡片形状**(v51 就做了 borderRadius + margin)——
      而是**列表容器也是纯白** ⇒ 白卡压白底 ⇒ 圆角与左右收边**全看不见**,
      看上去就是一整块通栏白。这解释了"改过一轮还是丑":上次改的是卡片,
      问题在"背景没有对比"。
   ⇒ 容器 + 外层兜底改 FbColors.paper(页面底色),卡片保持白;
     圆角 radiusS(10) → 新增 radiusCard(14)(列表项专用档:16 显胖、10 显方);
     左右各 pagePad(16)、卡间 10(原 8 偏挤)、行内边距 11→12。

验证:hvigor BUILD SUCCESSFUL;_fb_arkts_guard.js 347/0(本批新增 18 条,
另**收紧 2 条**旧判据 —— M 组"圆角卡"那条原来锚"逐字相邻两行"、且**测错了对象**:
没查容器背景,所以对"白卡压白底"这个真实缺陷毫无把关能力);
_fb_v59b_falsify.py 8 项注入 ⇒ 8/0。

⚠️ 本轮反向验证头一轮漏了 3 条(都是"判据太宽"),已逐条收紧并记入 pitfalls:
  · 删掉头像 onClick 后仍绿 —— openMyDetail 这个标识符在**方法定义**里也出现;
  · 容器改回白底后仍绿 —— 本页有**两处** FbColors.paper(容器 / 兜底);
  · /home unread 改成写死 2 后仍绿 —— Notification::unreadCount 在 PHP 里也有两处。
2026-10-18 20:58:40 +08:00
laoyang f020a671c0 v0.8.1 界面六条:删离线入口 / 标语统一 / 最近纪念日 / 图标真上色 / 真头像 / 日程四修
用户 2026-10-18 六条(全部已在真机逐条验证):

① 登录页「先不登录 / 离线使用」彻底删除
   用户:「把那些不登录、看离线数据之类的提示全部去掉。以后就不再拥有这样的
   功能了,把这些功能也全部删除。」
   ⇒ 两个按钮 + onSkip + allowSkip 参数 + Index 里的 skip 分支一起删净。
   这是产品决定(不是隐藏):该路径本身就是安全缺口,v58 上了整库加密后更要堵死。

② 标语统一为「一家人用岁月写成的一本书」
   用户:「这也是我们"家书"这个名字的由来。所以你不要再乱换这个标语了,
   只要是想出现标语或者副标题的地方,就用这样一句话。」
   · 端上 FB_DEFAULT_SLOGAN 是唯一定义处(登录页副标题 + 抽屉回落都用它);
   · 抽屉左上角原来是家庭名,现在显示**标语**;
   · 三层优先级(个人 slogan → 家庭 motto → 应用默认口号)**在服务端算**
     (Family::slogan,与网页端首页 heroSlogan 同一套),/login 与 /me 都返回。
   用户还说:「如果这个用户自己有标语……这个地方就是用户自己自定义的标语。」
   真机实测:登录者杨永全自己写了「修身,齐家」⇒ 抽屉就显示他那句。

③ 首页新增「最近纪念日」(放在近期任务之后、往年的今天之前)
   用户:「未来最近的三个纪念日,包括每个人的生日,以及手动填写的各个纪念日。
   以倒计时形式展示:距离哪个纪念日还有多少天,距离谁谁谁的生日还有多少天。」
   · /home.recent_days = Anniversary::upcoming(fam,pid,370) 取前 3 ——
     取满一年:窗口太小会让"刚过完生日"的家庭一个都取不到,模块直接空着;
   · 数据源 all() = 派生生日 + 自建纪念日,正好覆盖用户说的两样;
   · 倒计时:0 天显示「就是今天」(写「还有 0 天」读起来像已经过了)。

④ 悬浮栏图标也上色(用户:「除了下面的汉字,上面图标的颜色也变成跟汉字一样的颜色」)
   🔴🔴 真根因两层,都是"无报错失效":
   · 第一层:Image.fillColor() **只对 SVG 生效**,而本工程 30+ 图标**全是 PNG**
     ⇒ 全工程 24 处图标染色一直是空操作(文字走 fontColor 所以只有文字变了)。
   · 第二层(真机才现形):改用 colorFilter 后,矩阵写成了"系数乘 RGB"
     (R' = R_原 × 系数) —— 对白色图标成立,但本工程图标是**纯黑**,
     黑 × 任何系数 = 仍是黑 ⇒ 真机上图标像素依旧是 (0,0,0)。
   ⇒ 最终形态:`fbTint` 用 **alpha 当载体**(R' = (r/255) × A_原):
     系数是归一化约定(官方灰度示例系数和为 1,量纲确定);
     形状完全由原图 alpha 决定 ⇒ 黑/白图标都成立,描边抗锯齿自然过渡。
   真机像素实测:日程项图标与文字同为 (176,120,64)≈#B0763A;
   未选中项图标 (44,39,35) 深灰(不再是纯黑)。
   ⚠️ 全工程 24 处 fillColor 一并改掉;FbIconButton.tint 类型改成 string,
      让"误传 Resource"变成编译错误而不是又一个静默失效。

⑤ 顶栏:真实头像 + 拉开按钮间距
   用户:「右上角的头像应该是真实的……现在提醒的按钮距离头像的按钮太近了。」
   · /home 给 me_avatar、/login 给 avatar_url(avatar_url() 按线上存储驱动拼好);
   · 三颗按钮(同步 / 铃铛 / 头像)统一用 FbMetric.gapTopActions = 8。

⑥ 日程四处
   · 「日期下面有几个点」⇒ 月视图与周视图的圆点全部删除,
     连 FbDot / dots() / count / dotColor 一起清(不留死代码);
   · 「农历全部都是初一」⇒ 真根因是端上 lunarOf() **硬编码 return '初一'**,
     而服务端 lunarRange() 本来就每天给真实农历(title)⇒ 改取 title;
   · 「列表这个视图,今天的数据缺一条」⇒ 服务端 /calendar 的 from/to **默认只给本月**,
     而列表视图要显示 -7 ~ +60 天 ⇒ 端上显式传范围
     (loadModule 新增 pathOverride 参数);
   · 「点击了某一天之后并不明显,应该把这一天的颜色变深,而今天用一个较浅的颜色」
     ⇒ 照 SyncCalendar:选中 = 深色实底白字、今天 = 浅色底。
       真机实测:17 号(选中)bg=#FFB0763A,18 号(今天)bg=#FFF5F0EA。

另:FbKeyStore 补上一个真机抓到的 HUKS 坑 —— isKeyItemExist 在密钥不存在时
**会抛 12000011**(不是返回 false),首次运行必被误判成"本机不支持 HUKS"
⇒ 永久明文降级。改成把"不存在"当正常分支,且降级态每次启动重试一次
(把同一把 DEK 重新用 KEK 包起来,不换密钥以免重下全部附件)。

验证:hvigor BUILD SUCCESSFUL;_fb_arkts_guard.js 328/0;
_fb_v59ui_falsify.py 19 项注入 23/0;_fb_home_api.py 60/0;
六条已在真机逐条取像素/布局树确认。
2026-10-18 20:14:40 +08:00
laoyang 2132ee42d2 v0.8.0 本地加密 / 被踢清数据 / 增量同步 / 附件队列 / 顶栏同步进度
用户 2026-10-18 两条:
「直接做 L3 锁界面 + 本地加密(HUKS,踢设备即吊销密钥):数据在但读不出,
  重登后恢复密钥即可用。」
「右上角头像和提醒前面加同步进度…首次全量、之后增量;进来先展示本地数据,
  一边同步一边更新;附件后台队列同步(名册头像 / 电影海报 / 观影照片 / 资源附件)。」

① 整库加密(FbSchema v4→v5,新增 module_sync / attach_cache 两张表)
   RDB encrypt=true。加密属性一经创建不可修改 ⇒ openWithEncryption 三段式:
   直接开 → 失败删库重建 → 再失败降级明文(degraded 字段,设置页如实显示,
   不静默降级)。

② 两层密钥(FbKeyStore)
   HUKS 里 KEK(fb_kek_v1,不可导出)包裹 32 字节 DEK;revoke() 删 KEK
   ⇒ 已落盘附件密文在数学上解不开,这就是"踢设备即吊销密钥"。
   重新登录重新生成 DEK 并重下附件(不做服务端托管,为了省一次重下
   把能解你本地数据的密钥放到服务端不值)。
   会话属性里 PURPOSE 只出现一次:原来把含 ENCRYPT|DECRYPT 的生成属性直接
   拿去开会话再 push 一个 PURPOSE,同一 tag 出现两次在 HUKS 里行为未定义
   ⇒ 拆成 kekBaseProps / kekGenProps / kekSessionProps。

③ AES-256-GCM(FbCrypto)
   落盘 iv(12)|ct|tag(16);变换串必须带 padding 段(AES256|GCM|PKCS7,
   缺了抛 801);解密从尾部切 tag。

④ 附件后台队列(FbAttachQueue)
   attach_cache 台账(pending/done/fail,MAX_TRIES=3);密文放 filesDir、
   明文临时放 cacheDir;扩展名白名单筛 key。
   图片地址收成统一入口 fbImageSrc(key,token):本地有就用 file://,
   没有才回网络 —— 收成一个函数才漏不掉(5 个页面全部改过来)。

⑤ 被踢 / 退出清数据
   lockOut → 清令牌 → FB_ATTACH.wipe(第一步就是吊销 KEK)→ FbDb.wipe
   (先关句柄再 deleteRdbStore,并发去重,open 会等它)→ 同步状态复位。
   重新登录后重建密钥 + 库 + 附件索引,否则之后只读网络不写缓存且不报错。

⑥ 增量同步(FbSyncAll 重写)
   先问 /api/v1/changes;指纹相同就跳过。本地没水位必须拉(否则老用户升级后
   一个模块都不同步);24h 陈旧上限兜"改无 updated_at 表的已有行";
   /changes 拿不到时判 ping status>0 —— 断网直接收工,不退回全量
   (否则 12 个模块各等 15 秒)。
   家谱也进了预同步列表(原来只在打开时拉,离线是一片空白);
   总步数由 CACHE_MODULES.length 算出,不写死。

⑦ 删除传播
   服务端是物理删除、没有墓碑 ⇒ 观影同步改成"先清后插"
   (persons 跨模块共用,不清)。

⑧ 顶栏同步进度
   头像与铃铛之间加三态按钮(转圈 / 红感叹号 / 灰对勾)+ bindSheet 面板:
   进度条、「N 个模块没有变化」、附件行、失败清单、立即同步(防连点)。
   状态中心 FbSyncState(@ObservedV2 + @Trace,AppStorageV2 单例);
   界面直接读 @Trace 字段,不提供派生 getter。

验证:hvigor BUILD SUCCESSFUL;_fb_arkts_guard.js 290/0(本批新增 59 条);
_fb_v58_falsify.py 31 项注入 38/0;b57 反向验证 12/0(锚点跟上本批 logout 改动);
本地 e2e 1519/0;全量流水线 PUSH_RC=0。
2026-10-18 16:01:41 +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
laoyang 705a65ae2e v0.5.0 抽屉改「应用内左右滑动」触发 + 去掉汉堡按钮 + 统一区块边距
用户 2026-10-12 三条反馈。

## ① 抽屉改「应用内水平滑动」触发(关键更正)

用户实测指出:「左滑右滑不是从边上滑,而是在应用的内部从左往右滑或者从右往左滑。
如果从边上往里边滑的话,它是系统手势,我们是没有办法去控制它的。」

⇒ **这是之前手势完全没生效的根因**:屏幕边缘是系统手势区(返回/侧边栏),
  从边缘往里滑的事件根本轮不到应用。判据改为「在应用内部水平滑动」:
  · 向右滑 ⇒ 抽屉从左边出;· 向左滑 ⇒ 抽屉从右边出。
  (左手持机往右划、右手持机往左划,单手都顺。)

🔴 同时修掉一个真 bug:**`offsetX` 的单位是 vp**(SDK 原文 "in vp"),
   我之前又除以 density,把位移缩到 1/3 ⇒ 阈值永远达不到。
⚠️ 用 `parallelGesture`(不是 gesture):内容区还有竖向滚动与
   纪念日/财务/任务的横向滚动条,用 gesture 会把它们抢掉。
   阈值 80vp,轻扫横向列表不会误开。

## ② 去掉顶栏汉堡按钮
用户:「那个三个点、三个横线的按钮就不要了,图标靠左,显得更好看一些」。
⇒ TopBar 删掉按钮,`padding.left` 由 14 改为 `pagePad`,图标与下方内容左边线对齐。

## ③ 🔴 统一区块边距(修掉 15 处真 bug)
用户:「页面里的方框大小不一样,有的左右充满,有的有缝隙 —— 最好都留一点距离」。

实测界面树 + 像素采样找到根因:**卡片同时写了 `.width('100%')` 和
`.margin({left, right})` ⇒ width 先把宽度占满、margin 失效,卡片顶到屏幕两侧**。
(首页个人信息卡实测 x=0..1080 满宽,而别的区块是留边 17vp 的。)

全项目扫出 **15 处**同款写法(calendar 3 / days 2 / ledger 2 / movies 1 /
people 2 / settings 5),**全是卡片**(backgroundColor+borderRadius+margin)。
统一删掉那条 `.width('100%')`,宽度交给 margin 撑出。

### 验证(真机)
· 手势:向右滑 ⇒ 抽屉「家书」x=187(贴左);向左滑 ⇒ x=442(贴右)—— 双向 ✓
· 边距:像素级逐行采样,17 行里 15 行左右均 50px(17vp)完全一致;
  另 2 行是"标题文字起点"(文字有额外缩进),不是边距问题 ✓
· 14 页遍历 **14/14**;深验(每页特征文本)**12/12**
· 编译 **0 error / 0 warning**

### 工具链修复(都很关键)
· 🔴 `hdc file recv` 在 **Git Bash** 下会被路径转换改写:`/data/local/tmp/x`
  被当成 `C:/.../tmp/x` ⇒ **静默失败、界面树永远抓不到**。
  三个验证脚本已统一注入 `MSYS_NO_PATHCONV=1`。
· 探针不再点汉堡按钮开抽屉(按钮已删),改用「应用内向右滑」。
· 修探针一处误判:顶栏与抽屉**都有**「家书」,原来没区分 ⇒
  两种滑动都读到顶栏那个固定 x,误报"手势没生效"(其实生效了)。
2026-10-12 11:37:45 +08:00
laoyang d6bda758d8 v0.3.0 沉浸式按 SyncCalendar 重做(通知栏与页面完全同色)+ 个人信息卡改白块
## ① 沉浸式:改用本机 SyncCalendar 的方案(用户指定参考)

用户原话:「上面那一块的颜色和通知栏的颜色完全融为一体;
紧接着就是应用图标和标题,尽量靠上」。

三件套(缺一不可):
1. 系统栏涂**全透明** `#00000000`;
2. `setWindowBackgroundColor(页面底色)` 供透明系统栏透出;
3. **紧邻系统栏的元素不设自己的背景色** + 根容器 `expandSafeArea`。

🔴 第三件是最关键、也是我先前漏掉的一环:
我原来给顶栏设了白色 `backgroundColor`,于是状态栏(透出纸色)与顶栏(白)
仍上下拼接。读 SyncCalendar 源码发现它的 `header()` **根本没有 backgroundColor**
—— 这才是"融为一体"的真正机制。已在代码里写明原因,防止回退。

配套简化:删掉自己算安全区的那套(`statusBarH`/`bottomBarH`/
`loadWindowInsets`/`applyAvoidAreas`,共约 110 行)—— 不再手算,也就不会算错。

## ② 顶栏改「图标 + 标题」

按用户要求:应用图标 + 「家书」标题(下行小字显示当前模块)贴左上,
右侧铃铛与头像。顶栏高度 56 → 48vp,上下内边距压到 4,内容整体上移。

## ③ 个人信息卡恢复为白色卡片

用户明确要求("还是得用一个白色的块,这样显得好看")。
曾一度做成"不套卡片的头部"(理由是省首屏高度),现按用户观感改回白卡。
⚠️ 与顶栏的区别:顶栏**不能**有背景色(否则与状态栏割裂),
而这张卡在顶栏下方、与状态栏不相邻,套白卡没有这个问题。

## 验证(全部基于真机)

逐行像素采样(`_tooling/familybook_immersion_check.py`,
模型读不了图 ⇒ 用数字裁定,不靠目测):
· `y=0..271` 全为 `#F7F3EA` ⇒ **状态栏与顶栏同色,融为一体** ✓
· 底部 `y=2224..2444` 为纸色,无异常条 ✓

真机界面遍历(`_tooling/familybook_harmonyos_probe.py`):
· A 组抽屉 11 个模块 **11/11**
· B 组家谱 **1/1**;C 组通知/设置 **2/2**
· D 组深验(特征文本)**12/12**
合计 **14 个页面全通过**。

⚠️ 顺带修掉探针自身两个坑(都记进注释了):
· `nodes_of` 原来只收集**有文字**的节点 ⇒ 找不到纯图标的汉堡按钮,
  导致"抽屉打不开"、10 个模块连锁失败(看着像应用坏了,其实是探针瞎了);
· 汉堡按钮坐标写死 ⇒ 顶栏变矮后点空。改为在界面树里动态探测、
  并**排除系统状态栏区域**(那里也有可点击元素,曾误取到 (103,56))。

## 编译
0 error(保留 1 条 `setWindowBackgroundColor` 的 unavailable 告警,它是透明方案的必需组成)
2026-10-12 08:43:32 +08:00
laoyang 41e3aa3d95 v0.1.0 界面框架:抽屉骨架 + 13 个模块页面
对应服务端 FamilyBook(家书)的鸿蒙客户端首版。本轮只做**界面框架**,
数据全部是演示数据 —— 服务端尚无客户端接口,所有增删改只做入口与样式,
不落任何数据。

## 骨架
左侧抽屉 + 右侧内容。抽屉两套形态由窗口短边决定(≥600vp 为宽屏):
宽屏常驻侧栏、窄屏滑出层。判据取「短边」而非「宽度」,因为短边在旋转时
不变,比例接近 1:1 的设备横竖屏布局天然一致。

## 模块(与 Web 端 Module::LIST 一一对应,key 即路由名)
首页、家谱、名册、观影、旅程、日程、资源、任务、纪念日、财务、读书、
导航、笔记;另有通知消息、个人设置两个附加页。

## 与 Web 端保持一致的几处
· 模块清单唯一来源在 model/Modules.ets,加模块只改那一处;
· 模块主题色三档由主色按 HSL 压明度算出,预设色板与 Web 端逐值一致;
· 术语沿用 Web 端固定下来的口径(旅程 ⊃ 行程;观影的「影院」不单独占
  抽屉位,从模块内设置进);
· 页面结构照 Web 端的信息层次(首页信息面板 / 财务概览在账目之前 /
  纪念日「即将到来」在顶 / 任务按状态而非按看板)。

## 编译验证
hvigorw assembleHap --mode module -p product=default
→ BUILD SUCCESSFUL,0 error / 0 warning(含一次删 build 后的干净重建)

过程中修掉的编译期问题:
· Circle().fill() 是 API 26 才有的重载(compatibleSdk 是 24)
  → 换「方块 + 圆角」画圆,零版本风险;
· setWindowBackgroundColor 对 phone/tablet 不可用 → 去掉(页面已铺满同色);
· window.getLastWindow() 只有异步版 → 由 Ability 侧同步取窗存 AppStorage;
· 颜色类 @Param 声明成 string 导致传 Resource 报错 → 统一改 ResourceColor;
· 页面在 pages/<模块>/ 下,公共件 import 相对路径要多退一级。

(首轮编译 95 error / 18 warn,逐条定位到 5 类根因后归零。)
2026-10-11 22:07:48 +08:00