Skip to content

格式化分组 3.x

格式化分组功能允许你将常用的格式化字符串定义为可复用的分组,避免重复编写长格式化语句。

基本用法

定义和使用分组

javascript
import { calc, set_config } from 'a-calc'

// 定义分组
set_config({
  _fmt_groups: {
    'money': '~6=2,',                    // 金额:银行家舍入+2位小数+千分位
    'percent': '~5%=2',                  // 百分比:2位小数
    'compact': '!c !ua:股'               // 紧凑格式:带单位
  }
})

// 使用分组
calc('12345.678 | #money')              // '12,345.68'
calc('0.1234 | #percent')               // '12.34%'
calc('1234567 | #compact')              // '1.23M股'

两种语法

javascript
// 快捷语法(推荐)
calc('12345.678 | #money')

// 统一语法
calc('12345.678 | !g:money')

变量引用

使用 @ 前缀动态选择分组:

javascript
set_config({
  _fmt_groups: {
    'money': '~6=2,',
    'percent': '~5%=2'
  }
})

const data = [
  { value: 12345.678, type: 'money' },
  { value: 0.1234, type: 'percent' }
]

data.forEach(item => {
  console.log(calc('value | #@type', item))
})
// '12,345.68'
// '12.34%'

常用分组示例

金融场景

javascript
set_config({
  _fmt_groups: {
    'money': '~6=2,',                    // 12,345.68
    'money_cny': '~6=2, !ua:元',        // 12,345.68元
    'money_usd': '~6=2, !ub:$',         // $12,345.68
    'rate': '~5%=4+',                    // +5.2300%
    'change': '~5%=2+'                   // +12.34%
  }
})

电商平台

javascript
set_config({
  _fmt_groups: {
    'price': '~6=2, !ua:元',            // 价格
    'discount': '~5%=0',                 // 折扣:77%
    'qty': '=0,',                        // 数量:1,234
    'rating': '=1'                       // 评分:4.8
  },
  _unit_convert_out: {
    '元': { '分': 0.01 }                // 分转元
  }
})

calc('999900 | #price')                 // '9,999.00元'
calc('0.77 | #discount')                // '77%'
calc('1234 | #qty')                     // '1,234'

数据报表

javascript
set_config({
  _fmt_groups: {
    'compact': '!c !ua:股',             // 1.23M股
    'number': '=2,',                     // 12,345.68
    'integer': '=0,',                    // 12,346
    'order': '!i:8'                      // 00000042
  }
})

与其他功能结合

单位转换

javascript
set_config({
  _fmt_groups: {
    'price': '~6=2, !ua:元'
  },
  _unit_convert_out: {
    '元': { '分': 0.01 }
  }
})

calc('100000 | #price')  // '1,000.00元' (100000分 → 1000元)

千分位配置

javascript
set_config({
  _fmt_groups: {
    'money_en': '~6=2, !t:en !ub:$',    // 英文:$12,345.67
    'money_eu': '~6=2, !t:eu !ua:€'     // 欧式:12.345,67€
  },
  _thousands: {
    en: { sep: ',', point: '.' },
    eu: { sep: '.', point: ',' }
  }
})

性能特性

格式化分组采用懒加载 + 自动缓存机制:

  1. 首次使用:编译格式化字符串并缓存
  2. 后续使用:直接从缓存读取,性能优异
  3. 配置变更:自动清理缓存,确保使用最新配置
javascript
set_config({
  _fmt_groups: {
    'money': '~6=2,'
  }
})

// 首次调用:编译并缓存
calc('12345.678 | #money')  // 编译 + 执行

// 后续调用:使用缓存
calc('54321.123 | #money')  // 直接执行(快)
calc('99999.999 | #money')  // 直接执行(快)

实际应用示例

电商系统

javascript
set_config({
  _fmt_groups: {
    'price': '~6=2, !ua:元',
    'discount': '~5%=0',
    'save': '~6=2, !ub:¥',
    'qty': '=0,',
    'rating': '=1'
  },
  _unit_convert_out: {
    '元': { '分': 0.01 }
  }
})

const product = {
  price: 9999,        // 分
  original: 12999,    // 分
  qty: 1234,
  rating: 4.8
}

console.log('价格:', calc('price | #price', product))           // '99.99元'
console.log('原价:', calc('original | #price', product))        // '129.99元'
console.log('折扣:', calc('price / original | #discount', product))  // '77%'
console.log('节省:', calc('original - price | #save', product)) // '¥30.00'
console.log('销量:', calc('qty | #qty', product))               // '1,234'
console.log('评分:', calc('rating | #rating', product))         // '4.8'

金融报表

javascript
set_config({
  _fmt_groups: {
    'amount': '~6=2,',
    'amount_k': '!c:en =2',          // K/M/B 格式
    'ratio': '~5%=2+',
    'change': '~5%=2+'
  }
})

