fix desktop account status display

This commit is contained in:
2026-05-14 21:43:25 +08:00
parent 75b407ec6b
commit 639516f374
3 changed files with 165 additions and 27 deletions
@@ -1,3 +1,8 @@
import {
normalizeDesktopAccountErrorMessage,
translatePublisherPlatform,
} from '../../shared/publisher-errors'
type ClientErrorTone = 'error' | 'warning'
type ClientActionKind = 'bind-account' | 'open-console' | 'probe-account' | 'unbind-account'
@@ -48,7 +53,9 @@ function presentClientError(kind: ClientActionKind, error: unknown): ClientError
return {
tone: 'warning',
title: '授权已中断',
content: '授权窗口已关闭,本次绑定没有完成。重新点击“绑定账号”即可继续。',
content:
normalizeDesktopAccountErrorMessage(message) ??
'授权窗口已关闭,本次绑定没有完成。重新点击“绑定账号”即可继续。',
}
}
@@ -56,7 +63,9 @@ function presentClientError(kind: ClientActionKind, error: unknown): ClientError
return {
tone: 'warning',
title: '授权窗口已达上限',
content: '当前最多同时打开 2 个授权窗口。请先完成或关闭已有授权窗口,再继续新的绑定。',
content:
normalizeDesktopAccountErrorMessage(message) ??
'当前最多同时打开 2 个授权窗口。请先完成或关闭已有授权窗口,再继续新的绑定。',
}
}
@@ -64,7 +73,9 @@ function presentClientError(kind: ClientActionKind, error: unknown): ClientError
return {
tone: 'error',
title: '保存授权账号失败',
content: '平台侧授权已经完成,但客户端回写账号信息失败。请稍后重试。',
content:
normalizeDesktopAccountErrorMessage(message) ??
'平台侧授权已经完成,但客户端回写账号信息失败。请稍后重试。',
}
}
@@ -72,7 +83,7 @@ function presentClientError(kind: ClientActionKind, error: unknown): ClientError
return {
tone: 'error',
title: '账号绑定失败',
content: '授权流程执行失败,请稍后重新发起绑定。',
content: normalizeDesktopAccountErrorMessage(message) ?? '授权流程执行失败,请稍后重新发起绑定。',
}
}
@@ -81,7 +92,9 @@ function presentClientError(kind: ClientActionKind, error: unknown): ClientError
return {
tone: 'error',
title: '平台暂不支持',
content: `${platformId} 暂时还不支持这个操作。`,
content:
normalizeDesktopAccountErrorMessage(message) ??
`${translatePublisherPlatform(platformId)}暂时还不支持这个操作。`,
}
}
@@ -89,17 +102,20 @@ function presentClientError(kind: ClientActionKind, error: unknown): ClientError
return {
tone: 'warning',
title: kind === 'unbind-account' ? '账号状态已变化' : '账号状态已更新',
content: '当前账号状态刚刚发生了变化。请先刷新列表,再重试这次操作。',
content:
normalizeDesktopAccountErrorMessage(message) ??
'当前账号状态刚刚发生了变化。请先刷新列表,再重试这次操作。',
}
}
if (message.startsWith('desktop_account_session_expired:')) {
const platformId = message.split(':')[1] || '当前平台'
const platformLabel = platformId === 'qiehao' ? '企鹅号' : platformId
return {
tone: 'warning',
title: '授权已过期',
content: `${platformLabel} 登录态已失效,请重新授权后再打开工作台。`,
content:
normalizeDesktopAccountErrorMessage(message) ??
`${translatePublisherPlatform(platformId)}登录态已失效,请重新授权后再打开工作台。`,
}
}
@@ -107,7 +123,17 @@ function presentClientError(kind: ClientActionKind, error: unknown): ClientError
return {
tone: 'error',
title: '账号解绑失败',
content: '服务端解绑没有成功完成,请稍后重试。',
content:
normalizeDesktopAccountErrorMessage(message) ?? '服务端解绑没有成功完成,请稍后重试。',
}
}
const normalizedDesktopMessage = normalizeDesktopAccountErrorMessage(message)
if (normalizedDesktopMessage) {
return {
tone: message.includes('expired') || message.includes('challenge') ? 'warning' : 'error',
title: '操作失败',
content: normalizedDesktopMessage,
}
}
@@ -34,7 +34,7 @@ const batchProbeQueuedAccountIds = ref<readonly string[]>([])
const batchProbeTotalCount = ref(0)
const actionSuccess = ref<string | null>(null)
type AccountAuthState = 'authorized' | 'expired' | 'attention' | 'risk'
type AccountAuthState = 'authorized' | 'expired' | 'attention'
type AccountRow = Readonly<Omit<RuntimeAccount, 'tags'>> & { tags: readonly string[] }
const publishPlatformIds = new Set(desktopPublishMediaCatalog.map((item) => item.id))
@@ -43,9 +43,8 @@ const accounts = computed(() =>
)
const overview = computed(() => ({
authorized: accounts.value.filter((item) => item.health === 'live').length,
attention: accounts.value.filter((item) => item.health === 'captcha').length,
risk: accounts.value.filter((item) => item.health === 'risk').length,
authorized: accounts.value.filter((item) => authState(item) === 'authorized').length,
attention: accounts.value.filter((item) => authState(item) !== 'authorized').length,
onlineClients: snapshot.value?.summary.onlineClients ?? 0,
}))
@@ -76,7 +75,6 @@ const statusOptions = [
{ value: 'all', label: '全部状态' },
{ value: 'authorized', label: '已授权' },
{ value: 'attention', label: '待处理' },
{ value: 'risk', label: '风险观察' },
{ value: 'expired', label: '授权过期' },
] as const
@@ -105,7 +103,7 @@ function authState(account: AccountRow): AccountAuthState {
case 'challenge_required':
return 'attention'
default:
return 'risk'
return 'attention'
}
}
@@ -117,15 +115,19 @@ function authStateLabel(account: AccountRow): string {
return '校验中'
}
switch (authState(account)) {
case 'authorized':
switch (account.authState) {
case 'active':
return '已授权'
case 'expired':
return '授权过期'
case 'attention':
case 'revoked':
return '已停用'
case 'challenge_required':
return account.authReason === 'risk_control' ? '触发风控' : '需人工验证'
default:
case 'expiring_soon':
return account.probeState === 'network_error' ? '最近校验失败' : '待重新校验'
default:
return account.probeState === 'network_error' ? '最近校验失败' : '待校验'
}
}
@@ -134,13 +136,16 @@ function authTagColor(account: AccountRow): string {
return 'processing'
}
switch (authState(account)) {
case 'authorized':
switch (account.authState) {
case 'active':
return 'success'
case 'expired':
case 'revoked':
return 'error'
case 'attention':
case 'challenge_required':
return 'warning'
case 'expiring_soon':
return account.probeState === 'network_error' ? 'warning' : 'default'
default:
return 'default'
}
@@ -202,7 +207,7 @@ const filteredAccounts = computed(() => {
return false
}
if (selectedStatus.value !== 'all' && authState(account) !== selectedStatus.value) {
if (!matchesSelectedStatus(account)) {
return false
}
@@ -223,6 +228,17 @@ const filteredAccounts = computed(() => {
})
})
function matchesSelectedStatus(account: AccountRow): boolean {
switch (selectedStatus.value) {
case 'all':
return true
case 'attention':
return authState(account) !== 'authorized'
default:
return authState(account) === selectedStatus.value
}
}
function selectPlatform(platform: string) {
selectedPlatform.value = platform
void refreshAccounts()
@@ -462,10 +478,6 @@ const tableColumns = [
<div class="stat-label">待处理</div>
<div class="stat-value">{{ overview.attention }}</div>
</div>
<div class="stat-card">
<div class="stat-label">风险观察</div>
<div class="stat-value">{{ overview.risk }}</div>
</div>
<div class="stat-card">
<div class="stat-label">在线客户端</div>
<div class="stat-value">{{ overview.onlineClients }}</div>