diff --git a/tools/package/pack.ps1 b/tools/package/pack.ps1 index 6d59bed..509a6e6 100644 --- a/tools/package/pack.ps1 +++ b/tools/package/pack.ps1 @@ -126,12 +126,11 @@ $argsList = @( "--exclude-module", "transformers", # Transformers (huge) "--exclude-module", "tensorflow", "--exclude-module", "torch", # PyTorch (massive if present) - - # Hidden imports for LLM - "--hidden-import", "tiktoken_ext.openai_public", - "--hidden-import", "tiktoken_ext", - "--collect-all", "tiktoken", - "--copy-metadata", "tiktoken" + "--exclude-module", "numpy", # Numerics (not used in server) + "--exclude-module", "pandas", # Data analysis (not used in server) + "--exclude-module", "PIL", # Image processing (not used in server) + "--exclude-module", "Pillow", + "--exclude-module", "tiktoken" # Tokenizer (not used in server) ) if (Test-Path $RuntimeHookPath) { diff --git a/web/src/api/http.ts b/web/src/api/http.ts index 0566ee4..b584bca 100644 --- a/web/src/api/http.ts +++ b/web/src/api/http.ts @@ -6,8 +6,11 @@ const API_BASE = ''; // 相对路径 export class ApiError extends Error { - constructor(public status: number, message: string) { + public status: number; + + constructor(status: number, message: string) { super(message); + this.status = status; this.name = 'ApiError'; } } diff --git a/web/src/api/socket.ts b/web/src/api/socket.ts index 4748158..ddefe44 100644 --- a/web/src/api/socket.ts +++ b/web/src/api/socket.ts @@ -19,8 +19,11 @@ export class GameSocket { private reconnectTimer: number | null = null; private attempts = 0; private isIntentionalClose = false; + private options: SocketOptions; - constructor(private options: SocketOptions = {}) {} + constructor(options: SocketOptions = {}) { + this.options = options; + } public connect() { this.isIntentionalClose = false; diff --git a/web/src/components/game/Viewport.vue b/web/src/components/game/Viewport.vue index baf193a..1453907 100644 --- a/web/src/components/game/Viewport.vue +++ b/web/src/components/game/Viewport.vue @@ -72,10 +72,25 @@ function fitMap() { watch(() => [props.screenWidth, props.screenHeight], ([w, h]) => { if (viewport) { - // 窗口大小改变时,重新计算最小缩放值,防止用户看到黑边 - const fitScale = Math.min(w / props.worldWidth, h / props.worldHeight) - viewport.clampZoom({ minScale: fitScale * 0.8, maxScale: 4.0 }) + // 1. Resize Viewport 视口尺寸更新 viewport.resize(w, h, props.worldWidth, props.worldHeight) + + // 2. 重新计算适配比例 + const fitScale = Math.min(w / props.worldWidth, h / props.worldHeight) + + // 3. 设定缩放限制 + // 确保 maxScale 始终大于 minScale,防止地图极小时崩溃 + const minScale = fitScale * 0.8 + const maxScale = Math.max(4.0, minScale * 2.0) + + viewport.clampZoom({ minScale, maxScale }) + + // 4. 自动修正缩放 + // 如果当前缩放过小(导致黑边),或者因为初始化时的尺寸问题导致缩放不正确,强制恢复到适配大小 + if (viewport.scaled < minScale * 0.95) { + viewport.setZoom(fitScale) + viewport.moveCenter(props.worldWidth / 2, props.worldHeight / 2) + } } }) diff --git a/web/src/stores/ui.ts b/web/src/stores/ui.ts index 3017977..96551a2 100644 --- a/web/src/stores/ui.ts +++ b/web/src/stores/ui.ts @@ -1,8 +1,7 @@ import { defineStore } from 'pinia'; -import { ref, computed, watch } from 'vue'; +import { ref } from 'vue'; import { gameApi } from '../api/game'; import type { AvatarDetail, RegionDetail, HoverLine } from '../types/core'; -import { useWorldStore } from './world'; // Optional, if we need to cross-reference export type SelectionType = 'avatar' | 'region'; diff --git a/web/src/stores/world.ts b/web/src/stores/world.ts index 30c5761..537fa58 100644 --- a/web/src/stores/world.ts +++ b/web/src/stores/world.ts @@ -1,7 +1,7 @@ import { defineStore } from 'pinia'; import { ref, shallowRef, computed } from 'vue'; import type { AvatarSummary, GameEvent, MapMatrix, RegionSummary, CelestialPhenomenon } from '../types/core'; -import type { TickPayloadDTO, InitialStateDTO, MapResponseDTO } from '../types/api'; +import type { TickPayloadDTO } from '../types/api'; import { gameApi } from '../api/game'; export const useWorldStore = defineStore('world', () => { @@ -92,7 +92,7 @@ export const useWorldStore = defineStore('world', () => { // 检查并处理死亡事件,移除已死亡的角色 if (payload.events && Array.isArray(payload.events)) { - const deathEvents = payload.events.filter((e: any) => { + const deathEvents = (payload.events as any[]).filter((e: any) => { const c = e.content || ''; return c.includes('身亡') || c.includes('老死'); });