首页联系人:修头像显示 + 排除自己 (#88)
用户:首页联系人,需要带头像,排除自己。
① 头像(真 bug:从来没显示出来过)
改前 Image(p.avatar) —— 而 p.avatar 存的是**存储键**(avatars/xxx.jpg),
不是能喂给 Image() 的地址。Image("avatars/xxx.jpg") 被当成相对沙箱路径,
静默失败 ⇒ 永远只剩首字色块,看起来像"这个功能没做"。
正确出口项目里早就有:fbImageSrc(key, token)(先查本地解密缓存,
没缓存才拼 media.php?k=&token=)。名册页/观影卡都这么写,唯独首页这处漏了。
⇒ 改用 FbAvatar({ name, color, dia, imageUrl }):
· 底色+首字常驻,图片成功才盖上去 —— 名册绝大多数人没头像,必须回落;
· 有 key 但图坏了(OSS 文件缺失/token 过期)时 Image 是纯空白,
FbAvatar 会露出下面的首字,不会变成一块空光板。
personInitial() 因此成了死代码,删掉(FbAvatar 内部按 name 取首字)。
② 排除自己
FbPersonRepo.list() 返回整个名册(含"我"),自己占掉一个最显眼的位置
(一屏只露 6 个,3 列 × 2 行)。
- 用 session.me.id 判,不用名字/昵称比(重名、改名会漏);
- 取不到 id(0)时不剔任何人 —— 宁可多显示一个,
也不要因空 id 把列表清空(本项目踩过判断写反 ⇒ 列表恒空的坑);
- pfTotal 用剔除后的数量:它渲染成标题「N 人」,
用原始总数会写 800 人却只列 799 个,看着像丢人。
验证(真机 5NC0225B27004718):
- 标题 800 人 → 799 人;6 格从「爸爸/妈妈/岳父/杨永全/红围脖/轻舟」
变成「爸爸/妈妈/岳父/岳母/红围脖/轻舟」,即自己消失、后面依次前移;
- 底部说明同步为「共 799 人」;
- 6 个头像逐格取样(圆心 ±25px):色数 223~2162、主色占比 0.00~0.40,
全部是多色真实图像(纯色首字头会是主色占比>0.75、色数<50)。
hvigorw assembleHap BUILD SUCCESSFUL。
This commit is contained in:
@@ -53,7 +53,7 @@ import { FB_TOKEN_STORE } from '../../data/FbTokenStore';
|
|||||||
import { parseTaskMeta } from '../../data/FbParse';
|
import { parseTaskMeta } from '../../data/FbParse';
|
||||||
import { FB_CARD_FORMS } from '../../data/FbCardForms';
|
import { FB_CARD_FORMS } from '../../data/FbCardForms';
|
||||||
import { fbApi, FbApiResult } from '../../data/FbHttp';
|
import { fbApi, FbApiResult } from '../../data/FbHttp';
|
||||||
import { FbSectionTitle } from '../../components/Widgets';
|
import { FbAvatar, FbSectionTitle } from '../../components/Widgets';
|
||||||
import { FbStatCell } from '../../components/FbStatCell';
|
import { FbStatCell } from '../../components/FbStatCell';
|
||||||
import { FbDayEventPanel } from '../../components/FbDayEventPanel';
|
import { FbDayEventPanel } from '../../components/FbDayEventPanel';
|
||||||
import { FbEventSheet } from '../../components/FbEventSheet';
|
import { FbEventSheet } from '../../components/FbEventSheet';
|
||||||
@@ -1124,10 +1124,25 @@ export struct FbHomePage {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const people: FbRosterPerson[] = await FbPersonRepo.inst().list();
|
const people: FbRosterPerson[] = await FbPersonRepo.inst().list();
|
||||||
this.pfTotal = people.length;
|
/* 🔴 用户 2026-11-06:「首页联系人,需要带头像,**排除自己**。」
|
||||||
|
⇒ 从名册里剔掉"我"自己。首页这块是"家里人速览",
|
||||||
|
把自己列在里面既没用(头像是自己)又占掉一个宝贵的位置
|
||||||
|
(一屏只露 6 个,3 列 × 2 行)。
|
||||||
|
⚠️ 用 `session.me.id` 判,**不用名字/昵称比** —— 重名、改名都会漏;
|
||||||
|
名册的 `id` 与服务端 persons.id 同一套,稳。
|
||||||
|
⚠️ 取不到(0,比如还没登录完)时**不剔任何人**:宁可多显示一个,
|
||||||
|
也不要因为一个空 id 把整个列表清空(历史上踩过"suspend 条件写反
|
||||||
|
⇒ 列表恒空"的坑)。
|
||||||
|
⚠️ `pfTotal` 用**剔除后**的数量:它渲染成标题右侧「N 人」,
|
||||||
|
若还是原始总数,卡片会写"N 人"却只列出 N-1 个,看着像丢人。 */
|
||||||
|
const meId: number = this.app.session.me.id;
|
||||||
|
const others: FbRosterPerson[] = meId > 0
|
||||||
|
? people.filter((x: FbRosterPerson): boolean => x.id !== meId)
|
||||||
|
: people;
|
||||||
|
this.pfTotal = others.length;
|
||||||
/* 卡片上只露前 6 个:与 `HomeCards` 的 `contacts` 默认 `n => 8` 同口径,
|
/* 卡片上只露前 6 个:与 `HomeCards` 的 `contacts` 默认 `n => 8` 同口径,
|
||||||
手机上 6 个(3 列 × 2 行)刚好一屏内不压其他卡片。 */
|
手机上 6 个(3 列 × 2 行)刚好一屏内不压其他卡片。 */
|
||||||
this.pfRecent = people.slice(0, 6);
|
this.pfRecent = others.slice(0, 6);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
hilog.warn(DOMAIN, TAG, '首页读名册失败:%{public}s', JSON.stringify(err));
|
hilog.warn(DOMAIN, TAG, '首页读名册失败:%{public}s', JSON.stringify(err));
|
||||||
this.pfRecent = [];
|
this.pfRecent = [];
|
||||||
@@ -2759,27 +2774,22 @@ export struct FbHomePage {
|
|||||||
@Builder
|
@Builder
|
||||||
personTile(p: FbRosterPerson) {
|
personTile(p: FbRosterPerson) {
|
||||||
Column({ space: 5 }) {
|
Column({ space: 5 }) {
|
||||||
if (p.avatar !== '') {
|
/* 🔴 用户 2026-11-06:「首页联系人,需要带头像」。
|
||||||
Image(p.avatar)
|
改前这里是 `if (p.avatar !== '') { Image(p.avatar) }` —— 头像**从来显示不出来**。
|
||||||
.width(38)
|
根因:`FbRosterPerson.avatar` 存的是**存储键**(`avatars/xxx.jpg`),
|
||||||
.height(38)
|
不是能直接喂给 `Image()` 的地址。`Image('avatars/xxx.jpg')` 会被当成
|
||||||
.borderRadius(19)
|
相对沙箱路径 ⇒ 静默失败 ⇒ 永远走不到图,只剩首字色块。
|
||||||
.objectFit(ImageFit.Cover)
|
⇒ 统一改用 `FbAvatar`:它接受 `imageUrl`(用 `fbImageSrc(key, token)`
|
||||||
.alt($r('app.media.fb_ic_people'))
|
拼好传进来),并且**底色+首字常驻、图片成功才盖上去** ——
|
||||||
} else {
|
名册 800 人里只有 19 人传过头像,没图的必须回落到首字,
|
||||||
/* 没有头像 ⇒ 首字 + 名册里那个人的底色(与名册页一致,不另算颜色)。
|
而"有 key 但图坏了"时也不会变成一块空光板(`Image` 失败是空白)。
|
||||||
⚠️ 字也要用**对色**(`FbPersonRepo` 存了 avatarColor 是给底用的)——
|
⚠️ 尺寸 38 与原实现一致(三列网格、两行不压其它卡)。 */
|
||||||
这里简单用白字:底色本身就是中深色(名册页的取色规则)。 */
|
FbAvatar({
|
||||||
Text(this.personInitial(p))
|
name: this.personLabel(p),
|
||||||
.width(38)
|
color: p.avatarColor !== '' ? p.avatarColor : '#B7A99A',
|
||||||
.height(38)
|
dia: 38,
|
||||||
.borderRadius(19)
|
imageUrl: p.avatar !== '' ? fbImageSrc(p.avatar, FB_TOKEN_STORE.get()) : ''
|
||||||
.backgroundColor(p.avatarColor !== '' ? p.avatarColor : '#B7A99A')
|
})
|
||||||
.fontColor(Color.White)
|
|
||||||
.fontSize(16)
|
|
||||||
.fontWeight(FontWeight.Medium)
|
|
||||||
.textAlign(TextAlign.Center)
|
|
||||||
}
|
|
||||||
|
|
||||||
Text(this.personLabel(p))
|
Text(this.personLabel(p))
|
||||||
.fontSize(FbMetric.fontTiny)
|
.fontSize(FbMetric.fontTiny)
|
||||||
@@ -2814,11 +2824,8 @@ export struct FbHomePage {
|
|||||||
return p.name;
|
return p.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 首字(头像兜底)。空名兜底成 `?`,别画出一个空圆。 */
|
/** 首字兜底已移交给 `FbAvatar`(它内部按 `name` 取首字)。
|
||||||
private personInitial(p: FbRosterPerson): string {
|
* 2026-11-06 首页联系人改用它之后,这里的 `personInitial()` 成了死代码,删掉。 */
|
||||||
const nm: string = this.personLabel(p);
|
|
||||||
return nm.length > 0 ? nm.substring(0, 1) : '?';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 「最近纪念日」里的一行(v59,用户 2026-10-18)。
|
* 「最近纪念日」里的一行(v59,用户 2026-10-18)。
|
||||||
|
|||||||
Reference in New Issue
Block a user