|
|
f44b15684b
|
fix(push): 通知开关默认改开(修正误解「可配置项=默认关」致 token 从不上报)
★ 功能性硬伤修复:用户实测「新邮件根本没有通知」。
根因:我上一版把 PushService.isEnabled 默认设成关(读不到即 false),
误解了「接入系统通知是可配置项」的本意 —— 用户要的是「服务端没配凭证时
客户端优雅降级」(enabled:false 是正常态,不报错不阻塞),不是「默认关掉
推送功能」。结果 reportToken 最前 gate 直接 return,device token 从未上报,
DB 里 0 个 token,NotifyNewMail 在 len(tokens)==0 时静默返回 ⇒ 永远发不出。
修正:
- PushContract.DEFAULT_PUSH_ENABLED: false → true(契约层默认开)
- PushService.isEnabled: getSync 默认值用 DEFAULT_PUSH_ENABLED(true),
catch 也返回 true —— 只有用户显式关才不上报
- 判据同步:harmony-push-optin ①② 改默认开口径
验证(服务端→HMS 链路实打已通):
- OAuth access_token 取得(app_secret 有效)
- POST /v1/{appId}/messages:send + test_message 调通,
HMS 回 80300007 "All tokens are invalid"(假 token 无效,但凭证/形状/认证全被接受)
⇒ 只要 DB 有真实 device token 就能送达(token 由客户端上报)
|
2026-09-16 08:29:24 +08:00 |
|
|
|
cfe7808af4
|
ke: 鸿蒙 UI 整改:emoji→AmIcon 图标、宽屏侧栏、Md 第三方库、通知可配置项
- common/Icons.ets(生成器产出):43 枚与 WebUI icons.tsx 同几何的 Path 图标
- NavItems.ts:icon(emoji) → iconKey,与 WebUI 导航同图标
- 全页面 emoji 清除(空态改单行灰字,按钮/头像/刷新等换 AmIcon)
- MailDetailPage 接入 @luvi/lv-markdown-in(第三方,替代手写解析器)
- WideSidebar + MainPage isWide(≥768vp):宽屏侧栏 60vp 图标轨、藏底部条、onAreaChange 断点
- 通知=可配置项(默认关):PushService.isEnabled/setEnabled + reportToken 最前 gate (关=不取token/不弹权限/不打网关)+ SettingsPage Toggle + 服务端通道状态提示
- EntryAbility.onCreate 解析 want:冷启点通知也能路由(原来只有 onNewWant)
- 判据:harmony-widescreen(4) + harmony-push-optin(4) 新增;harmony-nav 同步 iconKey/条件 padding
|
2026-09-16 07:46:52 +08:00 |
|
|
|
9c6e9c66ad
|
跨端: 修复: 鸿蒙客户端"连不上服务器"—— 地址补 /api/v1 + 失败分类成人话(含网络白名单固化)
症状
鸿蒙客户端(client/harmony)连不上服务端,界面只显示"无法连接",用户无法自助;
而服务端 HTTPS 完全正常:https://mail.jianfgit.xyz/health → 200、
/api/v1/auth/me → 401、/api/v1/events/stream → 401(Let's Encrypt *.jianfgit.xyz,
TLS 校验通过;代理与直连 http://127.0.0.1:8180 行为一致)。
根因(两条,逐条核实过,其中一条**推翻了原判断**)
① apiBase 是"API 前缀本身"(ApiClient 里拼的是 '/auth/login' 这类相对路径),
而 Ui 只做 trim+去尾斜杠:用户若只填 `https://mail.jianfgit.xyz/`,请求就打到
`https://mail.jianfgit.xyz/auth/login` ⇒ 404,客户端再把它压成"无法连接"。
**这是本次故障最可能的直接原因。**
② 默认值 `http://192.168.2.60:8180/api/v1` 是明文 + 写死内网 IP:手机不在同网段
就永远不通(mail.jianfgit.xyz 解析到的就是这台内网机)。
★ 但"鸿蒙默认禁止明文 HTTP"这条**不成立**,已按本机离线官方文档核实:
`devecocli docs read .../使用HTTP访问网络/http-request` 的《明文HTTP访问权限配置说明》
写明 cleartextTrafficPermitted "默认为 true",Network Kit 默认允许明文;
另有 FAQ《Stage模型如何配置支持http明文传输》:"无需配置,支持HTTP明文传输数据"。
⇒ network_config.json 按"显式固化意图"处理(照文档形状写对,但**不冒充**它是修复)。
本机 SDK @ohos.net.http.d.ts 里确实有 2300997 Cleartext traffic not permitted(since 18),
所以那条错误码在客户端被建成一条可读提示,而不是被忽略。
改法
· 新增 model/ApiBase.ts(纯逻辑,无 @ohos,判据能用 node 直接跑):
normalizeApiBase(去尾斜杠**但不咬协议 //**、末尾没有 /api/v1 就补、已有的一字不动)、
validateApiBase(自带修法的中文提示 + "公网明文才告警、内网明文不误报")、
describeFailure(404 自己写文案并点名 /api/v1;其它状态码让服务端文案说话;
网络层按 2300006/2300007/2300028/2300997/2300998/2300058-60-77 分类成人话)。
· Config.ets:DEFAULT_API_BASE → https://mail.jianfgit.xyz/api/v1。
· ApiClient.ets:setBase/init **都**过 normalizeApiBase(唯一闸口 ⇒ 老装机里已经存下的
坏地址在读回时就治好,光改默认值救不了它);ApiError 带 nativeCode;错误路径改走
describeFailure;404 的提示指向"地址少了 /api/v1"。
· LoginPage.ets:地址先校验后持久化(不合法**不落库**、给可执行提示),明文警告常驻渲染;
SettingsPage.ets:添加账号同样校验(多账号库直接喂 SseService,坏地址会让该账号的实时
通道永久连不上);AccountManager/SseService 落库与建连时各自再归一化一次。
· 新增 resources/base/profile/network_config.json:按官方文档形状把内网明文
(192.168.2.60 / 10.0.2.2 / localhost)显式列进 domain-config 白名单。
文档给的就是这个**固定路径与文件名**,不需要在 module.json5 里写引用
(仓库里既有的 HomeAgent 工程同样是这么放的)。
· 新增判据 test/harmony-apibase.test.mjs(13 条)并接进 run-all.mjs 的 SUITE:
值判据**直接跑** model/ApiBase.ts;.ets 那几条是**静态**接线判据(本机无设备)。
验证(都真跑过)
· cd client/harmony && devecocli build clean && devecocli build
→ BUILD SUCCESSFUL in 7 s 186 ms;entry/build/default/outputs/default/entry-default-signed.hap
存在(1214592 B,15:14)。
· 解包 HAP:resources/base/profile/network_config.json 在包里、JSON 可解析、
cleartextTrafficPermitted=true 且白名单含 192.168.2.60/10.0.2.2/localhost;
bundleName 仍是 com.jianf.agentmail,module.json 没有多余的 metadata/securityConfiguration。
· devecocli check lint → 0 error;我改过的文件**零发现**(总工性从 8 降到 7,
顺带修掉 LoginPage 一条既有的 await-thenable)。
· node --experimental-strip-types --no-warnings --test test/harmony-apibase.test.mjs
→ ℹ tests 13 / pass 13 / fail 0。
· 变异验证 11/11 全红且**红在对应那条**(在 /tmp 的独立 worktree 里做的,不碰共享树):
归一化不补后缀、去斜杠咬掉协议、404 用通用文案、401 拿通用文案顶掉服务端原因、
网络码不再分类、默认地址退回明文内网、setBase 直接赋值、登录页去掉守卫、
内网白名单关掉明文、出现第二处自己拼 /api/v1、守卫变成空壳。
(M8 第一次是**假绿**——只判了方法声明、没判调用点;改成切出 doLogin 方法体后再判才红。)
未验到(别把"编译过了"读成"连通了")
· **没有**在真机/模拟器上点过一次登录:本机当前无设备在线,所以"真的连上了服务端"
这件事本轮**未被验证**;已验证的只是"地址会被补成带 /api/v1 的形态""构建产物正确"。
· network_config.json 的**实际效果**未验:按官方文档明文默认就允许,这份文件是显式固化,
没有做"关掉它再对比"的实验(也无法在无设备时做)。
· DNS/超时/证书这几条分类的文案是按 SDK 错误码写的,**没有构造真人故障去实测**
(即没有真的把 DNS 打坏、把证书换成自签来看提示)。
· 登录页那条"未 /api/v1 会 404"的因果链是从服务端路由 + 客户端拼接方式推出的,
没有用 curl 对 `https://mail.jianfgit.xyz/auth/login` 实打一次取证。
· test/run-all.mjs 在本机(node v24.14.1)**本来就是红的**:它只认 `# pass N`,
而 node 24 打的是 `ℹ pass N` ⇒ 25 个文件里 21 个被记成"没自报条数"。
这是既有环境漂移(已在 HEAD 的 worktree 里复现同样的红),**本次没有动它**,
所以新判据虽然已登记进 SUITE,要等 runner 的 marker 解析修好才会被套件真正计数。
|
2026-09-15 15:15:17 +08:00 |
|
|
|
1e3aac2f7d
|
跨端: feat(推送客户端): PushService.ets(取 token → 上报 → 点击跳转)+ 接进 EntryAbility ⇒ **文件真的被编译了**
pi 三件里的前两件 + 第三件的"目标解析"这半。
- `pushService.getToken()` → `POST /me/devices/push-token`(`provider/token/device_name/session_id`,省略空项);
- 上报标记按 **`accountKey|token`**(服务端同一 token 换账号是**转移**不是并存 ⇒ 标记必须按账号维度,否则新账号永远不报、旧账号的登记已被转走);
- 注销:`DELETE` **带 body**(服务端就是这么定的),`deleted:false` 不当错误;
- 点击跳转:`onNewWant` → `routeFromWant`(`parseNotificationData` + 有界去重 ledger)→ `PushService.pendingRoute` 等页面来取;
- **所有失败静默**(没 token / 401 / 400 / 500 / 权限拒绝 ⇒ 只写 hilog,不提示、不重试、不阻塞启动);
- 通知权限**只在拿到 token 后**才申请(没 token 就弹窗是打扰)。
★ 一条我差点当成"验过了"的证据:`assembleHap` 在**没接入**时也报 `BUILD SUCCESSFUL` ——
因为 ArkTS 只编译**可达**模块,没人 import 的文件根本不参与编译。我植入类型错误后仍是 SUCCESSFUL,
才确认"编译通过"当时**什么都没证明**。接入 EntryAbility 后再植入同样的错误 ⇒ `Failed :entry:default@CompileArkTS` 且指名 `PushService.ets:102` ✓
—— 现在这句"编译通过"是有内容的。
**未完成(不掩盖)**:① 登录成功后主动补报一次(现在只在冷启 `onCreate` 报,冷启时未登录 ⇒ 401 静默,等下次冷启才补上);
② `pendingRoute` 的**消费端**(页面读它并跳转)—— 这两处都要动 `LoginPage/MainPage`,而那两个文件正被别人在飞编辑,我没抢着改。
|
2026-09-15 14:20:00 +08:00 |
|
|
|
ed0ad2508e
|
跨端: feat(推送客户端): 按线上形状补契约层(DELETE 也带 body / 未知字段 400 / provider 无白名单 / 错误是 {"error"})
pi 2026-09-14 给的线上形状(从 handler/push.go 读的,不是猜的)逐条落成可判的:
- **请求体只放已知键**:`PUSH_BODY_KEYS` 登记四个键,**未知字段服务端直接 400**(不是静默忽略)
⇒ 拼错会立刻可见;可选字段为空就不放(空串虽合法,但不放更不容易踩校验)。
- **provider 只做形状校验、没有白名单**(`^[a-z0-9_-]{1,32}$`):判据断言 `apns`/`fcm` 也合法 ——
客户端**不许**硬编码"只有 hms 合法"去先拦一道(服务端没实现的通道不该变成客户端的 400)。
这正是"校验的范围必须等于它真正知道的事"的又一落点。
- **token**:空非法、512 上限;形状不合法 ⇒ `buildTokenBody` 返回 undefined,调用侧**静默跳过**,
不去打一次注定 400 的请求。
- **错误体是 `{"error"}` 不是 `{"message"}`**:判据专门断言 `{"message":"x"}` 解析出 undefined
(用错键会把"没有消息"当有消息)。
- **注销:`deleted:false`(本来没登记)不是失败** ⇒ 它**不改变分类**,所以**不再是入参**
(一个不影响结果的入参只会让人误以为它影响结果),判据断 `classifyUnregister.length === 2` 钉住这点。
- **`ApiClient.del` 补可选 JSON body**:DELETE 端点是 JSON body 形状(不是 query、不是 path 参数),
原来只有 `path` ⇒ 注销会无效。不传 body 时行为与旧版完全一致(向后兼容)。
EOF
|
2026-09-15 11:43:22 +08:00 |
|
|
|
474cadaf54
|
跨端: harmony 管理页(用户管理)+ P4c 壁纸上传入口 —— 「功能做全再交付」的两块
pi 的交付清单里缺的两块(`docs/GUI-PLAN-HARMONY.md` 原先把管理后台划在首版之外,
用户明确要求「功能做全再给我」之后收进来)。
标 `跨端:` 是因为本次的判据落在 `client/electron/test/`(鸿蒙的判据目录一向量在那里),
代码本体全在 `client/harmony/`。
## 管理页(用户管理)
- `pages/AdminUsersPage.ets`:新建 / 编辑(显示名·角色·白名单)/ 启停 / 重置密码。
排布照 `AdminUsersPage.tsx`,包括「受限」徽标的口径(普通用户且白名单非空才显示)、
最后登录缺席与空串都显示「从未登录」、管理员对白名单两项忽略。
- 入口在设置页底部,**仅管理员可见**(`role === 'admin'` 严格相等,与 `App.tsx` 同口径)。
读不到身份时**不**显示也不报错(乐观放行会让每个普通用户看到一个点进去 403 的入口)。
- `api/AdminApi.ets` + `model/AdminUsers.ts`(纯逻辑,零 import ⇒ 判据能真跑)。
- 启停**只发 status 一个字段** —— 服务端是部分更新,多发字段会把显示名与白名单一起改掉。
- `model/Models.ets` 补管理端 DTO;`main_pages.json` 注册路由。
## P4c 壁纸上传
- `model/ImagePrep.ts`:阈值与两档策略(2560/0.85 → 1280/0.78,入口 20MB,压后上限 3.5MiB)。
**一处有意不对齐 WebUI** 并写明理由:WebUI 卡 data-URL 长度(含 base64 膨胀),
鸿蒙内存直传 ArrayBuffer,卡的是字节数。
- `common/BackgroundPicker.ets`:不设 / 预设 / 自定义图片 + 浓度与模糊滑杆。
上传链:picker → 判可不可以 → 逐档按 desiredSize 解码压缩 → 上传 → **请页面以服务端为准重新同步**。
失败**必带原因**(服务端 415/413 文案原样透出)。
- `ApiClient.uploadBytes`:MultiFormData.data 收 ArrayBuffer(核了 SDK,since 11;本工程 23)
⇒ 内存直传,不需要 base64、也不需要临时文件。
- 用户取消选图**不算失败**,什么都不说。
## 顺带修掉的两处真问题(都是变异测试逼出来的)
1. **压缩循环的第二档此前是死代码**:循环里的 break 与循环外那句 shouldRetryWithActual
互相抵消 —— 把循环里那处改成 `if (true)`(永远只压一档)整套判据照样全绿。
收成一处判定(overLimit),循环外只读结论。
2. **壁纸的模糊档一直是「只写不读」**(计划文档 §7.12 登记过):滑杆能拖、值能存、
blurStyleFor 也写了,就是**没有调用点**,壁纸一点没糊。本次补上调用点
(壁纸层 .blur(px) = 图片内容模糊;导航条材质由 blurStyleFor 映射)。
同时按 §7.12 的原承诺更新了那一行。
## 一并修正的旧判据(都是"太宽/太窄",不是放宽标准)
- 「模糊归属」:原文「壁纸层不许有**任何**模糊调用」把**图片内容模糊**与**面板材质**
混为一谈(WebUI 侧核实:.app-backdrop 的 filter 与它之上那层的 backdrop-filter
是两个不同的量)⇒ 改成按两种模糊分别钉。
- 「bgBlur 只写不读,消费侧必须为 0」:值不再成立,**形状保留**(逐文件登记 + 计数 + 理由),
标题与断言里的假话一并改掉。
- isDarkMode 那条 `/dark\s*\)/` 断的是**参数顺序**(加一个入参就误红)⇒ 改成"dark 在实参里"。
- 导航材质三处断言原本钉 `Theme.navMaterial` 字面量 ⇒ 改成钉新的映射写法。
## 判据
新增 `harmony-admin.test.mjs`(22 条)、`harmony-imageprep.test.mjs`(29 条);
`harmony-presets.test.mjs` 加 1 条(模糊档搬运与归一,含 -0 那个洞)。
全量 203 条:**201 通过**,2 条失败为**改动前就红**的既有项
(BUILD_INFO 比对、词表↔余额)—— 用 stash 对照验证过。
两个新判据文件上跑了 **48 个变异体,全部被抓**(含"接线"类:删掉「受限」徽标、
组件自己宣布成功、release 不 await、按原图尺寸解码…),
其中 2 个变异体**红不了**,因此又补了 5 条判据(纯逻辑接线、退档判定只有一处、
两档都超限必拒、解码尺寸用的是目标尺寸而非原图尺寸、模糊档搬运)。
(数字口径:按 runner 的真实条件"锚点恰好命中 1 次才算跑过"统计;
另有 4 条锚点不命中、根本没跑,不算在这 48 里。我第一次写的是"40"——
凭记忆累加的,错了,已更正。)
**未验**:本机无设备/无模拟器 ⇒ 全部观感未验(管理页排版、滑杆手感、模糊在真机上的
实际档位观感)。代码齐 ≠ 真机验过。
|
2026-09-15 11:03:22 +08:00 |
|
|
|
d3f6f3baf6
|
跨端: 鸿蒙日历写侧(新建/编辑/删除/暂停恢复)+ 表单不再是一面滚轮墙
用户:「是的去吧」(批准上一封列出的下一步)。
- CalendarApi:createEvent / updateEvent / deleteEvent(POST /calendar/events、
PUT/DELETE /calendar/events/{id});新建与编辑发**同一份** CalendarEventInput
—— 服务端两个端点同形(CreateCalendarEvent 里那个 Status 字段的注释就写着这句),
拆两份会在严格解码下 400
- CalendarPage:写侧表单(新建与编辑共用一份)、二次确认删除、暂停/恢复走 update
(调度器只触发 active;没有暂停就只能删掉重加,而那会丢 event_id 与历史)
- 服务端 400 文案原样显示(收件地址无法解析:…)—— 建事件时就校验地址,
吞成保存失败等于让人猜,而猜的代价是以为设好了、实际永远发不出去
- 空标题/空收件人在本地就挡住,不发注定 400 的请求
- 提交的是**时间戳**(isoTimestampOfLocal),不是日期键;编辑回填走 localDateOf
- ★ 表单形状:日期/时间选择器合起来 ~1400px,展开着放会把标题与收件人挤出屏幕 ——
改成一行摘要 + 点开展开(默认收起)。这不是美观问题:展开态下保存在屏幕外,
要跨过一整面滚轮才够得着
- 判据 +7(端点/载荷/前置校验/文案/二次确认/时间戳往返/变异自检),23 条全绿
- 真机实测(hvigorw + hdc + uitest 逐字段输入 + 逐键点击,每一步都回库核对):
建 → 库里 event_time 是 2026-09-28T01:00Z(= 本地 09:00 整,默认值正确)、
暂停 → status=paused、删除第一下只变确认删除(库里还在)、第二下才真删(库里 0 条)
|
2026-09-14 18:57:53 +08:00 |
|
|
|
94ba4b9c58
|
跨端: 鸿蒙端功能同步第一步——日历(只读月视图)上架,入口进底部导航
用户:「要给鸿蒙端做功能同步」。按 API 面盘点(WebUI 62 个 API 函数 vs 鸿蒙 38 个),
最大的用户面缺口是**日历**:纯逻辑(model/Calendar.ts)与判据早就在,一直没页面。
新增:
- api/CalendarApi.ets:GET /calendar/events?from=&to=(与 WebUI 同参;区间按**网格**取,
不是月首月末 —— 首尾格子会显示邻月,只查当月会让那些格子永远空着)
- pages/CalendarPage.ets:月网格(翻月/回今天)、点某天看当天日程、事件点、今天/选中两态、
加载失败说出来。**没做**:写侧(增删改)、农历重复、.ics、滑动翻页 —— 逐条写在文件头
- model/Calendar.ts:补 localIsoOf / hhmmAtOffset / deviceOffsetMinutes(偏移是入参 ⇒ 三时区可真跑)
- model/Models.ets:CalendarEvent / CalendarListResponse(字段对齐服务端 JSON)
- NavItems:加「日历」,底部成为 通信/日历/联系人 三项(与 WebUI 同序)
- MainPage:日历是**常驻 pane**(visibility 控制),首次可见才拉数据;today 走
@Prop @Watch(visible) 在 pane 变可见时重算 ⇒ 结算欠账 calendar-today-recompute
(DEBTS 15 笔 → 14 笔,余额里不再计这一笔)
判据:harmony-calendar 新增 6 条(网格/表头同源、事件归日走 localIsoOf、三时区钟点、
today 重算路径、翻月走 addMonths、变异自检);harmony-nav ② 分派与 ④ 让位跟着改成结构性判据
(④ 原来那个 400 字符窗口一加 pane 就红 —— 窗口式判据的又一次现身);harmony-logic 两处
「只剩两个平级页签」跟着改成三项。
真机实测(harmony-emu + hvigorw assembleHap + hdc install + uitest click + dumpLayout):
9 月网格星期对齐(周一起始,2026-09-01 落在「二」列)、事件点恰好在有日程的那 6 天
(11/17/18/24/25/30)、点 09-17 列出当天两条日程且钟点是本地时间(DB 里 02:20Z/08:30Z
→ 界面 10:20/16:30)。
|
2026-09-14 18:38:51 +08:00 |
|
|
|
2a6ad93ec0
|
feat(harmony): P4 —— 外观(主题 + 壁纸)跟着账号走
服务端 2026-09-13 起就是外观的权威(账号级 `/api/v1/me/appearance`),WebUI 接好了,
**鸿蒙这边此前完全没接**。这一期补上,并把"谁覆盖谁"的规则做成可判据的纯逻辑。
## 改了什么
- `api/AppearanceApi.ets`:`GET/PUT /me/appearance`、`POST /me/appearance/image`、
`GET /me/appearance/image`(图片带认证取回本体:不用 `?token=`,也不让 Image 直连 http)。
- `api/ApiClient.ets`:新增 `getBytes()`(按 ARRAY_BUFFER 收)—— 复用 `request<T>` 会当场炸,
因为它假定响应是 JSON(`JSON.parse`)。
- `model/Appearance.ts`(纯逻辑,判据直接执行):归一化 / PUT 报文 / **合并决策** /
模糊值→系统材质档次 / 主题→系统色彩模式 / 遮罩浓度 / 状态文案。
- `common/AppearanceStore.ets`:落地副作用 —— 主题交给**系统**(`setColorMode`,不自己维护
深色色值)、壁纸取回 `PixelMap`、缓存**按账号**分键(`appearance.<accountId>`)。
- 入口两处:`MainPage`(进主界面就应用 —— 只在设置页生效的话"一进主界面就变回去",
WebUI 侧踩过)与 `SettingsPage` 新增「外观」段(三档主题 + 同步状态「已同步 / 仅本机」)。
## 为什么这么写(两条最贵的规则)
1. **服务端"没有记录"时以本地为准**(`saved === false`):服务端这时回的是一份*默认值*,
拿它覆盖本地 = 把用户已有的主题/壁纸抹掉(WebUI 原话:每个老用户升级后第一次登录
都会发现被重置)。正确动作是把本地那份推上去。
2. **降级必须可见**(`local-only` → 显示「仅本机」):否则用户以为换设备也能带走。
## 判据(新增 11 条,已接进 run-all;套件 10 → 11 个判据文件)
归一化(脏值/越界/小数/NaN 退回默认);`image` 档无图 → 退回 `none`;PUT 报文蛇形字段名;
★服务端无记录 → 以本地为准且**一个字段都不能被默认值顶掉**;服务端有记录 → 以服务端为准但
**不擦掉**本地那张服务端还没有的图;离线状态可见且三种状态文案互不相同;
★模糊值→系统材质档次(与 SDK 的 `BlurStyle` 成员**逐一比对**);
主题→色彩模式(数值与 SDK 的 `ConfigurationConstant.ColorMode` **逐一比对**);
★路径必须**相对基地址**(WebUI 那条"整套同步从来没生效过而单测全绿"的坑);
缓存键**带账号**;两处入口都真的应用。
变异验证(6 种,均判红):默认值覆盖本地 / 不管"image 档但服务端无图" / 材质档次自造名字 /
路径多写 `/api/v1` / 缓存键不带账号 / 深浅色彩模式数值写反。
## 判据抓到的两个真 bug
- `snapshotFromResponse` 在字段缺失时给 `bgDim = 0`,而 WebUI 语义是退回 12 ——
ArkTS 反序列化把缺失字段留成**类里写的默认值**,"字段不在"与"字段是 0"分不开。
已把默认值对齐 WebUI 的 `clamp(..., dflt)` 语义(并让 `saved` 默认 false = 安全的那一侧)。
- 主题落地按"0=浅色、1=深色"写的 `setColorMode` —— **正好反了**
(SDK:`COLOR_MODE_DARK = 0`、`COLOR_MODE_LIGHT = 1`),选深色会切成浅色。
靠判据去 SDK 枚举文件读数比对发现;映射已搬进纯逻辑 `colorModeValue`,
从"某处有个 setColorMode 调用"变成"可判据的行为"。
## 验证 / 未验
`hvigorw assembleHap` BUILD SUCCESSFUL;`npm test` 退出码 0(11 个判据文件全绿 + vitest 258/258)。
套件自检又抓到一次"判据写好没接进套件"(新文件第一版漏了 run-all),已修。
**未做**:壁纸**上传**入口(选图 → `POST /me/appearance/image`)—— 需要 picker,API 与命名已就位。
**未验**:壁纸在真机上的渲染 —— 需真机或模拟器。
|
2026-09-14 14:19:26 +08:00 |
|
|
|
73f886aea5
|
feat(harmony): P2b+P3 —— 「收件箱」改成「通信」(内部三栏 + 徽标 + 悬浮加号),发件箱与授权栏落地
用户:「收件发件授权改为一个导航项,通过内部导航区分,然后新建作为他们内部的一个悬浮的圆形加号」。
所以这一期不是"再加两个页面",而是对齐信息架构。
## 鸿蒙侧
- 底部第一项 **收件箱 → 通信**(`CommPage`),内部三栏 收件箱 / 发件箱 / 授权;
页签下划线式(不是浮动白胶囊 —— WebUI 侧用户原话「通信页面的二级页面与其他位置极其割裂」)。
- **徽标**:收件箱红(未读)、授权橙(**待决策**)、发件箱无;0 不显示,>99 写 `99+`。
合并成一个导航项后,底部看不到"授权有 3 个在等我",这个信息不能丢 —— 它比未读更急。
- **悬浮圆形加号**挂到通信页这一层(三个栏都要能新建);`⚙` 也搬上来(否则切栏就够不到设置)。
- **收件箱不再混权限邮件**(`splitByPermission`),未读按筛后算 ——
WebUI 实测过"一个会话 17 封权限邮件挤掉另外两个会话"。
- **发件箱**:`GET /me/mail/sent`,与收件箱同构(同一套折叠/行),行上主角是**收件人**;
空态有说明(主句与 WebUI 逐字一致「暂无邮件」+ 一句"这里放什么")。
- **授权栏**(P3 主体):`GET /permission/pending`(不从收件箱筛)+ `POST /permission/decide`。
拒绝**可填备注且备注真的送出**;请求**过期**时当场说清「审批不会让那次调用继续」。
- 顺手删掉死代码:收件箱里「写邮件」的 `bindSheet`(`composeVisible` 从未置 true,谁也打不开)。
## 判据(harmony-logic 19 → 28 条)
页签键/顺序从 WebUI 源码抽取比对(`uiStore.ts` 的 `CommTab` + `CommTabs.tsx` 的 `TABS`);
页签状态机(键↔下标往返、脏键/越界/非整数 → 回收件箱);徽标规则(数字来源、0 不显示、
99+ 上限、红/橙与 WebUI 类名对应);分家语义(决策过的不再算待决策、空串与 null 同义);
三栏空态互不相同且主句与 WebUI 一致;接线(三个 pane 真的渲染、加号是圆形且在通信页、
"先分家再折叠"、接口路径与决策体三字段、拒绝传备注、过期分支)。
判据抓到一个**真 bug**:`commTabFromIndex` 只判范围,`1.5` → `COMM_TABS[1.5]` = `undefined`
(表现"点哪都不亮")。已加 `Number.isInteger`。
变异验证(六种):授权徽标看未读 / 权限邮件不分出去 / 类型名拼错 / 决策过仍算待决策 /
收件箱不分家 / 发件箱空态去掉说明 —— 全部判红。
## 排序说明
**日历暂时没有入口**:P6 的内容(网格 + 事件读写 + 滑动翻页)还没做,
先放一个点进去空着的入口比暂时没有更糟 —— 有意排序,记在 §7.15 以免被当成漏做。
## 验证 / 未验
`hvigorw assembleHap` BUILD SUCCESSFUL;`npm test` 退出码 0(10 个判据文件全绿 + vitest 258/258)。
**未验**:页签/徽标/悬浮加号在真机上的观感与点击 —— 需设备或模拟器(模拟器要人在命令行启动)。
|
2026-09-14 14:13:45 +08:00 |
|
|
|
f9d757b5e5
|
chore: directory migration - gateway→server, web→client/electron
|
2026-09-08 19:16:35 +08:00 |
|