Showing
4 changed files
with
165 additions
and
22 deletions
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> | ... | ... |