feat(frontend): add P2 quality gates
This commit is contained in:
@@ -66,21 +66,31 @@ export function useAdminManualRedeemPage() {
|
||||
)
|
||||
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}` : '',
|
||||
)
|
||||
const currentTaskId = computed(() => Number(task.value?.taskId || route.query.taskId || 0) || 0)
|
||||
const reviewReady = computed(() => Boolean(session.value?.review?.capturedAt) && task.value?.status !== 'redeemed')
|
||||
const resultReady = computed(() => Boolean(result.value?.screenshotReady) && task.value?.status === 'redeemed')
|
||||
const reviewReady = computed(
|
||||
() => Boolean(session.value?.review?.capturedAt) && task.value?.status !== 'redeemed',
|
||||
)
|
||||
const resultReady = computed(
|
||||
() => Boolean(result.value?.screenshotReady) && task.value?.status === 'redeemed',
|
||||
)
|
||||
const loginTabs = [
|
||||
{ value: 'qq' as const, label: 'QQ账号登录' },
|
||||
{ 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: '登录昵称',
|
||||
@@ -120,18 +130,18 @@ export function useAdminManualRedeemPage() {
|
||||
])
|
||||
const canConfirmRole = computed(() =>
|
||||
Boolean(
|
||||
task.value
|
||||
&& task.value.status === 'claimed'
|
||||
&& hasSession.value
|
||||
&& roleReady.value
|
||||
&& !roleConfirmLoading.value,
|
||||
task.value &&
|
||||
task.value.status === 'claimed' &&
|
||||
hasSession.value &&
|
||||
roleReady.value &&
|
||||
!roleConfirmLoading.value,
|
||||
),
|
||||
)
|
||||
const canRedeem = computed(() =>
|
||||
Boolean(
|
||||
task.value
|
||||
&& ['role_confirmed', 'redeeming'].includes(task.value.status)
|
||||
&& !redeemLoading.value,
|
||||
task.value &&
|
||||
['role_confirmed', 'redeeming'].includes(task.value.status) &&
|
||||
!redeemLoading.value,
|
||||
),
|
||||
)
|
||||
const redeemBlockedReason = computed(() => {
|
||||
@@ -158,13 +168,17 @@ export function useAdminManualRedeemPage() {
|
||||
return ''
|
||||
})
|
||||
const redeemButtonLabel = computed(() => (redeemLoading.value ? '兑换中...' : '开始兑换'))
|
||||
const screenshotEmptyTitle = computed(() => (task.value?.status === 'redeemed' ? '未获取到结果图' : '等待角色截图'))
|
||||
const screenshotEmptyTitle = computed(() =>
|
||||
task.value?.status === 'redeemed' ? '未获取到结果图' : '等待角色截图',
|
||||
)
|
||||
const screenshotEmptyMessage = computed(() =>
|
||||
task.value?.status === 'redeemed'
|
||||
? '本次兑换可能未生成最终截图,或截图仍在同步中。'
|
||||
: '客户登录并识别到角色后,这里会展示给客服复核的角色截图。'
|
||||
: '客户登录并识别到角色后,这里会展示给客服复核的角色截图。',
|
||||
)
|
||||
const canCreateTask = computed(
|
||||
() => Boolean(form.proofValue.trim() && form.skuCode.trim()) && !createLoading.value,
|
||||
)
|
||||
const canCreateTask = computed(() => Boolean(form.proofValue.trim() && form.skuCode.trim()) && !createLoading.value)
|
||||
const hasActiveTask = computed(() => Boolean(task.value?.taskId))
|
||||
|
||||
watch(qrImage, () => {
|
||||
@@ -538,19 +552,20 @@ export function useAdminManualRedeemPage() {
|
||||
|
||||
const anchor = document.createElement('a')
|
||||
anchor.href = screenshotUrl.value
|
||||
anchor.download = task.value?.status === 'redeemed'
|
||||
? `manual-redeem-result-${task.value?.taskNo || 'task'}.png`
|
||||
: `manual-redeem-review-${task.value?.taskNo || 'task'}.png`
|
||||
anchor.download =
|
||||
task.value?.status === 'redeemed'
|
||||
? `manual-redeem-result-${task.value?.taskNo || 'task'}.png`
|
||||
: `manual-redeem-review-${task.value?.taskNo || 'task'}.png`
|
||||
anchor.click()
|
||||
return true
|
||||
}
|
||||
|
||||
async function writeImageBlobToClipboard(blob: Blob, fallbackMessage: string) {
|
||||
if (
|
||||
typeof navigator === 'undefined'
|
||||
|| !navigator.clipboard
|
||||
|| typeof window === 'undefined'
|
||||
|| !('ClipboardItem' in window)
|
||||
typeof navigator === 'undefined' ||
|
||||
!navigator.clipboard ||
|
||||
typeof window === 'undefined' ||
|
||||
!('ClipboardItem' in window)
|
||||
) {
|
||||
throw new Error('当前浏览器不支持直接复制图片,请改用截图发送或下载')
|
||||
}
|
||||
@@ -569,7 +584,9 @@ export function useAdminManualRedeemPage() {
|
||||
|
||||
async function loadScreenshotPreview(nextDetail = detail.value) {
|
||||
const taskId = Number(nextDetail?.task?.taskId || 0)
|
||||
const shouldFetch = Boolean(taskId && (nextDetail?.session?.review?.capturedAt || nextDetail?.result?.screenshotReady))
|
||||
const shouldFetch = Boolean(
|
||||
taskId && (nextDetail?.session?.review?.capturedAt || nextDetail?.result?.screenshotReady),
|
||||
)
|
||||
|
||||
if (!shouldFetch) {
|
||||
clearScreenshotPreview()
|
||||
@@ -601,7 +618,9 @@ export function useAdminManualRedeemPage() {
|
||||
|
||||
function resolveSkuName(skuCode: string) {
|
||||
const normalized = String(skuCode || '').trim()
|
||||
const matched = suggestions.value.find((item) => String(item.skuCode || '').trim() === normalized)
|
||||
const matched = suggestions.value.find(
|
||||
(item) => String(item.skuCode || '').trim() === normalized,
|
||||
)
|
||||
return matched?.skuCode || normalized
|
||||
}
|
||||
|
||||
@@ -682,7 +701,9 @@ export function useAdminManualRedeemPage() {
|
||||
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`,
|
||||
)
|
||||
|
||||
return {
|
||||
form,
|
||||
@@ -744,7 +765,10 @@ export function useAdminManualRedeemPage() {
|
||||
}
|
||||
}
|
||||
|
||||
function syncLoginTypeFromDetail(detail: AdminManualRedeemDetail, fallback: TencentLoginType = DEFAULT_LOGIN_TYPE) {
|
||||
function syncLoginTypeFromDetail(
|
||||
detail: AdminManualRedeemDetail,
|
||||
fallback: TencentLoginType = DEFAULT_LOGIN_TYPE,
|
||||
) {
|
||||
const nextLoginType = String(detail.session?.loginType || detail.task.loginType || '').trim()
|
||||
if (nextLoginType === 'wx') {
|
||||
return 'wx'
|
||||
@@ -823,7 +847,10 @@ function mergeDetail(current: AdminManualRedeemDetail | null, next: AdminManualR
|
||||
}
|
||||
}
|
||||
|
||||
function shouldRefreshQrImage(currentSession: AdminManualRedeemDetail['session'], nextSession: AdminManualRedeemDetail['session']) {
|
||||
function shouldRefreshQrImage(
|
||||
currentSession: AdminManualRedeemDetail['session'],
|
||||
nextSession: AdminManualRedeemDetail['session'],
|
||||
) {
|
||||
if (!currentSession || !nextSession || !nextSession.artifacts?.hasQrImage) {
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user