Commit d2c92faf059b5a0eea357c2bfc8e1aa52990901a

Authored by fengtao
Committed by xp.Huang
1 parent 60f291ee

fix: 修复针对火狐浏览器,随便拖拽一个组件,默认位置都在左上角并遮住的问题。并优化设备分布地图,弹窗可自定义显示内容

@@ -4,7 +4,6 @@ import { OverrideMapAmapConfig } from './index' @@ -4,7 +4,6 @@ import { OverrideMapAmapConfig } from './index'
4 import { chartInitConfig } from '@/settings/designSetting' 4 import { chartInitConfig } from '@/settings/designSetting'
5 import cloneDeep from 'lodash/cloneDeep' 5 import cloneDeep from 'lodash/cloneDeep'
6 import dataJson from './data.json' 6 import dataJson from './data.json'
7 -import defaultImg from '../../../../../../assets/external/marker/1.png'  
8 7
9 export type dataExtraInfoType = typeof dataJson.markers[number]['extraInfo'] //data.json下的extraInfo类型 8 export type dataExtraInfoType = typeof dataJson.markers[number]['extraInfo'] //data.json下的extraInfo类型
10 9
@@ -137,8 +136,15 @@ export const option = { @@ -137,8 +136,15 @@ export const option = {
137 mapMarkerType: MarkerEnum.MARKER, 136 mapMarkerType: MarkerEnum.MARKER,
138 viewMode: ViewModeEnum.PLANE, 137 viewMode: ViewModeEnum.PLANE,
139 lang: LangEnum.ZH_CN, 138 lang: LangEnum.ZH_CN,
140 - features: [FeaturesEnum.BG, FeaturesEnum.POINT, FeaturesEnum.ROAD, FeaturesEnum.BUILDING]  
141 - } 139 + features: [FeaturesEnum.BG, FeaturesEnum.POINT, FeaturesEnum.ROAD, FeaturesEnum.BUILDING],
  140 + },
  141 + // 自定义配置项
  142 + dialogCustomField: false, // 弹窗内的label是否自定义
  143 + dialogConfigField: [{
  144 + label:'',
  145 + value:'',
  146 + realValue:''
  147 + }] // 弹窗内配置字段
