重构为js
This commit is contained in:
@@ -1,31 +1,8 @@
|
||||
<script lang="ts" setup>
|
||||
<script setup>
|
||||
import { computed, ref } from "vue";
|
||||
import type { EChartsOption } from "echarts";
|
||||
import Chart from "@/components/chart/index.vue";
|
||||
|
||||
type AlarmStatus = "待研判" | "待处理" | "处置完成" | "误判";
|
||||
type ProjectName = "西江隧道" | "青云隧道" | "南山隧道";
|
||||
type DistributionRange = "近一周" | "近一个月" | "近三个月";
|
||||
|
||||
interface AlarmReportRecord {
|
||||
id: string;
|
||||
type: string;
|
||||
robot: string;
|
||||
project: ProjectName;
|
||||
status: AlarmStatus;
|
||||
time: string;
|
||||
}
|
||||
|
||||
interface TrendRecord {
|
||||
date: string;
|
||||
project: ProjectName;
|
||||
total: number;
|
||||
closed: number;
|
||||
}
|
||||
|
||||
const distributionRange = ref<DistributionRange>("近一周");
|
||||
|
||||
const reportData: AlarmReportRecord[] = [
|
||||
const distributionRange = ref("近一周");
|
||||
const reportData = [
|
||||
{ id: "AL-001", type: "线缆破损", robot: "巡检机器人 R1", project: "西江隧道", status: "待研判", time: "2026-06-23 10:24:18" },
|
||||
{ id: "AL-002", type: "局部高温", robot: "巡检机器人 Q1", project: "青云隧道", status: "待处理", time: "2026-06-23 10:18:42" },
|
||||
{ id: "AL-003", type: "墙体裂缝", robot: "巡检机器人 N3", project: "南山隧道", status: "处置完成", time: "2026-06-23 09:56:11" },
|
||||
@@ -44,10 +21,9 @@ const reportData: AlarmReportRecord[] = [
|
||||
{ id: "AL-016", type: "局部高温", robot: "巡检机器人 N4", project: "南山隧道", status: "处置完成", time: "2026-05-19 15:07:18" },
|
||||
{ id: "AL-017", type: "线缆破损", robot: "巡检机器人 R1", project: "西江隧道", status: "待处理", time: "2026-05-06 08:11:52" },
|
||||
{ id: "AL-018", type: "墙体裂缝", robot: "巡检机器人 Q2", project: "青云隧道", status: "误判", time: "2026-04-23 14:54:06" },
|
||||
{ id: "AL-019", type: "水渍渗漏", robot: "巡检机器人 N1", project: "南山隧道", status: "处置完成", time: "2026-04-12 10:03:16" },
|
||||
{ id: "AL-019", type: "水渍渗漏", robot: "巡检机器人 N1", project: "南山隧道", status: "处置完成", time: "2026-04-12 10:03:16" }
|
||||
];
|
||||
|
||||
const trendData: TrendRecord[] = [
|
||||
const trendData = [
|
||||
{ date: "06-09", project: "西江隧道", total: 1, closed: 1 },
|
||||
{ date: "06-09", project: "青云隧道", total: 1, closed: 0 },
|
||||
{ date: "06-09", project: "南山隧道", total: 1, closed: 1 },
|
||||
@@ -92,53 +68,48 @@ const trendData: TrendRecord[] = [
|
||||
{ date: "06-22", project: "南山隧道", total: 4, closed: 3 },
|
||||
{ date: "06-23", project: "西江隧道", total: 4, closed: 3 },
|
||||
{ date: "06-23", project: "青云隧道", total: 3, closed: 2 },
|
||||
{ date: "06-23", project: "南山隧道", total: 4, closed: 3 },
|
||||
{ date: "06-23", project: "南山隧道", total: 4, closed: 3 }
|
||||
];
|
||||
|
||||
const trendSeries = computed(() => {
|
||||
const grouped = trendData.reduce<Record<string, { total: number; closed: number }>>(
|
||||
const grouped = trendData.reduce(
|
||||
(accumulator, item) => {
|
||||
if (!accumulator[item.date]) {
|
||||
accumulator[item.date] = { total: 0, closed: 0 };
|
||||
}
|
||||
|
||||
accumulator[item.date].total += item.total;
|
||||
accumulator[item.date].closed += item.closed;
|
||||
return accumulator;
|
||||
},
|
||||
{},
|
||||
{}
|
||||
);
|
||||
|
||||
return Object.entries(grouped).map(([date, value]) => ({
|
||||
date,
|
||||
total: value.total,
|
||||
closed: value.closed,
|
||||
closed: value.closed
|
||||
}));
|
||||
});
|
||||
|
||||
const trendOption = computed<EChartsOption>(() => {
|
||||
const trendOption = computed(() => {
|
||||
const dates = trendSeries.value.map((item) => item.date);
|
||||
const totalValues = trendSeries.value.map((item) => item.total);
|
||||
const closedValues = trendSeries.value.map((item) => item.closed);
|
||||
|
||||
return {
|
||||
grid: {
|
||||
left: 24,
|
||||
right: 16,
|
||||
top: 24,
|
||||
bottom: 28,
|
||||
containLabel: true,
|
||||
containLabel: true
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
backgroundColor: "rgba(6, 20, 42, 0.92)",
|
||||
borderColor: "rgba(96, 208, 255, 0.24)",
|
||||
textStyle: {
|
||||
color: "#eefcff",
|
||||
},
|
||||
color: "#eefcff"
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
show: false,
|
||||
show: false
|
||||
},
|
||||
xAxis: {
|
||||
type: "category",
|
||||
@@ -146,35 +117,35 @@ const trendOption = computed<EChartsOption>(() => {
|
||||
data: dates,
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: "rgba(96, 188, 242, 0.2)",
|
||||
},
|
||||
color: "rgba(96, 188, 242, 0.2)"
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
color: "rgba(181, 230, 249, 0.74)",
|
||||
fontSize: 11,
|
||||
fontSize: 11
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
show: false
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: "value",
|
||||
splitNumber: 5,
|
||||
axisLine: {
|
||||
show: false,
|
||||
show: false
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
show: false
|
||||
},
|
||||
axisLabel: {
|
||||
color: "rgba(181, 230, 249, 0.62)",
|
||||
fontSize: 11,
|
||||
fontSize: 11
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: "rgba(97, 189, 242, 0.12)",
|
||||
},
|
||||
},
|
||||
color: "rgba(97, 189, 242, 0.12)"
|
||||
}
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
@@ -186,16 +157,16 @@ const trendOption = computed<EChartsOption>(() => {
|
||||
data: totalValues,
|
||||
lineStyle: {
|
||||
width: 3,
|
||||
color: "#74ecff",
|
||||
color: "#74ecff"
|
||||
},
|
||||
itemStyle: {
|
||||
color: "#74ecff",
|
||||
borderColor: "#081f3e",
|
||||
borderWidth: 2,
|
||||
borderWidth: 2
|
||||
},
|
||||
areaStyle: {
|
||||
color: "rgba(116, 236, 255, 0.12)",
|
||||
},
|
||||
color: "rgba(116, 236, 255, 0.12)"
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "闭环告警",
|
||||
@@ -206,48 +177,44 @@ const trendOption = computed<EChartsOption>(() => {
|
||||
data: closedValues,
|
||||
lineStyle: {
|
||||
width: 3,
|
||||
color: "#62e0a8",
|
||||
color: "#62e0a8"
|
||||
},
|
||||
itemStyle: {
|
||||
color: "#62e0a8",
|
||||
borderColor: "#081f3e",
|
||||
borderWidth: 2,
|
||||
borderWidth: 2
|
||||
},
|
||||
areaStyle: {
|
||||
color: "rgba(98, 224, 168, 0.08)",
|
||||
},
|
||||
},
|
||||
],
|
||||
color: "rgba(98, 224, 168, 0.08)"
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
const typeStats = computed(() => {
|
||||
const statsMap = new Map<string, number>();
|
||||
const statsMap = /* @__PURE__ */ new Map();
|
||||
reportData.forEach((item) => {
|
||||
statsMap.set(item.type, (statsMap.get(item.type) ?? 0) + 1);
|
||||
});
|
||||
|
||||
return Array.from(statsMap.entries()).map(([label, value]) => ({
|
||||
label,
|
||||
value,
|
||||
value
|
||||
}));
|
||||
});
|
||||
|
||||
const typeRadarOption = computed<EChartsOption>(() => {
|
||||
const typeRadarOption = computed(() => {
|
||||
const maxValue = Math.max(...typeStats.value.map((item) => item.value), 1);
|
||||
const indicators = typeStats.value.map((item) => ({
|
||||
name: item.label,
|
||||
max: maxValue,
|
||||
max: maxValue
|
||||
}));
|
||||
|
||||
return {
|
||||
tooltip: {
|
||||
trigger: "item",
|
||||
backgroundColor: "rgba(6, 20, 42, 0.92)",
|
||||
borderColor: "rgba(96, 208, 255, 0.24)",
|
||||
textStyle: {
|
||||
color: "#eefcff",
|
||||
},
|
||||
color: "#eefcff"
|
||||
}
|
||||
},
|
||||
radar: {
|
||||
radius: "68%",
|
||||
@@ -256,23 +223,23 @@ const typeRadarOption = computed<EChartsOption>(() => {
|
||||
splitNumber: 4,
|
||||
axisName: {
|
||||
color: "#dff7ff",
|
||||
fontSize: 12,
|
||||
fontSize: 12
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: "rgba(97, 189, 242, 0.22)",
|
||||
},
|
||||
color: "rgba(97, 189, 242, 0.22)"
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: "rgba(97, 189, 242, 0.16)",
|
||||
},
|
||||
color: "rgba(97, 189, 242, 0.16)"
|
||||
}
|
||||
},
|
||||
splitArea: {
|
||||
areaStyle: {
|
||||
color: ["rgba(16, 52, 94, 0.10)", "rgba(16, 52, 94, 0.05)"],
|
||||
},
|
||||
},
|
||||
color: ["rgba(16, 52, 94, 0.10)", "rgba(16, 52, 94, 0.05)"]
|
||||
}
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
@@ -282,50 +249,47 @@ const typeRadarOption = computed<EChartsOption>(() => {
|
||||
value: typeStats.value.map((item) => item.value),
|
||||
name: "告警类型分布",
|
||||
areaStyle: {
|
||||
color: "rgba(73, 207, 255, 0.20)",
|
||||
color: "rgba(73, 207, 255, 0.20)"
|
||||
},
|
||||
lineStyle: {
|
||||
color: "#61dcff",
|
||||
width: 2.5,
|
||||
width: 2.5
|
||||
},
|
||||
itemStyle: {
|
||||
color: "#8ff3ff",
|
||||
borderColor: "#07203e",
|
||||
borderWidth: 2,
|
||||
borderWidth: 2
|
||||
},
|
||||
symbolSize: 8,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
symbolSize: 8
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
const statusStats = computed(() => {
|
||||
const order: AlarmStatus[] = ["待研判", "待处理", "处置完成", "误判"];
|
||||
const order = ["待研判", "待处理", "处置完成", "误判"];
|
||||
const total = reportData.length || 1;
|
||||
|
||||
return order.map((status) => {
|
||||
const value = reportData.filter((item) => item.status === status).length;
|
||||
return {
|
||||
label: status,
|
||||
value,
|
||||
percent: `${Math.round((value / total) * 100)}%`,
|
||||
percent: `${Math.round(value / total * 100)}%`
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
const statusPieOption = computed<EChartsOption>(() => ({
|
||||
const statusPieOption = computed(() => ({
|
||||
tooltip: {
|
||||
trigger: "item",
|
||||
backgroundColor: "rgba(6, 20, 42, 0.92)",
|
||||
borderColor: "rgba(96, 208, 255, 0.24)",
|
||||
textStyle: {
|
||||
color: "#eefcff",
|
||||
},
|
||||
color: "#eefcff"
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
show: false,
|
||||
show: false
|
||||
},
|
||||
series: [
|
||||
{
|
||||
@@ -335,63 +299,50 @@ const statusPieOption = computed<EChartsOption>(() => ({
|
||||
avoidLabelOverlap: false,
|
||||
itemStyle: {
|
||||
borderColor: "#081f3e",
|
||||
borderWidth: 3,
|
||||
borderWidth: 3
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
color: "#dff7ff",
|
||||
formatter: "{b}\n{d}%",
|
||||
fontSize: 12,
|
||||
fontSize: 12
|
||||
},
|
||||
labelLine: {
|
||||
lineStyle: {
|
||||
color: "rgba(181, 230, 249, 0.52)",
|
||||
},
|
||||
color: "rgba(181, 230, 249, 0.52)"
|
||||
}
|
||||
},
|
||||
data: statusStats.value.map((item) => ({
|
||||
name: item.label,
|
||||
value: item.value,
|
||||
itemStyle: {
|
||||
color:
|
||||
item.label === "待研判"
|
||||
? "#ffd66e"
|
||||
: item.label === "待处理"
|
||||
? "#ff8b78"
|
||||
: item.label === "处置完成"
|
||||
? "#62e0a8"
|
||||
: "#8ea7ff",
|
||||
},
|
||||
})),
|
||||
},
|
||||
],
|
||||
color: item.label === "待研判" ? "#ffd66e" : item.label === "待处理" ? "#ff8b78" : item.label === "处置完成" ? "#62e0a8" : "#8ea7ff"
|
||||
}
|
||||
}))
|
||||
}
|
||||
]
|
||||
}));
|
||||
|
||||
const projectDistribution = computed(() => {
|
||||
const now = new Date("2026-06-23T23:59:59");
|
||||
const rangeDaysMap: Record<DistributionRange, number> = {
|
||||
const now = /* @__PURE__ */ new Date("2026-06-23T23:59:59");
|
||||
const rangeDaysMap = {
|
||||
近一周: 7,
|
||||
近一个月: 30,
|
||||
近三个月: 90,
|
||||
近三个月: 90
|
||||
};
|
||||
const threshold = new Date(
|
||||
now.getTime() - rangeDaysMap[distributionRange.value] * 24 * 60 * 60 * 1000,
|
||||
now.getTime() - rangeDaysMap[distributionRange.value] * 24 * 60 * 60 * 1e3
|
||||
);
|
||||
const data = reportData.filter((item) => new Date(item.time.replace(" ", "T")) >= threshold);
|
||||
const statsMap = new Map<string, number>();
|
||||
|
||||
const statsMap = /* @__PURE__ */ new Map();
|
||||
data.forEach((item) => {
|
||||
statsMap.set(item.project, (statsMap.get(item.project) ?? 0) + 1);
|
||||
});
|
||||
|
||||
const maxValue = Math.max(...statsMap.values(), 1);
|
||||
|
||||
return Array.from(statsMap.entries())
|
||||
.map(([label, value]) => ({
|
||||
label,
|
||||
value,
|
||||
width: `${(value / maxValue) * 100}%`,
|
||||
}))
|
||||
.sort((a, b) => b.value - a.value);
|
||||
return Array.from(statsMap.entries()).map(([label, value]) => ({
|
||||
label,
|
||||
value,
|
||||
width: `${value / maxValue * 100}%`
|
||||
})).sort((a, b) => b.value - a.value);
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -468,7 +419,7 @@ const projectDistribution = computed(() => {
|
||||
:key="range"
|
||||
:class="['report-filter-tab', { active: distributionRange === range }]"
|
||||
type="button"
|
||||
@click="distributionRange = range as DistributionRange"
|
||||
@click="distributionRange = range"
|
||||
>
|
||||
{{ range }}
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user