Commit e268d6d0c39f5f384600e630570b00b43c5dd108

Authored by xp.Huang
2 parents f1960079 dd543698

Merge branch 'ft' into 'main_dev'

feat(src/packages): 优化三维模型拖动时,webgl上下文丢失问题

See merge request yunteng/thingskit-view!134
Showing 24 changed files with 193 additions and 176 deletions
... ... @@ -111,7 +111,7 @@ export const getVideoUrl = (id: string) =>
111 111 })
112 112
113 113 //获取行政区域
114   -export const getGeoJsonMap = (code: number, level: string) =>
  114 +export const getGeoJsonMap = (code: number | string, level: string) =>
115 115 defHttp.get({
116 116 url: `${Api.GEOJSONURL}${code}/${level}`
117 117 })
... ...
... ... @@ -14,6 +14,26 @@ export const enum areaEnum {
14 14 TOWN = 'TOWN' //镇
15 15 }
16 16
  17 +//父级地区编码和级别接口
  18 +export interface HistoryParentType {
  19 + adcode: string | number
  20 + level: string
  21 +}
  22 +
  23 +//数据源接口
  24 +export interface dataPointI {
  25 + name: string
  26 + value: number[]
  27 + adcode: number
  28 + height: number
  29 + itemStyle: {
  30 + color: string
  31 + opacity: number
  32 + borderWidth: number
  33 + borderColor: string
  34 + }
  35 +}
  36 +
