· engineering· 约 19 分钟精读

Slingguard Wll Unit Precision Derating Representation — Technical Analysis | KeyRotate Technology

核心要点速览 · TL;DR 概要

SlingGuard 把额定载荷存成一个 Double 加一个四成员单位枚举。全仓库没有一次换算,只有一次乘法;六种挂法共用五个系数,折减结果不落盘。本文按源码核对这个数字从录入、显示、打印到 CSV 往返的每一处改写。

Slingguard Wll Unit Precision Derating Representation — Technical Analysis | KeyRotate Technology

港口堆场的工具间里,一条黄色扁平吊带的护套上印着 3.0 t。SlingGuard 的登记册里,这条资产的 WLL 字段也是 3.0 t。资产详情页底部「Safe Working Capacity」在默认档位下显示 3.00 t。打印出来的设备标签上,WLL 一行写 3.0 t,COLOR 一行写 Yellow。四个 3.0 看起来是同一个数,实际上它们出自四条不同的代码路径,各自的精度、单位与含义并不一致。

本文只追这一个数字。涉及的源文件是 RiggingAsset.swift(206 行)、AssetDetailView.swift(340 行)、AddAssetView.swift(141 行)、CSVExporter.swift(58 行)、CSVImporter.swift(177 行)、ReportExporter.swift(294 行)与 QRCodeGenerator.swift(77 行)。结论按源码逐行核对,不引用界面截图里的观感。

一、存储:一个 Double 加四个成员

额定载荷在模型里是 wllValue: Double,紧挨着一个 wllUnit: WLLUnit。枚举四个成员,每个成员带一个长名称的 rawValue 和一个短标签 shortLabel。

成员rawValueshortLabel折算成千克界面出现位置
tonnest (Metric Tonnes)t1000选择器、登记册、标签、报告、CSV
tonsT (US Tons)T907.18474同上
kgkgkg1同上
lbslbslbs0.45359237同上

这张表里有两件事值得记住。第一,rawValue 是四个成员唯一带完整名称的地方,而它在整个工程里从未被渲染过:它只在 CSV 导入时参与匹配,界面上一次也不出现。第二,shortLabel 里前两个成员分别是 t 与 T,区别只在一个字母的大小写。

二、t 与 T:只差一个字母的 10.2%

一美制短吨是 2000 磅,等于 907.18474 千克;一公吨是 1000 千克。同一个 3.0,按短吨读是 2721.6 千克,按公吨读是 3000 千克,两者相差 9.3%。反过来,把一条标着 3.0 T 的吊具当成 3.0 t 记进台账,等于把它的额定值上调 10.2%。

录入页的单位选择器只渲染 shortLabel:菜单里并排站着 t、T、kg、lbs 四个字符串,没有任何一处解释前两个的差别。操作者在现场打开菜单,看到的是两个只差大小写的选项,而背后是九个百分点以上的质量差。这不是排版瑕疵,是字段设计把区分成本推给了使用者。

三、全库只有一次乘法,零次换算

在整个仓库里检索 wllValue 的算术用法,只有一处命中:AssetDetailView.swift 第 192 行的 let rated = asset.wllValue * selectedHitch.factor。没有磅转千克,没有短吨转公吨,没有任何一次单位归一。其余出现的地方都是格式化输出。

把单位当作标签、数值保持录入原样,是一种可以辩护的取舍:端侧工具不替使用者改写他抄下来的读数。代价是倍数必须与录入单位同生共死——乘出来的结果,单位只能沿用录入时选的那一个。当录入值是磅时,折减结果也是磅;当录入值是短吨时,折减结果仍是短吨,而界面在两种情况下都只多印一个字母。

四、六种挂法,五个系数

RiggingHitch 有六个成员,系数只有五个不同的值。

成员显示名系数与单肢额定值的关系
straightStraight (1.0x)1.0单肢直吊,腿承载 100%
chokerChoker (0.8x)0.8单肢套结,按 80% 折减
basketBasket 90° (2.0x)2.0两肢竖直平行
bridle602-Leg 60° (1.73x)1.732两肢,水平夹角 60°
bridle452-Leg 45° (1.41x)1.414两肢,水平夹角 45°
bridle302-Leg 30° (1.00x)1.000两肢,水平夹角 30°

