xt-element-ui 1.3.3 → 1.4.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.
Files changed (124) hide show
  1. package/CHANGELOG.md +72 -72
  2. package/LICENSE +21 -21
  3. package/README.md +240 -240
  4. package/docs/README.md +100 -100
  5. package/docs/components/base/xt-button.md +114 -114
  6. package/docs/components/base/xt-card-item.md +104 -104
  7. package/docs/components/base/xt-card.md +108 -108
  8. package/docs/components/base/xt-config-provider.md +199 -199
  9. package/docs/components/base/xt-flex-box.md +115 -115
  10. package/docs/components/base/xt-grid-box.md +302 -302
  11. package/docs/components/base/xt-input.md +150 -150
  12. package/docs/components/base/xt-map-provider.md +23 -23
  13. package/docs/components/base/xt-map.md +331 -331
  14. package/docs/components/base/xt-step-price.md +165 -165
  15. package/docs/components/base/xt-text.md +212 -212
  16. package/docs/components/base/xt-time.md +165 -165
  17. package/docs/components/extend/ex-bar.md +67 -67
  18. package/docs/components/extend/ex-button.md +62 -62
  19. package/docs/components/extend/ex-card.md +86 -86
  20. package/docs/components/extend/ex-chart.md +463 -463
  21. package/docs/components/extend/ex-icon.md +189 -189
  22. package/docs/components/extend/ex-line.md +70 -70
  23. package/docs/components/extend/ex-multi.md +155 -155
  24. package/docs/components/extend/ex-pie.md +69 -69
  25. package/docs/components/extend/ex-select-tree.md +210 -210
  26. package/docs/components/extend/ex-table.md +590 -590
  27. package/docs/components/extend/ex-upload.md +134 -134
  28. package/docs/components/utils/size.md +147 -147
  29. package/docs/components/utils/theme.md +182 -182
  30. package/lib/index.common.js +4575 -4186
  31. package/lib/index.css +1 -1
  32. package/lib/index.umd.js +4475 -4085
  33. package/lib/index.umd.min.js +5 -5
  34. package/package.json +80 -81
  35. package/src/components/ex-button/index.js +7 -7
  36. package/src/components/ex-button/index.vue +66 -66
  37. package/src/components/ex-button/style/index.scss +67 -67
  38. package/src/components/ex-card/index.js +7 -7
  39. package/src/components/ex-card/index.vue +68 -68
  40. package/src/components/ex-card/style/index.scss +73 -73
  41. package/src/components/ex-chart/index.js +7 -7
  42. package/src/components/ex-chart/index.vue +136 -136
  43. package/src/components/ex-chart/theme/dark.js +4 -1
  44. package/src/components/ex-date-picker/index.js +7 -7
  45. package/src/components/ex-icon/index.js +7 -7
  46. package/src/components/ex-icon/index.vue +168 -168
  47. package/src/components/ex-icon/style/index.scss +7 -7
  48. package/src/components/ex-page/index.js +7 -7
  49. package/src/components/ex-select-tree/index.js +7 -7
  50. package/src/components/ex-table/ExTableCell.vue +22 -22
  51. package/src/components/ex-table/index.js +7 -7
  52. package/src/components/ex-table/virtualScrollData.js +35 -35
  53. package/src/components/ex-upload/index.js +7 -7
  54. package/src/components/index.scss +49 -40
  55. package/src/components/xt-badge/index.js +7 -0
  56. package/src/components/xt-badge/index.vue +71 -0
  57. package/src/components/xt-badge/style/index.scss +88 -0
  58. package/src/components/xt-button/index.js +7 -7
  59. package/src/components/xt-button/index.vue +97 -97
  60. package/src/components/xt-card/index.js +7 -7
  61. package/src/components/xt-card/style/index.scss +48 -48
  62. package/src/components/xt-card-item/index.js +7 -7
  63. package/src/components/xt-card-item/index.vue +5 -5
  64. package/src/components/xt-card-item/style/index copy.scss +71 -71
  65. package/src/components/xt-card-item/style/index.scss +82 -82
  66. package/src/components/xt-config-provider/index.js +7 -7
  67. package/src/components/xt-config-provider/index.vue +362 -362
  68. package/src/components/xt-config-provider/style/index.scss +11 -11
  69. package/src/components/xt-flex-box/index.js +7 -7
  70. package/src/components/xt-flex-box/style/index.scss +81 -81
  71. package/src/components/xt-grid-box/index.js +7 -7
  72. package/src/components/xt-grid-box/style/index.scss +92 -92
  73. package/src/components/xt-grid-item/index.js +7 -7
  74. package/src/components/xt-grid-item/index.vue +106 -106
  75. package/src/components/xt-input/index.js +7 -7
  76. package/src/components/xt-input/index.vue +66 -66
  77. package/src/components/xt-input/style/index.scss +84 -84
  78. package/src/components/xt-map/adapters/amap.js +235 -235
  79. package/src/components/xt-map/adapters/baidu.js +254 -254
  80. package/src/components/xt-map/adapters/base.js +267 -267
  81. package/src/components/xt-map/adapters/index.js +29 -29
  82. package/src/components/xt-map/adapters/tianditu.js +242 -242
  83. package/src/components/xt-map/config/xt-map-config.js +197 -197
  84. package/src/components/xt-map/index.js +8 -8
  85. package/src/components/xt-map/index.vue +351 -351
  86. package/src/components/xt-map/loaders/script-loader.js +114 -114
  87. package/src/components/xt-map/provider.vue +200 -200
  88. package/src/components/xt-map/style/index.scss +77 -77
  89. package/src/components/xt-map-provider/index.js +8 -8
  90. package/src/components/xt-progress/index.js +7 -0
  91. package/src/components/xt-progress/index.vue +103 -0
  92. package/src/components/xt-progress/style/index.scss +119 -0
  93. package/src/components/xt-step-price/index.js +10 -10
  94. package/src/components/xt-step-price/index.vue +272 -272
  95. package/src/components/xt-step-price/style/index.scss +123 -123
  96. package/src/components/xt-step-price-item/index.js +7 -7
  97. package/src/components/xt-step-price-item/index.vue +187 -187
  98. package/src/components/xt-tabs/TabPane.vue +36 -0
  99. package/src/components/xt-tabs/index.js +10 -0
  100. package/src/components/xt-tabs/index.vue +113 -0
  101. package/src/components/xt-tabs/style/index.scss +197 -0
  102. package/src/components/xt-text/index.js +7 -7
  103. package/src/components/xt-text/index.vue +16 -2
  104. package/src/components/xt-text/style/index.scss +110 -92
  105. package/src/components/xt-time/index.js +7 -7
  106. package/src/components/xt-time/index.vue +313 -313
  107. package/src/components/xt-time/style/index.scss +23 -23
  108. package/src/config/element-registry.js +135 -135
  109. package/src/index.js +169 -178
  110. package/src/styles/css-variables.scss +257 -257
  111. package/src/styles/theme/background.scss +5 -5
  112. package/src/styles/theme/border-radius.scss +3 -3
  113. package/src/styles/theme/borders.scss +3 -3
  114. package/src/styles/theme/colors.scss +101 -101
  115. package/src/styles/theme/component-variables.scss +69 -69
  116. package/src/styles/theme/dark-variables.scss +28 -28
  117. package/src/styles/theme/font.scss +12 -12
  118. package/src/styles/theme/index.scss +11 -11
  119. package/src/styles/theme/shadows.scss +2 -2
  120. package/src/styles/theme/spacing.scss +4 -4
  121. package/src/styles/theme/transitions.scss +2 -2
  122. package/src/styles/theme/typography.scss +4 -4
  123. package/src/styles/variables-export.scss +85 -85
  124. package/src/utils/index.js +191 -202
