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 5 import cloneDeep from 'lodash/cloneDeep'
6 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 14 export const includes = []
9 15
10 16 export const option = {
  17 + drillingIn:false,
11 18 dataset: dataJson,
12 19 mapRegion: {
13 20 adcode: 'china',
... ... @@ -100,19 +107,19 @@ export const option = {
100 107 borderColor: 'rgba(147, 235, 248, 0.8)',
101 108 textStyle: {
102 109 color: '#FFFFFF',
103   - fontSize: 12,
  110 + fontSize: 12
104 111 }
105 112 },
106 113 label: {
107 114 show: false,
108 115 color: '#FFFFFF',
109   - fontSize: 12,
  116 + fontSize: 12
110 117 },
111 118 emphasis: {
112 119 disabled: false,
113 120 label: {
114 121 color: '#FFFFFF',
115   - fontSize: 12,
  122 + fontSize: 12
116 123 },
117 124 itemStyle: {
118 125 areaColor: '#389BB7',
... ...
... ... @@ -2,18 +2,12 @@
2 2 <!-- Echarts 全局设置 -->
3 3 <global-setting :optionData="optionData"></global-setting>
4 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 9 </SettingItem>
15 10 </SettingItemBox>
16   -
17 11 <SettingItemBox name="区域颜色">
18 12 <SettingItem name="0%处颜色">
19 13 <n-color-picker
... ... @@ -69,11 +63,7 @@
69 63 </n-space>
70 64 </SettingItem>
71 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 67 </SettingItem>
78 68 <SettingItem name="字体大小">
79 69 <n-input-number
... ... @@ -129,7 +119,7 @@
129 119 ></n-color-picker>
130 120 </SettingItem>
131 121 </SettingItemBox>
132   -
  122 +
133 123 <SettingItemBox name="悬浮弹窗">
134 124 <SettingItem name="显示">
135 125 <n-space>
... ... @@ -191,7 +181,7 @@
191 181 <n-color-picker size="small" :modes="['hex']" v-model:value="seriesList[0].itemStyle.color"></n-color-picker>
192 182 </SettingItem>
193 183 </SettingItemBox>
194   -
  184 +
195 185 <SettingItemBox name="文本">
196 186 <SettingItem name="显示">
197 187 <n-space>
... ... @@ -232,6 +222,7 @@ import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
232 222 import { GlobalSetting } from '@/components/Pages/ChartItemSetting'
233 223 import { ref } from 'vue'
234 224 import mapChinaJson from './mapGeojson/china.json'
  225 +import SelectCity from './components/SelectCity.vue'
235 226
236 227 const mapRegionOptions = ref([
237 228 {
... ... @@ -274,4 +265,15 @@ const seriesList = computed(() => {
274 265 const mapRegion = computed(() => {
275 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 279 </script>
... ...
1 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 11 </v-chart>
4 12 </template>
5 13
... ... @@ -17,6 +25,7 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore
17 25 import { isPreview } from '@/utils'
18 26 import mapJsonWithoutHainanIsLands from './mapWithoutHainanIsLands.json'
19 27 import { DatasetComponent, GridComponent, TooltipComponent, GeoComponent, VisualMapComponent } from 'echarts/components'
  28 +import cityMap from './mapGeojson/china-main-city-map.json'
20 29
21 30 const props = defineProps({
22 31 themeSetting: {
... ... @@ -46,9 +55,37 @@ use([
46 55 VisualMapComponent
47 56 ])
48 57
  58 +const saveSelectValue = ref('')
  59 +
49 60 const option = reactive({
50 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 89 const vChartRef = ref<typeof VChart>()
53 90
54 91 //动态获取json注册地图
... ... @@ -67,7 +104,7 @@ registerMap(`${props.chartConfig.option.mapRegion.adcode}`, { geoJSON: {} as any
67 104 // 进行更换初始化地图 如果为china 单独处理
68 105 const registerMapInitAsync = async () => {
69 106 await nextTick()
70   - const adCode = `${props.chartConfig.option.mapRegion.adcode}`;
  107 + const adCode = `${props.chartConfig.option.mapRegion.adcode}`
71 108 if (adCode !== 'china') {
72 109 await getGeojson(adCode)
73 110 } else {
... ... @@ -93,6 +130,7 @@ const dataSetHandle = async (dataset: any) => {
93 130
94 131 isPreview() && vEchartsSetOption()
95 132 }
  133 +
96 134 // 处理海南群岛
97 135 const hainanLandsHandle = async (newData: boolean) => {
98 136 if (newData) {
... ... @@ -101,6 +139,7 @@ const hainanLandsHandle = async (newData: boolean) => {
101 139 registerMap('china', { geoJSON: mapJsonWithoutHainanIsLands as any, specialAreas: {} })
102 140 }
103 141 }
  142 +
104 143 //监听 dataset 数据发生变化
105 144 watch(
106 145 () => props.chartConfig.option.dataset,
... ... @@ -153,4 +192,14 @@ watch(
153 192 useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
154 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 205 </script>
... ...