qin
2025-03-18 fd206ba4e3e792eb01898fea540d50c2fd92f364
WinFrmUI/HStation.WinFrmUI.Xhs.Core/03-simulation/13-print/report/SimulationCommonReport.cs
@@ -1,6 +1,8 @@
using DevExpress.Utils;
using DevExpress.Charts.Native;
using DevExpress.Utils;
using DevExpress.XtraCharts;
using DevExpress.XtraReports.UI;
using Furion.DataValidation;
using Microsoft.CodeAnalysis;
using Yw.WinFrmUI.Phart;
@@ -13,10 +15,14 @@
            InitializeComponent();
        }
        private SimulationPrintViewModel _printViewModel;
        private List<Tuple<XYDiagram, AxisX, AxisY, SecondaryAxisY, SecondaryAxisY, HydroEnergyAnalyPipeItemViewModel>> _pointTuple = new();
        private int _currentChartIndex; // 当前图表索引
        public void SetBingdingData(SimulationPrintViewModel vm)
        {
            if (vm == null)
                return;
            // A4设置 827 1169
            this.PaperKind = DevExpress.Drawing.Printing.DXPaperKind.A4;
            this.Margins = new DevExpress.Drawing.DXMargins(50, 50, 50, 50);
@@ -230,88 +236,100 @@
                    this.Detail.Controls.Add(labForAccuracy);
                    currentY += firstCaptionHeight;
                    var accuracyScaleChart = ReportHelper.CreateAccuracyScale(working.Accuracy.Scale, 300F, 230F, currentY);
                    Detail.Controls.Add(accuracyScaleChart);
                    var accuracyFlowChart = ReportHelper.CreateAccuracyItem(working.Accuracy.Flow?.AvgError ?? 0, 213F, 230F, 300F, currentY);
                    Detail.Controls.Add(accuracyFlowChart);
                    var accuracyPressChart = ReportHelper.CreateAccuracyItem(working.Accuracy.Press?.AvgError ?? 0, 213F, 230F, 513F, currentY);
                    Detail.Controls.Add(accuracyPressChart);
                    currentY += accuracyScaleChart.HeightF;
                    currentY += 20F;
                    var labForAccuracyList = ReportHelper.CreateFirstCaption("(1.1)、评估列表", contentWidth - 25F, 15F, 20F, currentY);
                    this.Detail.Controls.Add(labForAccuracyList);
                    currentY += firstCaptionHeight;
                    #region 评估列表
                    if (working.Accuracy.Items != null && working.Accuracy.Items.Count > 0)
                    {                // 创建 XRTable
                        var tableForAccuracyList = new XRTable();
                        tableForAccuracyList.LocationF = new DevExpress.Utils.PointFloat(0F, currentY);
                        tableForAccuracyList.SizeF = new SizeF(727F, 30F + working.Accuracy.Items.Count * 25F); // 设置大小
                        // 创建表头行
                        XRTableRow headerRowAccuracyList = new XRTableRow();
                        headerRowAccuracyList.BackColor = Color.LightGray; // 设置背景颜色
                        // 添加表头列
                        headerRowAccuracyList.Cells.Add(ReportHelper.CreateTableCell("评估构件", 100));
                        headerRowAccuracyList.Cells.Add(ReportHelper.CreateTableCell("评估项", 100));
                        headerRowAccuracyList.Cells.Add(ReportHelper.CreateTableCell("监测值", 100));
                        headerRowAccuracyList.Cells.Add(ReportHelper.CreateTableCell("计算值", 100));
                        headerRowAccuracyList.Cells.Add(ReportHelper.CreateTableCell("评估误差", 100));
                        // 将表头行添加到表格
                        tableForAccuracyList.Rows.Add(headerRowAccuracyList);
                        foreach (var item in working.Accuracy.Items)
                    if (working.Accuracy != null)
                    {
                        XRChart accuracyScaleChart = null;
                        if (working.Accuracy.Scale != null)
                        {
                            // 创建数据行
                            var dataRow = new XRTableRow();
                            dataRow.Cells.Add(new XRTableCell()
                            {
                                Text = item.EvaluateName,
                                WidthF = 100F,
                                TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleCenter,
                                Borders = DevExpress.XtraPrinting.BorderSide.All
                            });
                            dataRow.Cells.Add(new XRTableCell()
                            {
                                Text = item.EvaluateItem,
                                WidthF = 100F,
                                TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleCenter,
                                Borders = DevExpress.XtraPrinting.BorderSide.All
                            });
                            dataRow.Cells.Add(new XRTableCell()
                            {
                                Text = item.MonitorValue.ToString(),
                                WidthF = 100F,
                                TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleCenter,
                                Borders = DevExpress.XtraPrinting.BorderSide.All
                            });
                            dataRow.Cells.Add(new XRTableCell()
                            {
                                Text = item.CalcuValue.ToString(),
                                WidthF = 100F,
                                TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleCenter,
                                Borders = DevExpress.XtraPrinting.BorderSide.All
                            });
                            dataRow.Cells.Add(new XRTableCell()
                            {
                                Text = item.EvaluateError?.ToString(),
                                WidthF = 100F,
                                TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleCenter,
                                Borders = DevExpress.XtraPrinting.BorderSide.All
                            });
                            tableForAccuracyList.Rows.Add(dataRow);
                            accuracyScaleChart = ReportHelper.CreateAccuracyScale(working.Accuracy.Scale, 300F, 230F, currentY);
                            Detail.Controls.Add(accuracyScaleChart);
                        }
                        // 将表格添加到Detail
                        this.Detail.Controls.Add(tableForAccuracyList);
                        currentY += tableForAccuracyList.HeightF;
                        var accuracyFlowChart = ReportHelper.CreateAccuracyItem(working.Accuracy.Flow?.AvgError ?? 0, 213F, 230F, 300F, currentY);
                        Detail.Controls.Add(accuracyFlowChart);
                        var accuracyPressChart = ReportHelper.CreateAccuracyItem(working.Accuracy.Press?.AvgError ?? 0, 213F, 230F, 513F, currentY);
                        Detail.Controls.Add(accuracyPressChart);
                        currentY += 20F;
                        var labForAccuracyList = ReportHelper.CreateFirstCaption("(1.1)、评估列表", contentWidth - 25F, 15F, 20F, currentY);
                        this.Detail.Controls.Add(labForAccuracyList);
                        currentY += firstCaptionHeight;
                        if (accuracyScaleChart != null)
                        {
                            currentY += accuracyScaleChart.HeightF;
                        }
                        #region 评估列表
                        if (working.Accuracy.Items != null && working.Accuracy.Items.Count > 0)
                        {                // 创建 XRTable
                            var tableForAccuracyList = new XRTable();
                            tableForAccuracyList.LocationF = new DevExpress.Utils.PointFloat(0F, currentY);
                            tableForAccuracyList.SizeF = new SizeF(727F, 30F + working.Accuracy.Items.Count * 25F); // 设置大小
                            // 创建表头行
                            XRTableRow headerRowAccuracyList = new XRTableRow();
                            headerRowAccuracyList.BackColor = Color.LightGray; // 设置背景颜色
                            // 添加表头列
                            headerRowAccuracyList.Cells.Add(ReportHelper.CreateTableCell("评估构件", 100));
                            headerRowAccuracyList.Cells.Add(ReportHelper.CreateTableCell("评估项", 100));
                            headerRowAccuracyList.Cells.Add(ReportHelper.CreateTableCell("监测值", 100));
                            headerRowAccuracyList.Cells.Add(ReportHelper.CreateTableCell("计算值", 100));
                            headerRowAccuracyList.Cells.Add(ReportHelper.CreateTableCell("评估误差", 100));
                            // 将表头行添加到表格
                            tableForAccuracyList.Rows.Add(headerRowAccuracyList);
                            foreach (var item in working.Accuracy.Items)
                            {
                                // 创建数据行
                                var dataRow = new XRTableRow();
                                dataRow.Cells.Add(new XRTableCell()
                                {
                                    Text = item.EvaluateName,
                                    WidthF = 100F,
                                    TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleCenter,
                                    Borders = DevExpress.XtraPrinting.BorderSide.All
                                });
                                dataRow.Cells.Add(new XRTableCell()
                                {
                                    Text = item.EvaluateItem,
                                    WidthF = 100F,
                                    TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleCenter,
                                    Borders = DevExpress.XtraPrinting.BorderSide.All
                                });
                                dataRow.Cells.Add(new XRTableCell()
                                {
                                    Text = item.MonitorValue.ToString(),
                                    WidthF = 100F,
                                    TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleCenter,
                                    Borders = DevExpress.XtraPrinting.BorderSide.All
                                });
                                dataRow.Cells.Add(new XRTableCell()
                                {
                                    Text = item.CalcuValue.ToString(),
                                    WidthF = 100F,
                                    TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleCenter,
                                    Borders = DevExpress.XtraPrinting.BorderSide.All
                                });
                                dataRow.Cells.Add(new XRTableCell()
                                {
                                    Text = item.EvaluateError?.ToString(),
                                    WidthF = 100F,
                                    TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleCenter,
                                    ForeColor = Color.Red,
                                    Borders = DevExpress.XtraPrinting.BorderSide.All
                                });
                                tableForAccuracyList.Rows.Add(dataRow);
                            }
                            // 将表格添加到Detail
                            this.Detail.Controls.Add(tableForAccuracyList);
                            currentY += tableForAccuracyList.HeightF;
                            currentY += 20F;
                        }
                    }
                    #endregion 评估列表
@@ -330,7 +348,8 @@
                            this.Detail.Controls.Add(label);
                            currentY += 20F;
                            #region 创建
                            #region 创建
                            XRChart chart = new XRChart();
                            ((System.ComponentModel.ISupportInitialize)(chart)).BeginInit();
                            chart.LocationF = new DevExpress.Utils.PointFloat(0F, currentY);
@@ -340,12 +359,11 @@
                            ReportHelper.SetChartDisplay(chart);
                            // 创建 XY 图表
                            XYDiagram xyDiagram = new XYDiagram();
                            ((System.ComponentModel.ISupportInitialize)(xyDiagram)).BeginInit();
                            // 配置主 X 轴
                            xyDiagram.AxisX.Title.Text = "流量(m³/h)";
                            xyDiagram.AxisX.Title.Visibility = DefaultBoolean.True;
                            xyDiagram.AxisX.Visibility = DefaultBoolean.True;
                            // xyDiagram.AxisX.Visibility = DefaultBoolean.True;
                            // 配置主 Y 轴
                            xyDiagram.AxisY.Title.Text = "扬程/m";
@@ -382,11 +400,11 @@
                            xyDiagram.SecondaryAxesY.Add(secondaryAxisY2);
                            xyDiagram.AxisX.VisibleInPanesSerializable = "1";
                            chart.Diagram = xyDiagram;
                            ((System.ComponentModel.ISupportInitialize)(xyDiagram)).EndInit();
                            ((System.ComponentModel.ISupportInitialize)(chart)).EndInit();
                            #endregion
                            #endregion 创建
                            // 创建第一个系列
                            Series series1 = new Series("Series 1", ViewType.Spline);
@@ -424,7 +442,7 @@
                            ReportHelper.GetOptimalSpaceMax(min_power, max_power, 4, out double min_power_chart, out double max_power_chart);
                            min_power_chart= ReportHelper.RoundDownMin(min_power_chart);
                            min_power_chart = ReportHelper.RoundDownMin(min_power_chart);
                            min_eff = 40;
@@ -448,7 +466,6 @@
                            {
                                series2.Points.Add(new SeriesPoint(qe.X, qe.Y));
                            }
                            ReportHelper.SetSecondaryAxisY(secondaryAxisY2, min_eff_chart, max_eff_chart);
                            ((XYDiagramSeriesViewBase)series2.View).Pane = pane2;
@@ -471,7 +488,7 @@
                            {
                                series3.Points.Add(new SeriesPoint(qp.X, qp.Y));
                            }
                            ReportHelper.SetSecondaryAxisY(secondaryAxisY1, min_power_chart,max_power_chart);
                            ReportHelper.SetSecondaryAxisY(secondaryAxisY1, min_power_chart, max_power_chart);
                            ((XYDiagramSeriesViewBase)series3.View).Pane = pane1;
                            ((XYDiagramSeriesViewBase)series3.View).AxisY = secondaryAxisY1;
@@ -488,8 +505,293 @@
                            }
                            chart.Series.Add(series3);
                            ((System.ComponentModel.ISupportInitialize)(chart)).EndInit();
                            Detail.Controls.Add(chart);
                            currentY += chart.HeightF;
                        }
                        currentY += 20F;
                    }
                    var labForPumpParallel = ReportHelper.CreateFirstCaption("(2.1)、水泵并联", contentWidth - 25F, 15F, 20F, currentY);
                    this.Detail.Controls.Add(labForPumpParallel);
                    currentY += 50F;
                    if (working.PumpAnaly != null && working.PumpAnaly.Parallel != null && working.PumpAnaly.Parallel.Items.Count > 0)
                    {
                        var group = working.PumpAnaly.Parallel.Items.GroupBy(x => x.BeginGroup).ToArray();
                        foreach (var item in group)
                        {
                            var label = ReportHelper.CreateFirstCaption(item.Key, contentWidth - 25F, 15F, 20F, currentY);
                            this.Detail.Controls.Add(label);
                            currentY += 20F;
                            XRChart chart = new XRChart();
                            ((System.ComponentModel.ISupportInitialize)(chart)).BeginInit();
                            chart.LocationF = new DevExpress.Utils.PointFloat(0F, currentY);
                            chart.WidthF = contentWidth;
                            chart.HeightF = 600F;
                            chart.Legend.Visibility = DevExpress.Utils.DefaultBoolean.False;
                            // 创建 XY 图表
                            XYDiagram xyDiagram = new XYDiagram();
                            ((System.ComponentModel.ISupportInitialize)(xyDiagram)).BeginInit();
                            // 配置主 X 轴
                            xyDiagram.AxisX.Title.Text = "流量(m³/h)";
                            xyDiagram.AxisX.Title.Visibility = DefaultBoolean.True;
                            xyDiagram.AxisX.Visibility = DefaultBoolean.True;
                            // 配置主 Y 轴
                            xyDiagram.AxisY.Title.Text = "扬程/m";
                            xyDiagram.AxisY.Title.Visibility = DefaultBoolean.True;
                            xyDiagram.AxisY.Visibility = DefaultBoolean.True;
                            xyDiagram.AxisX.VisibleInPanesSerializable = "1";
                            // 创建两个面板
                            XYDiagramPane pane1 = new XYDiagramPane();
                            pane1.Name = "Pane 1";
                            xyDiagram.Panes.Add(pane1);
                            XYDiagramPane pane2 = new XYDiagramPane();
                            pane2.Name = "Pane 2";
                            xyDiagram.Panes.Add(pane2);
                            // 创建次要 Y 轴
                            SecondaryAxisY secondaryAxisY1 = new SecondaryAxisY("Secondary Y-Axis 1");
                            secondaryAxisY1.Title.Text = "功率(KW)";
                            secondaryAxisY1.Title.Visibility = DefaultBoolean.True;
                            secondaryAxisY1.Visibility = DefaultBoolean.True;
                            secondaryAxisY1.GridLines.Visible = true;
                            secondaryAxisY1.Tickmarks.Thickness = 1;
                            secondaryAxisY1.GridLines.Color = Color.LightGray;
                            xyDiagram.SecondaryAxesY.Add(secondaryAxisY1);
                            SecondaryAxisY secondaryAxisY2 = new SecondaryAxisY("Secondary Y-Axis 2");
                            secondaryAxisY2.Title.Text = "效率(%)";
                            secondaryAxisY2.Title.Visibility = DefaultBoolean.True;
                            secondaryAxisY2.Visibility = DefaultBoolean.True;
                            secondaryAxisY2.GridLines.Visible = true;
                            secondaryAxisY2.Tickmarks.Thickness = 1;
                            secondaryAxisY2.GridLines.Color = Color.LightGray;
                            xyDiagram.SecondaryAxesY.Add(secondaryAxisY2);
                            var pipe = working.PumpAnaly.Parallel.Items[0];
                            chart.Diagram = xyDiagram;
                            ((System.ComponentModel.ISupportInitialize)(xyDiagram)).EndInit();
                            foreach (var valve in item)
                            {
                                if (valve.Items != null && valve.Items.Count > 0)
                                {
                                    foreach (var curve in valve.Items)
                                    {
                                        Series seriesQh = new Series("Series Qh", ViewType.Spline);
                                        if (curve.CurrentCurveQH != null)
                                        {
                                            foreach (var qh in curve.CurrentCurveQH)
                                            {
                                                seriesQh.Points.Add(new SeriesPoint(qh.X, qh.Y));
                                            }
                                        }
                                   ((SplineSeriesView)seriesQh.View).MarkerVisibility = DefaultBoolean.False;
                                        seriesQh.LabelsVisibility = DefaultBoolean.False;
                                        chart.Series.Add(seriesQh);
                                        Yw.Geometry.Point2d anchorPointQh = new Yw.Geometry.Point2d((double)valve.CurveQH.Last().X, (double)valve.CurveQH.Last().Y + 3); // 锚点坐标
                                        TextAnnotation annotation = ReportHelper.AddAnnotation("SampleTag", "并联线", Color.Red, xyDiagram.AxisY, xyDiagram.DefaultPane, anchorPointQh);
                                        if (annotation != null)
                                        {
                                            chart.AnnotationRepository.Add(annotation);
                                        }
                                        Series seriesQe = new Series("Series Qe", ViewType.Spline);
                                        if (curve.CurrentCurveQE != null)
                                        {
                                            foreach (var qe in curve.CurrentCurveQE)
                                            {
                                                seriesQe.Points.Add(new SeriesPoint(qe.X, qe.Y));
                                            }
                                        }
                                        ((XYDiagramSeriesViewBase)seriesQe.View).Pane = pane2;
                                        ((XYDiagramSeriesViewBase)seriesQe.View).AxisY = secondaryAxisY2;
                                        ((SplineSeriesView)seriesQe.View).MarkerVisibility = DefaultBoolean.False;
                                        seriesQe.LabelsVisibility = DefaultBoolean.False;
                                        chart.Series.Add(seriesQe);
                                        Series seriesQp = new Series("Series Qp", ViewType.Spline);
                                        if (curve.CurrentCurveQP != null)
                                        {
                                            foreach (var qp in curve.CurrentCurveQP)
                                            {
                                                seriesQp.Points.Add(new SeriesPoint(qp.X, qp.Y));
                                            }
                                        }
                                        ((XYDiagramSeriesViewBase)seriesQp.View).Pane = pane1;
                                        ((XYDiagramSeriesViewBase)seriesQp.View).AxisY = secondaryAxisY1;
                                        ((SplineSeriesView)seriesQp.View).MarkerVisibility = DefaultBoolean.False;
                                        seriesQp.LabelsVisibility = DefaultBoolean.False;
                                        chart.Series.Add(seriesQp);
                                    }
                                }
                                // 创建第一个系列
                                Series series1 = new Series("Series 1", ViewType.Spline);
                                if (valve.CurveQH != null)
                                {
                                    foreach (var qh in valve.CurveQH)
                                    {
                                        series1.Points.Add(new SeriesPoint(qh.X, qh.Y));
                                    }
                                    ((SplineSeriesView)series1.View).MarkerVisibility = DefaultBoolean.False;
                                    ((SplineSeriesView)series1.View).Color = Color.Black;
                                    series1.LabelsVisibility = DefaultBoolean.False;
                                }
                                chart.Series.Add(series1);
                                // 创建第二个系列
                                Series series2 = new Series("Series 2", ViewType.Spline);
                                if (valve.CurveQE != null)
                                {
                                    foreach (var qe in valve.CurveQE)
                                    {
                                        series2.Points.Add(new SeriesPoint(qe.X, qe.Y));
                                    }
                                    ((XYDiagramSeriesViewBase)series2.View).Pane = pane2;
                                    ((XYDiagramSeriesViewBase)series2.View).AxisY = secondaryAxisY2;
                                    ((SplineSeriesView)series2.View).MarkerVisibility = DefaultBoolean.False;
                                    ((SplineSeriesView)series2.View).Color = Color.Black;
                                    series2.LabelsVisibility = DefaultBoolean.False;
                                    chart.Series.Add(series2);
                                }
                                // 创建第三个系列
                                Series series3 = new Series("Series 3", ViewType.Spline);
                                if (valve.CurveQP != null)
                                {
                                    foreach (var qp in valve.CurveQP)
                                    {
                                        series3.Points.Add(new SeriesPoint(qp.X, qp.Y));
                                    }
                                    ((XYDiagramSeriesViewBase)series3.View).Pane = pane1;
                                    ((XYDiagramSeriesViewBase)series3.View).AxisY = secondaryAxisY1;
                                    ((SplineSeriesView)series3.View).MarkerVisibility = DefaultBoolean.False;
                                    ((SplineSeriesView)series3.View).Color = Color.Black;
                                    series3.LabelsVisibility = DefaultBoolean.False;
                                    chart.Series.Add(series3);
                                }
                                if (item != null)
                                {
                                    foreach (var itemInList in item)
                                    {
                                        if (itemInList.Items != null && itemInList.Items.Count > 0)
                                        {
                                            if (valve.CurveQH != null)
                                            {
                                                foreach (var items in itemInList.Items)
                                                {
                                                    if (items != null && items.CurrentCurveQH != null)
                                                    {
                                                        items.CurrentCurveQH.AddRange(valve.CurveQH);
                                                        break;
                                                    }
                                                }
                                                //itemInList.Items[0].CurrentCurveQH.AddRange(valve.CurveQH);
                                                //break;
                                            }
                                        }
                                    }
                                    foreach (var itemInList in item)
                                    {
                                        if (itemInList.Items != null && itemInList.Items.Count > 0)
                                        {
                                            if (valve.CurveQE != null)
                                            {
                                                foreach (var items in itemInList.Items)
                                                {
                                                    if (items != null && items.CurrentCurveQE != null)
                                                    {
                                                        items.CurrentCurveQE.AddRange(valve.CurveQE);
                                                        break;
                                                    }
                                                }
                                                //itemInList.Items[0].CurrentCurveQE.AddRange(valve.CurveQE);
                                                //break;
                                            }
                                        }
                                    }
                                    foreach (var itemInList in item)
                                    {
                                        if (itemInList.Items != null && itemInList.Items.Count > 0)
                                        {
                                            foreach (var items in itemInList.Items)
                                            {
                                                if (items != null && items.CurrentCurveQP != null)
                                                {
                                                    items.CurrentCurveQP.AddRange(valve.CurveQP);
                                                    break;
                                                }
                                            }
                                            /*if (valve.CurveQP != null)
                                            {
                                                itemInList.Items[0].CurrentCurveQP.AddRange(valve.CurveQP);
                                                break;
                                            }*/
                                        }
                                    }
                                    // 处理 X 轴设置
                                    var allQHForXY = item
                                     .Where(i => i.Items != null)
                                     .SelectMany(i => i.Items)
                                     .Where(inner => inner.CurrentCurveQH != null)
                                     .SelectMany(inner => inner.CurrentCurveQH);
                                    if (allQHForXY.Any())
                                    {
                                        var globalXMax = allQHForXY.Max(qh => qh.X);
                                        var globalXMin = allQHForXY.Min(qh => qh.X);
                                        var globalYMax = allQHForXY.Max(qh => qh.Y);
                                        var globalYMin = allQHForXY.Min(qh => qh.Y);
                                        ReportHelper.SetAxisX(xyDiagram, ReportHelper.RoundDownMin(globalXMin), ReportHelper.RoundUpMax(globalXMax));
                                        ReportHelper.SetAxisY(xyDiagram, ReportHelper.RoundDownMin(globalYMin), ReportHelper.RoundUpMax(globalYMax));
                                    }
                                    // 处理 Y 轴设置
                                    var allQpForY = item
                                      .Where(i => i.Items != null)
                                      .SelectMany(i => i.Items)
                                      .Where(inner => inner.CurrentCurveQP != null)
                                      .SelectMany(inner => inner.CurrentCurveQP);
                                    if (allQpForY.Any())
                                    {
                                        var globalYMax = allQpForY.Max(qh => qh.Y);
                                        var globalYMin = allQpForY.Min(qh => qh.Y);
                                        ReportHelper.SetSecondaryAxisY(secondaryAxisY1, ReportHelper.RoundDownMin(globalYMin), ReportHelper.RoundUpMax(globalYMax));
                                    }
                                    // 处理 Y 轴设置
                                    var allQeForY = item
                                    .Where(i => i.Items != null)
                                    .SelectMany(i => i.Items)
                                    .Where(inner => inner.CurrentCurveQE != null)
                                    .SelectMany(inner => inner.CurrentCurveQE);
                                    if (allQeForY.Any())
                                    {
                                        var globalYMax = allQeForY.Max(qh => qh.Y);
                                        var globalYMin = allQeForY.Min(qh => qh.Y);
                                        ReportHelper.SetSecondaryAxisY(secondaryAxisY2, ReportHelper.RoundDownMin(globalYMin), ReportHelper.RoundUpMax(globalYMax));
                                    }
                                }
                            }
                            ((System.ComponentModel.ISupportInitialize)(chart)).EndInit();
                            Detail.Controls.Add(chart);
                            currentY += chart.HeightF;
                        }
@@ -504,7 +806,7 @@
                    this.Detail.Controls.Add(labForMonitor);
                    currentY += 20F;
                    if (working.MonitorAnaly.Items != null && working.MonitorAnaly.Items.Count > 0)
                    if (working.MonitorAnaly != null && working.MonitorAnaly.Items != null && working.MonitorAnaly.Items.Count > 0)
                    {                // 创建 XRTable
                        var tableForMonitorList = new XRTable();
                        tableForMonitorList.LocationF = new DevExpress.Utils.PointFloat(0F, currentY);
@@ -573,6 +875,7 @@
                    if (working.EnergyAnaly != null)
                    {
                        int groupIndex = 0;
                        if (working.EnergyAnaly.Items != null && working.EnergyAnaly.Items.Count > 0)
                        {
                            var group = working.EnergyAnaly.Items.GroupBy(x => x.BeginGroup).ToArray();
@@ -589,10 +892,21 @@
                                chart.HeightF = 600F;
                                chart.Legend.Visibility = DevExpress.Utils.DefaultBoolean.False;
                                chart.CustomPaint += (sender, e) =>
                                {
                                    using Pen pen = new(Color.Black, 2)
                                    {
                                        DashStyle = System.Drawing.Drawing2D.DashStyle.DashDotDot
                                    };
                                    ReportHelper.DrawEquipPoint(_pointTuple[_currentChartIndex].Item1, _pointTuple[_currentChartIndex].Item2, _pointTuple[_currentChartIndex].Item3, _pointTuple[_currentChartIndex].Item4, _pointTuple[_currentChartIndex].Item5, e.Graphics, pen, _pointTuple[_currentChartIndex].Item6);
                                    ReportHelper.DrawEquipLine(_pointTuple[_currentChartIndex].Item1, _pointTuple[_currentChartIndex].Item2, _pointTuple[_currentChartIndex].Item3, e.Graphics, pen, _pointTuple[_currentChartIndex].Item6);
                                    _currentChartIndex++;
                                };
                                // 创建 XY 图表
                                XYDiagram xyDiagram = new XYDiagram();
                                ((System.ComponentModel.ISupportInitialize)(xyDiagram)).BeginInit();
                                xyDiagram.Tag = groupIndex;
                                // 配置主 X 轴
                                xyDiagram.AxisX.Title.Text = "流量(m³/h)";
                                xyDiagram.AxisX.Title.Visibility = DefaultBoolean.True;
@@ -602,7 +916,7 @@
                                xyDiagram.AxisY.Title.Text = "扬程/m";
                                xyDiagram.AxisY.Title.Visibility = DefaultBoolean.True;
                                xyDiagram.AxisY.Visibility = DefaultBoolean.True;
                                xyDiagram.AxisX.VisibleInPanesSerializable = "1";
                                // 创建两个面板
                                XYDiagramPane pane1 = new XYDiagramPane();
                                pane1.Name = "Pane 1";
@@ -623,32 +937,6 @@
                                xyDiagram.SecondaryAxesY.Add(secondaryAxisY1);
                                if (item != null)
                                {
                                    // 处理 X 轴设置
                                    var allQHForX = item
                                       .Where(singleItem => singleItem.CurrentCurveQH != null)
                                       .SelectMany(singleItem => singleItem.CurrentCurveQH);
                                    if (allQHForX.Any())
                                    {
                                        var globalXMax = allQHForX.Max(qh => qh.X);
                                        var globalXMin = allQHForX.Min(qh => qh.X);
                                        ReportHelper.SetAxisX(xyDiagram, globalXMin, ReportHelper.RoundUpMax(globalXMax));
                                    }
                                    // 处理 Y 轴设置
                                    var allQHForY = item
                                       .Where(singleItem => singleItem.CurrentCurveQH != null)
                                       .SelectMany(singleItem => singleItem.CurrentCurveQH);
                                    if (allQHForY.Any())
                                    {
                                        var globalYMax = allQHForY.Max(qh => qh.Y);
                                        var globalYMin = allQHForY.Min(qh => qh.Y);
                                        ReportHelper.SetAxisY(xyDiagram, ReportHelper.RoundDownMin(globalYMin), ReportHelper.RoundUpMax(globalYMax));
                                    }
                                }
                                SecondaryAxisY secondaryAxisY2 = new SecondaryAxisY("Secondary Y-Axis 2");
                                secondaryAxisY2.Title.Text = "效率(%)";
                                secondaryAxisY2.Title.Visibility = DefaultBoolean.True;
@@ -659,9 +947,22 @@
                                xyDiagram.SecondaryAxesY.Add(secondaryAxisY2);
                                var pipe = working.EnergyAnaly.Pipe.Items[groupIndex];
                                if (pipe != null)
                                {
                                    _pointTuple.Add(new Tuple<XYDiagram, AxisX, AxisY, SecondaryAxisY, SecondaryAxisY, HydroEnergyAnalyPipeItemViewModel>(
                                      xyDiagram,
                                      xyDiagram.AxisX,
                                      xyDiagram.AxisY,
                                      secondaryAxisY2,
                                      secondaryAxisY1,
                                      pipe
           ));
                                }
                                groupIndex++;
                                chart.Diagram = xyDiagram;
                                ((System.ComponentModel.ISupportInitialize)(xyDiagram)).EndInit();
                                ((System.ComponentModel.ISupportInitialize)(chart)).EndInit();
                                foreach (var valve in item)
                                {
@@ -673,10 +974,86 @@
                                        {
                                            series1.Points.Add(new SeriesPoint(qh.X, qh.Y));
                                        }
                                      ((SplineSeriesView)series1.View).MarkerVisibility = DefaultBoolean.False;
                                        ((SplineSeriesView)series1.View).MarkerVisibility = DefaultBoolean.False;
                                        series1.LabelsVisibility = DefaultBoolean.False;
                                        chart.Series.Add(series1);
                                    }
                                    chart.Series.Add(series1);
                                    var pt_f_list = new List<Yw.Geometry.Point2d>();
                                    if (pipe != null)
                                    {
                                        if (pipe.PipeH != null || pipe.PipeQ != null)
                                        {
                                            var start_point = new Yw.Geometry.Point2d(0.0, pipe.StartH);
                                            var end_point = new Yw.Geometry.Point2d(pipe.PipeQ.Value, pipe.PipeH.Value);
                                            pt_f_list = Yw.Pump.PerformParabolaHelper.GetEquipCurvePointList(start_point, end_point, 30);
                                        }
                                    }
                                    if (item != null)
                                    {
                                        foreach (var itemInList in item)
                                        {
                                            if (itemInList.CurrentCurveQH != null)
                                            {
                                                if (pt_f_list != null)
                                                {
                                                    itemInList.CurrentCurveQH.AddRange(pt_f_list);
                                                    // 处理 X 轴设置
                                                    var allQHForX = item
                                                       .Where(singleItem => singleItem.CurrentCurveQH != null)
                                                       .SelectMany(singleItem => singleItem.CurrentCurveQH);
                                                    if (allQHForX.Any())
                                                    {
                                                        var globalXMax = allQHForX.Max(qh => qh.X);
                                                        var globalXMin = allQHForX.Min(qh => qh.X);
                                                        ReportHelper.SetAxisX(xyDiagram, ReportHelper.RoundDownMin(globalXMin), ReportHelper.RoundUpMax(globalXMax));
                                                    }
                                                    // 处理 Y 轴设置
                                                    var allQHForY = item
                                                       .Where(singleItem => singleItem.CurrentCurveQH != null)
                                                       .SelectMany(singleItem => singleItem.CurrentCurveQH);
                                                    if (allQHForY.Any())
                                                    {
                                                        var globalYMax = allQHForY.Max(qh => qh.Y);
                                                        var globalYMin = allQHForY.Min(qh => qh.Y);
                                                        ReportHelper.SetAxisY(xyDiagram, ReportHelper.RoundDownMin(globalYMin), ReportHelper.RoundUpMax(globalYMax));
                                                    }
                                                    itemInList.CurrentCurveQH.RemoveAll(item => pt_f_list.Contains(item));
                                                    break;
                                                }
                                            }
                                        }
                                        // 处理 Y 轴设置
                                        var allQpForY = item
                                           .Where(singleItem => singleItem.RatedCurveQP != null)
                                           .SelectMany(singleItem => singleItem.RatedCurveQP);
                                        if (allQpForY.Any())
                                        {
                                            var globalYMax = allQpForY.Max(qh => qh.Y);
                                            var globalYMin = allQpForY.Min(qh => qh.Y);
                                            ReportHelper.SetSecondaryAxisY(secondaryAxisY1, ReportHelper.RoundDownMin(globalYMin), ReportHelper.RoundUpMax(globalYMax));
                                        }
                                        // 处理 Y 轴设置
                                        var allQeForY = item
                                           .Where(singleItem => singleItem.RatedCurveQE != null)
                                           .SelectMany(singleItem => singleItem.RatedCurveQE);
                                        if (allQeForY.Any())
                                        {
                                            var globalYMax = allQeForY.Max(qh => qh.Y);
                                            var globalYMin = allQeForY.Min(qh => qh.Y);
                                            ReportHelper.SetSecondaryAxisY(secondaryAxisY2, ReportHelper.RoundDownMin(globalYMin), ReportHelper.RoundUpMax(globalYMax));
                                        }
                                    }
                                    Series qhWorking = new Series("Series 5", ViewType.Spline);
                                    qhWorking.LabelsVisibility = DefaultBoolean.False;
                                    if (valve.CurrentQ != null && valve.CurrentH != null)
@@ -693,13 +1070,13 @@
                                        {
                                            series2.Points.Add(new SeriesPoint(qe.X, qe.Y));
                                        }
                                    ((XYDiagramSeriesViewBase)series2.View).Pane = pane2;
                                        ((XYDiagramSeriesViewBase)series2.View).Pane = pane2;
                                        ((XYDiagramSeriesViewBase)series2.View).AxisY = secondaryAxisY2;
                                        ((SplineSeriesView)series2.View).MarkerVisibility = DefaultBoolean.False;
                                        series2.LabelsVisibility = DefaultBoolean.False;
                                        ReportHelper.SetSecondaryAxisY(secondaryAxisY2, ReportHelper.RoundDownMin(valve.CurrentCurveQE.Min(qh => qh.Y)), ReportHelper.RoundUpMax(valve.CurrentCurveQE.Max(qh => qh.Y)));
                                        chart.Series.Add(series2);
                                    }
                                    Series qeWorking = new Series("Series 6", ViewType.Spline);
                                    qeWorking.LabelsVisibility = DefaultBoolean.False;
                                    if (valve.CurrentQ != null && valve.CurrentE != null)
@@ -710,6 +1087,7 @@
                                        chart.Series.Add(qeWorking);
                                    }
                                    // 创建第三个系列
                                    Series series3 = new Series("Series 3", ViewType.Spline);
                                    if (valve.RatedCurveQP != null)
@@ -718,12 +1096,12 @@
                                        {
                                            series3.Points.Add(new SeriesPoint(qp.X, qp.Y));
                                        }
                                    ((XYDiagramSeriesViewBase)series3.View).Pane = pane1;
                                        ((XYDiagramSeriesViewBase)series3.View).Pane = pane1;
                                        ((XYDiagramSeriesViewBase)series3.View).AxisY = secondaryAxisY1;
                                        ((SplineSeriesView)series3.View).MarkerVisibility = DefaultBoolean.False;
                                        series3.LabelsVisibility = DefaultBoolean.False;
                                        ReportHelper.SetSecondaryAxisY(secondaryAxisY1, ReportHelper.RoundDownMin(valve.RatedCurveQP.Min(qh => qh.Y)), ReportHelper.RoundUpMax(valve.RatedCurveQP.Max(qh => qh.Y)));
                                        chart.Series.Add(series3);
                                        if (valve.CurrentQ != null && valve.CurrentP != null)
                                        {
                                            Series qpWorking = new Series("Series 7", ViewType.Spline);
@@ -735,7 +1113,14 @@
                                        }
                                    }
                                }
                                ((System.ComponentModel.ISupportInitialize)(chart)).EndInit();
                                // 重新设置高度
                                chart.HeightF = chart.HeightF;
                                // 重新设置位置
                                chart.LocationF = chart.LocationF;
                                Detail.Controls.Add(chart);
                                currentY += chart.HeightF;
                            }
                        }
@@ -793,7 +1178,7 @@
                            });
                            dataRow.Cells.Add(new XRTableCell()
                            {
                                Text = item.LinkStatus,
                                Text = HydroLinkStatusHelper.GetStatusName(item.LinkStatus),
                                WidthF = 100F,
                                TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleCenter,
                                Borders = DevExpress.XtraPrinting.BorderSide.All