feat(user-center): merge promotion rewards into revenue
This commit is contained in:
1 parent
a87fd32fa3
commit
39c92017d9
14 files changed
+1048
-159
No files matched your search
@@ -702,7 +702,7 @@ $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
|
||||
&& isset($_GET['tab'])
|
||||
&& 'revenue' === sanitize_key((string) wp_unslash($_GET['tab']))
|
||||
);
|
||||
if ($is_revenue_surface) {
|
||||
if ($is_revenue_surface && !$is_profile_page) {
|
||||
$revenue_js = get_template_directory() . '/assets/js/revenue.js';
|
||||
wp_enqueue_script(
|
||||
'aksrt-revenue',
|
||||
@@ -919,6 +919,18 @@ $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
|
||||
|
||||
|
||||
|
||||
if ($is_profile_page) {
|
||||
$revenue_invite_js_path = get_template_directory() . '/assets/js/revenue-invite.js';
|
||||
if (file_exists($revenue_invite_js_path)) {
|
||||
wp_enqueue_script(
|
||||
'aksrt-revenue-invite',
|
||||
$base_uri . '/assets/js/revenue-invite.js',
|
||||
['aksrt-script'],
|
||||
(string) filemtime($revenue_invite_js_path),
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
// Badges UI: user center + public profile (zibll medal modal/list).
|
||||
if (class_exists('\AKSRT\User\Badges') && \AKSRT\User\Badges::enabled()) {
|
||||
$is_badge_surface = $is_profile_page
|
||||
|
||||
@@ -368,6 +368,7 @@ class Balance {
|
||||
'admin' => __('管理员调整', 'aksrt'),
|
||||
'exchange_from_credits' => __('积分兑换', 'aksrt'),
|
||||
'creator_income' => __('创作收益结算', 'aksrt'),
|
||||
'rebate' => __('推广返佣结算', 'aksrt'),
|
||||
'withdraw_hold' => __('提现冻结', 'aksrt'),
|
||||
'withdraw_refund' => __('提现退回', 'aksrt'),
|
||||
];
|
||||
|
||||
+23
-9
@@ -59,18 +59,30 @@ class Invite {
|
||||
'permission_callback' => function () {
|
||||
return is_user_logged_in();
|
||||
},
|
||||
'args' => [
|
||||
'page' => [
|
||||
'type' => 'integer',
|
||||
'default' => 1,
|
||||
'minimum' => 1,
|
||||
],
|
||||
'per_page' => [
|
||||
'type' => 'integer',
|
||||
'default' => 10,
|
||||
'minimum' => 1,
|
||||
'maximum' => 50,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/** 捕获 ?invite=XYZ */
|
||||
/** Capture ?ref=XYZ, with legacy ?invite=XYZ support. */
|
||||
public function capture_invite_cookie(): void {
|
||||
if (is_admin()) return;
|
||||
if (empty($_GET['invite'])) return;
|
||||
|
||||
$raw_code = $_GET['ref'] ?? $_GET['invite'] ?? '';
|
||||
if ($raw_code === '') return;
|
||||
// 邀请注册功能关闭时不处理
|
||||
if (class_exists('\AKSRT\Settings\Settings') && !\AKSRT\Settings\Settings::invite_registration_enabled()) return;
|
||||
|
||||
$code = sanitize_key((string) $_GET['invite']);
|
||||
$code = sanitize_key(wp_unslash((string) $raw_code));
|
||||
if ($code === '') return;
|
||||
|
||||
// 校验邀请码是否对应真实用户
|
||||
@@ -609,7 +621,7 @@ class Invite {
|
||||
}
|
||||
}
|
||||
|
||||
$invite_url = add_query_arg('invite', $code, aksrt_get_register_url());
|
||||
$invite_url = add_query_arg('ref', $code, home_url('/'));
|
||||
|
||||
return new \WP_REST_Response([
|
||||
'code' => $code,
|
||||
@@ -626,9 +638,7 @@ class Invite {
|
||||
global $wpdb;
|
||||
$user_id = get_current_user_id();
|
||||
$page = max(1, (int) $request->get_param('page'));
|
||||
$per_page = min(50, max(1, (int) $request->get_param('per_page') ?: 20));
|
||||
$offset = ($page - 1) * $per_page;
|
||||
|
||||
$per_page = min(50, max(1, (int) $request->get_param('per_page') ?: 10));
|
||||
$table = \AKSRT\Core\DBMigrator::table('invite');
|
||||
if (!$table) {
|
||||
return new \WP_REST_Response(['items' => [], 'total' => 0], 200);
|
||||
@@ -638,6 +648,9 @@ class Invite {
|
||||
"SELECT COUNT(*) FROM {$table} WHERE inviter_id = %d",
|
||||
$user_id
|
||||
));
|
||||
$total_pages = max(1, (int) ceil($total / $per_page));
|
||||
$page = min($page, $total_pages);
|
||||
$offset = ($page - 1) * $per_page;
|
||||
$rows = $wpdb->get_results($wpdb->prepare(
|
||||
"SELECT * FROM {$table} WHERE inviter_id = %d ORDER BY created_at DESC LIMIT %d OFFSET %d",
|
||||
$user_id,
|
||||
@@ -664,6 +677,7 @@ class Invite {
|
||||
'total' => $total,
|
||||
'page' => $page,
|
||||
'per_page' => $per_page,
|
||||
'total_pages' => $total_pages,
|
||||
], 200);
|
||||
}
|
||||
}
|
||||
+61
-28
@@ -79,31 +79,56 @@ class Rebate {
|
||||
public function settle(int $id): bool {
|
||||
global $wpdb;
|
||||
|
||||
$row = $wpdb->get_row($wpdb->prepare(
|
||||
"SELECT * FROM {$this->table()} WHERE id = %d AND status = %s",
|
||||
$id, self::STATUS_PENDING
|
||||
), ARRAY_A);
|
||||
|
||||
if (!$row) return false;
|
||||
|
||||
$user_id = (int) $row['user_id'];
|
||||
$amount = (float) $row['amount'];
|
||||
|
||||
$result = $wpdb->update($this->table(), [
|
||||
'status' => self::STATUS_SETTLED,
|
||||
'settled_at' => current_time('mysql'),
|
||||
], ['id' => $id]);
|
||||
|
||||
if ($result && class_exists('\AKSRT\Credits\Credits')) {
|
||||
\AKSRT\Credits\Credits::add($user_id, (int) $amount, 'rebate', [
|
||||
'ref_type' => 'rebate',
|
||||
'ref_id' => $id,
|
||||
]);
|
||||
if (!class_exists('\AKSRT\Credits\Balance')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (bool) $result;
|
||||
}
|
||||
$wpdb->query('START TRANSACTION');
|
||||
try {
|
||||
$row = $wpdb->get_row($wpdb->prepare(
|
||||
"SELECT id, user_id, amount, order_number FROM {$this->table()} WHERE id = %d AND status = %s FOR UPDATE",
|
||||
$id,
|
||||
self::STATUS_PENDING
|
||||
), ARRAY_A);
|
||||
if (!is_array($row)) {
|
||||
$wpdb->query('ROLLBACK');
|
||||
return false;
|
||||
}
|
||||
|
||||
$credited = \AKSRT\Credits\Balance::add(
|
||||
(int) $row['user_id'],
|
||||
(float) $row['amount'],
|
||||
'rebate',
|
||||
['type' => 'rebate', 'id' => (int) $row['id']],
|
||||
sprintf(__('推广返佣结算(订单 %s)', 'aksrt'), (string) $row['order_number'])
|
||||
);
|
||||
if (is_wp_error($credited)) {
|
||||
$wpdb->query('ROLLBACK');
|
||||
return false;
|
||||
}
|
||||
|
||||
$settled = $wpdb->update(
|
||||
$this->table(),
|
||||
[
|
||||
'status' => self::STATUS_SETTLED,
|
||||
'settled_at' => current_time('mysql'),
|
||||
],
|
||||
['id' => $id, 'status' => self::STATUS_PENDING],
|
||||
['%s', '%s'],
|
||||
['%d', '%s']
|
||||
);
|
||||
if ($settled !== 1) {
|
||||
$wpdb->query('ROLLBACK');
|
||||
return false;
|
||||
}
|
||||
|
||||
$wpdb->query('COMMIT');
|
||||
return true;
|
||||
} catch (\Throwable $e) {
|
||||
$wpdb->query('ROLLBACK');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 取消返佣
|
||||
*/
|
||||
@@ -159,24 +184,32 @@ class Rebate {
|
||||
/**
|
||||
* 获取统计
|
||||
*/
|
||||
public function get_stats(): array {
|
||||
public function get_stats(int $user_id = 0): array {
|
||||
global $wpdb;
|
||||
$table = $this->table();
|
||||
$where = '';
|
||||
$params = [];
|
||||
if ($user_id > 0) {
|
||||
$where = 'WHERE user_id = %d';
|
||||
$params[] = $user_id;
|
||||
}
|
||||
|
||||
$row = $wpdb->get_row(
|
||||
"SELECT
|
||||
$sql = "SELECT
|
||||
COUNT(*) as total,
|
||||
SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) as pending,
|
||||
SUM(CASE WHEN status = 'pending' THEN amount ELSE 0 END) as pending_amount,
|
||||
SUM(CASE WHEN status = 'settled' THEN 1 ELSE 0 END) as settled,
|
||||
SUM(amount) as total_amount,
|
||||
SUM(CASE WHEN status = 'settled' THEN amount ELSE 0 END) as settled_amount
|
||||
FROM {$table}",
|
||||
ARRAY_A
|
||||
);
|
||||
FROM {$table} {$where}";
|
||||
$row = $params
|
||||
? $wpdb->get_row($wpdb->prepare($sql, $params), ARRAY_A)
|
||||
: $wpdb->get_row($sql, ARRAY_A);
|
||||
|
||||
return [
|
||||
'total' => (int) ($row['total'] ?? 0),
|
||||
'pending' => (int) ($row['pending'] ?? 0),
|
||||
'pending_amount' => (float) ($row['pending_amount'] ?? 0),
|
||||
'settled' => (int) ($row['settled'] ?? 0),
|
||||
'total_amount' => (float) ($row['total_amount'] ?? 0),
|
||||
'settled_amount' => (float) ($row['settled_amount'] ?? 0),
|
||||
|
||||
@@ -90,7 +90,7 @@ class UserRuntime {
|
||||
|
||||
// Built-in switchable panels. VIP is always auto-injected when enabled
|
||||
// by AKSRT\User\Center — keep it allowed for explicit config too.
|
||||
$allowed_tabs = ['profile', 'level', 'posts', 'comments', 'favorites', 'credits', 'promotion', 'revenue', 'vip', 'orders', 'auth', 'settings'];
|
||||
$allowed_tabs = ['profile', 'level', 'posts', 'comments', 'favorites', 'credits', 'revenue', 'vip', 'orders', 'auth', 'settings'];
|
||||
$normalized_tabs = ['profile'];
|
||||
|
||||
foreach ((array) $tabs as $tab) {
|
||||
|
||||
+5
-31
@@ -91,12 +91,6 @@ class Center {
|
||||
'priority' => 50,
|
||||
'type' => 'panel',
|
||||
],
|
||||
'promotion' => [
|
||||
'label' => __('推广中心', 'aksrt'),
|
||||
'icon' => 'bullhorn',
|
||||
'priority' => 52,
|
||||
'type' => 'panel',
|
||||
],
|
||||
'revenue' => [
|
||||
'label' => __('收益中心', 'aksrt'),
|
||||
'icon' => 'chart-line',
|
||||
@@ -133,17 +127,9 @@ class Center {
|
||||
&& !empty(\AKSRT\User\Level::settings()['enabled']);
|
||||
$credits_on = class_exists('\AKSRT\Settings\Settings') && \AKSRT\Settings\Settings::credits_enabled();
|
||||
$balance_on = class_exists('\AKSRT\Credits\Balance') && \AKSRT\Credits\Balance::enabled();
|
||||
$invite_on = $credits_on
|
||||
&& class_exists('\AKSRT\Settings\Settings')
|
||||
&& \AKSRT\Settings\Settings::invite_enabled()
|
||||
&& \AKSRT\Settings\Settings::invite_registration_enabled();
|
||||
// Promotion (invite) center is its own tab; revenue stays pure earnings/withdrawal.
|
||||
$promotion_on = $invite_on;
|
||||
$revenue_tab_on = class_exists('\AKSRT\Settings\Settings')
|
||||
&& (
|
||||
!empty(\AKSRT\Settings\Settings::get_payment_revenue_settings()['enabled'])
|
||||
|| !empty(\AKSRT\Settings\Settings::get_payment_affiliate_settings()['enabled'])
|
||||
);
|
||||
&& !empty(\AKSRT\Settings\Settings::get_payment_affiliate_settings()['enabled'])
|
||||
&& \AKSRT\Settings\Settings::invite_registration_enabled();
|
||||
$vip_on = class_exists('\AKSRT\Settings\Settings')
|
||||
&& !empty(\AKSRT\Settings\Settings::get_payment_vip_settings()['enabled']);
|
||||
|
||||
@@ -190,20 +176,10 @@ class Center {
|
||||
if (($credits_on || $balance_on) && !in_array('credits', $order, true)) {
|
||||
$order[] = 'credits';
|
||||
}
|
||||
if ($promotion_on && !in_array('promotion', $order, true)) {
|
||||
$insert_at = count($order);
|
||||
foreach (['credits', 'favorites', 'posts'] as $anchor) {
|
||||
$idx = array_search($anchor, $order, true);
|
||||
if ($idx !== false) {
|
||||
$insert_at = (int) $idx + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
array_splice($order, $insert_at, 0, ['promotion']);
|
||||
}
|
||||
|
||||
if ($revenue_tab_on && !in_array('revenue', $order, true)) {
|
||||
$insert_at = count($order);
|
||||
foreach (['promotion', 'credits', 'favorites', 'posts'] as $anchor) {
|
||||
foreach (['credits', 'favorites', 'posts'] as $anchor) {
|
||||
$idx = array_search($anchor, $order, true);
|
||||
if ($idx !== false) {
|
||||
$insert_at = (int) $idx + 1;
|
||||
@@ -234,9 +210,7 @@ class Center {
|
||||
if ($key === 'revenue' && !$revenue_tab_on) {
|
||||
continue;
|
||||
}
|
||||
if ($key === 'promotion' && !$promotion_on) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($key === 'vip' && !$vip_on) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user