feat: 添加货币格式化配置,支持自定义小数位和分隔符,增强 API 响应的可读性

This commit is contained in:
2026-05-13 17:54:05 +08:00
parent 6defe6bb0d
commit 9d3d086adc
2 changed files with 58 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
namespace App\Support;
/**
* 将「最小货币单位」整数格式化为展示用字符串(不改变业务数字,仅格式化)。
*
* 拆分位数由 {@see config('lottery.ui.format.currency.decimals')} 决定,默认 2(即 ÷100
*/
final class CurrencyFormatter
{
public static function fromMinor(int|string|null $minor): string
{
if ($minor === null || $minor === '') {
return self::formatMinorInt(0);
}
return self::formatMinorInt((int) $minor);
}
private static function formatMinorInt(int $minorUnits): string
{
$decimals = max(0, min(12, (int) config('lottery.ui.format.currency.decimals', 2)));
$decSep = (string) config('lottery.ui.format.currency.decimal_separator', '.');
$thousandsSep = (string) config('lottery.ui.format.currency.thousands_separator', ',');
$divisor = (int) max(1, 10 ** $decimals);
$negative = $minorUnits < 0;
$abs = abs($minorUnits);
$integerPart = intdiv($abs, $divisor);
$fractionRaw = $abs % $divisor;
$fractionPadded = str_pad((string) $fractionRaw, $decimals, '0', STR_PAD_LEFT);
$integerPartFormatted = number_format((float) $integerPart, 0, $decSep, $thousandsSep);
if ($decimals === 0) {
return ($negative ? '-' : '').$integerPartFormatted;
}
return ($negative ? '-' : '').$integerPartFormatted.$decSep.$fractionPadded;
}
}

View File

@@ -79,4 +79,17 @@ return [
/** 结果发布后的冷静期(分钟),{@see draws.cooling_end_time} */
'cooldown_minutes' => max(0, (int) env('LOTTERY_DRAW_COOLDOWN_MINUTES', 15)),
],
/*
| ui.formatAPI *_formatted 展示用(由 {@see \App\Support\CurrencyFormatter} 读取)
*/
'ui' => [
'format' => [
'currency' => [
'decimals' => max(0, min(12, (int) env('LOTTERY_CURRENCY_DISPLAY_DECIMALS', 2))),
'decimal_separator' => env('LOTTERY_CURRENCY_DECIMAL_SEP', '.'),
'thousands_separator' => env('LOTTERY_CURRENCY_THOUSANDS_SEP', ','),
],
],
],
];