后端迁移会话活动信息模块

This commit is contained in:
yml
2026-05-21 15:37:15 +08:00
parent 150de31c74
commit e88b9d18fd
2 changed files with 102 additions and 17 deletions
@@ -1,9 +1,83 @@
// @ts-nocheck
/// <reference lib="dom" />
import { extractHostState, reloadActivityPageForPresentation } from './session-page.js'
import { shouldRefreshLoggedInPresentation } from './session-state.js'
export function createEmptyActivityInfo() {
type BrowserPageLike = {
evaluate: <T = any>(callback: any) => Promise<T>
waitForTimeout: (milliseconds: number) => Promise<void>
}
type HostState = {
loginText?: string
unloginVisible?: boolean
loginedVisible?: boolean
}
export type ActivityInfo = {
nickname: string
role: {
ready: boolean
roleName: string
roleId: string
area: string
partition: string
platId: string
md5str: string
checkparam: string
}
form: {
cdkeyInputId: string
cdkeyValue: string
verifyInputId: string
verifyValue: string
verifyImgId: string
submitId: string
}
verify: {
visible: boolean
src: string
naturalWidth: number
naturalHeight: number
}
popup: {
visible: boolean
text: string
detail: string
}
}
type SessionForPresentation = {
page: BrowserPageLike
presentationSyncAttempts: number
}
type EnsureLoggedInPresentationOptions = {
hostState?: HostState | null
credentialReady?: boolean
activityUrl?: string
extractHostState?: (page: BrowserPageLike) => Promise<HostState>
reloadActivityPageForPresentation?: (page: BrowserPageLike, activityUrl: string) => Promise<unknown>
shouldRefreshLoggedInPresentation?: (hostState: HostState) => boolean
}
type EnsureActivityInfoReadyOptions = {
triggerRender?: boolean
timeoutMs?: number
extractActivityInfo?: (page: BrowserPageLike) => Promise<ActivityInfo>
triggerActivityRoleRender?: (page: BrowserPageLike) => Promise<unknown>
now?: () => number
}
declare global {
interface Window {
renderCdkey?: () => void
roleData?: Record<string, unknown>
isRole?: unknown
}
}
export function createEmptyActivityInfo(): ActivityInfo {
return {
nickname: '',
role: {
@@ -39,7 +113,7 @@ export function createEmptyActivityInfo() {
}
export async function ensureLoggedInPresentation(
session,
session: SessionForPresentation,
{
hostState = null,
credentialReady = false,
@@ -47,8 +121,8 @@ export async function ensureLoggedInPresentation(
extractHostState: extractHostStateImpl = extractHostState,
reloadActivityPageForPresentation: reloadActivityPageForPresentationImpl = reloadActivityPageForPresentation,
shouldRefreshLoggedInPresentation: shouldRefreshLoggedInPresentationImpl = shouldRefreshLoggedInPresentation,
} = {},
) {
}: EnsureLoggedInPresentationOptions = {},
): Promise<{ reloaded: boolean; hostState: HostState }> {
let nextHostState = hostState || (await extractHostStateImpl(session.page))
if (!credentialReady || !shouldRefreshLoggedInPresentationImpl(nextHostState)) {
@@ -76,15 +150,15 @@ export async function ensureLoggedInPresentation(
}
export async function ensureActivityInfoReady(
page,
page: BrowserPageLike,
{
triggerRender = false,
timeoutMs = 8_000,
extractActivityInfo: extractActivityInfoImpl = extractActivityInfo,
triggerActivityRoleRender: triggerActivityRoleRenderImpl = triggerActivityRoleRender,
now = () => Date.now(),
} = {},
) {
}: EnsureActivityInfoReadyOptions = {},
): Promise<ActivityInfo> {
if (triggerRender) {
await triggerActivityRoleRenderImpl(page)
}
@@ -104,7 +178,7 @@ export async function ensureActivityInfoReady(
return lastInfo
}
export async function triggerActivityRoleRender(page) {
export async function triggerActivityRoleRender(page: BrowserPageLike): Promise<void> {
try {
await page.evaluate(() => {
const maybeRender = window.renderCdkey
@@ -118,11 +192,11 @@ export async function triggerActivityRoleRender(page) {
}
}
export async function extractActivityInfo(page) {
export async function extractActivityInfo(page: BrowserPageLike): Promise<ActivityInfo> {
try {
return await page.evaluate(() => {
const asString = (value) => (typeof value === 'string' ? value.trim() : '')
const isVisible = (element) => {
const asString = (value: unknown) => (typeof value === 'string' ? value.trim() : '')
const isVisible = (element: Element | null) => {
if (!element) {
return false
}
@@ -131,8 +205,11 @@ export async function extractActivityInfo(page) {
return style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0'
}
const pick = (selector) => document.querySelector(selector)
const pickBest = (selector, predicate = null) => {
const pick = (selector: string) => document.querySelector(selector)
const pickBest = (
selector: string,
predicate: ((element: Element) => boolean) | null = null,
): Element | null => {
const matches = [...document.querySelectorAll(selector)]
const preferred = matches.find((element) => {
if (predicate && !predicate(element)) {
@@ -170,7 +247,7 @@ export async function extractActivityInfo(page) {
const roleSelector = pick('[id^="milo_role_selector_"]')
const roleNameText =
textOf('#role_name') ||
asString(roleSelector?.selectedOptions?.[0]?.textContent || '')
asString(roleSelector instanceof HTMLSelectElement ? roleSelector.selectedOptions?.[0]?.textContent || '' : '')
const verifyImg = pickBest('[id^="milo_verifyImg_"]', (node) => node instanceof HTMLImageElement)
const popup = pick('#pop2')
const cdkeyInput = pickBest(
@@ -215,8 +292,8 @@ export async function extractActivityInfo(page) {
verify: {
visible: isVisible(verifyImg),
src: asString(verifyImg?.getAttribute('src')),
naturalWidth: Number(verifyImg?.naturalWidth || 0),
naturalHeight: Number(verifyImg?.naturalHeight || 0),
naturalWidth: verifyImg instanceof HTMLImageElement ? Number(verifyImg.naturalWidth || 0) : 0,
naturalHeight: verifyImg instanceof HTMLImageElement ? Number(verifyImg.naturalHeight || 0) : 0,
},
popup: {
visible: isVisible(popup),
@@ -488,6 +488,14 @@
- `npm run typecheck`
- `npm run build`
- `npm test` 共 139 个用例通过
104. 腾讯浏览器会话 activity 信息模块迁移到 `.ts`
- `src/services/session/session-activity.ts`
105. 活动角色 / 表单 / 验证码 / 弹窗信息结构、登录态 presentation 同步、角色渲染触发与轮询已显式类型化
106. Docker 内验证通过:
- `src/services/session/session.test.js` 共 14 个用例通过
- `npm run typecheck`
- `npm run build`
- `npm test` 共 139 个用例通过
## 下一步建议