Commit ac33360452a8e364a5e5ecbb438e8ef869e4d753

Authored by fengwotao
1 parent 2321340a

feat(src/packages): 图表地图新增地图下钻功能

  1 +<script lang="ts" setup name="SelectCity">
  2 +import { onMounted, reactive } from 'vue'
  3 +import { getAreaList } from '@/api/external/common/index'
  4 +import { areaEnum } from '../config'
  5 +
  6 +const emits = defineEmits(['submit'])
  7 +
  8 +const selectOptions = reactive({
  9 + provinceOptions: [],
  10 + cityOptions: [],
  11 + countryOptions: []
  12 +})
  13 +
  14 +const selectValues = reactive({
  15 + provinceValue: null,
  16 + cityValue: null,
  17 + countyValue: null
  18 +})
  19 +
  20 +const getAreaLists = async (level = areaEnum.PROVINCE, parentId = 1) => {
  21 + const resp = await getAreaList({
  22 + level,
  23 + parentId
  24 + })
  25 + if (!resp) return []
  26 + return resp.map((item: any) => ({ label: item.name, value: item.code }))
  27 +}
  28 +
  29 +onMounted(async () => {
  30 + selectOptions.provinceOptions = await getAreaLists()
  31 + ;(selectOptions.provinceOptions as never as any).unshift({
  32 + label: '中国',
  33 + value: 'china'
  34 + })
  35 +})
  36 +
  37 +const onHandleSelectProvince = async (value: number | string) => {
  38 + selectValues.cityValue = null
  39 + selectValues.countyValue = null
  40 + if (value === 'china') return
  41 + selectOptions.cityOptions = await getAreaLists(areaEnum.CITY, value as any)
  42 +}
  43 +
  44 +const onHandleSelectCity = async (value: number) => {
  45 + selectValues.countyValue = null
  46 + selectOptions.countryOptions = await getAreaLists(areaEnum.COUNTY, value)
  47 +}
  48 +
  49 +const onHandleSubmit = () => {
  50 + emits('submit', selectValues)
  51 +}
  52 +</script>
  53 +
  54 +<template>
  55 + <div class="select-city-content">
  56 + <n-select
  57 + @change="onHandleSelectProvince"
  58 + placeholder="请选择省份"
  59 + v-model:value="selectValues.provinceValue"
  60 + :options="selectOptions.provinceOptions"
  61 + />
  62 + <n-select
  63 + @change="onHandleSelectCity"
  64 + placeholder="请选择城市"
  65 + v-model:value="selectValues.cityValue"
  66 + :options="selectOptions.cityOptions"
  67 + />
  68 + <n-select
  69 + placeholder="请选择区域"
  70 + v-model:value="selectValues.countyValue"
  71 + :options="selectOptions.countryOptions"
  72 + />
  73 + <n-button type="primary" @click="onHandleSubmit">确定</n-button>
  74 + </div>
  75 +</template>
  76 +
  77 +<style lang="scss" scoped>
  78 +.select-city-content {
  79 + display: flex;
  80 + flex-direction: column;
  81 + justify-content: space-between;
  82 + align-items: center;
  83 + gap: 30px;
  84 +}
  85 +</style>
@@ -5,9 +5,16 @@ import { CreateComponentType } from '@/packages/index.d' @@ -5,9 +5,16 @@ import { CreateComponentType } from '@/packages/index.d'
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 7
  8 +//省市区枚举
  9 +export const enum areaEnum {
  10 + PROVINCE = 'PROVINCE',
  11 + CITY = 'CITY',
  12 + COUNTY = 'COUNTY'
  13 +}
