feat(frontend): add P2 quality gates

This commit is contained in:
yml2213
2026-05-15 17:35:50 +08:00
parent a65c0713fb
commit 787b01749c
62 changed files with 4907 additions and 1355 deletions
+37 -24
View File
@@ -22,11 +22,7 @@ import { notifyTencentActionError } from './tencent/session-errors'
const DEFAULT_LOGIN_TYPE: TencentLoginType = 'qq'
const POLL_INTERVAL_MS = 2500
const POLL_FAILURE_LIMIT = 3
const ACTIVE_TASK_STATUSES = new Set<ClaimTaskStatus>([
'claimed',
'role_confirmed',
'redeeming',
])
const ACTIVE_TASK_STATUSES = new Set<ClaimTaskStatus>(['claimed', 'role_confirmed', 'redeeming'])
export function useClaimPage(token: string) {
const detailLoading = ref(true)
@@ -53,7 +49,9 @@ export function useClaimPage(token: string) {
const roleReady = computed(() => Boolean(activityInfo.value?.role?.ready))
const hasSession = computed(() => Boolean(session.value?.sessionId))
const loginTypeLabel = computed(() => (loginType.value === 'wx' ? '微信' : 'QQ'))
const sessionNotice = computed(() => pollWarningMessage.value || session.value?.notice || task.value?.lastError || '')
const sessionNotice = computed(
() => pollWarningMessage.value || session.value?.notice || task.value?.lastError || '',
)
const qrImage = computed(() =>
session.value?.qrImageBase64 ? `data:image/png;base64,${session.value.qrImageBase64}` : '',
)
@@ -64,9 +62,13 @@ export function useClaimPage(token: string) {
{ value: 'wx' as const, label: '微信账号登录' },
]
const statusLabel = computed(() => resolveTaskStatusLabel(task.value?.status, session.value?.status))
const statusLabel = computed(() =>
resolveTaskStatusLabel(task.value?.status, session.value?.status),
)
const initButtonLabel = computed(() => `开始初始化 ${loginTypeLabel.value} 登录`)
const scanInstruction = computed(() => `请使用${loginTypeLabel.value}扫描二维码,并在手机上确认登录`)
const scanInstruction = computed(
() => `请使用${loginTypeLabel.value}扫描二维码,并在手机上确认登录`,
)
const roleFacts = computed(() => [
{
label: '登录昵称',
@@ -106,21 +108,21 @@ export function useClaimPage(token: string) {
])
const canConfirmRole = computed(() =>
Boolean(
task.value
&& !task.value.requiresSupportReview
&& hasSession.value
&& roleReady.value
&& task.value.status === 'claimed',
task.value &&
!task.value.requiresSupportReview &&
hasSession.value &&
roleReady.value &&
task.value.status === 'claimed',
),
)
const canRedeem = computed(() =>
Boolean(
task.value
&& !task.value.requiresSupportReview
&& hasSession.value
&& roleConfirmed.value
&& !redeemLoading.value
&& (task.value.status === 'role_confirmed' || task.value.status === 'redeeming'),
task.value &&
!task.value.requiresSupportReview &&
hasSession.value &&
roleConfirmed.value &&
!redeemLoading.value &&
(task.value.status === 'role_confirmed' || task.value.status === 'redeeming'),
),
)
const redeemBlockedReason = computed(() => {
@@ -158,14 +160,16 @@ export function useClaimPage(token: string) {
return ''
})
const redeemButtonLabel = computed(() => (task.value?.requiresSupportReview ? '等待客服兑换' : '开始兑换'))
const redeemButtonLabel = computed(() =>
task.value?.requiresSupportReview ? '等待客服兑换' : '开始兑换',
)
const screenshotEmptyTitle = computed(() =>
task.value?.status === 'redeemed' ? '本次没有可展示的截图' : '等待截图',
)
const screenshotEmptyMessage = computed(() =>
task.value?.status === 'redeemed'
? '本次兑换可能未生成截图,或截图产物还未同步完成。'
: '领取完成后,如本次生成了结果截图,这里会展示。'
: '领取完成后,如本次生成了结果截图,这里会展示。',
)
function applyLoginTypeFromDetail(nextDetail: ClaimDetailData) {
@@ -183,7 +187,11 @@ export function useClaimPage(token: string) {
activityInfo.value?.role?.partition || '',
].join('|'),
() => {
roleConfirmed.value = Boolean(task.value?.status === 'role_confirmed' || task.value?.status === 'redeeming' || task.value?.status === 'redeemed')
roleConfirmed.value = Boolean(
task.value?.status === 'role_confirmed' ||
task.value?.status === 'redeeming' ||
task.value?.status === 'redeemed',
)
},
{ immediate: true },
)
@@ -514,7 +522,9 @@ export function useClaimPage(token: string) {
maxWidth: '100%',
}))
const qrPreviewWidth = computed(() => `${Math.min(Math.max(qrDisplayWidth.value + 120, 360), 480)}px`)
const qrPreviewWidth = computed(
() => `${Math.min(Math.max(qrDisplayWidth.value + 120, 360), 480)}px`,
)
loadDetail()
@@ -567,7 +577,10 @@ export function useClaimPage(token: string) {
}
}
function syncLoginTypeFromDetail(detail: ClaimDetailData, fallback: TencentLoginType = DEFAULT_LOGIN_TYPE) {
function syncLoginTypeFromDetail(
detail: ClaimDetailData,
fallback: TencentLoginType = DEFAULT_LOGIN_TYPE,
) {
const nextLoginType = String(detail.session?.loginType || detail.task.loginType || '').trim()
if (nextLoginType === 'wx') {
return 'wx'