跨端: 接上聚合失败横幅(数据一直在收集,界面从来没读过 —— 安全网是断的)
逐页对齐 WebUI 时发现的**不是观感问题,是安全网断线**。
## 事实
`MailStore` 一直在收集"聚合模式下哪个账号取失败了":
MailStore.ets:142 const failed: AccountError[] = [];
MailStore.ets:208 failed.push(AccountError.of(acct.displayName, reason));
MailStore.ets:226 snap.accountErrors = failed;
(收件箱与发件箱两处 load 都写)
而**界面一次都没读过 `snap.accountErrors`**(`MainPage` 里 grep 为 0 处)。
⇒ 后果:某个账号拉不到邮件时,列表**静默少一整份**,界面看起来完全正常。
用户会据此得出错误结论 —— "没人给我发信"。
WebUI 把这条写成了显式警告(`MailList.tsx:85-91` 原注释):
「聚合时**某个账号取不到**必须说出来:静默丢掉它,列表会少一整份邮件,
而界面看起来完全正常 —— 这正是『聚合』最容易骗人的失败方式」
## 改动
· `InboxTab` 加 `@State accountErrors`,在 `applyStoreSnapshot` 里接上 `snap.accountErrors`;
· 卡片下方渲染琥珀色横幅,文案照 WebUI:
「有 {n} 个账号没取到:{账号}({原因});…」
(`bg-amber-50 border-amber-200 text-amber-800` → `warnBg` / `warnFgDark` / 11 号字);
· 新增 `accountErrorText()` 做拼接(`「a(原因);b(原因)」`)。
★ 只接了**收件箱**那一处。发件箱 `SentTab` 有自己的 `applyStoreSnapshot`,
本轮不动它 —— 它的聚合语义与收件箱不同(见 `SentTab.load`),
要不要显示同一张横幅需要单独判断,不顺手加(顺手加是本仓反复出现的错法)。
## 设备验证(如实)
✓ 收件箱正常渲染(`9 组 · 9 封`),进程存活(22242),无新 jscrash
✓ 横幅**正确不出现** —— 当前所有账号都取得到(这是应该的行为)
✗ **横幅"出现"的那条路径没能实测到**:要触发它需要一个取失败的账号,
而本机没有可用的失败账号构造。逻辑与 WebUI 逐条对齐、编译通过,
但"真的会显示成那样"我不声称已验 —— 与"动画中间帧看不到"同样的诚实口径。
This commit is contained in:
@ -18,7 +18,7 @@ import { MailApi, InboxResponse } from '../api/MailApi';
|
||||
import { AccountManager, AccountInfo } from '../api/AccountManager';
|
||||
import { SseService, SseEvent } from '../api/SseService';
|
||||
import { AppearanceStore } from '../common/AppearanceStore';
|
||||
import { MailStore, MailSnapshot, INBOX_PAGE_SIZE } from '../common/MailStore';
|
||||
import { MailStore, MailSnapshot, AccountError, INBOX_PAGE_SIZE } from '../common/MailStore';
|
||||
import { AppearanceApi } from '../api/AppearanceApi';
|
||||
import { performLogout } from '../api/Logout';
|
||||
import { ComposeIntent } from '../common/ComposeIntent';
|
||||
@ -502,6 +502,26 @@ struct InboxTab {
|
||||
}
|
||||
|
||||
/** 把 store 快照接进本组件的 `@State`(触发 ArkUI 刷新)。 */
|
||||
/**
|
||||
* 聚合模式下**单个账号**取失败的原因(`MailStore` 已在收集,此前没人读)。
|
||||
*
|
||||
* ★★ 2026-09-21 补(逐页对齐 WebUI 时发现的安全网断线):
|
||||
* 数据一直在 `MailSnapshot.accountErrors` 里、两处 load 都写,
|
||||
* 但**界面从来没有读过它** ⇒ 某个账号拉不到邮件时列表**静默少一整份**,
|
||||
* 而界面看起来完全正常 —— 用户会得出错误结论("没人给我发信")。
|
||||
*/
|
||||
@State accountErrors: AccountError[] = [];
|
||||
|
||||
/** 把聚合失败拼成 WebUI 那句文案:「a(原因);b(原因)」 */
|
||||
private accountErrorText(): string {
|
||||
const parts: string[] = [];
|
||||
for (let i = 0; i < this.accountErrors.length; i++) {
|
||||
const e: AccountError = this.accountErrors[i];
|
||||
parts.push(e.reason.length > 0 ? e.account + '(' + e.reason + ')' : e.account);
|
||||
}
|
||||
return parts.join(';');
|
||||
}
|
||||
|
||||
private applyStoreSnapshot(snap: MailSnapshot): void {
|
||||
/*
|
||||
* `MailLike[]` → `MailSummary[]`:store 持有的是接口类型(它不该依赖具体实现类),
|
||||
@ -516,6 +536,8 @@ struct InboxTab {
|
||||
this.notice = snap.notice;
|
||||
this.loading = snap.loading;
|
||||
this.error = snap.error;
|
||||
/* 聚合失败原因(见 `accountErrors` 的注释:数据一直有,界面前面没接) */
|
||||
this.accountErrors = snap.accountErrors;
|
||||
}
|
||||
|
||||
/** 展开状态放在数组里(ArkTS 的 @State 对 Map/Set 的变更不总是能观察到) */
|
||||
@ -613,6 +635,31 @@ struct InboxTab {
|
||||
.padding({ left: 10, right: 10 })
|
||||
.margin({ top: 10 })
|
||||
|
||||
/*
|
||||
* 聚合失败横幅(对齐 WebUI `MailList.tsx:85-96` 的 `account-errors`)。
|
||||
*
|
||||
* 文案/形状照 WebUI:
|
||||
* 「有 {n} 个账号没取到:{账号}({原因});…」
|
||||
* 琥珀底 + 琥珀边 + 11 号字(`bg-amber-50 border-amber-200 text-amber-800`)。
|
||||
*
|
||||
* ★★ 为什么值得单独占一块地方(WebUI 原注释):
|
||||
* 「聚合时**某个账号取不到**必须说出来:静默丢掉它,列表会少一整份邮件,
|
||||
* 而界面看起来完全正常 —— 这正是"聚合"最容易骗人的失败方式」
|
||||
*
|
||||
* 本仓的情况更糟一点:`MailStore` **一直在收集**这些失败
|
||||
* (`snap.accountErrors`,两处 load 都写),但**界面从来没有读过它** ⇒
|
||||
* 这个安全网当前是断的。是逐页对齐时比对出来的,不是猜的。
|
||||
*/
|
||||
if (this.accountErrors.length > 0) {
|
||||
Text('有 ' + this.accountErrors.length + ' 个账号没取到:' + this.accountErrorText())
|
||||
.fontSize(11).fontColor(Theme.warnFgDark)
|
||||
.width('100%')
|
||||
.padding({ left: 8, right: 8, top: 6, bottom: 6 })
|
||||
.backgroundColor(Theme.warnBg)
|
||||
.borderRadius(6)
|
||||
.margin({ top: 6 })
|
||||
}
|
||||
|
||||
// 账号选择器下拉
|
||||
if (this.showAccountPicker && this.accountList.length > 1) {
|
||||
Column() {
|
||||
|
||||
Reference in New Issue
Block a user