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