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 类根因后归零。)
This commit is contained in:
2026-10-11 22:07:48 +08:00
commit 41e3aa3d95
80 changed files with 6985 additions and 0 deletions
+126
View File
@@ -0,0 +1,126 @@
# FamilyBook_harmonyos · 家书鸿蒙客户端
**家书**([FamilyBook](https://code.yangyq.net/laoyang/FamilyBook))的 HarmonyOS 客户端。
服务端是那套「自托管的家庭生活系统」,这个仓库是它的手机 / 平板端。
> 把一个家的「人」「日子」「去过的地方、看过的电影」收进同一本书里。
---
## 当前状态
**界面框架阶段(v0.1.0)** —— 骨架与全部模块页面已就位,**数据全部是演示数据**。
服务端还没有客户端用的接口,所以这一轮只做「长什么样」,不做任何读写。
| 已完成 | 说明 |
| --- | --- |
| 工程骨架 | Stage 模型 + ArkTS / ArkUI,targetSdk 26.0.0 / compatibleSdk 6.1.1(24) |
| 左侧抽屉 | 宽屏常驻侧栏 / 窄屏滑出层,两套形态同一组件 |
| 13 个模块页面 | 首页、家谱、名册、观影、旅程、日程、资源、任务、纪念日、财务、读书、导航、笔记 |
| 附加页面 | 通知消息、个人设置 |
| 主题体系 | 宣纸米 / 砖红配色,深浅色两套资源,深浅自动跟随系统 |
| 模块主题色 | 与 Web 端 `Module::PRESET_COLORS` 同一套 12 色预设 |
| 编译验证 | `hvigorw assembleHap` **0 error / 0 warning** |
| 待办(下一轮) | 说明 |
| --- | --- |
| 接口对接 | 服务端需要提供客户端用的 JSON 接口(登录、各模块列表与详情) |
| 登录态 | 会话持久化、令牌刷新、启动时的登录门禁 |
| 交互实现 | 新建 / 编辑 / 删除、搜索、筛选、拖拽排序 |
| 日程周/天视图 | 按半小时定位的时间轴 + 手势(本轮只做了月视图) |
| 附件能力 | 上传、图片/视频预览、裁剪 |
| 财务折线图 | 净资产与各账目的盘点变化曲线 |
---
## 目录结构
```
entry/src/main/ets/
entryability/EntryAbility.ets 应用入口:主题跟随、系统栏配色
entrybackupability/ 备份扩展
common/
Theme.ets 设计令牌(颜色 / 间距 / 字号)+ 模块调色板
Store.ets 全局状态(V2:@ObservedV2 + @Trace)
model/
Modules.ets 模块注册中心(对应 Web 端 App\Module)
Types.ets 全部数据类型(对应各模板渲染的字段)
DemoData.ets 演示数据(接上接口后可整个删除)
components/
Widgets.ets 共享展示件(头像 / 标签 / 空态 / 圆点…)
Drawer.ets 左侧抽屉 + 骨架(并排 / 浮层两形态)
TopBar.ets 顶栏
pages/
Index.ets 主界面:模块分发
home/ movies/ trips/ calendar/ tasks/ people/
resources/ days/ ledger/ books/ misc/ settings/
```
---
## 设计说明
### 为什么是抽屉
Web 端顶栏是一排横向模块入口,最多放 12 个模块 —— 手机宽度下必然溢出。
改成左侧抽屉后,竖向排列不受数量限制,还能顺带放下「模块说明 + 主题色」
这层信息,一眼看清每个模块是干什么的。
抽屉有**两套形态**,由窗口短边决定(≥ 600vp 为宽屏):
- **宽屏**(平板 / 折叠屏展开 / 横屏手机):抽屉常驻,与内容并排;
- **窄屏**:内容铺满,抽屉从左侧滑出,点遮罩或选中模块即收起。
判据用「短边」而不是「宽度」—— 短边在旋转时不变,所以比例接近 1:1 的设备
横竖屏布局保持一致。
### 模块注册中心
模块清单只有**一个来源**:`model/Modules.ets` 的 `FB_MODULES`,
与 Web 端 `app/Module.php` 的 `Module::LIST` 一一对应(key 必须等于路由名)。
加一个模块只改那一处 —— 抽屉、设置页的显隐开关、主题色选择全部自动出现。
这是 Web 端踩过的坑(漏改一处就「有页面但导航里找不到入口」),端上照搬这套结构。
### 主题色
每个模块一个主题色,三档(按钮底 / hover / 文字色)由主色按 HSL 压明度算出来,
保证三档永远同色系。算法与 Web 端 `Module::cssVars()` 共用同一套公式。
预设色板 `FB_PRESET_COLORS` 也与 Web 端 `Module::PRESET_COLORS` **逐值一致** ——
否则同一个人在手机和电脑上选出的「观影紫」会是两种紫。
### 编译期约束(踩过的坑)
| 坑 | 处理 |
| --- | --- |
| `Circle().fill()` 是 API 26 才有的重载 | compatibleSdk 是 24,改用「方块 + 圆角」画圆(`components/Widgets.ets::FbDot`),零版本风险 |
| `setWindowBackgroundColor` 对 phone/tablet 不可用 | 去掉,页面自身已用同色铺满整屏 |
| `window.getLastWindow()` 只有异步版 | 由 `EntryAbility` 用 `getMainWindowSync()` 取一次存进 AppStorage,页面侧同步读 |
| 跨文件顶层名冲突(`arkts-no-decl-merging`) | 所有导出名统一加 `Fb` 前缀 |
| `Button('label') { ... }` 报 10905202 | 一律用 `Button() { Row() { ... } }` |
| `@Param` 类型写成 `string` 导致传 `Resource` 报错 | 颜色类入参统一声明 `ResourceColor` |
| 嵌套目录下 import 相对路径层级 | 页面在 `pages/<模块>/`,公共件在 `components/`、`model/`,相对路径要多退一级 |
---
## 构建
需要 HarmonyOS SDK(DevEco Studio 自带)。本机开发时:
```bash
export NODE_HOME="<DevEco>/tools/node"
export DEVECO_SDK_HOME="<DevEco>/sdk"
<DevEco>/tools/ohpm/bin/ohpm install --all
<DevEco>/tools/hvigor/bin/hvigorw assembleHap --mode module -p product=default
```
产物在 `entry/build/default/outputs/default/entry-default-unsigned.hap`。
`local.properties` 里写本机 SDK 路径,**不入库**(见 `.gitignore`)。
---
## 开源协议
[Apache License 2.0](LICENSE)