test(desktop): cover deepseek account name extraction for wechat + phone logins
Desktop Client Build / Resolve Build Metadata (push) Successful in 28s
Frontend CI / Frontend (push) Successful in 4m5s
Backend CI / Backend (push) Successful in 17m7s
Desktop Client Build / Publish Client Artifacts to NAS (push) Has been cancelled
Desktop Client Build / Build Desktop Client (push) Has been cancelled
Desktop Client Build / Resolve Build Metadata (push) Successful in 28s
Frontend CI / Frontend (push) Successful in 4m5s
Backend CI / Backend (push) Successful in 17m7s
Desktop Client Build / Publish Client Artifacts to NAS (push) Has been cancelled
Desktop Client Build / Build Desktop Client (push) Has been cancelled
Refactor readDeepseekAccountIdentity so the JSON payload parser is a pure
ts function (extractDeepseekIdentityFromPayload). The webContents IIFE now
just polls for userToken and returns the raw API JSON; payload picking lives
in ts and is unit-tested.
Tests lock the contract for both login types we observed in the wild:
- WeChat-bound account: id_profile.name = '阿白', picture present.
- Phone-only login: id_profile = null, mobile_number = '177******08',
email = '' (empty string, not null) — the case that originally regressed.
Plus regressions for the priority order (profile.name > mobile_number > email),
the all-empty fallback, and non-record payloads.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -56,6 +56,7 @@ type AIPlatformStatusCard = {
|
||||
accent: string
|
||||
description: string
|
||||
account: DesktopAccountInfo | null
|
||||
isClientOnline: boolean
|
||||
sampleStatus: string
|
||||
lastSampledAt: string | null
|
||||
actualSampleCount: number
|
||||
@@ -327,6 +328,17 @@ const selectedPlatformAuthorized = computed(() => {
|
||||
)
|
||||
})
|
||||
|
||||
const selectedPlatformOnlineAuthorized = computed(() => {
|
||||
const onlinePlatformIDs =
|
||||
dashboardQuery.data.value?.runtime.online_authorized_monitoring_platform_ids ?? []
|
||||
if (selectedPlatformId.value === 'all') {
|
||||
return onlinePlatformIDs.length > 0
|
||||
}
|
||||
return onlinePlatformIDs.some(
|
||||
(item) => normalizeMonitoringPlatformId(item) === selectedPlatformId.value,
|
||||
)
|
||||
})
|
||||
|
||||
const collectNowDisabledReason = computed(() => {
|
||||
if (!selectedBrandId.value) {
|
||||
return t('tracking.collectBrandRequired')
|
||||
@@ -356,6 +368,9 @@ const collectNowDisabledReason = computed(() => {
|
||||
if (!currentUserClientOnline.value) {
|
||||
return t('tracking.collectClientOnlineRequired')
|
||||
}
|
||||
if (dashboardQuery.data.value && !selectedPlatformOnlineAuthorized.value) {
|
||||
return t('tracking.collectClientOnlineRequired')
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
@@ -385,9 +400,19 @@ const aiPlatformStatusCards = computed<AIPlatformStatusCard[]>(() => {
|
||||
item,
|
||||
]),
|
||||
)
|
||||
const onlineAuthorizedPlatformIDs = new Set(
|
||||
(dashboardQuery.data.value?.runtime.online_authorized_monitoring_platform_ids ?? [])
|
||||
.map((item) => normalizeMonitoringPlatformId(item))
|
||||
.filter((item): item is string => Boolean(item)),
|
||||
)
|
||||
|
||||
return aiPlatformCatalog.map((platform) => {
|
||||
const matchedAccounts = [...(accountGroups.get(platform.id) ?? [])].sort((left, right) => {
|
||||
const leftOnline = left.client_online === true ? 1 : 0
|
||||
const rightOnline = right.client_online === true ? 1 : 0
|
||||
if (leftOnline !== rightOnline) {
|
||||
return rightOnline - leftOnline
|
||||
}
|
||||
const leftAt = Date.parse(resolveAccountCheckedAt(left) ?? '') || 0
|
||||
const rightAt = Date.parse(resolveAccountCheckedAt(right) ?? '') || 0
|
||||
return rightAt - leftAt
|
||||
@@ -401,6 +426,10 @@ const aiPlatformStatusCards = computed<AIPlatformStatusCard[]>(() => {
|
||||
accent: platform.accent,
|
||||
description: platform.description,
|
||||
account: matchedAccounts[0] ?? null,
|
||||
isClientOnline:
|
||||
onlineAuthorizedPlatformIDs.has(platform.id) ||
|
||||
(!dashboardQuery.data.value &&
|
||||
matchedAccounts.some((account) => account.client_online === true)),
|
||||
sampleStatus: breakdown?.platform_sample_status ?? 'pending',
|
||||
lastSampledAt: breakdown?.last_sampled_at ?? null,
|
||||
actualSampleCount: breakdown?.actual_sample_count ?? 0,
|
||||
@@ -671,12 +700,12 @@ function accountAuthColor(account: DesktopAccountInfo | null): string {
|
||||
}
|
||||
}
|
||||
|
||||
function desktopStatusLabel(account: DesktopAccountInfo | null): string {
|
||||
function desktopStatusLabel(account: DesktopAccountInfo | null, isClientOnline: boolean): string {
|
||||
if (!account?.client_id) {
|
||||
return '未绑定桌面端'
|
||||
}
|
||||
|
||||
return account.client_online ? '客户端在线' : '客户端离线'
|
||||
return isClientOnline ? '客户端在线' : '客户端离线'
|
||||
}
|
||||
|
||||
function formatCount(value: number | null | undefined): string {
|
||||
@@ -999,7 +1028,7 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean {
|
||||
</div>
|
||||
<div class="ai-platform-status-card__row">
|
||||
<span>客户端</span>
|
||||
<strong>{{ desktopStatusLabel(platform.account) }}</strong>
|
||||
<strong>{{ desktopStatusLabel(platform.account, platform.isClientOnline) }}</strong>
|
||||
</div>
|
||||
<div class="ai-platform-status-card__row">
|
||||
<span>采样状态</span>
|
||||
|
||||
Reference in New Issue
Block a user