Files
workspace/code/g3soft-libs/.changeset/table-number-precision.md
T
2026-10-15 22:47:42 +08:00

24 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
'@g3soft/ui': minor
---
G3Table:新增 `editor.precision`(数值精度)与列级 `format`(展示格式化),并导出 `checkPrecision` / `formatNumber`。
- **`editor.precision`:数值精度(小数位数)**,可传函数按行给。它同时驱动两件事,是**一处真源**:
- **展示**:非编辑态按精度格式化(`1200.5` → `1200.50`);
- **校验**:超出精度即 error(红底 + 左侧竖条),悬停浮层显示「最多 N 位小数」—— 这是**组件内置**的规则,业务不需要写任何与精度有关的 `validate`。
- ⚠️ **不静默四舍五入**:用户输了 `123.456` 而精度是 2,值**仍然是** `123.456`,只是这一格被标红,由用户自己改。悄悄改成 `123.46` 会让「屏幕上的」与「落库的」不是一回事 —— 财务对账时就是「我输的不是这个」。
- ⚠️ **超精度时不做格式化展示**(原样裸露真实值):按精度格式化成 `123.46` 会让屏幕完全合规、数据却不合规,用户永远发现不了自己错了。
- 录入时**不做实时拦截**:实时的精度过滤要与光标位置、输入法组合态、半输入态(`12.` / `-`)搏斗,是公认的坑;「输完再判」既确定又可预测。
- 判定用**字符串**数小数位而不是数值运算:`Math.round(v * 100) / 100` 在 `1.005` 上给出的是 `1`(`1.005 * 100 = 100.49999999999999`),而金额最容易撞上这种「看着是两位小数、二进制里不是」的值。
- **`checkPrecision(value, precision)` 对外导出**:业务在保存前做提交拦截时必须复用**同一个函数**,否则会出现「格子红了但存档能过」这类两边不一致、又极难排查的问题。
- **列级 `format`:展示态格式化**(只影响显示,落库值不变)。传选项对象走底座的 `formatNumber`(千分位 / `¥` 前后缀 / 万-亿缩写 / 百分比);传函数则完全自定义(`Intl.NumberFormat` 的正解 —— 多语言的小数点与千分位符号、会计的括号负数这些 locale 规则,重写一遍必然缺选项)。小数位取 `format.decimals ?? editor.precision`。
- **顺带解决一个缺口**:底座的 `createNumberCell` 是**纯展示**单元格,用法是 `customCell: NumberCell()`,而我们的 `resolveCustomCell` 对显式 `customCell` 是直接放行的 —— 业务一旦用它就绕过了整条编辑链路(编辑、校验、灰底、Tab 跳格、Enter/Esc 语义、草稿与失焦提交全没了)。也就是说「**可编辑的金额列**」此前没有任何合法方式做格式化展示。现在 `format` 与 `editor` 正交,两者可同时存在。
- **门控(性能)**:`resolveCustomCell` 新增两条常驻判据 —— 配了 `precision` 的 number 列、以及配了 `format` 的**纯展示**列(后者走一个只做格式化的轻量 cell)。代价只落在**显式配了这两样**的列上,普通列照旧走库的原生 td 渲染、零组件开销。
- 单测覆盖边界(`utils/precision.test.ts`,13 条):空值/非数字/展示文本/科学计数法一律放行、负数符号不参与位数、`1.005` 这类浮点陷阱、非法精度配置当作没配、格式化与自定义函数的优先级。
- **修复:右对齐列一点进编辑,文字就跳到左边。** `text-align` 本是继承属性,但**表单控件**的 UA 样式表把它覆盖成 `start` —— 实测点进金额格后 input 拿到的是 `start`(LTR 下即左对齐),于是文字与光标从右跳到左,进出编辑有明显位移(与「编辑器无缝嵌入、进出零位移」的目标正好相反)。现在表格侧按库的列对齐类(`.text-r` / `.text-c`)把 `input` / `textarea` 接回来。
- **没有给 `G3Input` 加 prop**:右对齐是**列**的属性(`align`),只有表格知道该不该右对齐;加在公共组件上只会多一个当前没人用的 API。将来表单里出现真实诉求再加不迟。
- 判据依赖库的 `.text-r` / `.text-c` 类名(实测打在 `td` 上);库若改名这层会**静默失效**(表现只是「编辑时又变回左对齐」),代码注释里写明了排查方式。
- 只管 `input` / `textarea`:右对齐的 `select` 极少见,且它的对齐由触发器内部的 flex 布局决定,不是一条 `text-align` 能解决的。
- 文档新增「数值精度与金额」一节(含保存前拦截的完整示例)。