fix(user-center): 防止大额资产金额断行

This commit is contained in:
2026-09-16 17:23:56 +08:00
parent e7ffb44b45
commit 56d1b2a417
9 changed files with 59 additions and 5 deletions
+17 -1
View File
@@ -15,7 +15,7 @@
/* Dual asset row — layout only (no outer mega-card). Desktop: 1 row; mobile: 2 rows. */
.uc-assets-row {
display: grid;
grid-template-columns: 1fr;
grid-template-columns: minmax(0, 1fr);
gap: 12px;
margin-bottom: 10px;
background: transparent;
@@ -65,10 +65,15 @@
grid-column: auto;
grid-row: auto;
}
.uc-asset-card__body {
flex-direction: column;
align-items: flex-start;
}
}
/* One surface per asset (wallet / points) — never nest inside another card shell */
.uc-asset-card {
min-width: 0;
display: flex;
flex-direction: column;
background: var(--main-bg-color, var(--surface-1, #fff));
@@ -78,6 +83,11 @@
padding: 16px 20px;
margin-bottom: 0;
}
/* Amount keeps its row; actions wrap below as a whole when space runs out. */
.uc-asset-card__body {
flex-wrap: wrap;
row-gap: 10px;
}
/* Card-pass under a col must not look like a second stacked card */
.uc-assets-col > .uc-card-pass {
margin: 0;
@@ -95,6 +105,12 @@
color: var(--main-color, #4e5358);
}
.uc-asset-card__amount {
flex: none;
max-width: 100%;
white-space: nowrap;
font-variant-numeric: tabular-nums;
overflow: hidden;
text-overflow: ellipsis;
font-size: 1.75rem;
line-height: 1.2;
}
+3 -1
View File
@@ -62,9 +62,10 @@
var points = data.credit_balance !== undefined ? data.credit_balance : data.points_balance;
if (wallet !== undefined && wallet !== null && wallet !== '') {
var walletNumber = Number(wallet);
var walletText = Number.isFinite(walletNumber) ? walletNumber.toFixed(2) : String(wallet);
var walletText = Number.isFinite(walletNumber) ? walletNumber.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }) : String(wallet);
document.querySelectorAll('[data-aksrt-wallet-value]').forEach(function (element) {
element.textContent = walletText;
element.title = walletText;
});
}
if (points !== undefined && points !== null && points !== '') {
@@ -72,6 +73,7 @@
var pointsText = Number.isFinite(pointsNumber) ? pointsNumber.toLocaleString() : String(points);
document.querySelectorAll('[data-aksrt-points-value]').forEach(function (element) {
element.textContent = pointsText;
element.title = pointsText;
});
}
}
+1
View File
@@ -117,6 +117,7 @@
notyf(result.json.message || '签到成功', 'success', 5, 'aksrt-balance-signin-toast');
document.querySelectorAll('[data-credits-value]').forEach(function (element) {
element.textContent = Number(result.json.balance || 0).toLocaleString();
element.title = element.textContent;
});
setButtonState('done');
refresh();
@@ -46,7 +46,7 @@ $currency = (string) ($currency_name ?? __('积分', 'aksrt'));
</div>
<div class="uc-asset-card__body flex jsb ac">
<div class="uc-asset-card__amount c-green">
<span class="uc-asset-card__value font-bold" data-aksrt-points-value data-credits-value><?php echo esc_html(aksrt_format_points($balance)); ?></span>
<span class="uc-asset-card__value font-bold" data-aksrt-points-value data-credits-value title="<?php echo esc_attr(aksrt_format_points($balance)); ?>"><?php echo esc_html(aksrt_format_points($balance)); ?></span>
</div>
<div class="uc-asset-card__actions flex0">
<?php if ($points_transfer_on) : ?>
@@ -78,7 +78,7 @@ $mark = (string) ($charge_view['currency_mark'] ?? '元');
<div class="uc-asset-card__body flex jsb ac">
<div class="uc-asset-card__amount c-blue-2">
<span class="uc-asset-card__mark px12"><?php echo esc_html($mark === '元' ? '¥' : $mark); ?></span>
<span class="uc-asset-card__value font-bold" data-aksrt-wallet-value><?php echo esc_html($wallet_fmt); ?></span>
<span class="uc-asset-card__value font-bold" data-aksrt-wallet-value title="<?php echo esc_attr($wallet_fmt); ?>"><?php echo esc_html($wallet_fmt); ?></span>
</div>
<div class="uc-asset-card__actions flex0">
<?php if ($transfer_on) : ?>
+3 -1
View File
@@ -83,6 +83,8 @@ final class AssetAmount {
if ($this->asset === AssetType::POINTS) {
return number_format_i18n($this->minor);
}
return $this->decimal();
global $wp_locale;
$decimal_point = isset($wp_locale->number_format['decimal_point']) ? $wp_locale->number_format['decimal_point'] : '.';
return number_format_i18n(intdiv($this->minor, 100)) . $decimal_point . sprintf('%02d', $this->minor % 100);
}
}
+8
View File
@@ -73,4 +73,12 @@ final class AssetAmountTest extends TestCase {
$this->expectException(InvalidArgumentException::class);
AssetAmount::percentage(100, 101);
}
public function test_formatted_adds_thousands_separators_to_balance(): void {
self::assertSame('0.00', AssetAmount::balance('0')->formatted());
self::assertSame('12.34', AssetAmount::balance('12.34')->formatted());
self::assertSame('564,000.00', AssetAmount::balance('564000')->formatted());
self::assertSame('1,234,567.89', AssetAmount::balance('1234567.89')->formatted());
self::assertSame('37', AssetAmount::points(37)->formatted());
}
}
+5
View File
@@ -56,6 +56,11 @@ if (!function_exists('wp_is_uuid')) {
return $version === null || strtolower($matches[1]) === strtolower((string) $version);
}
}
if (!function_exists('number_format_i18n')) {
function number_format_i18n($number): string {
return number_format((float) $number);
}
}
if (!class_exists('WP_Error')) {
class WP_Error {
public function __construct(private string $code, private string $message = '', private $data = null) {}
@@ -38,6 +38,26 @@ test('dual asset layout returns to a single-column flex flow on mobile', () => {
assert.match(mobile[1], /\.uc-assets-row--dual\s*>\s*\.uc-assets-col\s*\{[\s\S]*?display:\s*flex;/)
assert.match(mobile[1], /grid-column:\s*auto;/)
assert.match(mobile[1], /grid-row:\s*auto;/)
assert.match(mobile[1], /\.uc-asset-card__body\s*\{[\s\S]*?flex-direction:\s*column;/)
})
test('asset card amounts stay on one line and actions wrap below as a whole', () => {
const css = read('assets/css/routes/user-center/credits.css')
assert.match(css, /\.uc-assets-row\s*\{[\s\S]*?grid-template-columns:\s*minmax\(0,\s*1fr\);/)
assert.match(css, /\.uc-asset-card\s*\{[\s\S]*?min-width:\s*0;/)
assert.match(css, /\.uc-asset-card__body\s*\{[\s\S]*?flex-wrap:\s*wrap;/)
assert.match(css, /\.uc-asset-card__amount\s*\{[\s\S]*?white-space:\s*nowrap;[\s\S]*?font-variant-numeric:\s*tabular-nums;[\s\S]*?text-overflow:\s*ellipsis;/)
})
test('asset card amounts expose the full value via title tooltips', () => {
const wallet = read('inc/helpers/user-center-renderers/credits-wallet.php')
const balance = read('inc/helpers/user-center-renderers/credits-balance.php')
const amount = read('src/Ledger/AssetAmount.php')
assert.match(wallet, /data-aksrt-wallet-value[^>]*title="/)
assert.match(balance, /data-aksrt-points-value[^>]*data-credits-value[^>]*title="/)
assert.match(amount, /number_format_i18n\(intdiv\(\$this->minor, 100\)\)/)
})
test('removed asset card selectors do not return in loaded user-center styles', () => {