feat(credits): exchange balance for points

Replace the legacy points-to-balance and external points purchase flows
with direct integer balance-to-points exchange. Enforce exchange and
points-transfer limits and capability checks across the UI and REST API.
This commit is contained in:
kate522 committed 2026-08-13 15:20:06 +08:00
1 parent f9bce15c9a
commit 1247f9bf4e
18 files changed
+234 -648

No files matched your search

@@ -26,7 +26,6 @@ $transfer_on = !empty($recharge['transfer']['enabled']);
if ($transfer_on && class_exists('\AKSRT\Settings\Capabilities') && !\AKSRT\Settings\Capabilities::user_can('balance_transfer', $uid)) {
$transfer_on = false;
}
$exchange_on = !empty($recharge['exchange']['enabled']);
$all_settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_all() : [];
$withdraw_on = !empty($all_settings['pay_balance_withdraw_s']);
if ($withdraw_on && class_exists('\AKSRT\Settings\Capabilities') && !\AKSRT\Settings\Capabilities::user_can('balance_withdraw', $uid)) {
@@ -89,18 +88,9 @@ $mark = (string) ($charge_view['currency_mark'] ?? '元');
<button type="button" class="but b-blue-2" data-aksrt-charge-open><?php esc_html_e('充值', 'aksrt'); ?></button>
</div>
</div>
<?php if ($exchange_on) : ?>
<button type="button" class="uc-asset-card__link muted-2-color em09" data-aksrt-exchange-open>
<?php
$rate = (int) ($recharge['exchange']['rate'] ?? 100);
printf(esc_html__('积分兑换余额(%d 积分 = 1 元)', 'aksrt'), $rate);
?>
<i class="fa fa-angle-right em12 ml3" aria-hidden="true"></i>
</button>
<?php endif; ?>
<?php if ($withdraw_on) : ?>
<div class="uc-asset-card__foot muted-2-color em09 mt6">
<span><?php printf(esc_html__('处理中冻结 %s', 'aksrt'), esc_html(class_exists('\AKSRT\Credits\Balance') ? \AKSRT\Credits\Balance::format((float) $withdraw_pending_hold) : number_format_i18n((float) $withdraw_pending_hold, 2))); ?></span>
<span><?php printf(esc_html__('冻结中 %s', 'aksrt'), esc_html(class_exists('\AKSRT\Credits\Balance') ? \AKSRT\Credits\Balance::format((float) $withdraw_pending_hold) : number_format_i18n((float) $withdraw_pending_hold, 2))); ?></span>
</div>
<?php endif; ?>
</div>
@@ -181,60 +171,6 @@ $mark = (string) ($charge_view['currency_mark'] ?? '元');
</div>
</div>
<!-- Transfer modal (balance) -->
<div class="uc-modal" id="aksrt-transfer-modal" hidden data-aksrt-transfer-modal>
<div class="uc-modal__overlay" data-aksrt-transfer-close></div>
<div class="uc-modal__dialog" role="dialog" aria-modal="true">
<button type="button" class="uc-modal__close" data-aksrt-transfer-close aria-label="<?php esc_attr_e('关闭', 'aksrt'); ?>"><i class="fas fa-times" aria-hidden="true"></i></button>
<h3 class="uc-modal__title" data-aksrt-transfer-title><?php esc_html_e('余额转账', 'aksrt'); ?></h3>
<form data-aksrt-transfer-form>
<input type="hidden" name="type" value="balance" data-aksrt-transfer-type>
<div class="mb10">
<label class="muted-color em09"><?php esc_html_e('收款用户', 'aksrt'); ?></label>
<input type="search" class="uc-card-pass__input" data-aksrt-transfer-search placeholder="<?php esc_attr_e('搜索用户名/昵称/邮箱', 'aksrt'); ?>" autocomplete="off">
<div class="uc-transfer-results" data-aksrt-transfer-results></div>
<input type="hidden" name="recipient" value="" data-aksrt-transfer-recipient>
<div class="uc-transfer-selected muted-2-color em09 mt6" data-aksrt-transfer-selected></div>
</div>
<div class="mb10">
<label class="muted-color em09"><?php esc_html_e('金额', 'aksrt'); ?></label>
<input type="number" class="uc-card-pass__input" name="amount" min="0.01" step="0.01" data-aksrt-transfer-amount>
</div>
<?php if (!empty($recharge['transfer']['desc'])) : ?>
<div class="muted-box em09 mb10"><?php echo esc_html((string) $recharge['transfer']['desc']); ?></div>
<?php endif; ?>
<?php if (!empty($recharge['transfer']['service_charge'])) : ?>
<div class="c-yellow em09 mb10"><?php printf(esc_html__('转账将扣除 %s%% 手续费', 'aksrt'), esc_html((string) (int) $recharge['transfer']['service_charge'])); ?></div>
<?php endif; ?>
<p class="uc-modal__tip" data-aksrt-transfer-tip></p>
<button type="submit" class="but jb-blue btn-block" data-aksrt-transfer-submit><?php esc_html_e('确认转账', 'aksrt'); ?></button>
</form>
</div>
</div>
<!-- Exchange modal -->
<?php if ($exchange_on) : ?>
<div class="uc-modal" id="aksrt-exchange-modal" hidden data-aksrt-exchange-modal>
<div class="uc-modal__overlay" data-aksrt-exchange-close></div>
<div class="uc-modal__dialog" role="dialog" aria-modal="true">
<button type="button" class="uc-modal__close" data-aksrt-exchange-close aria-label="<?php esc_attr_e('关闭', 'aksrt'); ?>"><i class="fas fa-times" aria-hidden="true"></i></button>
<h3 class="uc-modal__title"><?php esc_html_e('积分兑换余额', 'aksrt'); ?></h3>
<?php if (!empty($recharge['exchange']['desc'])) : ?>
<div class="muted-box em09 mb10"><?php echo esc_html((string) $recharge['exchange']['desc']); ?></div>
<?php endif; ?>
<form data-aksrt-exchange-form>
<label class="muted-color em09"><?php esc_html_e('兑换积分数量', 'aksrt'); ?></label>
<input type="number" class="uc-card-pass__input" name="points" min="<?php echo esc_attr((string) (int) ($recharge['exchange']['rate'] ?? 100)); ?>" step="1" data-aksrt-exchange-points>
<p class="muted-2-color em09 mt6">
<?php printf(esc_html__('比例:%d 积分 = 1 元(向下取整)', 'aksrt'), (int) ($recharge['exchange']['rate'] ?? 100)); ?>
</p>
<p class="uc-modal__tip" data-aksrt-exchange-tip></p>
<button type="submit" class="but jb-blue btn-block" data-aksrt-exchange-submit><?php esc_html_e('确认兑换', 'aksrt'); ?></button>
</form>
</div>
</div>
<?php endif; ?>
<?php if ($withdraw_on) :
$withdraw_modal_rendered = !empty($GLOBALS['aksrt_withdraw_modal_rendered']);
if (!$withdraw_modal_rendered) {