chore: 移除废弃的 SgsMapRenderer 组件
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,316 +0,0 @@
|
||||
<template>
|
||||
<view class="sgs-map-renderer">
|
||||
<view ref="containerRef" class="sgs-map-container"></view>
|
||||
|
||||
<view v-if="isLoading" class="sdk-state-overlay">
|
||||
<view class="sdk-state-card">
|
||||
<view class="loading-spinner"></view>
|
||||
<text class="sdk-state-title">正在连接 SGS 三维地图</text>
|
||||
<text class="sdk-state-desc">{{ statusMessage }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-else-if="loadError" class="sdk-state-overlay error-overlay">
|
||||
<view class="sdk-state-card error-card">
|
||||
<text class="sdk-state-title">SGS 地图加载失败</text>
|
||||
<text class="sdk-state-desc">{{ statusMessage }}</text>
|
||||
<view class="retry-btn" @tap="retryLoad">
|
||||
<text class="retry-text">重新连接</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
import {
|
||||
dataSourceConfig,
|
||||
getSgsMapTargetOrigin
|
||||
} from '@/config/dataSource'
|
||||
import { SgsMapService } from '@/services/sgs/SgsMapService'
|
||||
import {
|
||||
toAppFloorId,
|
||||
toErrorResult,
|
||||
toFloorLabel,
|
||||
toFocusedResult,
|
||||
toFocusNodeName,
|
||||
toNumericFloorId,
|
||||
type SgsTargetFocusRequest,
|
||||
type SgsTargetFocusResult
|
||||
} from '@/services/sgs/SgsMapEventAdapter'
|
||||
import type {
|
||||
SgsMapEvents
|
||||
} from '@/types/sgs-map-sdk'
|
||||
|
||||
interface FloorOption {
|
||||
id: string
|
||||
label: string
|
||||
}
|
||||
|
||||
type ContainerRef = HTMLElement | { $el?: HTMLElement } | null
|
||||
|
||||
type ViewMode = 'overview' | 'floor' | 'multi'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
initialFloorId?: string
|
||||
initialView?: ViewMode
|
||||
floors?: FloorOption[]
|
||||
targetFocus?: SgsTargetFocusRequest | null
|
||||
}>(), {
|
||||
initialFloorId: 'L1',
|
||||
initialView: 'floor',
|
||||
floors: () => [] as FloorOption[],
|
||||
targetFocus: null
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
floorChange: [floorId: string]
|
||||
poiClick: [poi: SgsMapEvents['poiClick']]
|
||||
targetFocus: [result: SgsTargetFocusResult]
|
||||
}>()
|
||||
|
||||
const containerRef = ref<ContainerRef>(null)
|
||||
const isLoading = ref(true)
|
||||
const loadError = ref(false)
|
||||
const statusMessage = ref('正在加载 SDK 脚本与地图基座...')
|
||||
|
||||
let service: SgsMapService | null = null
|
||||
let currentFocusRequestId: number | string | null = null
|
||||
|
||||
const getContainerElement = () => {
|
||||
const container = containerRef.value
|
||||
if (!container || typeof HTMLElement === 'undefined') return null
|
||||
if (container instanceof HTMLElement) return container
|
||||
|
||||
const element = '$el' in container ? container.$el : null
|
||||
return element instanceof HTMLElement ? element : null
|
||||
}
|
||||
|
||||
const disposeService = () => {
|
||||
service?.destroy()
|
||||
service = null
|
||||
}
|
||||
|
||||
const registerEvents = () => {
|
||||
service?.on('floorChanged', (payload) => {
|
||||
emit('floorChange', toAppFloorId(payload.floorId))
|
||||
})
|
||||
|
||||
service?.on('poiClick', (poi) => {
|
||||
emit('poiClick', poi)
|
||||
})
|
||||
|
||||
service?.on('loadError', (error) => {
|
||||
loadError.value = true
|
||||
isLoading.value = false
|
||||
statusMessage.value = error.detail || '地图基座 iframe 加载失败,请检查 VITE_SGS_H5_ENGINE_URL。'
|
||||
})
|
||||
|
||||
service?.on('error', (error) => {
|
||||
loadError.value = true
|
||||
isLoading.value = false
|
||||
statusMessage.value = error.message || error.code || 'SGS Map SDK 运行异常'
|
||||
})
|
||||
}
|
||||
|
||||
const initSdk = async () => {
|
||||
disposeService()
|
||||
isLoading.value = true
|
||||
loadError.value = false
|
||||
statusMessage.value = '正在加载 SDK 脚本与地图基座...'
|
||||
|
||||
await nextTick()
|
||||
const container = getContainerElement()
|
||||
if (!container) {
|
||||
isLoading.value = false
|
||||
loadError.value = true
|
||||
statusMessage.value = '未找到 SGS 地图容器。'
|
||||
return
|
||||
}
|
||||
|
||||
service = new SgsMapService({
|
||||
container,
|
||||
scriptUrl: dataSourceConfig.sgsSdkScriptUrl,
|
||||
sdkUrl: dataSourceConfig.sgsMapEngineUrl,
|
||||
targetOrigin: getSgsMapTargetOrigin(),
|
||||
floorId: toNumericFloorId(props.initialFloorId),
|
||||
timeout: dataSourceConfig.sgsSdkTimeoutMs
|
||||
})
|
||||
|
||||
registerEvents()
|
||||
|
||||
try {
|
||||
await service.init()
|
||||
isLoading.value = false
|
||||
loadError.value = false
|
||||
statusMessage.value = 'SGS 三维地图已连接。'
|
||||
|
||||
if (props.initialView === 'overview' || props.initialView === 'multi') {
|
||||
await service.resetView().catch(() => undefined)
|
||||
}
|
||||
|
||||
if (props.targetFocus) {
|
||||
await focusTargetPoi(props.targetFocus)
|
||||
}
|
||||
} catch (error) {
|
||||
isLoading.value = false
|
||||
loadError.value = true
|
||||
statusMessage.value = error instanceof Error ? error.message : 'SGS Map SDK 初始化失败。'
|
||||
}
|
||||
}
|
||||
|
||||
const switchFloor = async (floorId: string) => {
|
||||
try {
|
||||
await service?.changeFloor(toNumericFloorId(floorId))
|
||||
} catch (error) {
|
||||
loadError.value = true
|
||||
statusMessage.value = error instanceof Error ? error.message : `楼层切换失败:${toFloorLabel(floorId)}`
|
||||
}
|
||||
}
|
||||
|
||||
const focusTargetPoi = async (request: SgsTargetFocusRequest) => {
|
||||
if (currentFocusRequestId === request.requestId) return
|
||||
currentFocusRequestId = request.requestId
|
||||
|
||||
try {
|
||||
await switchFloor(request.floorId)
|
||||
await service?.focusTo(toFocusNodeName(request))
|
||||
emit('targetFocus', toFocusedResult(request))
|
||||
} catch (error) {
|
||||
emit('targetFocus', toErrorResult(request, error))
|
||||
}
|
||||
}
|
||||
|
||||
const showOverview = async () => {
|
||||
await service?.resetView().catch(() => undefined)
|
||||
}
|
||||
|
||||
const showMultiFloor = async () => {
|
||||
await service?.resetView().catch(() => undefined)
|
||||
}
|
||||
|
||||
const disableAutoSwitchTemporarily = () => {
|
||||
// SGS SDK does not expose the local zoom auto-switch contract.
|
||||
}
|
||||
|
||||
const retryLoad = () => {
|
||||
void initSdk()
|
||||
}
|
||||
|
||||
watch(() => props.targetFocus, (request) => {
|
||||
if (request && !isLoading.value && !loadError.value) {
|
||||
void focusTargetPoi(request)
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
void initSdk()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
disposeService()
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
switchFloor,
|
||||
showOverview,
|
||||
showMultiFloor,
|
||||
disableAutoSwitchTemporarily
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.sgs-map-renderer {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background: #eef2f0;
|
||||
}
|
||||
|
||||
.sgs-map-container {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.sdk-state-overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 4;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 24px;
|
||||
box-sizing: border-box;
|
||||
background: rgba(245, 247, 244, 0.82);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.sdk-state-card {
|
||||
width: min(280px, 100%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 18px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 14px;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border: 1px solid rgba(255, 255, 255, 0.8);
|
||||
box-shadow: 0 12px 30px rgba(24, 32, 21, 0.12);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.error-card {
|
||||
border-color: rgba(255, 122, 89, 0.28);
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: 3px solid rgba(31, 35, 41, 0.12);
|
||||
border-top-color: #1f2329;
|
||||
border-radius: 50%;
|
||||
animation: spin 0.8s linear infinite;
|
||||
}
|
||||
|
||||
.sdk-state-title {
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
font-weight: 700;
|
||||
color: #1f2329;
|
||||
}
|
||||
|
||||
.sdk-state-desc {
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
color: #626a73;
|
||||
}
|
||||
|
||||
.retry-btn {
|
||||
min-width: 96px;
|
||||
height: 34px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 14px;
|
||||
border-radius: 17px;
|
||||
background: #1f2329;
|
||||
}
|
||||
|
||||
.retry-text {
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user