@@ -1,351 +1,351 @@
1
- <template>
2
- <div class="xt-map-wrapper">
3
- <div ref="mapContainer" class="xt-map-container" :data-theme="mergedTheme"></div>
4
- <div v-if="loading" class="xt-map-loading">
5
- <span>地图加载中...</span>
6
- </div>
7
- <div v-if="errorMessage" class="xt-map-error">
8
- <span>{{ errorMessage }}</span>
9
- </div>
10
- <slot name="overlay"></slot>
11
- </div>
12
- </template>
13
-
14
- <script>
15
- import { getAdapterClass } from './adapters/index'
16
- import { clearScriptCache } from './loaders/script-loader'
17
- import {
18
- getMapConfig,
19
- getMapProvider,
20
- getMapApiKey,
21
- getMapApiUrl,
22
- getMapType,
23
- getMapTheme,
24
- getMapCenter,
25
- getMapZoom,
26
- setSecurityJsCode,
27
- MAP_PROVIDERS,
28
- MAP_TYPES,
29
- MAP_THEMES,
30
- onMapConfigChange
31
- } from './config/xt-map-config'
32
-
33
- export default {
34
- name: 'XtMap',
35
-
36
- props: {
37
- provider: {
38
- type: String,
39
- default: '',
40
- validator: (val) => val === '' || MAP_PROVIDERS.includes(val)
41
- },
42
- apiKey: {
43
- type: String,
44
- default: ''
45
- },
46
- apiUrl: {
47
- type: String,
48
- default: ''
49
- },
50
- mapType: {
51
- type: String,
52
- default: '',
53
- validator: (val) => val === '' || MAP_TYPES.includes(val)
54
- },
55
- theme: {
56
- type: String,
57
- default: '',
58
- validator: (val) => val === '' || MAP_THEMES.includes(val)
59
- },
60
- center: {
61
- type: Array,
62
- default: () => null
63
- },
64
- zoom: {
65
- type: Number,
66
- default: null
67
- },
68
- plugins: {
69
- type: Array,
70
- default: () => []
71
- },
72
- width: {
73
- type: String,
74
- default: '100%'
75
- },
76
- height: {
77
- type: String,
78
- default: '400px'
79
- },
80
- securityJsCode: {
81
- type: String,
82
- default: ''
83
- },
84
- tiandituLayerType: {
85
- type: String,
86
- default: 'vec'
87
- },
88
- baiduCoordType: {
89
- type: String,
90
- default: 'bd09ll'
91
- }
92
- },
93
-
94
- data() {
95
- return {
96
- loading: true,
97
- errorMessage: '',
98
- adapter: null,
99
- _unsubscribeConfig: null
100
- }
101
- },
102
-
103
- computed: {
104
- mergedProvider() {
105
- return this.provider || getMapProvider() || 'amap'
106
- },
107
- mergedApiKey() {
108
- return this.apiKey || getMapApiKey() || ''
109
- },
110
- mergedApiUrl() {
111
- return this.apiUrl || getMapApiUrl() || ''
112
- },
113
- mergedMapType() {
114
- return this.mapType || getMapType() || 'standard'
115
- },
116
- mergedTheme() {
117
- return this.theme || getMapTheme() || 'light'
118
- },
119
- mergedCenter() {
120
- return this.center || getMapCenter() || [116.397428, 39.90923]
121
- },
122
- mergedZoom() {
123
- return this.zoom !== null ? this.zoom : getMapZoom()
124
- },
125
- mergedSecurityJsCode() {
126
- return this.securityJsCode || (getMapConfig().securityJsCode) || ''
127
- },
128
- mergedPlugins() {
129
- return this.plugins.length > 0 ? this.plugins : getMapConfig().plugins || []
130
- }
131
- },
132
-
133
- watch: {
134
- mergedProvider: {
135
- handler() {
136
- this.$nextTick(() => this.rebuildMap())
137
- }
138
- },
139
- mergedApiKey: {
140
- handler() {
141
- this.$nextTick(() => this.rebuildMap())
142
- }
143
- },
144
- mergedMapType: {
145
- handler(newVal) {
146
- if (this.adapter) this.adapter.setMapType(newVal)
147
- }
148
- },
149
- mergedTheme: {
150
- handler(newVal) {
151
- if (this.adapter) this.adapter.setTheme(newVal)
152
- if (this.$refs.mapContainer) {
153
- this.$refs.mapContainer.setAttribute('data-theme', newVal)
154
- }
155
- }
156
- },
157
- mergedCenter: {
158
- handler(newVal) {
159
- if (this.adapter) this.adapter.setCenter(newVal)
160
- }
161
- },
162
- mergedZoom: {
163
- handler(newVal) {
164
- if (this.adapter) this.adapter.setZoom(newVal)
165
- }
166
- },
167
- width: {
168
- handler() {
169
- this.$nextTick(() => {
170
- if (this.adapter) this.adapter.resize()
171
- })
172
- }
173
- },
174
- height: {
175
- handler() {
176
- this.$nextTick(() => {
177
- if (this.adapter) this.adapter.resize()
178
- })
179
- }
180
- },
181
- securityJsCode: {
182
- handler(newVal) {
183
- if (newVal) {
184
- setSecurityJsCode(newVal)
185
- // 高德 2.0:SDK 已加载后再设置 securityJsCode 无效,需要重建地图
186
- if (this.mergedProvider === 'amap' && this.adapter && this.adapter.ready) {
187
- this.$nextTick(() => this.rebuildMap())
188
- }
189
- }
190
- }
191
- }
192
- },
193
-
194
- mounted() {
195
- // 监听全局配置变更
196
- this._unsubscribeConfig = onMapConfigChange((key, value) => {
197
- if (!this.provider && (key === 'provider')) this.$nextTick(() => this.rebuildMap())
198
- if (!this.apiKey && (key === 'apiKey')) this.$nextTick(() => this.rebuildMap())
199
- if (!this.apiUrl && (key === 'apiUrl')) this.$nextTick(() => this.rebuildMap())
200
- if (!this.theme && key === 'theme' && this.adapter) this.adapter.setTheme(value)
201
- if (!this.mapType && key === 'mapType' && this.adapter) this.adapter.setMapType(value)
202
- if (!this.center && key === 'center' && this.adapter) this.adapter.setCenter(value)
203
- if (this.zoom === null && key === 'zoom' && this.adapter) this.adapter.setZoom(value)
204
- })
205
-
206
- // 设置高德安全密钥
207
- if (this.securityJsCode) setSecurityJsCode(this.securityJsCode)
208
-
209
- this.$nextTick(() => this.initMap())
210
-
211
- // 监听窗口尺寸变化
212
- this._onWindowResize = () => {
213
- if (this.adapter) this.adapter.resize()
214
- }
215
- if (typeof window !== 'undefined') {
216
- window.addEventListener('resize', this._onWindowResize)
217
- }
218
- },
219
-
220
- beforeDestroy() {
221
- this.destroyMap()
222
- if (this._unsubscribeConfig) this._unsubscribeConfig()
223
- if (this._onWindowResize && typeof window !== 'undefined') {
224
- window.removeEventListener('resize', this._onWindowResize)
225
- }
226
- },
227
-
228
- methods: {
229
- async initMap() {
230
- const container = this.$refs.mapContainer
231
- if (!container) return
232
-
233
- // 设置容器尺寸
234
- container.style.width = this.width
235
- container.style.height = this.height
236
-
237
- // 设置安全密钥(高德需要)
238
- if (this.securityJsCode) setSecurityJsCode(this.securityJsCode)
239
-
240
- this.loading = true
241
- this.errorMessage = ''
242
-
243
- const AdapterClass = getAdapterClass(this.mergedProvider)
244
-
245
- this.adapter = new AdapterClass(container, {
246
- apiKey: this.mergedApiKey,
247
- apiUrl: this.mergedApiUrl,
248
- mapType: this.mergedMapType,
249
- theme: this.mergedTheme,
250
- center: this.mergedCenter,
251
- zoom: this.mergedZoom,
252
- plugins: this.mergedPlugins,
253
- securityJsCode: this.mergedSecurityJsCode,
254
- tiandituLayerType: this.tiandituLayerType,
255
- baiduCoordType: this.baiduCoordType
256
- })
257
-
258
- try {
259
- await this.adapter.init()
260
- this.loading = false
261
-
262
- // 绑定事件
263
- this._bindAdapterEvents()
264
-
265
- // 向父组件发出 ready 事件
266
- this.$emit('ready', {
267
- provider: this.mergedProvider,
268
- map: this.adapter.getNativeMap(),
269
- adapter: this.adapter
270
- })
271
- } catch (err) {
272
- this.loading = false
273
- this.errorMessage = err.message || '地图初始化失败'
274
- this.$emit('error', err)
275
- }
276
- },
277
-
278
- rebuildMap() {
279
- this.destroyMap()
280
- // 清理脚本缓存,确保新配置能生效(例如切换密钥后重新加载)
281
- if (typeof clearScriptCache === 'function') {
282
- clearScriptCache()
283
- }
284
- this.$nextTick(() => this.initMap())
285
- },
286
-
287
- destroyMap() {
288
- if (this.adapter) {
289
- this.adapter.destroy()
290
- this.adapter = null
291
- }
292
- },
293
-
294
- _bindAdapterEvents() {
295
- if (!this.adapter) return
296
-
297
- const events = ['click', 'moveend', 'zoomend', 'zoomchange', 'mapmove']
298
- events.forEach((evt) => {
299
- this.adapter.on(evt, (data) => {
300
- this.$emit(evt, data)
301
- })
302
- })
303
- },
304
-
305
- // 对外暴露的统一 API
306
- setCenter(center) {
307
- if (this.adapter) this.adapter.setCenter(center)
308
- },
309
-
310
- setZoom(zoom) {
311
- if (this.adapter) this.adapter.setZoom(zoom)
312
- },
313
-
314
- setMapType(type) {
315
- if (this.adapter) this.adapter.setMapType(type)
316
- },
317
-
318
- setTheme(theme) {
319
- if (this.adapter) this.adapter.setTheme(theme)
320
- },
321
-
322
- getCenter() {
323
- return this.adapter ? this.adapter.getCenter() : this.mergedCenter
324
- },
325
-
326
- getZoom() {
327
- return this.adapter ? this.adapter.getZoom() : this.mergedZoom
328
- },
329
-
330
- getNativeMap() {
331
- return this.adapter ? this.adapter.getNativeMap() : null
332
- },
333
-
334
- resize() {
335
- if (this.adapter) this.adapter.resize()
336
- },
337
-
338
- on(eventName, handler) {
339
- if (this.adapter) this.adapter.on(eventName, handler)
340
- },
341
-
342
- off(eventName) {
343
- if (this.adapter) this.adapter.off(eventName)
344
- },
345
-
346
- rebuild() {
347
- this.rebuildMap()
348
- }
349
- }
350
- }
351
- </script>
1
+ <template>
2
+ <div class="xt-map-wrapper">
3
+ <div ref="mapContainer" class="xt-map-container" :data-theme="mergedTheme"></div>
4
+ <div v-if="loading" class="xt-map-loading">
5
+ <span>地图加载中...</span>
6
+ </div>
7
+ <div v-if="errorMessage" class="xt-map-error">
8
+ <span>{{ errorMessage }}</span>
9
+ </div>
10
+ <slot name="overlay"></slot>
11
+ </div>
12
+ </template>
13
+
14
+ <script>
15
+ import { getAdapterClass } from './adapters/index'
16
+ import { clearScriptCache } from './loaders/script-loader'
17
+ import {
18
+ getMapConfig,
19
+ getMapProvider,
20
+ getMapApiKey,
21
+ getMapApiUrl,
22
+ getMapType,
23
+ getMapTheme,
24
+ getMapCenter,
25
+ getMapZoom,
26
+ setSecurityJsCode,
27
+ MAP_PROVIDERS,
28
+ MAP_TYPES,
29
+ MAP_THEMES,
30
+ onMapConfigChange
31
+ } from './config/xt-map-config'
32
+
33
+ export default {
34
+ name: 'XtMap',
35
+
36
+ props: {
37
+ provider: {
38
+ type: String,
39
+ default: '',
40
+ validator: (val) => val === '' || MAP_PROVIDERS.includes(val)
41
+ },
42
+ apiKey: {
43
+ type: String,
44
+ default: ''
45
+ },
46
+ apiUrl: {
47
+ type: String,
48
+ default: ''
49
+ },
50
+ mapType: {
51
+ type: String,
52
+ default: '',
53
+ validator: (val) => val === '' || MAP_TYPES.includes(val)
54
+ },
55
+ theme: {
56
+ type: String,
57
+ default: '',
58
+ validator: (val) => val === '' || MAP_THEMES.includes(val)
59
+ },
60
+ center: {
61
+ type: Array,
62
+ default: () => null
63
+ },
64
+ zoom: {
65
+ type: Number,
66
+ default: null
67
+ },
68
+ plugins: {
69
+ type: Array,
70
+ default: () => []
71
+ },
72
+ width: {
73
+ type: String,
74
+ default: '100%'
75
+ },
76
+ height: {
77
+ type: String,
78
+ default: '400px'
79
+ },
80
+ securityJsCode: {
81
+ type: String,
82
+ default: ''
83
+ },
84
+ tiandituLayerType: {
85
+ type: String,
86
+ default: 'vec'
87
+ },
88
+ baiduCoordType: {
89
+ type: String,
90
+ default: 'bd09ll'
91
+ }
92
+ },
93
+
94
+ data() {
95
+ return {
96
+ loading: true,
97
+ errorMessage: '',
98
+ adapter: null,
99
+ _unsubscribeConfig: null
100
+ }
101
+ },
102
+
103
+ computed: {
104
+ mergedProvider() {
105
+ return this.provider || getMapProvider() || 'amap'
106
+ },
107
+ mergedApiKey() {
108
+ return this.apiKey || getMapApiKey() || ''
109
+ },
110
+ mergedApiUrl() {
111
+ return this.apiUrl || getMapApiUrl() || ''
112
+ },
113
+ mergedMapType() {
114
+ return this.mapType || getMapType() || 'standard'
115
+ },
116
+ mergedTheme() {
117
+ return this.theme || getMapTheme() || 'light'
118
+ },
119
+ mergedCenter() {
120
+ return this.center || getMapCenter() || [116.397428, 39.90923]
121
+ },
122
+ mergedZoom() {
123
+ return this.zoom !== null ? this.zoom : getMapZoom()
124
+ },
125
+ mergedSecurityJsCode() {
126
+ return this.securityJsCode || (getMapConfig().securityJsCode) || ''
127
+ },
128
+ mergedPlugins() {
129
+ return this.plugins.length > 0 ? this.plugins : getMapConfig().plugins || []
130
+ }
131
+ },
132
+
133
+ watch: {
134
+ mergedProvider: {
135
+ handler() {
136
+ this.$nextTick(() => this.rebuildMap())
137
+ }
138
+ },
139
+ mergedApiKey: {
140
+ handler() {
141
+ this.$nextTick(() => this.rebuildMap())
142
+ }
143
+ },
144
+ mergedMapType: {
145
+ handler(newVal) {
146
+ if (this.adapter) this.adapter.setMapType(newVal)
147
+ }
148
+ },
149
+ mergedTheme: {
150
+ handler(newVal) {
151
+ if (this.adapter) this.adapter.setTheme(newVal)
152
+ if (this.$refs.mapContainer) {
153
+ this.$refs.mapContainer.setAttribute('data-theme', newVal)
154
+ }
155
+ }
156
+ },
157
+ mergedCenter: {
158
+ handler(newVal) {
159
+ if (this.adapter) this.adapter.setCenter(newVal)
160
+ }
161
+ },
162
+ mergedZoom: {
163
+ handler(newVal) {
164
+ if (this.adapter) this.adapter.setZoom(newVal)
165
+ }
166
+ },
167
+ width: {
168
+ handler() {
169
+ this.$nextTick(() => {
170
+ if (this.adapter) this.adapter.resize()
171
+ })
172
+ }
173
+ },
174
+ height: {
175
+ handler() {
176
+ this.$nextTick(() => {
177
+ if (this.adapter) this.adapter.resize()
178
+ })
179
+ }
180
+ },
181
+ securityJsCode: {
182
+ handler(newVal) {
183
+ if (newVal) {
184
+ setSecurityJsCode(newVal)
185
+ // 高德 2.0:SDK 已加载后再设置 securityJsCode 无效,需要重建地图
186
+ if (this.mergedProvider === 'amap' && this.adapter && this.adapter.ready) {
187
+ this.$nextTick(() => this.rebuildMap())
188
+ }
189
+ }
190
+ }
191
+ }
192
+ },
193
+
194
+ mounted() {
195
+ // 监听全局配置变更
196
+ this._unsubscribeConfig = onMapConfigChange((key, value) => {
197
+ if (!this.provider && (key === 'provider')) this.$nextTick(() => this.rebuildMap())
198
+ if (!this.apiKey && (key === 'apiKey')) this.$nextTick(() => this.rebuildMap())
199
+ if (!this.apiUrl && (key === 'apiUrl')) this.$nextTick(() => this.rebuildMap())
200
+ if (!this.theme && key === 'theme' && this.adapter) this.adapter.setTheme(value)
201
+ if (!this.mapType && key === 'mapType' && this.adapter) this.adapter.setMapType(value)
202
+ if (!this.center && key === 'center' && this.adapter) this.adapter.setCenter(value)
203
+ if (this.zoom === null && key === 'zoom' && this.adapter) this.adapter.setZoom(value)
204
+ })
205
+
206
+ // 设置高德安全密钥
207
+ if (this.securityJsCode) setSecurityJsCode(this.securityJsCode)
208
+
209
+ this.$nextTick(() => this.initMap())
210
+
211
+ // 监听窗口尺寸变化
212
+ this._onWindowResize = () => {
213
+ if (this.adapter) this.adapter.resize()
214
+ }
215
+ if (typeof window !== 'undefined') {
216
+ window.addEventListener('resize', this._onWindowResize)
217
+ }
218
+ },
219
+
220
+ beforeDestroy() {
221
+ this.destroyMap()
222
+ if (this._unsubscribeConfig) this._unsubscribeConfig()
223
+ if (this._onWindowResize && typeof window !== 'undefined') {
224
+ window.removeEventListener('resize', this._onWindowResize)
225
+ }
226
+ },
227
+
228
+ methods: {
229
+ async initMap() {
230
+ const container = this.$refs.mapContainer
231
+ if (!container) return
232
+
233
+ // 设置容器尺寸
234
+ container.style.width = this.width
235
+ container.style.height = this.height
236
+
237
+ // 设置安全密钥(高德需要)
238
+ if (this.securityJsCode) setSecurityJsCode(this.securityJsCode)
239
+
240
+ this.loading = true
241
+ this.errorMessage = ''
242
+
243
+ const AdapterClass = getAdapterClass(this.mergedProvider)
244
+
245
+ this.adapter = new AdapterClass(container, {
246
+ apiKey: this.mergedApiKey,
247
+ apiUrl: this.mergedApiUrl,
248
+ mapType: this.mergedMapType,
249
+ theme: this.mergedTheme,
250
+ center: this.mergedCenter,
251
+ zoom: this.mergedZoom,
252
+ plugins: this.mergedPlugins,
253
+ securityJsCode: this.mergedSecurityJsCode,
254
+ tiandituLayerType: this.tiandituLayerType,
255
+ baiduCoordType: this.baiduCoordType
256
+ })
257
+
258
+ try {
259
+ await this.adapter.init()
260
+ this.loading = false
261
+
262
+ // 绑定事件
263
+ this._bindAdapterEvents()
264
+
265
+ // 向父组件发出 ready 事件
266
+ this.$emit('ready', {
267
+ provider: this.mergedProvider,
268
+ map: this.adapter.getNativeMap(),
269
+ adapter: this.adapter
270
+ })
271
+ } catch (err) {
272
+ this.loading = false
273
+ this.errorMessage = err.message || '地图初始化失败'
274
+ this.$emit('error', err)
275
+ }
276
+ },
277
+
278
+ rebuildMap() {
279
+ this.destroyMap()
280
+ // 清理脚本缓存,确保新配置能生效(例如切换密钥后重新加载)
281
+ if (typeof clearScriptCache === 'function') {
282
+ clearScriptCache()
283
+ }
284
+ this.$nextTick(() => this.initMap())
285
+ },
286
+
287
+ destroyMap() {
288
+ if (this.adapter) {
289
+ this.adapter.destroy()
290
+ this.adapter = null
291
+ }
292
+ },
293
+
294
+ _bindAdapterEvents() {
295
+ if (!this.adapter) return
296
+
297
+ const events = ['click', 'moveend', 'zoomend', 'zoomchange', 'mapmove']
298
+ events.forEach((evt) => {
299
+ this.adapter.on(evt, (data) => {
300
+ this.$emit(evt, data)
301
+ })
302
+ })
303
+ },
304
+
305
+ // 对外暴露的统一 API
306
+ setCenter(center) {
307
+ if (this.adapter) this.adapter.setCenter(center)
308
+ },
309
+
310
+ setZoom(zoom) {
311
+ if (this.adapter) this.adapter.setZoom(zoom)
312
+ },
313
+
314
+ setMapType(type) {
315
+ if (this.adapter) this.adapter.setMapType(type)
316
+ },
317
+
318
+ setTheme(theme) {
319
+ if (this.adapter) this.adapter.setTheme(theme)
320
+ },
321
+
322
+ getCenter() {
323
+ return this.adapter ? this.adapter.getCenter() : this.mergedCenter
324
+ },
325
+
326
+ getZoom() {
327
+ return this.adapter ? this.adapter.getZoom() : this.mergedZoom
328
+ },
329
+
330
+ getNativeMap() {
331
+ return this.adapter ? this.adapter.getNativeMap() : null
332
+ },
333
+
334
+ resize() {
335
+ if (this.adapter) this.adapter.resize()
336
+ },
337
+
338
+ on(eventName, handler) {
339
+ if (this.adapter) this.adapter.on(eventName, handler)
340
+ },
341
+
342
+ off(eventName) {
343
+ if (this.adapter) this.adapter.off(eventName)
344
+ },
345
+
346
+ rebuild() {
347
+ this.rebuildMap()
348
+ }
349
+ }
350
+ }
351
+ </script>