From a20339d35e5b6cdc4a8b78bc5e37cd7dd88b39b3 Mon Sep 17 00:00:00 2001 From: Huarch Date: Mon, 20 Jul 2026 13:47:39 +0800 Subject: [PATCH] Update prediction results workflow --- app/prediction.py | 259 +++++++++++++++++++++------------------ app/routes.py | 7 -- example.xlsx | Bin 32492 -> 36183 bytes requirements.txt | 4 +- static/css/app.css | 2 +- static/js/dashboard.js | 9 -- templates/home.html | 18 ++- templates/login.html | 2 +- templates/result.html | 66 ++-------- tests/test_prediction.py | 79 ++++++++++-- 10 files changed, 239 insertions(+), 207 deletions(-) diff --git a/app/prediction.py b/app/prediction.py index 19aad27..127c026 100644 --- a/app/prediction.py +++ b/app/prediction.py @@ -61,6 +61,16 @@ PIPE_AGE_COLUMN = "管龄(年)" LEGACY_PIPE_AGE_COLUMN = "管龄" STATUS_COLUMN = "状态" EVENT_AGE_COLUMN = "事件/观察管龄(年)" +COLUMN_ALIASES = { + "管径(mm)": "管径", + "管径(mm)": "管径", + "流速(m/s)": "流速", + "压力(MPa)": "压力", + "压力(MPa)": "压力", + "温度(℃)": "温度", + "年均降雨量(mm)": "降雨量", + "降雨量(mm)": "降雨量", +} INPUT_COLUMNS = [ ID_COLUMN, PIPE_AGE_COLUMN, @@ -68,6 +78,7 @@ INPUT_COLUMNS = [ EVENT_AGE_COLUMN, *FEATURES, ] +CHART_DISPLAY_LIMIT = 10 MATERIAL_COLUMN = "管材" MATERIAL_CODE_OPTIONS = [ (1, "镀锌"), @@ -103,6 +114,7 @@ MATERIAL_ALIAS_TO_CODE.update( ) SUPPORTED_EXTENSIONS = {".csv", ".xls", ".xlsx"} CHINESE_FONT_PROP = None +DEFECT_GRADE_VALUES = {"无": 0.0, "轻度": 1.0, "中度": 3.0, "严重": 5.0} class PredictionError(Exception): @@ -119,12 +131,35 @@ class PredictionArtifacts: excel_path: Path image_path: Path image_filename: str - importance_filename: str | None sample_count: int summary_rows: list[dict[str, Any]] analysis_text: str +class ModelBundleAdapter: + """Expose a bundled preprocessor and survival model as one predictor.""" + + def __init__(self, preprocessor, model) -> None: + self.preprocessor = preprocessor + self.model = model + + def _transform(self, frame: pd.DataFrame): + values = frame[FEATURES].copy() + values[MATERIAL_COLUMN] = values[MATERIAL_COLUMN].map( + lambda value: f"M{int(value)}" if pd.notna(value) else value + ) + values["位置"] = values["位置"].map( + lambda value: f"L{int(value)}" if pd.notna(value) else value + ) + return self.preprocessor.transform(values.to_numpy(dtype=object)).astype(np.float32) + + def predict_survival_function(self, frame: pd.DataFrame): + return self.model.predict_survival_function(self._transform(frame)) + + def predict(self, frame: pd.DataFrame): + return self.model.predict(self._transform(frame)) + + def configure_matplotlib_fonts(): for font_path in CHINESE_FONT_FILES: path = Path(font_path) @@ -159,6 +194,10 @@ def load_model(model_path: str): if not os.path.exists(model_path): raise FileNotFoundError(f"未找到模型文件: {model_path}") model = joblib.load(model_path) + if isinstance(model, dict): + if not {"preprocessor", "model"}.issubset(model): + raise ValueError("模型包缺少 preprocessor 或 model。") + model = ModelBundleAdapter(model["preprocessor"], model["model"]) feature_names = getattr(model, "feature_names_in_", None) if feature_names is not None and list(feature_names) != FEATURES: raise ValueError( @@ -195,17 +234,25 @@ def read_input_file(path: Path, suffix: str) -> pd.DataFrame: if suffix == ".csv": df = pd.read_csv(path, dtype={ID_COLUMN: "string"}) else: - df = pd.read_excel(path, dtype={ID_COLUMN: "string"}) + try: + df = pd.read_excel(path, sheet_name="Template", dtype={ID_COLUMN: "string"}) + except ValueError: + df = pd.read_excel(path, dtype={ID_COLUMN: "string"}) + df["_excel_row"] = df.index + 2 except Exception as exc: logging.exception("文件解析失败: %s", exc) raise PredictionError("文件解析失败,请检查编码或表格格式。") - return normalize_input_columns(df) + df = normalize_input_columns(df) + if suffix in {".xls", ".xlsx"}: + df = fill_defects_from_detail_sheet(path, df) + return df def normalize_input_columns(df: pd.DataFrame) -> pd.DataFrame: + aliases = dict(COLUMN_ALIASES) if PIPE_AGE_COLUMN not in df.columns and LEGACY_PIPE_AGE_COLUMN in df.columns: - return df.rename(columns={LEGACY_PIPE_AGE_COLUMN: PIPE_AGE_COLUMN}) - return df + aliases[LEGACY_PIPE_AGE_COLUMN] = PIPE_AGE_COLUMN + return df.rename(columns={name: aliases[name] for name in df.columns if name in aliases}) def normalize_id_value(value: Any, fallback: str) -> str: @@ -216,6 +263,79 @@ def normalize_id_value(value: Any, fallback: str) -> str: return str(value) +def defect_grade_value(value: Any) -> float | None: + if pd.isna(value): + return None + text = str(value).strip() + if text == "": + return None + if text in DEFECT_GRADE_VALUES: + return DEFECT_GRADE_VALUES[text] + try: + return float(text) + except ValueError: + return None + + +def weighted_defect_score(values: list[Any], weights: list[float]) -> float | None: + scores = [defect_grade_value(value) for value in values] + if any(score is None for score in scores): + return None + return round(sum(score * weight for score, weight in zip(scores, weights)), 3) + + +def numeric_or_none(value: Any) -> float | None: + try: + if pd.isna(value): + return None + return float(value) + except (TypeError, ValueError): + return None + + +def fill_defects_from_detail_sheet(path: Path, df: pd.DataFrame) -> pd.DataFrame: + if "结构缺陷" not in df.columns or "功能缺陷" not in df.columns or "_excel_row" not in df.columns: + return df + + structure = pd.to_numeric(df["结构缺陷"], errors="coerce") + function = pd.to_numeric(df["功能缺陷"], errors="coerce") + needs_fill = structure.isna() | function.isna() + df["结构缺陷"] = structure + df["功能缺陷"] = function + if not needs_fill.any(): + return df + + try: + from openpyxl import load_workbook + + workbook = load_workbook(path, data_only=False, read_only=True) + defect_sheet = workbook["缺陷计算"] + except Exception as exc: + logging.info("未能读取缺陷计算工作表,跳过缺陷自动计算: %s", exc) + return df + + for index in df.index[needs_fill]: + excel_row = int(df.at[index, "_excel_row"]) + if pd.isna(df.at[index, "结构缺陷"]): + value = numeric_or_none(defect_sheet.cell(excel_row, 5).value) + if value is None: + value = weighted_defect_score( + [defect_sheet.cell(excel_row, column).value for column in (2, 3, 4)], + [0.5, 0.4, 0.1], + ) + df.at[index, "结构缺陷"] = value + if pd.isna(df.at[index, "功能缺陷"]): + value = numeric_or_none(defect_sheet.cell(excel_row, 10).value) + if value is None: + value = weighted_defect_score( + [defect_sheet.cell(excel_row, column).value for column in (6, 7, 8, 9)], + [0.5, 0.2, 0.2, 0.1], + ) + df.at[index, "功能缺陷"] = value + + return df + + def validate_input_frame(df: pd.DataFrame) -> None: if df.empty: raise PredictionError("上传文件没有可预测的数据。") @@ -288,99 +408,6 @@ def make_analysis_text(summary_rows: list[dict[str, Any]]) -> str: ) -def compute_feature_importance(model, x_test: pd.DataFrame) -> np.ndarray | None: - try: - importances = model.feature_importances_ - except Exception: - importances = None - - if importances is not None and len(importances) == len(FEATURES): - vals = np.asarray(importances, dtype=float) - else: - try: - baseline = np.asarray(model.predict(x_test), dtype=float) - except Exception as exc: - logging.exception("特征重要性基线预测失败: %s", exc) - return None - - rng = np.random.default_rng(42) - vals = np.zeros(len(FEATURES), dtype=float) - for j, feat in enumerate(FEATURES): - diffs = [] - for _ in range(5): - x_perm = x_test.copy() - x_perm[feat] = rng.permutation(x_perm[feat].to_numpy()) - try: - perm_pred = np.asarray(model.predict(x_perm), dtype=float) - except Exception: - perm_pred = baseline - diffs.append(float(np.mean(np.abs(perm_pred - baseline)))) - vals[j] = float(np.mean(diffs)) if diffs else 0.0 - - vals = np.clip(vals, a_min=0.0, a_max=None) - total = float(vals.sum()) - if total > 0: - vals = vals / total - return vals - - -def render_importance_chart(values: np.ndarray, save_path: Path) -> None: - from matplotlib.colors import LinearSegmentedColormap - - keep = values >= 5e-4 - if not bool(np.any(keep)): - keep = np.ones_like(values, dtype=bool) - kept_feats = [FEATURES[i] for i in range(len(FEATURES)) if keep[i]] - kept_vals = values[keep] - - order = np.argsort(kept_vals) - sorted_feats = [kept_feats[k] for k in order] - sorted_vals = kept_vals[order] - n = len(sorted_vals) - - fig, ax = plt.subplots(figsize=(9, max(3.0, 0.62 * n + 1.6))) - cmap = LinearSegmentedColormap.from_list("brand", ["#7fb2e6", "#005EB8", "#0c4188"]) - colors = cmap(np.linspace(0.15, 1.0, n)) if n else None - y_pos = np.arange(n) - bars = ax.barh(y_pos, sorted_vals, color=colors, height=0.66, edgecolor="white", linewidth=0.8, zorder=3) - - font_kwargs = chinese_font_kwargs() - ax.set_xlabel("相对重要性", fontsize=11, color="#475569", **font_kwargs) - ax.set_title("模型输入因素重要性排序", fontsize=15, fontweight="bold", color="#0f172a", pad=14, **font_kwargs) - ax.set_yticks(y_pos) - ax.set_yticklabels(sorted_feats, **font_kwargs) - ax.grid(axis="x", color="#e2e8f0", linewidth=1, zorder=0) - ax.set_axisbelow(True) - for spine in ("top", "right", "left"): - ax.spines[spine].set_visible(False) - ax.spines["bottom"].set_color("#cbd5e1") - ax.tick_params(axis="y", length=0, labelsize=11) - ax.tick_params(axis="x", colors="#94a3b8", labelsize=9) - if CHINESE_FONT_PROP: - for label in [*ax.get_yticklabels(), *ax.get_xticklabels()]: - label.set_fontproperties(CHINESE_FONT_PROP) - - max_val = float(sorted_vals.max()) if n else 0.0 - for bar, value in zip(bars, sorted_vals): - ax.text( - bar.get_width() + max_val * 0.012, - bar.get_y() + bar.get_height() / 2, - f"{value:.1%}", - va="center", - ha="left", - fontsize=10, - fontweight="bold", - color="#1e293b", - **font_kwargs, - ) - if max_val > 0: - ax.set_xlim(0, max_val * 1.18) - - fig.tight_layout() - fig.savefig(save_path, dpi=160, bbox_inches="tight") - plt.close(fig) - - def run_prediction(uploaded: FileStorage, user_id: int, model) -> PredictionArtifacts: original_filename = uploaded.filename or "" if not original_filename: @@ -409,15 +436,6 @@ def run_prediction(uploaded: FileStorage, user_id: int, model) -> PredictionArti image_path = IMAGE_DIR / image_filename summary_rows, summary_sheet_rows = render_survival_chart(df, curves, image_path) - importance_filename = None - try: - importance_values = compute_feature_importance(model, x_test) - if importance_values is not None: - importance_filename = f"importance_{user_id}_{run_id}.png" - render_importance_chart(importance_values, IMAGE_DIR / importance_filename) - except Exception as exc: - logging.exception("生成特征重要性图失败: %s", exc) - safe_stem = Path(saved_filename).stem excel_path = user_dir / f"{safe_stem}_pre.xlsx" write_prediction_workbook(excel_path, curves, summary_rows, summary_sheet_rows) @@ -427,7 +445,6 @@ def run_prediction(uploaded: FileStorage, user_id: int, model) -> PredictionArti excel_path=excel_path, image_path=image_path, image_filename=image_filename, - importance_filename=importance_filename, sample_count=len(summary_rows), summary_rows=summary_rows, analysis_text=make_analysis_text(summary_rows), @@ -441,13 +458,17 @@ def render_survival_chart(df: pd.DataFrame, curves, image_path: Path) -> tuple[l plt.figure(figsize=(10, 5.6)) summary_rows: list[dict[str, Any]] = [] summary_sheet_rows: list[dict[str, Any]] = [] + display_note = f"说明:图中仅展示前{CHART_DISPLAY_LIMIT}条管道的示例数据,不足{CHART_DISPLAY_LIMIT}条则全部展示;完整结果请下载电子表格。" for i, curve in enumerate(curves): times = [float(x) for x in list(curve.x)] probs = [float(y) for y in list(curve.y)] pipe_id = normalize_id_value(df.iloc[i][ID_COLUMN], f"Pipe_{i+1:03d}") - pipe_age = f"{df.iloc[i][PIPE_AGE_COLUMN]} 年" if PIPE_AGE_COLUMN in df.columns and pd.notna(df.iloc[i][PIPE_AGE_COLUMN]) else "-" - health_probability = interpolate_probability(times, probs, 10) + raw_pipe_age = df.iloc[i][PIPE_AGE_COLUMN] if PIPE_AGE_COLUMN in df.columns else None + pipe_age_value = float(raw_pipe_age) if pd.notna(raw_pipe_age) else 0.0 + pipe_age = f"{raw_pipe_age} 年" if pd.notna(raw_pipe_age) else "-" + health_probability = interpolate_probability(times, probs, pipe_age_value) + health_risk = 1.0 - health_probability remaining_life = estimate_remaining_life(times, probs) grade_label, grade_desc, grade_class = grade_info(health_probability) @@ -456,6 +477,7 @@ def render_survival_chart(df: pd.DataFrame, curves, image_path: Path) -> tuple[l "pipe_id": pipe_id, "pipe_age": pipe_age, "health_probability": health_probability, + "health_risk": health_risk, "remaining_life": remaining_life, "grade_label": grade_label, "grade_desc": grade_desc, @@ -466,23 +488,25 @@ def render_survival_chart(df: pd.DataFrame, curves, image_path: Path) -> tuple[l { ID_COLUMN: pipe_id, PIPE_AGE_COLUMN: pipe_age, - "健康等级": grade_label, + "健康风险值": health_risk, } ) - plt.step(times, probs, where="post", linewidth=2, label=pipe_id) + if i < CHART_DISPLAY_LIMIT: + plt.step(times, probs, where="post", linewidth=2, label=pipe_id) font_kwargs = chinese_font_kwargs() plt.xlabel("管龄(年)", **font_kwargs) plt.ylabel("健康风险", **font_kwargs) - plt.title("预测分析图", **font_kwargs) + plt.title("管道的剩余寿命分析图", **font_kwargs) + plt.figtext(0.5, 0.02, display_note, ha="center", fontsize=9, color="#475569", **font_kwargs) plt.grid(alpha=0.18) - if len(summary_rows) <= 12: + if min(len(summary_rows), CHART_DISPLAY_LIMIT) <= 12: plt.legend(loc="best", fontsize=8, prop=CHINESE_FONT_PROP) ax = plt.gca() if CHINESE_FONT_PROP: for label in [*ax.get_xticklabels(), *ax.get_yticklabels()]: label.set_fontproperties(CHINESE_FONT_PROP) - plt.tight_layout() + plt.tight_layout(rect=(0, 0.07, 1, 1)) plt.savefig(image_path, dpi=160, bbox_inches="tight") plt.close() return summary_rows, summary_sheet_rows @@ -511,7 +535,7 @@ def write_prediction_workbook( ] with pd.ExcelWriter(excel_path, engine="openpyxl") as writer: - summary_df = pd.DataFrame(summary_sheet_rows, columns=[ID_COLUMN, PIPE_AGE_COLUMN, "健康等级"]) + summary_df = pd.DataFrame(summary_sheet_rows, columns=[ID_COLUMN, PIPE_AGE_COLUMN, "健康风险值"]) sample_df = pd.DataFrame(sample_data_rows, columns=sample_columns) if ID_COLUMN in summary_df.columns: summary_df[ID_COLUMN] = summary_df[ID_COLUMN].astype("string") @@ -520,6 +544,9 @@ def write_prediction_workbook( sample_df.to_excel(writer, sheet_name="样本数据", index=False) sample_worksheet = writer.book["样本数据"] + summary_worksheet = writer.book["结果摘要"] + for cell in summary_worksheet["C"][1:]: + cell.number_format = "0.0%" sample_worksheet.freeze_panes = "A2" sample_worksheet.auto_filter.ref = sample_worksheet.dimensions sample_worksheet.column_dimensions["A"].width = 12 diff --git a/app/routes.py b/app/routes.py index 20a3ebe..54004dd 100644 --- a/app/routes.py +++ b/app/routes.py @@ -130,16 +130,10 @@ def password_reset_users(): def prediction_result_payload(artifacts, record: UploadRecord) -> dict: image_url = url_for("static", filename=f"images/{artifacts.image_filename}") - importance_url = ( - url_for("static", filename=f"images/{artifacts.importance_filename}") - if artifacts.importance_filename - else None - ) return { "original_filename": artifacts.original_filename, "generated_at": format_app_datetime(record.upload_time), "image_url": image_url, - "importance_url": importance_url, "excel_url": url_for("main.download_file", record_id=record.id, file_type="prediction"), "result_url": url_for("main.result_page"), "sample_count": int(artifacts.sample_count), @@ -439,7 +433,6 @@ def predict(): { "message": "预测成功", "image_url": last_result["image_url"], - "importance_url": last_result["importance_url"], "excel_url": last_result["excel_url"], "result_url": last_result["result_url"], "sample_count": last_result["sample_count"], diff --git a/example.xlsx b/example.xlsx index f3827962cd937715826297ba5ef49dcfef230bbf..6566ace4383f6ff8517bc4ca00d8fcda3255d57c 100644 GIT binary patch literal 36183 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 literal 32492 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� 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:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem*var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.divide-line>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(226 232 240/var(--tw-divide-opacity,1))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-amber-100{--tw-border-opacity:1;border-color:rgb(254 243 199/var(--tw-border-opacity,1))}.border-blue-100{--tw-border-opacity:1;border-color:rgb(219 234 254/var(--tw-border-opacity,1))}.border-blue-200{--tw-border-opacity:1;border-color:rgb(191 219 254/var(--tw-border-opacity,1))}.border-line{--tw-border-opacity:1;border-color:rgb(226 232 240/var(--tw-border-opacity,1))}.border-orange-100{--tw-border-opacity:1;border-color:rgb(255 237 213/var(--tw-border-opacity,1))}.border-outline{--tw-border-opacity:1;border-color:rgb(199 206 216/var(--tw-border-opacity,1))}.border-primary{--tw-border-opacity:1;border-color:rgb(0 94 184/var(--tw-border-opacity,1))}.border-red-100{--tw-border-opacity:1;border-color:rgb(254 226 226/var(--tw-border-opacity,1))}.border-red-200{--tw-border-opacity:1;border-color:rgb(254 202 202/var(--tw-border-opacity,1))}.border-red-300{--tw-border-opacity:1;border-color:rgb(252 165 165/var(--tw-border-opacity,1))}.border-slate-200{--tw-border-opacity:1;border-color:rgb(226 232 240/var(--tw-border-opacity,1))}.border-slate-300{--tw-border-opacity:1;border-color:rgb(203 213 225/var(--tw-border-opacity,1))}.border-transparent{border-color:transparent}.bg-\[\#eceff3\]{--tw-bg-opacity:1;background-color:rgb(236 239 243/var(--tw-bg-opacity,1))}.bg-amber-50{--tw-bg-opacity:1;background-color:rgb(255 251 235/var(--tw-bg-opacity,1))}.bg-blue-50{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity,1))}.bg-blueSoft{--tw-bg-opacity:1;background-color:rgb(234 243 255/var(--tw-bg-opacity,1))}.bg-dangerSoft{--tw-bg-opacity:1;background-color:rgb(255 240 240/var(--tw-bg-opacity,1))}.bg-orange-50{--tw-bg-opacity:1;background-color:rgb(255 247 237/var(--tw-bg-opacity,1))}.bg-page{--tw-bg-opacity:1;background-color:rgb(243 245 248/var(--tw-bg-opacity,1))}.bg-primary{--tw-bg-opacity:1;background-color:rgb(0 94 184/var(--tw-bg-opacity,1))}.bg-red-50{--tw-bg-opacity:1;background-color:rgb(254 242 242/var(--tw-bg-opacity,1))}.bg-slate-100{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.bg-slate-50{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity,1))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.bg-white\/95{background-color:hsla(0,0%,100%,.95)}.object-contain{-o-object-fit:contain;object-fit:contain}.p-10{padding:2.5rem}.p-3{padding:.75rem}.p-3\.5{padding:.875rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.px-0{padding-left:0;padding-right:0}.px-16{padding-left:4rem;padding-right:4rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-7{padding-left:1.75rem;padding-right:1.75rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-14{padding-top:3.5rem;padding-bottom:3.5rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-3\.5{padding-top:.875rem;padding-bottom:.875rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pl-11{padding-left:2.75rem}.pr-1{padding-right:.25rem}.pr-12{padding-right:3rem}.pr-4{padding-right:1rem}.pt-0\.5{padding-top:.125rem}.text-left{text-align:left}.text-center{text-align:center}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-5xl{font-size:3rem;line-height:1}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[15px\]{font-size:15px}.text-\[16px\]{font-size:16px}.text-\[18px\]{font-size:18px}.text-\[26px\]{font-size:26px}.text-\[28px\]{font-size:28px}.text-\[32px\]{font-size:32px}.text-\[44px\]{font-size:44px}.text-\[52px\]{font-size:52px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-black{font-weight:900}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.leading-5{line-height:1.25rem}.leading-6{line-height:1.5rem}.leading-7{line-height:1.75rem}.leading-\[1\.5\]{line-height:1.5}.tracking-\[0\.12em\]{letter-spacing:.12em}.tracking-\[0\.18em\]{letter-spacing:.18em}.tracking-tight{letter-spacing:-.025em}.text-amber-600{--tw-text-opacity:1;color:rgb(217 119 6/var(--tw-text-opacity,1))}.text-blue-600{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity,1))}.text-dangerText{--tw-text-opacity:1;color:rgb(220 38 38/var(--tw-text-opacity,1))}.text-orange-600{--tw-text-opacity:1;color:rgb(234 88 12/var(--tw-text-opacity,1))}.text-primary{--tw-text-opacity:1;color:rgb(0 94 184/var(--tw-text-opacity,1))}.text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.text-slate-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity,1))}.text-successText{--tw-text-opacity:1;color:rgb(22 163 74/var(--tw-text-opacity,1))}.text-textMain{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity,1))}.text-textSub{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-white\/50{color:hsla(0,0%,100%,.5)}.text-white\/75{color:hsla(0,0%,100%,.75)}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.shadow-\[0_18px_45px_rgba\(15\2c 23\2c 42\2c \.16\)\]{--tw-shadow:0 18px 45px rgba(15,23,42,.16);--tw-shadow-colored:0 18px 45px var(--tw-shadow-color)}.shadow-\[0_18px_45px_rgba\(15\2c 23\2c 42\2c \.16\)\],.shadow-panel{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-panel{--tw-shadow:0 1px 2px rgba(15,23,42,.04);--tw-shadow-colored:0 1px 2px var(--tw-shadow-color)}.outline{outline-style:solid}.ring-4{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-red-100{--tw-ring-opacity:1;--tw-ring-color:rgb(254 226 226/var(--tw-ring-opacity,1))}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}@keyframes spin{to{transform:rotate(1turn)}}.hover\:border-primary:hover{--tw-border-opacity:1;border-color:rgb(0 94 184/var(--tw-border-opacity,1))}.hover\:bg-blue-50\/50:hover{background-color:rgba(239,246,255,.5)}.hover\:bg-slate-100:hover{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.hover\:bg-slate-50:hover{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity,1))}.hover\:text-primary:hover{--tw-text-opacity:1;color:rgb(0 94 184/var(--tw-text-opacity,1))}.hover\:text-primaryDeep:hover{--tw-text-opacity:1;color:rgb(12 65 136/var(--tw-text-opacity,1))}.hover\:text-slate-700:hover{--tw-text-opacity:1;color:rgb(51 65 85/var(--tw-text-opacity,1))}.focus\:border-primary:focus{--tw-border-opacity:1;border-color:rgb(0 94 184/var(--tw-border-opacity,1))}.focus\:ring-0:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-primary:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(0 94 184/var(--tw-ring-opacity,1))}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-slate-100:disabled{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.disabled\:text-slate-400:disabled{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}@media (min-width:640px){.sm\:left-12{left:3rem}.sm\:right-12{right:3rem}.sm\:top-24{top:6rem}.sm\:inline{display:inline}.sm\:flex{display:flex}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:items-start{align-items:flex-start}.sm\:items-center{align-items:center}.sm\:justify-between{justify-content:space-between}.sm\:p-6{padding:1.5rem}.sm\:px-12{padding-left:3rem;padding-right:3rem}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:text-4xl{font-size:2.25rem;line-height:2.5rem}}@media (min-width:768px){.md\:flex{display:flex}.md\:hidden{display:none}.md\:w-auto{width:auto}.md\:grid-cols-\[minmax\(0\2c 1fr\)_auto\]{grid-template-columns:minmax(0,1fr) auto}.md\:flex-nowrap{flex-wrap:nowrap}.md\:items-center{align-items:center}.md\:px-14{padding-left:3.5rem;padding-right:3.5rem}}@media (min-width:1024px){.lg\:col-start-1{grid-column-start:1}.lg\:col-start-2{grid-column-start:2}.lg\:row-start-1{grid-row-start:1}.lg\:row-start-2{grid-row-start:2}.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:grid-cols-\[1\.4fr_1fr\]{grid-template-columns:1.4fr 1fr}.lg\:grid-cols-\[minmax\(0\2c 1fr\)_360px\]{grid-template-columns:minmax(0,1fr) 360px}.lg\:flex-row{flex-direction:row}.lg\:items-end{align-items:flex-end}.lg\:justify-between{justify-content:space-between}.lg\:px-8{padding-left:2rem;padding-right:2rem}.lg\:py-8{padding-top:2rem;padding-bottom:2rem}.lg\:text-\[40px\]{font-size:40px}}@media (min-width:1280px){.xl\:left-auto{left:auto}.xl\:right-auto{right:auto}.xl\:w-\[320px\]{width:320px}} \ No newline at end of file +/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}input:where(:not([type])),input:where([type=date]),input:where([type=datetime-local]),input:where([type=email]),input:where([type=month]),input:where([type=number]),input:where([type=password]),input:where([type=search]),input:where([type=tel]),input:where([type=text]),input:where([type=time]),input:where([type=url]),input:where([type=week]),select,select:where([multiple]),textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow:0 0 #0000}input:where(:not([type])):focus,input:where([type=date]):focus,input:where([type=datetime-local]):focus,input:where([type=email]):focus,input:where([type=month]):focus,input:where([type=number]):focus,input:where([type=password]):focus,input:where([type=search]):focus,input:where([type=tel]):focus,input:where([type=text]):focus,input:where([type=time]):focus,input:where([type=url]):focus,input:where([type=week]):focus,select:focus,select:where([multiple]):focus,textarea:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#2563eb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-meridiem-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-year-field{padding-top:0;padding-bottom:0}select{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}select:where([multiple]),select:where([size]:not([size="1"])){background-image:none;background-position:0 0;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}input:where([type=checkbox]),input:where([type=radio]){-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#2563eb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow:0 0 #0000}input:where([type=checkbox]){border-radius:0}input:where([type=radio]){border-radius:100%}input:where([type=checkbox]):focus,input:where([type=radio]):focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}input:where([type=checkbox]):checked,input:where([type=radio]):checked{border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}input:where([type=checkbox]):checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0'/%3E%3C/svg%3E")}@media (forced-colors:active) {input:where([type=checkbox]):checked{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}input:where([type=radio]):checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E")}@media (forced-colors:active) {input:where([type=radio]):checked{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}input:where([type=checkbox]):checked:focus,input:where([type=checkbox]):checked:hover,input:where([type=radio]):checked:focus,input:where([type=radio]):checked:hover{border-color:transparent;background-color:currentColor}input:where([type=checkbox]):indeterminate{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E");border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}@media (forced-colors:active) {input:where([type=checkbox]):indeterminate{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}input:where([type=checkbox]):indeterminate:focus,input:where([type=checkbox]):indeterminate:hover{border-color:transparent;background-color:currentColor}input:where([type=file]){background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}input:where([type=file]):focus{outline:1px solid ButtonText;outline:1px auto -webkit-focus-ring-color}body,h1,h2,h3,h4{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.material-symbols-outlined{font-family:Material Symbols Outlined;font-weight:400;font-style:normal;font-size:24px;letter-spacing:normal;text-transform:none;width:1em;height:1em;min-width:1em;flex:0 0 auto;overflow:hidden;word-wrap:normal;direction:ltr;vertical-align:middle;font-variation-settings:"FILL" 0,"wght" 400,"GRAD" 0,"opsz" 24}.material-symbols-outlined,.ui-btn{line-height:1;display:inline-flex;align-items:center;justify-content:center;white-space:nowrap}.ui-btn{box-sizing:border-box;min-height:44px;height:44px;gap:.5rem;border-radius:.375rem;border:1px solid transparent;padding:0 1rem;font-size:.875rem;font-weight:700;transition:background-color .15s ease,border-color .15s ease,color .15s ease,box-shadow .15s ease}.ui-btn-lg{min-height:52px;height:52px;font-size:.875rem}.ui-btn-sm{min-height:40px;height:40px;padding:0 .75rem}.ui-btn-compact{min-height:34px;height:34px;padding:0 .65rem;gap:.35rem;font-size:.8125rem}.ui-btn-field{min-height:50px;height:50px}.ui-btn-primary{background:#005eb8;color:#fff;box-shadow:0 18px 34px rgba(15,23,42,.06)}.ui-btn-primary:hover{background:#0c4188}.ui-btn-secondary{border-color:#e2e8f0;background:#fff;color:#334155;box-shadow:0 1px 2px rgba(15,23,42,.04)}.ui-btn-secondary:hover{border-color:#005eb8;color:#005eb8}.ui-btn:disabled,.ui-btn[aria-disabled=true]{cursor:not-allowed;box-shadow:none;opacity:.7}.ui-btn-primary:disabled{background:#cbd5e1}.ui-btn .material-symbols-outlined,.ui-btn-icon{width:20px;height:20px;flex:0 0 20px;font-size:20px}.ui-icon-btn{display:inline-flex;width:28px;height:28px;flex:0 0 28px;justify-content:center;transition:background-color .15s ease,color .15s ease}.ui-action-row,.ui-icon-btn{box-sizing:border-box;align-items:center;border-radius:.375rem;line-height:1}.ui-action-row{display:flex;min-height:44px;justify-content:space-between;gap:.75rem;border:1px solid #e2e8f0;padding:0 .75rem;font-size:.875rem;font-weight:700;transition:border-color .15s ease,color .15s ease}.ui-action-row:hover{border-color:#005eb8;color:#005eb8}.spinner{display:inline-flex;width:20px;height:20px;flex:0 0 20px;border-radius:9999px;border:2px solid hsla(0,0%,100%,.35);border-top-color:#fff;animation:spin .75s linear infinite}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.left-1\/2{left:50%}.left-4{left:1rem}.left-7{left:1.75rem}.right-7{right:1.75rem}.top-0{top:0}.top-1\/2{top:50%}.top-20{top:5rem}.top-6{top:1.5rem}.z-30{z-index:30}.z-50{z-index:50}.order-1{order:1}.order-2{order:2}.order-3{order:3}.order-4{order:4}.mx-auto{margin-left:auto;margin-right:auto}.-mr-1{margin-right:-.25rem}.-mt-1{margin-top:-.25rem}.mb-10{margin-bottom:2.5rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.mb-7{margin-bottom:1.75rem}.mb-8{margin-bottom:2rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.block{display:block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-10{height:2.5rem}.h-14{height:3.5rem}.h-16{height:4rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-\[460px\]{height:460px}.h-\[50px\]{height:50px}.h-\[520px\]{height:520px}.h-\[710px\]{height:710px}.h-\[900px\]{height:900px}.h-\[calc\(100vh-230px\)\]{height:calc(100vh - 230px)}.h-full{height:100%}.h-px{height:1px}.max-h-full{max-height:100%}.min-h-0{min-height:0}.min-h-\[360px\]{min-height:360px}.min-h-\[520px\]{min-height:520px}.min-h-\[560px\]{min-height:560px}.min-h-\[620px\]{min-height:620px}.min-h-\[76px\]{min-height:76px}.min-h-screen{min-height:100vh}.w-14{width:3.5rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-\[calc\(100vw-2rem\)\]{width:calc(100vw - 2rem)}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.w-px{width:1px}.min-w-0{min-width:0}.min-w-10{min-width:2.5rem}.min-w-\[150px\]{min-width:150px}.min-w-full{min-width:100%}.max-w-3xl{max-width:48rem}.max-w-7xl{max-width:80rem}.max-w-\[120px\]{max-width:120px}.max-w-\[360px\]{max-width:360px}.max-w-\[420px\]{max-width:420px}.max-w-\[430px\]{max-width:430px}.max-w-\[440px\]{max-width:440px}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.translate-y-0{--tw-translate-y:0px}.translate-y-0,.translate-y-3{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-3{--tw-translate-y:0.75rem}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.resize{resize:both}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-\[1fr_92px_44px\]{grid-template-columns:1fr 92px 44px}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-5{gap:1.25rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem*var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.divide-line>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(226 232 240/var(--tw-divide-opacity,1))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-amber-100{--tw-border-opacity:1;border-color:rgb(254 243 199/var(--tw-border-opacity,1))}.border-blue-100{--tw-border-opacity:1;border-color:rgb(219 234 254/var(--tw-border-opacity,1))}.border-blue-200{--tw-border-opacity:1;border-color:rgb(191 219 254/var(--tw-border-opacity,1))}.border-line{--tw-border-opacity:1;border-color:rgb(226 232 240/var(--tw-border-opacity,1))}.border-orange-100{--tw-border-opacity:1;border-color:rgb(255 237 213/var(--tw-border-opacity,1))}.border-outline{--tw-border-opacity:1;border-color:rgb(199 206 216/var(--tw-border-opacity,1))}.border-primary{--tw-border-opacity:1;border-color:rgb(0 94 184/var(--tw-border-opacity,1))}.border-red-100{--tw-border-opacity:1;border-color:rgb(254 226 226/var(--tw-border-opacity,1))}.border-red-200{--tw-border-opacity:1;border-color:rgb(254 202 202/var(--tw-border-opacity,1))}.border-red-300{--tw-border-opacity:1;border-color:rgb(252 165 165/var(--tw-border-opacity,1))}.border-slate-200{--tw-border-opacity:1;border-color:rgb(226 232 240/var(--tw-border-opacity,1))}.border-slate-300{--tw-border-opacity:1;border-color:rgb(203 213 225/var(--tw-border-opacity,1))}.border-transparent{border-color:transparent}.bg-\[\#eceff3\]{--tw-bg-opacity:1;background-color:rgb(236 239 243/var(--tw-bg-opacity,1))}.bg-amber-50{--tw-bg-opacity:1;background-color:rgb(255 251 235/var(--tw-bg-opacity,1))}.bg-blue-50{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity,1))}.bg-blueSoft{--tw-bg-opacity:1;background-color:rgb(234 243 255/var(--tw-bg-opacity,1))}.bg-dangerSoft{--tw-bg-opacity:1;background-color:rgb(255 240 240/var(--tw-bg-opacity,1))}.bg-orange-50{--tw-bg-opacity:1;background-color:rgb(255 247 237/var(--tw-bg-opacity,1))}.bg-page{--tw-bg-opacity:1;background-color:rgb(243 245 248/var(--tw-bg-opacity,1))}.bg-primary{--tw-bg-opacity:1;background-color:rgb(0 94 184/var(--tw-bg-opacity,1))}.bg-red-50{--tw-bg-opacity:1;background-color:rgb(254 242 242/var(--tw-bg-opacity,1))}.bg-slate-100{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.bg-slate-50{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity,1))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.bg-white\/95{background-color:hsla(0,0%,100%,.95)}.object-contain{-o-object-fit:contain;object-fit:contain}.p-10{padding:2.5rem}.p-3{padding:.75rem}.p-3\.5{padding:.875rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.px-0{padding-left:0;padding-right:0}.px-16{padding-left:4rem;padding-right:4rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-7{padding-left:1.75rem;padding-right:1.75rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-14{padding-top:3.5rem;padding-bottom:3.5rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-3\.5{padding-top:.875rem;padding-bottom:.875rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pl-11{padding-left:2.75rem}.pr-12{padding-right:3rem}.pr-4{padding-right:1rem}.pt-0\.5{padding-top:.125rem}.text-left{text-align:left}.text-center{text-align:center}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-5xl{font-size:3rem;line-height:1}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[15px\]{font-size:15px}.text-\[16px\]{font-size:16px}.text-\[18px\]{font-size:18px}.text-\[26px\]{font-size:26px}.text-\[28px\]{font-size:28px}.text-\[32px\]{font-size:32px}.text-\[44px\]{font-size:44px}.text-\[52px\]{font-size:52px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-black{font-weight:900}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.leading-5{line-height:1.25rem}.leading-6{line-height:1.5rem}.leading-7{line-height:1.75rem}.leading-\[1\.5\]{line-height:1.5}.tracking-\[0\.12em\]{letter-spacing:.12em}.tracking-\[0\.18em\]{letter-spacing:.18em}.tracking-tight{letter-spacing:-.025em}.text-amber-600{--tw-text-opacity:1;color:rgb(217 119 6/var(--tw-text-opacity,1))}.text-blue-600{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity,1))}.text-dangerText{--tw-text-opacity:1;color:rgb(220 38 38/var(--tw-text-opacity,1))}.text-orange-600{--tw-text-opacity:1;color:rgb(234 88 12/var(--tw-text-opacity,1))}.text-primary{--tw-text-opacity:1;color:rgb(0 94 184/var(--tw-text-opacity,1))}.text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.text-slate-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity,1))}.text-successText{--tw-text-opacity:1;color:rgb(22 163 74/var(--tw-text-opacity,1))}.text-textMain{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity,1))}.text-textSub{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-white\/50{color:hsla(0,0%,100%,.5)}.text-white\/75{color:hsla(0,0%,100%,.75)}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.shadow-\[0_18px_45px_rgba\(15\2c 23\2c 42\2c \.16\)\]{--tw-shadow:0 18px 45px rgba(15,23,42,.16);--tw-shadow-colored:0 18px 45px var(--tw-shadow-color)}.shadow-\[0_18px_45px_rgba\(15\2c 23\2c 42\2c \.16\)\],.shadow-panel{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-panel{--tw-shadow:0 1px 2px rgba(15,23,42,.04);--tw-shadow-colored:0 1px 2px var(--tw-shadow-color)}.outline{outline-style:solid}.ring-4{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-red-100{--tw-ring-opacity:1;--tw-ring-color:rgb(254 226 226/var(--tw-ring-opacity,1))}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}@keyframes spin{to{transform:rotate(1turn)}}.hover\:border-primary:hover{--tw-border-opacity:1;border-color:rgb(0 94 184/var(--tw-border-opacity,1))}.hover\:bg-blue-50\/50:hover{background-color:rgba(239,246,255,.5)}.hover\:bg-slate-100:hover{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.hover\:bg-slate-50:hover{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity,1))}.hover\:text-primary:hover{--tw-text-opacity:1;color:rgb(0 94 184/var(--tw-text-opacity,1))}.hover\:text-primaryDeep:hover{--tw-text-opacity:1;color:rgb(12 65 136/var(--tw-text-opacity,1))}.hover\:text-slate-700:hover{--tw-text-opacity:1;color:rgb(51 65 85/var(--tw-text-opacity,1))}.focus\:border-primary:focus{--tw-border-opacity:1;border-color:rgb(0 94 184/var(--tw-border-opacity,1))}.focus\:ring-0:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-primary:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(0 94 184/var(--tw-ring-opacity,1))}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-slate-100:disabled{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.disabled\:text-slate-400:disabled{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}@media (min-width:640px){.sm\:left-12{left:3rem}.sm\:right-12{right:3rem}.sm\:top-24{top:6rem}.sm\:inline{display:inline}.sm\:flex{display:flex}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:items-start{align-items:flex-start}.sm\:items-center{align-items:center}.sm\:justify-between{justify-content:space-between}.sm\:p-6{padding:1.5rem}.sm\:px-12{padding-left:3rem;padding-right:3rem}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:text-4xl{font-size:2.25rem;line-height:2.5rem}}@media (min-width:768px){.md\:flex{display:flex}.md\:hidden{display:none}.md\:w-auto{width:auto}.md\:grid-cols-\[minmax\(0\2c 1fr\)_auto\]{grid-template-columns:minmax(0,1fr) auto}.md\:flex-nowrap{flex-wrap:nowrap}.md\:items-center{align-items:center}.md\:px-14{padding-left:3.5rem;padding-right:3.5rem}}@media (min-width:1024px){.lg\:col-start-1{grid-column-start:1}.lg\:col-start-2{grid-column-start:2}.lg\:row-start-1{grid-row-start:1}.lg\:row-start-2{grid-row-start:2}.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:grid-cols-\[1\.4fr_1fr\]{grid-template-columns:1.4fr 1fr}.lg\:grid-cols-\[minmax\(0\2c 1fr\)_360px\]{grid-template-columns:minmax(0,1fr) 360px}.lg\:flex-row{flex-direction:row}.lg\:items-end{align-items:flex-end}.lg\:justify-between{justify-content:space-between}.lg\:px-8{padding-left:2rem;padding-right:2rem}.lg\:py-8{padding-top:2rem;padding-bottom:2rem}.lg\:text-\[40px\]{font-size:40px}}@media (min-width:1280px){.xl\:left-auto{left:auto}.xl\:right-auto{right:auto}.xl\:w-\[320px\]{width:320px}} \ No newline at end of file diff --git a/static/js/dashboard.js b/static/js/dashboard.js index 12db5f4..3a36d5d 100644 --- a/static/js/dashboard.js +++ b/static/js/dashboard.js @@ -15,8 +15,6 @@ const inlineResult = document.getElementById('inlineResult'); const resultPlaceholder = document.getElementById('resultPlaceholder'); const resultContent = document.getElementById('resultContent'); const resultImage = document.getElementById('resultImage'); -const resultImportanceWrap = document.getElementById('resultImportanceWrap'); -const resultImportanceImage = document.getElementById('resultImportanceImage'); const excelBtn = document.getElementById('excelBtn'); const resultPageBtn = document.getElementById('resultPageBtn'); let selectedFile = null; @@ -69,13 +67,6 @@ function updateSelectedFile(file) { function renderResult(data) { resultImage.src = data.image_url; - if (data.importance_url) { - resultImportanceImage.src = data.importance_url; - resultImportanceWrap.classList.remove('hidden'); - } else { - resultImportanceWrap.classList.add('hidden'); - resultImportanceImage.removeAttribute('src'); - } excelBtn.href = data.excel_url; resultPageBtn.href = data.result_url; resultPlaceholder.classList.add('hidden'); diff --git a/templates/home.html b/templates/home.html index 77b3ec8..15727cf 100644 --- a/templates/home.html +++ b/templates/home.html @@ -7,7 +7,7 @@

管道健康状态与剩余寿命评估

-

上传标准数据文件,系统将生成生存概率曲线、健康等级摘要、剩余寿命判断和电子表格预测报告。

+

上传标准数据文件,系统将生成管道的剩余寿命分析图、健康等级摘要、剩余寿命判断和电子表格预测报告。

download @@ -59,7 +59,7 @@
monitoring
暂无预测结果
-
完成一次分析后,将生成生存概率阶梯图、摘要和电子表格报告。
+
完成一次分析后,将生成管道的剩余寿命分析图、摘要和电子表格报告。
@@ -81,15 +81,11 @@ -
-
-
-
生存概率阶梯图
- 预测图 -
-
© {{ now_year() }} 供水管道健康评估系统
diff --git a/templates/result.html b/templates/result.html index 08ca52a..3cfd0ae 100644 --- a/templates/result.html +++ b/templates/result.html @@ -23,25 +23,21 @@
-
- {% else %}
diff --git a/tests/test_prediction.py b/tests/test_prediction.py index 15e8727..0156937 100644 --- a/tests/test_prediction.py +++ b/tests/test_prediction.py @@ -7,8 +7,10 @@ from unittest.mock import patch import pandas as pd from openpyxl import load_workbook +from openpyxl import Workbook from app.prediction import ( + CHART_DISPLAY_LIMIT, FEATURES, ID_COLUMN, INPUT_COLUMNS, @@ -70,7 +72,8 @@ class PredictionHelpersTest(unittest.TestCase): worksheet = workbook["Template"] headers = [cell.value for cell in next(worksheet.iter_rows(min_row=1, max_row=1))] - self.assertEqual(headers, INPUT_COLUMNS) + self.assertEqual(len(headers), len(INPUT_COLUMNS)) + self.assertEqual(set(headers), set(INPUT_COLUMNS)) def test_read_input_file_preserves_text_pipe_ids(self) -> None: with TemporaryDirectory() as temp_dir: @@ -81,6 +84,36 @@ class PredictionHelpersTest(unittest.TestCase): self.assertEqual(df[ID_COLUMN].tolist(), ["00123"]) + def test_read_input_file_calculates_defects_from_template_detail_sheet(self) -> None: + with TemporaryDirectory() as temp_dir: + output_path = Path(temp_dir) / "input.xlsx" + workbook = Workbook() + template = workbook.active + template.title = "Template" + template.append(INPUT_COLUMNS) + template.append(["001", 5, 0, 5, 1, 100, 1.2, 0.4, 20, 800, 1, "=缺陷计算!E2", "=缺陷计算!J2"]) + + detail = workbook.create_sheet("缺陷计算") + detail.append([ + ID_COLUMN, + "泄漏\n权重0.5", + "腐蚀\n权重0.4", + "管瘤\n权重0.1", + "结构性缺陷值", + "气囊\n权重0.5", + "杂质\n权重0.2", + "异物\n权重0.2", + "不明连接\n权重0.1", + "功能性缺陷值", + ]) + detail.append(["001", "严重", "中度", "轻度", None, "轻度", "无", "中度", "严重", None]) + workbook.save(output_path) + + df = read_input_file(output_path, ".xlsx") + + self.assertAlmostEqual(float(df.loc[0, "结构缺陷"]), 3.8) + self.assertAlmostEqual(float(df.loc[0, "功能缺陷"]), 1.6) + def test_prepare_model_features_maps_material_aliases_to_codes(self) -> None: rows = [] for value in ["镀锌", "2-钢塑", 13]: @@ -110,8 +143,8 @@ class PredictionHelpersTest(unittest.TestCase): ] summary_rows = [{"pipe_id": "P001"}, {"pipe_id": "P002"}] summary_sheet_rows = [ - {ID_COLUMN: "P001", PIPE_AGE_COLUMN: "10 年", "健康概率": 0.7, "预计剩余寿命": 2.0, "健康等级": "IV级"}, - {ID_COLUMN: "P002", PIPE_AGE_COLUMN: "12 年", "健康概率": 0.6, "预计剩余寿命": 1.5, "健康等级": "III级"}, + {ID_COLUMN: "P001", PIPE_AGE_COLUMN: "10 年", "健康风险值": 0.3}, + {ID_COLUMN: "P002", PIPE_AGE_COLUMN: "12 年", "健康风险值": 0.4}, ] with TemporaryDirectory() as temp_dir: @@ -122,7 +155,7 @@ class PredictionHelpersTest(unittest.TestCase): self.assertEqual(workbook.sheet_names, ["结果摘要", "样本数据"]) summary_data = pd.read_excel(output_path, sheet_name="结果摘要") - self.assertEqual(summary_data.columns.tolist(), [ID_COLUMN, PIPE_AGE_COLUMN, "健康等级"]) + self.assertEqual(summary_data.columns.tolist(), [ID_COLUMN, PIPE_AGE_COLUMN, "健康风险值"]) sample_data = pd.read_excel(output_path, sheet_name="样本数据") self.assertEqual(sample_data.columns.tolist(), ["管龄(年)", "P001", "P002"]) @@ -140,7 +173,7 @@ class PredictionHelpersTest(unittest.TestCase): def test_prediction_workbook_writes_pipe_ids_as_excel_text(self) -> None: curves = [DummyCurve([1], [0.9])] summary_rows = [{"pipe_id": "00123"}] - summary_sheet_rows = [{ID_COLUMN: "00123", PIPE_AGE_COLUMN: "10 年", "健康等级": "V级"}] + summary_sheet_rows = [{ID_COLUMN: "00123", PIPE_AGE_COLUMN: "10 年", "健康风险值": 0.1}] with TemporaryDirectory() as temp_dir: output_path = Path(temp_dir) / "prediction.xlsx" @@ -161,13 +194,45 @@ class PredictionHelpersTest(unittest.TestCase): with TemporaryDirectory() as temp_dir: output_path = Path(temp_dir) / "chart.png" - with patch("app.prediction.plt.xlabel") as xlabel, patch("app.prediction.plt.ylabel") as ylabel: - render_survival_chart(df, [DummyCurve([1, 2], [0.9, 0.7])], output_path) + with ( + patch("app.prediction.plt.xlabel") as xlabel, + patch("app.prediction.plt.ylabel") as ylabel, + patch("app.prediction.plt.figtext") as figtext, + patch("app.prediction.plt.title") as title, + ): + summary_rows, _ = render_survival_chart(df, [DummyCurve([1, 10, 12], [0.9, 0.7, 0.4])], output_path) + + self.assertAlmostEqual(summary_rows[0]["health_probability"], 0.4) + self.assertAlmostEqual(summary_rows[0]["health_risk"], 0.6) + self.assertEqual(summary_rows[0]["grade_label"], "II级") xlabel.assert_called_once() self.assertEqual(xlabel.call_args.args[0], "管龄(年)") ylabel.assert_called_once() self.assertEqual(ylabel.call_args.args[0], "健康风险") + title.assert_called_once() + self.assertEqual(title.call_args.args[0], "管道的剩余寿命分析图") + figtext.assert_called_once() + self.assertIn(f"前{CHART_DISPLAY_LIMIT}条管道的示例数据", figtext.call_args.args[2]) + + def test_survival_chart_only_plots_first_ten_pipes(self) -> None: + sample_count = CHART_DISPLAY_LIMIT + 2 + df = pd.DataFrame( + { + ID_COLUMN: [f"P{i:03d}" for i in range(sample_count)], + PIPE_AGE_COLUMN: [12] * sample_count, + } + ) + curves = [DummyCurve([1, 10, 12], [0.9, 0.7, 0.4]) for _ in range(sample_count)] + + with TemporaryDirectory() as temp_dir: + output_path = Path(temp_dir) / "chart.png" + with patch("app.prediction.plt.step") as step, patch("app.prediction.plt.legend"): + summary_rows, summary_sheet_rows = render_survival_chart(df, curves, output_path) + + self.assertEqual(step.call_count, CHART_DISPLAY_LIMIT) + self.assertEqual(len(summary_rows), sample_count) + self.assertEqual(len(summary_sheet_rows), sample_count) if __name__ == "__main__":