feat:危险房子圆环更新接口以及请求
This commit is contained in:
parent
5a15829710
commit
98c219c17b
@ -45,7 +45,7 @@ const option = {
|
|||||||
left: '60%', // 默认更靠左一点,避免截断
|
left: '60%', // 默认更靠左一点,避免截断
|
||||||
top: 'center',
|
top: 'center',
|
||||||
icon: 'rect',
|
icon: 'rect',
|
||||||
showEmpty:false,
|
showEmpty: false,
|
||||||
// itemWidth: 10,
|
// itemWidth: 10,
|
||||||
itemHeight: 8,
|
itemHeight: 8,
|
||||||
itemGap: 5,
|
itemGap: 5,
|
||||||
@ -69,8 +69,9 @@ const option = {
|
|||||||
center: ['30%', '48%'],
|
center: ['30%', '48%'],
|
||||||
silent: true,
|
silent: true,
|
||||||
z: 1,
|
z: 1,
|
||||||
data: [{ value: 1, name: '', itemStyle: {
|
data: [{
|
||||||
color: {
|
value: 1, name: '', itemStyle: {
|
||||||
|
color: {
|
||||||
type: 'linear',
|
type: 'linear',
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
@ -82,7 +83,8 @@ const option = {
|
|||||||
{ offset: 1, color: 'rgba(200, 200, 200, 0.01)' },
|
{ offset: 1, color: 'rgba(200, 200, 200, 0.01)' },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
} }],
|
}
|
||||||
|
}],
|
||||||
label: { show: false },
|
label: { show: false },
|
||||||
labelLine: { show: false }
|
labelLine: { show: false }
|
||||||
},
|
},
|
||||||
@ -160,8 +162,7 @@ const option = {
|
|||||||
show: false,
|
show: false,
|
||||||
},
|
},
|
||||||
itemStyle: { shadowBlur: 12, shadowColor: 'rgba(0, 0, 0, 0.35)' }
|
itemStyle: { shadowBlur: 12, shadowColor: 'rgba(0, 0, 0, 0.35)' }
|
||||||
},
|
}
|
||||||
data: dataJson.source
|
|
||||||
},
|
},
|
||||||
// 内部渐变装饰环(在空洞边缘,提升质感)
|
// 内部渐变装饰环(在空洞边缘,提升质感)
|
||||||
{
|
{
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="go-border-box">
|
<div class="go-border-box">
|
||||||
<img src="./assets/title.svg" class="svg" />
|
<img src="./assets/title.svg" class="svg" />
|
||||||
<div class="header-title">报警统计</div>
|
<div class="header-title">报警统计</div>
|
||||||
<v-chart ref="vChartRef" autoresize :init-options="initOptions" :theme="themeColor" :option="option"></v-chart>
|
<v-chart ref="vChartRef" autoresize :init-options="initOptions" :theme="themeColor" :option="option"></v-chart>
|
||||||
<!-- 使用新的下拉选择器组件 -->
|
<!-- 使用新的下拉选择器组件 -->
|
||||||
<CustomSelect
|
<CustomSelect :options="option.dateTime.dataset" :selectedValue="option.dateTime.selectValue"
|
||||||
:options="option.dateTime.dataset"
|
@change="handleSelectChange" />
|
||||||
:selectedValue="option.dateTime.selectValue"
|
|
||||||
@change="handleSelectChange"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@ -27,6 +24,7 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore
|
|||||||
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent, GraphicComponent } from 'echarts/components'
|
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent, GraphicComponent } from 'echarts/components'
|
||||||
import CustomSelect from './select.vue'
|
import CustomSelect from './select.vue'
|
||||||
import dataJson from './data.json'
|
import dataJson from './data.json'
|
||||||
|
import axiosInstance from '@/api/axios';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
themeSetting: {
|
themeSetting: {
|
||||||
@ -54,7 +52,7 @@ const option = computed(() => {
|
|||||||
function calculateTotal(data: any) {
|
function calculateTotal(data: any) {
|
||||||
if (!data || !data.source) return 0
|
if (!data || !data.source) return 0
|
||||||
return data.source.reduce((total: number, item: any) => {
|
return data.source.reduce((total: number, item: any) => {
|
||||||
return total + (item[data.dimensions[1]] || 0)
|
return total + (item.value || 0)
|
||||||
}, 0)
|
}, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,18 +63,20 @@ function calculatePercentage(value: number, total: number) {
|
|||||||
const updateChartData = (newData: any) => {
|
const updateChartData = (newData: any) => {
|
||||||
if (!newData) return
|
if (!newData) return
|
||||||
|
|
||||||
|
// 确保数据被正确设置到图表配置中
|
||||||
|
props.chartConfig.option.dataset = newData
|
||||||
|
|
||||||
const total = calculateTotal(newData)
|
const total = calculateTotal(newData)
|
||||||
if (props.chartConfig.option.graphic?.[0]) {
|
if (props.chartConfig.option.graphic?.[0]) {
|
||||||
props.chartConfig.option.graphic[0].style.text = total.toString()
|
props.chartConfig.option.graphic[0].style.text = total.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 统一显示为 “名称 百分比”
|
// 统一显示为 "名称 百分比"
|
||||||
props.chartConfig.option.legend.formatter = (name: string) => {
|
props.chartConfig.option.legend.formatter = (name: string) => {
|
||||||
const item = newData.source.find((it: any) => it[newData.dimensions[0]] === name)
|
const item = newData.source.find((it: any) => it.name === name)
|
||||||
if (!item) return null
|
if (!item) return name
|
||||||
const val = item[newData.dimensions[1]] ?? 0
|
const val = item.value ?? 0
|
||||||
let p = calculatePercentage(val, total)
|
let p = calculatePercentage(val, total)
|
||||||
// return `{row|${name} ${p}%}`
|
|
||||||
if(Number(p)<10){
|
if(Number(p)<10){
|
||||||
p=' '+p
|
p=' '+p
|
||||||
}
|
}
|
||||||
@ -143,79 +143,176 @@ const updateChartData = (newData: any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const totalValue=newData.source.reduce((total: number, item: any) => {
|
const totalValue = newData.source.reduce((total: number, item: any) => {
|
||||||
return total + (item.value || 0)
|
return total + (item.value || 0)
|
||||||
}, 0)
|
}, 0)
|
||||||
props.chartConfig.option.series[props.chartConfig.option.series.length-1].label.formatter=`{a|${totalValue}}\n\n{b|总数}`
|
props.chartConfig.option.series[props.chartConfig.option.series.length-1].label.formatter = `{a|${totalValue}}\n\n{b|总数}`
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.chartConfig.option.dataset,
|
() => props.chartConfig.option.dataset,
|
||||||
newData => {
|
newData => {
|
||||||
if (newData) {
|
if (newData) {
|
||||||
props.chartConfig.option.dataset = newData
|
|
||||||
updateChartData(newData)
|
updateChartData(newData)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ deep: false, immediate: true }
|
{ deep: true, immediate: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
const { vChartRef } = useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
|
const { vChartRef } = useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
|
||||||
props.chartConfig.option.dataset = newData
|
|
||||||
updateChartData(newData)
|
updateChartData(newData)
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
updateChartData(props.chartConfig.option.dataset)
|
// 初始化时立即获取数据
|
||||||
})
|
const timeRange = generateTimeRange(props.chartConfig.option.dateTime.selectValue);
|
||||||
|
const fetchedData = await fetchAlarmData(timeRange);
|
||||||
|
if (fetchedData) {
|
||||||
|
updateChartData(fetchedData);
|
||||||
|
} else {
|
||||||
|
// 如果获取失败,使用默认数据
|
||||||
|
updateChartData(props.chartConfig.option.dataset);
|
||||||
|
}
|
||||||
|
});
|
||||||
// 处理下拉选择器变化
|
// 处理下拉选择器变化
|
||||||
const handleSelectChange = (value: any) => {
|
function formatDateTime(date: Date): string {
|
||||||
props.chartConfig.option.dateTime.selectValue = value
|
const year = date.getFullYear();
|
||||||
|
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
||||||
|
const day = date.getDate().toString().padStart(2, '0');
|
||||||
|
const hours = date.getHours().toString().padStart(2, '0');
|
||||||
|
const minutes = date.getMinutes().toString().padStart(2, '0');
|
||||||
|
const seconds = date.getSeconds().toString().padStart(2, '0');
|
||||||
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||||
}
|
}
|
||||||
|
function generateTimeRange(period: string): { startTime: string; endTime: string } {
|
||||||
|
const now = new Date();
|
||||||
|
let startTime: Date;
|
||||||
|
let endTime: Date;
|
||||||
|
endTime = new Date(now);
|
||||||
|
endTime.setDate(endTime.getDate() + 1);
|
||||||
|
endTime.setHours(0, 0, 0, 0);
|
||||||
|
switch (period) {
|
||||||
|
case 'day':
|
||||||
|
startTime = new Date(now);
|
||||||
|
startTime.setHours(0, 0, 0, 0);
|
||||||
|
break;
|
||||||
|
case 'week':
|
||||||
|
startTime = new Date(now);
|
||||||
|
startTime.setDate(startTime.getDate() - 7);
|
||||||
|
startTime.setHours(0, 0, 0, 0);
|
||||||
|
break;
|
||||||
|
case 'month':
|
||||||
|
startTime = new Date(now.getFullYear(), now.getMonth(), 1);
|
||||||
|
startTime.setHours(0, 0, 0, 0);
|
||||||
|
break;
|
||||||
|
case 'quarter':
|
||||||
|
const currentMonth = now.getMonth();
|
||||||
|
const quarterStartMonth = Math.floor(currentMonth / 3) * 3;
|
||||||
|
startTime = new Date(now.getFullYear(), quarterStartMonth, 1);
|
||||||
|
startTime.setHours(0, 0, 0, 0);
|
||||||
|
break;
|
||||||
|
case 'year':
|
||||||
|
startTime = new Date(now.getFullYear(), 0, 1);
|
||||||
|
startTime.setHours(0, 0, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
startTime = new Date(now);
|
||||||
|
startTime.setHours(0, 0, 0, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
startTime: formatDateTime(startTime),
|
||||||
|
endTime: formatDateTime(endTime),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
async function fetchAlarmData({ startTime, endTime }: { startTime: string; endTime: string }) {
|
||||||
|
try {
|
||||||
|
const res = await axiosInstance({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/getAlarmdataRecord',
|
||||||
|
params: { startTime, endTime },
|
||||||
|
responseType: 'json',
|
||||||
|
});
|
||||||
|
if (Array.isArray(res)) {
|
||||||
|
// 转换为图表需要的数据结构
|
||||||
|
return {
|
||||||
|
dimensions: ['name', 'value'],
|
||||||
|
source: res.map((item: any) => ({
|
||||||
|
name: item.alarmLevel,
|
||||||
|
value: item.alarmNun
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
console.warn('API returned unexpected data structure:', res);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching alarm data:', error);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function dataHandle(newData: any) {
|
||||||
|
if (!newData) {
|
||||||
|
props.chartConfig.option.dataset = { dimensions: ['name', 'value'], source: [] };
|
||||||
|
updateChartData(props.chartConfig.option.dataset);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updateChartData(newData);
|
||||||
|
}
|
||||||
|
const handleSelectChange = async (value: string) => {
|
||||||
|
props.chartConfig.option.dateTime.selectValue = value;
|
||||||
|
const { startTime, endTime } = generateTimeRange(value);
|
||||||
|
const fetchedData = await fetchAlarmData({ startTime, endTime });
|
||||||
|
await dataHandle(fetchedData);
|
||||||
|
};
|
||||||
|
onMounted(async () => {
|
||||||
|
const timeRange = generateTimeRange(props.chartConfig.option.dateTime.selectValue);
|
||||||
|
const fetchedData = await fetchAlarmData(timeRange);
|
||||||
|
await dataHandle(fetchedData);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@include go(border-box) {
|
@include go(border-box) {
|
||||||
position: relative;
|
position: relative;
|
||||||
border-radius: 5px;
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
padding: 0;
|
|
||||||
// 不渐变
|
|
||||||
// background-color: #0E121B;
|
|
||||||
// 渐变
|
|
||||||
background: linear-gradient(to top,
|
|
||||||
rgba(14, 18, 27, 1) 0%,
|
|
||||||
rgba(14, 18, 27, 0.6) 100%);
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
padding: 2px;
|
overflow: hidden;
|
||||||
/* 边框宽度 */
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0;
|
||||||
|
// 不渐变
|
||||||
|
// background-color: #0E121B;
|
||||||
|
// 渐变
|
||||||
background: linear-gradient(to top,
|
background: linear-gradient(to top,
|
||||||
rgba(128, 128, 128, 0.3),
|
rgba(14, 18, 27, 1) 0%,
|
||||||
rgba(128, 128, 128, 0));
|
rgba(14, 18, 27, 0.6) 100%);
|
||||||
-webkit-mask:
|
|
||||||
linear-gradient(#fff, #fff) content-box,
|
&::before {
|
||||||
linear-gradient(#fff, #fff);
|
content: '';
|
||||||
-webkit-mask-composite: xor;
|
position: absolute;
|
||||||
mask-composite: exclude;
|
top: 0;
|
||||||
pointer-events: none;
|
left: 0;
|
||||||
}
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 2px;
|
||||||
|
/* 边框宽度 */
|
||||||
|
background: linear-gradient(to top,
|
||||||
|
rgba(128, 128, 128, 0.3),
|
||||||
|
rgba(128, 128, 128, 0));
|
||||||
|
-webkit-mask:
|
||||||
|
linear-gradient(#fff, #fff) content-box,
|
||||||
|
linear-gradient(#fff, #fff);
|
||||||
|
-webkit-mask-composite: xor;
|
||||||
|
mask-composite: exclude;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-title{
|
.header-title {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
height: 45px;
|
height: 45px;
|
||||||
@ -231,7 +328,7 @@ const handleSelectChange = (value: any) => {
|
|||||||
|
|
||||||
|
|
||||||
.svg {
|
.svg {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 45px;
|
height: 45px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
Loading…
Reference in New Issue
Block a user