335 lines
8.7 KiB
Vue
335 lines
8.7 KiB
Vue
<template>
|
||
<div class="w-314px">
|
||
<div
|
||
class="font-pmzd text-18px mt-19px text-center bg-clip-text text-transparent bg-gradient-to-t from-[#76E9F0] to-[#A7E6EE]"
|
||
>隆昌农业产业情况(万元)</div
|
||
>
|
||
<div class="w-full h-250px mx-auto mt-10px" ref="chartRef"> </div>
|
||
<div
|
||
class="font-bold text-18px bg-clip-text text-transparent bg-gradient-to-t from-[#76E9F0] to-[#A7E6EE] text-center mt-10px"
|
||
>
|
||
总产值:
|
||
<CountTo
|
||
:startVal="0"
|
||
:endVal="countNumber"
|
||
class="font-bold text-18px bg-clip-text text-transparent bg-gradient-to-t from-[#76E9F0] to-[#A7E6EE]"
|
||
/>
|
||
万元
|
||
</div>
|
||
|
||
<div class="grid grid-cols-2 gap-y-18px gap-x-10px mx-10px mt-18px">
|
||
<div class="flex items-center" v-for="item in cityData" :key="item.slug">
|
||
<!-- <SvgIcon :name="item.slug" :size="40" color="transparent" /> -->
|
||
<img :src="item.icon" alt="" class="w-40px h-40px aim-spin" srcset="" />
|
||
<div class="text-white ml-6px">
|
||
<div class="text-12px font-bold">{{ item.name }}</div>
|
||
<div class="text-10px font-bold mt-4px">
|
||
<CountTo :startVal="0" :endVal="item.value" class="text-10px font-bold" />
|
||
<span>{{ item.unit }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<CModal v-model:visible="modelVisible" :footer="null" :name="currentData.name" />
|
||
</div>
|
||
</template>
|
||
|
||
<script lang="ts">
|
||
import {
|
||
Ref,
|
||
ref,
|
||
defineComponent,
|
||
onBeforeMount,
|
||
reactive,
|
||
toRefs,
|
||
watch,
|
||
computed,
|
||
onMounted,
|
||
} from 'vue'
|
||
import CModal from './CModal.vue'
|
||
import { useECharts } from '/@/hooks/web/useECharts'
|
||
import { getCitydataStatistics, getCropYieldCategoryStatics } from '/@/api/sys/other'
|
||
import { CountTo } from '/@/components/CountTo'
|
||
import { useVContext } from '../useVContext'
|
||
import { deepMerge } from '/@/utils'
|
||
import cityIcon1 from '/@/assets/images/city-1.png'
|
||
import cityIcon2 from '/@/assets/images/city-2.png'
|
||
import cityIcon3 from '/@/assets/images/city-3.png'
|
||
import cityIcon4 from '/@/assets/images/city-4.png'
|
||
|
||
import { useVisualizationStore } from '/@/store/modules/visualization'
|
||
|
||
var colorList = ['#73DDFF', '#73ACFF', '#FDD56A', '#FDB36A', '#FD866A', '#9E87FF', '#58D5FF']
|
||
|
||
interface cityDataType {
|
||
name: string
|
||
slug: string
|
||
unit: string
|
||
value: number
|
||
icon: string
|
||
}
|
||
|
||
const cityDefaultData = [
|
||
{
|
||
slug: 'city_data_area',
|
||
name: '面积',
|
||
value: '0',
|
||
unit: '平方公里',
|
||
icon: cityIcon1,
|
||
},
|
||
{
|
||
slug: 'city_data_population',
|
||
name: '人口',
|
||
value: '0',
|
||
unit: '万人',
|
||
icon: cityIcon2,
|
||
},
|
||
{
|
||
slug: 'city_data_street',
|
||
name: '镇街',
|
||
value: '0',
|
||
unit: '个',
|
||
icon: cityIcon3,
|
||
},
|
||
{
|
||
slug: 'city_data_cultivated_area',
|
||
name: '耕地',
|
||
value: '0',
|
||
unit: '万亩',
|
||
icon: cityIcon4,
|
||
},
|
||
]
|
||
|
||
export default defineComponent({
|
||
components: {
|
||
CountTo,
|
||
CModal,
|
||
},
|
||
setup() {
|
||
const modelVisible = ref(false)
|
||
const visualizationStore = useVisualizationStore()
|
||
const chartRef = ref<HTMLDivElement | null>(null)
|
||
const { setOptions, getInstance } = useECharts(chartRef as Ref<HTMLDivElement>)
|
||
const Data = reactive({
|
||
cityData: [] as cityDataType[],
|
||
lyqkData: [] as any,
|
||
})
|
||
|
||
const currentData = ref<any>({})
|
||
|
||
const { rootEmitter } = useVContext()
|
||
|
||
function chatInit() {
|
||
setOptions({
|
||
legend: {
|
||
show: true,
|
||
textStyle: {
|
||
color: '#fff',
|
||
},
|
||
orient: 'vertical',
|
||
right: 0,
|
||
top: 20,
|
||
bottom: 20,
|
||
},
|
||
tooltip: {
|
||
trigger: 'item',
|
||
// formatter: function (params) {
|
||
// return params.marker + params.name + ' ' + params.value + ' 万元'
|
||
// },
|
||
},
|
||
series: [
|
||
{
|
||
name: '隆昌农业产业情况',
|
||
type: 'pie',
|
||
radius: '80%',
|
||
center: ['40%', '50%'],
|
||
colorBy: 'data',
|
||
color: colorList,
|
||
itemStyle: {
|
||
color: function (params) {
|
||
return colorList[params.dataIndex]
|
||
},
|
||
},
|
||
label: {
|
||
show: false,
|
||
formatter: '{b}\n{d}%',
|
||
},
|
||
data: Data.lyqkData.map((item, index) => {
|
||
item.label = {
|
||
color: colorList[index],
|
||
}
|
||
return item
|
||
}),
|
||
},
|
||
],
|
||
})
|
||
|
||
chartAmi()
|
||
}
|
||
|
||
let timer: any = null
|
||
function chartAmi() {
|
||
let index = 0
|
||
timer && clearInterval(timer)
|
||
timer = setInterval(() => {
|
||
const currentIndex = index % Data.lyqkData.length
|
||
// getInstance()?.dispatchAction({
|
||
// type: 'legendUnSelect',
|
||
// name: legendData[currentIndex],
|
||
// })
|
||
|
||
// getInstance()?.dispatchAction({
|
||
// type: 'legendSelect',
|
||
// name: legendData[currentIndex],
|
||
// })
|
||
|
||
getInstance()?.dispatchAction({
|
||
type: 'showTip',
|
||
seriesIndex: 0,
|
||
dataIndex: currentIndex,
|
||
})
|
||
|
||
getInstance()?.dispatchAction({
|
||
type: 'downplay',
|
||
seriesIndex: 0,
|
||
dataIndex: currentIndex - 1,
|
||
})
|
||
getInstance()?.dispatchAction({
|
||
type: 'highlight',
|
||
seriesIndex: 0,
|
||
dataIndex: currentIndex,
|
||
})
|
||
|
||
index++
|
||
}, 3000)
|
||
}
|
||
|
||
async function getCropYieldCategory() {
|
||
const { list } = await getCropYieldCategoryStatics({
|
||
year: visualizationStore.getYear,
|
||
base_id: visualizationStore.getAddresId,
|
||
})
|
||
|
||
const arr = [] as { value: string | number; name: string }[]
|
||
for (const key in list) {
|
||
if (Object.prototype.hasOwnProperty.call(list, key)) {
|
||
arr.push({
|
||
value: (list[key] / 10000).toFixed(2),
|
||
name: key,
|
||
})
|
||
}
|
||
}
|
||
Data.lyqkData = arr
|
||
}
|
||
|
||
//获取所有
|
||
async function getCitydata() {
|
||
const resData = await getCitydataStatistics()
|
||
const temp = [] as cityDataType[]
|
||
cityDefaultData.forEach((e) => {
|
||
const obj = deepMerge({}, e)
|
||
const item: cityDataType = resData.find((r) => r.slug == e.slug)
|
||
if (item) {
|
||
obj.value = Number(item.value)
|
||
obj.unit = item.unit
|
||
}
|
||
temp.push(obj)
|
||
})
|
||
Data.cityData = temp
|
||
}
|
||
|
||
function onChangeMap(el) {
|
||
const keys = ['city_data_street']
|
||
const temp = [] as cityDataType[]
|
||
cityDefaultData.forEach((e) => {
|
||
const obj = deepMerge({}, e)
|
||
if (!keys.includes(e.slug)) {
|
||
//面积
|
||
if (e.slug == 'city_data_area') {
|
||
obj.value = Number(el.areas)
|
||
obj.unit = '亩'
|
||
} else if (e.slug == 'city_data_population') {
|
||
obj.value = el.workforce
|
||
} else if (e.slug == 'city_data_cultivated_area') {
|
||
obj.value = el.cultivated
|
||
}
|
||
temp.push(obj)
|
||
}
|
||
})
|
||
Data.cityData = temp
|
||
}
|
||
|
||
const countNumber = computed(() =>
|
||
Data.lyqkData.reduce((c, p) => {
|
||
c += Number(p.value)
|
||
return c
|
||
}, 0),
|
||
)
|
||
|
||
onMounted(() => {
|
||
getInstance()?.on('click', (e) => {
|
||
currentData.value = e.data
|
||
modelVisible.value = true
|
||
})
|
||
})
|
||
|
||
onBeforeMount(() => {
|
||
getCitydata()
|
||
getCropYieldCategory()
|
||
//地图点击
|
||
rootEmitter.on('map:click', (e) => {
|
||
onChangeMap(e)
|
||
getCropYieldCategory()
|
||
})
|
||
//地图返回
|
||
rootEmitter.on('map:back', () => {
|
||
getCitydata()
|
||
getCropYieldCategory()
|
||
})
|
||
|
||
rootEmitter.on('interval:auto', () => {
|
||
getCropYieldCategory()
|
||
})
|
||
})
|
||
|
||
watch(
|
||
() => Data.lyqkData,
|
||
() => {
|
||
chatInit()
|
||
},
|
||
)
|
||
|
||
watch(
|
||
() => visualizationStore.getYear,
|
||
() => {
|
||
getCropYieldCategory()
|
||
},
|
||
)
|
||
|
||
return {
|
||
modelVisible,
|
||
chartRef,
|
||
countNumber,
|
||
currentData,
|
||
...toRefs(Data),
|
||
}
|
||
},
|
||
})
|
||
</script>
|
||
|
||
<style scoped>
|
||
.aim-spin {
|
||
animation: spin 2s linear infinite;
|
||
}
|
||
|
||
@keyframes spin {
|
||
50% {
|
||
transform: scaleX(0);
|
||
}
|
||
|
||
100% {
|
||
transform: scaleX(1);
|
||
}
|
||
}
|
||
</style>
|