"""物理计算引擎 —— 试压报告的压力与保压时间计算
对标 VBA `Fun_计算压力时间` 模块,提供:
1. Lb 压力等级 → MPa 换算(150Lb→2.0, 300Lb→5.17, 600Lb→10.34)
2. 强度试验压力(按标准号 × 公称压力倍率)
3. 上密封试验压力(按标准号 × 公称压力倍率,止回阀/蝶阀特殊处理)
4. 主密封试验压力(按标准号 × 公称压力倍率)
5. 四种保压时间查表(强度 / 上密封 / 主密封,按标准号 + 口径)
设计原则:
- 纯函数,无副作用,无 DB / 文件 I/O 依赖
- 对标 VBA 逐行语义,不一致处标注差异
- 未匹配标准号 → 返回 None / "≥",不伪造数据
"""
from __future__ import annotations
import math
from collections.abc import Callable
from dataclasses import dataclass, field
from decimal import ROUND_HALF_UP, Decimal
from typing import Any
# ============================================================
# Lb → MPa 换算表(对标 VBA Lb2MPa() 第14-54行)
# ============================================================
# VBA 原文仅实现 150/300/600 三档,其余为空白占位(Case Else → Stop)。
# CertFlow 按 config.yaml sales_plan.pn_convert.lb_to_mpa 可扩展;
# 此处内置与 PNService.LB_TO_MPA_MAP 保持一致,避免重复维护。
LB_TO_MPA: dict[int, float] = {
150: 2.0,
300: 5.17,
600: 10.34,
800: 13.0,
900: 15.0,
1500: 25.0,
2500: 42.0,
}
[文档]
def lb_to_mpa(lb_level: int) -> float | None:
"""Lb 压力等级 → MPa 数值
Args:
lb_level: 压力等级(150/300/600/800/900/1500/2500)
Returns:
float: MPa 值,未匹配返回 None(VBA 中为 Stop)
"""
return LB_TO_MPA.get(lb_level)
# ============================================================
# 标准号别名归一化映射
# ============================================================
# VBA 使用 UCase(Trim(...)) 后用 Select Case Is = 逐条匹配,
# 大量变体散落在各个 Case 中。此处将所有已知别名归一为规范名。
_STANDARD_ALIASES: dict[str, str] = {
# API 598 系列
"API598": "API 598",
"API598:2009": "API 598",
"API 598-2009": "API 598",
"API 598": "API 598",
# GB/T 13927 系列
"GB/T 13927-2022": "GB/T 13927",
"GB/T 13927-2008": "GB/T 13927",
"GB/T13927": "GB/T 13927",
# GB/T 26480 系列
"GB/T 26480-2011": "GB/T 26480",
"GB/T26480": "GB/T 26480",
# JB/T 9092 系列
"JB/T 9092-1999": "JB/T 9092",
"JB/T9092": "JB/T 9092",
"JB/T9092-1999": "JB/T 9092",
# JB/T 3595 系列
"JB/T 3595-2002": "JB/T 3595",
"JB/T3595": "JB/T 3595",
# GB/T 12465 系列
"GB/T 12465-2007": "GB/T 12465",
"GB/T 12465-2017": "GB/T 12465",
"GB/T12465-2007": "GB/T 12465",
"GB/T12465-2017": "GB/T 12465",
# GB/T 12245 系列(减压阀)
"GB/T 12245-2006": "GB/T 12245",
"GB/T 12245-89": "GB/T 12245",
"GB/T 12245-1989": "GB/T 12245",
"GB/T12245-89": "GB/T 12245",
"GB/T12245-1989": "GB/T 12245",
"GB/T12245-06": "GB/T 12245",
"GB/T12245-2006": "GB/T 12245",
# GB/T 14382 系列
"GB/T 14382-2008": "GB/T 14382",
"GB/T14382": "GB/T 14382",
# GB/T 14478 系列
"GB/T 14478-2012": "GB/T 14478",
"GB/T14478": "GB/T 14478",
# GB/T 12251 系列(蒸汽疏水阀)
"GB/T 12251-2005": "GB/T 12251",
"GB/T 12251-1989": "GB/T 12251",
"GB12251-1989": "GB/T 12251",
# NB/T 47044 系列
"NB/T 47044-2014": "NB/T 47044",
"NB/T47044": "NB/T 47044",
# 其他
"GB12242": "GB 12242",
"SL553-2011": "SL 553",
"SL 553": "SL 553",
"DL/T 5190.5-2019": "DL/T 5190.5",
"DL/T5190.5": "DL/T 5190.5",
"JB/T 7387-1994": "JB/T 7387",
"JB/T7387": "JB/T 7387",
"GB/T 24917-2010": "GB/T 24917",
"JB/T 6446-2004": "JB/T 6446",
"GB/T 10869-2008": "GB/T 10869",
"背压阀外购厂家企业标准": "背压阀外购",
}
def _normalize_standard(standard: str) -> str:
"""将标准号字符串归一化为规范名。
Args:
standard: 原始标准号字符串
Returns:
str: 规范名,未匹配返回原始字符串的 uppercase trim
"""
if not standard:
return ""
key = standard.strip()
# 先尝试精确匹配
if key in _STANDARD_ALIASES:
return _STANDARD_ALIASES[key]
# 再尝试 uppercase 后匹配(VBA 使用 UCase)
key_upper = key.upper()
for alias, canonical in _STANDARD_ALIASES.items():
if alias.upper() == key_upper:
return canonical
return key_upper
# ============================================================
# 数据类定义
# ============================================================
[文档]
@dataclass
class PressureCalcResult:
"""物理计算结果
Attributes:
strength_test_pressure: 强度试验压力(MPa 数值,None 表示无法计算)
strength_test_pressure_display: 强度试验压力显示文本
upper_seal_pressure: 上密封试验压力(None 表示无此项目,如 "/")
upper_seal_pressure_display: 上密封试验压力显示文本
main_seal_pressure: 主密封试验压力
main_seal_pressure_display: 主密封试验压力显示文本
strength_hold_time: 强度保压时间(如 "≥15", "≥60", "≥")
upper_seal_hold_time: 上密封保压时间
main_seal_hold_time: 主密封保压时间
errors: 计算过程中的警告/错误信息列表
"""
strength_test_pressure: float | None = None
strength_test_pressure_display: str = ""
upper_seal_pressure: float | None = None
upper_seal_pressure_display: str = ""
main_seal_pressure: float | None = None
main_seal_pressure_display: str = ""
strength_hold_time: str = "≥"
upper_seal_hold_time: str = "≥"
main_seal_hold_time: str = "≥"
errors: list[str] = field(default_factory=list)
# ============================================================
# 压力计算
# ============================================================
[文档]
class PressureCalcService:
"""物理计算服务 —— 试压报告的压力与保压时间计算
对标 VBA `Fun_计算压力时间` 模块的 7 个函数。
所有方法均为纯函数(无状态、无副作用),可直接用于报告生成管线。
Examples:
>>> svc = PressureCalcService()
>>> result = svc.calculate(PressureCalcInput(
... standard="GB/T 13927-2022",
... nominal_pressure_mpa=2.5,
... caliber_mm=100,
... ))
>>> result.strength_test_pressure
3.75
>>> result.strength_hold_time
'≥60'
"""
# ---- 核心入口 ----
[文档]
def calculate(self, inp: PressureCalcInput) -> PressureCalcResult:
"""一次性计算所有试压参数(压力 + 保压时间)
Args:
inp: 输入参数
Returns:
PressureCalcResult: 完整计算结果
"""
result = PressureCalcResult()
standard_norm = _normalize_standard(inp.standard)
# 压力计算
result.strength_test_pressure = self.calc_strength_pressure(
standard_norm, inp.nominal_pressure_mpa
)
result.strength_test_pressure_display = _format_pressure(result.strength_test_pressure)
result.upper_seal_pressure = self.calc_upper_seal_pressure(
standard_norm,
inp.nominal_pressure_mpa,
inp.is_check_valve,
inp.is_butterfly_valve,
)
result.upper_seal_pressure_display = _format_pressure(
result.upper_seal_pressure, none_marker="/"
)
result.main_seal_pressure = self.calc_main_seal_pressure(
standard_norm,
inp.nominal_pressure_mpa,
inp.is_check_valve,
inp.is_butterfly_valve,
)
result.main_seal_pressure_display = _format_pressure(
result.main_seal_pressure, none_marker=""
)
# 保压时间计算
result.strength_hold_time = self.calc_strength_hold_time(
standard_norm, inp.caliber_mm, inp.is_check_valve, inp.is_metric
)
result.upper_seal_hold_time = self.calc_upper_seal_hold_time(
standard_norm, inp.caliber_mm, inp.is_metric
)
result.main_seal_hold_time = self.calc_main_seal_hold_time(
standard_norm, inp.caliber_mm, inp.is_check_valve, inp.is_metric
)
# 标准号为空 → 所有时间返回 "≥"(VBA 第328/550/678行)
if not inp.standard or not inp.standard.strip():
result.strength_hold_time = "≥"
result.upper_seal_hold_time = "≥"
result.main_seal_hold_time = "≥"
return result
# ---- 强度试验压力(对标 VBA 第56-121行) ----
[文档]
@staticmethod
def calc_strength_pressure(standard_norm: str, nominal_pressure_mpa: float) -> float | None:
"""计算强度试验压力
标准倍率规则(对标 VBA `根据标准号计算强度试验压力`):
==================== ===== ===================================
标准号 倍率 备注
==================== ===== ===================================
API 598 1.5x Lb 已在调用前换算为 MPa
GB/T 13927 1.5x
GB/T 26480 1.5x
JB/T 9092 1.5x
JB/T 3595 1.5x
GB/T 12465 1.5x
GB/T 12245 1.5x 减压阀
GB/T 14382 1.5x
GB/T 14478 1.5x
GB 12242 1.5x 水流指示器
GB/T 12251 1.5x 蒸汽疏水阀
SL 553 1.5x
DL/T 5190.5 1.5x
NB/T 47044 见下 电站阀门(分级)
≤4 MPa 1.5x (等同 JB/T 3595)
4-10 MPa 1.5x (等同 GB/T 26480)
10-17 MPa 3.0x
=17 MPa 48.0 (固定值, PW55 170V)
背压阀外购 4.0x
==================== ===== ===================================
"""
if not standard_norm or nominal_pressure_mpa <= 0:
return None
p = nominal_pressure_mpa
# 1.5x 标准族
_1_5X_STANDARDS = {
"API 598",
"GB/T 13927",
"GB/T 26480",
"JB/T 9092",
"JB/T 3595",
"GB/T 12465",
"GB/T 12245",
"GB/T 14382",
"GB/T 14478",
"GB 12242",
"GB/T 12251",
"SL 553",
"DL/T 5190.5",
}
if standard_norm in _1_5X_STANDARDS:
return round(p * 1.5, 2)
# NB/T 47044 电站阀门(分级)
if standard_norm == "NB/T 47044":
if p <= 4 or p < 10:
return round(p * 1.5, 2)
if p < 17:
return round(p * 3.0, 2)
if math.isclose(p, 17.0, rel_tol=0.01):
return 48.0 # PW55 170V 固定值
return round(p * 1.5, 2)
# 背压阀外购
if standard_norm == "背压阀外购":
return round(p * 4.0, 2)
# 真空阀门 / 眼镜阀 / 电站调节阀 — VBA 中无明确强度压力(空 Case)
_NO_STRENGTH_STANDARDS = {
"GB/T 24917",
"JB/T 6446",
"GB/T 10869",
}
if standard_norm in _NO_STRENGTH_STANDARDS:
return None
# 未匹配标准号 → 返回 None(VBA 返回 0,此处更安全)
return None
# ---- 上密封试验压力(对标 VBA 第123-204行) ----
[文档]
@staticmethod
def calc_upper_seal_pressure(
standard_norm: str,
nominal_pressure_mpa: float,
is_check_valve: bool = False,
is_butterfly_valve: bool = False, # noqa: ARG004 保留参数以对齐 VBA 接口
) -> float | None:
"""计算上密封试验压力
返回 None 表示无上密封试验项目(对标 VBA 返回 "/")。
返回 0.0 表示压力为 0(VBA 返回 0,如 GB/T 12465)。
关键规则:
- 止回阀(check valve):多数标准无上密封 → "/"
- 减压阀(GB/T 12245):无上密封 → "/"
- 伸缩节(GB/T 12465):无上密封 → 0
- 蒸汽疏水阀(GB/T 12251):只有强度试验 → "/"
- 背压阀外购:无上密封 → "/"
- GB/T 14382:无上密封 → "/"
"""
if not standard_norm or nominal_pressure_mpa <= 0:
return None
handler = _UPPER_SEAL_PRESSURE_TABLE.get(standard_norm)
if handler is None:
return None # 未匹配标准号 → None(VBA 返回 0)
return handler(nominal_pressure_mpa, is_check_valve)
# ---- 主密封试验压力(对标 VBA 第206-300行) ----
[文档]
@staticmethod
def calc_main_seal_pressure(
standard_norm: str,
nominal_pressure_mpa: float,
is_check_valve: bool = False,
is_butterfly_valve: bool = False,
) -> float | None:
"""计算主密封试验压力
关键规则:
- API 598:所有阀门 1.1x
- GB/T 26480 / JB/T 9092:止回阀 1.0x,其他 1.1x
- NB/T 47044:止回阀/蝶阀 1.0x,其他按公称压力分级
- GB/T 12465 / GB/T 14382 / DL/T 5190.5:1.25x
- GB 12242(水流指示器):1.2x
- 背压阀外购:1.2x
- GB/T 12251(蒸汽疏水阀):0(只有强度试验)
- GB/T 14478:需用户输入最大净水头(此处返回 None 需人工)
"""
if not standard_norm or nominal_pressure_mpa <= 0:
return None
handler = _MAIN_SEAL_PRESSURE_TABLE.get(standard_norm)
if handler is None:
return None # 未匹配 → None
return handler(nominal_pressure_mpa, is_check_valve, is_butterfly_valve)
# ============================================================
# 保压时间计算
# ============================================================
[文档]
@staticmethod
def calc_strength_hold_time(
standard_norm: str,
caliber_mm: float,
is_check_valve: bool = False,
is_metric: bool = True,
) -> str:
"""计算强度试验最短保压时间
对标 VBA `查找强度试验最短保压时间`(第658-861行)。
按标准号 + 口径查表,英制单位仅支持 API 598。
Returns:
str: 如 "≥15", "≥60", "≥120", "≥300", "≥1800", "≥"
"""
if not standard_norm:
return "≥"
# 英制单位仅处理 API 598
if not is_metric:
return _strength_time_api598(caliber_mm) if standard_norm == "API 598" else "≥"
handler = _STRENGTH_HOLD_TABLE.get(standard_norm)
if handler is None:
return "≥"
return handler(caliber_mm, is_check_valve)
[文档]
@staticmethod
def calc_upper_seal_hold_time(
standard_norm: str,
caliber_mm: float,
is_metric: bool = True,
) -> str:
"""计算上密封试验最短保压时间
对标 VBA `查找上密封试验最短保压时间`(第530-656行)。
无上密封试验项目 → 返回 "/" 或 "≥"
"""
if not standard_norm:
return "≥"
# 英制单位仅处理 API 598
if not is_metric:
if standard_norm == "API 598":
return "≥15" if caliber_mm <= 50 else "≥60"
return "≥"
handler = _UPPER_SEAL_HOLD_TABLE.get(standard_norm)
if handler is None:
return "≥"
return handler(caliber_mm)
[文档]
@staticmethod
def calc_main_seal_hold_time(
standard_norm: str,
caliber_mm: float,
is_check_valve: bool = False,
is_metric: bool = True,
) -> str:
"""计算主密封试验最短保压时间
对标 VBA `查找主密封试验最短保压时间`(第303-528行)。
"""
if not standard_norm:
return "≥"
# 英制单位仅处理 API 598
if not is_metric:
return (
_main_seal_time_api598(caliber_mm, is_check_valve)
if standard_norm == "API 598"
else "≥"
)
handler = _MAIN_SEAL_HOLD_TABLE.get(standard_norm)
if handler is None:
return "≥"
return handler(caliber_mm, is_check_valve)
# ============================================================
# 保压时间辅助函数(按标准号细分)
# ============================================================
def _strength_time_api598(d: float) -> str:
"""API 598 强度保压时间"""
if d <= 50:
return "≥15"
if d <= 150:
return "≥60"
if d <= 300:
return "≥120"
return "≥300"
def _strength_time_13927(d: float) -> str:
"""GB/T 13927 强度保压时间"""
if d <= 50:
return "≥15"
if d <= 150:
return "≥60"
if d <= 300:
return "≥120"
return "≥300"
def _strength_time_26480_other(d: float) -> str:
"""GB/T 26480 非止回阀强度保压时间"""
if d <= 50:
return "≥15"
if d <= 150:
return "≥60"
if d <= 300:
return "≥120"
return "≥300"
def _strength_time_47044(d: float) -> str:
"""NB/T 47044 强度保压时间"""
if d <= 50:
return "≥30"
if d <= 150:
return "≥120"
if d <= 300:
return "≥180"
return "≥240"
def _strength_time_3595(d: float) -> str:
"""JB/T 3595 强度保压时间"""
if d <= 125:
return "≥120"
if d <= 400:
return "≥180"
return "≥240"
def _main_seal_time_api598(d: float, is_check_valve: bool = False) -> str:
"""API 598 主密封保压时间"""
if is_check_valve:
return "≥60" if d <= 150 else "≥120"
if d <= 50:
return "≥15"
if d <= 150:
return "≥60"
return "≥120"
def _main_seal_time_13927(d: float, is_check_valve: bool = False) -> str:
"""GB/T 13927 主密封保压时间"""
if is_check_valve:
return "≥60" if d <= 150 else "≥120"
if d <= 50:
return "≥15"
if d <= 150:
return "≥60"
return "≥120"
def _main_seal_time_26480_other(d: float) -> str:
"""GB/T 26480 非止回阀主密封保压时间"""
if d <= 50:
return "≥15"
if d <= 150:
return "≥60"
return "≥120"
def _main_seal_time_47044(d: float) -> str:
"""NB/T 47044 主密封保压时间"""
if d <= 50:
return "≥30"
if d <= 150:
return "≥60"
if d <= 300:
return "≥120"
return "≥180"
def _main_seal_time_3595(d: float) -> str:
"""JB/T 3595 主密封保压时间"""
if d <= 125:
return "≥60"
if d <= 400:
return "≥120"
return "≥180"
# ============================================================
# 压力 / 保压时间派发表(对标 VBA Select Case,按标准号分发)
# 将 calc_* 中的长 if 标准号==X 分支链改为查表,复杂度更低且更易核对。
# ============================================================
def _upper_seal_pressure_47044(p: float, is_check_valve: bool = False) -> float | None:
"""NB/T 47044 上密封压力(分级,对标 VBA)"""
if p <= 4 or p < 10:
return round(p * 1.1, 2)
if p < 17:
return round(p * 2.2, 2)
if math.isclose(p, 17.0, rel_tol=0.01):
return 36.0 # PW55 170V 固定值
return round(p * 1.1, 2)
def _main_seal_pressure_47044(
p: float, is_check_valve: bool = False, is_butterfly_valve: bool = False
) -> float | None:
"""NB/T 47044 主密封压力(分级 + 止回阀/蝶阀)"""
if is_check_valve or is_butterfly_valve:
return round(p * 1.0, 2)
if p <= 4 or p < 10:
return round(p * 1.1, 2)
if p < 17:
return round(p * 2.2, 2)
if math.isclose(p, 17.0, rel_tol=0.01):
return 36.0 # PW55 170V 固定值
return round(p * 1.1, 2)
def _strength_hold_26480_9092(d: float, is_check_valve: bool = False) -> str:
"""GB/T 26480 / JB/T 9092 强度保压(止回阀特殊)"""
if is_check_valve:
return "≥60" if d <= 300 else "≥120"
return _strength_time_26480_other(d)
def _strength_hold_12251(d: float, is_check_valve: bool = False) -> str:
"""GB/T 12251 蒸汽疏水阀强度保压"""
if d <= 50:
return "≥15"
if d <= 150:
return "≥60"
return "≥"
def _upper_seal_hold_47044(d: float) -> str:
"""NB/T 47044 上密封保压"""
if d <= 150:
return "≥15"
if d <= 300:
return "≥20"
return "≥60"
def _main_seal_hold_26480_9092(d: float, is_check_valve: bool = False) -> str:
"""GB/T 26480 / JB/T 9092 主密封保压(止回阀特殊)"""
if is_check_valve:
return "≥60" if d <= 300 else "≥120"
return _main_seal_time_26480_other(d)
def _main_seal_hold_12245(d: float, is_check_valve: bool = False) -> str:
"""GB/T 12245 减压阀主密封保压"""
if d <= 50:
return "≥60"
if d <= 125:
return "≥120"
return "≥180"
# 上密封试验压力派发表:标准号 -> handler(p, is_check_valve)
_UPPER_SEAL_PRESSURE_TABLE: dict[str, Callable[[float, bool], float | None]] = {
"API 598": lambda p, c=False: None if c else round(p * 1.1, 2),
"GB/T 13927": lambda p, c=False: round(p * 1.1, 2),
"JB/T 7387": lambda p, c=False: round(p * 1.1, 2),
"JB/T 3595": lambda p, c=False: round(p * 1.1, 2),
"GB/T 26480": lambda p, c=False: None if c else round(p * 1.1, 2),
"JB/T 9092": lambda p, c=False: None if c else round(p * 1.1, 2),
"GB/T 12465": lambda p, c=False: 0.0,
"GB/T 14478": lambda p, c=False: 0.0,
"SL 553": lambda p, c=False: 0.0,
"NB/T 47044": _upper_seal_pressure_47044,
"GB/T 12251": lambda p, c=False: None,
"GB/T 12245": lambda p, c=False: None,
"GB/T 14382": lambda p, c=False: None,
"背压阀外购": lambda p, c=False: None,
"DL/T 5190.5": lambda p, c=False: round(p * 1.25, 2),
}
# 主密封试验压力派发表:标准号 -> handler(p, is_check_valve, is_butterfly_valve)
_MAIN_SEAL_PRESSURE_TABLE: dict[str, Callable[[float, bool, bool], float | None]] = {
"API 598": lambda p, c=False, b=False: round(p * 1.1, 2),
"GB 12242": lambda p, c=False, b=False: round(p * 1.2, 2),
"GB/T 13927": lambda p, c=False, b=False: round(p * 1.1, 2),
"JB/T 3595": lambda p, c=False, b=False: round(p * 1.1, 2),
"SL 553": lambda p, c=False, b=False: round(p * 1.1, 2),
"GB/T 26480": lambda p, c=False, b=False: round(p * 1.0, 2) if c else round(p * 1.1, 2),
"JB/T 9092": lambda p, c=False, b=False: round(p * 1.0, 2) if c else round(p * 1.1, 2),
"GB/T 12465": lambda p, c=False, b=False: round(p * 1.25, 2),
"GB/T 14382": lambda p, c=False, b=False: round(p * 1.25, 2),
"DL/T 5190.5": lambda p, c=False, b=False: round(p * 1.25, 2),
"GB/T 14478": lambda p, c=False, b=False: round(p * 1.1, 2),
"NB/T 47044": _main_seal_pressure_47044,
"GB/T 12251": lambda p, c=False, b=False: 0.0,
"JB/T 7387": lambda p, c=False, b=False: 0.0,
"GB/T 12245": lambda p, c=False, b=False: round(p * 1.1, 2),
"背压阀外购": lambda p, c=False, b=False: round(p * 1.2, 2),
}
# 强度保压时间派发表:标准号 -> handler(d, is_check_valve)
_STRENGTH_HOLD_TABLE: dict[str, Callable[[float, bool], str]] = {
"API 598": lambda d, c=False: _strength_time_api598(d),
"GB 12242": lambda d, c=False: "≥60",
"GB/T 13927": lambda d, c=False: _strength_time_13927(d),
"GB/T 26480": _strength_hold_26480_9092,
"JB/T 9092": _strength_hold_26480_9092,
"NB/T 47044": lambda d, c=False: _strength_time_47044(d),
"JB/T 3595": lambda d, c=False: _strength_time_3595(d),
"GB/T 12465": lambda d, c=False: "≥300",
"GB/T 14478": lambda d, c=False: "≥1800",
"SL 553": lambda d, c=False: "≥1800",
"GB/T 12251": _strength_hold_12251,
"GB/T 12245": lambda d, c=False: _strength_time_13927(d),
"GB/T 14382": lambda d, c=False: "≥600",
"背压阀外购": lambda d, c=False: "≥180",
"DL/T 5190.5": lambda d, c=False: _strength_time_47044(d),
"JB/T 7387": lambda d, c=False: "≥",
}
# 上密封保压时间派发表:标准号 -> handler(d)
_UPPER_SEAL_HOLD_TABLE: dict[str, Callable[[float], str]] = {
"API 598": lambda d: "≥15" if d <= 50 else "≥60",
"GB 12242": lambda d: "水流指示器没有上密封检测项目",
"GB/T 13927": lambda d: "≥15" if d <= 50 else "≥60",
"GB/T 26480": lambda d: "≥15" if d <= 50 else "≥60",
"JB/T 9092": lambda d: "≥15" if d <= 50 else "≥60",
"GB/T 12465": lambda d: "/",
"GB/T 14478": lambda d: "/",
"SL 553": lambda d: "/",
"NB/T 47044": _upper_seal_hold_47044,
"JB/T 3595": lambda d: "/",
"GB/T 12251": lambda d: "\\",
"JB/T 7387": lambda d: "≥180",
"GB/T 12245": lambda d: "/",
"GB/T 14382": lambda d: "/",
"背压阀外购": lambda d: "/",
"DL/T 5190.5": lambda d: _strength_time_47044(d),
}
# 主密封保压时间派发表:标准号 -> handler(d, is_check_valve)
_MAIN_SEAL_HOLD_TABLE: dict[str, Callable[[float, bool], str]] = {
"API 598": lambda d, c=False: _main_seal_time_api598(d, c),
"GB 12242": lambda d, c=False: "≥30",
"GB/T 13927": lambda d, c=False: _main_seal_time_13927(d, c),
"GB/T 26480": _main_seal_hold_26480_9092,
"JB/T 9092": _main_seal_hold_26480_9092,
"NB/T 47044": lambda d, c=False: _main_seal_time_47044(d),
"JB/T 3595": lambda d, c=False: _main_seal_time_3595(d),
"GB/T 12465": lambda d, c=False: "≥300",
"GB/T 14478": lambda d, c=False: "≥1800",
"SL 553": lambda d, c=False: "≥1800",
"GB/T 12251": lambda d, c=False: "\\",
"JB/T 7387": lambda d, c=False: "≥",
"GB/T 12245": _main_seal_hold_12245,
"GB/T 14382": lambda d, c=False: "≥600",
"背压阀外购": lambda d, c=False: "≥120",
"DL/T 5190.5": lambda d, c=False: _main_seal_time_47044(d),
}
# ============================================================
# 显示格式化
# ============================================================
def _format_pressure(value: float | None, none_marker: str = "") -> str:
"""将压力数值格式化为显示字符串。
Args:
value: 压力数值(MPa),None 表示无法计算
none_marker: None 时的占位符(上密封用 "/")
Returns:
str: 如 "3.75", "48.0", "/", ""
"""
if value is None:
return none_marker
if value == 0.0:
return "0"
# 保留最多 2 位小数,去掉末尾无意义的 0;
# 使用 decimal 做四舍五入,保证 5.17*1.5=7.755 → 7.76(向远离零方向进位)。
quantized = Decimal(str(value)).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
return f"{quantized:.2f}".rstrip("0").rstrip(".")
# ============================================================
# 便捷函数(供 report_service 直接调用)
# ============================================================
[文档]
def compute_pressure_params(
standard: str,
nominal_pressure_mpa: float,
caliber_mm: float,
is_check_valve: bool = False,
is_butterfly_valve: bool = False,
is_imperial: bool = False,
) -> dict[str, Any]:
"""便捷函数:一次性计算所有试压参数,返回字典。
供 report_service.py 直接调用,无需创建 PressureCalcInput 对象。
Args:
standard: 试压标准号
nominal_pressure_mpa: 公称压力(MPa)
caliber_mm: 口径(mm)
is_check_valve: 是否止回阀
is_butterfly_valve: 是否蝶阀
is_imperial: 是否英制型号
Returns:
dict: 包含所有压力和时间字段的字典,可直接 merge 到 report_data
"""
svc = PressureCalcService()
result = svc.calculate(
PressureCalcInput(
standard=standard or "",
nominal_pressure_mpa=nominal_pressure_mpa,
caliber_mm=caliber_mm,
is_check_valve=is_check_valve,
is_butterfly_valve=is_butterfly_valve,
is_metric=not is_imperial,
is_imperial=is_imperial,
)
)
return {
"strength_test_pressure": result.strength_test_pressure_display,
"strength_hold_time": result.strength_hold_time,
"upper_seal_pressure": result.upper_seal_pressure_display,
"upper_seal_hold_time": result.upper_seal_hold_time,
"main_seal_pressure": result.main_seal_pressure_display,
"main_seal_hold_time": result.main_seal_hold_time,
}