my-openlayer 1.0.14 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,529 +1,529 @@
1
- import Overlay from 'ol/Overlay';
2
- import { VueTemplatePointState } from '../types';
3
- import { ErrorHandler, ErrorType } from '../utils/ErrorHandler';
4
- import { ValidationUtils } from '../utils/ValidationUtils';
5
- // 动态导入Vue
6
- let Vue = null;
7
- let isVue3 = false;
8
- // 检测Vue版本并导入
9
- async function detectAndImportVue() {
10
- try {
11
- // 尝试动态导入Vue
12
- const vueModule = await import('vue');
13
- Vue = vueModule.default || vueModule;
14
- // 检测Vue版本
15
- if (Vue && (Vue.version?.startsWith('3') || Vue.createApp)) {
16
- isVue3 = true;
17
- }
18
- else {
19
- isVue3 = false;
20
- }
21
- }
22
- catch (e) {
23
- console.warn('Vue not found. Please ensure Vue is installed in your project.');
24
- Vue = null;
25
- }
26
- }
27
- // 同步版本的Vue检测(用于兼容性)
28
- function detectVueSync() {
29
- try {
30
- // 尝试从全局对象获取Vue
31
- if (typeof window !== 'undefined' && window.Vue) {
32
- Vue = window.Vue;
33
- isVue3 = !!(Vue.version?.startsWith('3') || Vue.createApp);
34
- return;
35
- }
36
- // 如果在Node.js环境中,尝试require
37
- if (typeof window === 'undefined') {
38
- try {
39
- // 使用eval来避免TypeScript编译时的require检查
40
- const requireFunc = eval('require');
41
- Vue = requireFunc('vue');
42
- isVue3 = !!(Vue.version?.startsWith('3') || Vue.createApp);
43
- }
44
- catch (e) {
45
- console.warn('Vue not found. Please ensure Vue is installed in your project.');
46
- Vue = null;
47
- }
48
- }
49
- }
50
- catch (e) {
51
- console.warn('Failed to detect Vue:', e);
52
- }
53
- }
54
- // 初始化Vue导入
55
- detectVueSync();
56
- if (!Vue) {
57
- detectAndImportVue();
58
- }
59
- /**
60
- * Vue模板点位管理类
61
- * 用于在地图上添加和管理Vue组件覆盖物
62
- */
63
- export default class VueTemplatePoint {
64
- /**
65
- * 构造函数
66
- * @param map OpenLayers地图实例
67
- */
68
- constructor(map) {
69
- this.vuePoints = new Map();
70
- ValidationUtils.validateRequired(map, 'Map instance is required');
71
- this.map = map;
72
- this.errorHandler = ErrorHandler.getInstance();
73
- }
74
- /**
75
- * 添加Vue模板点位
76
- * @param pointDataList 点位数据列表
77
- * @param template Vue模板
78
- * @param options 可选配置项
79
- * @returns 点位控制器
80
- */
81
- addVueTemplatePoint(pointDataList, template, options) {
82
- if (!pointDataList || !Array.isArray(pointDataList) || pointDataList.length === 0) {
83
- throw new Error('Valid point info list is required');
84
- }
85
- if (!template) {
86
- throw new Error('Vue template is required');
87
- }
88
- try {
89
- const instances = [];
90
- pointDataList.forEach((pointData) => {
91
- if (!ValidationUtils.validateLngLat(pointData.lgtd, pointData.lttd)) {
92
- throw new Error('Valid longitude and latitude are required for each point');
93
- }
94
- const pointOptions = {
95
- Template: template,
96
- lgtd: pointData.lgtd,
97
- lttd: pointData.lttd,
98
- props: {
99
- pointData: {
100
- type: Object,
101
- default: pointData
102
- }
103
- },
104
- positioning: options?.positioning,
105
- stopEvent: options?.stopEvent,
106
- };
107
- const instance = new VueTemplatePointInstanceImpl(this.map, pointOptions, this.errorHandler);
108
- instances.push(instance);
109
- this.vuePoints.set(instance.id, instance);
110
- });
111
- return {
112
- setVisible: (visible) => {
113
- instances.forEach((instance) => {
114
- instance.setVisible(visible);
115
- });
116
- },
117
- remove: () => {
118
- instances.forEach((instance) => {
119
- instance.remove();
120
- this.vuePoints.delete(instance.id);
121
- });
122
- },
123
- getPoints: () => instances
124
- };
125
- }
126
- catch (error) {
127
- throw new Error(`Failed to create Vue template points: ${error}`);
128
- }
129
- }
130
- /**
131
- * 根据ID获取点位实例
132
- * @param id 点位ID
133
- * @returns 点位实例或undefined
134
- */
135
- getPointById(id) {
136
- return this.vuePoints.get(id);
137
- }
138
- /**
139
- * 获取所有点位实例
140
- * @returns 所有点位实例数组
141
- */
142
- getAllPoints() {
143
- return Array.from(this.vuePoints.values());
144
- }
145
- /**
146
- * 移除所有点位
147
- */
148
- removeAllPoints() {
149
- this.vuePoints.forEach((instance) => {
150
- instance.remove();
151
- });
152
- this.vuePoints.clear();
153
- }
154
- /**
155
- * 获取点位数量
156
- * @returns 点位数量
157
- */
158
- getPointCount() {
159
- return this.vuePoints.size;
160
- }
161
- }
162
- /**
163
- * Vue模板点位实例实现类
164
- * @internal
165
- */
166
- class VueTemplatePointInstanceImpl {
167
- constructor(map, options, errorHandler) {
168
- this.app = null;
169
- this.state = VueTemplatePointState.CREATED;
170
- this.map = map;
171
- this.errorHandler = errorHandler;
172
- this.options = this.mergeDefaultOptions(options);
173
- this.id = this.generateUniqueId();
174
- this.position = [this.options.lgtd, this.options.lttd];
175
- try {
176
- // 参数验证
177
- this.validateConstructorParams(map, options);
178
- // 创建DOM元素
179
- this.dom = this.createDomElement();
180
- // 创建Vue应用实例
181
- this.createVueApp();
182
- // 创建覆盖层
183
- this.anchor = this.createOverlay();
184
- // 添加到地图
185
- this.map.addOverlay(this.anchor);
186
- // 设置初始状态
187
- this.state = VueTemplatePointState.MOUNTED;
188
- this.setVisible(this.options.visible ?? true);
189
- }
190
- catch (error) {
191
- this.handleError('Failed to create Vue template point', error, { map, options });
192
- throw error;
193
- }
194
- }
195
- /**
196
- * 验证构造函数参数
197
- * @param map 地图实例
198
- * @param options 配置选项
199
- * @private
200
- */
201
- validateConstructorParams(map, options) {
202
- ValidationUtils.validateRequired(map, 'Map instance is required');
203
- ValidationUtils.validateRequired(options, 'Options are required');
204
- const { Template, lgtd, lttd } = options;
205
- ValidationUtils.validateRequired(Template, 'Template is required in options');
206
- if (typeof lgtd !== 'number' || typeof lttd !== 'number') {
207
- throw new Error('Longitude and lttd must be numbers');
208
- }
209
- ValidationUtils.validateCoordinate(lgtd, lttd);
210
- }
211
- /**
212
- * 合并默认配置选项
213
- * @param options 用户配置选项
214
- * @returns 合并后的配置选项
215
- * @private
216
- */
217
- mergeDefaultOptions(options) {
218
- return {
219
- positioning: 'center-center',
220
- stopEvent: false,
221
- visible: true,
222
- zIndex: 1,
223
- ...options
224
- };
225
- }
226
- /**
227
- * 生成唯一ID
228
- * @returns 唯一标识符
229
- * @private
230
- */
231
- generateUniqueId() {
232
- return `dom-point-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
233
- }
234
- /**
235
- * 创建DOM元素
236
- * @returns DOM元素
237
- * @private
238
- */
239
- createDomElement() {
240
- const element = document.createElement('div');
241
- element.id = this.id;
242
- if (this.options.className) {
243
- element.className = this.options.className;
244
- }
245
- if (this.options.zIndex) {
246
- element.style.zIndex = this.options.zIndex.toString();
247
- }
248
- return element;
249
- }
250
- /**
251
- * 创建Vue应用实例
252
- * @private
253
- */
254
- createVueApp() {
255
- const { Template, props } = this.options;
256
- if (!Vue) {
257
- throw new Error('Vue is not available. Please ensure Vue is installed in your project.');
258
- }
259
- try {
260
- if (isVue3) {
261
- // Vue 3
262
- this.app = Vue.createApp({
263
- ...Template,
264
- props: props || {}
265
- });
266
- this.app.mount(this.dom);
267
- }
268
- else {
269
- // Vue 2
270
- this.app = new Vue({
271
- el: this.dom,
272
- render: (h) => h(Template, { props: props || {} })
273
- });
274
- }
275
- }
276
- catch (error) {
277
- throw new Error(`Failed to create Vue app: ${error}`);
278
- }
279
- }
280
- /**
281
- * 创建覆盖层
282
- * @returns 覆盖层实例
283
- * @private
284
- */
285
- createOverlay() {
286
- const overlay = new Overlay({
287
- element: this.dom,
288
- positioning: this.options.positioning || 'center-center',
289
- stopEvent: this.options.stopEvent || false
290
- });
291
- overlay.setPosition(this.position);
292
- return overlay;
293
- }
294
- /**
295
- * 错误处理
296
- * @param message 错误消息
297
- * @param error 原始错误
298
- * @param context 错误上下文
299
- * @private
300
- */
301
- handleError(message, error, context) {
302
- this.errorHandler.createAndHandleError(`${message}: ${error}`, ErrorType.COMPONENT_ERROR, { ...context, domPointId: this.id });
303
- }
304
- /**
305
- * 设置可见性
306
- * @param visible 是否可见
307
- * @throws 当操作失败时抛出错误
308
- */
309
- setVisible(visible) {
310
- if (this.state === VueTemplatePointState.DESTROYED) {
311
- throw new Error('Cannot set visibility on destroyed DOM point');
312
- }
313
- ValidationUtils.validateType(visible, 'boolean', 'Visible parameter must be a boolean');
314
- try {
315
- this.dom.style.visibility = visible ? 'visible' : 'hidden';
316
- this.state = visible ? VueTemplatePointState.VISIBLE : VueTemplatePointState.HIDDEN;
317
- }
318
- catch (error) {
319
- this.handleError('Failed to set visibility', error, { visible });
320
- throw error;
321
- }
322
- }
323
- /**
324
- * 获取当前可见性状态
325
- * @returns 是否可见
326
- */
327
- isVisible() {
328
- return this.state === VueTemplatePointState.VISIBLE;
329
- }
330
- /**
331
- * 更新位置
332
- * @param lgtd 新经度
333
- * @param lttd 新纬度
334
- * @throws 当操作失败时抛出错误
335
- */
336
- updatePosition(lgtd, lttd) {
337
- if (this.state === VueTemplatePointState.DESTROYED) {
338
- throw new Error('Cannot update position on destroyed DOM point');
339
- }
340
- ValidationUtils.validateCoordinate(lgtd, lttd);
341
- try {
342
- this.position = [lgtd, lttd];
343
- this.anchor.setPosition(this.position);
344
- }
345
- catch (error) {
346
- this.handleError('Failed to update position', error, { lgtd, lttd });
347
- throw error;
348
- }
349
- }
350
- /**
351
- * 获取当前位置
352
- * @returns 当前坐标位置
353
- */
354
- getPosition() {
355
- return [...this.position];
356
- }
357
- /**
358
- * 更新组件属性
359
- * @param newProps 新的属性对象
360
- * @throws 当操作失败时抛出错误
361
- */
362
- updateProps(newProps) {
363
- if (this.state === VueTemplatePointState.DESTROYED) {
364
- throw new Error('Cannot update props on destroyed DOM point');
365
- }
366
- try {
367
- // 重新创建Vue应用实例
368
- this.destroyVueApp();
369
- this.options.props = { ...this.options.props, ...newProps };
370
- this.createVueApp();
371
- }
372
- catch (error) {
373
- this.handleError('Failed to update props', error, { newProps });
374
- throw error;
375
- }
376
- }
377
- /**
378
- * 设置CSS样式
379
- * @param styles 样式对象
380
- * @throws 当操作失败时抛出错误
381
- */
382
- setStyle(styles) {
383
- if (this.state === VueTemplatePointState.DESTROYED) {
384
- throw new Error('Cannot set style on destroyed DOM point');
385
- }
386
- try {
387
- Object.assign(this.dom.style, styles);
388
- }
389
- catch (error) {
390
- this.handleError('Failed to set style', error, { styles });
391
- throw error;
392
- }
393
- }
394
- /**
395
- * 添加CSS类名
396
- * @param className 要添加的类名
397
- * @throws 当操作失败时抛出错误
398
- */
399
- addClass(className) {
400
- if (this.state === VueTemplatePointState.DESTROYED) {
401
- throw new Error('Cannot add class to destroyed DOM point');
402
- }
403
- ValidationUtils.validateNonEmptyString(className, 'Valid class name is required');
404
- try {
405
- this.dom.classList.add(className);
406
- }
407
- catch (error) {
408
- this.handleError('Failed to add class', error, { className });
409
- throw error;
410
- }
411
- }
412
- /**
413
- * 移除CSS类名
414
- * @param className 要移除的类名
415
- * @throws 当操作失败时抛出错误
416
- */
417
- removeClass(className) {
418
- if (this.state === VueTemplatePointState.DESTROYED) {
419
- throw new Error('Cannot remove class from destroyed DOM point');
420
- }
421
- ValidationUtils.validateNonEmptyString(className, 'Valid class name is required');
422
- try {
423
- this.dom.classList.remove(className);
424
- }
425
- catch (error) {
426
- this.handleError('Failed to remove class', error, { className });
427
- throw error;
428
- }
429
- }
430
- /**
431
- * 销毁Vue应用实例
432
- * @private
433
- */
434
- destroyVueApp() {
435
- if (this.app) {
436
- try {
437
- if (isVue3) {
438
- // Vue 3: 使用 unmount
439
- this.app.unmount();
440
- }
441
- else {
442
- // Vue 2: 使用 $destroy
443
- this.app.$destroy();
444
- }
445
- }
446
- catch (error) {
447
- this.handleError('Failed to destroy Vue app', error);
448
- }
449
- finally {
450
- this.app = null;
451
- }
452
- }
453
- }
454
- /**
455
- * 移除点位
456
- * @throws 当移除失败时抛出错误
457
- */
458
- remove() {
459
- if (this.state === VueTemplatePointState.DESTROYED) {
460
- console.warn('DOM point already destroyed');
461
- return;
462
- }
463
- try {
464
- // 销毁Vue应用实例
465
- this.destroyVueApp();
466
- // 从地图移除覆盖层
467
- this.map.removeOverlay(this.anchor);
468
- // 清理DOM元素
469
- if (this.dom && this.dom.parentNode) {
470
- this.dom.parentNode.removeChild(this.dom);
471
- }
472
- // 更新状态
473
- this.state = VueTemplatePointState.DESTROYED;
474
- }
475
- catch (error) {
476
- this.handleError('Failed to remove DOM point', error);
477
- throw error;
478
- }
479
- }
480
- /**
481
- * 获取覆盖层
482
- * @returns 覆盖层实例
483
- */
484
- getOverlay() {
485
- return this.anchor;
486
- }
487
- /**
488
- * 获取点位ID
489
- * @returns 点位唯一标识符
490
- */
491
- getId() {
492
- return this.id;
493
- }
494
- /**
495
- * 获取DOM元素
496
- * @returns DOM元素
497
- */
498
- getDomElement() {
499
- return this.dom;
500
- }
501
- /**
502
- * 获取当前状态
503
- * @returns 当前状态
504
- */
505
- getState() {
506
- return this.state;
507
- }
508
- /**
509
- * 获取配置选项
510
- * @returns 配置选项的副本
511
- */
512
- getOptions() {
513
- return Object.freeze({ ...this.options });
514
- }
515
- /**
516
- * 检查是否已销毁
517
- * @returns 是否已销毁
518
- */
519
- isDestroyed() {
520
- return this.state === VueTemplatePointState.DESTROYED;
521
- }
522
- /**
523
- * 获取地图实例
524
- * @returns 地图实例
525
- */
526
- getMap() {
527
- return this.map;
528
- }
529
- }
1
+ import Overlay from 'ol/Overlay';
2
+ import { VueTemplatePointState } from '../types';
3
+ import { ErrorHandler, ErrorType } from '../utils/ErrorHandler';
4
+ import { ValidationUtils } from '../utils/ValidationUtils';
5
+ // 动态导入Vue
6
+ let Vue = null;
7
+ let isVue3 = false;
8
+ // 检测Vue版本并导入
9
+ async function detectAndImportVue() {
10
+ try {
11
+ // 尝试动态导入Vue
12
+ const vueModule = await import('vue');
13
+ Vue = vueModule.default || vueModule;
14
+ // 检测Vue版本
15
+ if (Vue && (Vue.version?.startsWith('3') || Vue.createApp)) {
16
+ isVue3 = true;
17
+ }
18
+ else {
19
+ isVue3 = false;
20
+ }
21
+ }
22
+ catch (e) {
23
+ console.warn('Vue not found. Please ensure Vue is installed in your project.');
24
+ Vue = null;
25
+ }
26
+ }
27
+ // 同步版本的Vue检测(用于兼容性)
28
+ function detectVueSync() {
29
+ try {
30
+ // 尝试从全局对象获取Vue
31
+ if (typeof window !== 'undefined' && window.Vue) {
32
+ Vue = window.Vue;
33
+ isVue3 = !!(Vue.version?.startsWith('3') || Vue.createApp);
34
+ return;
35
+ }
36
+ // 如果在Node.js环境中,尝试require
37
+ if (typeof window === 'undefined') {
38
+ try {
39
+ // 使用eval来避免TypeScript编译时的require检查
40
+ const requireFunc = eval('require');
41
+ Vue = requireFunc('vue');
42
+ isVue3 = !!(Vue.version?.startsWith('3') || Vue.createApp);
43
+ }
44
+ catch (e) {
45
+ console.warn('Vue not found. Please ensure Vue is installed in your project.');
46
+ Vue = null;
47
+ }
48
+ }
49
+ }
50
+ catch (e) {
51
+ console.warn('Failed to detect Vue:', e);
52
+ }
53
+ }
54
+ // 初始化Vue导入
55
+ detectVueSync();
56
+ if (!Vue) {
57
+ detectAndImportVue();
58
+ }
59
+ /**
60
+ * Vue模板点位管理类
61
+ * 用于在地图上添加和管理Vue组件覆盖物
62
+ */
63
+ export default class VueTemplatePoint {
64
+ /**
65
+ * 构造函数
66
+ * @param map OpenLayers地图实例
67
+ */
68
+ constructor(map) {
69
+ this.vuePoints = new Map();
70
+ ValidationUtils.validateRequired(map, 'Map instance is required');
71
+ this.map = map;
72
+ this.errorHandler = ErrorHandler.getInstance();
73
+ }
74
+ /**
75
+ * 添加Vue模板点位
76
+ * @param pointDataList 点位数据列表
77
+ * @param template Vue模板
78
+ * @param options 可选配置项
79
+ * @returns 点位控制器
80
+ */
81
+ addVueTemplatePoint(pointDataList, template, options) {
82
+ if (!pointDataList || !Array.isArray(pointDataList) || pointDataList.length === 0) {
83
+ throw new Error('Valid point info list is required');
84
+ }
85
+ if (!template) {
86
+ throw new Error('Vue template is required');
87
+ }
88
+ try {
89
+ const instances = [];
90
+ pointDataList.forEach((pointData) => {
91
+ if (!ValidationUtils.validateLngLat(pointData.lgtd, pointData.lttd)) {
92
+ throw new Error('Valid longitude and latitude are required for each point');
93
+ }
94
+ const pointOptions = {
95
+ Template: template,
96
+ lgtd: pointData.lgtd,
97
+ lttd: pointData.lttd,
98
+ props: {
99
+ pointData: {
100
+ type: Object,
101
+ default: pointData
102
+ }
103
+ },
104
+ positioning: options?.positioning,
105
+ stopEvent: options?.stopEvent,
106
+ };
107
+ const instance = new VueTemplatePointInstanceImpl(this.map, pointOptions, this.errorHandler);
108
+ instances.push(instance);
109
+ this.vuePoints.set(instance.id, instance);
110
+ });
111
+ return {
112
+ setVisible: (visible) => {
113
+ instances.forEach((instance) => {
114
+ instance.setVisible(visible);
115
+ });
116
+ },
117
+ remove: () => {
118
+ instances.forEach((instance) => {
119
+ instance.remove();
120
+ this.vuePoints.delete(instance.id);
121
+ });
122
+ },
123
+ getPoints: () => instances
124
+ };
125
+ }
126
+ catch (error) {
127
+ throw new Error(`Failed to create Vue template points: ${error}`);
128
+ }
129
+ }
130
+ /**
131
+ * 根据ID获取点位实例
132
+ * @param id 点位ID
133
+ * @returns 点位实例或undefined
134
+ */
135
+ getPointById(id) {
136
+ return this.vuePoints.get(id);
137
+ }
138
+ /**
139
+ * 获取所有点位实例
140
+ * @returns 所有点位实例数组
141
+ */
142
+ getAllPoints() {
143
+ return Array.from(this.vuePoints.values());
144
+ }
145
+ /**
146
+ * 移除所有点位
147
+ */
148
+ removeAllPoints() {
149
+ this.vuePoints.forEach((instance) => {
150
+ instance.remove();
151
+ });
152
+ this.vuePoints.clear();
153
+ }
154
+ /**
155
+ * 获取点位数量
156
+ * @returns 点位数量
157
+ */
158
+ getPointCount() {
159
+ return this.vuePoints.size;
160
+ }
161
+ }
162
+ /**
163
+ * Vue模板点位实例实现类
164
+ * @internal
165
+ */
166
+ class VueTemplatePointInstanceImpl {
167
+ constructor(map, options, errorHandler) {
168
+ this.app = null;
169
+ this.state = VueTemplatePointState.CREATED;
170
+ this.map = map;
171
+ this.errorHandler = errorHandler;
172
+ this.options = this.mergeDefaultOptions(options);
173
+ this.id = this.generateUniqueId();
174
+ this.position = [this.options.lgtd, this.options.lttd];
175
+ try {
176
+ // 参数验证
177
+ this.validateConstructorParams(map, options);
178
+ // 创建DOM元素
179
+ this.dom = this.createDomElement();
180
+ // 创建Vue应用实例
181
+ this.createVueApp();
182
+ // 创建覆盖层
183
+ this.anchor = this.createOverlay();
184
+ // 添加到地图
185
+ this.map.addOverlay(this.anchor);
186
+ // 设置初始状态
187
+ this.state = VueTemplatePointState.MOUNTED;
188
+ this.setVisible(this.options.visible ?? true);
189
+ }
190
+ catch (error) {
191
+ this.handleError('Failed to create Vue template point', error, { map, options });
192
+ throw error;
193
+ }
194
+ }
195
+ /**
196
+ * 验证构造函数参数
197
+ * @param map 地图实例
198
+ * @param options 配置选项
199
+ * @private
200
+ */
201
+ validateConstructorParams(map, options) {
202
+ ValidationUtils.validateRequired(map, 'Map instance is required');
203
+ ValidationUtils.validateRequired(options, 'Options are required');
204
+ const { Template, lgtd, lttd } = options;
205
+ ValidationUtils.validateRequired(Template, 'Template is required in options');
206
+ if (typeof lgtd !== 'number' || typeof lttd !== 'number') {
207
+ throw new Error('Longitude and lttd must be numbers');
208
+ }
209
+ ValidationUtils.validateCoordinate(lgtd, lttd);
210
+ }
211
+ /**
212
+ * 合并默认配置选项
213
+ * @param options 用户配置选项
214
+ * @returns 合并后的配置选项
215
+ * @private
216
+ */
217
+ mergeDefaultOptions(options) {
218
+ return {
219
+ positioning: 'center-center',
220
+ stopEvent: false,
221
+ visible: true,
222
+ zIndex: 1,
223
+ ...options
224
+ };
225
+ }
226
+ /**
227
+ * 生成唯一ID
228
+ * @returns 唯一标识符
229
+ * @private
230
+ */
231
+ generateUniqueId() {
232
+ return `dom-point-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
233
+ }
234
+ /**
235
+ * 创建DOM元素
236
+ * @returns DOM元素
237
+ * @private
238
+ */
239
+ createDomElement() {
240
+ const element = document.createElement('div');
241
+ element.id = this.id;
242
+ if (this.options.className) {
243
+ element.className = this.options.className;
244
+ }
245
+ if (this.options.zIndex) {
246
+ element.style.zIndex = this.options.zIndex.toString();
247
+ }
248
+ return element;
249
+ }
250
+ /**
251
+ * 创建Vue应用实例
252
+ * @private
253
+ */
254
+ createVueApp() {
255
+ const { Template, props } = this.options;
256
+ if (!Vue) {
257
+ throw new Error('Vue is not available. Please ensure Vue is installed in your project.');
258
+ }
259
+ try {
260
+ if (isVue3) {
261
+ // Vue 3
262
+ this.app = Vue.createApp({
263
+ ...Template,
264
+ props: props || {}
265
+ });
266
+ this.app.mount(this.dom);
267
+ }
268
+ else {
269
+ // Vue 2
270
+ this.app = new Vue({
271
+ el: this.dom,
272
+ render: (h) => h(Template, { props: props || {} })
273
+ });
274
+ }
275
+ }
276
+ catch (error) {
277
+ throw new Error(`Failed to create Vue app: ${error}`);
278
+ }
279
+ }
280
+ /**
281
+ * 创建覆盖层
282
+ * @returns 覆盖层实例
283
+ * @private
284
+ */
285
+ createOverlay() {
286
+ const overlay = new Overlay({
287
+ element: this.dom,
288
+ positioning: this.options.positioning || 'center-center',
289
+ stopEvent: this.options.stopEvent || false
290
+ });
291
+ overlay.setPosition(this.position);
292
+ return overlay;
293
+ }
294
+ /**
295
+ * 错误处理
296
+ * @param message 错误消息
297
+ * @param error 原始错误
298
+ * @param context 错误上下文
299
+ * @private
300
+ */
301
+ handleError(message, error, context) {
302
+ this.errorHandler.createAndHandleError(`${message}: ${error}`, ErrorType.COMPONENT_ERROR, { ...context, domPointId: this.id });
303
+ }
304
+ /**
305
+ * 设置可见性
306
+ * @param visible 是否可见
307
+ * @throws 当操作失败时抛出错误
308
+ */
309
+ setVisible(visible) {
310
+ if (this.state === VueTemplatePointState.DESTROYED) {
311
+ throw new Error('Cannot set visibility on destroyed DOM point');
312
+ }
313
+ ValidationUtils.validateType(visible, 'boolean', 'Visible parameter must be a boolean');
314
+ try {
315
+ this.dom.style.visibility = visible ? 'visible' : 'hidden';
316
+ this.state = visible ? VueTemplatePointState.VISIBLE : VueTemplatePointState.HIDDEN;
317
+ }
318
+ catch (error) {
319
+ this.handleError('Failed to set visibility', error, { visible });
320
+ throw error;
321
+ }
322
+ }
323
+ /**
324
+ * 获取当前可见性状态
325
+ * @returns 是否可见
326
+ */
327
+ isVisible() {
328
+ return this.state === VueTemplatePointState.VISIBLE;
329
+ }
330
+ /**
331
+ * 更新位置
332
+ * @param lgtd 新经度
333
+ * @param lttd 新纬度
334
+ * @throws 当操作失败时抛出错误
335
+ */
336
+ updatePosition(lgtd, lttd) {
337
+ if (this.state === VueTemplatePointState.DESTROYED) {
338
+ throw new Error('Cannot update position on destroyed DOM point');
339
+ }
340
+ ValidationUtils.validateCoordinate(lgtd, lttd);
341
+ try {
342
+ this.position = [lgtd, lttd];
343
+ this.anchor.setPosition(this.position);
344
+ }
345
+ catch (error) {
346
+ this.handleError('Failed to update position', error, { lgtd, lttd });
347
+ throw error;
348
+ }
349
+ }
350
+ /**
351
+ * 获取当前位置
352
+ * @returns 当前坐标位置
353
+ */
354
+ getPosition() {
355
+ return [...this.position];
356
+ }
357
+ /**
358
+ * 更新组件属性
359
+ * @param newProps 新的属性对象
360
+ * @throws 当操作失败时抛出错误
361
+ */
362
+ updateProps(newProps) {
363
+ if (this.state === VueTemplatePointState.DESTROYED) {
364
+ throw new Error('Cannot update props on destroyed DOM point');
365
+ }
366
+ try {
367
+ // 重新创建Vue应用实例
368
+ this.destroyVueApp();
369
+ this.options.props = { ...this.options.props, ...newProps };
370
+ this.createVueApp();
371
+ }
372
+ catch (error) {
373
+ this.handleError('Failed to update props', error, { newProps });
374
+ throw error;
375
+ }
376
+ }
377
+ /**
378
+ * 设置CSS样式
379
+ * @param styles 样式对象
380
+ * @throws 当操作失败时抛出错误
381
+ */
382
+ setStyle(styles) {
383
+ if (this.state === VueTemplatePointState.DESTROYED) {
384
+ throw new Error('Cannot set style on destroyed DOM point');
385
+ }
386
+ try {
387
+ Object.assign(this.dom.style, styles);
388
+ }
389
+ catch (error) {
390
+ this.handleError('Failed to set style', error, { styles });
391
+ throw error;
392
+ }
393
+ }
394
+ /**
395
+ * 添加CSS类名
396
+ * @param className 要添加的类名
397
+ * @throws 当操作失败时抛出错误
398
+ */
399
+ addClass(className) {
400
+ if (this.state === VueTemplatePointState.DESTROYED) {
401
+ throw new Error('Cannot add class to destroyed DOM point');
402
+ }
403
+ ValidationUtils.validateNonEmptyString(className, 'Valid class name is required');
404
+ try {
405
+ this.dom.classList.add(className);
406
+ }
407
+ catch (error) {
408
+ this.handleError('Failed to add class', error, { className });
409
+ throw error;
410
+ }
411
+ }
412
+ /**
413
+ * 移除CSS类名
414
+ * @param className 要移除的类名
415
+ * @throws 当操作失败时抛出错误
416
+ */
417
+ removeClass(className) {
418
+ if (this.state === VueTemplatePointState.DESTROYED) {
419
+ throw new Error('Cannot remove class from destroyed DOM point');
420
+ }
421
+ ValidationUtils.validateNonEmptyString(className, 'Valid class name is required');
422
+ try {
423
+ this.dom.classList.remove(className);
424
+ }
425
+ catch (error) {
426
+ this.handleError('Failed to remove class', error, { className });
427
+ throw error;
428
+ }
429
+ }
430
+ /**
431
+ * 销毁Vue应用实例
432
+ * @private
433
+ */
434
+ destroyVueApp() {
435
+ if (this.app) {
436
+ try {
437
+ if (isVue3) {
438
+ // Vue 3: 使用 unmount
439
+ this.app.unmount();
440
+ }
441
+ else {
442
+ // Vue 2: 使用 $destroy
443
+ this.app.$destroy();
444
+ }
445
+ }
446
+ catch (error) {
447
+ this.handleError('Failed to destroy Vue app', error);
448
+ }
449
+ finally {
450
+ this.app = null;
451
+ }
452
+ }
453
+ }
454
+ /**
455
+ * 移除点位
456
+ * @throws 当移除失败时抛出错误
457
+ */
458
+ remove() {
459
+ if (this.state === VueTemplatePointState.DESTROYED) {
460
+ console.warn('DOM point already destroyed');
461
+ return;
462
+ }
463
+ try {
464
+ // 销毁Vue应用实例
465
+ this.destroyVueApp();
466
+ // 从地图移除覆盖层
467
+ this.map.removeOverlay(this.anchor);
468
+ // 清理DOM元素
469
+ if (this.dom && this.dom.parentNode) {
470
+ this.dom.parentNode.removeChild(this.dom);
471
+ }
472
+ // 更新状态
473
+ this.state = VueTemplatePointState.DESTROYED;
474
+ }
475
+ catch (error) {
476
+ this.handleError('Failed to remove DOM point', error);
477
+ throw error;
478
+ }
479
+ }
480
+ /**
481
+ * 获取覆盖层
482
+ * @returns 覆盖层实例
483
+ */
484
+ getOverlay() {
485
+ return this.anchor;
486
+ }
487
+ /**
488
+ * 获取点位ID
489
+ * @returns 点位唯一标识符
490
+ */
491
+ getId() {
492
+ return this.id;
493
+ }
494
+ /**
495
+ * 获取DOM元素
496
+ * @returns DOM元素
497
+ */
498
+ getDomElement() {
499
+ return this.dom;
500
+ }
501
+ /**
502
+ * 获取当前状态
503
+ * @returns 当前状态
504
+ */
505
+ getState() {
506
+ return this.state;
507
+ }
508
+ /**
509
+ * 获取配置选项
510
+ * @returns 配置选项的副本
511
+ */
512
+ getOptions() {
513
+ return Object.freeze({ ...this.options });
514
+ }
515
+ /**
516
+ * 检查是否已销毁
517
+ * @returns 是否已销毁
518
+ */
519
+ isDestroyed() {
520
+ return this.state === VueTemplatePointState.DESTROYED;
521
+ }
522
+ /**
523
+ * 获取地图实例
524
+ * @returns 地图实例
525
+ */
526
+ getMap() {
527
+ return this.map;
528
+ }
529
+ }