feat(desktop/account-health): mark freshly bound accounts as live

Bind callbacks now stamp the runtime account as health=live with a fresh
verified_at and seed the health record via markTrackedAccountBound, so the
UI doesn't show a just-bound account as 尚未校验 while waiting for the next
probe. Also let force probes bypass the cached-result short-circuit so the
manual 重新校验 button always re-runs the probe.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-29 17:11:50 +08:00
parent e89349399b
commit 426e94dd6b
2 changed files with 41 additions and 1 deletions
+31 -1
View File
@@ -402,7 +402,7 @@ function canUseCachedProbe(
now = Date.now(),
): boolean {
if (options.force) {
return Boolean(record.lastProbeAt && now - record.lastProbeAt < MANUAL_PROBE_MIN_INTERVAL_MS);
return false;
}
if (
@@ -675,6 +675,36 @@ export function forgetTrackedAccountHealth(
}
}
export function markTrackedAccountBound(
account: PublishAccountIdentity,
profile: AccountHealthProfile | null = null,
): AccountHealthSnapshot {
const record = ensureRecord(account);
const previousSignature = snapshotSignature(record);
const now = Date.now();
const resolvedProfile: AccountHealthProfile = {
displayName: profile?.displayName ?? account.displayName ?? null,
avatarUrl: profile?.avatarUrl ?? null,
subjectUid: profile?.subjectUid ?? account.platformUid ?? null,
};
trackedAccounts.set(account.id, account);
record.platform = account.platform;
record.authState = "active";
record.probeState = "idle";
record.authReason = "bind_success";
record.lastVerifiedAt = now;
record.lastProbeAt = now;
record.nextProbeAt = nextRegularProbeAt(now);
record.lastAuthFailureAt = null;
record.profile = resolvedProfile;
record.sessionFingerprint = resolvedProfile.subjectUid ?? record.sessionFingerprint;
record.suspectedExpiredAt = null;
record.confirmFailureCount = 0;
return commitRecord(record, previousSignature);
}
export function getAccountHealthSnapshot(accountId: string): AccountHealthSnapshot | null {
ensureInitialized();
const record = records.get(accountId);
@@ -45,6 +45,7 @@ import {
forgetTrackedAccountHealth,
getAccountHealthSnapshot,
getProjectedAccountHealth,
markTrackedAccountBound,
probeTrackedAccount,
reportAccountFailure,
syncTrackedAccounts,
@@ -1255,9 +1256,12 @@ export async function requestRuntimeAccountProbe(
}
export function noteRuntimeAccountBound(account: DesktopAccountInfo): void {
const verifiedAt = new Date().toISOString();
const normalizedAccount: DesktopAccountInfo = {
...account,
platform_uid: normalizeAccountPlatformUid(account.platform_uid) || account.platform_uid,
health: "live",
verified_at: account.verified_at ?? verifiedAt,
};
const existingIndex = state.accounts.findIndex((item) =>
item.id === normalizedAccount.id
@@ -1282,6 +1286,12 @@ export function noteRuntimeAccountBound(account: DesktopAccountInfo): void {
});
state.lastAccountsSyncAt = Date.now();
syncTrackedAccounts(state.accounts.map((item) => accountIdentityFromDesktopAccount(item)));
markTrackedAccountBound(accountIdentityFromDesktopAccount(normalizedAccount), {
subjectUid: normalizedAccount.platform_uid,
displayName: normalizedAccount.display_name,
avatarUrl: normalizedAccount.avatar_url,
});
enqueueAccountHealthReport(normalizedAccount.id);
refreshAccountNames();
}