Commit d61d4d358399c9289238573d5cb8c328223bc8be
1 parent
0f13f3c4
feat(src/packages): 图表3d地图也支持下钻 修改地图注册方式为服务端接口请求
Showing
5 changed files
with
89 additions
and
49 deletions
| @@ -24,7 +24,8 @@ const selectOptions = reactive({ | @@ -24,7 +24,8 @@ const selectOptions = reactive({ | ||
| 24 | const selectValues = reactive({ | 24 | const selectValues = reactive({ |
| 25 | provinceValue: 'china', | 25 | provinceValue: 'china', |
| 26 | cityValue: null, | 26 | cityValue: null, |
| 27 | - countyValue: null | 27 | + countyValue: null, |
| 28 | + levelStr: areaEnum.COUNTRY | ||
| 28 | }) | 29 | }) |
| 29 | 30 | ||
| 30 | const getAreaLists = async (level = areaEnum.PROVINCE, parentId = 1) => { | 31 | const getAreaLists = async (level = areaEnum.PROVINCE, parentId = 1) => { |
| @@ -49,13 +50,15 @@ onMounted(async () => { | @@ -49,13 +50,15 @@ onMounted(async () => { | ||
| 49 | const onHandleSelectProvince = async (value: number | string) => { | 50 | const onHandleSelectProvince = async (value: number | string) => { |
| 50 | selectValues.cityValue = null | 51 | selectValues.cityValue = null |
| 51 | selectValues.countyValue = null | 52 | selectValues.countyValue = null |
| 52 | - if (value === 'china') return | 53 | + if (value === 'china') return (selectValues.levelStr = areaEnum.COUNTRY) |
| 53 | selectOptions.cityOptions = await getAreaLists(areaEnum.CITY, value as any) | 54 | selectOptions.cityOptions = await getAreaLists(areaEnum.CITY, value as any) |
| 55 | + selectValues.levelStr = areaEnum.PROVINCE | ||
| 54 | } | 56 | } |
| 55 | 57 | ||
| 56 | const onHandleSelectCity = async (value: number) => { | 58 | const onHandleSelectCity = async (value: number) => { |
| 57 | selectValues.countyValue = null | 59 | selectValues.countyValue = null |
| 58 | selectOptions.countryOptions = await getAreaLists(areaEnum.COUNTY, value) | 60 | selectOptions.countryOptions = await getAreaLists(areaEnum.COUNTY, value) |
| 61 | + selectValues.levelStr = areaEnum.CITY | ||
| 59 | } | 62 | } |
| 60 | 63 | ||
| 61 | const onHandleSubmit = () => { | 64 | const onHandleSubmit = () => { |
| @@ -7,9 +7,11 @@ import dataMaps from './data.json' | @@ -7,9 +7,11 @@ import dataMaps from './data.json' | ||
| 7 | 7 | ||
| 8 | //省市区枚举 | 8 | //省市区枚举 |
| 9 | export const enum areaEnum { | 9 | export const enum areaEnum { |
| 10 | - PROVINCE = 'PROVINCE', | ||
| 11 | - CITY = 'CITY', | ||
| 12 | - COUNTY = 'COUNTY' | 10 | + PROVINCE = 'PROVINCE', //省份 |
| 11 | + CITY = 'CITY', //城市 | ||
| 12 | + COUNTY = 'COUNTY', //县 | ||
| 13 | + COUNTRY = 'COUNTRY', //国家 | ||
| 14 | + TOWN = 'TOWN' //镇 | ||
| 13 | } | 15 | } |
| 14 | 16 | ||
| 15 | export const includes = [] | 17 | export const includes = [] |
| @@ -24,34 +26,28 @@ export const option = { | @@ -24,34 +26,28 @@ export const option = { | ||
| 24 | mapRegion: { | 26 | mapRegion: { |
| 25 | adcode: 'china', | 27 | adcode: 'china', |
| 26 | showHainanIsLands: true, | 28 | showHainanIsLands: true, |
| 27 | - saveSelect: {} | 29 | + saveSelect: { |
| 30 | + levelStr: areaEnum.COUNTRY | ||
| 31 | + } | ||
| 28 | }, | 32 | }, |
| 29 | tooltip: { | 33 | tooltip: { |
| 30 | show: true | 34 | show: true |
| 31 | }, | 35 | }, |
| 32 | geo3D: { | 36 | geo3D: { |
| 37 | + show: false, // 隐藏该层,为true时会导致出现两个地图 | ||
| 33 | map: 'centerMap', | 38 | map: 'centerMap', |
| 34 | roam: true, | 39 | roam: true, |
| 35 | regionHeight: 0, | 40 | regionHeight: 0, |
| 36 | - label: { | ||
| 37 | - show: true, | ||
| 38 | - textStyle: { | ||
| 39 | - fontSize: 14, | ||
| 40 | - color: 'blue', | ||
| 41 | - borderWidth: 0, | ||
| 42 | - borderColor: '#000' | ||
| 43 | - } | ||
| 44 | - }, | ||
| 45 | emphasis: { | 41 | emphasis: { |
| 46 | label: { | 42 | label: { |
| 47 | show: true, | 43 | show: true, |
| 48 | textStyle: { | 44 | textStyle: { |
| 49 | - color: 'black', | ||
| 50 | - fontSize: 32 | 45 | + color: '#000', |
| 46 | + fontSize: 14 | ||
| 51 | } | 47 | } |
| 52 | }, | 48 | }, |
| 53 | itemStyle: { | 49 | itemStyle: { |
| 54 | - color: '#fd9c5a' | 50 | + color: '#ff0' |
| 55 | } | 51 | } |
| 56 | } | 52 | } |
| 57 | }, | 53 | }, |
| @@ -63,8 +59,10 @@ export const option = { | @@ -63,8 +59,10 @@ export const option = { | ||
| 63 | regionHeight: 3, | 59 | regionHeight: 3, |
| 64 | label: { | 60 | label: { |
| 65 | show: true, | 61 | show: true, |
| 66 | - color: 'yellow', | ||
| 67 | - fontSize: 14 | 62 | + textStyle: { |
| 63 | + color: '#fff', | ||
| 64 | + fontSize: 14 | ||
| 65 | + } | ||
| 68 | }, | 66 | }, |
| 69 | itemStyle: { | 67 | itemStyle: { |
| 70 | color: 'green', | 68 | color: 'green', |
| @@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
| 2 | <!-- Echarts 全局设置 --> | 2 | <!-- Echarts 全局设置 --> |
| 3 | <global-setting :optionData="optionData"></global-setting> | 3 | <global-setting :optionData="optionData"></global-setting> |
| 4 | <CollapseItem name="地图" :expanded="true"> | 4 | <CollapseItem name="地图" :expanded="true"> |
| 5 | - <!-- <SettingItemBox name="开启下钻"> | 5 | + <SettingItemBox name="开启下钻"> |
| 6 | <SettingItem name=""> | 6 | <SettingItem name=""> |
| 7 | <n-switch v-model:value="optionData.drillingIn" size="small"></n-switch> | 7 | <n-switch v-model:value="optionData.drillingIn" size="small"></n-switch> |
| 8 | </SettingItem> | 8 | </SettingItem> |
| @@ -34,7 +34,7 @@ | @@ -34,7 +34,7 @@ | ||
| 34 | placeholder="请输入" | 34 | placeholder="请输入" |
| 35 | ></n-input-number> | 35 | ></n-input-number> |
| 36 | </SettingItem> | 36 | </SettingItem> |
| 37 | - </SettingItemBox> --> | 37 | + </SettingItemBox> |
| 38 | <SelectCity :optionData="optionData" :drillingIn="optionData.drillingIn" @submit="onHandleSelectValues" /> | 38 | <SelectCity :optionData="optionData" :drillingIn="optionData.drillingIn" @submit="onHandleSelectValues" /> |
| 39 | <SettingItemBox name="颜色"> | 39 | <SettingItemBox name="颜色"> |
| 40 | <SettingItem name="区域颜色"> | 40 | <SettingItem name="区域颜色"> |
| @@ -69,11 +69,15 @@ | @@ -69,11 +69,15 @@ | ||
| 69 | <n-switch v-model:value="seriesList[0].label.show" size="small"></n-switch> | 69 | <n-switch v-model:value="seriesList[0].label.show" size="small"></n-switch> |
| 70 | </SettingItem> | 70 | </SettingItem> |
| 71 | <SettingItem name="颜色"> | 71 | <SettingItem name="颜色"> |
| 72 | - <n-color-picker size="small" :modes="['hex']" v-model:value="seriesList[0].label.color"></n-color-picker> | 72 | + <n-color-picker |
| 73 | + size="small" | ||
| 74 | + :modes="['hex']" | ||
| 75 | + v-model:value="seriesList[0].label.textStyle.color" | ||
| 76 | + ></n-color-picker> | ||
| 73 | </SettingItem> | 77 | </SettingItem> |
| 74 | <SettingItem name="大小"> | 78 | <SettingItem name="大小"> |
| 75 | <n-input-number | 79 | <n-input-number |
| 76 | - v-model:value="seriesList[0].label.fontSize" | 80 | + v-model:value="seriesList[0].label.textStyle.fontSize" |
| 77 | :min="0" | 81 | :min="0" |
| 78 | size="small" | 82 | size="small" |
| 79 | placeholder="请输入" | 83 | placeholder="请输入" |
| @@ -4,12 +4,12 @@ | @@ -4,12 +4,12 @@ | ||
| 4 | </template> | 4 | </template> |
| 5 | 5 | ||
| 6 | <script setup lang="ts"> | 6 | <script setup lang="ts"> |
| 7 | -import { onMounted, ref, nextTick, PropType, toRefs, watch } from 'vue' | 7 | +import { onMounted, ref, nextTick, PropType, toRefs, watch, reactive } from 'vue' |
| 8 | import * as echarts from 'echarts' | 8 | import * as echarts from 'echarts' |
| 9 | import { registerMap } from 'echarts/core' | 9 | import { registerMap } from 'echarts/core' |
| 10 | import 'echarts-gl' | 10 | import 'echarts-gl' |
| 11 | -import config from './config' | ||
| 12 | -import cityMap from '../OverrideMapBase/mapGeojson/china-main-city-map.json' | 11 | +import config, { areaEnum } from './config' |
| 12 | +import { getGeoJsonMap } from '@/api/external/common' | ||
| 13 | 13 | ||
| 14 | type historyDataType = { name: string; code: string } | 14 | type historyDataType = { name: string; code: string } |
| 15 | 15 | ||
| @@ -71,40 +71,76 @@ props.chartConfig.option = { | @@ -71,40 +71,76 @@ props.chartConfig.option = { | ||
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | //地图点击返回 | 73 | //地图点击返回 |
| 74 | -const watchAdcode = () => { | 74 | +const watchAdcode = async () => { |
| 75 | if (props.chartConfig.option.drillingIn) { | 75 | if (props.chartConfig.option.drillingIn) { |
| 76 | - const code = historyData.value.at(-2)?.code | ||
| 77 | - props.chartConfig.option.mapRegion.adcode = code ? code : 'china' | ||
| 78 | - historyData.value.pop() | 76 | + saveLevelStr.level = saveLevelStr.parentInfo.level |
| 77 | + await getGeojson(saveLevelStr.parentInfo.adcode) | ||
| 78 | + props.chartConfig.option.geo3D.map = | ||
| 79 | + saveLevelStr.parentInfo.adcode === 100000 ? 'china' : saveLevelStr.parentInfo.adcode | ||
| 80 | + props.chartConfig.option.series.forEach((item: any) => { | ||
| 81 | + if (item.type === 'map3D') | ||
| 82 | + item.map = saveLevelStr.parentInfo.adcode === 100000 ? 'china' : saveLevelStr.parentInfo.adcode | ||
| 83 | + item.data = props.chartConfig.option.dataset | ||
| 84 | + }) | ||
| 85 | + handleSetOption(chartInstance.value, props.chartConfig.option) | ||
| 79 | } | 86 | } |
| 80 | } | 87 | } |
| 81 | 88 | ||
| 89 | +const regionMapParentArea = { | ||
| 90 | + [areaEnum.PROVINCE]: areaEnum.COUNTRY, //省份的上一级 中国 | ||
| 91 | + [areaEnum.CITY]: areaEnum.PROVINCE, //城市的上一级 省份 | ||
| 92 | + [areaEnum.COUNTY]: areaEnum.CITY, //县或者区的上一级 城市 | ||
| 93 | + [areaEnum.TOWN]: areaEnum.COUNTY //镇的上一级 县或者区 | ||
| 94 | +} | ||
| 95 | + | ||
| 82 | //地图点击 | 96 | //地图点击 |
| 83 | const handleMap3DClick = async (params: any) => { | 97 | const handleMap3DClick = async (params: any) => { |
| 84 | if (props.chartConfig.option.drillingIn) { | 98 | if (props.chartConfig.option.drillingIn) { |
| 85 | const { name } = params | 99 | const { name } = params |
| 86 | - saveSelectValue.value = name | ||
| 87 | - const findAdcode = (cityMap as any)[name] | ||
| 88 | - if (!findAdcode) return | ||
| 89 | - props.chartConfig.option.mapRegion.adcode = findAdcode | ||
| 90 | - historyData.value.push({ | ||
| 91 | - name, | ||
| 92 | - code: findAdcode | 100 | + saveGeojson.value?.features.forEach((item: any) => { |
| 101 | + if (item.properties.name === name) { | ||
| 102 | + const level = item.properties.level.toUpperCase() | ||
| 103 | + const adcode = item.properties.adcode | ||
| 104 | + props.chartConfig.option.mapRegion.adcode = adcode | ||
| 105 | + saveLevelStr.level = level | ||
| 106 | + saveLevelStr.parentInfo.adcode = item.properties.parent.adcode //保存上一级的地区编码 | ||
| 107 | + saveLevelStr.parentInfo.level = (regionMapParentArea as any)[level] //保存上一级的行政级别 | ||
| 108 | + } | ||
| 93 | }) | 109 | }) |
| 94 | } | 110 | } |
| 95 | } | 111 | } |
| 96 | 112 | ||
| 113 | +const saveGeojson: any = ref({}) // 保存geojson | ||
| 114 | + | ||
| 115 | +const chinaDefaultRegionId = ref(100000) //如果是china则adcode为100000 | ||
| 116 | + | ||
| 117 | +const saveLevelStr = reactive({ | ||
| 118 | + // 保存行政级别和上一级的adcode和level | ||
| 119 | + level: '', | ||
| 120 | + parentInfo: { | ||
| 121 | + adcode: 0, | ||
| 122 | + level: '' | ||
| 123 | + } | ||
| 124 | +}) | ||
| 125 | + | ||
| 97 | //动态获取geojson文件进行注册地图 | 126 | //动态获取geojson文件进行注册地图 |
| 98 | -const getGeojson = (regionId: string) => { | 127 | +const getGeojson = (regionId: any) => { |
| 99 | try { | 128 | try { |
| 100 | return new Promise<boolean>(resolve => { | 129 | return new Promise<boolean>(resolve => { |
| 101 | - import(`../OverrideMapBase/mapGeojson/${regionId}.json`).then(data => { | ||
| 102 | - registerMap(regionId, { geoJSON: data.default as any, specialAreas: {} }) | 130 | + const { levelStr } = props.chartConfig.option.mapRegion.saveSelect //右侧配置项获取的行政级别 |
| 131 | + getGeoJsonMap( | ||
| 132 | + regionId === 'china' ? chinaDefaultRegionId.value : regionId, | ||
| 133 | + !saveLevelStr.level ? levelStr : saveLevelStr.level | ||
| 134 | + ).then(res => { | ||
| 135 | + const { geoJson, name, code, level } = res.data | ||
| 136 | + const geoJsonFile = JSON.parse(geoJson) | ||
| 137 | + saveGeojson.value = geoJsonFile | ||
| 138 | + registerMap(level === areaEnum.COUNTRY ? name : code, { geoJSON: geoJsonFile as any, specialAreas: {} }) | ||
| 103 | resolve(true) | 139 | resolve(true) |
| 104 | }) | 140 | }) |
| 105 | }) | 141 | }) |
| 106 | - } catch (e) { | ||
| 107 | - console.log(e) | 142 | + } catch (error) { |
| 143 | + console.error('注册地图出错', error) | ||
| 108 | } | 144 | } |
| 109 | } | 145 | } |
| 110 | 146 | ||
| @@ -126,8 +162,7 @@ const initMap = async () => { | @@ -126,8 +162,7 @@ const initMap = async () => { | ||
| 126 | handleSetOption(chartInstance.value, props.chartConfig.option) | 162 | handleSetOption(chartInstance.value, props.chartConfig.option) |
| 127 | }) | 163 | }) |
| 128 | chartInstance.value.on('click', (e: any) => { | 164 | chartInstance.value.on('click', (e: any) => { |
| 129 | - console.log(`地图点击`, e) | ||
| 130 | - // handleMap3DClick(e) | 165 | + handleMap3DClick(e) |
| 131 | }) | 166 | }) |
| 132 | } | 167 | } |
| 133 | 168 | ||
| @@ -137,8 +172,8 @@ const handleSetOption = (instance: any, option: any) => { | @@ -137,8 +172,8 @@ const handleSetOption = (instance: any, option: any) => { | ||
| 137 | try { | 172 | try { |
| 138 | instance.clear() | 173 | instance.clear() |
| 139 | instance.setOption(option) | 174 | instance.setOption(option) |
| 140 | - // eslint-disable-next-line no-empty | ||
| 141 | - } finally { | 175 | + } catch (error) { |
| 176 | + console.error('触发渲染出错', error) | ||
| 142 | } | 177 | } |
| 143 | } | 178 | } |
| 144 | 179 | ||
| @@ -161,7 +196,7 @@ watch( | @@ -161,7 +196,7 @@ watch( | ||
| 161 | }) | 196 | }) |
| 162 | handleSetOption(chartInstance.value, props.chartConfig.option) | 197 | handleSetOption(chartInstance.value, props.chartConfig.option) |
| 163 | } catch (error) { | 198 | } catch (error) { |
| 164 | - console.log(error) | 199 | + console.log('展示区域发生变化出错', error) |
| 165 | } | 200 | } |
| 166 | }, | 201 | }, |
| 167 | { | 202 | { |
| @@ -152,7 +152,7 @@ const getGeojson = async (regionId: any) => { | @@ -152,7 +152,7 @@ const getGeojson = async (regionId: any) => { | ||
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | //异步时先注册空的 保证初始化不报错 | 154 | //异步时先注册空的 保证初始化不报错 |
| 155 | -registerMap(`${props.chartConfig.option.mapRegion.adcode}`, { geoJSON: {} as any, specialAreas: {} }) | 155 | +registerMap(props.chartConfig.option.mapRegion.adcode, { geoJSON: {} as any, specialAreas: {} }) |
| 156 | 156 | ||
| 157 | // 进行更换初始化地图 如果为china 单独处理 | 157 | // 进行更换初始化地图 如果为china 单独处理 |
| 158 | const registerMapInitAsync = async () => { | 158 | const registerMapInitAsync = async () => { |