feat(user-center): redesign sidebar and wallet tips

This commit is contained in:
kate522 committed 2026-07-28 13:41:00 +08:00
1 parent 82e71d1bf9
commit a7f3caec59
24 files changed
+895 -528

No files matched your search

+101
View File
@@ -244,6 +244,105 @@ class Balance {
return !empty(\AKSRT\Settings\Settings::get_all()['pay_balance_s']);
}
/**
* Atomically transfer cash balance between two users.
*
* @param array<string,mixed> $ref
* @return array{sender_balance:float,recipient_balance:float}|\WP_Error
*/
public static function transfer(int $sender_id, int $recipient_id, float $amount, string $reason_out = 'tip_sent', string $reason_in = 'tip_received', array $ref = [], string $remark = '') {
global $wpdb;
$amount = round($amount, 2);
if ($sender_id <= 0 || $recipient_id <= 0 || $sender_id === $recipient_id) {
return new \WP_Error('aksrt_balance_transfer_user', __('转账用户无效', 'aksrt'));
}
if ($amount <= 0) {
return new \WP_Error('aksrt_balance_transfer_amount', __('转账金额必须大于零', 'aksrt'));
}
if (!class_exists('\AKSRT\Core\DBMigrator')) {
return new \WP_Error('aksrt_balance_transfer_unavailable', __('余额服务不可用', 'aksrt'));
}
foreach ([$sender_id, $recipient_id] as $user_id) {
if (!metadata_exists('user', $user_id, self::META_KEY)) {
add_user_meta($user_id, self::META_KEY, '0', true);
}
}
$meta_table = $wpdb->usermeta;
$log_table = \AKSRT\Core\DBMigrator::table('balance_log');
$locked_ids = [$sender_id, $recipient_id];
sort($locked_ids, SORT_NUMERIC);
$wpdb->query('START TRANSACTION');
try {
foreach ($locked_ids as $user_id) {
$wpdb->get_var($wpdb->prepare(
"SELECT umeta_id FROM {$meta_table} WHERE user_id = %d AND meta_key = %s FOR UPDATE",
$user_id,
self::META_KEY
));
}
$sender_before = (float) $wpdb->get_var($wpdb->prepare(
"SELECT meta_value FROM {$meta_table} WHERE user_id = %d AND meta_key = %s LIMIT 1",
$sender_id,
self::META_KEY
));
if ($sender_before < $amount) {
$wpdb->query('ROLLBACK');
return new \WP_Error('aksrt_balance_insufficient', __('余额不足', 'aksrt'));
}
$sender_after = round($sender_before - $amount, 2);
$recipient_before = (float) $wpdb->get_var($wpdb->prepare(
"SELECT meta_value FROM {$meta_table} WHERE user_id = %d AND meta_key = %s LIMIT 1",
$recipient_id,
self::META_KEY
));
$recipient_after = round($recipient_before + $amount, 2);
$sender_updated = $wpdb->update($meta_table, ['meta_value' => (string) $sender_after], ['user_id' => $sender_id, 'meta_key' => self::META_KEY], ['%s'], ['%d', '%s']);
$recipient_updated = $wpdb->update($meta_table, ['meta_value' => (string) $recipient_after], ['user_id' => $recipient_id, 'meta_key' => self::META_KEY], ['%s'], ['%d', '%s']);
if ($sender_updated !== 1 || $recipient_updated !== 1) {
throw new \RuntimeException('balance_update_failed');
}
$ref_type = isset($ref['type']) ? sanitize_key((string) $ref['type']) : 'tip';
$ref_id = isset($ref['id']) ? (int) $ref['id'] : null;
$created_at = current_time('mysql', true);
$log_rows = [
[$sender_id, -$amount, $sender_after, $reason_out],
[$recipient_id, $amount, $recipient_after, $reason_in],
];
foreach ($log_rows as [$user_id, $delta, $balance_after, $reason]) {
$inserted = $wpdb->insert($log_table, [
'user_id' => $user_id,
'delta' => $delta,
'balance_after' => $balance_after,
'reason' => sanitize_key($reason),
'remark' => $remark !== '' ? sanitize_text_field(substr($remark, 0, 255)) : null,
'ref_type' => $ref_type,
'ref_id' => $ref_id,
'created_at' => $created_at,
], ['%d', '%f', '%f', '%s', '%s', '%s', '%d', '%s']);
if ($inserted !== 1) {
throw new \RuntimeException('balance_log_failed');
}
}
$wpdb->query('COMMIT');
wp_cache_delete($sender_id, 'user_meta');
wp_cache_delete($recipient_id, 'user_meta');
do_action('aksrt_balance_transferred', $sender_id, $recipient_id, $amount, $ref);
return ['sender_balance' => $sender_after, 'recipient_balance' => $recipient_after];
} catch (\Throwable $e) {
$wpdb->query('ROLLBACK');
return new \WP_Error('aksrt_balance_transfer_failed', __('打赏入账失败,请稍后重试', 'aksrt'));
}
}
/**
* Format yuan for display.
*/
@@ -262,6 +361,8 @@ class Balance {
'recharge' => __('余额充值', 'aksrt'),
'transfer_in' => __('转入', 'aksrt'),
'transfer_out' => __('转出', 'aksrt'),
'tip_sent' => __('打赏支出', 'aksrt'),
'tip_received' => __('收到打赏', 'aksrt'),
'admin' => __('管理员调整', 'aksrt'),
'exchange_from_credits' => __('积分兑换', 'aksrt'),
'withdraw_hold' => __('提现冻结', 'aksrt'),