17 37 export const includes = []
18 38
19 39 export const option = {
... ... @@ -41,6 +61,9 @@ export const option = {
41 61 emphasis: {
42 62 label: {
43 63 show: true,
  64 + formatter: function (params: Recordable) {
  65 + return params.data.name ? params.data.name : ' '
  66 + },
44 67 textStyle: {
45 68 color: '#000',
46 69 fontSize: 14
... ... @@ -59,6 +82,9 @@ export const option = {
59 82 regionHeight: 3,
60 83 label: {
61 84 show: true,
  85 + formatter: function (params: Recordable) {
  86 + return params.data.name ? params.data.name : ' '
  87 + },
62 88 textStyle: {
63 89 color: '#fff',
64 90 fontSize: 14
... ...
... ... @@ -12,7 +12,7 @@ import { onMounted, ref, nextTick, PropType, toRefs, watch, reactive } from 'vue
12 12 import * as echarts from 'echarts'
13 13 import { registerMap } from 'echarts/core'
14 14 import 'echarts-gl'
15   -import config, { areaEnum } from './config'
  15 +import config, { areaEnum, dataPointI, HistoryParentType } from './config'
16 16 import { getGeoJsonMap } from '@/api/external/common'
17 17 import dataMaps from './data.json'
18 18
... ... @@ -73,28 +73,26 @@ props.chartConfig.option = {
73 73
74 74 //地图点击返回
75 75 const watchAdcode = async () => {
  76 + stopWatch()
76 77 if (props.chartConfig.option.drillingIn) {
77 78 //如果是从右边配置里设置的,比如点击四川省,然后点击返回
78 79 const savePopParent = saveHistoryParent.value.pop()
79   - let saveAdcode: any = savePopParent?.adcode
80   - saveLevelStr.level = savePopParent?.level as string
  80 + let saveAdcode = savePopParent?.adcode as string | number
  81 + saveLevelStr.level = savePopParent?.level
81 82 if (!savePopParent) {
82 83 saveAdcode = getParentAdcode(props.chartConfig.option.mapRegion.adcode)
83   - saveLevelStr.level = (regionMapParentArea as any)[props.chartConfig.option.mapRegion.saveSelect.levelStr]
  84 + saveLevelStr.level = (regionMapParentArea as Recordable)[props.chartConfig.option.mapRegion.saveSelect.levelStr]
84 85 }
85 86 if (saveAdcode === 0) {
86 87 saveAdcode = 'china'
87 88 saveLevelStr.level = 'COUNTRY'
88 89 }
89   - await getGeojson(saveAdcode)
  90 + const exist = await getGeojson(saveAdcode)
90 91 const adcode = saveAdcode === 100000 ? 'china' : saveAdcode
91   - props.chartConfig.option.geo3D.map = adcode
92   - props.chartConfig.option.series.forEach((item: any) => {
93   - if (item.type === 'map3D') item.map = adcode
94   - item.data = props.chartConfig.option.dataset
95   - })
96   - handleSetOption(chartInstance.value, props.chartConfig.option)
97   - handleDataPoint(adcode)
  92 + if (exist) {
  93 + //fix解决点击下钻返回后页面为空问题
  94 + props.chartConfig.option.mapRegion.adcode = adcode
  95 + }
98 96 }
99 97 }
100 98
... ... @@ -106,46 +104,40 @@ const regionMapParentArea = {
106 104 }
107 105
108 106 //地图点击
109   -const handleMap3DClick = async (params: any) => {
  107 +const handleMap3DClick = async (params: Recordable) => {
110 108 if (props.chartConfig.option.drillingIn) {
111 109 const { name } = params
112   - saveGeojson.value?.features.forEach((item: any) => {
  110 + saveGeojson.value?.features.forEach((item: Recordable) => {
113 111 if (item.properties.name === name) {
114 112 const level = item.properties.level.toUpperCase()
115 113 const adcode = item.properties.adcode
116 114 if (level === 'DISTRICT') return
117   - if(String(adcode).startsWith('15') && level===areaEnum.CITY) return
  115 + if (String(adcode).startsWith('15') && level === areaEnum.CITY) return
118 116 props.chartConfig.option.mapRegion.adcode = adcode
119 117 saveLevelStr.level = level
120 118 handleDataPoint(adcode)
121 119 saveHistoryParent.value.push({
122 120 adcode: item.properties.parent.adcode,
123   - level: (regionMapParentArea as any)[level]
  121 + level: (regionMapParentArea as Recordable)[level]
124 122 })
125 123 }
126 124 })
127 125 }
128 126 }
129 127
130   -const saveGeojson: any = ref({}) // 保存geojson
  128 +const saveGeojson: Recordable = ref({}) // 保存geojson
131 129
132 130 const chinaDefaultRegionId = ref(100000) //如果是china则adcode为100000
133 131
134   -const saveLevelStr = reactive({
135   - // 地区级别
136   - level: ''
  132 +// 保存地区级别
  133 +const saveLevelStr = reactive<{ level: string | undefined }>({
  134 + level: ''
137 135 })
138 136
139   -//父级地区编码和级别接口
140   -interface HistoryParentType {
141   - adcode: number
142   - level: string
143   -}
144   -
145 137 const saveHistoryParent = ref<HistoryParentType[]>([])
146 138
147 139 //动态注册地图
148   -const getGeojson = (regionId: any) => {
  140 +const getGeojson = (regionId: number | string) => {
149 141 try {
150 142 return new Promise<boolean>(resolve => {
151 143 const { levelStr } = props.chartConfig.option.mapRegion.saveSelect //右侧配置项获取的行政级别
... ... @@ -171,11 +163,10 @@ const getGeojson = (regionId: any) => {
171 163 }
172 164 }
173 165
174   -
175 166 //传adcode 获取上级
176 167 const getParentAdcode = (adcode: number) => {
177 168 let adcodeNum = 100000
178   - saveGeojson.value?.features.forEach((item: any) => {
  169 + saveGeojson.value?.features.forEach((item: Recordable) => {
179 170 if (item.properties.adcode === adcode) {
180 171 adcodeNum = item.properties.parent.adcode
181 172 }
... ... @@ -200,13 +191,13 @@ const initMap = async () => {
200 191 await nextTick().then(() => {
201 192 handleSetOption(chartInstance.value, props.chartConfig.option)
202 193 })
203   - chartInstance.value.on('click', (e: any) => {
  194 + chartInstance.value.on('click', (e: Recordable) => {
204 195 handleMap3DClick(e)
205 196 })
206 197 }
207 198
208 199 // 手动触发渲染
209   -const handleSetOption = (instance: any, option: any) => {
  200 +const handleSetOption = (instance: any, option: Recordable) => {
210 201 if (!instance) return
211 202 try {
212 203 instance.clear()
... ... @@ -221,22 +212,22 @@ onMounted(() => {
221 212 })
222 213
223 214 //处理数据标点
224   -const handleDataPoint = (newData: any) => {
  215 +const handleDataPoint = (newData: string | number) => {
225 216 if (newData === 'china') {
226 217 props.chartConfig.option.dataset = dataMaps
227 218 } else {
228   - props.chartConfig.option.dataset = dataMaps.filter((item: any) => item.adcode === newData)
  219 + props.chartConfig.option.dataset = dataMaps.filter((item: dataPointI) => item.adcode === newData)
229 220 }
230 221 }
231 222
232 223 //监听地图展示区域发生变化
233 224 watch(
234 225 () => `${props.chartConfig.option.mapRegion.adcode}`,
235   - async (newData: any) => {
  226 + async (newData: string | number) => {
236 227 try {
237 228 await getGeojson(newData)
238 229 props.chartConfig.option.geo3D.map = newData
239   - props.chartConfig.option.series.forEach((item: any) => {
  230 + props.chartConfig.option.series.forEach((item: Recordable) => {
240 231 if (item.type === 'map3D') {
241 232 item.map = newData
242 233 item.data = props.chartConfig.option.dataset
... ... @@ -254,7 +245,7 @@ watch(
254 245 )
255 246
256 247 // 监听地图右侧配置项变化
257   -watch(
  248 +const stopWatch = watch(
258 249 props.chartConfig.option,
259 250 async newData => {
260 251 try {
... ... @@ -273,7 +264,7 @@ watch(
273 264 () => props.chartConfig.option.dataset,
274 265 newData => {
275 266 try {
276   - props.chartConfig.option.series.forEach((item: any) => {
  267 + props.chartConfig.option.series.forEach((item: Recordable) => {
277 268 if (item.type === 'map3D') {
278 269 item.data = newData
279 270 }
... ...
... ... @@ -129,7 +129,7 @@ const loadList = async () => {
129 129 }
130 130
131 131 const handleSubmit = () => {
132   - searchParams.deviceProfileIds = [searchParams.deviceProfileIds] as any
  132 + // searchParams.deviceProfileIds = [searchParams.deviceProfileIds] as any
133 133 emit('searchParams', searchPage, searchParams)
134 134 handleCancel()
135 135 }
... ...
... ... @@ -88,10 +88,11 @@ export const option = {
88 88 amapLon: 104.108689,
89 89 amapLat: 30.66176,
90 90 amapZindex: 11,
91   - typeMarker: '',
  91 + iconMarker: '1.png',
92 92 mpBorderConfig: {
93   - value: 'Border01',
  93 + value: 'Border01'
94 94 },
  95 + bgColor: 'rgba(255, 255, 255, 0.1)',
95 96 marker: {
96 97 fillColor: '#E98984FF',
97 98 fillOpacity: 0.5,
... ...
... ... @@ -81,8 +81,8 @@
81 81 size="small"
82 82 placeholder="请选择您要使用的图标"
83 83 style="width: 250px"
84   - :value="typeMarkerValue"
85   - :options="typeMarkerOptions"
  84 + :value="iconMarkerValue"
  85 + :options="iconMarkerOptions"
86 86 :render-label="renderOption"
87 87 clearable
88 88 filterable
... ... @@ -92,16 +92,6 @@
92 92 </setting-item-box>
93 93 <setting-item-box name="弹窗选择" v-if="optionData.mapOptions.mapMarkerType === MarkerEnum.MARKER">
94 94 <setting-item name="弹窗选择">
95   - <!-- <NSelect
96   - size="small"
97   - placeholder="请选择您要使用的弹窗"
98   - style="width: 250px"
99   - :value="mapSelectBorderValue"
100   - :options="mapSelectBorderOption.option"
101   - @update:value="mapSelectBorderHandle"
102   - clearable
103   - filterable
104   - /> -->
105 95 <NSelect
106 96 size="small"
107 97 placeholder="请选择您要使用的弹窗"
... ... @@ -115,11 +105,16 @@
115 105 />
116 106 </setting-item>
117 107 </setting-item-box>
  108 + <setting-item-box name="弹窗背景" v-if="optionData.mapOptions.mapMarkerType === MarkerEnum.MARKER">
  109 + <div style="width: 10vw">
  110 + <n-color-picker :modes="['rgb']" v-model:value="optionData.mapOptions.bgColor" size="small"></n-color-picker>
  111 + </div>
  112 + </setting-item-box>
118 113 </collapse-item>
119 114 </template>
120 115
121 116 <script setup lang="ts">
122   -import { PropType, ref, computed, h, onMounted, reactive } from 'vue'
  117 +import { PropType, ref, computed, h, onMounted } from 'vue'
123 118 import { option, MarkerEnum, ThemeEnum, LangEnum, ViewModeEnum, FeaturesEnum } from './config'
124 119 import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
125 120 import { NEllipsis, NImage, NSelect, NSpace, SelectOption } from 'naive-ui'
... ... @@ -234,7 +229,7 @@ const featuresOptions = [
234 229 const MarkerOptions = [
235 230 // {
236 231 // value: MarkerEnum.CIRCLE_MARKER,
237   - // label: '圆形标点'
  232 + // label: '圆形标点' //在地图里点击无效,所以注释,有需要自行打开即可
238 233 // },
239 234 {
240 235 value: MarkerEnum.MARKER,
... ... @@ -246,17 +241,7 @@ const MarkerOptions = [
246 241 }
247 242 ]
248 243
249   -onMounted(() => {
250   - props.optionData.mapOptions.typeMarker = getMarkerImagePath(props.optionData.mapOptions.typeMarker || 'position1.png')
251   - typeMarkerValue.value = props.optionData.mapOptions.typeMarker || 'position1.png'
252   - mapSelectBorderValue.value =
253   - `${props.optionData.mapOptions.mpBorderConfig.value.toLocaleLowerCase()}.png` || 'border01.png'
254   -})
255   -
256   -const typeMarkerValue = ref<string | null>('position1.png')
257   -
258   -const mapSelectBorderValue = ref<string | null>('border01.png')
259   -
  244 +/**通用函数封装 */
260 245 const isHref = (url: string) => {
261 246 try {
262 247 new URL(url)
... ... @@ -265,81 +250,86 @@ const isHref = (url: string) => {
265 250 return false
266 251 }
267 252 }
  253 +const renderCommonOption = (option: SelectOption, src: string) => {
  254 + return h(NSpace, { justify: 'space-between', style: 'padding: 0 15px; height: 28px; line-height: 28px;' }, () => [
  255 + h(NImage, {
  256 + width: 25,
  257 + src,
  258 + previewDisabled: true,
  259 + style: { height: '25px' }
  260 + } as Recordable),
  261 + h(NEllipsis, null, () => option.label)
  262 + ])
  263 +}
  264 +const getImagePath = (path: string, name: string) => {
  265 + return isHref(name) ? name : new URL(`${path}/${name}`, import.meta.url).href
  266 +}
  267 +/** */
  268 +
  269 +/** 图标选择 */
  270 +const iconMarkerValue = ref<string | null>('1.png')
268 271
269   -// import.meta.glob 这个不能封装,必须是字符串,不能通过传值传进去
270   -const typeMarkerOptions = computed(() => {
  272 +// import.meta.glob 这里没有封装,不能通过传值传进去
  273 +const iconMarkerOptions = computed(() => {
271 274 const pathList = import.meta.glob('./images/marker/*')
272 275 return Object.keys(pathList).map(item => {
273 276 const imgName = item.split('/').at(-1)
274 277 return {
275 278 label: imgName,
276 279 value: imgName
277   - } as SelectOption
  280 + }
278 281 })
279 282 })
280 283 //
281 284
282   -const getMarkerImagePath = (name: string) => {
283   - return isHref(name) ? name : new URL(`./images/marker/${name}`, import.meta.url).href
284   -}
  285 +const getMarkerImagePath = (name: string) => getImagePath('./images/marker', name)
285 286
286   -const renderOption = (option: SelectOption) => {
287   - return h(NSpace, { justify: 'space-between', style: 'padding: 0 15px; height: 28px; line-height: 28px;' }, () => [
288   - h(NImage, {
289   - width: 25,
290   - src: getMarkerImagePath(option.value as string),
291   - previewDisabled: true,
292   - style: { height: '25px' }
293   - } as Recordable),
294   - h(NEllipsis, null, () => option.label)
295   - ])
296   -}
  287 +const renderOption = (option: SelectOption) => renderCommonOption(option, getMarkerImagePath(option.value as string))
297 288
298 289 const selectHandle = (value: string) => {
299   - typeMarkerValue.value = value
300   - props.optionData.mapOptions.typeMarker = getMarkerImagePath(value)
  290 + iconMarkerValue.value = value
  291 + props.optionData.mapOptions.iconMarker = getMarkerImagePath(value)
301 292 }
  293 +/** */
  294 +
  295 +/** 弹窗选择 */
  296 +const mapSelectBorderValue = ref<string | null>('border01.png')
302 297
303 298 const needBorder = ['border01.png', 'border02.png', 'border03.png', 'border05.png', 'border07.png']
304 299
305   -// import.meta.glob 这个不能封装,必须是字符串,不能通过传值传进去
  300 +// import.meta.glob 这里没有封装,不能通过传值传进去
306 301 const mapBorderOptions = computed(() => {
307 302 const pathList = import.meta.glob('../../../../../../assets/images/chart/decorates/*')
308 303 return Object.keys(pathList)
309 304 .map(item => {
310 305 const imgName = item.split('/').at(-1) as string
311   - if (needBorder.includes(imgName)) {
312   - return {
313   - label: imgName,
314   - value: imgName
315   - } as SelectOption
316   - }
  306 + if (!needBorder.includes(imgName)) return
  307 + return {
  308 + label: imgName,
  309 + value: imgName
  310 + } as SelectOption
317 311 })
318 312 .filter(Boolean) as SelectOption[]
319 313 })
320 314 //
321 315
322   -const getMapBorderImagePath = (name: string) => {
323   - return isHref(name) ? name : new URL(`../../../../../../assets/images/chart/decorates/${name}`, import.meta.url).href
324   -}
  316 +const getMapBorderImagePath = (name: string) => getImagePath('../../../../../../assets/images/chart/decorates', name)
325 317
326   -const renderMapBorderOption = (option: SelectOption) => {
327   - return h(NSpace, { justify: 'space-between', style: 'padding: 0 15px; height: 28px; line-height: 28px;' }, () => [
328   - h(NImage, {
329   - width: 25,
330   - src: getMapBorderImagePath(option.value as string),
331   - previewDisabled: true,
332   - style: { height: '25px' }
333   - } as Recordable),
334   - h(NEllipsis, null, () => option.label)
335   - ])
336   -}
  318 +const renderMapBorderOption = (option: SelectOption) =>
  319 + renderCommonOption(option, getMapBorderImagePath(option.value as string))
337 320
338 321 const selectMapBorderHandle = (value: string) => {
339 322 mapSelectBorderValue.value = value
340 323 const toLowerValue = value.toLocaleLowerCase()
341 324 ;(props.optionData.mapOptions.mpBorderConfig as BaseSelectBorderIF) = {
342   - value: toLowerValue[0]?.toUpperCase() + toLowerValue?.substr(1)?.split('.')[0]
343   - }
  325 + value: toLowerValue[0]?.toUpperCase() + toLowerValue?.substring(1)?.split('.')[0]
  326 + } //这里首字母转大写,动态引入时匹配对应目录也是大写字母开头,即components\Decorates\Borders\Border01
344 327 }
  328 +/** */
  329 +
  330 +onMounted(() => {
  331 + iconMarkerValue.value = props.optionData.mapOptions.iconMarker?.split('/')?.at(-1) as string
  332 + props.optionData.mapOptions.iconMarker = getMarkerImagePath(iconMarkerValue.value)
  333 + mapSelectBorderValue.value = `${props.optionData.mapOptions.mpBorderConfig.value?.toLocaleLowerCase()}.png`
  334 +})
345 335 </script>
... ...
src/packages/components/external/Charts/Maps/OverrideMapAmap/images/marker/1.png renamed from src/packages/components/external/Charts/Maps/OverrideMapAmap/images/marker/position1.png

1.24 KB

src/packages/components/external/Charts/Maps/OverrideMapAmap/images/marker/2.png renamed from src/packages/components/external/Charts/Maps/OverrideMapAmap/images/marker/position2.png

1.4 KB

src/packages/components/external/Charts/Maps/OverrideMapAmap/images/marker/3.png renamed from src/packages/components/external/Charts/Maps/OverrideMapAmap/images/marker/position3.png

904 Bytes

src/packages/components/external/Charts/Maps/OverrideMapAmap/images/marker/4.png renamed from src/packages/components/external/Charts/Maps/OverrideMapAmap/images/marker/position4.png

1.02 KB

src/packages/components/external/Charts/Maps/OverrideMapAmap/images/marker/5.png renamed from src/packages/components/external/Charts/Maps/OverrideMapAmap/images/marker/position5.png

970 Bytes

1 1 <template>
2 2 <div @mouseenter="handleMouseenter" @mouseleave="handleMouseleave" class="chart-amap" ref="vChartRef">
3   - <div v-show="showSearchBox" @click.stop="handleOpenSearchBox" class="search-box"></div>
4   - <search-box :modelShow="modelShow" @searchParams="handleSearchParams" @closeDrawer="handleCloseDrawer"></search-box>
  3 + <!-- <div v-show="showSearchBox" @click.stop="handleOpenSearchBox" class="search-box"></div>
  4 + <search-box :modelShow="modelShow" @searchParams="handleSearchParams" @closeDrawer="handleCloseDrawer"></search-box> -->
5 5 </div>
6 6 </template>
7 7
... ... @@ -16,7 +16,7 @@ import { isArray } from '@/utils'
16 16 import djh from './images/djh.png'
17 17 import online from './images/online.png'
18 18 import lx1 from './images/lx1.png'
19   -import positionImg from './images/marker/position1.png'
  19 +import onLineImg from './images/marker/3.png'
20 20 import { getDeviceActiveTime, getDeviceList } from '@/api/external/common/index'
21 21 import dayjs from 'dayjs'
22 22 import SearchBox from './components/SearchBox.vue'
... ... @@ -32,7 +32,7 @@ const modelShow = ref(false)
32 32
33 33 const showSearchBox = ref(false)
34 34
35   -let {
  35 +const {
36 36 amapKey,
37 37 amapStyleKey,
38 38 amapLon,
... ... @@ -46,8 +46,9 @@ let {
46 46 pitch,
47 47 skyColor,
48 48 marker,
49   - typeMarker,
50   - mpBorderConfig
  49 + iconMarker,
  50 + mpBorderConfig,
  51 + bgColor
51 52 } = toRefs(props.chartConfig.option.mapOptions)
52 53
53 54 //官方没有高德地图api的ts,所以类型全用的any
... ... @@ -104,7 +105,7 @@ const createInfoWindow = async (extraInfo: dataExtraInfoType) => {
104 105 const res = await getDeviceActiveTime(tbDeviceId) //查询设备最后离线时间
105 106 let { lastUpdateTs } = res[0]
106 107 const lastUpdateFormatTs = dayjs(lastUpdateTs).format('YYYY-MM-DD HH:mm:ss')
107   - //render方式渲染小组件里的边框组件
  108 + //render方式渲染小组件里的边框组件
108 109 const BorderInstance = await import(`../../../../Decorates/Borders/${mpBorderConfig.value.value}/index.vue`)
109 110 const config = await import(`../../../../Decorates/Borders/${mpBorderConfig.value.value}/config.ts`)
110 111 const BorderConfigInstance = new config.default()
... ... @@ -132,7 +133,7 @@ const createInfoWindow = async (extraInfo: dataExtraInfoType) => {
132 133 </div>
133 134 <div style="color:white;">所属组织:${organizationDTO.name}</div>
134 135 <div style="margin-top:6px;color:white">接入协议:${deviceProfile.transportType}</div>
135   - <div style="margin-top:6px;color:white">
  136 + <div style="margin-top:6px;color:white;width:15vw;text-overflow: ellipsis;overflow: hidden; word-break: break-all;white-space: nowrap;">
136 137 设备位置:${!deviceInfo.address ? '该设备暂无地理位置' : deviceInfo.address}
137 138 </div>
138 139 <div style="margin-top:6px;color:white">
... ... @@ -158,10 +159,15 @@ const handleCloseDrawer = () => (modelShow.value = false)
158 159
159 160 const handleSearchParams = async (searchPage: any, params: any) => {
160 161 try {
  162 + Object.keys(params).forEach(item => {
  163 + if (!params[item]) Reflect.deleteProperty(params, item)
  164 + })
161 165 const { items } = await getDeviceList(searchPage, params)
162 166 const values = filterDevice(items)
163 167 if (!values) return
164   - dataHandle(values)
  168 + setTimeout(() => {
  169 + dataHandle(values)
  170 + }, 1000)
165 171 } finally {
166 172 handleCloseDrawer()
167 173 }
... ... @@ -198,10 +204,11 @@ const dataHandle = (newData: dataJsonType) => {
198 204 // 记录新标记
199 205 if (mapMarkerType.value === MarkerEnum.MARKER) {
200 206 newData.markers.forEach((markerItem: dataJsonMarkersType) => {
  207 + const { deviceState } = markerItem.extraInfo
201 208 const markerInstance = new AMapIns.Marker({
202 209 position: [markerItem.position[0], markerItem.position[1]],
203 210 offset: new AMapIns.Pixel(-13, -30),
204   - icon: typeMarker.value || positionImg
  211 + icon: deviceState === 'ONLINE' ? onLineImg : iconMarker.value
205 212 })
206 213 // markers.push(markerInstance) 原作者这种方式添加,属于JS API 1.4.8版本的
207 214 // markerInstance.setMap(mapIns)
... ... @@ -255,7 +262,9 @@ watch(
255 262 // 预览
256 263 useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
257 264 stopWatch()
258   - dataHandle(newData)
  265 + setTimeout(() => {
  266 + dataHandle(newData)
  267 + }, 1000)
259 268 })
260 269 </script>
261 270
... ... @@ -271,15 +280,9 @@ useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
271 280 }
272 281 .amap-info-content .go-border-box {
273 282 position: absolute;
274   - transform: scale(0.7);
  283 + transform: scale(0.68);
275 284 top: -10px;
276   - /* opacity: 0,8; */
277   - /* background-color: rgba(0, 0, 0, 0.1); */
278   - background-color:rgba(255,255,255,0.1)
279   -}
280   -.amap-info-content .go-border-box svg {
281   - /* background-color: rgba(0, 0, 0, 0.1); */
282   - /* background-color: rgba(255, 255, 255, 0.8); */
  285 + background-color: v-bind(bgColor);
283 286 }
284 287 </style>
285 288 <style lang="scss" scoped>
... ...
... ... @@ -5,7 +5,7 @@ import cloneDeep from 'lodash/cloneDeep'
5 5 import { chartInitConfig } from '@/settings/designSetting'
6 6
7 7 export const option = {
8   - dataset: [new URL('/src/assets/external/three/test.obj', import.meta.url).href],//三维数据源
  8 + dataset: [new URL('/src/assets/external/three/test.obj', import.meta.url).href], //三维数据源
9 9 backgroundColor: '', //场景背景色
10 10 backgroundAlpha: 0, //场景透明度
11 11 enableDamping: false, //是否启用阻尼
... ... @@ -18,7 +18,9 @@ export const option = {
18 18 */
19 19 outputEncoding: 'liner',
20 20 clearScene: false, //是否清空场景内容
21   - lights: [//灯光为数组,type 为 环境光(AmbientLight) | 方向光(DirectionalLight) | 点光(PointLight) | 半球光(HemisphereLight)
  21 + lightInput: 1,
  22 + lights: [
  23 + //灯光为数组,type 为 环境光(AmbientLight) | 方向光(DirectionalLight) | 点光(PointLight) | 半球光(HemisphereLight)
22 24 {
23 25 type: 'AmbientLight',
24 26 label: '环境光(只有颜色)',
... ... @@ -54,38 +56,41 @@ export const option = {
54 56 size: 1,
55 57 show: false
56 58 },
57   - position: [//模型位置
  59 + position: [
  60 + //模型位置
58 61 {
59 62 x: 0,
60 63 y: 0,
61 64 z: 0
62 65 }
63 66 ],
64   - rotation: [//模型旋转
  67 + rotation: [
  68 + //模型旋转
65 69 {
66 70 x: 0,
67 71 y: 0,
68 72 z: 0
69 73 }
70 74 ],
71   - showFps:false,//是否显示fps
72   - labels:[ //添加图片/文字标签,暂且支持文字
  75 + showFps: false, //是否显示fps
  76 + labels: [
  77 + //添加图片/文字标签,暂且支持文字
73 78 {
74   - image: "",
75   - text: "",
  79 + image: '',
  80 + text: '',
76 81 textStyle: {
77   - fontFamily: "Arial",
  82 + fontFamily: 'Arial',
78 83 fontSize: 18,
79   - fontWeight: "normal",
  84 + fontWeight: 'normal',
80 85 lineHeight: 1,
81   - color: "#ffffff",
  86 + color: '#ffffff',
82 87 borderWidth: 8,
83 88 borderRadius: 4,
84   - borderColor: "rgba(0,0,0,1)",
85   - backgroundColor: "rgba(0, 0, 0, 1)"
  89 + borderColor: 'rgba(0,0,0,1)',
  90 + backgroundColor: 'rgba(0, 0, 0, 1)'
86 91 },
87   - position: {x:0, y:0, z:0},
88   - scale:{x:1, y:1, z:0},
  92 + position: { x: 0, y: 0, z: 0 },
  93 + scale: { x: 1, y: 1, z: 0 },
89 94 sid: null
90 95 }
91 96 ]
... ...
... ... @@ -11,15 +11,15 @@
11 11 <n-input-number :min="0" v-model:value="optionData.borderConfig.size" size="small" />
12 12 </setting-item>
13 13 </setting-item-box>
14   - <setting-item-box name="上传文件">
  14 + <setting-item-box name="上传文件">
15 15 <setting-item>
16 16 <FileUpload
17   - :max="100"
18   - :fileList="optionData.dataset"
19   - :threeSupportFileFormat="threeSupportFileFormat"
20   - :singleFileType="singleFileTypeNotMtl"
21   - @fileStaticUri="handleFileStaticUri"
22   - />
  17 + :max="100"
  18 + :fileList="optionData.dataset"
  19 + :threeSupportFileFormat="threeSupportFileFormat"
  20 + :singleFileType="singleFileTypeNotMtl"
  21 + @fileStaticUri="handleFileStaticUri"
  22 + />
23 23 </setting-item>
24 24 </setting-item-box>
25 25 <setting-item-box :alone="true">
... ... @@ -78,8 +78,13 @@
78 78 </template>
79 79 </setting-item>
80 80 </setting-item-box>
  81 + <setting-item-box name="灯光选择">
  82 + <setting-item name="灯光选择((0,环境光),(1,方向光),(2,点光),(3,半球光))">
  83 + <n-input-number :min="0" :max="3" v-model:value="optionData.lightInput" size="small" />
  84 + </setting-item>
  85 + </setting-item-box>
81 86 <setting-item-box name="灯光配置">
82   - <setting-item v-for="(item, index) in optionData.lights" :name="item.label" :key="index">
  87 + <setting-item v-for="(item, index) in [optionData.lights[optionData.lightInput]]" :name="item.label" :key="index">
83 88 <n-color-picker
84 89 v-if="!includeHemisphereLight.includes(item.type)"
85 90 size="small"
... ... @@ -180,15 +185,9 @@
180 185 <SettingItem v-if="optionData.enableDamping" name="阻尼值">
181 186 <n-input-number v-model:value="optionData.dampingFactor" :min="0" :max="1" size="small"></n-input-number>
182 187 </SettingItem>
183   - <SettingItem name="启用动画">
184   - <n-switch v-model:value="optionData.autoPlay" size="small" />
185   - </SettingItem>
186   - <SettingItem name="输出编码">
  188 + <SettingItem name="输出编码,可取值为 liner 或 sRGB。linear 是 LinearEncoding 线性编码, sRGB 即 sRGBEncoding rgb 模式编码(sRGBEncoding 能更好的还原材质颜色)">
187 189 <n-select v-model:value="optionData.outputEncoding" size="small" :options="encodinghList"></n-select>
188 190 </SettingItem>
189   - <SettingItem name="是否清空场景">
190   - <n-switch @change="handleChange" v-model:value="optionData.clearScene" size="small" />
191   - </SettingItem>
192 191 </setting-item-box>
193 192 </collapse-item>
194 193 </template>
... ... @@ -253,10 +252,6 @@ const encodinghList = [
253 252 { label: 'sRGB ', value: 'sRGB ' }
254 253 ]
255 254
256   -const handleChange = (e: boolean) => {
257   - if (e) props.optionData.dataset = ['']
258   -}
259   -
260 255 const handleFileStaticUri = (value: UploadFileInfo[]) => {
261 256 props.optionData.dataset = value.map(item => item?.url)?.filter(Boolean) as any
262 257 if (Array.isArray(props.optionData.dataset) && props.optionData.dataset.length === 0) {
... ...
1 1 <template>
2   - <div class="go-content-box" :style="{ border: !borderConfig.show ? 'none' : ''}">
3   - <div v-if="useDetectWebGLContext()">
  2 + <div class="go-content-box" :style="{ border: !borderConfig.show ? 'none' : '' }">
  3 + <div>
4 4 <vue3dLoader
5 5 ref="vue3dLoaderRef"
6 6 :webGLRendererOptions="webGLRendererOptions"
... ... @@ -20,7 +20,7 @@
20 20 @load="onLoad"
21 21 :position="position"
22 22 :rotation="rotation"
23   - :lights="lights"
  23 + :lights="[lights[lightInput]]"
24 24 :showFps="showFps"
25 25 :labels="labels"
26 26 />
... ... @@ -29,15 +29,13 @@
29 29 <n-progress type="line" :color="themeColor" :percentage="process" :indicator-placement="'inside'" processing />
30 30 </div>
31 31 </div>
32   - <div v-else>您的浏览器不支持WebGL!</div>
33 32 </div>
34 33 </template>
35 34 <script setup lang="ts">
36   -import { PropType, toRefs, ref, nextTick, computed, watch } from 'vue'
  35 +import { PropType, toRefs, ref, nextTick, computed } from 'vue'
37 36 import { CreateComponentType } from '@/packages/index.d'
38 37 import { vue3dLoader } from 'vue-3d-loader'
39 38 import { useDesignStore } from '@/store/modules/designStore/designStore'
40   -import { useDetectWebGLContext } from '@/utils/external/useSupportWebGL'
41 39
42 40 const designStore = useDesignStore()
43 41
... ... @@ -54,7 +52,6 @@ const themeColor = computed(() => {
54 52
55 53 const vue3dLoaderRef = ref(null)
56 54
57   -//threejs配置
58 55 const webGLRendererOptions = {
59 56 alpha: true, // 透明
60 57 antialias: true, // 抗锯齿
... ... @@ -96,13 +93,9 @@ const {
96 93 rotation,
97 94 lights,
98 95 showFps,
99   - labels
100   -} = toRefs(props.chartConfig.option) as any
101   -
102   -watch(dataset, (newData: string) => {
103   - //dateset为空则清除场景
104   - if(!newData) clearScene.value=true
105   -})
  96 + labels,
  97 + lightInput
  98 +} = toRefs(props.chartConfig.option) as any
106 99 </script>
107 100
108 101 <style lang="scss" scoped>
... ...
1 1 <template>
2 2 <div>
3 3 <n-tree
  4 + ref="nTreeRef"
4 5 :accordion="treeConfig.accordion"
5 6 :checkable="treeConfig.checkable"
6 7 :default-expand-all="treeConfig.defaultExpandAll"
... ... @@ -11,17 +12,20 @@
11 12 label-field="name"
12 13 children-field="children"
13 14 @update:selected-keys="onClick"
  15 + @update:checked-keys="onClick"
  16 + :checked-keys="checkedKeys"
14 17 />
15 18 </div>
16 19 </template>
17 20
18 21 <script setup lang="ts">
19   -import { PropType, toRefs } from 'vue'
  22 +import { PropType, toRefs, ref } from 'vue'
20 23 import { CreateComponentType } from '@/packages/index.d'
21 24 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
22 25 import { useChartInteract } from '@/hooks/external/useChartSelectInteract.hook'
23 26 import { InteractEventOn } from '@/enums/eventEnum'
24 27 import { ComponentInteractParamsEnum } from './interact'
  28 +import { NTree } from 'naive-ui'
25 29
26 30 const props = defineProps({
27 31 chartConfig: {
... ... @@ -32,7 +36,16 @@ const props = defineProps({
32 36
33 37 const { dataset, treeConfig } = toRefs(props.chartConfig.option)
34 38
  39 +const nTreeRef = ref<null | InstanceType<typeof NTree>>(null)
  40 +
  41 +const checkedKeys = ref([])
  42 +
35 43 const onClick = (v: string[]) => {
  44 + // nTreeRef.value?.selectedKeys(v)
  45 + console.log(nTreeRef.value)
  46 + console.log(v)
  47 + // nTreeRef.value?.onUpdateCheckedKeys(v)
  48 + if (Array.isArray(v) && v.length == 0) return
36 49 useChartInteract(
37 50 props.chartConfig,
38 51 useChartEditStore,
... ...