const report = {
  revenue: 12345678.90,
  profit: 2345678.12,
  growth: 0.1523,
  margin: 0.1899
}

console.log('营收:', calc('revenue | #amount', report))         // '12,345,678.90'
console.log('利润:', calc('profit | #amount_k', report))        // '2.35M'
console.log('增长:', calc('growth | #change', report))          // '+15.23%'
console.log('利润率:', calc('margin | #ratio', report))         // '+18.99%'

注意事项

1. 分组与其他格式化参数的组合

分组可以与其他格式化参数组合使用,后面的参数会覆盖分组中相同类型的配置:

javascript
set_config({
  _fmt_groups: {
    'money': '~6=2,'  // 银行家舍入 + 2位小数 + 千分位
  }
})

// 后面的参数会覆盖分组中的配置
calc('12345.678 | #money =4')      // '12,345.6780' (覆盖精度为4位)
calc('12345.678 | #money <=1')     // '12,345.7' (覆盖精度范围)
calc('12345.678 | #money +')       // '+12,345.68' (追加符号显示)
calc('12345.678 | #money ~+')      // '12,345.68' (覆盖舍入模式为进一)

// 前面的参数也会被后面的分组覆盖
calc('12345.678 | =4 #money')      // '12,345.6780' (=4在后,覆盖分组的=2)

组合规则

  • 分组 tokens 作为基础
  • 其他 tokens 按顺序追加
  • 相同类型的配置,后面的覆盖前面的
  • 不同类型的配置会叠加

2. 多个分组的使用限制

当前版本只支持使用一个分组,如果指定多个分组,只有第一个会生效:

javascript
set_config({
  _fmt_groups: {
    'money': '~6=2,',
    'percent': '%=4'
  }
})

// ⚠️ 只有第一个分组生效
calc('12345.678 | #money #percent')   // '12,345.68' (只应用了 #money)
calc('0.12345 | #percent #money')     // '12.3450%' (只应用了 #percent)

推荐做法

  • 每次只使用一个分组
  • 如果需要组合多种格式,在分组定义中包含所有格式
  • 或者使用分组作为基础,后面追加其他格式化参数
javascript
// ✅ 推荐:在分组中定义完整格式
set_config({
  _fmt_groups: {
    'money_percent': '~6=2,%'  // 组合多种格式
  }
})

// ✅ 推荐:使用分组 + 追加参数
calc('12345.678 | #money + !ua:元')  // '+12,345.68元'

3. 分组配置建议

分组中的格式化字符串应该是完整、有效的格式化配置:

javascript
// ✅ 推荐:完整配置
set_config({
  _fmt_groups: {
    'price': '~6=2, !ua:元'  // 明确指定单位
  }
})

// ✅ 也可以:使用默认单位(需要配置 _unit_default_out)
set_config({
  _unit_default_out: '元',
  _unit_convert_out: { '元': { '分': 0.01 } },
  _fmt_groups: {
    'price': '~6=2, !ua'  // 使用默认单位
  }
})

calc('10000 | #price')  // '100.00元'

// ❌ 错误:语法错误(冒号后缺少单位)
set_config({
  _fmt_groups: {
    'price': '~6=2, !ua:'  // 冒号后缺少单位,不会显示单位
  }
})

calc('10000 | #price')  // '10,000.00' (不会显示单位)

建议

  • 在分组中明确指定所有参数,让配置更清晰
  • 如果使用默认单位,确保已配置 _unit_default_out
  • 避免使用 !ua: 这种不完整的语法(冒号后缺少单位)

4. 分组名称规则

  • 支持字母、数字、下划线
  • 建议使用有意义的名称
  • 可以使用简短别名
javascript
set_config({
  _fmt_groups: {
    // 完整名称
    'money': '~6=2,',
    'money_cny': '~6=2, !ua:元',
    
    // 简短别名
    'm': '~6=2,',
    'p': '~5%=2'
  }
})

5. 分组不存在时的行为

引用不存在的分组时,会给出警告并返回原值:

javascript
calc('12345.678 | #notexist')  
// 警告: Format group "notexist" not found, ignoring.
// 返回: '12345.678'

配置管理

重置配置

javascript
// 重置所有配置
reset_config()

// 只重置分组配置
reset_config('_fmt_groups')

获取当前配置

javascript
// 获取所有配置
const config = get_config()

// 获取分组配置
const groups = get_config('_fmt_groups')

语法速查

语法说明示例
#name快捷语法(推荐)#money
!g:name统一语法!g:money
#@var变量引用(快捷)#@fmt
!g:@var变量引用(统一)!g:@fmt

配置项

配置项类型说明
_fmt_groupsobject格式化分组定义

分组定义格式:

javascript
{
  'groupName': 'formatString'
}

其中 formatString 是完整的格式化字符串,支持所有格式化语法。

基于 MIT 许可发布