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,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> |