747 lines
24 KiB
TypeScript
747 lines
24 KiB
TypeScript
"use client";
|
|
|
|
import React, { useEffect, useMemo, useRef } from "react";
|
|
import ReactECharts from "echarts-for-react";
|
|
import {
|
|
Box,
|
|
Button,
|
|
Dialog,
|
|
GlobalStyles,
|
|
IconButton,
|
|
Stack,
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableContainer,
|
|
TableHead,
|
|
TableRow,
|
|
Typography,
|
|
} from "@mui/material";
|
|
import {
|
|
Close,
|
|
PrintOutlined,
|
|
WaterDropOutlined,
|
|
} from "@mui/icons-material";
|
|
import { PredictionResult } from "./types";
|
|
import { buildHealthRiskReportData } from "./healthRiskReport";
|
|
|
|
interface HealthRiskReportProps {
|
|
open: boolean;
|
|
onClose: () => void;
|
|
predictionResults: PredictionResult[];
|
|
currentYear: number;
|
|
analysisQueryTime: string | null;
|
|
networkName: string;
|
|
generatedAt: Date;
|
|
}
|
|
|
|
const REPORT_BLUE = "#0b4f87";
|
|
const REPORT_INK = "#172435";
|
|
const REPORT_MUTED = "#5f6f80";
|
|
const REPORT_LINE = "#d8e0e8";
|
|
|
|
const reportFontFamily =
|
|
'-apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif';
|
|
|
|
const formatDateTime = (value: Date | string | null) => {
|
|
if (!value) return "未记录";
|
|
const date = value instanceof Date ? value : new Date(value);
|
|
if (Number.isNaN(date.getTime())) return "未记录";
|
|
return new Intl.DateTimeFormat("zh-CN", {
|
|
year: "numeric",
|
|
month: "2-digit",
|
|
day: "2-digit",
|
|
hour: "2-digit",
|
|
minute: "2-digit",
|
|
second: "2-digit",
|
|
hour12: false,
|
|
}).format(date);
|
|
};
|
|
|
|
const formatPercent = (value: number | null, fractionDigits = 1) =>
|
|
value === null ? "无有效数据" : `${(value * 100).toFixed(fractionDigits)}%`;
|
|
|
|
const SectionTitle = ({ children }: { children: React.ReactNode }) => (
|
|
<Stack
|
|
direction="row"
|
|
alignItems="center"
|
|
spacing={1.25}
|
|
sx={{ mb: 1.5 }}
|
|
>
|
|
<Box
|
|
aria-hidden="true"
|
|
sx={{ width: 24, height: 3, bgcolor: REPORT_BLUE, flexShrink: 0 }}
|
|
/>
|
|
<Typography
|
|
component="h2"
|
|
sx={{
|
|
color: REPORT_INK,
|
|
fontSize: 17,
|
|
fontWeight: 700,
|
|
lineHeight: 1.4,
|
|
}}
|
|
>
|
|
{children}
|
|
</Typography>
|
|
</Stack>
|
|
);
|
|
|
|
const HealthRiskReport: React.FC<HealthRiskReportProps> = ({
|
|
open,
|
|
onClose,
|
|
predictionResults,
|
|
currentYear,
|
|
analysisQueryTime,
|
|
networkName,
|
|
generatedAt,
|
|
}) => {
|
|
const printStateRef = useRef<{ title: string } | null>(null);
|
|
const reportData = useMemo(
|
|
() => buildHealthRiskReportData(predictionResults, currentYear),
|
|
[currentYear, predictionResults],
|
|
);
|
|
|
|
useEffect(
|
|
() => () => {
|
|
if (printStateRef.current) {
|
|
document.title = printStateRef.current.title;
|
|
document.body.classList.remove("health-risk-report-printing");
|
|
}
|
|
},
|
|
[],
|
|
);
|
|
|
|
const restoreAfterPrint = () => {
|
|
if (!printStateRef.current) return;
|
|
document.title = printStateRef.current.title;
|
|
printStateRef.current = null;
|
|
document.body.classList.remove("health-risk-report-printing");
|
|
};
|
|
|
|
const handlePrint = () => {
|
|
if (printStateRef.current) return;
|
|
printStateRef.current = { title: document.title };
|
|
document.title = `管网健康风险体检报告-${networkName || "未命名管网"}-${new Intl.DateTimeFormat(
|
|
"zh-CN",
|
|
{ year: "numeric", month: "2-digit", day: "2-digit" },
|
|
)
|
|
.format(generatedAt)
|
|
.replaceAll("/", "-")}`;
|
|
document.body.classList.add("health-risk-report-printing");
|
|
window.addEventListener("afterprint", restoreAfterPrint, { once: true });
|
|
window.print();
|
|
};
|
|
|
|
const distributionOption = {
|
|
animation: false,
|
|
grid: { top: 4, right: 38, bottom: 28, left: 148 },
|
|
xAxis: {
|
|
type: "value",
|
|
name: "管段数",
|
|
minInterval: 1,
|
|
axisLine: { lineStyle: { color: "#8b99a8" } },
|
|
axisLabel: { color: REPORT_MUTED, fontSize: 10 },
|
|
splitLine: { lineStyle: { color: "#e7edf2" } },
|
|
nameTextStyle: { color: REPORT_MUTED, fontSize: 10 },
|
|
},
|
|
yAxis: {
|
|
type: "category",
|
|
inverse: true,
|
|
data: reportData.distribution.map((item) => item.label),
|
|
axisLine: { show: false },
|
|
axisTick: { show: false },
|
|
axisLabel: { color: REPORT_INK, fontSize: 10 },
|
|
},
|
|
tooltip: { show: false },
|
|
series: [
|
|
{
|
|
type: "bar",
|
|
barMaxWidth: 14,
|
|
data: reportData.distribution.map((item) => ({
|
|
value: item.count,
|
|
itemStyle: { color: item.color },
|
|
})),
|
|
label: {
|
|
show: true,
|
|
position: "right",
|
|
color: REPORT_INK,
|
|
fontSize: 10,
|
|
},
|
|
},
|
|
],
|
|
};
|
|
|
|
const trendOption = {
|
|
animation: false,
|
|
grid: { top: 24, right: 24, bottom: 38, left: 48 },
|
|
xAxis: {
|
|
type: "category",
|
|
name: "预测年份",
|
|
boundaryGap: false,
|
|
data: reportData.trend.map((item) => item.year),
|
|
axisLine: { lineStyle: { color: "#8b99a8" } },
|
|
axisLabel: {
|
|
color: REPORT_MUTED,
|
|
fontSize: 10,
|
|
interval: Math.max(0, Math.ceil(reportData.trend.length / 9) - 1),
|
|
},
|
|
nameTextStyle: { color: REPORT_MUTED, fontSize: 10 },
|
|
},
|
|
yAxis: {
|
|
type: "value",
|
|
name: "较高及以上风险管段数",
|
|
minInterval: 1,
|
|
axisLine: { show: false },
|
|
axisLabel: { color: REPORT_MUTED, fontSize: 10 },
|
|
splitLine: { lineStyle: { color: "#e7edf2" } },
|
|
nameTextStyle: { color: REPORT_MUTED, fontSize: 10 },
|
|
},
|
|
tooltip: { show: false },
|
|
series: [
|
|
{
|
|
type: "line",
|
|
smooth: true,
|
|
symbol: "none",
|
|
lineStyle: { color: "#c83d3d", width: 2.5 },
|
|
areaStyle: { color: "rgba(200, 61, 61, 0.08)" },
|
|
data: reportData.trend.map((item) => item.count),
|
|
},
|
|
],
|
|
};
|
|
|
|
const metricItems = [
|
|
{ label: "分析管段", value: reportData.totalCount.toLocaleString("zh-CN") },
|
|
{ label: "有效结果", value: reportData.validCount.toLocaleString("zh-CN") },
|
|
{
|
|
label: "平均生存概率",
|
|
value: formatPercent(reportData.averageProbability),
|
|
},
|
|
{
|
|
label: "较高及以上风险",
|
|
value: `${reportData.highRiskCount.toLocaleString("zh-CN")} 条`,
|
|
detail: formatPercent(reportData.highRiskRatio),
|
|
danger: reportData.highRiskCount > 0,
|
|
},
|
|
];
|
|
|
|
return (
|
|
<>
|
|
<GlobalStyles
|
|
styles={{
|
|
"@page": { size: "A4 portrait", margin: 0 },
|
|
"@media print": {
|
|
"html, body": {
|
|
width: "210mm",
|
|
minHeight: "297mm",
|
|
margin: 0,
|
|
padding: 0,
|
|
backgroundColor: "#fff",
|
|
},
|
|
"body.health-risk-report-printing > *:not(.health-risk-report-dialog)":
|
|
{
|
|
display: "none !important",
|
|
},
|
|
".health-risk-report-dialog": {
|
|
position: "static !important",
|
|
display: "block !important",
|
|
},
|
|
".health-risk-report-dialog .MuiBackdrop-root, .health-risk-report-actions":
|
|
{
|
|
display: "none !important",
|
|
},
|
|
".health-risk-report-dialog .MuiDialog-container": {
|
|
display: "block !important",
|
|
height: "auto !important",
|
|
},
|
|
".health-risk-report-dialog .MuiDialog-paper": {
|
|
width: "210mm !important",
|
|
maxWidth: "none !important",
|
|
minHeight: "297mm !important",
|
|
maxHeight: "none !important",
|
|
margin: "0 !important",
|
|
overflow: "visible !important",
|
|
boxShadow: "none !important",
|
|
},
|
|
".health-risk-report-preview": {
|
|
padding: "0 !important",
|
|
overflow: "visible !important",
|
|
backgroundColor: "#fff !important",
|
|
},
|
|
"#health-risk-print-root": {
|
|
width: "210mm !important",
|
|
minHeight: "297mm !important",
|
|
padding: "12mm !important",
|
|
boxShadow: "none !important",
|
|
printColorAdjust: "exact",
|
|
WebkitPrintColorAdjust: "exact",
|
|
},
|
|
".health-risk-report-section, .health-risk-report-metrics": {
|
|
breakInside: "avoid",
|
|
pageBreakInside: "avoid",
|
|
},
|
|
".health-risk-report-table-row": {
|
|
breakInside: "avoid",
|
|
pageBreakInside: "avoid",
|
|
},
|
|
},
|
|
}}
|
|
/>
|
|
<Dialog
|
|
open={open}
|
|
onClose={onClose}
|
|
maxWidth={false}
|
|
fullWidth
|
|
className="health-risk-report-dialog"
|
|
slotProps={{
|
|
paper: {
|
|
sx: {
|
|
width: "100%",
|
|
height: "100%",
|
|
maxHeight: "100%",
|
|
m: 0,
|
|
borderRadius: 0,
|
|
bgcolor: "#e8edf2",
|
|
},
|
|
},
|
|
}}
|
|
>
|
|
<Stack
|
|
className="health-risk-report-actions"
|
|
direction="row"
|
|
alignItems="center"
|
|
justifyContent="space-between"
|
|
sx={{
|
|
position: "sticky",
|
|
top: 0,
|
|
zIndex: 2,
|
|
minHeight: 64,
|
|
px: { xs: 1.5, sm: 3 },
|
|
bgcolor: "#fff",
|
|
boxShadow: "0 1px 4px rgba(23, 36, 53, 0.16)",
|
|
}}
|
|
>
|
|
<Stack direction="row" alignItems="center" spacing={1}>
|
|
<IconButton
|
|
onClick={onClose}
|
|
aria-label="关闭报告预览"
|
|
sx={{ width: 40, height: 40 }}
|
|
>
|
|
<Close />
|
|
</IconButton>
|
|
<Box>
|
|
<Typography sx={{ fontWeight: 700, color: REPORT_INK }}>
|
|
报告预览
|
|
</Typography>
|
|
<Typography variant="caption" sx={{ color: REPORT_MUTED }}>
|
|
A4 纵向,可在打印窗口另存为 PDF
|
|
</Typography>
|
|
</Box>
|
|
</Stack>
|
|
<Button
|
|
variant="contained"
|
|
startIcon={<PrintOutlined />}
|
|
onClick={handlePrint}
|
|
sx={{
|
|
minHeight: 40,
|
|
borderRadius: 1.5,
|
|
bgcolor: REPORT_BLUE,
|
|
"&:hover": { bgcolor: "#083f6d" },
|
|
"&:active": { transform: "scale(0.96)" },
|
|
}}
|
|
>
|
|
打印
|
|
</Button>
|
|
</Stack>
|
|
|
|
<Box
|
|
className="health-risk-report-preview"
|
|
sx={{
|
|
flex: 1,
|
|
overflow: "auto",
|
|
px: { xs: 0, sm: 2 },
|
|
py: { xs: 0, sm: 3 },
|
|
}}
|
|
>
|
|
<Box
|
|
id="health-risk-print-root"
|
|
lang="zh-CN"
|
|
sx={{
|
|
boxSizing: "border-box",
|
|
width: { xs: "100%", sm: "min(210mm, 100%)" },
|
|
minHeight: "297mm",
|
|
mx: "auto",
|
|
p: { xs: 2, sm: "12mm" },
|
|
bgcolor: "#fff",
|
|
color: REPORT_INK,
|
|
boxShadow: { xs: "none", sm: "0 12px 32px rgba(23,36,53,0.16)" },
|
|
fontFamily: reportFontFamily,
|
|
fontVariantNumeric: "tabular-nums",
|
|
}}
|
|
>
|
|
<Box
|
|
component="header"
|
|
sx={{
|
|
bgcolor: REPORT_BLUE,
|
|
color: "#f4f8fb",
|
|
px: { xs: 2.5, sm: 4 },
|
|
py: { xs: 2.5, sm: 3.5 },
|
|
}}
|
|
>
|
|
<Stack
|
|
direction={{ xs: "column", sm: "row" }}
|
|
justifyContent="space-between"
|
|
alignItems={{ xs: "flex-start", sm: "center" }}
|
|
spacing={2}
|
|
>
|
|
<Box>
|
|
<Stack direction="row" alignItems="center" spacing={1}>
|
|
<WaterDropOutlined aria-hidden="true" />
|
|
<Typography
|
|
lang="en"
|
|
sx={{ fontSize: 13, fontWeight: 700, letterSpacing: "0.08em" }}
|
|
>
|
|
TJWATER
|
|
</Typography>
|
|
</Stack>
|
|
<Typography
|
|
component="h1"
|
|
sx={{
|
|
mt: 1.5,
|
|
fontSize: { xs: 24, sm: 30 },
|
|
fontWeight: 700,
|
|
lineHeight: 1.25,
|
|
textWrap: "balance",
|
|
}}
|
|
>
|
|
管网健康风险体检报告
|
|
</Typography>
|
|
<Typography
|
|
sx={{
|
|
mt: 0.75,
|
|
color: "#cfe1ef",
|
|
fontSize: 13,
|
|
lineHeight: 1.7,
|
|
}}
|
|
>
|
|
Pipeline health risk assessment
|
|
</Typography>
|
|
</Box>
|
|
<Box
|
|
sx={{
|
|
minWidth: { sm: 168 },
|
|
width: { xs: "100%", sm: "auto" },
|
|
pt: { xs: 2, sm: 0 },
|
|
pl: { xs: 0, sm: 3 },
|
|
borderTop: {
|
|
xs: "1px solid rgba(224, 238, 248, 0.28)",
|
|
sm: "none",
|
|
},
|
|
borderLeft: {
|
|
xs: "none",
|
|
sm: "1px solid rgba(224, 238, 248, 0.28)",
|
|
},
|
|
}}
|
|
>
|
|
<Stack direction="row" alignItems="center" spacing={0.8}>
|
|
<Box
|
|
aria-hidden="true"
|
|
sx={{
|
|
width: 7,
|
|
height: 7,
|
|
flexShrink: 0,
|
|
borderRadius: "50%",
|
|
bgcolor:
|
|
reportData.highRiskCount > 0 ? "#ffb3a7" : "#9dd7bd",
|
|
}}
|
|
/>
|
|
<Typography sx={{ color: "#cfe1ef", fontSize: 11 }}>
|
|
本期提示
|
|
</Typography>
|
|
</Stack>
|
|
<Typography
|
|
sx={{
|
|
mt: 0.75,
|
|
fontWeight: 700,
|
|
fontSize: 20,
|
|
lineHeight: 1.35,
|
|
}}
|
|
>
|
|
{reportData.highRiskCount > 0 ? "需重点关注" : "持续监测"}
|
|
</Typography>
|
|
</Box>
|
|
</Stack>
|
|
</Box>
|
|
|
|
<Box
|
|
component="dl"
|
|
sx={{
|
|
m: 0,
|
|
display: "grid",
|
|
gridTemplateColumns: { xs: "1fr", sm: "repeat(2, 1fr)" },
|
|
borderBottom: `1px solid ${REPORT_LINE}`,
|
|
}}
|
|
>
|
|
{[
|
|
["管网项目", networkName || "未命名管网"],
|
|
["预测时点", `第 ${currentYear} 年`],
|
|
["分析数据时间", formatDateTime(analysisQueryTime)],
|
|
["报告生成时间", formatDateTime(generatedAt)],
|
|
].map(([label, value]) => (
|
|
<Box
|
|
key={label}
|
|
sx={{
|
|
display: "grid",
|
|
gridTemplateColumns: "96px 1fr",
|
|
gap: 1,
|
|
px: 2,
|
|
py: 1.25,
|
|
borderBottom: { xs: `1px solid ${REPORT_LINE}`, sm: "none" },
|
|
}}
|
|
>
|
|
<Typography
|
|
component="dt"
|
|
sx={{ color: REPORT_MUTED, fontSize: 12 }}
|
|
>
|
|
{label}
|
|
</Typography>
|
|
<Typography
|
|
component="dd"
|
|
sx={{
|
|
m: 0,
|
|
color: REPORT_INK,
|
|
fontSize: 12,
|
|
fontWeight: 600,
|
|
overflowWrap: "anywhere",
|
|
}}
|
|
>
|
|
{value}
|
|
</Typography>
|
|
</Box>
|
|
))}
|
|
</Box>
|
|
|
|
<Box
|
|
component="section"
|
|
className="health-risk-report-section"
|
|
sx={{ mt: 3 }}
|
|
>
|
|
<SectionTitle>总体结论</SectionTitle>
|
|
<Box
|
|
sx={{
|
|
bgcolor:
|
|
reportData.highRiskCount > 0 ? "#fff4f1" : "#eff8f4",
|
|
px: 2.25,
|
|
py: 1.75,
|
|
}}
|
|
>
|
|
<Typography sx={{ fontSize: 13, lineHeight: 1.8, color: REPORT_INK }}>
|
|
{reportData.conclusion}
|
|
</Typography>
|
|
{reportData.invalidCount > 0 && (
|
|
<Typography sx={{ mt: 0.5, fontSize: 11, color: REPORT_MUTED }}>
|
|
另有 {reportData.invalidCount} 条管段在当前预测年份缺少有效结果,未纳入本期统计。
|
|
</Typography>
|
|
)}
|
|
</Box>
|
|
</Box>
|
|
|
|
<Box
|
|
className="health-risk-report-metrics"
|
|
sx={{
|
|
mt: 2.25,
|
|
display: "grid",
|
|
gridTemplateColumns: { xs: "repeat(2, 1fr)", sm: "repeat(4, 1fr)" },
|
|
borderTop: `1px solid ${REPORT_LINE}`,
|
|
borderBottom: `1px solid ${REPORT_LINE}`,
|
|
}}
|
|
>
|
|
{metricItems.map((item, index) => (
|
|
<Box
|
|
key={item.label}
|
|
sx={{
|
|
px: 1.5,
|
|
py: 1.75,
|
|
borderRight:
|
|
index < metricItems.length - 1
|
|
? `1px solid ${REPORT_LINE}`
|
|
: "none",
|
|
}}
|
|
>
|
|
<Typography sx={{ color: REPORT_MUTED, fontSize: 11 }}>
|
|
{item.label}
|
|
</Typography>
|
|
<Typography
|
|
sx={{
|
|
mt: 0.5,
|
|
color: item.danger ? "#a62f2f" : REPORT_INK,
|
|
fontSize: 20,
|
|
fontWeight: 700,
|
|
lineHeight: 1.25,
|
|
}}
|
|
>
|
|
{item.value}
|
|
</Typography>
|
|
{item.detail && (
|
|
<Typography sx={{ mt: 0.25, color: REPORT_MUTED, fontSize: 10 }}>
|
|
占有效结果 {item.detail}
|
|
</Typography>
|
|
)}
|
|
</Box>
|
|
))}
|
|
</Box>
|
|
|
|
<Box
|
|
component="section"
|
|
className="health-risk-report-section"
|
|
sx={{ mt: 3 }}
|
|
>
|
|
<SectionTitle>当前年份风险分布</SectionTitle>
|
|
<Typography sx={{ mb: 1, color: REPORT_MUTED, fontSize: 11 }}>
|
|
生存概率越低,表示模型预测风险越高。统计口径与地图风险图例一致。
|
|
</Typography>
|
|
<ReactECharts
|
|
option={distributionOption}
|
|
style={{ width: "100%", height: 300 }}
|
|
opts={{ renderer: "svg" }}
|
|
notMerge
|
|
/>
|
|
</Box>
|
|
|
|
<Box
|
|
component="section"
|
|
className="health-risk-report-section"
|
|
sx={{ mt: 3 }}
|
|
>
|
|
<SectionTitle>重点风险趋势</SectionTitle>
|
|
<Typography sx={{ mb: 1, color: REPORT_MUTED, fontSize: 11 }}>
|
|
展示各预测年份中生存概率不高于 0.3 的管段数量。
|
|
</Typography>
|
|
<ReactECharts
|
|
option={trendOption}
|
|
style={{ width: "100%", height: 240 }}
|
|
opts={{ renderer: "svg" }}
|
|
notMerge
|
|
/>
|
|
</Box>
|
|
|
|
<Box component="section" sx={{ mt: 3 }}>
|
|
<SectionTitle>重点风险管段</SectionTitle>
|
|
<Typography sx={{ mb: 1.25, color: REPORT_MUTED, fontSize: 11 }}>
|
|
按当前预测年份的生存概率从低到高排列,最多展示 20 条。
|
|
</Typography>
|
|
{reportData.priorityPipes.length > 0 ? (
|
|
<TableContainer>
|
|
<Table
|
|
size="small"
|
|
aria-label="重点风险管段"
|
|
sx={{ tableLayout: "fixed" }}
|
|
>
|
|
<TableHead>
|
|
<TableRow sx={{ bgcolor: "#edf3f7" }}>
|
|
<TableCell sx={{ width: 52, fontWeight: 700 }}>序号</TableCell>
|
|
<TableCell sx={{ width: "34%", fontWeight: 700 }}>
|
|
管段编号
|
|
</TableCell>
|
|
<TableCell align="right" sx={{ width: 110, fontWeight: 700 }}>
|
|
生存概率
|
|
</TableCell>
|
|
<TableCell sx={{ fontWeight: 700 }}>风险等级</TableCell>
|
|
</TableRow>
|
|
</TableHead>
|
|
<TableBody>
|
|
{reportData.priorityPipes.map((pipe, index) => (
|
|
<TableRow
|
|
key={`${pipe.linkId}-${index}`}
|
|
className="health-risk-report-table-row"
|
|
>
|
|
<TableCell>{index + 1}</TableCell>
|
|
<TableCell
|
|
sx={{ fontWeight: 600, overflowWrap: "anywhere" }}
|
|
>
|
|
{pipe.linkId}
|
|
</TableCell>
|
|
<TableCell align="right">
|
|
{formatPercent(pipe.probability, 2)}
|
|
</TableCell>
|
|
<TableCell>
|
|
<Stack direction="row" alignItems="center" spacing={1}>
|
|
<Box
|
|
aria-hidden="true"
|
|
sx={{
|
|
width: 9,
|
|
height: 9,
|
|
flexShrink: 0,
|
|
bgcolor: pipe.color,
|
|
borderRadius: "50%",
|
|
}}
|
|
/>
|
|
<Typography sx={{ fontSize: 12 }}>
|
|
{pipe.riskLabel}
|
|
</Typography>
|
|
</Stack>
|
|
</TableCell>
|
|
</TableRow>
|
|
))}
|
|
</TableBody>
|
|
</Table>
|
|
</TableContainer>
|
|
) : (
|
|
<Box sx={{ bgcolor: "#f4f7f9", px: 2, py: 2 }}>
|
|
<Typography sx={{ color: REPORT_MUTED, fontSize: 12 }}>
|
|
当前预测年份没有较高及以上风险管段。
|
|
</Typography>
|
|
</Box>
|
|
)}
|
|
</Box>
|
|
|
|
<Box
|
|
component="section"
|
|
className="health-risk-report-section"
|
|
sx={{ mt: 3 }}
|
|
>
|
|
<SectionTitle>处置建议</SectionTitle>
|
|
<Box component="ol" sx={{ m: 0, pl: 3 }}>
|
|
{reportData.recommendations.map((recommendation) => (
|
|
<Typography
|
|
component="li"
|
|
key={recommendation}
|
|
sx={{
|
|
pl: 0.5,
|
|
mb: 0.75,
|
|
color: REPORT_INK,
|
|
fontSize: 12,
|
|
lineHeight: 1.75,
|
|
}}
|
|
>
|
|
{recommendation}
|
|
</Typography>
|
|
))}
|
|
</Box>
|
|
</Box>
|
|
|
|
<Box
|
|
component="footer"
|
|
sx={{
|
|
mt: 3.5,
|
|
pt: 1.5,
|
|
borderTop: `1px solid ${REPORT_LINE}`,
|
|
display: "flex",
|
|
justifyContent: "space-between",
|
|
gap: 2,
|
|
color: REPORT_MUTED,
|
|
}}
|
|
>
|
|
<Typography sx={{ fontSize: 10 }}>TJWater 管网分析平台</Typography>
|
|
<Typography sx={{ fontSize: 10, textAlign: "right" }}>
|
|
风险阈值:生存概率 ≤ 0.3
|
|
</Typography>
|
|
</Box>
|
|
</Box>
|
|
</Box>
|
|
</Dialog>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default HealthRiskReport;
|