中间完成

This commit is contained in:
bunny 2025-05-24 17:27:51 +08:00
parent 8ca3934de7
commit e381bb62a4
8 changed files with 272 additions and 32 deletions

View File

@ -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: '操作成功',
}),
},
]);

View File

@ -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');
};

View File

@ -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,
]);
/**

View File

@ -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();
},
},
});

View File

@ -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 });
};

View File

@ -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 });
};

View File

@ -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="销售设备数量区域占比" />

View File

@ -15,7 +15,7 @@ const { deviceSalesStats, companySalesDistribution, brandsDistribution } =
/* 初始化数据获取 */
const initAppData = async () => {
//
dataAnalyseStore.fetchDeviceSaesStats();
dataAnalyseStore.fetchDeviceSalesStats();
//
dataAnalyseStore.fetchCompanySalesDistribution();
//