完善样式系统与调试链路底座

This commit is contained in:
2026-03-30 18:19:05 +08:00
parent 2c0fd4c549
commit 3b9117427e
40 changed files with 7526 additions and 389 deletions

View File

@@ -0,0 +1,250 @@
const DEFAULT_DEBUG_LOG_URL = 'wss://gs.gotomars.xyz/debug-log'
const MAX_QUEUED_LOGS = 80
export type MockSimulatorDebugLogLevel = 'info' | 'warn' | 'error'
export interface MockSimulatorDebugLoggerState {
enabled: boolean
connected: boolean
connecting: boolean
url: string
statusText: string
}
export interface MockSimulatorDebugLogEntry {
type: 'debug-log'
timestamp: number
scope: string
level: MockSimulatorDebugLogLevel
message: string
payload?: Record<string, unknown>
}
function normalizeMockSimulatorLogUrl(rawUrl: string): string {
const trimmed = String(rawUrl || '').trim()
if (!trimmed) {
return DEFAULT_DEBUG_LOG_URL
}
let normalized = trimmed
if (!/^wss?:\/\//i.test(normalized)) {
normalized = `ws://${normalized.replace(/^\/+/, '')}`
}
if (!/\/debug-log(?:\?.*)?$/i.test(normalized)) {
normalized = normalized.replace(/\/+$/, '')
normalized = `${normalized}/debug-log`
}
return normalized
}
export class MockSimulatorDebugLogger {
socketTask: WechatMiniprogram.SocketTask | null
enabled: boolean
connected: boolean
connecting: boolean
url: string
queue: MockSimulatorDebugLogEntry[]
onStateChange?: (state: MockSimulatorDebugLoggerState) => void
constructor(onStateChange?: (state: MockSimulatorDebugLoggerState) => void) {
this.socketTask = null
this.enabled = false
this.connected = false
this.connecting = false
this.url = DEFAULT_DEBUG_LOG_URL
this.queue = []
this.onStateChange = onStateChange
}
getState(): MockSimulatorDebugLoggerState {
return {
enabled: this.enabled,
connected: this.connected,
connecting: this.connecting,
url: this.url,
statusText: !this.enabled
? `已关闭 (${this.url})`
: this.connected
? `已连接 (${this.url})`
: this.connecting
? `连接中 (${this.url})`
: `未连接 (${this.url})`,
}
}
emitState(): void {
if (this.onStateChange) {
this.onStateChange(this.getState())
}
}
setEnabled(enabled: boolean): void {
if (this.enabled === enabled) {
return
}
this.enabled = enabled
if (!enabled) {
this.disconnect()
this.queue = []
this.emitState()
return
}
this.emitState()
this.connect()
}
setUrl(url: string): void {
const nextUrl = normalizeMockSimulatorLogUrl(url)
if (this.url === nextUrl) {
return
}
this.url = nextUrl
if (!this.enabled) {
this.emitState()
return
}
this.disconnect()
this.emitState()
this.connect()
}
log(
scope: string,
level: MockSimulatorDebugLogLevel,
message: string,
payload?: Record<string, unknown>,
): void {
if (!this.enabled) {
return
}
const entry: MockSimulatorDebugLogEntry = {
type: 'debug-log',
timestamp: Date.now(),
scope,
level,
message,
...(payload ? { payload } : {}),
}
if (this.connected && this.socketTask) {
this.send(entry)
return
}
this.queue.push(entry)
if (this.queue.length > MAX_QUEUED_LOGS) {
this.queue.splice(0, this.queue.length - MAX_QUEUED_LOGS)
}
this.connect()
}
disconnect(): void {
const socketTask = this.socketTask
this.socketTask = null
this.connected = false
this.connecting = false
if (socketTask) {
try {
socketTask.close({})
} catch (_error) {
// noop
}
}
this.emitState()
}
destroy(): void {
this.disconnect()
this.queue = []
}
connect(): void {
if (!this.enabled || this.connected || this.connecting) {
return
}
this.connecting = true
this.emitState()
try {
const socketTask = wx.connectSocket({
url: this.url,
})
this.socketTask = socketTask
socketTask.onOpen(() => {
this.connected = true
this.connecting = false
this.emitState()
this.send({
type: 'debug-log',
timestamp: Date.now(),
scope: 'logger',
level: 'info',
message: 'logger channel connected',
payload: {
url: this.url,
},
})
this.flush()
})
socketTask.onClose(() => {
this.connected = false
this.connecting = false
this.socketTask = null
this.emitState()
})
socketTask.onError(() => {
this.connected = false
this.connecting = false
this.socketTask = null
this.emitState()
})
socketTask.onMessage(() => {
// 模拟器会广播所有消息debug logger 不消费回包。
})
} catch (_error) {
this.connected = false
this.connecting = false
this.socketTask = null
this.emitState()
}
}
flush(): void {
if (!this.connected || !this.socketTask || !this.queue.length) {
return
}
const pending = this.queue.splice(0, this.queue.length)
pending.forEach((entry) => {
this.send(entry)
})
}
send(entry: MockSimulatorDebugLogEntry): void {
if (!this.socketTask || !this.connected) {
return
}
try {
this.socketTask.send({
data: JSON.stringify(entry),
})
} catch (_error) {
this.connected = false
this.connecting = false
this.socketTask = null
this.emitState()
}
}
}