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 个模块全报"抽屉里没找到"(像应用坏了,其实是探针过期)。
- 资源/笔记两页写死了早已不存在的条目(户口本/房产证/阳台改造清单)⇒ 改成
  结构性文案(副标题 + 常驻筛选胶囊),不随用户数据变化而恒红。
This commit is contained in:
2026-10-18 23:12:57 +08:00
parent 1c1a859464
commit 7858de27e3
26 changed files with 1213 additions and 257 deletions
+64 -1
View File
@@ -354,4 +354,67 @@ function fbIconOf(name: string): Resource {
case 'fb_ic_trash': return $r('app.media.fb_ic_trash');
default: return $r('app.media.fb_ic_dot');
}
}
}
// ============================================================
// 透明度色的**唯一正确写法**
// ============================================================
/**
* 🔴🔴 ArkUI 的 8 位十六进制颜色是 `#AARRGGBB`(**透明度在前**),
* 不是 Web/CSS 的 `#RRGGBBAA`。
*
* 本项目为此踩了一个"看不见的 bug"(2026-10-18 真机像素采样定位):
* · 遮罩写的是 `'#00000066'` —— 本意"黑色 40%",实际是 **alpha=0x00**
* ⇒ **完全透明** ⇒ 全应用所有"页面内浮层"的遮罩**从来没显示过**;
* 用户说的「弹框和下面白色的列表糊在一起,根本看不出是弹框」,
* 根因就是这个 —— 不是卡片样式不够,而是**遮罩压根没画出来**。
* · `brand + '1A'`(浅色底)实际变成"30% 不透明的橄榄色"
* ⇒ 主题色浅底看着发黄发脏,而不是"很淡的同色"。
* · `shadow({color:'#00000033'})` 同理 ⇒ 阴影也不存在。
*
* 证据(同一次真机截图里取像素):
* 实底 `brand` 采样 (77,131,137);浅底按钮采样 (217,219,186)。
* 按 AARRGGBB 算:`#4D83891A` = alpha 0x4D(30%) × (131,137,26) 叠白
* = (218,219,186) ✓ 与采样一致;按 RRGGBBAA 算应是 (237,242,243) ✗。
*
* ⚠️ 所以:**任何带透明度的颜色都必须走下面这两个工具**,不要手写 8 位 hex,
* 也不要再"在颜色串后面拼两位" —— 拼在后面就是拼到了蓝色通道上。
*/
/**
* 给 `#RRGGBB` 加透明度,产出 ArkUI 认识的 `#AARRGGBB`。
*
* @param hex 六位十六进制(`#RRGGBB`;也容忍八位,会先截成前六位)
* @param alpha 0~1(0.4 = 40% 不透明)
*/
export function fbAlpha(hex: string, alpha: number): string {
let base: string = hex.trim();
if (base.startsWith('#')) {
base = base.substring(1);
}
if (base.length > 6) {
// 已经是八位:取**后六位**当颜色(历史写法把透明度拼在了末尾)
base = base.substring(base.length - 6);
}
let a: number = Math.round(alpha * 255);
if (a < 0) {
a = 0;
}
if (a > 255) {
a = 255;
}
let aa: string = a.toString(16).toUpperCase();
if (aa.length < 2) {
aa = '0' + aa;
}
return '#' + aa + base.toUpperCase();
}
/** 页面内浮层的遮罩(黑色 40%)—— 全应用**同一档**,两级浮层不能深浅不一 */
export const FB_MASK: string = '#66000000';
/** 浮层卡片阴影(黑色 20%) */
export const FB_SHADOW: string = '#33000000';
/** 卡片描边(黑色 8%,同色背景上仍有一条可见界线) */
export const FB_HAIRLINE: string = '#14000000';