This commit is contained in:
@@ -1,60 +0,0 @@
|
||||
import type {
|
||||
SgsMapSDKConstructor
|
||||
} from '@/types/sgs-map-sdk'
|
||||
|
||||
let loadingScriptUrl = ''
|
||||
let loadRequest: Promise<SgsMapSDKConstructor> | null = null
|
||||
|
||||
const findExistingScript = (scriptUrl: string) => (
|
||||
Array.from(document.scripts).find((script) => script.src.endsWith(scriptUrl) || script.getAttribute('src') === scriptUrl)
|
||||
)
|
||||
|
||||
export const loadSgsMapScript = (scriptUrl: string): Promise<SgsMapSDKConstructor> => {
|
||||
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
||||
return Promise.reject(new Error('SGS Map SDK 只能在 H5 浏览器环境中加载'))
|
||||
}
|
||||
|
||||
if (window.SGSMapSDK) {
|
||||
return Promise.resolve(window.SGSMapSDK)
|
||||
}
|
||||
|
||||
if (loadRequest && loadingScriptUrl === scriptUrl) {
|
||||
return loadRequest
|
||||
}
|
||||
|
||||
loadingScriptUrl = scriptUrl
|
||||
const request = new Promise<SgsMapSDKConstructor>((resolve, reject) => {
|
||||
const existingScript = findExistingScript(scriptUrl)
|
||||
const script = existingScript || document.createElement('script')
|
||||
|
||||
const resolveLoadedSdk = () => {
|
||||
if (!window.SGSMapSDK) {
|
||||
reject(new Error('SGS Map SDK 脚本已加载,但未发现 window.SGSMapSDK'))
|
||||
return
|
||||
}
|
||||
|
||||
resolve(window.SGSMapSDK)
|
||||
}
|
||||
|
||||
script.addEventListener('load', resolveLoadedSdk, { once: true })
|
||||
script.addEventListener('error', () => {
|
||||
reject(new Error(`SGS Map SDK 脚本加载失败: ${scriptUrl}`))
|
||||
}, { once: true })
|
||||
|
||||
if (!existingScript) {
|
||||
script.src = scriptUrl
|
||||
script.async = true
|
||||
document.head.appendChild(script)
|
||||
return
|
||||
}
|
||||
|
||||
if (window.SGSMapSDK) {
|
||||
resolveLoadedSdk()
|
||||
}
|
||||
}).finally(() => {
|
||||
loadRequest = null
|
||||
})
|
||||
|
||||
loadRequest = request
|
||||
return request
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
import type {
|
||||
SgsMapEvents,
|
||||
SgsMapSDKInstance,
|
||||
SgsMarkerConfig,
|
||||
SgsMapNode,
|
||||
SgsRouteOptions,
|
||||
SgsRouteResult
|
||||
} from '@/types/sgs-map-sdk'
|
||||
import {
|
||||
loadSgsMapScript
|
||||
} from './SgsMapScriptLoader'
|
||||
|
||||
interface SgsMapServiceOptions {
|
||||
container: HTMLElement
|
||||
scriptUrl: string
|
||||
sdkUrl: string
|
||||
targetOrigin: string
|
||||
floorId: string | number
|
||||
timeout: number
|
||||
}
|
||||
|
||||
type SgsMapListener<K extends keyof SgsMapEvents> = (payload: SgsMapEvents[K]) => void
|
||||
|
||||
export class SgsMapService {
|
||||
private sdk: SgsMapSDKInstance | null = null
|
||||
private readyPromise: Promise<SgsMapEvents['ready']> | null = null
|
||||
private resolveReady: ((payload: SgsMapEvents['ready']) => void) | null = null
|
||||
private rejectReady: ((error: Error) => void) | null = null
|
||||
private listeners: Array<() => void> = []
|
||||
private externalListeners: Array<{
|
||||
event: keyof SgsMapEvents
|
||||
listener: (payload: SgsMapEvents[keyof SgsMapEvents]) => void
|
||||
}> = []
|
||||
private disposed = false
|
||||
|
||||
constructor(private readonly options: SgsMapServiceOptions) {}
|
||||
|
||||
async init() {
|
||||
if (this.readyPromise) return this.readyPromise
|
||||
|
||||
this.readyPromise = new Promise<SgsMapEvents['ready']>((resolve, reject) => {
|
||||
this.resolveReady = resolve
|
||||
this.rejectReady = reject
|
||||
})
|
||||
|
||||
loadSgsMapScript(this.options.scriptUrl)
|
||||
.then((SDKConstructor) => {
|
||||
if (this.disposed) {
|
||||
this.rejectReady?.(new Error('SGS Map SDK 初始化已取消'))
|
||||
return
|
||||
}
|
||||
|
||||
this.sdk = new SDKConstructor({
|
||||
container: this.options.container,
|
||||
sdkUrl: this.options.sdkUrl,
|
||||
targetOrigin: this.options.targetOrigin,
|
||||
floorId: this.options.floorId,
|
||||
timeout: this.options.timeout
|
||||
})
|
||||
|
||||
this.externalListeners.forEach(({ event, listener }) => {
|
||||
this.registerSdkListener(event, listener)
|
||||
})
|
||||
|
||||
this.registerSdkListener('ready', (payload) => {
|
||||
this.resolveReady?.(payload)
|
||||
})
|
||||
|
||||
this.registerSdkListener('loadError', (payload) => {
|
||||
this.rejectReady?.(new Error(payload.detail || 'SGS Map SDK 地图基座加载失败'))
|
||||
})
|
||||
|
||||
this.registerSdkListener('error', (payload) => {
|
||||
if (!this.sdk?.getIsReady()) {
|
||||
this.rejectReady?.(new Error(payload.message || payload.code || 'SGS Map SDK 初始化失败'))
|
||||
}
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
this.rejectReady?.(error instanceof Error ? error : new Error('SGS Map SDK 初始化失败'))
|
||||
})
|
||||
|
||||
return this.readyPromise
|
||||
}
|
||||
|
||||
on<K extends keyof SgsMapEvents>(event: K, listener: SgsMapListener<K>) {
|
||||
this.externalListeners.push({
|
||||
event,
|
||||
listener: listener as (payload: SgsMapEvents[keyof SgsMapEvents]) => void
|
||||
})
|
||||
|
||||
if (this.sdk) {
|
||||
this.registerSdkListener(event, listener)
|
||||
}
|
||||
}
|
||||
|
||||
private registerSdkListener<K extends keyof SgsMapEvents>(event: K, listener: SgsMapListener<K>) {
|
||||
if (!this.sdk) return
|
||||
|
||||
this.sdk.on(event, listener)
|
||||
this.listeners.push(() => {
|
||||
this.sdk?.off(event, listener)
|
||||
})
|
||||
}
|
||||
|
||||
private async getReadySdk() {
|
||||
if (!this.sdk) {
|
||||
await this.init()
|
||||
}
|
||||
|
||||
await this.readyPromise
|
||||
|
||||
if (!this.sdk || this.disposed) {
|
||||
throw new Error('SGS Map SDK 已销毁')
|
||||
}
|
||||
|
||||
return this.sdk
|
||||
}
|
||||
|
||||
async changeFloor(floorId: string | number, options?: { forceReload?: boolean }) {
|
||||
const sdk = await this.getReadySdk()
|
||||
return sdk.changeFloor(floorId, this.options.timeout, options)
|
||||
}
|
||||
|
||||
async focusTo(node: SgsMapNode | string) {
|
||||
const sdk = await this.getReadySdk()
|
||||
sdk.focusTo(node)
|
||||
}
|
||||
|
||||
async addMarker(config: SgsMarkerConfig) {
|
||||
const sdk = await this.getReadySdk()
|
||||
sdk.addMarker(config)
|
||||
}
|
||||
|
||||
async clearMarkers() {
|
||||
const sdk = await this.getReadySdk()
|
||||
sdk.clearMarkers()
|
||||
}
|
||||
|
||||
async resetView() {
|
||||
const sdk = await this.getReadySdk()
|
||||
return sdk.resetView(this.options.timeout)
|
||||
}
|
||||
|
||||
async setViewMode(mode: '2d' | '3d') {
|
||||
const sdk = await this.getReadySdk()
|
||||
return sdk.setViewMode(mode, this.options.timeout)
|
||||
}
|
||||
|
||||
async planRoute(from: SgsMapNode | string, to: SgsMapNode | string, options?: SgsRouteOptions): Promise<SgsRouteResult> {
|
||||
const sdk = await this.getReadySdk()
|
||||
return sdk.planRoute(from, to, options, this.options.timeout)
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.disposed = true
|
||||
this.listeners.splice(0).forEach((cleanup) => cleanup())
|
||||
this.sdk?.destroy()
|
||||
this.sdk = null
|
||||
this.rejectReady?.(new Error('SGS Map SDK 已销毁'))
|
||||
this.resolveReady = null
|
||||
this.rejectReady = null
|
||||
this.readyPromise = null
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user