Commit 38f8e17d8940c4497aaa16eb68a712d81ebd45fc

Authored by fengwotao
1 parent 3b34bcf0

feat(src/packages): 图表地图支持下钻 修改地图注册方式为服务端接口请求

... ... @@ -13,7 +13,8 @@ enum Api {
13 13 VIDEO = '/video/list',
14 14 DEVICE_PROFILE = '/device_profile/me/list',
15 15 DEVICE = '/device',
16   - VIDEOURL = '/video/url/'
  16 + VIDEOURL = '/video/url/',
  17 + GEOJSONURL = '/map/geo_json/'
17 18 }
18 19
19 20 export const getDictItemByCode = (value: string) => {
... ... @@ -106,3 +107,9 @@ export const getVideoUrl = (id: string) =>
106 107 defHttp.get({
107 108 url: `${Api.VIDEOURL}${id}`
108 109 })
  110 +
  111 +//获取行政区域
  112 +export const getGeoJsonMap = (code: number, level: string) =>
  113 + defHttp.get({
  114 + url: `${Api.GEOJSONURL}${code}/${level}`
  115 + })
... ...
... ... @@ -24,7 +24,8 @@ const selectOptions = reactive({
24 24 const selectValues = reactive({
25 25 provinceValue: 'china',
26 26 cityValue: null,
27   - countyValue: null
  27 + countyValue: null,
  28 + levelStr: areaEnum.COUNTRY
28 29 })
29 30
30 31 const getAreaLists = async (level = areaEnum.PROVINCE, parentId = 1) => {
... ... @@ -49,13 +50,15 @@ onMounted(async () => {
49 50 const onHandleSelectProvince = async (value: number | string) => {
50 51 selectValues.cityValue = null
51 52 selectValues.countyValue = null
52   - if (value === 'china') return
  53 + if (value === 'china') return (selectValues.levelStr = areaEnum.COUNTRY)
53 54 selectOptions.cityOptions = await getAreaLists(areaEnum.CITY, value as any)
  55 + selectValues.levelStr = areaEnum.PROVINCE
54 56 }
55 57
56 58 const onHandleSelectCity = async (value: number) => {
57 59 selectValues.countyValue = null
58 60 selectOptions.countryOptions = await getAreaLists(areaEnum.COUNTY, value)
  61 + selectValues.levelStr = areaEnum.CITY
59 62 }
60 63
61 64 const onHandleSubmit = () => {
... ...
... ... @@ -7,23 +7,27 @@ import dataJson from './data.json'
7 7
8 8 //省市区枚举
9 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 export const includes = []
15 17
16 18 export const option = {
17   - iconColor:'black',
18   - showIcon:false,
19   - iconDistanceRight:20,
20   - iconDistanceTop:20,
  19 + iconColor: 'black',
  20 + showIcon: false,
  21 + iconDistanceRight: 20,
  22 + iconDistanceTop: 20,
21 23 drillingIn: false,
22 24 dataset: dataJson,
23 25 mapRegion: {
24 26 adcode: 'china',
25 27 showHainanIsLands: true,
26   - saveSelect:{}
  28 + saveSelect: {
  29 + levelStr: areaEnum.COUNTRY
  30 + }
27 31 },
28 32 tooltip: {
29 33 show: true,
... ... @@ -157,7 +161,7 @@ export const option = {
157 161 shadowOffsetY: 2,
158 162 shadowBlur: 10
159 163 }
160   - },
  164 + }
161 165 ]
162 166 }
163 167 export const MapDefaultConfig = { ...option }
... ...
... ... @@ -6,6 +6,7 @@
6 6 :theme="themeColor"
7 7 :option="option.value"
8 8 :manual-update="isPreview()"
  9 + :loading="loading"
9 10 autoresize
10 11 >
11 12 </v-chart>
... ... @@ -13,7 +14,7 @@
13 14
14 15 <script setup lang="ts">
15 16 import { PropType, reactive, watch, ref, nextTick } from 'vue'
16   -import config, { includes } from './config'
  17 +import config, { includes, areaEnum } from './config'
17 18 import VChart from 'vue-echarts'
18 19 import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
19 20 import { use, registerMap } from 'echarts/core'
... ... @@ -25,9 +26,7 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore
25 26 import { isPreview } from '@/utils'
26 27 import mapJsonWithoutHainanIsLands from './mapWithoutHainanIsLands.json'
27 28 import { DatasetComponent, GridComponent, TooltipComponent, GeoComponent, VisualMapComponent } from 'echarts/components'
28   -import cityMap from './mapGeojson/china-main-city-map.json'
29   -
30   -type historyDataType = { name: string; code: string }
  29 +import { getGeoJsonMap } from '@/api/external/common'
31 30
32 31 const props = defineProps({
33 32 themeSetting: {
... ... @@ -57,14 +56,12 @@ use([
57 56 VisualMapComponent
58 57 ])
59 58
60   -const saveSelectValue = ref('')
  59 +const loading = ref(true)
61 60
62 61 const iconStr = ref(
63 62 'path://M853.333333 245.333333H245.333333l93.866667-93.866666c12.8-12.8 12.8-34.133333 0-46.933334-12.8-12.8-34.133333-12.8-46.933333 0l-145.066667 145.066667c-12.8 12.8-12.8 34.133333 0 46.933333l145.066667 145.066667c6.4 6.4 14.933333 10.666667 23.466666 10.666667s17.066667-4.266667 23.466667-10.666667c12.8-12.8 12.8-34.133333 0-46.933333L256 311.466667h597.333333c6.4 0 10.666667 4.266667 10.666667 10.666666v426.666667c0 6.4-4.266667 10.666667-10.666667 10.666667H170.666667c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h682.666666c40.533333 0 74.666667-34.133333 74.666667-74.666667V320c0-40.533333-34.133333-74.666667-74.666667-74.666667z'
64 63 )
65 64
66   -const historyData = ref<historyDataType[]>([])
67   -
68 65 const option = reactive({
69 66 value: mergeTheme(props.chartConfig.option, props.themeSetting, includes)
70 67 })
... ... @@ -105,28 +102,52 @@ props.chartConfig.option = {
105 102 ...{ toolbox: toolBoxOption.value }
106 103 }
107 104
108   -//地图点击返回
109   -const watchAdcode = () => {
  105 +//地图点击返回 adcode=100000,名字必须是china
  106 +const watchAdcode = async () => {
110 107 if (props.chartConfig.option.drillingIn) {
111   - const code = historyData.value.at(-2)?.code
112   - props.chartConfig.option.mapRegion.adcode = code ? code : 'china'
113   - historyData.value.pop()
  108 + saveLevelStr.level = saveLevelStr.parentInfo.level
  109 + await getGeojson(saveLevelStr.parentInfo.adcode)
  110 + props.chartConfig.option.geo.map =
  111 + saveLevelStr.parentInfo.adcode === 100000 ? 'china' : saveLevelStr.parentInfo.adcode
  112 + props.chartConfig.option.series.forEach((item: any) => {
  113 + if (item.type === 'map')
  114 + item.map = saveLevelStr.parentInfo.adcode === 100000 ? 'china' : saveLevelStr.parentInfo.adcode
  115 + })
  116 + vEchartsSetOption()
114 117 }
115 118 }
116 119
117 120 const vChartRef = ref<typeof VChart>()
118 121
119   -//动态获取json注册地图
120   -const getGeojson = (regionId: string) => {
  122 +const saveGeojson: any = ref({}) // 保存geojson
  123 +
  124 +const chinaDefaultRegionId = ref(100000) //如果是china则adcode为100000
  125 +
  126 +const saveLevelStr = reactive({
  127 + // 保存行政级别和上一级的adcode和level
  128 + level: '',
  129 + parentInfo: {
  130 + adcode: 0,
  131 + level: ''
  132 + }
  133 +})
  134 +
  135 +//动态注册地图
  136 +const getGeojson = async (regionId: any) => {
121 137 try {
122   - return new Promise<boolean>(resolve => {
123   - import(`./mapGeojson/${regionId}.json`).then(data => {
124   - registerMap(regionId, { geoJSON: data.default as any, specialAreas: {} })
125   - resolve(true)
126   - })
127   - })
128   - } finally {
129   - console.log
  138 + const { levelStr } = props.chartConfig.option.mapRegion.saveSelect //右侧配置项获取的行政级别
  139 + const { data } = await getGeoJsonMap(
  140 + regionId === 'china' ? chinaDefaultRegionId.value : regionId,
  141 + !saveLevelStr.level ? levelStr : saveLevelStr.level
  142 + )
  143 + const { geoJson, name, code, level } = data
  144 + const geoJsonFile = JSON.parse(geoJson)
  145 + saveGeojson.value = geoJsonFile
  146 + registerMap(level === areaEnum.COUNTRY ? name : code, { geoJSON: geoJsonFile as any, specialAreas: {} })
  147 + loading.value = false
  148 + } catch (error) {
  149 + loading.value = false
  150 + console.error('动态注册地图出错', error)
130 151 }
131 152 }
132 153
... ... @@ -136,7 +157,7 @@ registerMap(`${props.chartConfig.option.mapRegion.adcode}`, { geoJSON: {} as any
136 157 // 进行更换初始化地图 如果为china 单独处理
137 158 const registerMapInitAsync = async () => {
138 159 await nextTick()
139   - const adCode = `${props.chartConfig.option.mapRegion.adcode}`
  160 + const adCode = props.chartConfig.option.mapRegion.adcode
140 161 if (adCode !== 'china') {
141 162 await getGeojson(adCode)
142 163 } else {
... ... @@ -147,9 +168,13 @@ const registerMapInitAsync = async () => {
147 168 registerMapInitAsync()
148 169
149 170 // 手动触发渲染
150   -const vEchartsSetOption = () => {
151   - option.value = props.chartConfig.option
152   - setOption(vChartRef.value, props.chartConfig.option)
  171 +const vEchartsSetOption = async () => {
  172 + try {
  173 + option.value = props.chartConfig.option
  174 + setOption(vChartRef.value, props.chartConfig.option)
  175 + } catch (error) {
  176 + console.error('触发渲染出错', error)
  177 + }
153 178 }
154 179
155 180 // 更新数据处理
... ... @@ -159,7 +184,6 @@ const dataSetHandle = async (dataset: any) => {
159 184 else if (item.type === 'map' && dataset.map) item.data = dataset.map
160 185 })
161 186 if (dataset.pieces) props.chartConfig.option.visualMap.pieces = dataset.pieces
162   -
163 187 isPreview() && vEchartsSetOption()
164 188 }
165 189
... ... @@ -202,7 +226,7 @@ watch(
202 226
203 227 //监听地图展示区域发生变化
204 228 watch(
205   - () => `${props.chartConfig.option.mapRegion.adcode}`,
  229 + () => props.chartConfig.option.mapRegion.adcode,
206 230 async newData => {
207 231 try {
208 232 await getGeojson(newData)
... ... @@ -225,17 +249,26 @@ useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
225 249 dataSetHandle(newData)
226 250 })
227 251
228   -//地图点击
  252 +const regionMapParentArea = {
  253 + [areaEnum.PROVINCE]: areaEnum.COUNTRY, //省份的上一级 中国
  254 + [areaEnum.CITY]: areaEnum.PROVINCE, //城市的上一级 省份
  255 + [areaEnum.COUNTY]: areaEnum.CITY, //县或者区的上一级 城市
  256 + [areaEnum.TOWN]: areaEnum.COUNTY //镇的上一级 县或者区
  257 +}
  258 +
  259 +//地图点击下钻
229 260 const handleVChartClick = async (params: any) => {
230 261 if (props.chartConfig.option.drillingIn) {
231 262 const { name } = params
232   - saveSelectValue.value = name
233   - const findAdcode = (cityMap as any)[name]
234   - if (!findAdcode) return
235   - props.chartConfig.option.mapRegion.adcode = findAdcode
236   - historyData.value.push({
237   - name,
238   - code: findAdcode
  263 + saveGeojson.value?.features.forEach((item: any) => {
  264 + if (item.properties.name === name) {
  265 + const level = item.properties.level.toUpperCase()
  266 + const adcode = item.properties.adcode
  267 + props.chartConfig.option.mapRegion.adcode = adcode
  268 + saveLevelStr.level = level
  269 + saveLevelStr.parentInfo.adcode = item.properties.parent.adcode //保存上一级的地区编码
  270 + saveLevelStr.parentInfo.level = (regionMapParentArea as any)[level] //保存上一级的行政级别
  271 + }
239 272 })
240 273 }
241 274 }
... ...