diff --git a/apps/backend/src/services/session/session-proof-html.js b/apps/backend/src/services/session/session-proof-html.ts similarity index 93% rename from apps/backend/src/services/session/session-proof-html.js rename to apps/backend/src/services/session/session-proof-html.ts index afe0eb3a..31f5d32b 100644 --- a/apps/backend/src/services/session/session-proof-html.js +++ b/apps/backend/src/services/session/session-proof-html.ts @@ -1,4 +1,16 @@ -export function buildProofHtml({ redeemImageBase64, timeImageBase64, redeemMessage, timePageUrl }) { +export type ProofHtmlInput = { + redeemImageBase64: string + timeImageBase64: string + redeemMessage?: string + timePageUrl: string +} + +export function buildProofHtml({ + redeemImageBase64, + timeImageBase64, + redeemMessage, + timePageUrl, +}: ProofHtmlInput): string { const capturedAt = new Date().toLocaleString('zh-CN', { hour12: false, timeZone: 'Asia/Shanghai', @@ -159,7 +171,7 @@ export function buildProofHtml({ redeemImageBase64, timeImageBase64, redeemMessa ` } -export function escapeHtml(value) { +export function escapeHtml(value: unknown): string { return String(value || '') .replaceAll('&', '&') .replaceAll('<', '<') diff --git a/apps/backend/src/services/session/session-proof-renderer.js b/apps/backend/src/services/session/session-proof-renderer.ts similarity index 75% rename from apps/backend/src/services/session/session-proof-renderer.js rename to apps/backend/src/services/session/session-proof-renderer.ts index 97a88f49..891d5735 100644 --- a/apps/backend/src/services/session/session-proof-renderer.js +++ b/apps/backend/src/services/session/session-proof-renderer.ts @@ -1,14 +1,37 @@ -// @ts-nocheck +/// import fs from 'node:fs/promises' import { buildProofHtml } from './session-proof-html.js' -export async function showResultDialog(page, message) { +type BrowserPageLike = { + evaluate: (callback: any, arg?: unknown) => Promise + waitForTimeout: (milliseconds: number) => Promise + setViewportSize: (viewport: { width: number; height: number }) => Promise + setContent: (html: string, options?: { waitUntil?: string }) => Promise + screenshot: (options: { path: string; fullPage?: boolean }) => Promise + close: () => Promise +} + +type BrowserContextLike = { + newPage: () => Promise +} + +type ComposeProofScreenshotOptions = { + outputPath: string + redeemImagePath: string + timeImagePath: string + redeemMessage?: string + timePageUrl: string +} + +export async function showResultDialog(page: BrowserPageLike, message: string): Promise { await page.evaluate((text) => { document.querySelectorAll('iframe').forEach((element) => element.remove()) document.querySelectorAll('.pop').forEach((element) => { - element.style.display = 'none' + if (element instanceof HTMLElement) { + element.style.display = 'none' + } }) let card = document.getElementById('codex-redeem-result') @@ -80,9 +103,9 @@ export async function showResultDialog(page, message) { } export async function composeProofScreenshot( - browserContext, - { outputPath, redeemImagePath, timeImagePath, redeemMessage, timePageUrl }, -) { + browserContext: BrowserContextLike, + { outputPath, redeemImagePath, timeImagePath, redeemMessage, timePageUrl }: ComposeProofScreenshotOptions, +): Promise { const [redeemImageBase64, timeImageBase64] = await Promise.all([ fs.readFile(redeemImagePath, 'base64'), fs.readFile(timeImagePath, 'base64'), diff --git a/apps/backend/src/services/session/session-proof-result-writer.js b/apps/backend/src/services/session/session-proof-result-writer.ts similarity index 58% rename from apps/backend/src/services/session/session-proof-result-writer.js rename to apps/backend/src/services/session/session-proof-result-writer.ts index e259334a..2910933e 100644 --- a/apps/backend/src/services/session/session-proof-result-writer.js +++ b/apps/backend/src/services/session/session-proof-result-writer.ts @@ -1,11 +1,29 @@ -// @ts-nocheck - import fs from 'node:fs/promises' -import { BAIDU_BEIJING_TIME_URL } from './session-proof-constants.js' +import { BAIDU_BEIJING_TIME_URL, type RedeemProofMode } from './session-proof-constants.js' + +type RedeemResultFilePayload = { + proofMode: RedeemProofMode + sessionId?: string + activityUrl: string + code: string + finalResult?: { + role?: { + area?: string + } + [key: string]: unknown + } | null + attempts?: unknown[] + screenshotPath: string + htmlPath?: string + redeemPageScreenshotPath?: string + beijingTimeScreenshotPath?: string + beijingTimePageUrl?: string + beijingTimeError?: string +} export async function writeRedeemResultFile( - resultPath, + resultPath: string, { proofMode, sessionId, @@ -19,8 +37,8 @@ export async function writeRedeemResultFile( beijingTimeScreenshotPath = '', beijingTimePageUrl = BAIDU_BEIJING_TIME_URL, beijingTimeError = '', - }, -) { + }: RedeemResultFilePayload, +): Promise { await fs.writeFile( resultPath, JSON.stringify( diff --git a/docs/backend-typescript-migration-plan.md b/docs/backend-typescript-migration-plan.md index af2a2f05..5b2f5c47 100644 --- a/docs/backend-typescript-migration-plan.md +++ b/docs/backend-typescript-migration-plan.md @@ -408,6 +408,16 @@ - `npm run typecheck` - `npm run build` - `npm test` 共 139 个用例通过 +77. 腾讯浏览器会话 proof 渲染 / 结果写入模块迁移到 `.ts`: + - `src/services/session/session-proof-html.ts` + - `src/services/session/session-proof-renderer.ts` + - `src/services/session/session-proof-result-writer.ts` +78. 凭证 HTML 输入、结果 JSON payload、浏览器截图合成上下文、页面弹窗渲染已显式类型化 +79. Docker 内验证通过: + - `src/services/session/session-proof.test.js` 共 4 个用例通过 + - `npm run typecheck` + - `npm run build` + - `npm test` 共 139 个用例通过 ## 下一步建议