v74 端上删掉家谱 + 名册页头改「醒目搜索 + 添加」
用户 2026-10-21:「算了,你画不好。这个功能直接从鸿蒙端去掉吧,不要了。 这样名册这个功能,进来以后,上面就是搜索和添加按钮,搜索,做的醒目一点, 现在看不清。家谱和名册的标签,都不要了。家谱的相关功能,都删除。」 家谱链路整条删除(不是隐藏): - 删 common/KinLayout.ets、components/FbKinGraph.ets 两个源文件 - 删 Types 的 FbKinPerson / FbKinGraph / FbKinRelation、FbParse 的 parseKin - 删 FbModuleLoad 路由、FbModuleRepo 模块名、FbSyncAll 预同步清单里的 kin - 删 DemoData 的 FB_DEMO_KIN_RELATIONS、Theme/Settings 的家谱图标映射 - 删死资源 fb_ic_kin.png - Index 的 kin 分支去掉(不再有「名册/家谱」两个模块共用一个页面) - FbPeoplePage:删 subView 分段切换、kinHeader/kinView、loadKin、segBtn; openDetail 不再借家谱字段兜底,改成纯 id 占位 + 异步补全 (保留"本地没缓存也要立刻开浮层",那是 v73 修过的"点了没反应") 名册页头: - 第一行就是搜索 + 添加,上面不再有任何东西 - 搜索框从「看不清」改成醒目:白底 #FFFFFF(原来 inputBg 与页面米色几乎同色 ⇒ 没有边界)、1.5 主题色描边、高度 36→44、图标 15→18 并染主题色、 字号 fontSmall→fontBody、提示词收短成「搜索姓名 / 首字母 / 手机」 验证: - ArkTS 静态守卫 917/0(新增 6 条:家谱五条链路全清 + 搜索框三个具体数值) - 反向验证 154/0(新增 7 条注入全部有效;另修好两条因代码演进失效的旧锚点) - 编译 BUILD SUCCESSFUL + 装机 install bundle successfully - 真机 v74 探针 22/0(高度实测 44.2vp、白底、占屏 66%、同排对齐、 家谱在页面与抽屉里都不存在、搜索输入与清空真的生效) 顺带修掉探针三处假红(都不是应用问题,是量错了节点): - 搜索框在界面树里是两层,TextInput(75px) 只是内部输入区, 白底容器 Row(138px) 才是盒子;只按"有文字/可点"收集会把它漏掉 - uitest uiInput inputText 是 (x,y,text) 三参数,只给文本会静默不输入 - 空态文案是「换个关键词试试…」,按"没有/找到"判永远为假
This commit is contained in:
@@ -647,7 +647,7 @@ struct Index {
|
||||
moduleContent() {
|
||||
if (this.app.activeModule === 'home') {
|
||||
FbHomePage({ app: this.app, topBar: this.topBarSlot })
|
||||
} else if (this.app.activeModule === 'people' || this.app.activeModule === 'kin') {
|
||||
} else if (this.app.activeModule === 'people') {
|
||||
FbPeoplePage({ app: this.app, topBar: this.topBarSlot })
|
||||
} else if (this.app.activeModule === 'movies') {
|
||||
FbMoviesPage({ app: this.app, topBar: this.topBarSlot })
|
||||
|
||||
@@ -1,28 +1,25 @@
|
||||
/**
|
||||
* 家书 FamilyBook · 名册 / 家谱(鸿蒙端)
|
||||
* 家书 FamilyBook · 名册(鸿蒙端)
|
||||
*
|
||||
* 对应 Web 端 `templates/people/index.php`(名册)与 `templates/kin/tree.php`(家谱)。
|
||||
* 对应 Web 端 `templates/people/index.php`。
|
||||
*
|
||||
* 这两页在 Web 端是两个模块,但**看的是同一批人**:名册是「平铺的名单」(通讯录视角),
|
||||
* 家谱是「以我为中心的连线」(关系视角)。端上放在同一个文件里,用内部分段切换 ——
|
||||
* 手机上在两页之间来回跳没有意义,切一下就能对照看。
|
||||
*
|
||||
* ⚠️ 家谱的树形图(Web 端是 HTML 折线)在手机窄屏上排不下。
|
||||
* 端上改成**「以我为中心的三圈」**:我 → 直系(父母/配偶/子女)→ 其他亲属,
|
||||
* 每圈一张卡,卡里按人列。关系表达上等价,宽度可控。
|
||||
* 🔴 v74(用户 2026-10-21):「这个功能直接从鸿蒙端去掉吧,不要了。
|
||||
* 这样名册这个功能,进来以后,上面就是搜索和添加按钮……
|
||||
* 家谱和名册的标签,都不要了。家谱的相关功能,都删除。」
|
||||
* ⇒ **家谱在端上彻底删除**(页面内分段切换、图谱视图、`/api/v1/kin` 取数、
|
||||
* 同步清单里的 `kin` 项全都没了)。现在这一页只有名册。
|
||||
* ⚠️ Web 端的家谱页**不受影响**(用户说的是"鸿蒙端")——
|
||||
* 服务端 `templates/kin/`、`Kinship` 那套仍然照常工作。
|
||||
*/
|
||||
|
||||
import { FbColors, FbMetric, fbTint, FbTint, FB_MASK } from '../../common/Theme';
|
||||
import { FbAppState, fbAppState } from '../../common/Store';
|
||||
import { FbKinGraph, FbKinPerson, FbRosterItem } from '../../model/Types';
|
||||
import { FbRosterItem } from '../../model/Types';
|
||||
import { FbModuleDef, fbModuleOf, fbThemeVars } from '../../model/Modules';
|
||||
import { parseKin } from '../../data/FbParse';
|
||||
import { loadModule } from '../../data/FbModuleLoad';
|
||||
import { FbAvatar, FbPrimaryButton, FbTag } from '../../components/Widgets';
|
||||
import { FbPersonSheet } from '../../components/FbPersonSheet';
|
||||
import { FbPersonQuickSheet } from '../../components/FbPersonQuickSheet';
|
||||
import { FbPersonEditSheet } from '../../components/FbPersonEditSheet';
|
||||
import { FbKinGraphView } from '../../components/FbKinGraph';
|
||||
import { FbTagChip } from '../../components/FbTagChip';
|
||||
import { FB_DOCK_RESERVE } from '../../components/FloatDock';
|
||||
import { FbDb } from '../../data/FbDb';
|
||||
@@ -183,8 +180,6 @@ export struct FbPeoplePage {
|
||||
@BuilderParam topBar: () => void;
|
||||
@Param app: FbAppState = fbAppState();
|
||||
|
||||
/** 子视图:名册(roster)/ 家谱(kin) */
|
||||
@Local subView: string = 'roster';
|
||||
/** 搜索词(本地过滤) */
|
||||
@Local keyword: string = '';
|
||||
/**
|
||||
@@ -300,23 +295,6 @@ export struct FbPeoplePage {
|
||||
*/
|
||||
private rawById: Map<number, FbRosterPerson> = new Map<number, FbRosterPerson>();
|
||||
|
||||
/**
|
||||
* 家谱里的人(**来自接口** `/api/v1/kin`)。
|
||||
*
|
||||
* ⚠️ 与名册的 `all` **是两批数据**:
|
||||
* 名册是"我名册里的人"(可上千),家谱是"以我为中心的关系网"(上下两代、十来人)。
|
||||
* 所以家谱要**单独拉**,不能从 `all` 里挑。
|
||||
*/
|
||||
@Local kinPeople: FbKinPerson[] = [];
|
||||
/** 家谱的同步提示(与名册分开:两批数据可能一个成功一个失败) */
|
||||
@Local kinSyncNote: string = '';
|
||||
/**
|
||||
* ⚠️ v73:原来这里有 `kinMode`('graph' / 'list' 两种视图)。
|
||||
* 用户 2026-10-21 要求去掉列表、只留图谱 ⇒ 状态本身也不用了。
|
||||
* 「列表」那套是按代数分组的通讯录,名册页已经有同样的能力。
|
||||
*/
|
||||
/** 我在家谱里的 id(图谱里要标出「我」) */
|
||||
@Local kinMeId: number = 0;
|
||||
private repo: FbPersonRepo = FbPersonRepo.inst();
|
||||
|
||||
/**
|
||||
@@ -378,12 +356,7 @@ export struct FbPeoplePage {
|
||||
this.quickFromDetail = null;
|
||||
return true;
|
||||
}
|
||||
// ④ 家谱 ⇒ 回名册(同一页的两个子视图,"返回上一层"就是回到默认那个)
|
||||
if (this.subView === 'kin') {
|
||||
this.subView = 'roster';
|
||||
return true;
|
||||
}
|
||||
// ⑤ 本页没有可关的东西 ⇒ 交给 `Index`(换回上一个模块)
|
||||
// ④ 本页没有可关的东西 ⇒ 交给 `Index`(换回上一个模块)
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -491,13 +464,6 @@ export struct FbPeoplePage {
|
||||
* "这次没更新",用户手上的数据仍然可用。只在页面上留一行小字。
|
||||
*/
|
||||
private async syncInBackground(): Promise<void> {
|
||||
// 🔴 家谱与名册**并行拉**:两者是**独立的两批数据**
|
||||
// (名册 = 我名册里的人,可上千;家谱 = 以我为中心的上下两代,十来人)。
|
||||
// ⚠️ 并行(不是串行):串行会让"切到家谱"多等一个往返。
|
||||
// ⚠️ 家谱**不 await 在名册后面**:名册走实体表、家谱走通用缓存,
|
||||
// 两条路互不依赖。
|
||||
this.loadKin();
|
||||
|
||||
const token: string = FB_TOKEN_STORE.get();
|
||||
if (token === '') {
|
||||
this.syncNote = '未登录,显示的是本地数据';
|
||||
@@ -613,25 +579,6 @@ export struct FbPeoplePage {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 拉家谱(`/api/v1/kin`)—— 先缓存、再网络。
|
||||
*
|
||||
* ⚠️ 家谱走**通用缓存**(`module_cache`)而不是实体表:
|
||||
* 它是"一张关系网",形状与名册的"一批人"不同,
|
||||
* 落成实体表要 4 张(人/父母/配偶/子女),收益却只是
|
||||
* "省一次解析"——不值得。见 `FbModuleRepo` 的说明。
|
||||
*/
|
||||
private async loadKin(): Promise<void> {
|
||||
await loadModule<FbKinGraph>('kin', parseKin,
|
||||
(g: FbKinGraph): void => {
|
||||
this.kinPeople = g.people;
|
||||
this.kinMeId = g.meId;
|
||||
},
|
||||
(note: string): void => {
|
||||
this.kinSyncNote = note;
|
||||
});
|
||||
}
|
||||
|
||||
build() {
|
||||
// 🔴 外层再套一个 Stack:把"页面内容"与"人员详情浮层"叠起来。
|
||||
// 浮层是**页面内的覆盖层**(不是系统弹窗),理由见 FbPersonSheet 文件头。
|
||||
@@ -840,13 +787,9 @@ export struct FbPeoplePage {
|
||||
// ⇒ 解法:**把顶栏与页头塞进 `List` 的第一个 item**,
|
||||
// 它们就成了"列表内容的一部分",随列表一起滚走;
|
||||
// 同时 `List` 仍是唯一滚动容器 ⇒ 按需渲染、性能不丢。
|
||||
// (见 rosterView / kinView 里的 `this.pageHeaderItem()`)
|
||||
// (见 rosterView 里的 `this.pageHeaderItem()`)
|
||||
Column() {
|
||||
if (this.subView === 'roster') {
|
||||
this.rosterView()
|
||||
} else {
|
||||
this.kinView()
|
||||
}
|
||||
this.rosterView()
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
@@ -880,80 +823,101 @@ export struct FbPeoplePage {
|
||||
* 页头(分段切换 + 搜索 + 标签筛选条)。
|
||||
*
|
||||
* ⚠️ 从 `rosterView` 里提出来放在**页面级**:
|
||||
* 这样"名册/家谱"与搜索框在两个子视图下都常驻,
|
||||
* 切换子视图时不会跟着列表一起滚走。
|
||||
* 这样搜索框在滚动中常驻在列表内容里。
|
||||
*
|
||||
* 🔴 v74(用户 2026-10-21):
|
||||
* · 「家谱和名册的标签,都不要了」⇒ 整条分段切换删掉,
|
||||
* 连同"当前子视图"那个状态与它的切换按钮生成器一并移除。
|
||||
* · 「进来以后,上面就是搜索和添加按钮」⇒ 页头**第一行就是搜索 + 添加**,
|
||||
* 不再有任何东西排在它前面。
|
||||
* · 「搜索,做的醒目一点,现在看不清」⇒ 见下面 `searchBox` 的说明:
|
||||
* 高度 36→44、底色从 `inputBg`(几乎与页面同色)改成**白底 + 主题色描边**、
|
||||
* 图标 15→18 并改用主题色、字号 fontSmall→fontBody、提示词去掉冗长的能力罗列。
|
||||
*/
|
||||
@Builder
|
||||
peopleHeader() {
|
||||
Column() {
|
||||
// ---- 分段切换(名册 / 家谱)----
|
||||
//
|
||||
// 🔴 v59c(用户 2026-10-18):「名册、家谱这两个标签,用的不是主题色。」
|
||||
// ⇒ 原来两个都硬编码 `'#A84A28'`(**品牌砖红**),而名册的主题色是
|
||||
// `FB_MODULES` 里那个 `#4A7C82`(青)—— 页面里其它地方
|
||||
// (如列表项那个"详情"按钮的底色/字色)用的都是主题色粉调,
|
||||
// 于是这一处显得"跟整个页面不是一个色系"。
|
||||
// ⚠️ 用 `fbThemeVars(...).brand` 走统一算法,而不是直接把 `#4A7C82`
|
||||
// 抄进来:`fbThemeVars` 会把色相拉到一个**可读的饱和度/亮度区间**
|
||||
// (见其实现),直接抄模块色在选中态当底、白字压上去会偏亮发飘。
|
||||
// ⚠️ 两处都必须传同一个值 —— 之前正是"两处各写一遍字面量"才漂的。
|
||||
Row({ space: 4 }) {
|
||||
this.segBtn('名册', 'roster')
|
||||
this.segBtn('家谱', 'kin')
|
||||
}
|
||||
.padding(3)
|
||||
.backgroundColor(FbColors.inputBg)
|
||||
.borderRadius(FbMetric.radiusPill)
|
||||
.margin({ left: FbMetric.pagePad, right: FbMetric.pagePad, top: 12 })
|
||||
|
||||
if (this.subView === 'roster') {
|
||||
// ---- 搜索 + 添加 ----
|
||||
// ---- 搜索 + 添加(页头第一行,上面不再有任何东西)----
|
||||
Row({ space: 10 }) {
|
||||
// ============================================================
|
||||
// 搜索框:**白底 + 主题色细描边 + 略深的内阴影观感**
|
||||
// ============================================================
|
||||
//
|
||||
// 🔴🔴 v74(用户 2026-10-21):「搜索,做的醒目一点,现在看不清」。
|
||||
//
|
||||
// 原来为什么"看不清"(三个原因叠在一起):
|
||||
// ① 底色用 `FbColors.inputBg` —— 它和页面米色 `FbColors.paper`
|
||||
// 几乎同色,搜索框**没有边界**,看上去就是一段空白;
|
||||
// ② 高度只有 36,图标 15、字 fontSmall —— 在一屏 2444px 的真机上
|
||||
// 它占的比例很小,视线扫过去是"灰灰的一条";
|
||||
// ③ 提示词写着「搜索:姓名 / 拼音首字母(yyq)/ 手机 / 单位」,
|
||||
// 20 多字塞进 36 高的框里 ⇒ 强制缩小字号 / 显示不全,
|
||||
// 信息过载反而更难读。
|
||||
//
|
||||
// ⇒ 四件事一起改(缺一件都还是不够醒目):
|
||||
// · **白底**(`#FFFFFF`)—— 页面是米色,白底天然"浮"起来;
|
||||
// · **1.5 描边 + 主题色**(`#4A7C82` 青)—— 有明确的边界;
|
||||
// · **高度 44**(≈ 44×3.125 = 138px),接近系统搜索框的舒适高度;
|
||||
// · **字号 fontBody + 图标 18 且染主题色** —— 一眼能认出"这是搜索"。
|
||||
// ⚠️ 提示词收短成「搜索姓名 / 首字母 / 手机」,能力说明挪到
|
||||
// `searchHint()` 的注释里 —— 框里只留能一眼读完的东西。
|
||||
Row({ space: 8 }) {
|
||||
Row({ space: 6 }) {
|
||||
Image($r('app.media.fb_ic_search'))
|
||||
.width(15)
|
||||
.height(15)
|
||||
.renderMode(ImageRenderMode.Template)
|
||||
.colorFilter(fbTint(FbTint.faint))
|
||||
TextInput({ placeholder: '搜索:姓名 / 拼音首字母(yyq)/ 手机 / 单位', text: this.keyword })
|
||||
.placeholderColor(FbColors.faint)
|
||||
.placeholderFont({ size: FbMetric.fontSmall })
|
||||
.fontSize(FbMetric.fontSmall)
|
||||
.fontColor(FbColors.ink)
|
||||
.backgroundColor(Color.Transparent)
|
||||
.padding(0)
|
||||
.layoutWeight(1)
|
||||
.onChange((v: string) => {
|
||||
this.keyword = v;
|
||||
})
|
||||
/* 🔴 v59e:搜索框右侧补一个「清空」——
|
||||
名册上千人,搜错了要逐字删掉很烦(而且手机上退格容易连删)。
|
||||
⚠️ 命中区给 24×24(图标只有 12):手机上 12vp 的点击区域点不中。 */
|
||||
if (this.keyword !== '') {
|
||||
Row() {
|
||||
Image($r('app.media.fb_ic_close'))
|
||||
.width(12)
|
||||
.height(12)
|
||||
.colorFilter(fbTint(FbTint.faint))
|
||||
}
|
||||
.width(24)
|
||||
.height(24)
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.onClick((): void => {
|
||||
this.keyword = '';
|
||||
})
|
||||
Image($r('app.media.fb_ic_search'))
|
||||
.width(18)
|
||||
.height(18)
|
||||
.renderMode(ImageRenderMode.Template)
|
||||
// 图标用**名册主题色**(不是原来的 faint 灰)—— 让"搜索"这个动作有颜色。
|
||||
// ⚠️ 用 `this.themeBrand()` 而不是 `FbTint.brand`:后者是品牌砖红
|
||||
// (#A84A28),与名册的青色主题不是一个色系(v59c 踩过同样的问题)。
|
||||
.colorFilter(fbTint(this.themeBrand()))
|
||||
TextInput({ placeholder: '搜索姓名 / 首字母 / 手机', text: this.keyword })
|
||||
.placeholderColor(FbColors.muted)
|
||||
.placeholderFont({ size: FbMetric.fontBody })
|
||||
.fontSize(FbMetric.fontBody)
|
||||
.fontColor(FbColors.ink)
|
||||
.backgroundColor(Color.Transparent)
|
||||
.padding(0)
|
||||
.layoutWeight(1)
|
||||
.onChange((v: string) => {
|
||||
this.keyword = v;
|
||||
})
|
||||
/* 🔴 v59e:搜索框右侧补一个「清空」——
|
||||
名册上千人,搜错了要逐字删掉很烦(而且手机上退格容易连删)。
|
||||
⚠️ 命中区给 28×28(图标只有 14):手机上 14vp 的点击区域点不中。
|
||||
v74 跟着搜索框放大一档(24→28),否则在 44 高的框里显得太小。 */
|
||||
if (this.keyword !== '') {
|
||||
Row() {
|
||||
Image($r('app.media.fb_ic_close'))
|
||||
.width(14)
|
||||
.height(14)
|
||||
.colorFilter(fbTint(FbTint.muted))
|
||||
}
|
||||
.width(28)
|
||||
.height(28)
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.onClick((): void => {
|
||||
this.keyword = '';
|
||||
})
|
||||
}
|
||||
.layoutWeight(1)
|
||||
.height(36)
|
||||
.padding({ left: 12, right: 12 })
|
||||
.backgroundColor(FbColors.inputBg)
|
||||
.borderRadius(FbMetric.radiusS)
|
||||
.alignItems(VerticalAlign.Center)
|
||||
}
|
||||
.layoutWeight(1)
|
||||
.height(44)
|
||||
.padding({ left: 14, right: 10 })
|
||||
.backgroundColor('#FFFFFF')
|
||||
// radiusCard=14:比内嵌小块(10)圆润、比区块卡(16)收得住,
|
||||
// 正好是"一个独立的输入控件"该有的圆角。
|
||||
.borderRadius(FbMetric.radiusCard)
|
||||
.border({ width: 1.5, color: this.themeBrand() })
|
||||
.alignItems(VerticalAlign.Center)
|
||||
|
||||
/* 添加按钮:跟着搜索框一起放到 44 高,两颗控件等高才不显歪。
|
||||
⚠️ `FbPrimaryButton` 自己按内容高度走(约 34),
|
||||
这里用 `height(44)` 的容器包一层把它撑到同高 ——
|
||||
直接把 44 塞给组件会破坏它内部的 padding 比例。 */
|
||||
Column() {
|
||||
FbPrimaryButton({
|
||||
label: '添加',
|
||||
bg: '#4A7C82',
|
||||
bg: this.themeBrand(),
|
||||
icon: $r('app.media.fb_ic_plus'),
|
||||
// 🔴 v52:接上(之前这颗按钮**没有回调**,点了什么都不发生 ——
|
||||
// "全功能客户端"不能有这样的摆设)。
|
||||
@@ -962,13 +926,15 @@ export struct FbPeoplePage {
|
||||
}
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
.padding({ left: FbMetric.pagePad, right: FbMetric.pagePad, top: 12, bottom: 8 })
|
||||
.alignItems(VerticalAlign.Center)
|
||||
|
||||
// ---- 标签筛选条 ----
|
||||
this.tagBar()
|
||||
.height(44)
|
||||
.justifyContent(FlexAlign.Center)
|
||||
}
|
||||
.width('100%')
|
||||
.padding({ left: FbMetric.pagePad, right: FbMetric.pagePad, top: 14, bottom: 10 })
|
||||
.alignItems(VerticalAlign.Center)
|
||||
|
||||
// ---- 标签筛选条 ----
|
||||
this.tagBar()
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
@@ -1372,18 +1338,18 @@ export struct FbPeoplePage {
|
||||
* ⚠️ 用 `this.detailToken` 防止"快速连点两个人,前一个的响应把后一个覆盖"。
|
||||
*/
|
||||
private openDetail(id: number): void {
|
||||
/* 🔴🔴 v73 真 bug:点家谱卡片**静默没反应**。
|
||||
/* 🔴🔴 v73 真 bug:点卡片**静默没反应**(当时是家谱卡片,现在名册卡片同理)。
|
||||
根因:这里原来只从 `rawById` 取,而 `rawById` 来自 `repo.list()`
|
||||
—— 那条 SQL 带 `JOIN person_roster`,**只包含"我挑进名册的人"**。
|
||||
家谱里的人(父母、岳父母、配偶)**不一定在我的名册里** ⇒ 查不到 ⇒ 直接 return。
|
||||
名册外的人(从分享/搜索进来的人)**不一定在我的名册里** ⇒ 查不到 ⇒ 直接 return。
|
||||
字面上就是"点了没反应",而且不打日志的话 hilog 一个字都抓不到。
|
||||
|
||||
修法分两段(与 `byId()` 的注释同一条思路):
|
||||
① 名册里有 ⇒ 立刻用本地那份开浮层(不等网络,点开就有内容);
|
||||
② 名册里没有 ⇒ 先空着把浮层**打开**(`detailPerson` 用一个占位),
|
||||
② 名册里没有 ⇒ 先开一个**只有 id** 的占位把浮层打开,
|
||||
再异步 `byId()` / 网络详情补上 —— **不能**因为本地没缓存就不响应点击。
|
||||
⚠️ 注意 `detailPerson` 是 `FbRosterPerson`,不能塞 `null` 当作"只开框",
|
||||
所以第 ② 种情况必须先构造一个最小可渲染对象(只有 id + 姓名)。
|
||||
所以第 ② 种情况必须先构造一个最小可渲染对象。
|
||||
*/
|
||||
const cached: FbRosterPerson | undefined = this.rawById.get(id);
|
||||
hilog.info(DOMAIN, TAG, 'openDetail(%{public}d):名册命中=%{public}s(名册共 %{public}d 人)',
|
||||
@@ -1395,14 +1361,13 @@ export struct FbPeoplePage {
|
||||
if (cached !== undefined) {
|
||||
this.detailPerson = cached;
|
||||
} else {
|
||||
// ② 名册里没有 —— 先用家谱那份拼一个最小对象把浮层打开
|
||||
const kin: FbKinPerson | undefined = this.kinPeople.find(
|
||||
(p: FbKinPerson): boolean => p.id === id);
|
||||
if (kin === undefined) {
|
||||
hilog.warn(DOMAIN, TAG, 'openDetail(%{public}d):名册与家谱都没有这个人', id);
|
||||
return;
|
||||
}
|
||||
this.detailPerson = placeholderPerson(kin);
|
||||
/* ② 本地名册里没有 —— 仍然立刻把浮层打开,先去 `byId()` 捞一份。
|
||||
🔴 v74:家谱已从端上删除,原来"用家谱那份拼占位"的兜底没有了;
|
||||
这里退化成**纯占位**(只有 id),随后 `repo.byId()` / `fetchDetail()`
|
||||
任一路回来都会整份替换掉它。
|
||||
⚠️ 不能因为"本地没缓存"就 return —— 那正是 v73 那个"点了没反应"的病。 */
|
||||
hilog.info(DOMAIN, TAG, 'openDetail(%{public}d):本地名册未命中,先开占位浮层', id);
|
||||
this.detailPerson = placeholderPerson(id);
|
||||
}
|
||||
|
||||
const token: string = FB_TOKEN_STORE.get();
|
||||
@@ -1502,126 +1467,21 @@ export struct FbPeoplePage {
|
||||
}
|
||||
|
||||
|
||||
// ============================================================
|
||||
// 家谱
|
||||
// ============================================================
|
||||
|
||||
/**
|
||||
* 家谱的说明条(「以我为中心」+ 人数)。
|
||||
*
|
||||
* 🔴 v68:这里原来还有一颗「补关系」按钮,**从来没有 `onTap`** ——
|
||||
* 点了一点反应都没有(全仓库扫过,只剩这一颗)。
|
||||
* 它要的是"选一个还没有亲属关系的人 → 给他挂上父/母/配偶",
|
||||
* 而服务端 `relations` 表**只有读**(没有写接口),网页版也没有这个功能
|
||||
* ⇒ 与其留一个永远点不动的按钮,先撤掉(免得被当成"坏了")。
|
||||
* 要做得先加 `POST /api/v1/persons/<id>/relations`,那是独立一批活。
|
||||
*
|
||||
* 🔴 v73(用户 2026-10-21):右侧的「图谱 / 列表」切换**整块撤掉**。
|
||||
* 原话是"手机端这个家谱实在是很难看",而那个"列表"视图
|
||||
* 本质就是个按代数分组的通讯录 —— 名册页早就有同样的能力
|
||||
* (还能搜索、筛选标签),留着它只会让人以为家谱有两种画法。
|
||||
* 现在家谱只有一种形态:**图**。
|
||||
*/
|
||||
@Builder
|
||||
kinHeader() {
|
||||
Row({ space: 8 }) {
|
||||
Column({ space: 2 }) {
|
||||
Text('以我为中心')
|
||||
.fontSize(FbMetric.fontBody)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.fontColor(FbColors.ink)
|
||||
Text(this.kinTotalText())
|
||||
.fontSize(FbMetric.fontTiny)
|
||||
.fontColor(FbColors.faint)
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.layoutWeight(1)
|
||||
}
|
||||
.width('100%')
|
||||
.padding({ left: FbMetric.pagePad, right: FbMetric.pagePad, top: 12, bottom: 8 })
|
||||
.alignItems(VerticalAlign.Center)
|
||||
}
|
||||
|
||||
@Builder
|
||||
kinView() {
|
||||
Column() {
|
||||
this.pageHeaderItem()
|
||||
this.kinHeader()
|
||||
|
||||
if (this.loading) {
|
||||
Text('正在读取本地数据…')
|
||||
.width('100%')
|
||||
.padding({ top: 40, bottom: 40 })
|
||||
.textAlign(TextAlign.Center)
|
||||
.fontSize(FbMetric.fontSmall)
|
||||
.fontColor(FbColors.faint)
|
||||
} else if (this.kinPeople.length === 0) {
|
||||
Text('还没有亲属关系。\n在网页端「家谱」里填上父母 / 配偶 / 子女,这里就会长出来。')
|
||||
.width('100%')
|
||||
.padding({ top: 40, bottom: 40, left: 24, right: 24 })
|
||||
.textAlign(TextAlign.Center)
|
||||
.fontSize(FbMetric.fontSmall)
|
||||
.fontColor(FbColors.faint)
|
||||
} else {
|
||||
// ---- 家谱图(Canvas 画线 + 原生卡片,见 components/FbKinGraph.ets)----
|
||||
Column() {
|
||||
FbKinGraphView({
|
||||
people: this.kinPeople,
|
||||
meId: this.kinMeId,
|
||||
onPick: (id: number): void => {
|
||||
this.openDetail(id);
|
||||
}
|
||||
})
|
||||
}
|
||||
.layoutWeight(1)
|
||||
.width('100%')
|
||||
.padding({ left: FbMetric.pagePad, right: FbMetric.pagePad, bottom: FB_DOCK_RESERVE - 24 })
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.layoutWeight(1)
|
||||
}
|
||||
|
||||
/**
|
||||
* 一代人(家谱里的一层)。
|
||||
*
|
||||
* ⚠️ v73:这个 Builder 与 `kinRow` 一起**已删除** —— 它们只服务
|
||||
* 「列表」视图,而用户 2026-10-21 要求去掉列表、只留图谱。
|
||||
* 原来这里按代数分组、每组一个白卡片 + 行分隔线,
|
||||
* 本质就是个通讯录;名册页已经有同样的能力(还能搜索/筛标签)。
|
||||
*/
|
||||
|
||||
// ============================================================
|
||||
// 共用小件
|
||||
// ============================================================
|
||||
|
||||
/**
|
||||
* 分段切换的一个按钮(名册 / 家谱)。
|
||||
* 名册模块的主题色。
|
||||
*
|
||||
* 🔴 v59c(用户 2026-10-18):「名册、家谱这两个标签,用的不是主题色。」
|
||||
* ⇒ 颜色**不再由调用方传字面量**,改成方法内部自己取名册模块的主题色。
|
||||
* 之前两个调用点各写一遍 `'#A84A28'`(品牌砖红,与名册的青色主题不符),
|
||||
* 而且"两处各写一遍"本身就是漂移源(改一处忘一处)。
|
||||
* ⚠️ 取色走 `fbThemeVars(名册模块色).brand`(统一算法),
|
||||
* 不是直接抄 `FB_MODULES` 里那个 `#4A7C82` —— 见调用点上方那段说明。
|
||||
* 🔴 原来叫「选中态实底」,服务的是「名册 / 家谱」分段切换;
|
||||
* v74 分段切换删掉了,这个方法**留着**是因为搜索框的描边、搜索图标染色、
|
||||
* 添加按钮底色都用它 —— 一处取值,三处不漂。
|
||||
* ⚠️ 取色走 `fbThemeVars(名册模块色).brand`(统一算法),
|
||||
* 不是直接抄 `FB_MODULES` 里那个 `#4A7C82`:
|
||||
* `fbThemeVars` 会把色相拉到可读的饱和度/亮度区间,
|
||||
* 直接抄模块色当实底、白字压上去会偏亮发飘。
|
||||
*/
|
||||
@Builder
|
||||
segBtn(label: string, key: string) {
|
||||
Text(label)
|
||||
.fontSize(FbMetric.fontSmall)
|
||||
.fontWeight(this.subView === key ? FontWeight.Medium : FontWeight.Normal)
|
||||
.fontColor(this.subView === key ? Color.White : FbColors.muted)
|
||||
.textAlign(TextAlign.Center)
|
||||
.height(30)
|
||||
.layoutWeight(1)
|
||||
.backgroundColor(this.subView === key ? this.themeBrand() : Color.Transparent)
|
||||
.borderRadius(FbMetric.radiusPill)
|
||||
.onClick(() => {
|
||||
this.subView = key;
|
||||
})
|
||||
}
|
||||
|
||||
/** 名册模块的主题色(选中态实底)。取色规则见 `segBtn` 的说明。 */
|
||||
private themeBrand(): string {
|
||||
const m: FbModuleDef | undefined = fbModuleOf('people');
|
||||
return fbThemeVars(m !== undefined ? m.color : '#A84A28').brand;
|
||||
@@ -1665,14 +1525,6 @@ export struct FbPeoplePage {
|
||||
代数分层的信息现在由**图谱本身的纵向位置**表达(长辈在上、晚辈在下),
|
||||
不再需要「父母辈 / 我这一辈」这种文字小标题。 */
|
||||
|
||||
/** 家谱顶部的人数说明 */
|
||||
private kinTotalText(): string {
|
||||
if (this.kinPeople.length === 0) {
|
||||
return '还没有亲属关系';
|
||||
}
|
||||
return this.kinPeople.length.toString() + ' 位亲属 · 上下两代';
|
||||
}
|
||||
|
||||
/** 取某个人的头像色(从名册里查,查不到用默认砖红) */
|
||||
private colorOf(id: number): string {
|
||||
const hit: FbRosterItem | undefined = this.all.find((p: FbRosterItem): boolean => p.id === id);
|
||||
@@ -1681,27 +1533,28 @@ export struct FbPeoplePage {
|
||||
}
|
||||
|
||||
/**
|
||||
* 用「家谱里的那个人」拼一个**最小可渲染**的 `FbRosterPerson`。
|
||||
* 拼一个**最小可渲染**的 `FbRosterPerson`(只有 id + 姓名)。
|
||||
*
|
||||
* 🔴 为什么需要(v73 真 bug):家谱里的人**不一定在我名册里**
|
||||
* (`FbPersonRepo.list()` 带 `JOIN person_roster`,只含"我挑进名册的人"),
|
||||
* 那时点卡片以前是**静默 return ⇒ 点了没反应**。
|
||||
* 这里先拼一个只够画浮层头部的对象,**让浮层立刻打开**,
|
||||
* 随后 `repo.byId()` / `fetchDetail()` 到了再原地升级。
|
||||
* 🔴 为什么需要(v73 真 bug,v74 保留):`FbPersonRepo.list()` 带 `JOIN person_roster`,
|
||||
* 只包含"我挑进名册的人";而详情接口能取到**名册外**的人(例如从别处跳进来的人)。
|
||||
* 以前本地查不到就直接 return ⇒ 字面上"点了没反应",hilog 里一个字都没有。
|
||||
* ⇒ 先拼一个只够画浮层头部的对象,**让浮层立刻打开**,
|
||||
* 随后 `repo.byId()` / `fetchDetail()` 到了再原地升级。
|
||||
*
|
||||
* ⚠️ 只填家谱真有的那几项,其余给空值 —— 不要瞎猜(填错比空着更糟:
|
||||
* 用户会以为"系统里有这个资料")。本地库/接口补上来后会被整份替换掉。
|
||||
* ⚠️ v74 起**不再从家谱借字段**(家谱功能已从端上删除):只填 id 与姓名,
|
||||
* 其余一律给空值 —— 不要瞎猜(填错比空着更糟:用户会以为"系统里有这个资料")。
|
||||
* 本地库/接口补上来后会被整份替换掉。
|
||||
*/
|
||||
function placeholderPerson(k: FbKinPerson): FbRosterPerson {
|
||||
function placeholderPerson(id: number): FbRosterPerson {
|
||||
const p: FbRosterPerson = {
|
||||
id: k.id,
|
||||
name: k.name,
|
||||
shown: k.shown !== '' ? k.shown : k.name,
|
||||
// 家谱那份的称谓是服务端算好的,这里能用
|
||||
label: k.label,
|
||||
id: id,
|
||||
name: '',
|
||||
shown: '',
|
||||
// 称谓由服务端按家族关系算(端上没有家谱了,取不到)⇒ 留空
|
||||
label: '',
|
||||
tags: [],
|
||||
avatarColor: k.avatarColor,
|
||||
avatar: k.avatar,
|
||||
avatarColor: '#A84A28',
|
||||
avatar: '',
|
||||
birthdaySolar: '',
|
||||
birthdayFull: '',
|
||||
birthdayLunar: '',
|
||||
|
||||
@@ -682,7 +682,6 @@ export struct FbSettingsPage {
|
||||
private iconOf(key: string): Resource {
|
||||
switch (key) {
|
||||
case 'home': return $r('app.media.fb_ic_home');
|
||||
case 'kin': return $r('app.media.fb_ic_kin');
|
||||
case 'people': return $r('app.media.fb_ic_people');
|
||||
case 'movies': return $r('app.media.fb_ic_movies');
|
||||
case 'trips': return $r('app.media.fb_ic_trips');
|
||||
|
||||
Reference in New Issue
Block a user