两肢对称吊装时,单肢张力与系统载荷的关系是

Tleg=W2sin⁡βT_{\mathrm{leg}}=\frac{W}{2\sin\beta}

其中 β 是吊索与水平面的夹角,W 是系统载荷。把系统额定容量写成 Wmax=2 WLLsin⁡βW_{\mathrm{max}}=2\,WLL\sin\beta,就得到表中的三个系数:60° 对应 1.732,45° 对应 1.414,30° 对应 1.000。

真正需要说清楚的是那两个 1.000。直吊的 1.0 意思是「一条腿承担全部载荷,这条腿用到 100% 额定值」;两肢 30° 的 1.0 意思是「两条腿各承担一半,每条腿同样用到 100% 额定值」。系统容量相同,载荷路径不同。倍数只描述系统容量相对单肢额定值的比例,不描述有几条腿在受力。按各自的额定容量加载时,四种对称配置下每条腿的利用率都恰好是 100%:直吊是 W=WLLW=WLL,两肢 60° 是 T=1.732 WLL/1.732=WLLT=1.732\,WLL/1.732=WLL。系数表改变的是系统能吊多重,不是每条腿还剩多少余量。

这张表还有两处没有写出来的前提。第一,basket 的 2.0 以两肢竖直平行为条件,D/d 曲率折减不参与计算,钢丝绳吊索在小直径载荷上按标准需要额外降级,这里仍按 2.0 出数。第二,挂法选择器不按器具类型设闸门:七类器具共用这六个档位,卸扣、吊环螺栓与主环也在其中。一条 8.5 t 的弓形卸扣选中 Basket 90° 后,界面会给出 17.00 t,而这个数字对卸扣没有标准依据——卸扣的侧向受力折算走的是另一套规则。界面没有拦,因为这一段 Section 是无条件渲染的。

五、警示靠颜色,不靠字段

30° 档位的结果用橙色渲染,脚注写 Angles <= 30° multiply leg tension severely。这是界面上唯一能把「两个 1.000」区分开的手段:同一个数字,一个蓝色一个橙色,一段普通说明一段警告。

RiggingHitch 的声明是 String, CaseIterable, Identifiable,没有 Codable。这意味着挂法这个状态在类型层面就无法进入任何持久化模型——不是没有写,而是写不进去。想要把「这次核算按哪种挂法」记下来,得先给枚举加一致性,再给模型加字段,再给报告加一行。

六、折减结果没有落点

rated 是 View body 里的一个局部常量,随每次重绘重新计算,不写回资产,不进记录,不进 PDF,也不进 CSV。ReportExporter 里检索不到 RiggingHitch 的任何引用,InspectionRecord 里也没有挂法字段。PDF 汇总表的 WLL 列取的是额定值本身,证据页的 Equipment 行同样是 %.1f 加短标签。

这一列在版面上的预算是 48 点宽:表格从 x=34 起排,列宽数组是 62、138、88、48、76、75、72,字号 8.2 点,绘制进一个 48×15 的矩形。这个宽度放 3.0 t、11.2 t 绰绰有余,但单位一旦选成磅,同一个额定值会写成五位数字加三个字母,接近甚至超出这 48 点的预算;draw(in:) 不做省略号截断,超出部分被裁掉,纸面上不会留下任何标记。

于是「这次核算假设的是哪种挂法」只存活在一个 @State 里,而它的初值是 .straight。离开详情页再进来,选择回到直吊,上一次看到的橙色警告与 1.00 一起消失。纸面上留下的只有一个额定值,读者无法从报告反推出核算时用了几条腿、什么角度。

七、一位小数:取整方向不保证向下

WLL 在七处被格式化成字符串:六处 %.1f,一处(CSV 导出)%.2f;折减结果另用 %.2f。一位小数看起来只是排版,对额定值却是实打实的改写。