142 } 148 }
143 149
144 export default class Config extends PublicConfigClass implements CreateComponentType { 150 export default class Config extends PublicConfigClass implements CreateComponentType {
1 <template> 1 <template>
2 <collapse-item name="基础" :expanded="true"> 2 <collapse-item name="基础" :expanded="true">
  3 + <setting-item-box name="弹窗label" :alone="true">
  4 + <setting-item>
  5 + <n-switch v-model:value="optionData.dialogCustomField" size="small"></n-switch>
  6 + </setting-item>
  7 + </setting-item-box>
  8 + <setting-item-box name="使用注意" :alone="true">
  9 + <n-gradient-text :size="14" type="success">弹窗字段里面配置的键值需要</n-gradient-text>
  10 + <n-gradient-text :size="14" type="success">和静态数据里的customField</n-gradient-text>
  11 + <n-gradient-text :size="14" type="success">对象里的键相对应</n-gradient-text>
  12 + </setting-item-box>
  13 + <setting-item-box v-if="optionData.dialogCustomField" name="弹窗字段" :alone="true">
  14 + <setting-item>
  15 + <template v-for="(item, index) in optionData.dialogConfigField" :key="index">
  16 + <setting-item-box name="键名" :alone="true">
  17 + <setting-item>
  18 + <n-input-group>
  19 + <n-input v-model:value="item.label" size="small" placeholder="请输入键名"></n-input>
  20 + </n-input-group>
  21 + </setting-item>
  22 + </setting-item-box>
  23 + <setting-item-box name="键值" :alone="true">
  24 + <setting-item>
  25 + <n-input-group>
  26 + <n-input v-model:value="item.value" size="small" placeholder="请输入键值"></n-input>
  27 + </n-input-group>
  28 + </setting-item>
  29 + </setting-item-box>
  30 + <setting-item-box :alone="true">
  31 + <setting-item>
  32 + <n-button size="small" @click="optionData.dialogConfigField.splice(index, 1)"> - </n-button>
  33 + </setting-item>
  34 + </setting-item-box>
  35 + </template>
  36 + <setting-item-box :alone="true">
  37 + <setting-item>
  38 + <n-button
  39 + v-if="optionData.dialogConfigField.length < 9"
  40 + size="small"
  41 + @click="
  42 + optionData.dialogConfigField.push({
  43 + label: '',
  44 + value: '',
  45 + realValue: ''
  46 + })
  47 + "
  48 + >
  49 + +
  50 + </n-button>
  51 + </setting-item>
  52 + </setting-item-box>
  53 + </setting-item>
  54 + </setting-item-box>
3 <setting-item-box name="语言类型" :alone="true"> 55 <setting-item-box name="语言类型" :alone="true">
4 <setting-item> 56 <setting-item>
5 <n-select size="small" v-model:value="optionData.mapOptions.lang" :options="langOptions" /> 57 <n-select size="small" v-model:value="optionData.mapOptions.lang" :options="langOptions" />
@@ -284,8 +336,8 @@ const renderOption = (option: SelectOption) => { @@ -284,8 +336,8 @@ const renderOption = (option: SelectOption) => {
284 336
285 const selectHandle = (value: string) => { 337 const selectHandle = (value: string) => {
286 iconMarkerValue.value = value 338 iconMarkerValue.value = value
287 - getUrlBase64(getMarkerImagePath(value),'png',(baseEncodeText: string)=>{  
288 - props.optionData.mapOptions.iconMarker =baseEncodeText 339 + getUrlBase64(getMarkerImagePath(value), 'png', (baseEncodeText: string) => {
  340 + props.optionData.mapOptions.iconMarker = baseEncodeText
289 }) 341 })
290 } 342 }
291 343
@@ -335,7 +387,7 @@ const selectMapBorderHandle = (value: string) => { @@ -335,7 +387,7 @@ const selectMapBorderHandle = (value: string) => {
335 } 387 }
336 388
337 onMounted(() => { 389 onMounted(() => {
338 - getUrlBase64(getMarkerImagePath(props.optionData.mapOptions.iconMarker),'png',(baseEncodeText: string)=>{ 390 + getUrlBase64(getMarkerImagePath(props.optionData.mapOptions.iconMarker), 'png', (baseEncodeText: string) => {
339 props.optionData.mapOptions.iconMarker = baseEncodeText 391 props.optionData.mapOptions.iconMarker = baseEncodeText
340 }) 392 })
341 mapSelectBorderValue.value = `${props.optionData.mapOptions.mpBorderConfig.value?.toLocaleLowerCase()}.png` 393 mapSelectBorderValue.value = `${props.optionData.mapOptions.mpBorderConfig.value?.toLocaleLowerCase()}.png`
1 { 1 {
2 "markers": [ 2 "markers": [
3 { 3 {
4 - "name": "模拟数据1", 4 + "name": "模拟数据",
5 "value": 20, 5 "value": 20,
6 - "position": [103.856504, 30.687278], 6 + "position": [
  7 + 103.856504,
  8 + 30.687278
  9 + ],
7 "extraInfo": { 10 "extraInfo": {
8 "tbDeviceId": "@xxxxxxxxxxx", 11 "tbDeviceId": "@xxxxxxxxxxx",
9 - "name": "模拟数据1",  
10 - "alias": "模拟数据1", 12 + "name": "模拟数据",
  13 + "alias": "模拟数据",
11 "organizationDTO": { 14 "organizationDTO": {
12 - "name": "模拟数据1" 15 + "name": "模拟数据"
13 }, 16 },
14 "deviceState": "INACTIVE", 17 "deviceState": "INACTIVE",
15 "deviceProfile": { 18 "deviceProfile": {
16 "transportType": "MQTT" 19 "transportType": "MQTT"
17 }, 20 },
18 - "deviceProfileId":"", 21 + "deviceProfileId": "",
19 "deviceInfo": { 22 "deviceInfo": {
20 - "address": "四川省", 23 + "address": "四川省成都市",
21 "longitude": 103.856504, 24 "longitude": 103.856504,
22 "latitude": 30.687278 25 "latitude": 30.687278
23 - }  
24 - }  
25 - },  
26 - {  
27 - "name": "模拟数据2",  
28 - "value": 30,  
29 - "position": [104.095368, 30.716787],  
30 - "extraInfo": {  
31 - "tbDeviceId": "@xxxxxxxxxxxxxxx",  
32 - "name": "模拟数据2",  
33 - "alias": "模拟数据2",  
34 - "organizationDTO": {  
35 - "name": "模拟数据2"  
36 }, 26 },
37 - "deviceState": "INACTIVE",  
38 - "deviceProfile": {  
39 - "transportType": "TCP"  
40 - },  
41 - "deviceProfileId":"",  
42 - "deviceInfo": {  
43 - "address": "四川省",  
44 - "longitude": 104.095368,  
45 - "latitude": 30.716787 27 + "customField": {
  28 + "devicetype": "模拟数据",
  29 + "devicecode": "1211"
46 } 30 }
47 } 31 }
48 } 32 }
49 ] 33 ]
50 -} 34 +}
@@ -27,6 +27,7 @@ import { getDeviceActiveTime } from '@/api/external/common/index' @@ -27,6 +27,7 @@ import { getDeviceActiveTime } from '@/api/external/common/index'
27 import dayjs from 'dayjs' 27 import dayjs from 'dayjs'
28 import DeviceLatestTable from './components/DeviceLatestTable.vue' 28 import DeviceLatestTable from './components/DeviceLatestTable.vue'
29 import { getDeviceLatest, getProfileAttrs } from '@/api/external/common' 29 import { getDeviceLatest, getProfileAttrs } from '@/api/external/common'
  30 +import { isObject } from '@/utils/external/is'
30 31
31 const props = defineProps({ 32 const props = defineProps({
32 chartConfig: { 33 chartConfig: {
@@ -51,11 +52,12 @@ const { @@ -51,11 +52,12 @@ const {
51 pitch, 52 pitch,
52 skyColor, 53 skyColor,
53 marker, 54 marker,
54 - iconMarker,  
55 mpBorderConfig, 55 mpBorderConfig,
56 bgColor 56 bgColor
57 } = toRefs(props.chartConfig.option.mapOptions) 57 } = toRefs(props.chartConfig.option.mapOptions)
58 58
  59 +const { dialogCustomField, dialogConfigField } = toRefs(props.chartConfig.option)
  60 +
59 //官方没有高德地图api的ts,所以类型全用的any 61 //官方没有高德地图api的ts,所以类型全用的any
60 let mapIns: any = null 62 let mapIns: any = null
61 let markers: any = [] 63 let markers: any = []
@@ -116,21 +118,48 @@ const devicePartInfo = reactive<devicePartInfoInterface>({ @@ -116,21 +118,48 @@ const devicePartInfo = reactive<devicePartInfoInterface>({
116 //创建信息弹窗 118 //创建信息弹窗
117 const createInfoWindow = async (extraInfo: dataExtraInfoType) => { 119 const createInfoWindow = async (extraInfo: dataExtraInfoType) => {
118 try { 120 try {
119 - const { name, alias, organizationDTO, deviceState, deviceProfile, deviceInfo, tbDeviceId, deviceProfileId } =  
120 - extraInfo 121 + const {
  122 + name,
  123 + alias,
  124 + organizationDTO,
  125 + deviceState,
  126 + deviceProfile,
  127 + deviceInfo,
  128 + tbDeviceId,
  129 + deviceProfileId,
  130 + customField
  131 + } = extraInfo
  132 + // customField 用于自定义服务端返回的数据
  133 + let realDialogConfigFieldValue = []
  134 + if ('customField' in extraInfo && isObject(customField)) {
  135 + realDialogConfigFieldValue = dialogConfigField.value?.reduce((acc: Recordable[], curr: Recordable) => {
  136 + const realValue = Object.entries(customField)?.map(([label, value]) => ({
  137 + label,
  138 + value
  139 + }))
  140 + const findRealValue = realValue?.find(realItem => realItem.label === curr.value)?.value
  141 + curr['realValue'] = findRealValue
  142 + acc.push(curr)
  143 + return [...acc]
  144 + }, [])
  145 + }
  146 + //
121 devicePartInfo.tbDeviceId = tbDeviceId 147 devicePartInfo.tbDeviceId = tbDeviceId
122 devicePartInfo.alias = alias 148 devicePartInfo.alias = alias
123 devicePartInfo.name = name 149 devicePartInfo.name = name
124 devicePartInfo.deviceProfileId = deviceProfileId 150 devicePartInfo.deviceProfileId = deviceProfileId
125 - if (tbDeviceId.startsWith('@')) return //假的模拟数据则终止  
126 let deviceLastUpdateTs = null 151 let deviceLastUpdateTs = null
127 - const res = await getDeviceActiveTime(tbDeviceId) //查询设备最后离线时间  
128 - if (!res) {  
129 - deviceLastUpdateTs = null  
130 - } else {  
131 - deviceLastUpdateTs = res[0]['lastUpdateTs'] 152 + try {
  153 + const res = !dialogCustomField.value ? await getDeviceActiveTime(tbDeviceId) : [{ lastUpdateTs: '' }] //查询设备最后离线时间
  154 + if (!res) {
  155 + deviceLastUpdateTs = null
  156 + } else {
  157 + deviceLastUpdateTs = res[0]['lastUpdateTs']
  158 + }
  159 + } catch (e) {
  160 + console.error(`${e}`, '查询设备最后离线时间(tbDeviceId错误)')
132 } 161 }
133 - const lastUpdateFormatTs = deviceLastUpdateTs ? dayjs(deviceLastUpdateTs).format('YYYY-MM-DD HH:mm:ss'): '' 162 + const lastUpdateFormatTs = deviceLastUpdateTs ? dayjs(deviceLastUpdateTs).format('YYYY-MM-DD HH:mm:ss') : ''
134 //以render方式渲染小组件里的边框组件 163 //以render方式渲染小组件里的边框组件
135 const BorderInstance = await import(`../../../../Decorates/Borders/${mpBorderConfig.value.value}/index.vue`) 164 const BorderInstance = await import(`../../../../Decorates/Borders/${mpBorderConfig.value.value}/index.vue`)
136 const config = await import(`../../../../Decorates/Borders/${mpBorderConfig.value.value}/config.ts`) 165 const config = await import(`../../../../Decorates/Borders/${mpBorderConfig.value.value}/config.ts`)
@@ -141,48 +170,66 @@ const createInfoWindow = async (extraInfo: dataExtraInfoType) => { @@ -141,48 +170,66 @@ const createInfoWindow = async (extraInfo: dataExtraInfoType) => {
141 render(h(BorderInstance.default, { chartConfig: BorderConfigInstance }), document.getElementById(id)!) 170 render(h(BorderInstance.default, { chartConfig: BorderConfigInstance }), document.getElementById(id)!)
142 }, 100) 171 }, 100)
143 // 172 //
144 - const textOverflow = `width:16rem;text-overflow:ellipsis;overflow:hidden;word-break:break-all;white-space:nowrap;`  
145 - const textOverflowFontBold = `width:12rem;text-overflow:ellipsis;overflow:hidden;word-break:break-all;white-space:nowrap;font-size:15px;font-weight:bold;`  
146 - const deviceStateContainer = `display:flex;justify-content:space-between;align-items:center;`  
147 - const deviceStateImg = `width:1.2rem;height:1.2rem;`  
148 - const deviceStateText = `margin-left:0.6rem;font-weight:bold;` 173 +
  174 + const dialogStyles = {
  175 + textOverflowStyle: `width:15rem;text-overflow:ellipsis;overflow:hidden;word-break:break-all;white-space:nowrap;`,
  176 + customFieldBox: `display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;color:white;`,
  177 + defaultFieldHeaderBox: `display:flex;justify-content:space-between;align-items:center;color:white;`,
  178 + defaultFieldHeaderBoldText: `width:12rem;text-overflow:ellipsis;overflow:hidden;word-break:break-all;white-space:nowrap;font-size:15px;font-weight:bold;`,
  179 + defaultFieldBox: `display:flex;flex-direction:column;justify-content:space-between;color:white;margin-top:1rem;gap:0.95rem;`,
  180 + iconSize: `width:1.2rem;height:1.2rem;`,
  181 + textStatus: `margin-left:0.6rem;font-weight:bold;`,
  182 + defaultFieldHeaderRightBox: `display:flex;justify-content:space-between;align-items:center;margin-right:16px`
  183 + }
  184 +
149 return ` 185 return `
150 - <div id="${id}" style="width:30rem;">  
151 - <div style="display:flex;flex-direction:column;margin:3.5rem 5.5rem 2rem 6.5rem;position:relative;">  
152 - <div style="display:flex;justify-content:space-between;align-items:center;color:white;">  
153 - <span style="${textOverflowFontBold}">${alias || name}</span>  
154 - ${  
155 - deviceState === 'INACTIVE'  
156 - ? `<div style="${deviceStateContainer}">  
157 - <img onclick="handleOpenDrawer()" title="最新数据" style="${deviceStateImg};cursor:pointer;" src="${listView}"/>  
158 - <img style="${deviceStateImg};margin-left:0.3rem" src="${inactive}"/>  
159 - <span style="${deviceStateText}">待激活</span>  
160 - </div>`  
161 - : deviceState === 'ONLINE'  
162 - ? `<div style="${deviceStateContainer}">  
163 - <img onclick="handleOpenDrawer()" title="最新数据" style="${deviceStateImg};cursor:pointer;" src="${listView}"/>  
164 - <img style="${deviceStateImg};margin-left:0.3rem" src="${online}"/>  
165 - <span style="${deviceStateText}">在线</span>  
166 - </div>`  
167 - : `<div style="${deviceStateContainer}">  
168 - <img onclick="handleOpenDrawer()" title="最新数据" style="${deviceStateImg};cursor:pointer;" src="${listView}"/>  
169 - <img style="${deviceStateImg};margin-left:0.3rem" src="${offline}"/>  
170 - <span style="${deviceStateText}">离线</span>  
171 - </div>`  
172 - }  
173 - </div>  
174 - <div style="display:flex;flex-direction:column;justify-content:space-between;color:white;margin-top:1rem;gap:0.95rem;">  
175 - <div style="${textOverflow}">所属组织:${organizationDTO.name}</div>  
176 - <div style="${textOverflow}">接入协议:${deviceProfile.transportType}</div>  
177 - <div style="${textOverflow}">设备位置:${  
178 - !deviceInfo.address ? '该设备暂无地理位置' : deviceInfo.address  
179 - }</div>  
180 - <div style="${textOverflow}">${  
181 - deviceState === 'ONLINE' ? '在线' : deviceState === 'INACTIVE' ? '创建' : '离线'  
182 - }时间:${lastUpdateFormatTs}</div> 186 + <div id="${id}" style="position: absolute;top: 70px">
  187 + </div>
  188 + ${
  189 + dialogCustomField.value
  190 + ? `
  191 + <div style="position: absolute;top: 135px;left:110px;width:20rem">
  192 + <div style="${dialogStyles.customFieldBox}">
  193 + ${realDialogConfigFieldValue?.map((item: { label: string; value: string; realValue: any }) => {
  194 + const { label, realValue } = item
  195 + return `
  196 + <div style="${dialogStyles.textOverflowStyle}">
  197 + <span >${label}:${realValue}</span>
  198 + </div>
  199 + `
  200 + })}
183 </div> 201 </div>
184 </div> 202 </div>
185 - </div> 203 + `
  204 + : `
  205 + <div style="position: absolute;top: 135px;left:110px;width:20rem">
  206 + <div style="${dialogStyles.defaultFieldHeaderBox}">
  207 + <span style="${dialogStyles.defaultFieldHeaderBoldText}">${alias || name}</span>
  208 + <div style="${dialogStyles.defaultFieldHeaderRightBox}">
  209 + <img onclick="handleOpenDrawer()" style="${
  210 + dialogStyles.iconSize
  211 + };cursor:pointer;margin-right:0.5rem" src="${listView}"/>
  212 + <img style="${dialogStyles.iconSize};margin-left:0.5rem" src="${
  213 + deviceState === 'INACTIVE' ? inactive : deviceState === 'ONLINE' ? online : offline
  214 + }"/>
  215 + <span style="${dialogStyles.textStatus}">${
  216 + deviceState === 'INACTIVE' ? '待激活' : deviceState === 'ONLINE' ? '在线' : '离线'
  217 + }</span>
  218 + </div>
  219 + </div>
  220 + <div style="${dialogStyles.defaultFieldBox}">
  221 + <div style="${dialogStyles.textOverflowStyle}">所属组织:${organizationDTO?.name}</div>
  222 + <div style="${dialogStyles.textOverflowStyle}">接入协议:${deviceProfile?.transportType}</div>
  223 + <div style="${dialogStyles.textOverflowStyle}">设备位置:${
  224 + !deviceInfo?.address ? '该设备暂无地理位置' : deviceInfo?.address
  225 + }</div>
  226 + <div style="${dialogStyles.textOverflowStyle}">${
  227 + deviceState === 'ONLINE' ? '在线' : deviceState === 'INACTIVE' ? '创建' : '离线'
  228 + }时间:${lastUpdateFormatTs}</div>
  229 + </div>
  230 + `
  231 + }
  232 +
186 ` 233 `
187 } catch (e) { 234 } catch (e) {
188 console.error(e) 235 console.error(e)
@@ -199,11 +246,11 @@ const handleOpenDrawer = async () => { @@ -199,11 +246,11 @@ const handleOpenDrawer = async () => {
199 } 246 }
200 247
201 onMounted(() => { 248 onMounted(() => {
202 - (window as any).handleOpenDrawer = handleOpenDrawer 249 + ;(window as any).handleOpenDrawer = handleOpenDrawer
203 }) 250 })
204 251
205 onUnmounted(() => { 252 onUnmounted(() => {
206 - (window as any).handleOpenDrawer = null 253 + ;(window as any).handleOpenDrawer = null
207 }) 254 })
208 255
209 //地图鼠标hover 256 //地图鼠标hover
@@ -214,10 +261,9 @@ const mapClick = (markerInstance: any, markerItem: dataJsonMarkersType) => { @@ -214,10 +261,9 @@ const mapClick = (markerInstance: any, markerItem: dataJsonMarkersType) => {
214 // mouseover 261 // mouseover
215 markerInstance.on('click', async (e: any) => { 262 markerInstance.on('click', async (e: any) => {
216 const { extraInfo } = e.target.getExtData() 263 const { extraInfo } = e.target.getExtData()
217 - if (extraInfo.tbDeviceId.startsWith('@')) return //假的模拟数据则终止弹窗  
218 let infoWindow = new AMapIns.InfoWindow({ 264 let infoWindow = new AMapIns.InfoWindow({
219 - content: await createInfoWindow(extraInfo),  
220 - offset: new AMapIns.Pixel(3, -30) 265 + content: await createInfoWindow(extraInfo)
  266 + // offset: new AMapIns.Pixel(3, -30)
221 }) 267 })
222 infoWindow.open(mapIns, e.target.getPosition()) 268 infoWindow.open(mapIns, e.target.getPosition())
223 }) 269 })
@@ -238,13 +284,17 @@ const dataHandle = (newData: dataJsonType) => { @@ -238,13 +284,17 @@ const dataHandle = (newData: dataJsonType) => {
238 // 记录新标记 284 // 记录新标记
239 if (mapMarkerType.value === MarkerEnum.MARKER) { 285 if (mapMarkerType.value === MarkerEnum.MARKER) {
240 newData.markers.forEach((markerItem: dataJsonMarkersType) => { 286 newData.markers.forEach((markerItem: dataJsonMarkersType) => {
241 - console.log("🚀 ~ newData.markers.forEach ~ markerItem:", markerItem.extraInfo.deviceState) 287 + console.log('🚀 ~ newData.markers.forEach ~ markerItem:', markerItem.extraInfo.deviceState)
242 const markerInstance = new AMapIns.Marker({ 288 const markerInstance = new AMapIns.Marker({
243 position: [markerItem.position[0], markerItem.position[1]], 289 position: [markerItem.position[0], markerItem.position[1]],
244 offset: new AMapIns.Pixel(-13, 5), 290 offset: new AMapIns.Pixel(-13, 5),
245 icon: new AMapIns.Icon({ 291 icon: new AMapIns.Icon({
246 - // image: iconMarker.value,  
247 - image: markerItem.extraInfo.deviceState === 'ONLINE' ? online : markerItem.extraInfo.deviceState === 'INACTIVE' ? inactive : offline, 292 + image:
  293 + markerItem.extraInfo.deviceState === 'ONLINE'
  294 + ? online
  295 + : markerItem.extraInfo.deviceState === 'INACTIVE'
  296 + ? inactive
  297 + : offline,
248 size: new AMapIns.Size(35, 35), //图标所处区域大小 298 size: new AMapIns.Size(35, 35), //图标所处区域大小
249 imageSize: new AMapIns.Size(35, 35) //图标大小 299 imageSize: new AMapIns.Size(35, 35) //图标大小
250 }) 300 })
@@ -324,7 +374,10 @@ useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => { @@ -324,7 +374,10 @@ useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
324 } 374 }
325 375
326 .amap-info-content { 376 .amap-info-content {
  377 + width: 30rem;
  378 + height: 20rem;
327 overflow: hidden !important; 379 overflow: hidden !important;
  380 + position: relative;
328 } 381 }
329 382
330 /**去除高德地图原生弹窗*/ 383 /**去除高德地图原生弹窗*/
@@ -9,6 +9,7 @@ const tryRunFunction = (v: string) => { @@ -9,6 +9,7 @@ const tryRunFunction = (v: string) => {
9 } 9 }
10 10
11 export const JSONParse = (data: string) => { 11 export const JSONParse = (data: string) => {
  12 + if (!data) return
12 return JSON.parse(data, (k, v) => { 13 return JSON.parse(data, (k, v) => {
13 // 过滤函数字符串 14 // 过滤函数字符串
14 if (excludeParseEventKeyList.includes(k)) return v 15 if (excludeParseEventKeyList.includes(k)) return v
@@ -39,8 +39,13 @@ export const dragHandle = async (e: DragEvent) => { @@ -39,8 +39,13 @@ export const dragHandle = async (e: DragEvent) => {
39 newComponent.chartConfig.title = dropData.title 39 newComponent.chartConfig.title = dropData.title
40 newComponent.chartConfig.chartFrame = dropData.chartFrame 40 newComponent.chartConfig.chartFrame = dropData.chartFrame
41 } 41 }
42 -  
43 - setComponentPosition(newComponent, e.offsetX - newComponent.attr.w / 2, e.offsetY - newComponent.attr.h / 2) 42 + /**
  43 + * 修复火狐浏览器随便拖拽一个组件,默认位置都在左上角并遮住。
  44 + * 原因是浏览器兼容问题,火狐浏览器的offsetX和offsetY始终为0值,而应该使用layerX和layerY,其余浏览器使用offsetX和offsetY即可。
  45 + */
  46 + // 源码 setComponentPosition(newComponent, e.offsetX - newComponent.attr.w / 2, e.offsetY - newComponent.attr.h / 2)
  47 + setComponentPosition(newComponent, (e.offsetX === 0 ? (e as any).layerX: e.offsetX) - newComponent.attr.w / 2,(e.offsetY === 0 ? (e as any).layerY: e.offsetY) - newComponent.attr.h / 2)
  48 + //
44 chartEditStore.addComponentList(newComponent, false, true) 49 chartEditStore.addComponentList(newComponent, false, true)
45 chartEditStore.setTargetSelectChart(newComponent.id) 50 chartEditStore.setTargetSelectChart(newComponent.id)
46 loadingFinish() 51 loadingFinish()
@@ -14,6 +14,7 @@ const isSharePageMode = () => { @@ -14,6 +14,7 @@ const isSharePageMode = () => {
14 14
15 // THINGS_KIT 兼容之前的用户数据 15 // THINGS_KIT 兼容之前的用户数据
16 const compatibleOldUserDataHook = (fileData:object)=>{ 16 const compatibleOldUserDataHook = (fileData:object)=>{
  17 + if(!fileData) return
17 let userData:Recordable = fileData 18 let userData:Recordable = fileData
18 if(!Reflect.get(fileData,'pageConfig')){ 19 if(!Reflect.get(fileData,'pageConfig')){
19 userData={ 20 userData={