8 export const includes = [] 14 export const includes = []
9 15
10 export const option = { 16 export const option = {
  17 + drillingIn:false,
11 dataset: dataJson, 18 dataset: dataJson,
12 mapRegion: { 19 mapRegion: {
13 adcode: 'china', 20 adcode: 'china',
@@ -100,19 +107,19 @@ export const option = { @@ -100,19 +107,19 @@ export const option = {
100 borderColor: 'rgba(147, 235, 248, 0.8)', 107 borderColor: 'rgba(147, 235, 248, 0.8)',
101 textStyle: { 108 textStyle: {
102 color: '#FFFFFF', 109 color: '#FFFFFF',
103 - fontSize: 12, 110 + fontSize: 12
104 } 111 }
105 }, 112 },
106 label: { 113 label: {
107 show: false, 114 show: false,
108 color: '#FFFFFF', 115 color: '#FFFFFF',
109 - fontSize: 12, 116 + fontSize: 12
110 }, 117 },
111 emphasis: { 118 emphasis: {
112 disabled: false, 119 disabled: false,
113 label: { 120 label: {
114 color: '#FFFFFF', 121 color: '#FFFFFF',
115 - fontSize: 12, 122 + fontSize: 12
116 }, 123 },
117 itemStyle: { 124 itemStyle: {
118 areaColor: '#389BB7', 125 areaColor: '#389BB7',
@@ -2,18 +2,12 @@ @@ -2,18 +2,12 @@
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="地图区域">  
6 - <SettingItem name="默认中国">  
7 - <n-select  
8 - size="small"  
9 - v-model:value="mapRegion.adcode"  
10 - :options="mapRegionOptions"  
11 - value-field="adcode"  
12 - label-field="name"  
13 - /> 5 + <SelectCity @submit="onHandleSelectValues" />
  6 + <SettingItemBox name="开启下钻">
  7 + <SettingItem name="">
  8 + <n-switch v-model:value="optionData.drillingIn" size="small"></n-switch>
14 </SettingItem> 9 </SettingItem>
15 </SettingItemBox> 10 </SettingItemBox>
16 -  
17 <SettingItemBox name="区域颜色"> 11 <SettingItemBox name="区域颜色">
18 <SettingItem name="0%处颜色"> 12 <SettingItem name="0%处颜色">
19 <n-color-picker 13 <n-color-picker
@@ -69,11 +63,7 @@ @@ -69,11 +63,7 @@
69 </n-space> 63 </n-space>
70 </SettingItem> 64 </SettingItem>
71 <SettingItem name="字体颜色"> 65 <SettingItem name="字体颜色">
72 - <n-color-picker  
73 - size="small"  
74 - :modes="['hex']"  
75 - v-model:value="seriesList[1].label.color"  
76 - ></n-color-picker> 66 + <n-color-picker size="small" :modes="['hex']" v-model:value="seriesList[1].label.color"></n-color-picker>
77 </SettingItem> 67 </SettingItem>
78 <SettingItem name="字体大小"> 68 <SettingItem name="字体大小">
79 <n-input-number 69 <n-input-number
@@ -129,7 +119,7 @@ @@ -129,7 +119,7 @@
129 ></n-color-picker> 119 ></n-color-picker>
130 </SettingItem> 120 </SettingItem>
131 </SettingItemBox> 121 </SettingItemBox>
132 - 122 +
133 <SettingItemBox name="悬浮弹窗"> 123 <SettingItemBox name="悬浮弹窗">
134 <SettingItem name="显示"> 124 <SettingItem name="显示">
135 <n-space> 125 <n-space>
@@ -191,7 +181,7 @@ @@ -191,7 +181,7 @@
191 <n-color-picker size="small" :modes="['hex']" v-model:value="seriesList[0].itemStyle.color"></n-color-picker> 181 <n-color-picker size="small" :modes="['hex']" v-model:value="seriesList[0].itemStyle.color"></n-color-picker>
192 </SettingItem> 182 </SettingItem>
193 </SettingItemBox> 183 </SettingItemBox>
194 - 184 +
195 <SettingItemBox name="文本"> 185 <SettingItemBox name="文本">
196 <SettingItem name="显示"> 186 <SettingItem name="显示">
197 <n-space> 187 <n-space>
@@ -232,6 +222,7 @@ import { GlobalThemeJsonType } from '@/settings/chartThemes/index' @@ -232,6 +222,7 @@ import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
232 import { GlobalSetting } from '@/components/Pages/ChartItemSetting' 222 import { GlobalSetting } from '@/components/Pages/ChartItemSetting'
233 import { ref } from 'vue' 223 import { ref } from 'vue'
234 import mapChinaJson from './mapGeojson/china.json' 224 import mapChinaJson from './mapGeojson/china.json'
  225 +import SelectCity from './components/SelectCity.vue'
235 226
236 const mapRegionOptions = ref([ 227 const mapRegionOptions = ref([
237 { 228 {
@@ -274,4 +265,15 @@ const seriesList = computed(() => { @@ -274,4 +265,15 @@ const seriesList = computed(() => {
274 const mapRegion = computed(() => { 265 const mapRegion = computed(() => {
275 return props.optionData.mapRegion 266 return props.optionData.mapRegion
276 }) 267 })
  268 +
  269 +const onHandleSelectValues = (values: any) => {
  270 + const { cityValue, countyValue, provinceValue } = values
  271 + props.optionData.mapRegion.adcode = countyValue
  272 + ? countyValue
  273 + : cityValue
  274 + ? cityValue
  275 + : provinceValue === 'china'
  276 + ? 'china'
  277 + : provinceValue
  278 +}
277 </script> 279 </script>
1 <template> 1 <template>
2 - <v-chart ref="vChartRef" :init-options="initOptions" :theme="themeColor" :option="option.value" :manual-update="isPreview()" autoresize> 2 + <v-chart
  3 + @click="handleVChartClick"
  4 + ref="vChartRef"
  5 + :init-options="initOptions"
  6 + :theme="themeColor"
  7 + :option="option.value"
  8 + :manual-update="isPreview()"
  9 + autoresize
  10 + >
3 </v-chart> 11 </v-chart>
4 </template> 12 </template>
5 13
@@ -17,6 +25,7 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore @@ -17,6 +25,7 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore
17 import { isPreview } from '@/utils' 25 import { isPreview } from '@/utils'
18 import mapJsonWithoutHainanIsLands from './mapWithoutHainanIsLands.json' 26 import mapJsonWithoutHainanIsLands from './mapWithoutHainanIsLands.json'
19 import { DatasetComponent, GridComponent, TooltipComponent, GeoComponent, VisualMapComponent } from 'echarts/components' 27 import { DatasetComponent, GridComponent, TooltipComponent, GeoComponent, VisualMapComponent } from 'echarts/components'
  28 +import cityMap from './mapGeojson/china-main-city-map.json'
20 29
21 const props = defineProps({ 30 const props = defineProps({
22 themeSetting: { 31 themeSetting: {
@@ -46,9 +55,37 @@ use([ @@ -46,9 +55,37 @@ use([
46 VisualMapComponent 55 VisualMapComponent
47 ]) 56 ])
48 57
  58 +const saveSelectValue = ref('')
  59 +
49 const option = reactive({ 60 const option = reactive({
50 value: mergeTheme(props.chartConfig.option, props.themeSetting, includes) 61 value: mergeTheme(props.chartConfig.option, props.themeSetting, includes)
51 }) 62 })
  63 +
  64 +const toolBoxOption = {
  65 + show: true,
  66 + right: 20,
  67 + feature: {
  68 + myFullButton: {
  69 + show: true,
  70 + title: '返回',
  71 + icon: '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',
  72 + onclick: () => watchAdcode()
  73 + }
  74 + }
  75 +}
  76 +
  77 +props.chartConfig.option = {
  78 + ...props.chartConfig.option,
  79 + ...{ toolbox: toolBoxOption }
  80 +}
  81 +
  82 +const watchAdcode = () => {
  83 + if (props.chartConfig.option.drillingIn) {
  84 + const findCity = (cityMap as any)[saveSelectValue.value]
  85 + props.chartConfig.option.mapRegion.adcode = 'china'
  86 + }
  87 +}
  88 +
52 const vChartRef = ref<typeof VChart>() 89 const vChartRef = ref<typeof VChart>()
53 90
54 //动态获取json注册地图 91 //动态获取json注册地图
@@ -67,7 +104,7 @@ registerMap(`${props.chartConfig.option.mapRegion.adcode}`, { geoJSON: {} as any @@ -67,7 +104,7 @@ registerMap(`${props.chartConfig.option.mapRegion.adcode}`, { geoJSON: {} as any
67 // 进行更换初始化地图 如果为china 单独处理 104 // 进行更换初始化地图 如果为china 单独处理
68 const registerMapInitAsync = async () => { 105 const registerMapInitAsync = async () => {
69 await nextTick() 106 await nextTick()
70 - const adCode = `${props.chartConfig.option.mapRegion.adcode}`; 107 + const adCode = `${props.chartConfig.option.mapRegion.adcode}`
71 if (adCode !== 'china') { 108 if (adCode !== 'china') {
72 await getGeojson(adCode) 109 await getGeojson(adCode)
73 } else { 110 } else {
@@ -93,6 +130,7 @@ const dataSetHandle = async (dataset: any) => { @@ -93,6 +130,7 @@ const dataSetHandle = async (dataset: any) => {
93 130
94 isPreview() && vEchartsSetOption() 131 isPreview() && vEchartsSetOption()
95 } 132 }
  133 +
96 // 处理海南群岛 134 // 处理海南群岛
97 const hainanLandsHandle = async (newData: boolean) => { 135 const hainanLandsHandle = async (newData: boolean) => {
98 if (newData) { 136 if (newData) {
@@ -101,6 +139,7 @@ const hainanLandsHandle = async (newData: boolean) => { @@ -101,6 +139,7 @@ const hainanLandsHandle = async (newData: boolean) => {
101 registerMap('china', { geoJSON: mapJsonWithoutHainanIsLands as any, specialAreas: {} }) 139 registerMap('china', { geoJSON: mapJsonWithoutHainanIsLands as any, specialAreas: {} })
102 } 140 }
103 } 141 }
  142 +
104 //监听 dataset 数据发生变化 143 //监听 dataset 数据发生变化
105 watch( 144 watch(
106 () => props.chartConfig.option.dataset, 145 () => props.chartConfig.option.dataset,
@@ -153,4 +192,14 @@ watch( @@ -153,4 +192,14 @@ watch(
153 useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => { 192 useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
154 dataSetHandle(newData) 193 dataSetHandle(newData)
155 }) 194 })
  195 +
  196 +//地图点击
  197 +const handleVChartClick = async (params: any) => {
  198 + if (props.chartConfig.option.drillingIn) {
  199 + const { name } = params
  200 + saveSelectValue.value = name
  201 + const findAdcode = (cityMap as any)[name]
  202 + props.chartConfig.option.mapRegion.adcode = findAdcode
  203 + }
  204 +}
156 </script> 205 </script>