From 180bc3c40643a640787b72e5880ff96e17c8c33c Mon Sep 17 00:00:00 2001
From: bunny <1319900154@qq.com>
Date: Tue, 13 May 2025 20:04:27 +0800
Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20=E7=A4=BE=E5=8C=BA=E5=B7=A6?=
=?UTF-8?q?=E8=BE=B9=E5=92=8C=E4=B8=AD=E9=97=B4=E5=AE=8C=E6=88=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
mock/community.ts | 94 ++++++++++-----
src/api/community.ts | 14 +++
src/api/smartPark.ts | 6 +-
.../DigitalNumber/DigitalNumber.tsx | 4 +-
src/store/modules/community.ts | 35 +++++-
src/store/modules/smartPark.ts | 18 ++-
src/views/big-data/charts/left-body.tsx | 23 ++--
.../charts/right-bottom-chart.vue | 2 +-
.../community/charts/conten-body-chart.tsx | 82 +++++++++++++
.../community/charts/left-body-chart.tsx | 67 +++++++++++
.../community/charts/left-header-chart.tsx | 109 ++++++++++++++++++
.../components/community-content.vue | 70 ++++++-----
.../community/components/community-left.vue | 75 +++++++++++-
.../components/smart-park-content.vue | 6 +-
14 files changed, 509 insertions(+), 96 deletions(-)
create mode 100644 src/views/community/charts/conten-body-chart.tsx
create mode 100644 src/views/community/charts/left-body-chart.tsx
create mode 100644 src/views/community/charts/left-header-chart.tsx
diff --git a/mock/community.ts b/mock/community.ts
index e56c902..68cb57e 100644
--- a/mock/community.ts
+++ b/mock/community.ts
@@ -5,41 +5,81 @@ const randomNumber = (range: number = 100) => {
};
export default defineFakeRoute([
+ // 设备总数
+ {
+ url: '/api/community/devices-amount',
+ method: 'GET',
+ response: () => ({
+ code: 200,
+ data: [
+ { name: '设备类型一', outside: randomNumber(), connect: randomNumber() },
+ { name: '设备类型二', outside: randomNumber(), connect: randomNumber() },
+ { name: '设备类型三', outside: randomNumber(), connect: randomNumber() },
+ { name: '设备类型四', outside: randomNumber(), connect: randomNumber() },
+ ],
+ message: '操作成功',
+ }),
+ },
+ // 预警概览
+ {
+ url: '/api/community/alarms-overview',
+ method: 'GET',
+ response: () => ({
+ code: 200,
+ data: {
+ total: 500000,
+ list: Array(4)
+ .fill(0)
+ .map((_, index) => ({ name: `name-${index}`, value: randomNumber(9999) })),
+ },
+ message: '操作成功',
+ }),
+ },
+ // 中间顶部区域
{
url: '/api/community/community-statistics',
method: 'GET',
response: () => ({
code: 200,
- data: [
- {
- name: '统计人口',
+ data: Array(4)
+ .fill(0)
+ .map((_, index) => ({
+ name: `统计人口-${index + 1}`,
total: randomNumber(9999),
- subtitle: '常驻人口',
+ subtitle: `常驻人口${index + 1}`,
subPercent: `${randomNumber()}%`,
subTotal: randomNumber(99999),
- },
- {
- name: '统计人口',
- total: randomNumber(9999),
- subtitle: '常驻人口',
- subPercent: `${randomNumber()}%`,
- subTotal: randomNumber(99999),
- },
- {
- name: '统计人口',
- total: randomNumber(9999),
- subtitle: '常驻人口',
- subPercent: `${randomNumber()}%`,
- subTotal: randomNumber(99999),
- },
- {
- name: '统计人口',
- total: randomNumber(9999),
- subtitle: '常驻人口',
- subPercent: `${randomNumber()}%`,
- subTotal: randomNumber(99999),
- },
- ],
+ })),
+ message: '操作成功',
+ }),
+ },
+ // 中间区域设备运行状态
+ {
+ url: '/api/community/devices-status',
+ method: 'GET',
+ response: () => ({
+ code: 200,
+ data: {
+ devcies: [
+ {
+ title: '正常运行总数',
+ total: randomNumber(100),
+ },
+ {
+ title: '故障总数',
+ total: randomNumber(100),
+ },
+ {
+ title: '故障总数',
+ total: randomNumber(100),
+ },
+ {
+ title: '故障总数',
+ total: randomNumber(100),
+ },
+ ],
+ security: randomNumber(),
+ },
message: '操作成功',
}),
},
diff --git a/src/api/community.ts b/src/api/community.ts
index 6610482..0d0d650 100644
--- a/src/api/community.ts
+++ b/src/api/community.ts
@@ -1,6 +1,20 @@
import request from '@/api/server/request';
+/* 设备总数 */
+export const getCommunityDevicesAmount = () => {
+ return request.get('community/devices-amount');
+};
+
+export const getAlarmsOverview = () => {
+ return request.get('community/alarms-overview');
+};
+
/* 社区统计 */
export const getCommunityStatistics = () => {
return request.get('community/community-statistics');
};
+
+/* 设备运行状态 */
+export const getCommityDeicesStatus = () => {
+ return request.get('/community/devices-status');
+};
diff --git a/src/api/smartPark.ts b/src/api/smartPark.ts
index 16d630c..e499867 100644
--- a/src/api/smartPark.ts
+++ b/src/api/smartPark.ts
@@ -1,16 +1,16 @@
import request from '@/api/server/request';
/* 实时道路 */
-export const fetchRoadStatus = () => {
+export const gethRoadStatus = () => {
return request.get('/smart-park/road-status');
};
/* 车辆监控 */
-export const fetchTollgateMonitoringData = () => {
+export const getTollgateMonitoringData = () => {
return request.get('smart-park/monitor');
};
/* 车流量概览 */
-export const fetchTrafficStatistics = () => {
+export const getTrafficStatistics = () => {
return request.get('/smart-park/flow-rate');
};
diff --git a/src/components/DigitalNumber/DigitalNumber.tsx b/src/components/DigitalNumber/DigitalNumber.tsx
index bb61b5d..70e9934 100644
--- a/src/components/DigitalNumber/DigitalNumber.tsx
+++ b/src/components/DigitalNumber/DigitalNumber.tsx
@@ -21,11 +21,11 @@ export default defineComponent({
.flat();
return () => (
- <>
+
{moneyStringList.map((item, index) => (
{item}
))}
- >
+
);
},
});
diff --git a/src/store/modules/community.ts b/src/store/modules/community.ts
index b2c9f0d..62d9e21 100644
--- a/src/store/modules/community.ts
+++ b/src/store/modules/community.ts
@@ -1,15 +1,42 @@
import { defineStore } from 'pinia';
-import { getCommunityStatistics } from '@/api/community';
+import {
+ getAlarmsOverview,
+ getCommityDeicesStatus,
+ getCommunityDevicesAmount,
+ getCommunityStatistics,
+} from '@/api/community';
export const useCommunityStore = defineStore('communityStore', {
state: () => ({
- communityStatisticsList: [],
+ // 设备总数
+ devicesList: [],
+ // 预警概览
+ alarmOverviewList: [],
+ // 统计列表
+ statisticsList: [],
+ // 设备状态
+ deviceStatus: { devcies: [], security: undefined },
}),
actions: {
+ /* 设备总数 */
+ async fetchCommunityDevicesAmount() {
+ const result = await getCommunityDevicesAmount();
+ this.devicesList = result;
+ },
+ /* 预警概览 */
+ async fetchAlarmsOverview() {
+ const result = await getAlarmsOverview();
+ this.alarmOverviewList = result;
+ },
/* 社区统计 */
- async loadCommunityStatisticsList() {
- this.communityStatisticsList = await getCommunityStatistics();
+ async fetchCommunityStatisticsList() {
+ this.statisticsList = await getCommunityStatistics();
+ },
+ /* 设备状态 */
+ async fetchCommityDeicesStatus() {
+ const result = await getCommityDeicesStatus();
+ this.deviceStatus = result;
},
},
});
diff --git a/src/store/modules/smartPark.ts b/src/store/modules/smartPark.ts
index 5fc3f7b..eecb229 100644
--- a/src/store/modules/smartPark.ts
+++ b/src/store/modules/smartPark.ts
@@ -1,10 +1,6 @@
import { defineStore } from 'pinia';
-import {
- fetchRoadStatus,
- fetchTollgateMonitoringData,
- fetchTrafficStatistics,
-} from '@/api/smartPark';
+import { gethRoadStatus, getTollgateMonitoringData, getTrafficStatistics } from '@/api/smartPark';
export const useSmartPark = defineStore('smartparkStore', {
state: () => ({
@@ -19,19 +15,19 @@ export const useSmartPark = defineStore('smartparkStore', {
}),
actions: {
/* 道路情况 */
- async loadRoadStatus() {
- const result: any = await fetchRoadStatus();
+ async fetchRoadStatus() {
+ const result: any = await gethRoadStatus();
this.roadStatus = result.entrances;
this.roadStatusSuggest = result.suggest;
},
/* 卡口车辆监控 */
- async loadTollgateMonitoringData() {
- const result = await fetchTollgateMonitoringData();
+ async fetchTollgateMonitoringData() {
+ const result = await getTollgateMonitoringData();
this.tollgateMonitoringData = result;
},
/* 车流量概览 */
- async loadFlowRate() {
- const result = await fetchTrafficStatistics();
+ async fetchFlowRate() {
+ const result = await getTrafficStatistics();
this.trafficStatistics = result;
},
},
diff --git a/src/views/big-data/charts/left-body.tsx b/src/views/big-data/charts/left-body.tsx
index 510fc2f..ab93f64 100644
--- a/src/views/big-data/charts/left-body.tsx
+++ b/src/views/big-data/charts/left-body.tsx
@@ -51,13 +51,25 @@ const renderEcharts: any = (myChart: Ref, element: Ref, props: any) => {
+ const series = myChart.value.getOption().series;
+ series[0].data[0].value = props.percent;
+ series[0].data[0].itemStyle = props.percent >= 20 ? itemStyles[0] : itemStyles[1];
+
+ myChart.value?.setOption({ series });
+};
+
/* 封装组件 */
export const ChartProgress = defineComponent({
+ name: 'ChartProgress',
props: { percent: { type: Number } },
setup(props) {
- const chart = ref();
+ // 唯一的 Chart
const myChart = ref();
+ // 元素
+ const chart = ref();
onMounted(() => {
renderEcharts(myChart, chart);
@@ -75,12 +87,3 @@ export const ChartProgress = defineComponent({
return () => ;
},
});
-
-/** 更新图标数据 */
-const updateChart = (myChart: Ref, props: any) => {
- const series = myChart.value.getOption().series;
- series[0].data[0].value = props.percent;
- series[0].data[0].itemStyle = props.percent >= 20 ? itemStyles[0] : itemStyles[1];
-
- myChart.value?.setOption({ series });
-};
diff --git a/src/views/business-supervision/charts/right-bottom-chart.vue b/src/views/business-supervision/charts/right-bottom-chart.vue
index 48fa3d5..905fa57 100644
--- a/src/views/business-supervision/charts/right-bottom-chart.vue
+++ b/src/views/business-supervision/charts/right-bottom-chart.vue
@@ -58,7 +58,7 @@ option.value = {
type: 'pictorialBar',
barWidth: 30,
itemStyle: { color: '#0D3770' },
- symbolRepeat: 'true',
+ symbolRepeat: true,
symbolMargin: 3,
symbol: 'rect',
symbolSize: [30, 4],
diff --git a/src/views/community/charts/conten-body-chart.tsx b/src/views/community/charts/conten-body-chart.tsx
new file mode 100644
index 0000000..5b2569f
--- /dev/null
+++ b/src/views/community/charts/conten-body-chart.tsx
@@ -0,0 +1,82 @@
+import type { EChartsOption } from 'echarts';
+import { type Ref, ref } from 'vue';
+
+import echarts from '@/plugins/echarts';
+import { debounceChart } from '@/utils/chart';
+
+let myChart = null;
+
+const option = ref({
+ grid: { top: 0, right: 0, bottom: -100, left: 0, containLabel: true },
+ series: [
+ {
+ type: 'gauge',
+ startAngle: 180,
+ endAngle: 0,
+ center: ['50%', '75%'],
+ radius: '90%',
+ min: 0,
+ max: 1,
+ splitNumber: 8,
+ axisLine: {
+ lineStyle: { width: 12, color: [[1, '#05C1D3']] },
+ },
+ pointer: {
+ show: false,
+ icon: 'path://M12.8,0.7l12,40.1H0.7L12.8,0.7z',
+ length: '12%',
+ width: 20,
+ offsetCenter: [0, '-60%'],
+ itemStyle: {
+ color: 'auto',
+ },
+ },
+ axisTick: {
+ length: 44,
+ distance: -44,
+ lineStyle: { color: 'auto', width: 1 },
+ },
+ splitLine: {
+ length: 24,
+ distance: -24,
+ lineStyle: { color: 'auto', width: 8, miterLimit: 12 },
+ },
+ progress: {
+ show: true,
+ width: 14,
+ itemStyle: { color: '#707070' },
+ },
+ axisLabel: { show: false },
+ detail: {
+ fontSize: 18,
+ offsetCenter: [0, '-9%'],
+ valueAnimation: true,
+ formatter: function (value) {
+ return Math.round(value * 100) + '\n安全指数';
+ },
+ color: '#05C1D3',
+ },
+ data: [0.5],
+ },
+ ],
+});
+
+/** 渲染图表 */
+export const renderBodyChart = (element: Ref) => {
+ myChart = echarts.init(element.value, null, {
+ renderer: 'canvas',
+ devicePixelRatio: window.devicePixelRatio,
+ });
+
+ debounceChart(myChart);
+
+ myChart.setOption(option.value);
+};
+
+/** 更新图标数据 */
+export const updateBodyChart = (props: any) => {
+ const series = myChart?.getOption()?.series;
+ series[0].data = [props.data / 100];
+
+ myChart.setOption({ series });
+};
diff --git a/src/views/community/charts/left-body-chart.tsx b/src/views/community/charts/left-body-chart.tsx
new file mode 100644
index 0000000..4deb5d6
--- /dev/null
+++ b/src/views/community/charts/left-body-chart.tsx
@@ -0,0 +1,67 @@
+import type { EChartsOption } from 'echarts';
+import { type Ref, ref } from 'vue';
+
+import echarts from '@/plugins/echarts';
+import { debounceChart } from '@/utils/chart';
+
+let myChart = null;
+
+/* 随机颜色 */
+
+const colors = ['#3D7FFF', '#00FFFF', '#FF1190', '#FEDB65'];
+
+const option = ref({
+ title: {
+ text: '34467',
+ subtext: '历史预警数',
+ left: 'center',
+ top: 'center',
+ textStyle: { color: '#fff', fontSize: 34 },
+ subtextStyle: { color: '#fff', fontSize: 16 },
+ },
+ grid: { containLabel: false },
+ polar: { radius: [60, '100%'] },
+ angleAxis: { show: false, startAngle: 90 },
+ radiusAxis: { show: false, type: 'category' },
+ tooltip: {},
+ series: {
+ type: 'bar',
+ data: [],
+ barWidth: 20,
+ barGap: 0,
+ coordinateSystem: 'polar',
+ itemStyle: {},
+ label: { show: true, position: 'middle' },
+ },
+});
+
+/** 渲染图表 */
+export const renderBodyChart = (element: Ref) => {
+ myChart = echarts.init(element.value, null, {
+ renderer: 'canvas',
+ devicePixelRatio: window.devicePixelRatio,
+ });
+
+ debounceChart(myChart);
+
+ myChart.setOption(option.value);
+};
+
+/** 更新图标数据 */
+export const updateBodyChart = (props: any) => {
+ const series = myChart?.getOption()?.series;
+ series[0].data = props.list.map((item, index) => ({
+ name: item.name,
+ value: item.value,
+ itemStyle: { color: colors[index], borderRadius: 10 },
+ }));
+
+ const total = props.list.reduce((old, item) => old + item.value, 0);
+ // const angleAxis = myChart?.getOption()?.angleAxis;
+ // angleAxis[0].max = undefined;
+
+ const title = myChart?.getOption()?.title;
+ title[0].text = total;
+
+ myChart.setOption({ series, title });
+};
diff --git a/src/views/community/charts/left-header-chart.tsx b/src/views/community/charts/left-header-chart.tsx
new file mode 100644
index 0000000..637cdc3
--- /dev/null
+++ b/src/views/community/charts/left-header-chart.tsx
@@ -0,0 +1,109 @@
+import 'echarts/lib/component/dataZoom';
+
+import type { EChartsOption, EChartsType } from 'echarts';
+import { defineComponent, onMounted, type Ref, ref, watch } from 'vue';
+
+import echarts from '@/plugins/echarts';
+import { debounceChart } from '@/utils/chart';
+
+const option = ref({
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: { type: 'line' },
+ },
+ grid: {
+ top: 0,
+ left: '0',
+ right: '0',
+ bottom: '0',
+ containLabel: false,
+ },
+ xAxis: { show: false, type: 'value' },
+ yAxis: { show: false, type: 'category' },
+ series: [
+ {
+ name: 'Direct',
+ type: 'bar',
+ stack: 'total',
+ label: { show: false },
+ emphasis: {
+ focus: 'series',
+ },
+ itemStyle: {
+ borderRadius: [10],
+ color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
+ { offset: 0, color: '#17EAFE' },
+ { offset: 1, color: '#009CD7' },
+ ]),
+ },
+ barWidth: 20,
+ data: [320],
+ },
+ {
+ type: 'bar',
+ stack: 'total',
+ label: { show: false },
+ itemStyle: {
+ borderRadius: [10],
+ color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
+ { offset: 0, color: '#00FFBC' },
+ { offset: 1, color: '#09ADA7' },
+ ]),
+ },
+ barWidth: 20,
+ emphasis: {
+ focus: 'series',
+ },
+ data: [120],
+ },
+ ],
+});
+
+/** 绘制图表 */
+export const renderLeftHeaderEcharts: any = (
+ myChart: Ref,
+ element: Ref
+) => {
+ myChart.value = echarts.init(element.value, null, {
+ renderer: 'canvas',
+ devicePixelRatio: window.devicePixelRatio,
+ });
+
+ myChart.value!.setOption(option.value!);
+
+ debounceChart(myChart.value);
+};
+
+/** 更新图标数据 */
+const updateChart = (myChart: Ref, props: any) => {
+ const series = myChart.value.getOption().series;
+ series[0].data[0] = props.dataLeft;
+ series[1].data[0] = props.dataRight;
+
+ myChart.value?.setOption({ series });
+};
+
+const LeftHeaderChart = defineComponent({
+ name: 'LeftHeaderChart',
+ props: { dataLeft: { type: Number }, dataRight: { type: Number } },
+ setup(props) {
+ const myChartRef = ref();
+ const chartRef = ref();
+
+ onMounted(() => {
+ renderLeftHeaderEcharts(myChartRef, chartRef);
+
+ watch(
+ () => [props.dataLeft, () => props.dataRight],
+ () => {
+ updateChart(myChartRef, props);
+ },
+ { immediate: true }
+ );
+ });
+
+ return () => ;
+ },
+});
+
+export default LeftHeaderChart;
diff --git a/src/views/community/components/community-content.vue b/src/views/community/components/community-content.vue
index 3be69bf..a4101be 100644
--- a/src/views/community/components/community-content.vue
+++ b/src/views/community/components/community-content.vue
@@ -1,17 +1,35 @@
@@ -19,11 +37,7 @@ onMounted(() => {