✨ 中间完成
This commit is contained in:
parent
8ca3934de7
commit
e381bb62a4
|
@ -56,4 +56,49 @@ export default defineFakeRoute([
|
|||
message: '操作成功',
|
||||
}),
|
||||
},
|
||||
// 数据展示
|
||||
{
|
||||
url: `${BASE_URL}/data-show`,
|
||||
method: 'GET',
|
||||
response: () => ({
|
||||
code: 200,
|
||||
data: Array(3)
|
||||
.fill(0)
|
||||
.map((_, index) => ({
|
||||
name: `数据展示-${index + 1}`,
|
||||
value: randomNumber(99999),
|
||||
})),
|
||||
message: '操作成功',
|
||||
}),
|
||||
},
|
||||
{
|
||||
url: `${BASE_URL}/region-sales-ratio`,
|
||||
method: 'GET',
|
||||
response: () => ({
|
||||
code: 200,
|
||||
data: Array(12)
|
||||
.fill(0)
|
||||
.map((_, index) => {
|
||||
const city = [
|
||||
'北京',
|
||||
'上海',
|
||||
'广州',
|
||||
'深圳',
|
||||
'成都',
|
||||
'杭州',
|
||||
'武汉',
|
||||
'重庆',
|
||||
'西安',
|
||||
'苏州',
|
||||
'南京',
|
||||
'长沙',
|
||||
];
|
||||
return {
|
||||
name: city[index],
|
||||
value: randomNumber(9999),
|
||||
};
|
||||
}),
|
||||
message: '操作成功',
|
||||
}),
|
||||
},
|
||||
]);
|
||||
|
|
|
@ -14,3 +14,13 @@ export const getCompanySalesDistribution = () => {
|
|||
export const getBrandsDistribution = () => {
|
||||
return request.get('data-analyse/brands-distribution');
|
||||
};
|
||||
|
||||
/* 数据展示 */
|
||||
export const getDataShow = () => {
|
||||
return request.get('data-analyse/data-show');
|
||||
};
|
||||
|
||||
/* 销售设备数量区域占比 */
|
||||
export const getRegionSalesRatio = () => {
|
||||
return request.get('data-analyse/region-sales-ratio');
|
||||
};
|
||||
|
|
|
@ -1,4 +1,13 @@
|
|||
import { BarChart, GaugeChart, LineChart, PictorialBarChart, PieChart } from 'echarts/charts';
|
||||
import {
|
||||
BarChart,
|
||||
EffectScatterChart,
|
||||
GaugeChart,
|
||||
LineChart,
|
||||
MapChart,
|
||||
PictorialBarChart,
|
||||
PieChart,
|
||||
TreemapChart,
|
||||
} from 'echarts/charts';
|
||||
import {
|
||||
DataZoomComponent,
|
||||
GraphicComponent,
|
||||
|
@ -17,11 +26,13 @@ import type { App } from 'vue';
|
|||
const { use } = echarts;
|
||||
use([
|
||||
PieChart,
|
||||
EffectScatterChart,
|
||||
BarChart,
|
||||
LineChart,
|
||||
CanvasRenderer,
|
||||
SVGRenderer,
|
||||
GridComponent,
|
||||
TreemapChart,
|
||||
TitleComponent,
|
||||
PolarComponent,
|
||||
LegendComponent,
|
||||
|
@ -32,6 +43,7 @@ use([
|
|||
VisualMapComponent,
|
||||
PictorialBarChart,
|
||||
GaugeChart,
|
||||
MapChart,
|
||||
]);
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,7 +3,9 @@ import { defineStore } from 'pinia';
|
|||
import {
|
||||
getBrandsDistribution,
|
||||
getCompanySalesDistribution,
|
||||
getDataShow,
|
||||
getDeviceSalesStats,
|
||||
getRegionSalesRatio,
|
||||
} from '@/api/dataAnalyse';
|
||||
|
||||
import { store } from '..';
|
||||
|
@ -19,10 +21,14 @@ export const useDataAnalyseStore = defineStore('dataAnalyseStore', {
|
|||
companySalesDistribution: [],
|
||||
// 品牌占有率
|
||||
brandsDistribution: [],
|
||||
// 数据展示
|
||||
dataShow: [],
|
||||
// 销售设备数量区域占比
|
||||
regionSalesRatio: [],
|
||||
}),
|
||||
actions: {
|
||||
/* 销售设备总量 */
|
||||
async fetchDeviceSaesStats() {
|
||||
async fetchDeviceSalesStats() {
|
||||
this.deviceSalesStats = await getDeviceSalesStats();
|
||||
},
|
||||
|
||||
|
@ -35,6 +41,16 @@ export const useDataAnalyseStore = defineStore('dataAnalyseStore', {
|
|||
async fetchBrandsDistribution() {
|
||||
this.brandsDistribution = await getBrandsDistribution();
|
||||
},
|
||||
|
||||
/* 数据展示 */
|
||||
async fetchDataShow() {
|
||||
this.dataShow = await getDataShow();
|
||||
},
|
||||
|
||||
/* 销售设备数量区域占比 */
|
||||
async fetchRegionSalesRatio() {
|
||||
this.regionSalesRatio = await getRegionSalesRatio();
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
import type { Ref } from 'vue';
|
||||
|
||||
import echarts from '@/plugins/echarts';
|
||||
import { debounceChart } from '@/utils/chart';
|
||||
|
||||
let myChart = null;
|
||||
|
||||
const option = {
|
||||
grid: { left: '4%', right: '4%', bottom: '19%', top: '20%', containLabel: true },
|
||||
roam: true,
|
||||
geo: {
|
||||
map: 'jiangsu',
|
||||
roam: true,
|
||||
// 长宽比
|
||||
aspectScale: 1,
|
||||
zoom: 1.4,
|
||||
// label: { show: true, color: '#fff', fontSize: 12 },
|
||||
itemStyle: {
|
||||
areaColor: '#113F7D',
|
||||
borderColor: '#2678B6',
|
||||
borderWidth: 1,
|
||||
},
|
||||
emphasis: {
|
||||
// 鼠标放上是否显示地区名称
|
||||
label: { show: false, color: '#FFD700', fontSize: 14 },
|
||||
itemStyle: { areaColor: '#1E90FF' },
|
||||
},
|
||||
},
|
||||
series: [
|
||||
// {
|
||||
// type: 'map',
|
||||
// map: 'jiangsu',
|
||||
// label: {
|
||||
// show: true,
|
||||
// color: '#fff',
|
||||
// fontSize: 12,
|
||||
// formatter: '{b}',
|
||||
// rich: {
|
||||
// bg: {
|
||||
// backgroundColor: 'rgba(0,0,0,0.5)',
|
||||
// borderRadius: 4,
|
||||
// padding: [2, 4],
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// itemStyle: {
|
||||
// areaColor: '#113F7D',
|
||||
// borderColor: '#2678B6',
|
||||
// borderWidth: 1,
|
||||
// },
|
||||
// emphasis: {
|
||||
// label: {
|
||||
// show: true,
|
||||
// formatter: ['{bg|{b}}'].join('\n'),
|
||||
// },
|
||||
// itemStyle: {
|
||||
// areaColor: '#1E90FF',
|
||||
// },
|
||||
// },
|
||||
// data: [
|
||||
// { name: '南京市', value: 100 },
|
||||
// { name: '苏州市', value: 95 },
|
||||
// { name: '无锡市', value: 90 },
|
||||
// { name: '常州市', value: 85 },
|
||||
// { name: '镇江市', value: 80 },
|
||||
// { name: '扬州市', value: 75 },
|
||||
// { name: '泰州市', value: 70 },
|
||||
// { name: '南通市', value: 65 },
|
||||
// { name: '盐城市', value: 60 },
|
||||
// { name: '淮安市', value: 55 },
|
||||
// { name: '连云港市', value: 50 },
|
||||
// { name: '徐州市', value: 45 },
|
||||
// { name: '宿迁市', value: 40 },
|
||||
// ],
|
||||
// },
|
||||
{
|
||||
type: 'effectScatter',
|
||||
coordinateSystem: 'geo',
|
||||
symbolSize: 8,
|
||||
rippleEffect: {
|
||||
brushType: 'stroke',
|
||||
scale: 5,
|
||||
period: 3,
|
||||
},
|
||||
itemStyle: {
|
||||
color: '#FFD700',
|
||||
shadowBlur: 10,
|
||||
shadowColor: '#FFD700',
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
position: 'right',
|
||||
formatter: '{b}',
|
||||
color: '#FFD700',
|
||||
fontSize: 12,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
data: [
|
||||
// 江苏省各市中心坐标 [经度, 纬度, 数据值]
|
||||
{ name: '南京市', value: [118.7674, 32.0415, 100] },
|
||||
{ name: '苏州市', value: [120.6196, 31.2994, 95] },
|
||||
{ name: '无锡市', value: [120.3017, 31.5747, 90] },
|
||||
{ name: '常州市', value: [119.947, 31.7799, 85] },
|
||||
{ name: '镇江市', value: [119.4528, 32.2044, 80] },
|
||||
{ name: '扬州市', value: [119.421, 32.3932, 75] },
|
||||
{ name: '泰州市', value: [119.915, 32.4849, 70] },
|
||||
{ name: '南通市', value: [120.8646, 32.0162, 65] },
|
||||
{ name: '盐城市', value: [120.1399, 33.3776, 60] },
|
||||
{ name: '淮安市', value: [119.0213, 33.5975, 55] },
|
||||
{ name: '连云港市', value: [119.1788, 34.6, 50] },
|
||||
{ name: '徐州市', value: [117.1848, 34.2618, 45] },
|
||||
{ name: '宿迁市', value: [118.2752, 33.963, 40] },
|
||||
],
|
||||
zlevel: 1,
|
||||
},
|
||||
],
|
||||
visualMap: {
|
||||
min: 0,
|
||||
max: 100,
|
||||
text: ['高', '低'],
|
||||
realtime: false,
|
||||
calculable: true,
|
||||
inRange: { color: ['#50a3ba', '#eac736', '#d94e5d'] },
|
||||
textStyle: { color: '#fff' },
|
||||
},
|
||||
};
|
||||
|
||||
/** 渲染图表 */
|
||||
export const renderBodyChart = async (element: Ref<HTMLDivElement>) => {
|
||||
myChart = echarts.init(element.value, null, {
|
||||
renderer: 'canvas',
|
||||
devicePixelRatio: window.devicePixelRatio,
|
||||
});
|
||||
const json = await (
|
||||
await fetch('https://geo.datav.aliyun.com/areas_v3/bound/320000_full.json')
|
||||
).json();
|
||||
|
||||
debounceChart(myChart);
|
||||
echarts.registerMap('jiangsu', json);
|
||||
myChart.setOption(option);
|
||||
};
|
||||
|
||||
/** 更新图表数据 */
|
||||
export const updateBodyChart = (data: any) => {
|
||||
const series = myChart.getOption().series;
|
||||
series[0].data = data;
|
||||
myChart.setOption({ series });
|
||||
};
|
|
@ -15,26 +15,18 @@ const option = {
|
|||
},
|
||||
title: {
|
||||
text: '单位:(万元)',
|
||||
textStyle: {
|
||||
color: 'rgba(131, 162, 192, 1)',
|
||||
fontSize: 12,
|
||||
},
|
||||
textStyle: { color: '#83A2C0FF', fontSize: 12 },
|
||||
top: '4%',
|
||||
left: '2%',
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
tooltip: { trigger: 'axis' },
|
||||
legend: {
|
||||
data: ['增加值'],
|
||||
icon: 'rich',
|
||||
show: true,
|
||||
itemWidth: 18,
|
||||
itemHeight: 2,
|
||||
textStyle: {
|
||||
color: '#AFBDD1',
|
||||
fontSize: '12px',
|
||||
},
|
||||
textStyle: { color: '#AFBDD1', fontSize: '12px' },
|
||||
top: 8,
|
||||
right: 10,
|
||||
itemGap: 34,
|
||||
|
@ -50,9 +42,7 @@ const option = {
|
|||
color: '#50637A',
|
||||
},
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
axisTick: { show: false },
|
||||
axisLabel: {
|
||||
interval: 0,
|
||||
color: '#6071A9',
|
||||
|
@ -77,9 +67,9 @@ const option = {
|
|||
series: [
|
||||
{
|
||||
name: '增加值',
|
||||
data: [1, 2, 3, 4, 7, 6, 7, 8, 4, 10],
|
||||
data: [],
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
// smooth: true,
|
||||
color: '#00F7FF',
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
|
@ -119,14 +109,12 @@ export const renderFooterChart = (element: Ref<HTMLDivElement>) => {
|
|||
});
|
||||
|
||||
debounceChart(myChart);
|
||||
|
||||
myChart.setOption(option);
|
||||
};
|
||||
|
||||
/** 更新图表数据 */
|
||||
export const updateChart = (option: Array<Array<number>>) => {
|
||||
export const updateChart = (data: any) => {
|
||||
const series = myChart.getOption().series;
|
||||
// series[0].data = option[0];
|
||||
// series[1].data = option[1];
|
||||
series[0].data = data;
|
||||
myChart.setOption({ series });
|
||||
};
|
||||
|
|
|
@ -1,33 +1,54 @@
|
|||
<script lang="ts" setup>
|
||||
import { useIntervalFn } from '@vueuse/core';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
import { renderFooterChart } from '@/views/data-analyse/charts/content-footer';
|
||||
import { useDataAnalyseHook } from '@/store/modules/dataAnalyse';
|
||||
import { renderBodyChart } from '@/views/data-analyse/charts/content-body';
|
||||
import { renderFooterChart, updateChart } from '@/views/data-analyse/charts/content-footer';
|
||||
import PanelTitle from '@/views/data-analyse/components/PanelTitle.vue';
|
||||
|
||||
const titleList = [170582, 586220, 168902];
|
||||
const dataAnalyseHook = useDataAnalyseHook();
|
||||
const { dataShow, regionSalesRatio } = storeToRefs(dataAnalyseHook);
|
||||
|
||||
const footerChartRef = ref();
|
||||
const bodyChartRef = ref();
|
||||
|
||||
const footerChart = () => {
|
||||
renderFooterChart(footerChartRef);
|
||||
// 初始化数据
|
||||
const initAppData = async () => {
|
||||
// 数据展示
|
||||
dataAnalyseHook.fetchDataShow();
|
||||
// 销售设备数量区域占比
|
||||
await dataAnalyseHook.fetchRegionSalesRatio();
|
||||
|
||||
updateChart(regionSalesRatio.value);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
footerChart();
|
||||
renderFooterChart(footerChartRef);
|
||||
renderBodyChart(bodyChartRef);
|
||||
|
||||
initAppData();
|
||||
|
||||
useIntervalFn(() => {
|
||||
initAppData();
|
||||
}, 1000);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="data-analyse-content">
|
||||
<ul class="data-analyse-content__header">
|
||||
<li v-for="(item, index) in titleList" :key="index">
|
||||
<h3>数据展示</h3>
|
||||
<strong>{{ item }}</strong>
|
||||
<li v-for="(item, index) in dataShow" :key="index">
|
||||
<h3>{{ item.name }}</h3>
|
||||
<strong>{{ item.value }}</strong>
|
||||
<span>台</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<main class="data-analyse-content__body">body</main>
|
||||
<main class="data-analyse-content__body">
|
||||
<div ref="bodyChartRef" class="w-full h-[567px]" />
|
||||
</main>
|
||||
|
||||
<footer class="data-analyse-content__footer">
|
||||
<PanelTitle title="销售设备数量区域占比" />
|
||||
|
|
|
@ -15,7 +15,7 @@ const { deviceSalesStats, companySalesDistribution, brandsDistribution } =
|
|||
/* 初始化数据获取 */
|
||||
const initAppData = async () => {
|
||||
// 销售设备总量
|
||||
dataAnalyseStore.fetchDeviceSaesStats();
|
||||
dataAnalyseStore.fetchDeviceSalesStats();
|
||||
// 销售公司销售设备数量占比
|
||||
dataAnalyseStore.fetchCompanySalesDistribution();
|
||||
// 品牌占有率
|
||||
|
|
Loading…
Reference in New Issue