录入值显示值偏差
3.153.1−1.59%
4.254.2−1.18%
4.754.8+1.05%
0.750.8+6.67%
2.252.2−2.22%
6.756.8+0.74%

取整走的是二进制表示上的就近取偶,方向由具体数值决定,不保证向下。样例数据里正好有现成的例子:名称写着 Grade 80 Single Leg 3.15t 的那条,同一行 WLL 列印 3.1 t;名称写着 4.75t Bow Shackle 的那条,列里印 4.8 t,比标称高 1.05%。对一条报废判据、一个验收阈值来说,向上取整的那一半是危险方向。

八、CSV 往返:大写 T 落地成小写 t

导出时 WLL 写成 %.2f 加短标签,单位列就是一个 T 或 t。导入时的匹配逻辑是:

let unit = WLLUnit.allCases.first {
    $0.rawValue.caseInsensitiveCompare(unitText) == .orderedSame
        || $0.shortLabel.caseInsensitiveCompare(unitText) == .orderedSame
} ?? .tonnes

first(where:) 按 allCases 的声明顺序取第一个命中,而 tonnes 声明在 tons 之前;比较又是大小写不敏感的。于是导出的一行 3.00,T,回读时第一个候选 t 就与 T 判为相等,落的成员是公吨。

环节值单位
录入3.0tons(美制短吨)
导出3.00T
导入匹配3.00t(公吨)
折算质量3000 kg实际应为 2721.6 kg

一次往返,额定值被抬高 10.2%,全程没有任何提示。单位列缺失或写了 pounds、metric tonnes 这类全称时,匹配同样落空,?? .tonnes 静默补上公吨。也就是说,这套导入对单位的处理只有两种结果:命中四个短标签之一,或者默认成公吨。它不会拒绝一行单位不明的数据。

九、颜色是第二套编码

EN 1492-1 的表 3 用八种颜色标注编织吊带的额定值:紫 1 t、绿 2 t、黄 3 t、灰 4 t、红 5 t、棕 6 t、蓝 8 t、橙 10 t。SlingColor 的 rawValue 把这套对照一字不差地照抄下来,还额外写了磅值,例如 Yellow (3t / 6,600 lbs)。按 6600 除以 3 反推,这份文本用的是 2200 磅一吨,比精确的 2204.6 少 0.2%——一个只存在于字符串里、不参与任何计算的第三套换算。

颜色选择器只在编织吊带与圆吊带时出现,这一点与标准的适用范围一致。问题在于它与 WLL 字段之间没有任何校验:选 Red(5 t)同时把 WLL 填成 2.0,保存不会拦;打印标签会把 WLL: 2.0 t 与 COLOR: Red 并排印出来。护套上的颜色与标签上的数字本来是一次交叉校验的机会,应用把这次机会留给了现场的人。

标签本身也有取舍。QRCodeGenerator 的画布是 360×220,二维码 140 点见方,右侧文字从 x=170 起,五行以 26 点步进。COLOR 一行只取 rawValue 按空格切分后的第一段,也就是 Yellow,括号里的吨位在纸面上被截掉。WLL 一行用 %.1f。于是这块 360×220 的标签上,色名与数字都在,唯独两者之间的换算关系不在。

十、录入面:两个兜底值,一个没有上界

AddAssetView 对同一个字段写了两个默认值。保存按钮的可用性判断是 (Double(wllValueString) ?? 0) > 0,解析失败按 0 处理,按钮变灰;而 saveAsset() 里写的是 Double(wllValueString) ?? 1.0,解析失败按 1.0 处理。后者在正常路径上永远走不到,因为按钮已经拦住了;但两个兜底值不一致这件事本身说明,字段的失败语义没有被定义过一次。

输入框用 decimalPad。这个键盘的小数点键位跟随区域设置,而 Double(String) 的解析只认句点:在把逗号当小数点的区域,操作者按下键盘上的逗号得到 1,5,Double 返回 nil,保存按钮变灰,界面上没有任何提示说明为什么。额定值的录入面没有上界,也没有有效位数约定,1、1.0、1.000 与 1000 都是合法输入。

