后端迁移会话活动信息模块
This commit is contained in:
+94
-17
@@ -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 个用例通过
|
||||
|
||||
## 下一步建议
|
||||
|
||||
|
||||
Reference in New Issue
Block a user