新增表单的三个默认值是 2.0、tonnes、green。三者恰好自洽——绿色在 EN 1492-1 里正是 2 t。这种默认值制造了一种一致性的错觉:打开表单就是一条绿色两吨吊带,看起来颜色与数值互相印证。但改动 WLL 不会带动颜色,改动颜色也不会带动 WLL,两个控件之间没有一条约束。默认值是「碰巧对」,不是「保证对」。

十一、五条可以落地的收敛线

第一,把单位在入口归一。模型存千克或牛顿的整数,单位只作为显示层的换算参数;或者把 Double 换成带单位的结构体,让「乘以一个系数」这种操作在类型层面无法忽略单位。后者改动大,但它能一次性关掉本文第二、三、八节的全部问题。

第二,单位选择器显示全称。公吨 (t) 与 美制短吨 (T) 并排,短标签改成 t 与 sh tn。这一条只改显示,不动存储,代价最小。

第三,容量计算下沉为纯函数。输入是额定值、单位、挂法与肢数,输出带单位;RiggingHitch 移出 View 并补上 Codable,让每次核算的假设能随记录落盘。报告里加一行「核算假设」,比在界面上多画一个橙色数字更有用。

第四,额定值的显示改为向下取整,或按有效数字显示并在标签上注明「不少于」。折减结果保留两位小数没有意义——输入只有一位小数时,输出精度不可能高于输入。

第五,CSV 导入的单位匹配改成严格相等并区分大小写,未知单位拒绝该行而不是回落公吨。拒绝一行数据,比悄悄改写它的量纲要好。

一个额定值,四个落点同一个 3.0,在存储、显示、折减、导出四处分别是四种东西存储:Double + 单位枚举3.0 t= 3 000 kg公吨3.0 T= 2 722 kg美制短吨同一数字,质量差 9.3%按公吨读,即高估 10.2%3.0 kg= 3.0 kg千克3.0 lbs= 1.36 kg磅四个成员,两个只差一个字母全仓库换算函数:0 个显示 · 六处一位小数0.75 印成 0.8,2.25 印成 2.2:就近取偶,不保证向下Register / 详情 / 录入 / 标签 / 报告两处折减 · 全库唯一一次乘法6.7 × 1.732 = 11.60,单位原样沿用录入值六种挂法、五个倍数,角度只有三档CSV · 两位小数 + 短标签导出 3.00,T;回读大小写不敏感,落在 t 上一次往返,短吨变公吨打印 · 标签只留颜色名COLOR: Yellow,括号里的 3t 在标签上被截掉纸面上只剩一个可以互校的字段倍数乘在哪个数上,取决于录入时选了哪个单位口径来源:RiggingAsset.swift · AssetDetailView.swift · CSVExporter.swift · CSVImporter.swift

十二、能力边界

  • 应用不判断器具类型与挂法是否匹配。挂法选择器对七类器具一视同仁,包括卸扣、吊环与主环,而这些器具的额定值并不按吊索的挂法折算。
  • 系数表只有六档离散值,角度不是连续输入,也不处理三肢、四肢与非对称受力。
  • 不计算 D/d 曲率折减,不计算套结角小于 120° 的分档折减。
  • 不采集实际载荷,因此无法给出利用率;「Safe Working Capacity」是容量上限,不是这次吊装的安全结论。
  • 折减结果不落盘、不进报告,纸面证据只承载额定值。
  • 单位换算依赖使用者选对枚举成员,应用不做任何一致性校验。
  • 所有判定在本机完成,没有外部证书链,也没有第三方复核轨迹。

十三、结语

一个额定值,四种写法:录入时的 3.0 加一个字母,登记册里的 3.0 t,折减后的 5.20 t,CSV 里的 3.00,T。它们各自都说得通,放在一条证据链上就开始互相矛盾。端侧工具的价值在于把现场读数固定下来,而固定的前提是先约定这个数是什么单位、几位有效数字、在哪个环节允许被改写。

把单位归一、把系数下沉、把假设落盘,这三件事都不增加功能,只是让同一个问题只有一个答案。

参考资料

Share:
Back to Blog